こんにちは。Word VBAの世界へようこそ。
「マクロの記録」ボタンを押して生成された、冗長で不安定なコードに絶望したことはありませんか?
WordのオブジェクトモデルはExcelよりも遥かに「文脈」を読み取る必要があるため、少し癖があります。しかし、一度その本質を掴めば、あなたは数千ページの文書を一瞬で操る魔術師になれるでしょう。
今日は、業務自動化の登竜門であり、かつ奥義でもある「文書の分割と結合」について、メモリ管理と整合性の観点から解説します。ここをクリアすれば、Word VBAの基本はバッチリです。
—
1. なぜ「Range」を使うのか?(オブジェクトの哲学)
多くの初心者は `Selection` を使ってカーソルを動かそうとします。しかし、これは「画面をスクロールさせながら手作業でテキストを選択する」のと同じで、非常に低速でエラーの温床です。
プロのエンジニアは `Range` オブジェクトを使います。
`Range` とは、文書内の「ある地点からある地点までの仮想的なマーキング」です。画面を動かさず、メモリ上で直接操作するため、圧倒的に高速かつ安全です。
—
2. 実践:章ごとの文書分割(メモリ管理の極意)
大きな文書を章ごとに分割する際、最も重要なのは「オブジェクトの解放」と「文書の整合性」です。
思考のプロセス
1. 文書の最後にある「セクション区切り」や「見出しスタイル」を起点に範囲を特定する。
2. その範囲を新しい文書へコピーする。
3. 重要: 新しい文書を作成する際、元の文書のスタイル定義を継承させる。
Sub SplitDocumentByHeading()
Dim docSource As Document
Dim docNew As Document
Dim rngTarget As Range
Dim i As Long
Set docSource = ActiveDocument
‘ 効率化:画面更新と警告を一時停止(処理速度を劇的に改善)
Application.ScreenUpdating = False
Application.DisplayAlerts = wdAlertsNone
‘ 文書内の各セクションを順次処理する例
For i = 1 To docSource.Sections.Count
‘ 現在のセクション範囲を取得
Set rngTarget = docSource.Sections(i).Range
‘ 新規文書を作成
Set docNew = Documents.Add
‘ 範囲をコピーして貼り付け
docNew.Range.FormattedText = rngTarget.FormattedText
‘ ファイル名を決めて保存(拡張子を忘れずに)
docNew.SaveAs2 FileName:=docSource.Path & “\Chapter_” & i & “.docx”
docNew.Close SaveChanges:=wdDoNotSaveChanges
Next i
Application.ScreenUpdating = True
Application.DisplayAlerts = wdAlertsAll
MsgBox “分割完了!メモリもクリーンな状態です。”
End Sub
—
3. 文書結合の罠:ページ番号と目次の崩壊を防ぐ
複数のファイルを結合する際、単に `InsertFile` するだけでは、目次(TOC)やページ番号がバラバラになります。ここで重要なのが「セクション区切りの制御」です。
ページ番号を維持するテクニック
文書を結合する際は、「次から開始」のセクション区切りを適切に挿入し、ページ番号のプロパティを「前のセクションから引き継ぐ」設定に強制変更する必要があります。
Sub MergeDocumentsAndFixPagination()
Dim docMain As Document
Dim strFilePath As String
Dim fso As Object
Set docMain = Documents.Add
‘ 結合対象のフォルダパス(実務に合わせて変更してください)
strFilePath = “C:\Reports\Chapters\”
‘ 順次ファイルを挿入
‘ InsertFileはRangeの末尾に対して実行するのが鉄則
With docMain.Range(0, 0)
.InsertFile FileName:=strFilePath & “Chapter1.docx”
.InsertBreak Type:=wdSectionBreakNextPage ‘ セクション区切りを入れる
.InsertFile FileName:=strFilePath & “Chapter2.docx”
End With
‘ ページ番号の連続性を保証する(全セクションをループ)
Dim sec As Section
For Each sec In docMain.Sections
With sec.Headers(wdHeaderFooterPrimary).PageNumbers
.RestartNumberingAtSection = False ‘ 前のセクションから引き継ぐ
End With
Next sec
‘ 最後に目次を更新
docMain.TablesOfContents(1).Update
End Sub
—
4. 伝説のエンジニアからのアドバイス:エラーを避けるために
1. オブジェクトの明示的参照: `ActiveDocument` を連発してはいけません。必ず `Set doc = Documents.Open(…)` のように変数に格納してください。VBAは「今どの文書がアクティブか」を見失いやすいからです。
2. FormattedTextを使う: 単なる `Text` の転送は書式を捨てます。`FormattedText` を使うことで、太字やフォントサイズなどのメタデータを保持したまま、高速に文書間を移動できます。
3. 「Range(0,0)」の魔法: 文書の先頭に挿入したい場合、`Range(0, 0)` を使います。これは「0番目から0番目まで(つまり挿入ポイント)」を指す、Word VBAにおける最強の定石です。
—
まとめ
Word VBAは「文書という巨大な構造体」を操作するパズルです。
最初は難しく感じるかもしれませんが、`Range` と `Section`、そして `FormattedText` をマスターすれば、あなたの仕事は数秒で終わるようになります。
まずは、小さな文書でコードを書いてみてください。エラーが出たら、それはPCからの「もっと効率の良い書き方があるよ」というサインです。そのサインを一つずつ紐解いていくことこそが、伝説のエンジニアへの第一歩です。
応援していますよ。困ったことがあれば、またいつでも聞きに来てくださいね。
