Sub ExtractOverlappingShapesAndTextBoxes()
Dim ws As Worksheet
Dim shp As Shape
Dim rect As Shape
Dim txtBox As Shape
Dim i As Integer, j As Integer
Dim outputRow As Integer
Dim rectangles As Collection
Dim textBoxes As Collection
Dim rectBounds As Object
Dim txtBounds As Object
Dim maxCol As Double
' シート『5Aフロー』を取得
On Error Resume Next
Set ws = ThisWorkbook.Worksheets("5Aフロー")
On Error GoTo 0
If ws Is Nothing Then
MsgBox "シート『5Aフロー』が見つかりません。", vbCritical
Exit Sub
End If
' AQ列の列番号を取得(AQ = 43列目)
maxCol = 43 * ws.Columns(1).Width
' 既存のBA21以降、BF21以降をクリア
ws.Range("BA21:BA1000").ClearContents
ws.Range("BF21:BF1000").ClearContents
' コレクションを初期化
Set rectangles = New Collection
Set textBoxes = New Collection
' AQ列より左の範囲で四角形とテキストボックスを分類
For Each shp In ws.Shapes
' AQ列より左にある図形のみを対象とする
If shp.Left < maxCol Then
' グループ化されている場合の処理
If shp.Type = msoGroup Then
Dim grpShape As Shape
For Each grpShape In shp.GroupItems
If grpShape.Type = msoAutoShape And grpShape.AutoShapeType = msoShapeRectangle Then
rectangles.Add grpShape
ElseIf grpShape.Type = msoTextBox Then
textBoxes.Add grpShape
End If
Next grpShape
Else
' 単体の図形の場合
If shp.Type = msoAutoShape And shp.AutoShapeType = msoShapeRectangle Then
rectangles.Add shp
ElseIf shp.Type = msoTextBox Then
textBoxes.Add shp
End If
End If
End If
Next shp
' 出力開始行
outputRow = 21
' 四角形とテキストボックスの重なりをチェック
For i = 1 To rectangles.Count
Set rect = rectangles(i)
' 四角形の境界を設定
Set rectBounds = CreateObject("Scripting.Dictionary")
rectBounds("Left") = rect.Left
rectBounds("Top") = rect.Top
rectBounds("Right") = rect.Left + rect.Width
rectBounds("Bottom") = rect.Top + rect.Height
For j = 1 To textBoxes.Count
Set txtBox = textBoxes(j)
' テキストボックスの境界を設定
Set txtBounds = CreateObject("Scripting.Dictionary")
txtBounds("Left") = txtBox.Left
txtBounds("Top") = txtBox.Top
txtBounds("Right") = txtBox.Left + txtBox.Width
txtBounds("Bottom") = txtBox.Top + txtBox.Height
' 重なりをチェック
If IsOverlapping(rectBounds, txtBounds) Then
' BA列に四角形のテキスト、BF列にテキストボックスのテキストを出力
On Error Resume Next
ws.Cells(outputRow, 53).Value = rect.TextFrame.Characters.Text ' BA列 = 53列目
ws.Cells(outputRow, 58).Value = txtBox.TextFrame.Characters.Text ' BF列 = 58列目
On Error GoTo 0
outputRow = outputRow + 1
End If
Next j
Next i
MsgBox "処理が完了しました。" & vbCrLf & _
"抽出されたペア数: " & (outputRow - 21) & "組", vbInformation
End Sub
' 二つの矩形が重なっているかどうかをチェックする関数
Private Function IsOverlapping(rect1 As Object, rect2 As Object) As Boolean
' 重なりの条件:
' rect1の右端がrect2の左端より右にある AND
' rect1の左端がrect2の右端より左にある AND
' rect1の下端がrect2の上端より下にある AND
' rect1の上端がrect2の下端より上にある
IsOverlapping = (rect1("Right") > rect2("Left")) And _
(rect1("Left") < rect2("Right")) And _
(rect1("Bottom") > rect2("Top")) And _
(rect1("Top") < rect2("Bottom"))
End Function