こんにちは! Word VBAの世界へようこそ。
マクロの記録ボタンを押して「なんだかよくわからないけれど動いた!」という感動を味わった次は、「もっと処理を速くしたい」「思い通りにテキストを操りたい」という壁にぶ当たるころですね。
大丈夫、ここをクリアすれば、あなたのWord VBAスキルは「初学者」の領域を抜け出し、一気にプロのアーキテクトへと近づきます。
今回は、Word VBAにおける最大のパフォーマンスハックの一つ『Range.FormattedText』について、魂を込めて解説します。クリップボードの呪縛から解放され、爆速で書式付きテキストをコピーする方法を一緒にマスターしましょう!
—
1. なぜ「マクロの記録」のコピー&ペーストは遅いのか?
Wordでテキストと書式を別の場所にコピーしたいとき、マクロの記録を使うと大体こんなコードが出力されますよね。
‘ 【アンチパターン】マクロの記録が吐き出す典型的なコード
Selection.Copy
Selection.GoTo What:=wdGoToBookmark, Name:=”TargetArea”
Selection.Paste
一見、問題なく動くように見えますが、プロの視点から言うと「絶対にやってはいけないアンチパターン」です。
なぜなら、このコードは目に見えないところで「Windowsのクリップボード」を経由しているからです。
人間が「コピー&ペースト」をする感覚と同じように、WordがわざわざOSのクリップボード領域にデータを書き込み、それを別の場所に貼り付けるという重い処理を裏で行っています。
さらに、`Selection`(選択範囲)オブジェクトを操作しているため、画面の描き替え(スクリーン・アップデート)が発生し、処理がカクカクと遅くなります。数十回、数百回とこの処理を繰り返すマクロを作ったら……想像するだけで恐ろしいですよね。
—
2. 救世主『FormattedText』オブジェクトとは?
そこで登場するのが、今回の主役である `FormattedText` プロパティ です。
Word VBAにおける `Range` オブジェクトは、文字だけでなく「フォント名」「サイズ」「太字」「段落書式」といったすべてのスタイル情報(書式)を内包しています。
`FormattedText` を使えば、クリップボードを一切経由せず、メモリ上で直接 `Range` 同士の書式付きテキストをコピー・代入できるのです。
図解イメージ
- 従来のコピペ(Selection + クリップボード)
`[元Range]` ーー(OSのクリップボードを経由:重い!)ーー> `[先Range]`
- FormattedText による直結コピー
`[元Range]` ===(メモリ上でダイレクトに転送:爆速!)===> `[先Range]`
画面の書き換えも起きないため、処理速度は文字通り「ケタ違い」になります。
—
3. 実践!『FormattedText』を使った爆速コード
百聞は一見にしかず。実際にコードを見てみましょう。
ここでは、文書の冒頭にあるタイトル部分(書式付き)を、文書の末尾にある特定の位置へ一瞬でコピーするコードを書きます。
Sub CopyFormattedTextFast()
Dim doc As Document
Set doc = ActiveDocument
Dim rngSource As Range
Dim rngTarget As Range
‘ 1. 画面の描画を停止してさらにパフォーマンスを極限まで上げる
Application.ScreenUpdating = False
On Error GoTo ErrorHandler
オブジェクトのライフサイクルやパフォーマンスを知り尽くした
‘ 2. コピー元(ソース)のRangeを設定(例:先頭の段落)
Set rngSource = doc.Paragraphs(1).Range
‘ 3. コピー先(ターゲット)のRangeを設定(例:末尾の段落の挿入ポイント)
Set rngTarget = doc.Content
rngTarget.Collapse wdCollapseEnd ‘ 文書の最後にカーソルを合わせるイメージ
‘ 4. 【核心】FormattedTextで書式ごとダイレクトに転送!
rngTarget.FormattedText = rngSource.FormattedText
MsgBox “書式付きテキストの転送が完了しました!”, vbInformation
ErrorHandler:
‘ 5. 処理が終わったら必ず画面描画を戻す
Application.ScreenUpdating = True
If Err.Number <> 0 Then
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical
End If
End Sub
コードのポイント解説
- `Application.ScreenUpdating = False`: VBAの鉄則です。画面のチラつきを抑え、処理速度を劇的に向上させます。
- `rngTarget.Collapse wdCollapseEnd`: ターゲットの範囲を「文書の末尾の一点(文字数ゼロの幅)」に折りたたんでいます。これがないと、文書全体のテキストがコピー元のテキストに上書きされて消えてしまうので注意してください。
- `rngTarget.FormattedText = rngSource.FormattedText`: これが今回のキモです。`Selection`を使わず、見えないところで瞬時に「文字+書式」が流し込まれます。
—
4. 陥りやすい罠とエラー回避の知見
実務でこの `FormattedText` を使う際、中級者でもハマりがちな罠が一つだけあります。
それは、「コピー先の `Range` の寿命(ライフサイクル)」 です。
`FormattedText` で文字を流し込むと、代入された側の `Range` は「新しく挿入されたテキストを含む範囲」に自動的に拡張されます。もし同じ `Range` オブジェクトに対して連続で代入処理を行おうとすると、予期せぬ場所が書き換わったり、意図しないレイアウト崩れを起こす原因になります。
対策:
連続してテキストや書式を転送する場合は、毎回 `Range` の位置(StartとEnd)を正しく再定義するか、`Collapse` メソッドを使って挿入位置を常に末尾にコントロールする癖をつけましょう。
—
おわりに:ここをクリアすれば、Word VBAの基本はバッチリです!
お疲れ様でした!
今回は `Selection` から脱却し、メモリ上で効率よくオブジェクトを操作する `FormattedText` の世界をご紹介しました。
- クリップボードを使わないから速い。
- 画面を書き換えないからスマート。
- 余計なオブジェクトを選択しないからバグに強い。
この3つを意識するだけで、あなたが書くWordマクロの質は見違えるほどプロフェッショナルなものになります。ぜひ、日々の業務自動化に取り入れて、その圧倒的なスピードを体感してみてください。
それでは、次回の極限の知見でお会いしましょう!
