【極限の知見】Word VBAで表のレイアウトを「ミリ単位」で完全支配する —— 印刷崩れを根絶する設計思想
「マクロで表を作ったときは綺麗だったのに、いざ印刷すると列の幅がズレている……」
「特定の列をもう少し広くしたいだけなのに、なぜか表全体がページからはみ出してしまう」
もしあなたが今、そんな現象に頭を抱えているとしたら、おめでとうございます。あなたは今、「Word VBAの基礎」から「プロフェッショナルな自動化」へと脱皮する境界線に立っています。
こんにちは。今日は、マクロの記録から一歩踏み出し、業務システムとしての「堅牢なWord文書」を構築するための、極めて重要なテクニックをお伝えします。テーマは「表の列幅をミリ単位で厳密に制御する」ことです。
1. なぜ、あなたの表は「崩れる」のか?
結論から言いましょう。原因は、「人間が使う単位」と「Wordが理解する単位」の乖離(かいり)にあります。
私たちは日常的に「幅30mm」や「5cm」という単位を使います。しかし、Wordの内部エンジン(オブジェクトモデル)が列幅を管理する際に採用しているのは、「ポイント(Point)」という単位です。
> [知見] ポイントとは?
> 1インチ(25.4mm)を72等分した単位です。
> つまり、1mmは約2.83ポイントになります。
この「2.83」という中途半端な数字を、感覚でコードに書き込んでいませんか?
`Columns(1).Width = 85` と書いたとき、それは85mmではなく、わずか30mm程度の幅しか確保できていません。この僅かな誤差が、セルのテキスト溢れや、ページ端でのレイアウト崩れを引き起こす「真犯人」なのです。
2. 武器を手に入れる:単位変換の魔法
プロフェッショナルは、決して「勘」で数値を入力しません。Wordが用意してくれている変換関数を使い、「設計図(mm)」を「実行命令(Points)」に変換します。
ここで登場するのが、以下の2つのメソッドです。
- `MillimetersToPoints(mm)`: ミリメートルをポイントに変換する(列幅を指定するときに使う)
- `PointsToMillimeters(pt)`: ポイントをミリメートルに変換する(現在の幅を確認するときに使う)
これらを使いこなすことで、あなたのコードは「人間が読める論理的な設計」へと昇華されます。
3. 実践:レイアウト崩れを許さない「完璧な表生成」コード
それでは、実際に「列幅をミリ単位で指定して、データが流し込まれても崩れない表」を作成するコードを見てみましょう。
単に幅を指定するだけでは不十分です。Wordの「自動調整機能(AutoFit)」という、良かれと思ってレイアウトを壊す「お節介機能」を封じ込める工程が不可欠です。
Sub CreateStrictLayoutTable()
Dim doc As Document
Dim tbl As Table
Dim targetWidths As Variant
Dim i As Integer
Dim totalWidthMM As Single
Dim pageWidthMM As Single
Set doc = ActiveDocument
' --- 1. 設計図の定義(ミリ単位で直感的に指定) ---
' 例:1列目は30mm、2列目は100mm、3列目は40mm
targetWidths = Array(30, 100, 40)
' ページ全体の有効幅を計算(ここでは仮にA4横向きを想定して計算する考え方)
' ※実際には doc.PageSetup を参照するのがベストです
pageWidthMM = 190 ' 余白を除いた有効幅(例)
' --- 2. 表の生成 ---
' 文末に3行3列の表を作成
Set tbl = doc.Tables.Add(Range:=doc.Content, NumRows:=3, NumColumns:=3)
With tbl
' 【重要】自動調整機能をオフにする
' これをやらないと、後から文字を入れた瞬間に幅が勝手に変わります
.AllowAutoFit = False
' 表全体のレイアウト設定を「固定」にする
.AutoFitBehavior (wdAutoFitFixed)
' --- 3. 列幅の厳密な適用 ---
For i = 1 To .Columns.Count
' 配列から設計上の幅を取得(VBAの配列は0始まりなので i-1)
' MillimetersToPoints を使い、設計図(mm)をWordの言語(pt)に翻訳する
.Columns(i).Width = MillimetersToPoints(targetWidths(i - 1))
Next i
' --- 4. データの流し込み(テスト) ---
.Cell(1, 1).Range.Text = "項目名"
.Cell(1, 2).Range.Text = "詳細説明(長いテキストが入っても崩れません)"
.Cell(1, 3).Range.Text = "備考"
.Cell(2, 1).Range.Text = "価格"
.Cell(2, 2).Range.Text = "¥1,200"
.Cell(2, 3).Range.Text = "税込"
End With
MsgBox "設計通りの表を作成しました。", vbInformation, "完了"
End Sub
コードの核心:なぜこの手順なのか?
1. `AllowAutoFit = False`:
これが最大の防波堤です。Wordは「セルの中に長い単語が入ったら、列を広げよう」と気を利かせますが、業務文書においてはそれが「レイアウト崩れ」になります。このプロパティを`False`にすることで、Wordの独断を禁止します。
2. `AutoFitBehavior (wdAutoFitFixed)`:
表の挙動を「コンテンツに合わせる」から「固定幅」へと強制的に切り替えます。
3. `MillimetersToPoints` の活用:
コードを読んだ人が「あ、この列は30mmなんだな」と即座に理解できる。これが保守性の高いコードの条件です。
4. 陥りやすい「罠」と回避策
エンジニアとして、あえて警告しておきます。以下の2点には注意してください。
罠①:セルの余白(Cell Margins)
列幅を30mmに設定しても、セルの中に「左余白 2.5mm、右余白 2.5mm」という設定があると、実際にテキストが書ける幅は25mmになります。
対策: 表全体の余白を制御したい場合は、`tbl.TopPadding` や `tbl.LeftPadding` もミリ単位(変換後)で明示的に指定しましょう。
罠②:合計幅のオーバーフロー
指定した列幅の合計が、ページの有効幅(余白を除いた幅)を超えてしまうと、Wordは強制的に列幅を縮小し、あなたの設計を無視します。
対策: `doc.PageSetup.UsableWidth`(※プロパティ名は環境により異なりますが、有効幅を取得するロジック)を計算に組み込み、合計幅がページ内に収まっているかを事前にチェックするバリデーションを実装するのが、真のアーキテクトの仕事です。
最後に:ここをクリアすれば、あなたはもう初心者ではない
「マクロの記録」で生成されるコードは、常に「その時、その瞬間の状態」を記録するだけの、断片的なものです。
しかし、今回のように「単位を意識し」「オブジェクトの挙動(AutoFit)を制御し」「設計思想を持って数値を扱う」ことができれば、あなたの書くマクロは、どんな環境でも、どんなデータが来ても、寸分違わぬ美しさを保つ「ツール」へと進化します。
一歩ずつ、確実に。
この「単位の制御」をマスターしたあなたは、もうWord VBAの荒波を乗りこなす準備ができています。
さあ、次の自動化へ向かいましょう!
