【VBAリファレンス】VBA練習問題VBA100本ノック 51本目:シート一覧と印刷ページ数

スポンサーリンク

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が裏側でどのようにデータを処理し、どのように画面へ出力しているのか。そのメカニズムを理解し、コードで制御する。これこそが、ベテランエンジニアへの第一歩です。ぜひ、ご自身の業務でこのコードをカスタマイズし、さらなる高みを目指してください。

タイトルとURLをコピーしました