Word VBAの「表」を制する:全角・半角混在の地獄を終わらせるための極限コード
Wordで資料を作成していると、必ず直面する問題がある。「表の中の数字が全角だったり半角だったりして、CSV出力や集計時に大惨事になる」という問題だ。
初心者はここで「手作業で修正」という泥沼に足を踏み入れるが、我々アーキテクトにその選択肢はない。今日は、Wordのテーブルオブジェクトを安全かつ高速に走査し、全角英数字を半角へ一括変換する、プロダクションレベルのコードを伝授する。
—
なぜ「安易なループ」が死を招くのか
まず、初心者が書きがちな「ダメなコード」の象徴を理解してほしい。
‘ 【避けるべきコード】
For Each tbl In ActiveDocument.Tables
For Each row In tbl.Rows
‘ …ここでセルを深追いして処理
Next
Next
なぜこれが非効率なのか。Wordのオブジェクトモデルにおいて、`Tables`コレクションや`Rows`コレクションを無闇に回すのは、メモリのオーバーヘッドを増大させる。特にドキュメントが巨大な場合、オブジェクトの参照整合性を保つためのコストが無視できなくなる。
我々が目指すべきは、「ターゲットを絞り、一括でメモリ上に展開し、最小限のアクセスで書き換える」という設計思想だ。
—
実務で使える堅牢な変換マクロ
このコードは、現在のドキュメント内のすべての表を走査し、`StrConv`関数を用いて全角英数字を半角に強制変換する。ポイントは、`Range`オブジェクトを直接操作することで、カーソルの移動(`Selection`)を排除している点だ。カーソル移動はWord VBAにおいて最もパフォーマンスを損なう要因である。
Option Explicit
”’
”’
Public Sub NormalizeTableData()
Dim tbl As Table
Dim cell As cell
Dim targetRange As Range
‘ エラーハンドリング:表が存在しない場合のクラッシュを防ぐ
On Error GoTo ErrHandler
‘ 画面更新を停止して高速化
Application.ScreenUpdating = False
‘ ドキュメント内のすべての表に対してループ
For Each tbl In ActiveDocument.Tables
For Each cell In tbl.Range.Cells
‘ セル内のRangeオブジェクトを取得
Set targetRange = cell.Range
‘ セル末尾の「セルの終わりマーク」を除外するため、長さ調整
‘ これを忘れると、表の構造が崩壊する可能性がある
If targetRange.Characters.Count > 1 Then
targetRange.End = targetRange.End – 1
‘ StrConv: vbNarrowで全角→半角変換
targetRange.Text = StrConv(targetRange.Text, vbNarrow)
End If
Next
Next
CleanExit:
Application.ScreenUpdating = True
Exit Sub
ErrHandler:
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical
Resume CleanExit
End Sub
—
コードの心臓部を読み解く:なぜこの設計なのか
1. `Application.ScreenUpdating = False` の重み
Wordは描画更新のたびにリソースを食う。数千行の表を処理する場合、これがあるかないかで実行時間に数倍の差が出る。プロは「ユーザーに見せる必要のない計算」にCPUを割かない。
2. `targetRange.End – 1` の重要性
Wordのセルには、必ず「セル終端記号」という特殊文字が含まれている。これを`StrConv`で変換対象に含めると、表のレイアウトが崩壊し、最悪の場合ドキュメントが破壊される。この「-1」は、業務現場における防御策の要だ。
3. `Range`の直接操作
`Selection.MoveRight`などは一切使用していない。`Selection`は現在ユーザーが見ている画面と連動するため、バックグラウンド処理には不向きだ。常に`Range`オブジェクトを生成してメモリ上で処理を行うのが、堅牢なシステムの鉄則である。
—
データベース連携を見据えた注意点
このツールでクリーンアップしたデータを、後々SQL ServerやExcelへ流し込む予定があるなら、以下の2点だけは覚えておいてほしい。
- 非表示文字の混入: `StrConv`だけでは、コピー&ペーストで混入した「改行コード」や「タブ」は消えない。必要に応じて `Replace(targetRange.Text, vbCr, “”)` などを組み込み、クレンジングを強固にすること。
- 例外的な書式: 数式や図形がセル内に含まれている場合、`targetRange.Text` への代入で意図せぬ動作をする可能性がある。複雑な表を扱う場合は、`targetRange.Information(wdWithInTable)` で条件分岐を入れるのが賢明だ。
最後に:エンジニアとしてのマインドセット
コードをコピペして動かすのは誰でもできる。しかし、「なぜそのコードが保守性が高く、バグに強いのか」を言語化できることこそが、君をただの「VBA使い」から「自動化エンジニア」へと昇華させる。
このマクロをベースに、自分の業務に合わせてカスタマイズしてほしい。あなたの仕事の時間が、この数秒の自動化によって、よりクリエイティブなものに充てられることを期待している。
