excelvba

How to group an array of shapes


I am making a flow chart, where I want to group the entire flow chart for the user to move it around later if he/she wants.

I made an array of rectangular shapes and arrow respectively and named them accordingly. However, I am not able to group them all together.

There will be more such flowcharts in the same sheet. So, I don't want to use thisSheet.Shapes option.

Following is the code that I have prepared

Dim i As Integer
Dim outer_box As Shape
Dim shp(20) As Shape
Dim arw(20) As Shape
Dim shpgrp As Shape
Dim rg As Range
Dim height As Long


 
With ActiveSheet
    Set rg = .Range("B11")
End With

i = 1
height = 0
If process(i - 1) = vbNullString Then
    End
Else
    For i = 1 To 20
        If process(i - 1) = vbNullString Then 'Separate userform where process() array gets inputs
            Exit For
        Else
            Set shp(i) = ActiveSheet.Shapes.AddShape(msoShapeRectangle, 1, 1, 1, 1) 
            With shp(i)
                .Width = 150
                .TextFrame.HorizontalAlignment = xlHAlignLeft
                .TextFrame.VerticalAlignment = xlVAlignCenter
                .TextFrame.Characters.Text = i & ". " & process(i - 1) 'Separate userform where process() array gets inputs
                .Left = rg.Left + 5
                .Top = rg.Top + 10 + height + 20 * (i - 1)
                .Name = "shp" & i
            End With
            If Not i - 1 = 0 Then
                Set arw(i) = ActiveSheet.Shapes.AddConnector(msoConnectorStraight, 100, 100, 100, 100)
                With arw(i)
                    .Line.EndArrowheadStyle = msoArrowheadTriangle
                    .ConnectorFormat.BeginConnect shp(i - 1), 3
                    .ConnectorFormat.EndConnect shp(i), 1
                    .Name = "arw" & i
                End With
            End If
        End If
        height = height + shp(i).height
    Next i
    Set outer_box = ActiveSheet.Shapes.AddShape(msoShapeRectangle, 1, 1, 1, 1)
    With outer_box
        .Top = rg.Top
        .Left = rg.Left
        .Width = 160
        .height = height + 20 * (i - 1)
        .ZOrder msoSendToBack
        .Name = "outer_box"
    End With
End If

Set shpgrp = ActiveSheet.Shapes.Range(Array("outer_box", "shp" & (i - 1), "arw" & (i - 1))).Group
shpgrp.Select
End Sub

I am only able to group the last shapes. How do I group the array of shapes and arrows here? Is it possible to iteratively add the shapes and arrows as into a group, when the for loop is running? Thank you.


Solution

  • Microsoft documentation:

    Split function

    Option Explicit
    Sub Demo()
        Dim i As Integer
        Dim outer_box As Shape
        Dim shp(20) As Shape
        Dim arw(20) As Shape
        Dim shpgrp As Shape
        Dim rg As Range
        Dim sShpList As String
        Dim height As Long
        With ActiveSheet
            Set rg = .Range("B11")
        End With
        i = 1
        height = 0
        If process(i - 1) = vbNullString Then
            End
        Else
            sShpList = "outer_box"
            For i = 1 To 20
                If process(i - 1) = vbNullString Then 'Separate userform where process() array gets inputs
                    Exit For
                Else
                    Set shp(i) = ActiveSheet.Shapes.AddShape(msoShapeRectangle, 1, 1, 1, 1)
                    With shp(i)
                        .Width = 150
                        .TextFrame.HorizontalAlignment = xlHAlignLeft
                        .TextFrame.VerticalAlignment = xlVAlignCenter
                        .TextFrame.Characters.Text = i & ". " & process(i - 1) 'Separate userform where process() array gets inputs
                        .Left = rg.Left + 5
                        .Top = rg.Top + 10 + height + 20 * (i - 1)
                        .Name = "shp" & i
                        sShpList = sShpList & "|" & "shp" & i
                    End With
                    If Not i - 1 = 0 Then
                        Set arw(i) = ActiveSheet.Shapes.AddConnector(msoConnectorStraight, 100, 100, 100, 100)
                        With arw(i)
                            .Line.EndArrowheadStyle = msoArrowheadTriangle
                            .ConnectorFormat.BeginConnect shp(i - 1), 3
                            .ConnectorFormat.EndConnect shp(i), 1
                            .Name = "arw" & i
                            sShpList = sShpList & "|" & "arw" & i
                        End With
                    End If
                End If
                height = height + shp(i).height
            Next i
            Set outer_box = ActiveSheet.Shapes.AddShape(msoShapeRectangle, 1, 1, 1, 1)
            With outer_box
                .Top = rg.Top
                .Left = rg.Left
                .Width = 160
                .height = height + 20 * (i - 1)
                .ZOrder msoSendToBack
                .Name = "outer_box"
            End With
        End If
        Set shpgrp = ActiveSheet.Shapes.Range(Split(sShpList, "|")).Group
        shpgrp.Select
    End Sub