前々回、PDFの結合処理にAcrobat APIとPDFtkを使用する方法を書きましたが、職場環境によっては、フリーソフトをイントールできなかったりする場合もありますので、参考にまで!
📌 デメリット 🚨 PDFの構造が壊れる可能性が高いです。
① メイン処理(シート名をリスト化 & PDF出力)
📌 何をするコードか?
このコードでは、印刷対象のシートを探し、PDFとして保存 し、「印刷」シートに記録 します。
📌 処理の流れ
- 画面更新を停止 して、処理速度を向上させる。
- 「印刷」シートをクリア(前回の実行結果を削除)。
- 店番リスト(印刷対象のシート)を取得(データシートから)。
- すべてのシートをチェックし、印刷対象を判定。
- シートの保護を解除(パスワード付き)。
- B2 / C4 のセルを確認し、該当するシートをリスト化。
- 印刷対象のシートをPDFとして保存。
- すべてのPDFを結合。
- 画面更新を再開し、完了メッセージを表示。
VBAコード
Sub WriteSheetsToPrintAndMergePDFs()
Dim ws As Worksheet
Dim dataSheet As Worksheet
Dim printSheet As Worksheet
Dim fukuokaShops As Object
Dim shopCode As Variant
Dim shopList As Variant
Dim excludeSheets As Variant
Dim i As Integer
Dim printRow As Integer
Dim isB2 As Boolean
Dim sheetName As String
Dim password As String
Dim tempPDFs As Object
Dim tempPDFPath As String
Dim finalPDFPath As String
Dim printRange As Range ' ← 修正: printRange を事前に宣言
' ① 画面更新を停止して処理速度を向上
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.DisplayAlerts = False
Application.StatusBar = "処理を開始しています..."
' ② データシートと印刷シートをセット
Set dataSheet = ThisWorkbook.Sheets("データ")
Set printSheet = ThisWorkbook.Sheets("印刷")
' ③ 除外するシートリスト
excludeSheets = Array("データ", "データ2", "データ3", "印刷")
' ④ 「印刷」シートのリストをクリア
printSheet.Range("A2:A1000").ClearContents
' ⑤ 店番を一括取得(辞書を利用)
Set fukuokaShops = CreateObject("Scripting.Dictionary")
shopList = dataSheet.Range("A2:A" & dataSheet.Cells(Rows.Count, 1).End(xlUp).Row).Value
' ⑥ 店番リストを辞書に格納
For i = LBound(shopList) To UBound(shopList)
If Not fukuokaShops.exists(shopList(i, 1)) Then
fukuokaShops.Add shopList(i, 1), True
End If
Next i
' ⑦ 一時PDFファイルリストを作成
Set tempPDFs = CreateObject("Scripting.Dictionary")
' ⑧ シート名を「印刷」シートに書き出し & PDF出力
printRow = 2
password = "1234"
For Each ws In ThisWorkbook.Worksheets
isB2 = False
sheetName = ws.Name
Application.StatusBar = "処理中: " & sheetName & " を確認中..."
' 除外リストにあるシートはスキップ
If Not IsSheetExcluded(sheetName, excludeSheets) Then
' シート保護解除
If ws.ProtectContents Then
On Error Resume Next
ws.Unprotect Password:=password
On Error GoTo 0
End If
' B2 / C4 の店番があるかチェック
If Not IsEmpty(ws.Range("B2").Value) Then
shopCode = ws.Range("B2").Value
If fukuokaShops.exists(shopCode) Then
isB2 = True
Set printRange = ws.Range("A1:T60") ' ← 修正: printRange を正しく設定
End If
ElseIf Not IsEmpty(ws.Range("C4").Value) Then
shopCode = ws.Range("C4").Value
If fukuokaShops.exists(shopCode) Then
isB2 = False
Set printRange = ws.Range("A1:M46") ' ← 修正: printRange を正しく設定
End If
Else
GoTo NextSheet
End If
' 「印刷」シートにシート名を記録
printSheet.Cells(printRow, 1).Value = sheetName
printRow = printRow + 1
' 書式設定を適用(エラー回避のため `printRange` が Nothing でないことを確認)
If Not printRange Is Nothing Then
Call ApplyFormatting(ws, printRange, isB2)
End If
' PDFをエクスポート
tempPDFPath = Environ("TEMP") & "\" & sheetName & ".pdf"
ws.ExportAsFixedFormat Type:=xlTypePDF, Filename:=tempPDFPath, _
Quality:=xlQualityStandard, IncludeDocProperties:=True, _
IgnorePrintAreas:=False, OpenAfterPublish:=False
tempPDFs.Add tempPDFPath, tempPDFPath
End If
NextSheet:
Next ws
' ⑨ すべてのPDFを1つに結合
finalPDFPath = Environ("USERPROFILE") & "\Documents\福岡店番データ.pdf"
If tempPDFs.Count > 0 Then
Application.StatusBar = "PDFを結合しています..."
MergePDFs_Copy(tempPDFs, finalPDFPath)
End If
' ⑩ 画面更新を再開
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Application.DisplayAlerts = True
Application.StatusBar = False
' ⑪ 完了メッセージ
MsgBox "印刷シートにリストアップされたシートのPDF作成と結合が完了しました。" & vbCrLf & "保存場所:" & finalPDFPath, vbInformation
End Sub
② 除外リストチェック関数
📌 何をするコードか?
このコードは、特定のシートを印刷から除外する ための関数です。
📌処理の流れ
- あらかじめ決めた「印刷対象外のシートリスト」を作成。
- 今チェックしているシートが、そのリストの中にあるか確認。
- もしリスト内にあれば「True(除外)」、なければ「False(印刷対象)」を返す。
📌 どんな時に使う?
例えば、「データ」や「データ1」などのシートは印刷しない ようにするために使います。
vbコード
Function IsSheetExcluded(sheetName As String, excludeSheets As Variant) As Boolean
Dim i As Integer
IsSheetExcluded = False
For i = LBound(excludeSheets) To UBound(excludeSheets)
If sheetName = excludeSheets(i) Then
IsSheetExcluded = True
Exit Function
End If
Next i
End Function
③ PDF結合処理
📌 何をするコードか?
このコードは、複数のPDFを1つのPDFに結合 します。
📌 処理の流れ
- すべてのPDFファイルのリストを作成。
- Windowsのコマンド「copy /b」を使って、すべてのPDFを連結。
- 一時的に作成したPDFを削除(不要なデータを残さないようにする)。
📌 どんな時に使う?
個別に保存されたPDFを、最終的に1つのPDFにまとめたい時 に使います。
VBコード
Sub MergePDFs_Copy(tempPDFs As Object, outputPDF As String)
Dim pdfList As String
Dim tempPDF As Variant
Dim command As String
' ① PDFのリストを作成
pdfList = ""
For Each tempPDF In tempPDFs
pdfList = pdfList & " """ & tempPDF & """"
Next tempPDF
' ② Windows コマンドを作成
command = "cmd /c copy /b " & pdfList & " """ & outputPDF & """"
' ③ コマンドを実行
Shell command, vbNormalFocus
' ④ 一時ファイルを削除
For Each tempPDF In tempPDFs
Kill tempPDF
Next tempPDF
End Sub
④ 書式設定
📌 何をするコードか?
このコードは、印刷する前に書式を設定する ためのものです。
📌 処理の流れ
- フォントの種類とサイズを設定。
- B2の店番があるシートだけ、6行目~12行目のフォントサイズを大きくする。
- B2の店番があるシートだけ、S列の幅を自動調整。
- 余白の設定(B2とC4で異なる)。
📌 どんな時に使う?
印刷前に書式を整え、見やすいレイアウトにするため に使います。
vbコード
Sub ApplyFormatting(ws As Worksheet, printRange As Range, isB2 As Boolean)
' フォントサイズ設定
With printRange.Font
.Name = "Arial"
.Size = 12
.Bold = True
End With
' B2のシートの特別設定
If isB2 Then
With ws.Range("A6:T12").Font
.Size = 14
.Bold = True
End With
ws.Columns("S:S").AutoFit
End If
' 余白設定
With ws.PageSetup
.PrintArea = printRange.Address
.Orientation = xlPortrait
.PaperSize = xlPaperA4
If isB2 Then
.LeftMargin = Application.InchesToPoints(0.3)
.RightMargin = Application.InchesToPoints(0.3)
.TopMargin = Application.InchesToPoints(0.6)
.BottomMargin = Application.InchesToPoints(0.6)
Else
.LeftMargin = Application.InchesToPoints(0.6)
.RightMargin = Application.InchesToPoints(0.6)
.TopMargin = Application.InchesToPoints(0.9)
.BottomMargin = Application.InchesToPoints(0.9)
End If
.CenterHorizontally = True
.CenterVertically = True
End With
End Sub
📢 まとめ
| ステップ | 何をするコード? |
|---|---|
| ① メイン処理 | 印刷対象のシートを探し、PDFとして保存する |
| ② 除外リストチェック関数 | 「印刷しないシート」を判別し、スキップする |
| ③ PDF結合処理 | 複数のPDFを1つに結合する |
| ④ 書式設定 | 印刷前に、フォントサイズや余白を整える |
コメント