選択したコネクタの中間点に新たなオートシェイプを配置する

昨日、一昨日の二日間にわたって、スピンボタンのupとdownを押してコネクタの接続位置を変化させてみました。

infoment.hatenablog.com

今日は、コネクタ選択したコネクタの中間位置に、新たなオートシェイプを配置することに挑戦です。

今日やりたいこと

処理や分岐間に新たな処理などが追加されることは、よくあることだと思います。この場合、一般的に以下手順での追加作業になります。

  1. コネクタを削除
  2. 新たなオートシェイプを良きところに配置
  3. 前後をコネクタでつなぐ

そこで、これを自動で行う機能を追加してみます。

必要なこと

  1. テキストボックスとコマンドボタンの配置
  2. コマンドボタン押下時の処理を作成
  3. ネクタリストの更新

1.テキストボックスとコマンドボタンの配置

オートシェイプの中身が空っぽだと、色々な場面でエラーになる恐れがあります。そこで中身の文字を指定したうえで、オートシェイプを追加することにしました。

f:id:Infoment:20180923071244p:plain

2.コマンドボタン押下時の処理を作成

先ほど追加した「ブロック追加」ボタンを押した際、以下の手順で処理を行うことにしました。

  1. 選択したコネクタを削除
  2. 削除したコネクタの始端と終端にあるオートシェイプの位置関係から、新たに追加する位置を決定
  3. オートシェイプを追加
  4. 始端 ⇒ 新規 ⇒ 終端の順にコネクタ接続
  5. コネクタのリスト更新
【ユーザーフォームのモジュール】
Private Sub AddChartButton_Click()

    ' コネクタ削除
    SC.myShape.Delete
    
    Dim PositionRelationIndex As Long
        PositionRelationIndex = SC.GetPositionRelation(start_shape, end_shape)
    Dim myLeft As Long
    Dim myTop As Long
        Select Case PositionRelationIndex
            ' 真上、真下の場合
            Case 1, 3
                myLeft = start_shape.Left
                myTop = (start_shape.Top + end_shape.Top) / 2
            ' 左横、右横の場合
            Case 2, 4
                myLeft = (start_shape.Left + end_shape.Left) / 2
                myTop = start_shape.Top
            ' 左斜め上、右斜め上の場合
            Case 5, 8
                myLeft = end_shape.Left
                myTop = start_shape.Top
            ' 左斜め下、右斜め下の場合
            Case 6, 7
                myLeft = start_shape.Left
                myTop = end_shape.Top
        End Select
    
    Set SC.myShape = ActiveSheet.Shapes.AddShape(msoShapeFlowchartProcess, myLeft, myTop, 100, 50)
        SC.myShape.TextFrame2.TextRange.Characters.Text = AddChartTextBox.Value
        SC.SetFormat
    
    Dim AddShape(3) As Shape
    Set AddShape(1) = start_shape
    Set AddShape(2) = SC.myShape
    Set AddShape(3) = end_shape
    
    Dim i As Long
        For i = 1 To 2
            ConnectShape AddShape(i), AddShape(i + 1)
        Next
        
    Call UpdateConnectorList

End Sub

3.コネクタリストの更新

上記コードの最後で、コネクタのリストを更新するサブプロシージャを呼び出しています。

Call UpdateConnectorList

現時点では存在しないサブプロシージャなので、これから作成します。といっても、ユーザーフォームの初期化時に一度行っているので、これを切り出して同プロシージャに充てることにします。

【標準モジュール】
Public Sub UpdateConnectorList()

    ' 一旦全てのオートシェイプ選択を解除
    Range("A1").Select

    Dim Shape As Shape
    Dim col As Collection
    Set col = New Collection
        For Each Shape In ActiveSheet.Shapes
            If Shape.Connector = msoTrue Then
                col.Add Shape.Name
            End If
        Next
    
    Dim SQC As SequenceClass
    Set SQC = New SequenceClass
        EditConnectorForm.ListBox2.Clear
        EditConnectorForm.ListBox2.List = SQC.ToArray(col)

End Sub

ユーザーフォームから取り出したため、「どのユーザーフォームか」を明示する必要があります。

 EditConnectorForm.ListBox2.List = SQC.ToArray(col)

そのままコピーしてエラーになることが(私は)よくあるので、(私の)注意が必要です。

切り出した分だけ、ユーザーフォームの初期化がすっきりしました。

【ユーザーフォームのモジュール】
Private Sub UserForm_Initialize()

        ' 今回切り出して置き換えた箇所
        Call UpdateConnectorList
        
        StartSpinButton.Value = StartSpinButton.Max / 2
        EndSpinButton.Value = EndSpinButton.Max / 2
        
End Sub

結果

コネクタをオートシェイプに置き換えて、新たなコネクタで接続することが出来ました。
f:id:Infoment:20180923074414p:plain

    ↓ 置き換え後

f:id:Infoment:20180923074434p:plain

ただし、置き換えた場所に既に別のオートシェイプがあるなどの場合に、現時点では対応できていません。今後は、オートシェイプの重なり判定などを盛り込む必要があると考えています。

次回に続きます。

参考まで。