こんにちは!Word VBAの世界へようこそ。
マクロの記録ボタンを押して自動生成されたコードを見たものの、「なんだこの呪文は…」「変えたくないページまで向きが変わってしまう!」と頭を抱えた経験はありませんか?
Wordのレイアウト制御は、Excelのセル操作とは全く違う独特の哲学を持っています。特に「縦向きのページの中に、1枚だけ横向きの表を差し込みたい」といったレイアウトの混在は、多くの開発者がつまずくポイントです。
今回は、Word VBAのオブジェクトモデルの本質を捉え、「セクション」と「Range.PageSetup」を華麗に操ってレイアウト崩れを防ぐ極意を伝授します。ここをクリアすれば、あなたのWord VBAスキルは間違いなく一段上のステージに到達しますよ!
—
1. Word VBAの基本哲学:Excelとの決定的な違い
Excelは「セル(Cell)」というグリッド(格子状)の世界ですが、Wordは「連続したテキストの流れ(ストリーム)」の世界です。
Wordでページや余白を変えたいとき、画面全体を指す `ActiveDocument.PageSetup` を安易にいじると、ドキュメント全体のレイアウトがすべて書き換わって大惨事になります。
部分的にページ設定を変えるために絶対に必要な概念、それが「セクション(Section)」です。
「セクション」とは、用紙の「着替え室」である
Wordの文書は、1つの大きなセクションから始まっています。途中で「ここから横向きにしたい!」と思ったとき、文書の中に「セクション区切り」という境界線(仕切り板)を挿入します。
この仕切り板で区切られたエリアごとに、用紙の向き(縦・横)、サイズ、余白といった「ページ設定(PageSetup)」を独立して持たせることができるのです。
—
2. マクロの記録の限界を超える:なぜ「Range」を使うのか?
「マクロの記録」を使ってページ設定を変更すると、以下のようなコードが生成されます。
‘ マクロの記録が吐き出す典型的なコード
Selection.PageSetup.Orientation = wdOrientLandscape
一見動くように見えますが、これは最悪のアンチパターンです。理由は以下の通りです。
1. カーソル(Selection)に依存している:ユーザーが意図しない場所をクリックしているだけで、意図しないセクションの向きが変わる。
2. 描画の負荷が高い:画面上のカーソルをいちいち動かすため(Selectの多用)、処理が遅く、画面がチラつく。
プロの選択:`Range.PageSetup` による直接制御
シニアエンジニアは `Selection` を使いません。代わりに、目に見えない文書内の「範囲(Range)」を指定し、その範囲が属するセクションに対してダイレクトに命令を下します。
これによって、画面を一切チラつかせず、一瞬で安全にレイアウトを書き換えることが可能になります。
—
3. 実践:縦・横混在ドキュメントを自動生成するVBAコード
それでは、現場で即戦力となる実用コードを見てみましょう。
このコードは、「表紙(縦) ➔ 本文(縦) ➔ 大規模なデータ一覧表(横) ➔ 結び(縦)」という、ビジネス書やレポートで非常によくあるレイアウトを自動構築するマクロです。
Sub CreateMixedLayoutDocument()
Dim doc As Document
Set doc = ActiveDocument
‘ —————————————————-
‘ 1. 表紙セクション(縦向き)
‘ —————————————————-
doc.Content.Text = “【業務効率化レポート】” & vbCrLf & “作成者:チーフアーキテクト” & vbCrLf
‘ —————————————————-
‘ 2. 本文セクションへの移行(セクション区切りの挿入)
‘ —————————————————-
‘ 文書の末尾に「次のページから新しいセクションを開始」する区切りを入れる
Dim secBody As Section
Set secBody = doc.Sections.Add(doc.Content.Paragraphs(doc.Content.Paragraphs.Count).Range, wdSectionNewPage)
‘ 本文セクションの設定(縦向き、余白すっきり)
With secBody.PageSetup
.Orientation = wdOrientPortrait
.TopMargin = CentimetersToPoints(2.5)
.BottomMargin = CentimetersToPoints(2.5)
End With
‘ 本文のテキストを追加
doc.Content.Append (“第1章:はじめに” & vbCrLf & “ここに通常の縦向きの文章が続きます。” & vbCrLf)
‘ —————————————————-
‘ 3. 横向きセクションの挿入(ここが今回のキモ!)
‘ —————————————————-
‘ さらに次のセクションを追加
Dim secLandscape As Section
Set secLandscape = doc.Sections.Add(doc.Content.Paragraphs(doc.Content.Paragraphs.Count).Range, wdSectionNewPage)
‘ ★Range経由ではなく、追加したSectionオブジェクトのPageSetupを直接叩くのが最も確実
With secLandscape.PageSetup
.Orientation = wdOrientLandscape ‘ 横向きに変更
.TopMargin = CentimetersToPoints(2#)
.BottomMargin = CentimetersToPoints(2#)
.LeftMargin = CentimetersToPoints(2#)
.RightMargin = CentimetersToPoints(2#)
End With
‘ 横向きセクションに大きな表のためのテキストを追加
doc.Content.Append (“【付録】大規模データ一覧表(このページだけ横向きになります)” & vbCrLf)
‘ —————————————————-
‘ 4. 最後の縦向きセクションへの復帰
‘ —————————————————-
Dim secEnd As Section
Set secEnd = doc.Sections.Add(doc.Content.Paragraphs(doc.Content.Paragraphs.Count).Range, wdSectionNewPage)
With secEnd.PageSetup
.Orientation = wdOrientPortrait ‘ 再び縦向きに戻す
End With
doc.Content.Append (“第2章:おわりに” & vbCrLf & “ここから再び縦向きに戻ります。”)
MsgBox “レイアウトの混在制御が完了しました!”, vbInformation
End Sub
コードの解説とここがポイント!
- `doc.Sections.Add(Range, Type)`: 指定した位置(Range)に新しいセクション区切りを挿入し、新しいセクションオブジェクトを返します。
- `CentimetersToPoints`関数: Word VBAでは、余白などの単位は「ポイント(1pt = 1/72インチ)」で指定する必要があります。人間が直感的にわかりやすい「センチメートル」で指定するために、この変換関数を使うのがプロの作法です。
- セクションごとに `.Orientation` や `.PageSetup` を独立して持たせているため、前のセクションのレイアウトを巻き込んで破壊する心配が一切ありません。
—
4. 陥りやすいエラーと回避の知見
現場でこのコードや応用を書く際によく遭遇する「罠」と、その回避策を共有しておきます。
罠①:「前のセクションとヘッダー・フッターが連動してしまう」
セクションを新しく追加すると、デフォルトでは「前と同じヘッダー/フッターを使用する(LinkToPrevious = True)」というおせっかいな機能が有効になっています。
これによって、「横向きページのせいで、次の縦向きページのヘッダーがおかしくなった!」という事故が起きます。
【解決策】
新しいセクションを作ったら、必ず以下のコードでリンクを断ち切りましょう。
‘ 新しく作ったセクションのヘッダーのリンクをオフにする
secLandscape.Headers(wdHeaderFooterPrimary).LinkToPrevious = False
罠②:最後のセクションの向きを変えたつもりが…
文書の「最後の1ページだけ」を横向きにしようとして、セクション区切りを入れずにページ設定を変えると、ドキュメント全体が横向きになります。
Wordで「一部だけ向きを変える」ときは、「変更したい部分の『前』」と「『後』」の両方にセクション区切りが必要になる点に注意してください(つまり、挟み撃ちにするイメージです)。
—
まとめ
今回は、Word VBAにおける「セクション制御」と「ページ設定の動的変更」について解説しました。
1. Excelと違い、Wordは「セクション」単位でページ設定を管理する。
2. `Selection`のカーソル操作は封印し、`Section` や `Range` オブジェクトを直接操作する。
3. レイアウトを変えるときはセクション区切りで「挟み撃ち」にし、必要に応じて `LinkToPrevious = False` でヘッダーの連動を切る。
この3つさえ押さえておけば、どんなに複雑なレイアウトの自動生成も自由自在です。
ここをクリアしたあなたなら、もうWord VBAで迷うことはありません。ぜひ実際の業務ツール開発に応用してみてくださいね!
