こんにちは。自動化の深淵へようこそ。
「マクロの記録」ボタンを押して生成される、あの冗長で不安定なコードに別れを告げる時が来ましたね。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`(範囲)という階層構造を持っています。今回は「文書全体」を扱いましたが、慣れてくれば「選択した箇所だけ」「特定のセクションだけ」という制御も容易になります。
まずはこのコードをコピーして、ご自身の環境で動かしてみてください。
「機械に命令を下し、一瞬で文書が変わる」という感覚。この成功体験こそが、あなたを真の自動化エンジニアへと進化させます。
何か不明点があれば、いつでも聞いてくださいね。あなたの挑戦を全力でサポートします。
