こんにちは! Word VBAの世界へようこそ。
マクロの記録ボタンを押すだけの「初心者」を卒業し、自分の手でドキュメントを自在に操る「エンジニア」へとステップアップする素晴らしいタイミングですね。
今回は、実務で本当によく遭遇する「巨大な表の中から、特定の条件を満たす行だけを抜き出して、別の新しい表として綺麗にまとめる(フィルタリング抽出)」というテーマを深掘りします。
Excel VBAなら「オートフィルタ」一発ですが、Wordの表(Table)構造は、実はExcelとは少し勝手が違います。セルの結合があったり、段落の概念が絡んできたりと、適当にコードを書くと「謎のruntimeエラー」や「消えたデータ」に泣かされることになります。
でも、安心してください。オブジェクトのライフサイクルとWord特有の癖さえ掴めば、驚くほどスッキリとしたスマートなコードが書けるようになります。
ここをクリアすれば、あなたのWord VBAスキルは間違いなく中級者の域に達しますよ。さあ、一緒に極限の知見を紐解いていきましょう!
—
1. なぜWordの表操作はつまずきやすいのか?
まず、Word VBAの心構えからお話しします。
Excelのシートは「格子状のセル」が綺麗に並んでいますが、Wordの表(`Table`オブジェクト)の本質は「段落(Paragraph)の入れ物」です。
1つのセルの中には複数の段落が存在でき、セル自体の削除や行の挿入を行うたびに、Word内部のインデックス番号が目まぐるしく変化します。
特に、「ループを回しながら行を削除する・コピーする」という処理を素人がやると、必ずと言っていいほど「インデックスが範囲外です」というエラーか、データの取りこぼしが発生します。
これを回避するための鉄則が、今回紹介する「逆順ループ(下から上への走査)」です。
—
2. 実装イメージとアルゴリズム
今回は、次のようなシナリオを想定します。
- 元表(Source Table):ドキュメント内にある、様々なステータスが混ざった一覧表。
- 条件:2列目のテキストが「要確認」または「対応中」であること。
- 処理:条件に合致した行をごっそりコピーし、文書の末尾に「新しい表(Destination Table)」として生成する。
[ 元の表 ] [ 抽出後の新しい表 ]
+——-+———–+ +——-+———–+
| 項目A | 完了 | | 項目B | 要確認 | <- 抽出された!
+-------+-----------+ ⇒ +-------+-----------+
| 項目B | 要確認 | (抽出) | 項目D | 対応中 | <- 抽出された!
+-------+-----------+ +-------+-----------+
| 項目C | 完了 |
+-------+-----------+
| 項目D | 対応中 |
+-------+-----------+
---
3. 実用VBAコード:条件抽出&新規テーブル生成
それでは、開発の現場でそのままコピペして使える実用コードを公開します。
コード内のコメントをしっかりと読みながら、動きをイメージしてください。
Sub FilterAndCreateNewTable()
Dim doc As Document
Set doc = ActiveDocument
Dim srcTable As Table
‘ 文書内に表が存在するかチェック
If doc.Tables.Count = 0 Then
MsgBox “文書内に表が見つかりません。”, vbExclamation
Exit Sub
End If
‘ ここではデモとして「文書内の最初の表」を元表とします
Set srcTable = doc.Tables(1)
‘ —————————————————-
‘ 1. 新しい表の骨組みを作る(ヘッダー行の複製)
‘ —————————————————-
Dim destTable As Table
Dim targetRange As Range
‘ 文書の一番最後に新しい表を作成(行数:1行、列数:元表と同じ)
Set targetRange = doc.Content
targetRange.Collapse wdCollapseEnd
targetRange.InsertParagraphAfter ‘ 改行を挟んで表を追加
‘ 新規テーブル生成(ヘッダー分の1行だけ先につくる)
Set destTable = doc.Tables.Add(Range:=doc.Content.Paragraphs(doc.Content.Paragraphs.Count).Range, _
NumRows:=1, NumColumns:=srcTable.Columns.Count)
‘ 表のデザインを元表と同じにする(お好みで)
destTable.Style = srcTable.Style
‘ ヘッダー行をコピーして新規テーブルの1行目にペースト
Dim colIdx As Integer
For colIdx = 1 To srcTable.Columns.Count
‘ セルの文字列を綺麗にコピー(末尾の改行コードを除去するためRange.Textを調整)
destTable.Cell(1, colIdx).Range.Text = CleanCellText(srcTable.Cell(1, colIdx).Range)
Next colIdx
‘ —————————————————-
‘ 2. 条件に合致する行を抽出して転記する
‘ —————————————————-
Dim r As Long
Dim cellText As String
Dim newRow As Row
‘ 【重要】データ行の判定は「下から上へ(逆順)」ループする!
‘ 上から順に回すと、行の追加・削除時にインデックスが狂うため。
For r = srcTable.Rows.Count To 2 Step -1
‘ 例として「2列目」のテキストを条件判定の対象にする
cellText = CleanCellText(srcTable.Cell(r, 2).Range)
‘ 条件:「要確認」または「対応中」が含まれている場合
If InStr(cellText, “要確認”) > 0 Or InStr(cellText, “対応中”) > 0 Then
‘ 新規テーブルに新しい行を追加
Set newRow = destTable.Rows.Add
‘ 該当行の全セルの内容を新しい行にコピー
For colIdx = 1 To srcTable.Columns.Count
destTable.Cell(destTable.Rows.Count, colIdx).Range.Text = CleanCellText(srcTable.Cell(r, colIdx).Range)
Next colIdx
End If
Next r
‘ 完了メッセージ
MsgBox “フィルタリング処理が完了しました!新規テーブルを確認してください。”, vbInformation
End Sub
‘ —————————————————————–
‘ 補助関数:Wordのセル末尾にある特殊文字(セル終端文字)を除去する
‘ —————————————————————–
Function CleanCellText(cellRange As Range) As String
Dim txt As String
txt = cellRange.Text
‘ Wordのセル範囲を取得すると、末尾に必ず Chr(13) & Chr(7) が含まれるため削除
If Len(txt) >= 2 Then
txt = Left(txt, Len(txt) – 2)
End If
CleanCellText = Trim(txt)
End Function
—
4. コードの深掘りポイント(ここが分かればプロ級!)
① なぜ「下から上へ(`To 2 Step -1`)」回すのか?
先ほども触れましたが、Word VBAにおいて上から順(`1 To srcTable.Rows.Count`)にループを回すと、処理の途中で表の構造をいじった瞬間にインデックスのズレが生じ、行のスキップや予期せぬクラッシュを引き起こします。
「データを走査するだけの読み取り用ループ」なら上からでも良いですが、「構造を変更する処理」を伴う場合は、必ず下から上へ逆順で回す。これはWordマクロ開発の鉄則中の鉄則です。
② Wordセルの「見えない罠」:`Chr(13) & Chr(7)`
Excelのセルと違い、Wordのセルテキスト(`.Range.Text`)を取得すると、文字列の最後に必ずセル終端マーク(改行コード+ベル文字)がくっついてきます。
これをそのまま新しいセルに代入すると、表の中に変な改行がどんどん溜まっていき、レイアウトが崩壊します。
上記のコードで用意した補助関数 `CleanCellText` は、この余分な末尾2文字を綺麗に削ぎ落とすためのエンジニアの知恵(ライフハック)です。これがあるだけで、データのクレンジング精度が劇的に上がります。
—
5. まとめ
今回は、Word VBAを使った「条件付き行抽出と新規テーブル生成」のテクニックを解説しました。
- Wordの表は「段落の入れ物」であるという構造を意識する
- 構造を変更するループは、必ず「逆順(下から上)」で回す
- セルの文字列取得時は、末尾の特殊文字(`Chr(13) & Chr(7)`)を必ず除去する
この3つをマスターすれば、もうマクロの記録の限界に悩むことはありません。実務における膨大なドキュメント整理やレポート自動生成を、一瞬で終わらせる強力な武器を手に入れたことになります。
ここをクリアしたあなたなら、もうWord VBAの基本はバッチリです!
ぜひ自分の環境でコードを動かして、その爽快感を味わってみてくださいね。次回の応用編もお楽しみに!
