わーぷろおじさん

WordやOffice関連の小細工の備忘録。

【word vba】差し込み印刷をマクロで制御(備忘録)

基本操作

Sub testMMDS()
    Dim mmds As MailMergeDataSource
    Set mmds = ActiveDocument.MailMerge.DataSource
    
    Debug.Print mmds.ConnectString
    Debug.Print mmds.QueryString
    Debug.Print mmds.TableName
    Debug.Print mmds.Name
    
    Dim i As Long
    For i = 1 To mmds.RecordCount
        mmds.ActiveRecord = i
        Debug.Print mmds.ActiveRecord
        
        Dim mmdf As MailMergeDataField
        For Each mmdf In mmds.DataFields
            Debug.Print mmdf.Name & ":" & mmdf.Value
        Next
    Next
    mmds.ActiveRecord = wdFirstRecord
    ActiveDocument.MailMerge.ViewMailMergeFieldCodes = True
End Sub

※TableNameとNameは読み取り専用。

フィルター操作

テーブル名はエクセルワークシートを想定

参照設定:Microsoft VBScript Regular Expressions

Public Sub filterMMDS()
    On Error GoTo ErrorHandler
    Dim mmds As Word.MailMergeDataSource
    Set mmds = ActiveDocument.MailMerge.DataSource
    
    Dim re As RegExp
    Set re = New RegExp
    re.Pattern = "SELECT \* FROM `[^$]*\$[^`]*`"
    
    Dim mc As MatchCollection
    Set mc = re.Execute(mmds.QueryString)
    
    Dim BaseQuery As String
    BaseQuery = mc(0)
    
    Dim tmp As Variant
    tmp = Split(InputBox("nameとageをカンマ区切りで入力"), ",")
    
    Dim myName As String
    Dim myAge As Long
    myName = "'" & tmp(0) & "'"
    myAge = tmp(1)
    
    mmds.QueryString = BaseQuery & " WHERE name=" & myName & " AND age=" & myAge
    MsgBox "抽出件数は" & mmds.RecordCount & "件です。"
    Exit Sub

ErrorHandler:
    mmds.QueryString = BaseQuery
    MsgBox "抽出条件をクリアしました"
End Sub

※数値データをシングルクォテーションで囲ってもVBA上は動作するが、QueryStringにシングルクォテーションを残したまま保存すると、次回起動時にデータ参照エラーが出てしまうので、文字列データだけをシングルクォテーションで囲う。

※QueryStringのフィールド名はwordの仕様上バッククォートで囲うようだが、囲わなくてもOK。ファイル再起動時も影響なし(バージョンによるかも)

※使用できるSQL構文は、AND/OR、=/<>/</>/<=/>=、WHERE、ORDER BY、ASC/DESC

イベントハンドラ

差し込み印刷でファイルに出力したときに、出力先のdocumentオブジェクトを捕捉する例。

Documentモジュールに記載

Option Explicit
Private WithEvents WordApp As Word.Application
 
Private Sub Document_Open()
    Set WordApp = Word.Application
End Sub
 
Public Sub testMailMerge()
    Dim mm As MailMerge
    Set mm = ActiveDocument.MailMerge
    mm.Destination = wdSendToNewDocument
    mm.Execute 'イベント発生
End Sub
 
Private Sub WordApp_MailMergeAfterMerge(ByVal Doc As Document, ByVal DocResult As Document)
    Debug.Print DocResult.Name
End Sub

※クラスモジュールでの実装も可

※Document_Open以外でも任意のタイミングでWord.Applicationを捕捉すればよい

※testMailMergeで差し込み印刷を実行しているが、マクロからの実行でもリボンからの操作での実行でもイベントは捉えられる。

レコードごとに個別ファイル(docx, pdf)で保存

DocumentモジュールかClassモジュールに記載

Option Explicit
Private WithEvents WordApp As Word.Application
 
Public Sub SaveEachRecord()
    Set WordApp = Word.Application
 
    Dim mm As MailMerge
    Set mm = ActiveDocument.MailMerge
    mm.Destination = wdSendToNewDocument
 
    Dim mmds As MailMergeDataSource
    Set mmds = mm.DataSource
 
    Dim i As Long
    For i = 1 To mmds.RecordCount
        With mmds
            .ActiveRecord = i
            .FirstRecord = i
            .LastRecord = i
        End With
        mm.Execute 'イベント発生
    Next
 
    With mmds
        .ActiveRecord = wdDefaultFirstRecord
        .FirstRecord = wdDefaultFirstRecord
        .LastRecord = wdDefaultLastRecord
    End With
End Sub
 
Private Sub WordApp_MailMergeAfterMerge(ByVal Doc As Document, ByVal DocResult As Document)
    Dim mmds As MailMergeDataSource
    Set mmds = Doc.MailMerge.DataSource
 
    Dim OutputFile As String
    OutputFile = Doc.Path & "\" & Format(mmds.ActiveRecord, "00_") & mmds.DataFields("hogehoge").Value
 
    With DocResult
        .SaveAs2 FileName:=OutputFile & ".docx"
        .ExportAsFixedFormat OutputFileName:=OutputFile & ".pdf", ExportFormat:=wdExportFormatPDF
        .Close SaveChanges:=False
    End With
End Sub