【VBAリファレンス】VBA ShapesとDrawingObjectsの深淵:使い分けと実践テクニック徹底解説

スポンサーリンク

概要

Excel VBAにおいて、図形オブジェクトを操作する際に「Shapesコレクション」と「DrawingObjectsコレクション」という二つの主要なオブジェクトが登場します。これらは似ているようで、その性質や利用シーンには明確な違いがあります。本記事では、この二つのコレクションの相違点を詳細に解説し、それぞれの特性を活かした具体的な使い方をサンプルコードと共に紹介します。さらに、実務で遭遇するであろう課題とその解決策、そしてより効率的な図形操作のためのアドバイスを提供し、読者の皆様のVBAスキル向上に貢献することを目指します。

Shapesコレクションの詳細解説

Shapesコレクションは、Excelシート上に存在するすべての図形オブジェクト(オートシェイプ、テキストボックス、画像、チャート、ActiveXコントロールなど)を網羅する強力なオブジェクトです。シート上の「図形」という概念を包括的に捉えており、その種類を問わずアクセスできるのが最大の特徴です。

Shapesコレクションの特性

  • 網羅性: シート上のほぼ全ての視覚的要素を対象とします。
  • 汎用性: オートシェイプ、画像、テキストボックス、チャート、ActiveXコントロールなど、多岐にわたるオブジェクトを同じShapesコレクション内で扱えます。
  • 柔軟性: オブジェクトの種類に応じて、共通のプロパティ(例: Name, Top, Left, Width, Height, Visible)やメソッド(例: Select, Delete)に加え、各オブジェクト固有のプロパティやメソッドにもアクセスできます。
  • 構造: Eachループで順番に処理する際に、オブジェクトの追加順や配置順に依存することがあります。

Shapesコレクションの使い方

Shapesコレクションへのアクセスは、対象となるワークシートを指定して行います。

‘ アクティブシートのShapesコレクションにアクセス
Dim sh As Shape
For Each sh In ActiveSheet.Shapes
Debug.Print sh.Name & ” – Type: ” & sh.Type
Next sh

‘ 特定の名前のShapeを取得
Dim myShape As Shape
Set myShape = ActiveSheet.Shapes(“Rectangle 1”)
myShape.Fill.ForeColor.RGB = RGB(255, 0, 0) ‘ 赤色に塗りつぶし

Shapeオブジェクトの`Type`プロパティは、その図形が何であるかを示す定数を返します。例えば、`msoShapeRectangle` (四角形), `msoPicture` (画像), `msoTextBox` (テキストボックス) などがあります。

DrawingObjectsコレクションの詳細解説

DrawingObjectsコレクションは、より限定的なオブジェクト群を指します。具体的には、Excelの「挿入」タブから追加できる「図形」や「テキストボックス」といった、いわゆる「描画オブジェクト」に特化しています。チャートや画像、ActiveXコントロールなどは、DrawingObjectsコレクションには含まれません。

DrawingObjectsコレクションの特性

  • 限定性: オートシェイプ、テキストボックス、グループ化された図形など、描画機能に属するオブジェクトのみを対象とします。
  • 互換性: 以前のバージョンのExcelとの互換性を考慮して存在しており、特定の描画オブジェクト操作に特化しています。
  • 構造: Shapesコレクションと同様に、Eachループで処理できますが、対象となるオブジェクトの種類が少ないです。
  • 注意点: ChartオブジェクトやImageコントロールなどは含まれないため、これらのオブジェクトを操作したい場合はShapesコレクションを使用する必要があります。

DrawingObjectsコレクションの使い方

DrawingObjectsコレクションも、対象となるワークシートを指定してアクセスします。

‘ アクティブシートのDrawingObjectsコレクションにアクセス
Dim dObj As DrawingObject
For Each dObj In ActiveSheet.DrawingObjects
Debug.Print dObj.Name & ” – TopLeftCell: ” & dObj.TopLeftCell.Address
Next dObj

‘ 特定の名前のDrawingObjectを取得
Dim myDrawingObject As DrawingObject
Set myDrawingObject = ActiveSheet.DrawingObjects(“TextBox 1”)
myDrawingObject.TextFrame.Characters.Text = “これはDrawingObjectです”

DrawingObjectには、`TextFrame` プロパティ(テキストボックスの場合)や `ShapeRange` プロパティ(グループ化された描画オブジェクトの場合)など、描画オブジェクト特有のプロパティがあります。

ShapesとDrawingObjectsの相違点まとめ

| 特徴 | Shapesコレクション | DrawingObjectsコレクション |
| —————- | —————————————————– | ——————————————————– |
| **対象オブジェクト** | 全ての図形オブジェクト(オートシェイプ、画像、チャート、ActiveXコントロール、テキストボックス等) | 描画オブジェクト(オートシェイプ、テキストボックス、グループ化された図形等) |
| **網羅性** | 高い(シート上のほぼ全ての視覚要素) | 限定的(描画機能に属するオブジェクトのみ) |
| **互換性** | 最新のExcel機能に対応 | 過去のExcelバージョンとの互換性を意識 |
| **主な用途** | 多様なオブジェクトの統一的な操作、高度な図形操作 | 特定の描画オブジェクトの操作、シンプルな図形操作 |
| **チャートや画像** | 含まれる | 含まれない |
| **ActiveXコントロール** | 含まれる | 含まれない |

端的に言えば、**Shapesコレクションは「シート上の全ての視覚要素」を、DrawingObjectsコレクションは「Excelが描画機能として管理する一部のオブジェクト」を指す**と理解すると良いでしょう。

サンプルコード:実践的な使い方

1. 全ての図形を削除する(Shapesコレクション)

シート上の全ての図形を削除したい場合、Shapesコレクションを使用するのが最も簡単です。

Sub DeleteAllShapes()
Dim sh As Shape
‘ オブジェクトを逆順に削除することで、インデックスのずれによるエラーを防ぐ
For i = ActiveSheet.Shapes.Count To 1 Step -1
ActiveSheet.Shapes(i).Delete
Next i
MsgBox “全ての図形を削除しました。”, vbInformation
End Sub

2. 特定の種類の図形だけを削除する(Shapesコレクション)

画像ファイルだけを削除したい、といった場合にもShapesコレクションは便利です。

Sub DeleteAllPictures()
Dim sh As Shape
For i = ActiveSheet.Shapes.Count To 1 Step -1
‘ msoPictureは画像オブジェクトを示す定数
If ActiveSheet.Shapes(i).Type = msoPicture Then
ActiveSheet.Shapes(i).Delete
End If
Next i
MsgBox “全ての画像を削除しました。”, vbInformation
End Sub

3. テキストボックスのテキストをまとめて変更する(ShapesコレクションとDrawingObjectsコレクション)

ShapesコレクションとDrawingObjectsコレクションの両方でテキストボックスを操作できますが、ここではShapesコレクションを使用します。

Sub ChangeTextBoxText()
Dim sh As Shape
Dim newText As String
newText = “更新されたテキスト”

‘ シート上の全てのShapeをループ
For Each sh In ActiveSheet.Shapes
‘ Typeプロパティでテキストボックスかどうかを判定
If sh.Type = msoTextBox Then
‘ TextFrameプロパティでテキストフレームにアクセス
sh.TextFrame.Characters.Text = newText
End If
Next sh
MsgBox “全てのテキストボックスのテキストを変更しました。”, vbInformation
End Sub

4. DrawingObjectの特定のプロパティにアクセスする

DrawingObjectに固有のプロパティ(例:Anchorセル)にアクセスする例です。

Sub InspectDrawingObjects()
Dim dObj As DrawingObject
Dim sh As Shape

‘ DrawingObjectsコレクションをループ
For Each dObj In ActiveSheet.DrawingObjects
Debug.Print “DrawingObject Name: ” & dObj.Name
‘ 描画オブジェクトはShapeオブジェクトでもあるので、ShapeRange経由でアクセス可能
Set sh = dObj.ShapeRange
Debug.Print ” Shape Type: ” & sh.Type
Debug.Print ” Linked Cell: ” & dObj.LinkedCell ‘ DrawingObject固有のプロパティ
Debug.Print ” TopLeftCell: ” & dObj.TopLeftCell.Address
Debug.Print “——————–”
Next dObj
End Sub

5. ShapesコレクションとDrawingObjectsコレクションの併用(注意点)

実は、DrawingObjectsコレクションに含まれるオブジェクトは、Shapesコレクションにも含まれています。そのため、DrawingObjectsコレクションにしか存在しないプロパティ(例: `LinkedCell`)にアクセスしたい場合は、Shapesコレクションで対象のShapeオブジェクトを取得した後、そのShapeオブジェクトがDrawingObjectであるかを判定し、必要であればDrawingObjectとしてのキャストを行う、といった少し複雑な処理が必要になる場合があります。

しかし、多くのケースでは、Shapesコレクションで統一的に操作する方がコードがシンプルになります。DrawingObjectsコレクションは、特定の描画オブジェクトの挙動を細かく制御したい場合や、古いExcelバージョンとの互換性を重視する場合に限定して使用するのが賢明です。

実務アドバイスと注意点

1. どちらを使うべきか?

基本的には、**Shapesコレクションを優先して使用する**ことをお勧めします。Shapesコレクションは、Excelシート上のあらゆる視覚要素を網羅しており、画像、チャート、ActiveXコントロールなど、DrawingObjectsコレクションでは扱えないオブジェクトもまとめて操作できます。コードの汎用性と保守性が向上します。

DrawingObjectsコレクションは、以下のような限定的な状況でのみ検討するのが良いでしょう。

  • 特定の描画オブジェクト(オートシェイプ、テキストボックス)の、DrawingObject固有のプロパティ(例: `LinkedCell`)にアクセスする必要がある。
  • 古いバージョンのExcelとの互換性を厳密に保つ必要がある。

2. オブジェクトの特定方法

Shapesコレクションでループ処理を行う場合、`sh.Type` プロパティでオブジェクトの種類を特定できます。よく使う定数には以下のようなものがあります。

  • `msoAutoShape`: オートシェイプ
  • `msoTextBox`: テキストボックス
  • `msoPicture`: 画像
  • `msoChart`: Excelチャート
  • `msoOLEControlObject`: ActiveXコントロール
  • `msoGroup`: グループ化されたオブジェクト

これらの定数と`If`文を組み合わせることで、特定の種類の図形のみを対象とした処理が可能になります。

3. エラーハンドリングの重要性

存在しない図形を参照しようとするとエラーが発生します。特に、図形名で直接指定する場合や、ループ処理で削除などを行う際には、エラーハンドリング (`On Error Resume Next` や `On Error GoTo 0`) や、オブジェクトが存在するかどうかのチェック (`If Not sh Is Nothing Then`) を適切に行うことが重要です。

Sub GetShapeSafely()
Dim sh As Shape
Dim shapeName As String
shapeName = “MyNonExistentShape”

On Error Resume Next ‘ エラー発生時に処理を続行
Set sh = ActiveSheet.Shapes(shapeName)
On Error GoTo 0 ‘ エラーハンドリングを元に戻す

If sh Is Nothing Then
MsgBox “指定された名前の図形は見つかりませんでした。”, vbExclamation
Else
MsgBox “図形 ‘” & shapeName & “‘ が見つかりました。Top: ” & sh.Top
End If
End Sub

4. パフォーマンスに関する考慮

大量の図形オブジェクトを操作する場合、ループ処理の効率がパフォーマンスに影響します。

  • **オブジェクト変数を使用する:** `For Each sh In ActiveSheet.Shapes` のようにオブジェクト変数を明示的に使用しましょう。
  • **不要な操作を避ける:** 処理対象外のオブジェクトに対する操作はスキップしましょう。
  • **画面更新を停止する:** 大量の図形変更を行う場合は、`Application.ScreenUpdating = False` を設定して画面の再描画を抑制すると、処理速度が大幅に向上します。処理終了後に `Application.ScreenUpdating = True` を忘れずに設定してください。

Sub ProcessManyShapes()
Application.ScreenUpdating = False ‘ 画面更新を停止

Dim sh As Shape
For Each sh In ActiveSheet.Shapes
‘ ここで何らかの処理を行う
‘ 例: If sh.Type = msoTextBox Then sh.TextFrame.Characters.Text = “Processsed”
Next sh

Application.ScreenUpdating = True ‘ 画面更新を再開
MsgBox “図形処理が完了しました。”, vbInformation
End Sub

まとめ

ShapesコレクションとDrawingObjectsコレクションは、Excel VBAで図形オブジェクトを操作する上でそれぞれ異なる役割と特性を持っています。Shapesコレクションは、シート上のあらゆる視覚要素を網羅する汎用性の高いコレクションであり、ほとんどの図形操作において第一選択肢となります。一方、DrawingObjectsコレクションは、特定の描画オブジェクトに特化したコレクションであり、限定的な用途や互換性維持のために使用されます。

本記事で解説した両コレクションの相違点、具体的な使い方、そして実践的なアドバイスを理解し、適切に使い分けることで、より効率的で洗練されたVBAコードを作成できるようになります。ぜひ、これらの知識を実際の業務で活用し、Excel作業の自動化と効率化をさらに進めてください。

タイトルとURLをコピーしました