【入門編】【中級者向け】段落の「アウトラインレベル」を元に、文書の階層構造をツリー形式で抽出する – Word VBA解析バイブル

スポンサーリンク

Word VBAで文書構造を「見える化」!段落のアウトラインレベルをツリー形式で抽出する極意

Word文書を作成していると、あっという間に長文になって、どこに何があるのか分からなく…なんて経験、ありませんか?🤔

特に、会議の議事録や、レポート、マニュアルなど、階層構造がしっかりしている文書ほど、その構造を把握することが重要になってきます。

そこで今回は、Word VBAの「段落のアウトラインレベル」という機能を使って、文書の階層構造をツリー形式で抽出し、文書の構成を分かりやすく「見える化」する方法を、中級者向けに徹底解説します!

「マクロの記録」だけでは物足りない!と感じているあなたへ。この記事を読み終える頃には、Word VBAの基本をしっかり理解し、さらに応用的な処理にも自信が持てるようになっているはずですよ。さあ、一緒にWord VBAの世界を深掘りしていきましょう!🚀

なぜ「アウトラインレベル」が重要なのか?

Wordで文書を作成する際、見出しに「見出し1」「見出し2」といったスタイルを適用すると、自動的にアウトラインレベルが設定されます。このアウトラインレベルこそが、文書の階層構造を司るカギなんです!

例えば、

  • 見出し1: レベル 1
  • 見出し2: レベル 2
  • 見出し3: レベル 3

のように、レベルが上がるほど上位の階層、レベルが下がるほど下位の階層、という関係性が生まれます。

このアウトラインレベルをVBAで取得できるようになれば、文書全体の構造をプログラムで理解し、それを元に様々な処理を行うことが可能になります。例えば、

  • 目次を自動生成する: レベルに応じたインデントを付けて、見やすい目次を作成。
  • 章ごとにファイルを分割する: 特定のアウトラインレベルの見出しで文書を区切り、別ファイルに保存。
  • 文書構造を分析する: 階層の深さや、各レベルの項目数を集計。

など、アイデア次第で可能性は無限大!✨

今回は、このアウトラインレベルを抽出し、文書の構成をツリー形式で別シートに書き出すという、具体的な活用例を通して学んでいきましょう。

準備:Word VBAの基本を再確認

さて、いよいよコードを書いていきますが、その前にWord VBAの基本的な考え方を軽くおさらいしておきましょう。

Word VBAでは、Wordアプリケーションそのもの、開いている文書、そして文書内の要素(段落、文字、表など)が、それぞれオブジェクトとして扱われます。

  • `Application`: Wordアプリケーション全体を表します。
  • `Document`: 現在開いているWord文書を表します。
  • `Paragraphs`: 文書内のすべての段落の集まりを表します。
  • `Paragraph`: 個々の段落を表します。

これらのオブジェクトを階層的にたどっていくことで、文書内の様々な情報にアクセスし、操作することができます。

今回、私たちが注目するのは、個々の段落を表す `Paragraph` オブジェクト です。

コードを書いてみよう!:段落のアウトラインレベルを抽出する

では、早速コードを書いていきましょう。以下のコードは、現在アクティブな文書の各段落のアウトラインレベルを取得し、その結果を新しいシートに書き出すものです。

Sub ExtractOutlineLevel()

Dim doc As Document
Dim para As Paragraph
Dim wsOutput As Worksheet
Dim rowIndex As Long

‘— 初期設定 —
‘ 現在アクティブな文書を取得
Set doc = ActiveDocument
‘ 出力用の新しいシートを追加
On Error Resume Next ‘ シートが既に存在する場合のエラーを無視
Set wsOutput = ThisWorkbook.Sheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
On Error GoTo 0 ‘ エラーハンドリングを元に戻す
wsOutput.Name = “文書構造レポート” ‘ シート名を変更

‘ ヘッダー行を設定
wsOutput.Cells(1, 1).Value = “行番号”
wsOutput.Cells(1, 2).Value = “アウトラインレベル”
wsOutput.Cells(1, 3).Value = “段落テキスト”
wsOutput.Range(wsOutput.Cells(1, 1), wsOutput.Cells(1, 3)).Font.Bold = True ‘ ヘッダーを太字に

rowIndex = 2 ‘ データ書き込み開始行

‘— 段落のループ処理 —
‘ 文書内の各段落をループで処理
For Each para In doc.Paragraphs
‘ 段落のアウトラインレベルを取得
‘ wdOutlineLevel1 ~ wdOutlineLevel9 の定数で表される
‘ レベルが設定されていない場合は 0 になる
Dim outlineLevel As WdOutlineLevel
outlineLevel = para.OutlineLevel

‘ テキストを取得(改行コードは削除)
Dim paraText As String
paraText = Trim(para.Range.Text) ‘ 前後の空白や改行を削除
paraText = Replace(paraText, vbCrLf, ” “) ‘ 改行コードをスペースに置換
paraText = Replace(paraText, vbCr, ” “) ‘ 改行コードをスペースに置換
paraText = Replace(paraText, vbLf, ” “) ‘ 改行コードをスペースに置換

‘ アウトラインレベルが設定されている(0以外)場合のみ書き出す
If outlineLevel > 0 Then
‘ 新しいシートに行番号、アウトラインレベル、段落テキストを書き込む
wsOutput.Cells(rowIndex, 1).Value = rowIndex – 1 ‘ 元の文書の行数的なイメージ
wsOutput.Cells(rowIndex, 2).Value = outlineLevel
wsOutput.Cells(rowIndex, 3).Value = paraText
rowIndex = rowIndex + 1 ‘ 次の行へ
End If
Next para

‘— 書式設定 —
‘ 列幅を自動調整
wsOutput.Columns(“A:C”).AutoFit

‘ 完了メッセージ
MsgBox “文書構造レポートを作成しました。”, vbInformation

End Sub

コードの解説(ここが重要!)

このコードを一行ずつ、その意味と狙いを丁寧に解説していきますね。

1. `Dim doc As Document`: `doc`という名前で、Wordの文書オブジェクトを格納するための変数を宣言しています。
2. `Dim para As Paragraph`: `para`という名前で、文書内の個々の段落オブジェクトを格納するための変数を宣言しています。
3. `Dim wsOutput As Worksheet`: `wsOutput`という名前で、レポートを出力するExcelシートオブジェクトを格納するための変数を宣言しています。
4. `Dim rowIndex As Long`: `rowIndex`という名前で、シートへの書き込み行を管理するための数値を格納する変数を宣言しています。`Long`型は大きな整数も扱えるので、長文でも安心です。
5. `Set doc = ActiveDocument`: 現在開いている、アクティブなWord文書を`doc`変数に代入しています。
6. `On Error Resume Next` 〜 `On Error GoTo 0`: この部分は、もし「文書構造レポート」という名前のシートが既に存在していた場合に、エラーでマクロが停止してしまうのを防ぐための「エラーハンドリング」というテクニックです。

  • `On Error Resume Next`: エラーが発生しても、次の行のコードを実行し続けます。
  • `Set wsOutput = ThisWorkbook.Sheets.Add(…)`: 新しいシートを追加し、それを`wsOutput`変数に代入しようとします。もし同名のシートがあれば、ここではエラーが発生しますが、`On Error Resume Next`のおかげでマクロは止まりません。
  • `On Error GoTo 0`: エラーハンドリングを通常の状態に戻します。

7. `wsOutput.Name = “文書構造レポート”`: 新しく追加されたシート、または既存のシートの名前を「文書構造レポート」に変更しています。
8. ヘッダー行の設定:

  • `wsOutput.Cells(1, 1).Value = “行番号”`: 1行目の1列目(A1セル)に「行番号」と入力します。
  • 同様に、B1セルに「アウトラインレベル」、C1セルに「段落テキスト」と入力します。
  • `wsOutput.Range(wsOutput.Cells(1, 1), wsOutput.Cells(1, 3)).Font.Bold = True`: A1からC1までの範囲を太字に設定し、ヘッダーであることが分かりやすいようにしています。

9. `rowIndex = 2`: データは2行目から書き始めるので、`rowIndex`を2に初期化します。
10. `For Each para In doc.Paragraphs`: ここからが、文書内の各段落を順番に処理するメインループです。`doc.Paragraphs`は、文書内のすべての段落の集まりを表し、`For Each`文はその集まりの各要素(ここでは`para`という段落オブジェクト)に対して、中の処理を繰り返します。
11. `Dim outlineLevel As WdOutlineLevel`: 段落のアウトラインレベルを格納するための変数を宣言しています。`WdOutlineLevel`は、Word VBAで定義されている、アウトラインレベルを表す列挙型(定数の集まり)です。
12. `outlineLevel = para.OutlineLevel`: 現在処理している段落 (`para`) のアウトラインレベルを取得し、`outlineLevel`変数に代入しています。

  • ここが超重要ポイント! `para.OutlineLevel`は、`wdOutlineLevel1`(レベル1)から`wdOutlineLevel9`(レベル9)までの定数、またはレベルが設定されていない場合は`0`を返します。

13. 段落テキストの取得と整形:

  • `paraText = Trim(para.Range.Text)`: 段落の実際のテキストを取得します。`para.Range.Text`は、段落の末尾に改行コードが含まれることがあるため、`Trim`関数で前後の不要な空白や改行を削除しています。
  • `paraText = Replace(…)`: 段落テキストに含まれる可能性のある改行コード (`vbCrLf`, `vbCr`, `vbLf`) をスペースに置換しています。これは、シートに書き出す際に、改行が入ると見づらくなるためです。

14. `If outlineLevel > 0 Then`: 段落にアウトラインレベルが設定されている(つまり、見出しスタイルなどが適用されている)場合のみ、以下の処理を実行します。レベル0(通常の段落)はスキップします。
15. データ書き込み:

  • `wsOutput.Cells(rowIndex, 1).Value = rowIndex – 1`: 行番号として、現在の`rowIndex`から1を引いた値を書き込みます。これは、ヘッダー行を除いた、文書内の段落の順番のようなイメージです。
  • `wsOutput.Cells(rowIndex, 2).Value = outlineLevel`: 取得したアウトラインレベルを書き込みます。
  • `wsOutput.Cells(rowIndex, 3).Value = paraText`: 整形した段落テキストを書き込みます。
  • `rowIndex = rowIndex + 1`: 次のデータ行のために、`rowIndex`を1増やします。

16. `Next para`: `For Each`ループの次の段落の処理に移ります。
17. `wsOutput.Columns(“A:C”).AutoFit`: A列からC列までの幅を、表示されている内容に合わせて自動調整します。これで、テキストがはみ出ることなく綺麗に表示されます。
18. `MsgBox “文書構造レポートを作成しました。”, vbInformation`: 処理が完了したことをユーザーに知らせるメッセージボックスを表示します。

実行方法

1. Wordを開き、マクロを記述したい文書を開きます。
2. `Alt` + `F11` キーを押して、VBAエディターを開きます。
3. メニューバーの「挿入」→「標準モジュール」を選択します。
4. 表示されたコードウィンドウに、上記のVBAコードをコピー&ペーストします。
5. VBAエディターの実行ボタン(緑色の三角形)をクリックするか、Wordに戻って `Alt` + `F8` キーでマクロダイアログを開き、「ExtractOutlineLevel」を選択して「実行」ボタンをクリックします。

すると、新しいシート「文書構造レポート」に、文書の階層構造がアウトラインレベルと共にリストアップされているはずです!

陥りやすいエラーとその対策

  • エラー:「オブジェクトが必要です」
  • 原因: `ActiveDocument`が参照できていない(Word文書が開かれていない、またはVBAエディターから直接実行しようとしている)。
  • 対策: 必ずWord文書を開いた状態で、そのWord文書からマクロを実行してください。
  • エラー:「’Sub’または’Function’が定義されていません」
  • 原因: コードのコピペミス、またはプロシージャ(Sub)が正しく定義されていない。
  • 対策: コード全体を正確にコピー&ペーストし、`Sub ExtractOutlineLevel()`と`End Sub`で囲まれているか確認してください。
  • 意図しない段落が抽出される
  • 原因: 段落の定義は、改行コード(Enterキー)で区切られたものです。空行も1つの段落として扱われます。また、図表のキャプションなども段落として認識されます。
  • 対策: コード内で `If outlineLevel > 0 Then` とすることで、見出しレベルが設定されているものだけを抽出するようにしていますが、もし「見出しではないが、特定のレベルで抽出したい」という場合は、`paraText`の内容でさらにフィルタリングする条件を追加する必要があります。例えば、`If outlineLevel = 2 And Left(paraText, 3) = “要約” Then` のように。
  • アウトラインレベルが正しく取得できない
  • 原因: 段落に「見出し1」などのスタイルが適用されているように見えても、実際にはアウトラインレベルが設定されていない場合があります。これは、スタイルをカスタマイズした際などに起こることがあります。
  • 対策: VBAエディターで `para.OutlineLevel` の部分にカーソルを置き、F1キーを押してヘルプを確認したり、デバッグ機能(F8キーで一行ずつ実行)を使って、実際にどのような値が返ってきているかを確認することが重要です。

さらに活用!ツリー形式で表示するには?

ここまでで、文書の階層構造をリスト形式で抽出できるようになりました。さらに、これを「ツリー形式」で表示すると、より直感的に文書の構造を把握できるようになります。

ツリー形式で表示するには、抽出したアウトラインレベルに応じて、インデント(字下げ)を付けて表示します。

以下のコードは、先ほどのコードを少し変更し、ツリー形式で表示するためのコードです。

Sub ExtractOutlineLevelAsTree()

Dim doc As Document
Dim para As Paragraph
Dim wsOutput As Worksheet
Dim rowIndex As Long
Dim previousLevel As WdOutlineLevel ‘ 前の段落のアウトラインレベルを保持する変数

‘— 初期設定 —
Set doc = ActiveDocument
On Error Resume Next
Set wsOutput = ThisWorkbook.Sheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
On Error GoTo 0
wsOutput.Name = “文書構造ツリーレポート”

‘ ヘッダー行を設定
wsOutput.Cells(1, 1).Value = “階層”
wsOutput.Cells(1, 2).Value = “段落テキスト”
wsOutput.Range(wsOutput.Cells(1, 1), wsOutput.Cells(1, 2)).Font.Bold = True

rowIndex = 2
previousLevel = 0 ‘ 初期化

‘— 段落のループ処理 —
For Each para In doc.Paragraphs
Dim outlineLevel As WdOutlineLevel
outlineLevel = para.OutlineLevel

Dim paraText As String
paraText = Trim(para.Range.Text)
paraText = Replace(paraText, vbCrLf, ” “)
paraText = Replace(paraText, vbCr, ” “)
paraText = Replace(paraText, vbLf, ” “)

‘ アウトラインレベルが設定されている(0以外)場合のみ処理
If outlineLevel > 0 Then
‘ ツリー表示のためのインデントを計算
Dim indentString As String
‘ レベルに応じてスペースを追加
‘ 例: レベル1ならスペースなし、レベル2ならスペース2つ、レベル3ならスペース4つ…
indentString = String( (outlineLevel – 1) 2, ” “) ‘ レベル1は0個、レベル2は2個、レベル3は4個のスペース

‘ 新しいシートにインデント付きテキストを書き込む
wsOutput.Cells(rowIndex, 1).Value = indentString ‘ 階層(インデント)
wsOutput.Cells(rowIndex, 2).Value = paraText ‘ 段落テキスト
rowIndex = rowIndex + 1

‘ 次のループのために現在のレベルを保存
previousLevel = outlineLevel
End If
Next para

‘— 書式設定 —
wsOutput.Columns(“B”).AutoFit ‘ 段落テキスト列の幅を自動調整

MsgBox “文書構造ツリーレポートを作成しました。”, vbInformation

End Sub

ツリー表示コードのポイント

  • `previousLevel` 変数: 前の段落のアウトラインレベルを保持するために使用します。今回は直接は使いませんが、より複雑なツリー表示(例えば、子要素がない場合に「├──」などの記号を付ける場合)には必要になります。
  • `indentString = String( (outlineLevel – 1) 2, ” “)`: ここがツリー表示の肝です!
  • `outlineLevel – 1`: レベル1を基準(インデント0)にするため、レベルから1を引きます。
  • ` 2`: 各レベルの深さに対して、2つのスペースをインデントとして追加します。これにより、視覚的に階層が深くなるほど、右にずれて表示されます。
  • `wsOutput.Cells(rowIndex, 1).Value = indentString`: 計算されたインデント文字列を1列目に書き込みます。
  • `wsOutput.Cells(rowIndex, 2).Value = paraText`: 段落テキストは2列目に書き込みます。

このコードを実行すると、各段落の前に、そのアウトラインレベルに応じたスペースが追加され、まるでツリーのように階層構造が表現されます。

まとめ:Word VBAで文書作成をよりスマートに!

いかがでしたか?

今回は、Word VBAを使って段落のアウトラインレベルを抽出し、文書の構造を「見える化」する方法を解説しました。

  • `Paragraph.OutlineLevel` プロパティで、段落の階層情報を取得できること。
  • 取得した情報を元に、新しいシートにリスト形式やツリー形式で出力できること。

これらの知識とテクニックをマスターすれば、長文ドキュメントの作成や編集が格段に効率的になります。

「マクロの記録」から一歩踏み出し、VBAのオブジェクトモデルを理解することで、Word VBAの可能性は大きく広がります。今回学んだことを基に、ぜひ色々な応用を試してみてください。

「ここをクリアすれば、Word VBAの基本はバッチリですよ!」

このブログが、あなたのWord VBAスキルアップの一助となれば幸いです。また次の記事でお会いしましょう!👋

タイトルとURLをコピーしました