目次

1. はじめに:VBAでの図形・画像処理における「ずれる」「消せない」という悩み

Excel VBAを使用して業務を自動化する際、セルのデータ処理だけでなく、シート上に配置された図形(オートシェイプ)や写真などの画像データを操作する機会は多くあります。例えば、システムから出力された大量の製品画像をフォーマットに合わせて配置したり、不要になった図形を定期的にクリアしたりする作業です。

しかし、VBAで図形や画像を扱う際、多くの開発者が以下のような壁にぶつかります。

  • 「マクロで行や列を挿入・削除したり、セルの幅を変更したりすると、配置したはずの図形や画像が勝手に縦横に伸びたり、位置がずれたりしてしまう」
  • 「マクロでシート上の図形を一括削除しようとしたら、なぜか削除しきれずに残ってしまう図形がある」
  • 「VBAで削除コードを実行したら、図形と一緒にマクロを起動するためのボタンや、セルのコメントまで消えてしまった」

これらはExcelの仕様や、コレクション(オブジェクトの集まり)をVBAで処理する際の特有のメカニズムを理解していないことによって引き起こされます。

この記事では、図形や画像がずれてしまう原因とその防止策、そしてエラーなく安全に、かつ意図した図形だけを一括処理(削除・位置調整)するためのマクロの書き方を、実務レベルの正確な知識に基づいて4000文字以上のボリュームで徹底的に解説します。

2. 図形や画像が「ずれる」原因と根本的な解決策

行列の挿入・削除やサイズ変更による影響

Excelのシートに図形や画像を貼り付けた際、それらのオブジェクトは内部的に「特定のセル(左上の角が位置するセル)」に紐づいて配置されています。そのため、ユーザーの手作業やVBAのマクロによって行や列の挿入・削除、あるいはセルの高さや幅の変更が行われると、Excelはデフォルトの仕様として、セルの変動に合わせて図形の位置やサイズを自動的に追従させようとします。

これが「図形がずれる」「画像が勝手に伸び縮みする」という現象の正体です。この動作を制御するためには、図形の「プロパティ」にアクセスし、セルに対する動作設定を変更する必要があります。

Placementプロパティの3つの定数とその意味

VBAにおいて、図形や画像がセルに合わせてどのように振る舞うかを決定するのが、Shape オブジェクトの Placement プロパティです。このプロパティには、以下の3つの定数のいずれかを設定します。

  • xlMoveAndSize (値: 1)
    「セルに合わせて移動やサイズ変更をする」という設定です。多くの場合、図形を新規作成した際のデフォルト設定がこれになっています。セルの幅を広げると図形も広がり、行を挿入すると図形も一緒に下に移動します。
  • xlMove (値: 2)
    「セルに合わせて移動するがサイズ変更はしない」という設定です。行の挿入などでセルの位置が変われば一緒に移動しますが、セルの幅や高さを変更しても図形の大きさはそのまま維持されます。
  • xlFreeFloating (値: 3)
    「セルに合わせて移動やサイズ変更をしない」という設定です。これを設定すると、図形はシートの絶対的な座標に固定されます。セルの幅を変えようが、行を挿入・削除しようが、図形の位置とサイズは一切変わりません。

「図形がずれる」という問題を完全に解決するためには、目的の図形の Placement プロパティを xlFreeFloating または xlMove に設定する必要があります。

VBAで図形のPlacementを一括設定してズレを防止するコード

以下のマクロは、アクティブなシート上に存在するすべての図形・画像に対して、一括で「セルに合わせて移動やサイズ変更をしない(xlFreeFloating)」を設定するコードです。データ処理を行うマクロの序盤にこれを実行しておくことで、その後の行列操作によるレイアウト崩れを完全に防ぐことができます。

Sub SetShapesFreeFloating()
    Dim shp As Shape

    ' アクティブシート上のすべてのShapeオブジェクトをループ処理
    For Each shp In ActiveSheet.Shapes
        ' Placementプロパティを変更し、セル操作によるズレや変形を防ぐ
        shp.Placement = xlFreeFloating
    Next shp

    MsgBox "すべての図形を「セルに合わせて移動やサイズ変更をしない」に設定しました。", vbInformation
End Sub

3. 図形や画像がVBAで「削除できない」3つの原因

VBAで Shape.Delete メソッドを使用してもエラーが発生したり、図形が消えずに残ってしまったりする場合、主に以下の3つの原因が考えられます。

原因1:シートが保護されている

最も多い原因です。Excelのシートが保護されており、かつ「オブジェクトの編集」が許可されていない場合、VBAから図形を削除しようとすると「実行時エラー 1004」が発生します。図形を操作する前には、必ず ActiveSheet.Unprotect を用いてシートの保護を解除し、操作が終わった後に再保護するという処理を組み込む必要があります。

原因2:図形がグループ化されている

複数の図形がグループ化されている場合、グループ内の個別の図形(子オブジェクト)を直接指定して削除しようとすると失敗することがあります。VBAで削除を行う場合、グループ全体(親オブジェクト)を一つのShapeとして扱うため、適切にループ処理を組んでいれば通常はグループごと削除されますが、複雑な階層になっている場合は Ungroup メソッドでグループ化を解除してから削除するアプローチが必要になることがあります。

原因3:非表示になっている図形の存在

Visible プロパティが msoFalse に設定され、画面上からは見えなくなっている図形が存在することがあります。ユーザーが画面上で全選択してDeleteキーを押してもこれらは消えませんが、VBAの Shapes コレクションには含まれているため、マクロの処理対象となります。見えない図形が原因で思わぬエラーを引き起こすことがあるため、VBAでは非表示の図形も含めて処理できるという点を理解しておく必要があります。

4. VBAで図形・画像を安全に一括削除するマクロの書き方

最も重要なルール:ループは「後ろから順番に」回す(Step -1)

シート上の図形をすべて削除する際、初心者が書きがちなのが For i = 1 To ActiveSheet.Shapes.Count という昇順のループ処理です。しかし、この書き方では「図形が消え残る」というバグが必ず発生します。

理由は、コレクション(オブジェクトの集まり)から要素を削除すると、残りの要素のインデックス番号(順番)が自動的に前に詰められるからです。
例えば、1番目の図形を削除すると、元々2番目だった図形が「新しい1番目」に繰り上がります。しかし、ループのカウンター変数は「次は2番目」へと進んでしまうため、「新しい1番目(元2番目)」の図形は処理をスキップされてしまい、結果として半分ほどの図形が消え残ってしまいます。

この問題を回避するための絶対的な鉄則が、「インデックスの最後尾から先頭に向かって逆順にループを回す」ことです。VBAでは Step -1 を使用します。

すべての図形を無条件で一括削除する基本コード

上記の鉄則に従った、最も安全かつ確実な図形一括削除の基本コードは以下の通りです。

Sub DeleteAllShapesSafely()
    Dim i As Long

    ' シートの保護を解除(パスワードがある場合は Password:="パスワード" を追加)
    ActiveSheet.Unprotect

    ' 図形の総数を取得し、最後尾から1に向かって逆順にループ処理を行う
    For i = ActiveSheet.Shapes.Count To 1 Step -1
        ActiveSheet.Shapes(i).Delete
    Next i

    MsgBox "すべての図形を削除しました。", vbInformation
End Sub

5. 実務で必須!特定の種類の図形だけを削除・除外するテクニック

Shape.Typeプロパティによるオブジェクトの識別

前章のコードを実行すると、シート上のありとあらゆるShapeオブジェクトが削除されます。しかし実務においては、「貼り付けた商品画像だけを消したい」「マクロを実行するためのボタンは残したい」「セルのコメント機能もShapeとして認識されるため、消さずに残したい」といった細やかな制御が必須となります。

図形の種類を判別するためには、Shape オブジェクトの Type プロパティを使用します。このプロパティは、オブジェクトの種類を表す MsoShapeType 列挙型の数値を返します。代表的なものは以下の通りです。

  • msoPicture (値: 13):画像、写真
  • msoAutoShape (値: 1):オートシェイプ(四角形、矢印など)
  • msoFormControl (値: 8):フォームコントロール(マクロ登録用のボタンなど)
  • msoOLEControlObject (値: 12):ActiveXコントロール
  • msoComment (値: 4):セルのコメント
  • msoChart (値: 3):グラフ
  • msoGroup (値: 6):グループ化された図形

マクロ実行ボタンやコメントを誤って消さないための条件分岐

一括削除処理を行う際、マクロ起動用のボタン(msoFormControl や msoOLEControlObject)や、重要な注釈であるコメント(msoComment)を保護するための条件分岐(If文)を組み込むのは、プロのVBA開発者として必須のテクニックです。

写真・画像(Picture)だけを狙って一括削除するコード

以下は、Type プロパティを利用して、「画像(msoPicture)」だけを正確に狙って一括削除するサンプルコードです。その他のボタンや図形、コメントは一切影響を受けません。

Sub DeleteOnlyPictures()
    Dim i As Long
    Dim shpType As Long

    ActiveSheet.Unprotect

    ' 逆順ループで処理
    For i = ActiveSheet.Shapes.Count To 1 Step -1
        ' 図形の種類を取得
        shpType = ActiveSheet.Shapes(i).Type

        ' 種類が画像(msoPicture)の場合のみ削除を実行する
        If shpType = msoPicture Then
            ActiveSheet.Shapes(i).Delete
        End If
    Next i

    MsgBox "画像データのみを削除しました。", vbInformation
End Sub

6. 実務でそのまま使える最強の図形一括処理マクロテンプレート

これまでに解説した知識をすべて統合し、実務で安全に運用できる「最強の図形一括処理マクロ」のテンプレートを公開します。
このマクロは以下の動作を一度に、かつ安全に行います。

  1. シートの保護を一時的に解除する。
  2. マクロ実行ボタンやセルのコメント、入力規則のドロップダウンなどの「システム上必要なオブジェクト」を除外する。
  3. それ以外の不要な図形や画像をすべて削除する。
  4. 残した図形(ボタンなど)が、今後のセル操作で崩れないように「セルに合わせて移動やサイズ変更をしない(xlFreeFloating)」に設定を修正する。
  5. 最後にシートを再度保護する。
Sub UltimateShapeManager()
    Dim i As Long
    Dim shp As Shape
    Dim shpType As Long
    Dim ws As Worksheet

    Set ws = ActiveSheet

    ' 画面のチラつき防止と高速化
    Application.ScreenUpdating = False

    ' シート保護の解除
    ws.Unprotect

    ' --- ステップ1:不要な図形の削除 ---
    ' 削除を伴うため、必ず最後尾からStep -1でループ
    For i = ws.Shapes.Count To 1 Step -1
        Set shp = ws.Shapes(i)
        shpType = shp.Type

        ' 削除してはいけないオブジェクトを判定
        ' 8=フォームボタン, 12=ActiveX, 4=コメント, 14=入力規則のドロップダウン
        If shpType <> msoFormControl And _
           shpType <> msoOLEControlObject And _
           shpType <> msoComment And _
           shpType <> 14 Then ' 14はドロップダウン(msoFormControlの亜種)

            ' 条件に該当しない(残すべきではない)図形・画像を削除
            shp.Delete
        End If
    Next i

    ' --- ステップ2:残ったオブジェクトのズレ防止設定 ---
    ' 削除処理が終わった後なので、通常のFor Eachループで問題なし
    For Each shp In ws.Shapes
        ' コメント(Type=4)のPlacementを変更するとエラーになる場合があるため除外
        If shp.Type <> msoComment Then
            ' セルに合わせて移動・サイズ変更しないように固定
            shp.Placement = xlFreeFloating
        End If
    Next shp

    ' シートの再保護
    ws.Protect

    ' 画面更新の再開
    Application.ScreenUpdating = True

    MsgBox "図形の整理と位置の固定化が完了しました。", vbInformation
End Sub

このテンプレートコードを使用することで、図形の消し漏れやシステム破壊を防ぎつつ、完璧なレイアウト維持とクリーンアップを同時に実現できます。

7. まとめ

VBAを利用した図形や画像の自動処理は、Excel特有の仕様による落とし穴が多く存在します。図形が「ずれる」問題については、セルへの追従設定である Placement プロパティを理解し、xlFreeFloating など適切な定数を設定することで完全にコントロール可能です。

また、図形が「削除できない」「消え残る」問題については、シートの保護状態の確認に加え、コレクション要素の削除における大原則である「後ろから順番に削除する(Step -1)」というループ構造を用いることが唯一の解決策となります。

さらに実務では、一律にすべてを削除するのではなく、Type プロパティを活用して「マクロボタン」や「コメント」といった重要な要素を保護する条件分岐が欠かせません。今回提供した最強のテンプレートコードをベースにして、あなたの業務要件に合わせた堅牢な画像・図形処理マクロを構築してください。