【入門編】【中級者向け】表の各行を独立したWordファイルとして分割保存するドキュメント自動生成術 – Word VBA解析バイブル

スポンサーリンク
スポンサーリンク

「マクロの記録」の先へ。巨大な表を「一行ずつ」別ファイルへ切り出す、プロのドキュメント生成術

こんにちは。業務自動化の世界へようこそ。

「マクロの記録」を使って、なんとか操作を自動化できた。そんな喜びを感じているあなたなら、次にぶつかる壁は間違いなく「もっと複雑な、条件に応じた動きをさせたい」という欲求のはずです。

例えば、こんな場面を想像してみてください。
「1つのExcelやWordにまとまった100件の見積データ。これを、1件ずつ個別のPDFやWordファイルにして、取引先に送りたい……」

これを手作業でやっていたら、日が暮れてしまいますよね。
今日は、そんな「大量のデータを、個別のドキュメントとして切り出す」という、実務において極めて価値の高いテクニックを伝授します。

単なるコードの書き方だけでなく、「なぜその書き方をするのか」という、プロが守るべき設計思想についても触れていきます。ここを理解すれば、あなたのVBAは「ただ動くもの」から「信頼されるシステム」へと進化します。

1. 設計図:何を、どう動かすのか?

いきなりコードを書くのは、地図を持たずに樹海に入るようなものです。まずは、私たちがこれから作ろうとしているプログラムの「論理的な流れ」を整理しましょう。

私たちが目指すのは、以下のプロセスです。

1. ソース(元データ)となるドキュメントを開く
2. ドキュメント内の「表(Table)」を特定する
3. 表の行を、1行ずつループ(繰り返し)で処理する
4. 各ループの中で、以下の作業を行う:

  • 新しいWordドキュメントをメモリ上に生成する
  • 「見出し行」と「現在の行」をコピーする
  • 新しいドキュメントに貼り付ける
  • 行内の特定のセル(名前やIDなど)を使ってファイル名を決める
  • 指定のフォルダに保存して、新しいドキュメントを閉じる

ここで重要なのは、「新しいドキュメントを毎回作り、使い終わったら閉じる」というサイクルです。これを忘れると、パソコンのメモリを食いつぶし、Wordがクラッシュする原因になります。

2. 実践:行分割自動生成コード

それでは、魂を込めて書いた実装コードを見ていきましょう。
このコードは、「1行目は見出し、2行目以降にデータがある表」を想定しています。

Sub SplitTableRowsToFiles()
    ' ============================================================
    ' 目的:表の各行を、見出しと共に個別のWordファイルとして保存する
    ' 設計思想:Selection(選択)ではなくRange(範囲)を操作し、高速かつ安定させる
    ' ============================================================
    
    Dim srcDoc As Document
    Dim newDoc As Document
    Dim targetTable As Table
    Dim headerRow As Range
    Dim currentRow As Range
    Dim i As Long
    Dim savePath As String
    Dim fileName As String
    Dim targetFolder As String
    
    ' --- 設定エリア ---
    ' 保存先フォルダを指定(末尾に必ず \ を入れること)
    targetFolder = "C:\Users\YourName\Desktop\Output\"
    
    ' フォルダが存在しない場合に備える(実務では重要)
    If Dir(targetFolder, vbDirectory) = "" Then
        MsgBox "保存先フォルダが見つかりません。パスを確認してください。", vbCritical
        Exit Sub
    End If
    
    ' 現在開いているドキュメントをソースとしてセット
    Set srcDoc = ActiveDocument
    
    ' 文書内の最初の表を対象とする
    If srcDoc.Tables.Count = 0 Then
        MsgBox "表が見つかりません。", vbExclamation
        Exit Sub
    End If
    Set targetTable = srcDoc.Tables(1)
    
    ' 見出し行(1行目)をRangeとして記憶しておく
    ' これにより、分割後のファイルにも必ず見出しが付くようになります
    Set headerRow = targetTable.Rows(1).Range
    
    ' 高速化のため、画面更新を停止(※WordにはExcelのような明確なScreenUpdatingがないため
    ' 処理中にウィンドウを最小化するか、Visibleを制御するのがプロの技です)
    
    ' --- メインループ ---
    ' 2行目から最終行まで繰り返す
    For i = 2 To targetTable.Rows.Count
        
        ' 1. 現在の行の範囲を取得
        Set currentRow = targetTable.Rows(i).Range
        
        ' 2. 新しいドキュメントを作成
        Set newDoc = Documents.Add
        
        ' 3. 見出し行をコピーして貼り付け
        headerRow.Copy
        newDoc.Range.Paste
        
        ' 4. 改行を入れてから、現在の行をコピーして貼り付け
        newDoc.Content.InsertAfter vbCr ' 改行を挿入
        currentRow.Copy
        newDoc.Range(newDoc.Content.End - 1).Paste
        
        ' 5. ファイル名の決定
        ' ここでは、表の1列目(Cells(1))の内容をファイル名に採用します
        ' 注意:セル内に改行や禁止文字が含まれるとエラーになるため、本来はクリーニングが必要
        fileName = targetTable.Cell(i, 1).Range.Text
        fileName = CleanFileName(fileName) ' 下記の自作関数でゴミを除去
        
        ' 6. 保存と終了
        savePath = targetFolder & fileName & ".docx"
        
        ' 同名ファイルがある場合の衝突を避けるため、エラーハンドリングを意識
        On Error Resume Next
        newDoc.SaveAs2 FileName:=savePath
        If Err.Number <> 0 Then
            MsgBox "ファイル保存に失敗しました: " & fileName & vbCrLf & "ファイル名に使用できない文字がある可能性があります。", vbCritical
            Err.Clear
        End If
        On Error GoTo 0
        
        ' 7. 新しいドキュメントを閉じる(これを忘れるとメモリ不足で死にます)
        newDoc.Close SaveChanges:=wdDoNotSaveChanges
        
    Next i
    
    MsgBox "すべての分割処理が完了しました!", vbInformation
End Sub

' ------------------------------------------------------------
' 補助関数:Wordのセル特有の制御文字を除去する
' ------------------------------------------------------------
Function CleanFileName(txt As String) As String
    Dim temp As String
    temp = txt
    ' Wordのセル末尾には、必ず「セル区切り文字」が含まれるため除去が必要
    temp = Replace(temp, Chr(13), "") ' キャリッジリターン除去
    temp = Replace(temp, Chr(7), "")  ' セル区切り文字(Bell)除去
    
    ' ファイル名に使えない禁止文字を置換(簡易版)
    Dim invalidChars As Variant
    Dim char As Variant
    invalidChars = Array("\", "/", ":", "*", "?", """", "<", ">", "|")
    For Each char In invalidChars
        temp = Replace(temp, char, "_")
    Next char
    
    CleanFileName = Trim(temp)
End Function

3. プロが教える「ここが落とし穴」

コードをコピペして動かすだけでは、あなたはまだ「マクロを使える人」です。
「マクロを使いこなす人」になるために、以下の3つのポイントを深く理解してください。

① `Selection` ではなく `Range` を使え

マクロの記録を使っていると、必ず `Selection.Copy` や `Selection.Paste` というコードが出てきます。これは「今、マウスで選択されている場所」を操作する命令です。

しかし、大量のデータを処理する際、`Selection` を使うと画面が激しく動き、処理速度も著しく低下します。プロは `Range` オブジェクト を使います。`Range` は「目に見えない範囲」を直接指定して操作するため、バックグラウンドで静かに、かつ超高速に処理を進めることができるのです。

② セル内の「見えない文字」の正体

ここが最大の難所です。Wordの表のセル内には、目に見えない `Chr(7)`(ベル文字/セル区切り文字) という特殊な文字が必ず含まれています。
これをそのままファイル名に使おうとすると、「ファイル名が不正です」というエラーでプログラムが止まります。

上記のコードでは `CleanFileName` という関数を用意しました。このように、「入力データは常に汚れているもの」という前提で、掃除(クリーニング)する処理を入れるのが、堅牢なプログラムを作る鉄則です。

③ オブジェクトのライフサイクル管理

ループの中で `Documents.Add` を実行したら、必ず `newDoc.Close` で閉じてください。
これを怠ると、ループの回数分だけWordのドキュメントがメモリ上に「幽霊」のように残り続け、最終的にあなたのパソコンの動作を重くし、最悪の場合は強制終了させます。「作ったものは、使い終わったら片付ける」。これはプログラミングにおける最も基本的なマナーです。

最後に

いかがでしたか?
最初は難しく感じるかもしれませんが、この「ループの中で新しいオブジェクトを作り、操作して、閉じる」という構造は、Word VBAだけでなく、あらゆる自動化技術に通じる共通のパターンです。

一歩ずつ、このパターンを自分のものにしていってください。
あなたが書いたコードが、誰かの膨大な作業時間を数秒に短縮したとき、あなたはエンジニアとしての真の喜びを知ることになるでしょう。

応援していますよ。次はもっと複雑な、条件分岐を組み合わせた自動化に挑戦してみましょう!

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