VBA100本ノック第51弾:ブック内の全シート一覧と印刷ページ数の抽出
Excel VBAの実務において、「ブック全体の構成を把握し、印刷時のボリュームを正確に見積もる」というタスクは、資料作成の最終段階で頻繁に発生します。特に、数十枚のシートが存在する巨大なワークブックを扱う際、一つひとつ手作業でページ数を確認するのは非効率的であり、ヒューマンエラーの温床となります。
本稿では、VBA100本ノックの第51本目として、「ブック内のすべてのシート名を取得し、それぞれのシートが印刷時に何ページになるかをリスト化する」という実用的な処理について、その技術的背景と実装方法を徹底解説します。
技術的背景:VBAでページ数を取得する仕組み
ExcelのVBAにおいて、あるシートが印刷されたときに何ページになるかを取得するには、PageSetupオブジェクトの情報を参照するだけでは不十分です。PageSetupはあくまで「印刷設定」を保持しているだけであり、実際にExcelが計算する「改ページ位置」を直接教えてくれるわけではないからです。
ここで重要となるのが、HPageBreaksコレクションとVPageBreaksコレクションです。
・HPageBreaks:水平方向の改ページ(行方向)
・VPageBreaks:垂直方向の改ページ(列方向)
印刷されるページ数は、これらのコレクション数によって決定されます。具体的には、水平方向の区切りが「n」箇所あれば、行方向には「n+1」の領域が存在することになります。同様に、列方向の区切りが「m」箇所あれば、列方向には「m+1」の領域が存在します。したがって、全体のページ数は「(HPageBreaks.Count + 1) * (VPageBreaks.Count + 1)」という数式で算出可能です。
ただし、注意点があります。これらは「自動改ページ」だけでなく「手動改ページ」も含まれるため、非常に正確な値が得られます。また、印刷範囲が設定されていない場合はシート全体が対象となりますが、印刷設定によっては計算結果がゼロになるケースもあるため、エラーハンドリングを考慮する必要があります。
実装のためのサンプルコード
以下に、対象ブックの全シートを巡回し、シート名とページ数を新規シートに出力するプロシージャを提示します。
Sub GetSheetPrintPages()
Dim ws As Worksheet
Dim reportWs As Worksheet
Dim i As Long
Dim hCount As Long
Dim vCount As Long
Dim totalPages As Long
' レポート用シートの作成
Set reportWs = Worksheets.Add
reportWs.Name = "印刷ページ一覧_" & Format(Now, "yyyymmdd_hhmmss")
reportWs.Range("A1:B1").Value = Array("シート名", "ページ数")
i = 2
' 全シートをループ処理
For Each ws In ThisWorkbook.Worksheets
' レポートシート自体は除外
If ws.Name <> reportWs.Name Then
' 改ページ数の取得
' 注意:印刷設定が正しく行われていないシートではエラーになる可能性があるため
' On Error Resume Next 等で制御する必要がある
On Error Resume Next
hCount = ws.HPageBreaks.Count
vCount = ws.VPageBreaks.Count
On Error GoTo 0
' ページ数の計算
totalPages = (hCount + 1) * (vCount + 1)
' 結果を出力
reportWs.Cells(i, 1).Value = ws.Name
reportWs.Cells(i, 2).Value = totalPages
i = i + 1
End If
Next ws
' 仕上げ:列幅の自動調整
reportWs.Columns("A:B").AutoFit
MsgBox "ページ数の抽出が完了しました。", vbInformation
End Sub
詳細解説:コードのポイントと注意点
このコードを理解する上で、いくつかの重要なポイントがあります。
まず、「On Error Resume Next」の使用です。なぜこれが必要かというと、印刷プレビューを通していないシートや、印刷範囲が極端に狭い、あるいはExcel側がまだ改ページ位置を計算していない状態のシートに対して「HPageBreaks.Count」を参照すると、実行時エラーが発生する場合があるからです。プロフェッショナルなコードとしては、エラーを無視するだけでなく、必要に応じて「ws.PageSetup.PrintArea」を確認するなどのロジックを追加するとより堅牢になります。
次に、ページ数の論理式です。なぜ「+1」をしているのか。これは、「改ページ線」とは「区切り」そのものであり、例えば1枚の紙には改ページ線が0本ですが、ページ数は1です。改ページ線が1本入れば、ページ数は2になります。この「n+1」という関係性を理解しておくことが、Excelの印刷制御をマスターする近道です。
最後に、レポート用シートの命名です。ブック内のシート名と重複しないように、現在時刻を付与して生成しています。これにより、何度実行してもエラーで止まることがなく、履歴を保持したまま集計を行うことが可能です。
実務におけるアドバイス:プロの視点
実務でこのスクリプトを運用する場合、以下の3点を意識してください。
1. 印刷設定の事前確認
このコードは、あくまで「その時点での印刷設定」に基づくページ数を算出します。ユーザーが「A4横」なのか「A4縦」なのか、「拡大縮小設定」をどうしているかによって結果は大きく変わります。本番環境で実行する前に、対象シートのPageSetupが統一されているか、あるいは意図通りかを確認するステップを挟むのがベストです。
2. 計算負荷の考慮
シート数が数百枚に及ぶ場合、HPageBreaksへのアクセスはExcelの計算エンジンを走らせるため、処理に時間がかかることがあります。この場合、画面更新を停止する「Application.ScreenUpdating = False」を冒頭に入れ、処理速度を向上させるのが鉄則です。
3. PDF出力との連携
このマクロを応用すれば、全シートをPDF化する前に、「合計で何ページになるか」を事前に警告することができます。例えば、「合計ページ数が100を超えていたらPDF出力の中断を促す」といった制御を加えることで、意図しない大量印刷や巨大なPDF生成を防ぐ「ガードレール」としての役割を持たせることができます。
まとめ
VBA100本ノックの第51弾として、シート一覧とページ数取得の技術を解説しました。単に「ページ数を出す」という機能は、一見すると地味ですが、これは「Excelの印刷エンジンを制御する」という深い領域への入り口です。
PageSetupオブジェクトと改ページコレクションを自由に操れるようになれば、帳票作成の自動化における品質は劇的に向上します。特に、大規模なブックを管理するエンジニアにとって、今回紹介したコードは、そのままツールボックスに入れておける武器となるはずです。
VBAは、単なるマクロの記録ではありません。Excelが裏側でどのようにデータを処理し、どのように画面へ出力しているのか。そのメカニズムを理解し、コードで制御する。これこそが、ベテランエンジニアへの第一歩です。ぜひ、ご自身の業務でこのコードをカスタマイズし、さらなる高みを目指してください。
