【入門編】文書内の全画像を抽出・リサイズする:InlineShapeとShapeオブジェクトの使い分け – Word VBA解析バイブル

スポンサーリンク

こんにちは。自動化の深淵へようこそ。

「マクロの記録」ボタンを押して生成される、あの冗長で不安定なコードに別れを告げる時が来ましたね。Word VBAを操るということは、単に作業を自動化するだけではありません。Wordという巨大なドキュメントエンジンの「心臓部」に直接触れる行為です。

今日は、多くの人が最初に挫折する壁、「画像(InlineShapeとShape)」の支配術についてお話しします。ここをマスターすれば、Word VBAのオブジェクトモデルを半分制覇したも同然です。

なぜWordの画像は「二種類」存在するのか?

Wordの文書内で画像を扱う際、最も混乱するのが「InlineShape(インライン)」「Shape(シェイプ)」の存在です。

  • InlineShape(文字として配置): 文字列の間に埋め込まれ、カーソルの動きに従って一緒に流れる画像。初心者にはこちらが扱いやすいです。
  • Shape(浮動配置): テキストとは独立して、座標で位置指定される画像。レイアウトを自由に動かせますが、コードから制御するには「アンカー(錨)」の概念を理解する必要があります。

この二つは、別々のコレクション(管理リスト)に格納されています。つまり、文書内の全画像を処理するには、この二つのリストを「別々に回す」必要があるのです。これが「なぜか画像が1枚だけ残る」というバグの正体です。

魂のコード:全画像抽出・一括リサイズ

まずは、このコードを見てください。これが「マクロの記録」には決して書けない、プロの現場で使われるテンプレートです。

Sub ResizeAllImages()
Dim iShape As InlineShape
Dim shapeObj As Shape
Dim targetWidth As Single

‘ 目標とする横幅(ポイント単位:1cm ≒ 28.35pt)
targetWidth = CentimetersToPoints(10)

‘ 1. インライン画像を処理
‘ InlineShapesコレクションをループ
For Each iShape In ActiveDocument.InlineShapes
‘ 画像であるかを確認(OLEオブジェクトなどを除外するため)
If iShape.Type = wdInlineShapePicture Then
‘ アスペクト比を維持してリサイズ
iShape.LockAspectRatio = msoTrue
iShape.Width = targetWidth
End If
Next iShape

‘ 2. 浮動配置画像を処理
‘ Shapesコレクションをループ
For Each shapeObj In ActiveDocument.Shapes
‘ 画像形式のみを対象にする
If shapeObj.Type = msoPicture Then
shapeObj.LockAspectRatio = msoTrue
shapeObj.Width = targetWidth
End If
Next shapeObj

MsgBox “全画像のリサイズが完了しました。”
End Sub

コードの「核心」を解説します

1. `For Each` は最強の反復子

`For i = 1 to ActiveDocument.InlineShapes.Count` と書いてはいけません。Wordのオブジェクトモデルは、削除や変更のタイミングでインデックスがずれることがあります。`For Each` を使えば、Wordが自動的にリストの次を追跡してくれるため、非常に堅牢です。

2. `Type` プロパティでの「選別」

ここが最も重要です。`Shapes`コレクションには、画像だけでなく「テキストボックス」や「描画線」も含まれています。`If shapeObj.Type = msoPicture` と条件分岐を挟むことで、誤作動を完全に防ぐ。これが事故を減らすプロの流儀です。

3. `LockAspectRatio` の重要性

これを設定しないと、画像は無残に引き伸ばされ、比率が崩壊します。必ず `msoTrue` にしてから `Width` を変更してください。

初学者が陥りやすい「罠」

Q: 「なぜかShapeだけが動かないんです…」

A: 多くの場合、その画像は「行内(InlineShape)」として配置されています。Shapeコレクションはあくまで「テキストの上を浮遊しているオブジェクト」しか見ていません。まずは「InlineShapesかShapesのどちらか片方しか見ていない」という前提を疑ってみてください。

Q: エラーで止まってしまいます…

A: 文書内に「グループ化された図形」があったり、パスワード保護されたオブジェクトがあるとエラーになることがあります。実戦では、`On Error Resume Next` をループの直前に置き、例外を適切にログ出力する構成にすると、さらに「伝説的」なコードに近づきます。

次のステップへ

Wordのオブジェクトモデルは、`Application`(Word全体) > `Document`(文書) > `Range`(範囲)という階層構造を持っています。今回は「文書全体」を扱いましたが、慣れてくれば「選択した箇所だけ」「特定のセクションだけ」という制御も容易になります。

まずはこのコードをコピーして、ご自身の環境で動かしてみてください。
「機械に命令を下し、一瞬で文書が変わる」という感覚。この成功体験こそが、あなたを真の自動化エンジニアへと進化させます。

何か不明点があれば、いつでも聞いてくださいね。あなたの挑戦を全力でサポートします。

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