Word VBAにおける「ミリ単位の精密レイアウト」の極意:ピクセルとポイントの呪縛から脱却せよ
Wordのテーブル操作を「なんとなく」の数値で行う時代は終わった。
印刷物や報告書において、1ミリのズレは「素人の仕事」を意味する。しかし、Wordの内部単位は「ポイント(pt)」だ。1インチ=72ポイントという厄介な仕様に振り回され、`Selection.Cells.Width`を調整しては崩れるレイアウトに溜息をつく日々は、今日で終わりにしよう。
今回は、真のプロフェッショナルが実務で採用する、「ミリ単位を絶対値として扱う」ための堅牢な設計手法を伝授する。
—
1. なぜ「ミリ指定」がWordで崩れるのか
Wordのレイアウトエンジンは、基本的に「可変的」である。
`PointsToMillimeters`や`MillimetersToPoints`という標準関数が存在するが、これら単体では不十分だ。なぜなら、「表のプロパティ」における「優先幅」や「自動調整」の設定が、VBAの指定を無効化するからである。
鉄則:レイアウトを制御するなら「自動調整」を殺せ
プログラムで精密に制御する場合、以下の設定を強制することがスタートラインだ。
- `Table.AllowAutoFit = False`(自動調整をオフにする)
- `Table.PreferredWidthType = wdPreferredWidthPoints`(幅をポイント単位の固定値にする)
これを怠れば、テキスト量やウィンドウ幅によって、あなたの苦労したレイアウトはものの数秒で崩壊する。
—
2. 【プロダクションコード】ミリ単位・精密テーブル生成器
このコードは、再利用性を極限まで高めたクラス設計の断片である。`Range`を引数に取ることで、ドキュメントのどこにでも精密な表を射出できる。
‘ ———————————————————
‘ 目的: 指定したミリ数で精密にテーブルを生成する
‘ ———————————————————
Public Sub CreatePrecisionTable(targetRange As Range, rows As Long, cols As Long)
Dim tbl As Table
Dim cellWidthPts As Single
‘ ミリをポイントに変換して格納
cellWidthPts = Application.MillimetersToPoints(30) ‘ 幅30mmで固定
‘ 表の追加
Set tbl = targetRange.Tables.Add(targetRange, rows, cols)
‘ 【重要】レイアウト崩壊を防ぐための防御的設定
With tbl
.AllowAutoFit = False ‘ 自動調整を無効化
.PreferredWidthType = wdPreferredWidthPoints
.PreferredWidth = cellWidthPts cols ‘ 全体の幅を固定
‘ セル幅の強制固定
Dim c As Cell
For Each c In .Range.Cells
c.Width = cellWidthPts
c.HeightRule = wdRowHeightExactly ‘ 高さを「固定値」に
c.Height = Application.MillimetersToPoints(10) ‘ 高さ10mmで固定
Next c
‘ 罫線の微調整(必要に応じて)
.Borders.Enable = True
End With
End Sub
—
3. 実務で「詰まない」ための3つの知見
① セル結合の罠を回避する
セルを結合する場合、`Range.Cells.Merge` を使うが、その直後に必ず 「結合後のセル幅の再計算」 を行うべきだ。結合後のセルは、親のテーブルが持つ優先幅の情報を引き継がないことがある。結合後に `Cell.Width` を明示的に再代入するコードを忘れてはならない。
② データ流し込み時の「テキスト溢れ」対策
データベースから文字列を流し込む際、文字数が想定を超えるとレイアウトが押し出される。
- 対策: `Cell.FitText = True` を設定せよ。これにより、セル幅内に収まるよう文字が自動縮小される。あるいは、文字列の長さを判定し、`Font.Size` を動的に下げるロジックを前段に噛ませるのが、伝説的なエンジニアの流儀だ。
③ データベース連携におけるライフサイクルの管理
ExcelやSQL Serverからデータを取得する場合、`Recordset`や`Collection`を `For Each` で回すだろう。その際、`DoEvents`をループに組み込むことを強く勧める。Wordは巨大なテーブルを生成する際、一時的にフリーズしたような挙動を見せることがある。`DoEvents`はプロセスの応答性を維持し、ユーザーに「止まっていない」という安心感を与える。
—
4. 最後に:コードは「文書」である
私が部下に求めているのは、動くコードではない。「明日、仕様変更があっても一行の修正で済むコード」だ。
今回のミリ単位制御も同様だ。`MillimetersToPoints` を直接コードに埋め込むのではなく、定数として管理し、レイアウトの定義を一つの設定用モジュールに集約せよ。
Word VBAはレガシーと言われることもある。だが、APIの奥底にある「描画エンジン」を制御し、ミリ単位で支配下に置く快感を知れば、これほど強力な自動化武器はないことに気づくはずだ。
さあ、そのテーブルを、美しく、狂いのないものへと進化させたまえ。君のコードで、Wordを「ただの文書作成ツール」から「精密なデータ出力エンジン」へと変えるのだ。
