【VBA】Excelで請求書を自動作成してPDF保存する方法(コピペOK)

VBA
スポンサーリンク
スポンサーリンク

この記事でできること

  • 一覧表から請求書テンプレートにデータを自動転記できる
  • 全件をループしてPDFファイルとして一括保存できる
  • 確認ダイアログ+進捗表示で安全に実行できる

対象: Excel 2016以降 / Microsoft 365、Windows 10/11


完成イメージ(Before / After)

Before(手作業):

  1. 一覧表を見ながら請求書テンプレートに1件ずつ転記
  2. 取引先名・金額・日付をコピペ
  3. PDF保存して次の請求書へ
  4. 20社分で2時間。転記ミスで再発行のリスクあり

After(マクロ実行):

  1. 一覧シートにデータを入力
  2. マクロを実行する
  3. 確認ダイアログ「20 件の請求書を作成します。実行しますか?」が表示される
  4. ステータスバーに「請求書作成中… 5/20」と進捗が出る
  5. 「請求書PDF」フォルダに20件のPDFが保存される
  6. 5分で完了。転記ミスゼロ

一覧シート(入力するデータ):

A B C D E
1 請求番号 取引先名 件名 金額 請求日
2 INV-001 株式会社ABC Webサイト制作 500000 2026/03/31
3 INV-002 株式会社DEF システム保守 300000 2026/03/31
4 INV-003 株式会社GHI コンサルティング 200000 2026/03/31

出力されるPDFファイル:


請求書PDF\
  ├── 請求書_株式会社ABC_20260331.pdf
  ├── 請求書_株式会社DEF_20260331.pdf
  └── 請求書_株式会社GHI_20260331.pdf

毎月20社分の請求書を手作業で作っていた時期がある。一覧表を見ながらテンプレートに1件ずつ転記して、PDF保存して、また次の取引先。金額のコピペミスで再発行になったことが2回ある。正直、月末の請求書作業が怖かった。

VBAで自動化してからはミスゼロになった。作業時間は2時間→5分。一覧シートにデータを入力してマクロを実行するだけで、PDFが全件できあがる。月末の請求書作業が怖くなくなった。

同じように毎月の請求書で消耗している人に、この一括処理を体験してほしい。まずは最小版で1件だけ転記して、動くことを確認するところから始めよう。

一覧表 → テンプレート転記 → PDF保存。この流れをVBAで自動化する。


事前準備

シート構成を用意する

このマクロは2つのシートを使う。

「一覧」シート — 請求データを入力する場所

内容
A列 請求番号 INV-001
B列 取引先名 株式会社ABC
C列 件名 Webサイト制作
D列 金額 500000
E列 請求日 2026/03/31
  • 1行目はヘッダー。データは2行目から入力する
  • A列が空の行が最終行として判定される

「請求書」シート — テンプレート(転記先)

セル 内容
C3 取引先名(宛名)
C5 件名
C8 請求番号
E3 請求日
D15 金額

テンプレートの作り方は本記事の後半で解説する。

バックアップを取る

テンプレートシートにデータを上書きする処理のため、実行前にファイルのコピーを取っておくこと。テスト用のダミーデータで動作確認してから本番データで実行することを強く推奨する。

Excelをマクロ有効ブック(.xlsm)で保存する

拡張子が .xlsx のままだとマクロは保存できない。

  1. 「ファイル」→「名前を付けて保存」
  2. ファイルの種類を「Excelマクロ有効ブック (*.xlsm)」に変更
  3. 保存

手順(コピペ → 実行まで約5分)

VBE(コードを書く画面)を開く

  1. Excelで Alt + F11 を押す
  2. VBE(Visual Basic Editor)が開く

標準モジュールを挿入する

  1. VBEのメニュー →「挿入」→「標準モジュール」
  2. 白い画面(コードウィンドウ)が表示される

コードを貼り付けて実行する

  1. コードウィンドウに、下のコードをそのままコピペする
  2. コード内の書き換えポイント(★マーク)を自分の環境に合わせて変更する
  3. Alt + F8 → マクロ名を選んで「実行」

コード(最小版)– 一覧から請求書テンプレートに1件転記

まず1件だけ転記して動作確認する。ループもPDF保存もない最小構成。

セルの転記の基本はセルの転記を自動化する方法を参照。


Sub 請求書を作成する()
    Dim wsList As Worksheet
    Dim wsTemplate As Worksheet
    Dim lastRow As Long
    Dim i As Long

    Set wsList = Worksheets("一覧")
    Set wsTemplate = Worksheets("請求書")

    ' ★ 最終行を取得(A列で判定)
    lastRow = wsList.Cells(wsList.Rows.Count, 1).End(xlUp).Row

    If lastRow < 2 Then
        MsgBox "一覧にデータがありません。", vbExclamation
        Exit Sub
    End If

    ' 1件目のデータを転記(動作確認用)
    With wsTemplate
        .Range("C3").Value = wsList.Cells(2, 2).Value   ' 取引先名
        .Range("C5").Value = wsList.Cells(2, 3).Value   ' 件名
        .Range("E3").Value = wsList.Cells(2, 5).Value   ' 請求日
        .Range("D15").Value = wsList.Cells(2, 4).Value  ' 金額
        .Range("C8").Value = wsList.Cells(2, 1).Value   ' 請求番号
    End With

    wsTemplate.Activate
    MsgBox "請求書を作成しました。"
End Sub

書き換えポイント

# 書き換え箇所 初期値 説明
1 Worksheets("一覧") 一覧 一覧データのシート名
2 Worksheets("請求書") 請求書 テンプレートのシート名
3 .Range("C3") C3, C5, E3, D15, C8 テンプレート側の転記先セル
4 wsList.Cells(2, 2) 列2,3,5,4,1 一覧側の列番号(B=2, C=3 …)

動作確認

  1. 「一覧」シートの2行目にテスト用データを1件入力する
  2. マクロを実行する
  3. 「請求書」シートに切り替わり、データが転記されていることを確認する

最小版で転記が確認できたら、次の実務版に進む。


コード(実務版)– 全件ループ+PDF保存+確認ダイアログ+進捗表示

自分はこの方法で毎月20社分の請求書を処理している。2時間かかっていた作業が5分で終わるようになった。

一覧の全件をループしてテンプレートに転記し、1件ずつPDF保存する。PDF保存の基本はExcelファイルをPDFに一括変換する方法を参照。


Sub 請求書を一括作成してPDF保存()
    Dim wsList As Worksheet
    Dim wsTemplate As Worksheet
    Dim lastRow As Long
    Dim i As Long
    Dim savePath As String
    Dim fileName As String
    Dim cnt As Long
    Dim clientName As String

    Set wsList = Worksheets("一覧")
    Set wsTemplate = Worksheets("請求書")

    ' ★ 最終行を取得(A列で判定)
    lastRow = wsList.Cells(wsList.Rows.Count, 1).End(xlUp).Row

    If lastRow < 2 Then
        MsgBox "一覧にデータがありません。", vbExclamation
        Exit Sub
    End If

    ' ★ 保存先フォルダ(ブックと同じ場所に「請求書PDF」フォルダ)
    savePath = ThisWorkbook.Path & "\請求書PDF\"
    If Dir(savePath, vbDirectory) = "" Then
        MkDir savePath
    End If

    ' 確認ダイアログ(件数+保存先を表示)
    If MsgBox((lastRow - 1) & " 件の請求書を作成します。" & vbCrLf & _
              "保存先: " & savePath & vbCrLf & vbCrLf & _
              "実行しますか?", vbYesNo + vbQuestion) = vbNo Then
        Exit Sub
    End If

    Application.ScreenUpdating = False

    For i = 2 To lastRow
        ' ステータスバーに進捗表示
        Application.StatusBar = "請求書作成中... " & (i - 1) & "/" & (lastRow - 1)

        ' テンプレートに転記
        With wsTemplate
            .Range("C3").Value = wsList.Cells(i, 2).Value   ' 取引先名
            .Range("C5").Value = wsList.Cells(i, 3).Value   ' 件名
            .Range("E3").Value = wsList.Cells(i, 5).Value   ' 請求日
            .Range("D15").Value = wsList.Cells(i, 4).Value  ' 金額
            .Range("C8").Value = wsList.Cells(i, 1).Value   ' 請求番号
        End With

        ' ファイル名の禁止文字を置換
        clientName = Replace(wsList.Cells(i, 2).Value, "/", "/")
        clientName = Replace(clientName, "\", "\")
        clientName = Replace(clientName, ":", ":")
        clientName = Replace(clientName, "*", "*")
        clientName = Replace(clientName, "?", "?")
        clientName = Replace(clientName, """", """)
        clientName = Replace(clientName, "<", "<")
        clientName = Replace(clientName, ">", ">")
        clientName = Replace(clientName, "|", "|")

        ' ★ PDFファイル名: 請求書_取引先名_日付.pdf
        fileName = "請求書_" & clientName & "_" & _
                   Format(wsList.Cells(i, 5).Value, "yyyymmdd") & ".pdf"

        ' PDF保存
        wsTemplate.ExportAsFixedFormat _
            Type:=xlTypePDF, _
            Filename:=savePath & fileName, _
            Quality:=xlQualityStandard

        cnt = cnt + 1
    Next i

    ' テンプレートをクリア(前回データの残留防止)
    With wsTemplate
        .Range("C3").ClearContents
        .Range("C5").ClearContents
        .Range("E3").ClearContents
        .Range("D15").ClearContents
        .Range("C8").ClearContents
    End With

    Application.StatusBar = False
    Application.ScreenUpdating = True

    MsgBox cnt & " 件の請求書PDFを保存しました。" & vbCrLf & _
           "保存先: " & savePath, vbInformation
End Sub

書き換えポイント

# 書き換え箇所 初期値 説明
1 "\請求書PDF\" 請求書PDF PDF保存先フォルダ名
2 .Range("C3") C3, C5, E3, D15, C8 テンプレート側の転記先セル
3 wsList.Cells(i, 2) 列2,3,5,4,1 一覧側の列番号
4 "請求書_" 請求書_ PDFファイル名のプレフィックス

実務版で追加した機能

機能 説明 参考記事
確認ダイアログ 件数+保存先を表示してYes/Noで確認
進捗表示 ステータスバーに「5/20」形式で進捗を表示 進捗表示の方法
PDF一括保存 ExportAsFixedFormatで1件ずつPDF化 PDF一括変換
フォルダ自動作成 MkDirで保存先フォルダを自動作成
禁止文字置換 ファイル名に使えない文字を全角に変換
テンプレートクリア ループ完了後にClearContentsで前回データを消去

テンプレートの作り方

「請求書」シートのレイアウト例を示す。実際のデザインは自由に変更してよい。重要なのは転記先のセル位置を合わせること。

レイアウト例


行1  : [空白]
行2  : [空白]        [空白]        請 求 書
行3  : [空白]  C3:取引先名 御中           E3:請求日
行4  : [空白]
行5  : [空白]  C5:件名
行6  : [空白]
行7  : [空白]  下記の通りご請求申し上げます。
行8  : [空白]  C8:請求番号
行9  : [空白]
行10 : [空白]  ─────────────────
行11 : [空白]  項目           数量    単価      金額
行12 : [空白]  ─────────────────
行13 : [空白]  (明細行)
行14 : [空白]  ─────────────────
行15 : [空白]  [空白]         [空白]  小計    D15:金額
行16 : [空白]  [空白]         [空白]  消費税  (数式: =D15*0.1)
行17 : [空白]  [空白]         [空白]  合計    (数式: =D15+D16)
行18 : [空白]
行19 : [空白]  振込先: ○○銀行 ○○支店 普通 1234567
行20 : [空白]  支払期限: 翌月末日

ポイント

  • 消費税(D16)と合計(D17)はExcelの数式で計算する。VBA側で転記するのは小計(D15)だけでよい
  • テンプレートの書式(フォント、罫線、列幅)は事前に整えておく
  • 印刷範囲を設定しておくとPDFのレイアウトが安定する(「ページレイアウト」→「印刷範囲の設定」)
  • 金額セル(D15)の表示形式は #,##0 に設定しておく。書式設定の詳細はセルの書式を一括変更する方法を参照

よくある落とし穴5選

# 症状 原因 対策
1 「パスが見つかりません」エラー PDF保存先フォルダが存在しない MkDir で自動作成する。実務版コードでは Dir(savePath, vbDirectory) で存在チェック後に作成している
2 PDF保存時に「実行時エラー 1004」 取引先名に / \ : などファイル名に使えない文字が含まれている Replace 関数で禁止文字を全角に置換する。実務版コードでは9種類の禁止文字を置換済み
3 金額が「500000」と表示される(カンマなし) テンプレートのセル書式が「標準」になっている テンプレートのD15セルの表示形式を #,##0 に設定する。または wsTemplate.Range("D15").NumberFormat = "#,##0" をコードに追加
4 2回目の実行でテンプレートに前回データが残る ループ終了後にClearContentsしていない 実務版コードではループ完了後に全転記セルをClearContentsしている。最小版で試す場合も手動でクリアすること
5 一覧の列を追加したらデータがズレた Cells(i, 2) のように列番号をハードコーディングしている 列番号を Const で定数化する(例: Const COL_CLIENT As Long = 2)。列を変更したら定数だけ直せばよい

取引先名に「/」が入っていてPDF保存でエラーになったことがある。「株式会社A/B」のような社名で、ファイル名に使えない文字だと気づかずに30分溶かした。実務版コードでは最初からReplace処理を入れているので同じ失敗は起きない。


FAQ

Q1. 請求書に明細行(複数行の品目)を入れたい

一覧シートの構成を変更する。1つの請求番号に対して複数行を持たせ、ループ処理で請求番号が変わるタイミングでPDF保存する。本記事の構成は「1行=1請求書」の最もシンプルなパターン。明細対応は別記事で解説予定。

Q2. 既存のPDFが上書きされるのを防ぎたい

Dir() で同名ファイルの存在をチェックしてスキップする。


If Dir(savePath & fileName) <> "" Then
    ' 既に存在する場合はスキップ
    GoTo NextRecord
End If

Q3. 請求日を今日の日付で自動設定したい

一覧シートのE列に Date 関数の値を入れるか、コード内で直接設定する。


wsTemplate.Range("E3").Value = Date

Q4. 消費税を自動計算してテンプレートに反映したい

テンプレートのD16セルにExcelの数式 =D15*0.1 を入れておく。VBAで小計(D15)を転記すると消費税は数式で自動計算される。コード側で計算する必要はない。

Q5. ボタンからマクロを実行したい

マクロをボタン1つで実行する方法を参照。シート上にボタンを設置して OnAction にマクロ名「請求書を一括作成してPDF保存」を割り当てる。経理以外の人にも使ってもらう場合はボタン化が便利。


まとめ

この記事では、VBAで一覧表から請求書テンプレートにデータを自動転記し、PDFファイルとして一括保存する方法を解説した。

  • 最小版: 1件だけ転記して動作確認
  • 実務版: 全件ループ + PDF保存 + 確認ダイアログ + 進捗表示

テスト用のダミーデータで動作確認してから、本番データで実行すること。

関連記事


次にやりたくなること

コメント

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