一覧の1件ずつをテンプレートに差し込んで連続印刷する(印刷前の確認つき)
顧客一覧などの1行ずつを帳票テンプレートのシートに差し込み、連続で印刷するマクロです。最初の1件をプレビューで確認する流れ、印刷対象の絞り込み、印刷済みの記録など、紙の無駄を防ぐ工夫も解説します。
どんな場面で使うか
顧客ごとの案内状、社員ごとの支給明細、取引先ごとの納品書など、「同じ書式に宛先や金額だけを差し替えて印刷する」作業は多くの職場にあります。一覧の値を1件ずつ手でコピーして印刷していると、件数が多いほど時間がかかり、差し替え漏れによる誤送付の原因にもなります。
テンプレートのシートを1枚用意し、マクロで一覧の値を差し込みながら印刷すれば、件数が多くても同じ手順で処理できます。ただし、印刷は実行すると取り消しにくい処理なので、この記事では印刷前の確認の仕組みもあわせて紹介します。
前提とするシート
「一覧」シートの A列:顧客コード、B列:氏名、C列:住所、D列:請求金額、E列:印刷対象(○を付けた行だけ印刷)、F列:印刷日とします。「テンプレート」シートには、差し込み先のセル(B3:氏名、B4:住所、E10:金額、E2:顧客コード)を決めておき、それ以外の文面や罫線はあらかじめ作っておきます。差し込み先のセル番地はコードの先頭で定数にしておくと、レイアウト変更時の修正が楽になります。
コード
まず印刷対象の件数とプリンター名を表示して確認を取り、続けて1件目だけを印刷プレビューで表示します。プレビューを閉じた後にもう一度確認し、「はい」を選んだときだけ全件を印刷します。印刷した行には F列に日付を記録します。
Option Explicit
Sub PrintEach()
Const CELL_CODE As String = "E2"
Const CELL_NAME As String = "B3"
Const CELL_ADDR As String = "B4"
Const CELL_AMT As String = "E10"
Dim wsList As Worksheet, wsTpl As Worksheet
Dim lastRow As Long, r As Long, targetCnt As Long, printed As Long
Dim firstRow As Long
Set wsList = ThisWorkbook.Worksheets("一覧")
Set wsTpl = ThisWorkbook.Worksheets("テンプレート")
lastRow = wsList.Cells(wsList.Rows.Count, "A").End(xlUp).Row
targetCnt = WorksheetFunction.CountIf(wsList.Range("E2:E" & lastRow), "○")
If targetCnt = 0 Then
MsgBox "印刷対象(E列が○の行)がありません"
Exit Sub
End If
If MsgBox(targetCnt & " 件を印刷します。" & vbCrLf & "プリンター:" & _
Application.ActivePrinter & vbCrLf & "1件目をプレビューで確認しますか?", _
vbYesNo + vbQuestion) = vbNo Then Exit Sub
' 1件目を差し込んでプレビューで確認する
For r = 2 To lastRow
If wsList.Cells(r, "E").Value = "○" Then firstRow = r: Exit For
Next r
FillTemplate wsTpl, wsList, firstRow, CELL_CODE, CELL_NAME, CELL_ADDR, CELL_AMT
wsTpl.PrintPreview
If MsgBox("このレイアウトで " & targetCnt & " 件を印刷しますか?", _
vbYesNo + vbExclamation) = vbNo Then Exit Sub
For r = 2 To lastRow
If wsList.Cells(r, "E").Value = "○" Then
FillTemplate wsTpl, wsList, r, CELL_CODE, CELL_NAME, CELL_ADDR, CELL_AMT
wsTpl.PrintOut Copies:=1
wsList.Cells(r, "F").Value = Date ' 印刷日を記録
printed = printed + 1
End If
Next r
MsgBox printed & " 件を印刷しました"
End Sub
' 一覧の指定行の値をテンプレートに差し込む
Private Sub FillTemplate(ByVal wsTpl As Worksheet, ByVal wsList As Worksheet, ByVal r As Long, _
ByVal cCode As String, ByVal cName As String, ByVal cAddr As String, ByVal cAmt As String)
wsTpl.Range(cCode).Value = wsList.Cells(r, "A").Value
wsTpl.Range(cName).Value = wsList.Cells(r, "B").Value & " 様"
wsTpl.Range(cAddr).Value = wsList.Cells(r, "C").Value
wsTpl.Range(cAmt).Value = wsList.Cells(r, "D").Value
wsTpl.Calculate ' 金額を参照する数式を再計算
End Subコードのポイント
印刷の前に、件数とプリンター名をメッセージで表示しています。Application.ActivePrinter は現在の既定のプリンターを返すため、前回別のプリンターに印刷していた場合などの出力先の間違いに気づけます。さらに1件目をプレビューで表示することで、差し込み位置のずれや文字のはみ出しを、紙に出す前に確認できます。
差し込み処理は FillTemplate という別の Sub に分け、プレビュー用と本番の印刷で同じ処理を使っています。こうしておくと、プレビューでは正しいのに本番では違う、という食い違いが起きません。テンプレートに合計や税額の数式がある場合に備えて、差し込み後に Calculate で再計算しています。
注意点と運用の工夫
印刷は、途中で止めても既にプリンターへ送ったページは出力されます。件数が多い場合は、最初に数件だけ ○ を付けて試し、問題がないことを確かめてから全件を対象にしてください。印刷日を記録しているので、途中で紙詰まりなどがあっても、どこまで印刷したかを確認して残りだけ ○ を付け直せます。
画面更新を止める ScreenUpdating = False と PrintPreview を組み合わせると、プレビューが正しく表示されないことがあるため、この記事のコードでは画面更新を止めていません。また、テンプレートの印刷範囲や用紙サイズは、事前にページ設定で決めておきます。紙ではなく PDF で保存・送付したい場合は、PrintOut の代わりに ExportAsFixedFormat を使うと、同じ流れで1件ずつ PDF を作成できます。
- 件数とプリンター名を確認してから印刷する
- 1件目をプレビューで確認する
- 印刷日を記録し、途中で止まっても再開できるようにする
※印刷は実行すると取り消せません。最初は少ない件数で動作を確認してください。氏名や住所など個人情報を含む帳票は、印刷物の取り扱いにも注意してください。