こんにちは!Word VBAの世界へようこそ。
マクロの記録ボタンを押して、画面がガチャガチャと切り替わる自動操作に感動したのも束の間、「なんだか処理が遅いな」「画面がチラついてイライラするな」と感じ始めたあなた。おめでとうございます。それこそが、シニア・エンジニアへの第一歩です。
今回は、数あるWord VBAの機能の中でも、一歩進んだ「表データの高速転送」についてお話しします。
一般的なテキストのコピー&ペーストや、`Range`オブジェクトを画面経由で行き来させる方法は、裏でWordの描画エンジンが必死に画面を書き換えているため、どうしても動作が重くなります。
これを解決するのが、「メモリ上でのデータ直接やり取り(バイナリ的アプローチ)」です。
ここをクリアすれば、あなたももう初心者ではありません。一緒にWord VBAの本質をマスターしていきましょう!
—
1. なぜ「画面を触らない」と爆速になるのか?
初心者がやりがちなミスは、次のようなコードです。
‘ 【NGな例】画面の選択とコピー&ペーストに頼った処理
Selection.Tables(1).Range.Copy
Documents.Open “C:\Target.docx”
Selection.Paste
これの何が問題か分かりますか?
Wordにとって「画面を選択する(Select)」「クリップボードを経由する」「貼り付ける(Paste)」という一連の動作は、人間が手作業で行うのとほぼ同じ負荷をVBAに強いることになります。ファイルが大きいと、これだけで数秒〜数十秒のロスが生まれます。
プロの頭の中:データは「配列(Array)」と「セル(Cell)」の直接参照で扱う
Wordの表(Table)は、突き詰めれば「行(Row)と列(Column)の二次元グリッド」です。
画面を一切選択せず、メモリ上で「A社の表の1行2列目の文字列」を「B社の表の2行1列目」に直接代入してしまった方が、圧倒的に速く、エラーも起きません。
—
2. 【実践】別ファイルの表から表へ、データをダイレクトに流し込むコード
それでは、今回のメインディッシュです。
「元となるファイル(Source)」の表データを一瞬で読み込み、画面の描き換えを一切行わずに「宛先ファイル(Destination)」の表へ流し込む、実用的なプロシージャを公開します。
開発の現場でそのままコピペして使えるよう、丁寧なコメントをつけておきました。
Option Explicit
Sub TransferTableDataFast()
‘ =========================================================================
‘ 目的: 画面描画を完全に抑制し、メモリ上で表データを高速転送する
‘ 前提: 元ファイルと宛先ファイルの双方が開かれている、またはパスを指定して開く
‘ =========================================================================
Dim srcDoc As Document, dstDoc As Document
Dim srcTable As Table, dstTable As Table
Dim r As Long, c As Long
Dim maxRow As Long, maxCol As Long
‘ 【超重要】画面描画と警告をオフにして、マクロの速度を限界まで引き上げる
Application.ScreenUpdating = False
Application.DisplayAlerts = wdAlertsNone
On Error GoTo ErrorHandler
‘ 1. ドキュメントとテーブルのオブジェクトを特定
‘ (今回はアクティブ文書と、あらかじめ開いてある2番目の文書を例にします)
Set srcDoc = ActiveDocument
‘ ※実務ではここで Workbooks.Open などの代わりに Documents.Open を使ってパスを指定します
Set dstDoc = Documents(2)
‘ 双方の文書に表が存在するかチェック
If srcDoc.Tables.Count = 0 Or dstDoc.Tables.Count = 0 Then
MsgBox “転送対象となる表が見つかりません。”, vbExclamation
GoTo Finally
End If
Set srcTable = srcDoc.Tables(1)
Set dstTable = dstDoc.Tables(1)
‘ 2. 行数と列数を取得(余計なセル末尾の特殊文字を排除してクリーンに扱う)
maxRow = srcTable.Rows.Count
maxCol = srcTable.Columns.Count
‘ 3. 宛先側の表のサイズが足りない場合は、行を動的に追加する
Do While dstTable.Rows.Count < maxRow
dstTable.Rows.Add
Loop
' 4. 【核心】セル単位のテキストデータをメモリ上で直接ダイレクト転送
' Rangeオブジェクトをコピーするのではなく、Textプロパティの値を直接代入します
For r = 1 To maxRow
For c = 1 To maxCol
' Wordのセル末尾には必ず「セル終了マーク(Chr(13) + Chr(7))」が含まれるため
' 取得・設定時は余分な制御文字をトリムするのがプロの技
Dim cellText As String
cellText = srcTable.Cell(r, c).Range.Text
' 末尾の制御文字(2文字分)を削除
If Len(cellText) >= 2 Then
cellText = Left(cellText, Len(cellText) – 2)
End If
‘ 宛先のセルへダイレクトに流し込む
dstTable.Cell(r, c).Range.Text = cellText
Next c
Next r
‘ 正常終了メッセージ
MsgBox “表データの高速転送が完了しました!”, vbInformation
Finally:
‘ 【重要】オフにした設定は、必ずfinallyブロックで元に戻すこと!
Application.ScreenUpdating = True
Application.DisplayAlerts = wdAlertsAll
Exit Sub
ErrorHandler:
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical
Resume Finally
End Sub
—
3. コードのキモと、初心者がハマりがちな「Word特有の罠」
上記のコードで、特に重要なポイントをエンジニアの視点から解説します。
① `Application.ScreenUpdating = False` の魔法
これを記述すると、Wordは画面を再描画する処理を一切放棄します。結果として、何千行という巨大な表を処理する際でも、一瞬で処理が完了します。
ただし、エラー時に `True` に戻し忘れるとWordがフリーズしたような状態になるため、必ず上記のコードのように `ErrorHandler` や `Finally` の概念を組み込みましょう。
② Wordの表セルにある「見えない文字」の正体
Excelのセルと違い、Wordの表の `Cell(r, c).Range.Text` をそのまま取得すると、文字列の最後に必ず `vbCr & vbBel`(セル終了マーク) という特殊な制御文字がくっついてきます。
これを無視して別のセルに代入し続けると、表がどんどん歪んでいったり、謎の改行が大量発生するバグの原因になります。
コード内で行っている `Left(cellText, Len(cellText) – 2)` という処理こそが、この厄介な制御文字をキレイに剥ぎ取るためのプロのテクニックです。
—
まとめ:ここをクリアすれば、Word VBAは怖くない!
今回は、オブジェクトのライフサイクルとパフォーマンスを意識した「メモリ上での表データ高速転送」について解説しました。
- 画面(Selection)を触るな、オブジェクト(Range / Cell)を直接叩け。
- 重い処理の前には `ScreenUpdating = False` を忘れるな。
- Wordのセル末尾の制御文字(-2文字)に気をつけろ。
この3つさえ押さえておけば、あなたが書くマクロは「ただ動くもの」から「実務で頼りにされるプロフェッショナルなツール」へと生まれ変わります。
最初は難しく感じるかもしれませんが、実際にコードを動かして、その「一瞬で処理が終わる爽快感」をぜひ味わってみてください。
あなたのWord VBAライフが、より一層素晴らしいものになることを応援しています!
