第7回 ループ処理に書き換える
前回
までで、ついに
データ(笑)を差し込んだ新規文書をちょっと手入れして名前を付けて保存する
という核心部分の処理が出来上がりました。
今回は、この処理をループ処理に書き換えます。
目次
ループ回数の上限を求める
ここまで使ってきたコードでは、差し込み印刷用文書(sample.docm
)に差し込むデータ(笑)は、
mds.ActiveRecord = 1
mds.FirstRecord = 1
mds.LastRecord = 1
このように、全部「1
」。〝決め打ち〟でした。
しかしながら、差し込み印刷というものは、自動で全レコードを順に差し込んでくれるからありがたいのであって、手動で一つ一つレコードを指定しなくてはいけないのでは、オートフィーダーのあるコピー機で原稿を一枚一枚ガラスの上にセットするようなものです。
それではタンザニアのイカンガーでしょう。
そこで、For ... Next
ループを使います。
ループの始点は`1
`で良いとして、終点はどうするか。
答えは簡単です。差し込みデータ(笑)の件数にすれば良いですね。
そして、このおじさんが知っている差し込みデータ用のテーブル、すなわち文書に接続されているテーブルが
MailMergeDataSource
オブジェクトです。
MailMergeDataSource
オブジェクトはおじさん、すなわちMailMerge
オブジェクトにぶら下がっているオブジェクトです。
MailMergeDataSource
オブジェクトは、MailMerge
オブジェクトのDataSource
プロパティを叩くことで取得することができます。
こう述べたように、差し込み印刷用文書(sample.docm
)に接続されているソースデータを表すMailMergeDataSource
オブジェクトは、文書本体を表すDocument
オブジェクトにぶら下がっているMailMerge
オブジェクトにぶら下がっていますので、
Dim doc As Document
Set doc = ThisDocument
Dim mm As MailMerge
Set mm = doc.MailMerge
mm.Destination = wdSendToNewDocument
mm.SuppressBlankLines = True
Dim mds As MailMergeDataSource
Set mds = mm.DataSource
このように、MailMerge
オブジェクトのDataSource
プロパティを叩いてやれば取得することができます。
このMailMergeDataSource
オブジェクトが何件のレコードを持っているのか調べるには、コチラにあるように、RecordCount
プロパティを叩きます。
したがって、変数mds
にMailMergeDataSource
オブジェクトが格納されているとすると、
Dim recCnt As Long
recCnt = mds.RecordCount
としてやれば、変数recCnt
にレコード件数を突っ込むことができます。
これであとは、
Dim i As Long
For i = 1 To recCnt
Next
というブロック内に、データ(笑)を差し込んで新規文書を整えて名前を付けて保存する処理を入れ込むだけです。
Forブロックに処理を入れ込む
では、前回までのコードをFor ... Next
に入れ込みます。
リスト1
Public Sub ExportMailMergeDocuments()
' Documentオブジェクト取得
Dim doc As Document
Set doc = ThisDocument
' MailMergeオブジェクト取得
Dim mm As MailMerge
Set mm = doc.MailMerge
' MailMergeオブジェクトの初期設定
mm.Destination = wdSendToNewDocument
mm.SuppressBlankLines = True
' MailMergeDataSourceオブジェクト取得
Dim mds As MailMergeDataSource
Set mds = mm.DataSource
' レコード数取得
Dim recCnt As Long
recCnt = mds.RecordCount
' Forループで差し込み→ファイル作成
Dim i As Long
For i = 1 To recCnt
' 差し込むレコードと始点・終点をセット
mds.ActiveRecord = i
mds.FirstRecord = i
mds.LastRecord = i
' You 差し込みやっちゃいなよ
Call mm.Execute( _
Pause:=True _
)
' 生み出された新規文書を即取得
Dim newDoc As Document
Set newDoc = Application.ActiveDocument
' 文書末尾の余分なセクション区切りをポア
Dim lastSection As Section
Set lastSection = newDoc.Sections(newDoc.Sections.Count)
If lastSection.Range.Start = newDoc.Content.End - 1 Then
Call lastSection.Range.Previous(Unit:=wdCharacter, Count:=1).Delete
End If
' 今となっては不要の先頭ページもポア
' (狡兎死して走狗烹らる)
Call newDoc.Range(0, 0).Select
Dim firstPageRng As Range
Set firstPageRng = newDoc.Bookmarks.Item("\Page").Range
Call firstPageRng.Delete
' 保存用のファイルパスを組み立てる
Dim dirPath As String
dirPath = ThisDocument.Path & "\★作成した文書\"
Dim tgtFilename As String
tgtFilename = "諸葛亮曰く" & "_" & Format(mds.DataFields.Item("ID"), "00") & ".docx"
' You、保存、やっちゃいなよ
Call newDoc.SaveAs2( _
FileName:=dirPath & tgtFilename _
)
' 保存した文書を閉じる
Call newDoc.Close( _
SaveChanges:=False _
)
Next
End Sub
処理の段階ごとにコメントを付けておきました。
エラー対応などは一切ない骨組みだけのコードですが、必要な機能は揃っています。
動作確認
実行前の保存用フォルダは
この状態です。
データソースであるExcelのワークシートが接続されている状態ならば、リスト1のマクロを実行してやると、
このように、レコード数分のWordドキュメントが出来上がりました。
中身もばっちりです。
おわりに
ここまで、どうだったでしょうか。
しくみをしっかり理解することができれば、いろいろと応用もできるでしょう。
私は、前職時代、これを応用して差し込みレコードごとにPDFドキュメントを作成する、といったマクロを作成したりしていました。
まあ、わざわざ差し込み印刷機能なんか使わなくても、かんたんなデータ差し込みなら
こんなふうに、Wordの〝ブックマーク〟機能を使っても良いのですが。
これはこれでWordのマクロ上でExcelのオブジェクトを取得・操作する必要があって、めんどくさいかもしれませんね。
次回からは仕上げの作業に移ります。