【脱エクセルVBA初心者】請求書作成マクロの全体おさらいと総仕上げ

みなさん、こんにちは!
タカハシ(@ntakahashi0505)です。

脱エクセルVBA初心者向け、請求書を自動で作る際の様々なテクニックについて連載でお伝えしてきました。

前回の記事はコチラ。

429 Too Many Requests

Vlookup時に発生するエラーを上手に回避する方法についてお伝えしました。

これにて、請求書作成プログラムはだいぶ出来上がってきまして、残す処理はほんの少しとなりました。

過去の記事でお伝えしたテクニックも多く含まれますが、おさらいも含めまして総仕上げの解説をしていきます。

スポンサーリンク

前回までのおさらい

前回までで作成したプログラムはこちらです。

Sub 請求書作成()

Dim wsData As Worksheet '「請求データ」シート
Set wsData = ThisWorkbook.Worksheets("請求データ")

Dim rngAccount As Range '「取引先マスタ」検索範囲
Set rngAccount = ThisWorkbook.Worksheets("取引先マスタ").Range("A:D")

Call wsDataSort

Dim startRow As Long 'コピー範囲の最初の行と最終行を格納
startRow = 2

Dim wsInvoice As Worksheet '「請求書ひな形」シート
Dim strFile As String '保存先フォルダパス&ファイル名(拡張子抜き)

Dim strAccount As String '取引先名

Dim i As Long
i = 2
Do While wsData.Cells(i, 1).Value <> ""

    i = i + 1
    If firstDay(wsData.Cells(i, 1).Value) <> firstDay(wsData.Cells(startRow, 1).Value) Or _
        wsData.Cells(i, 2).Value <> wsData.Cells(startRow, 2).Value Then
       
      '*****新規ワークブックを作成***** 
        Workbooks.Add '新規ワークブックを作成
        ThisWorkbook.Worksheets("請求書ひな形").Copy before:=ActiveWorkbook.Sheets(1) '新規ワークブックのsheet1の前にひな形をコピー

        Set wsInvoice = ActiveSheet 'コピーしたシートを変数にセット
        wsInvoice.Name = "請求書" 'シート名を変更

        Application.DisplayAlerts = False '確認メッセージをオフにする
        ActiveWorkbook.Worksheets("Sheet1").Delete 'Sheet1を削除する
        Application.DisplayAlerts = True '確認メッセージをオンにする

        strFile = ThisWorkbook.Path & "\" & Format(wsData.Cells(startRow, 1).Value, "YYYYMM") & "請求書_" & wsData.Cells(startRow, 2).Value & "御中"

        '*****PDF出力設定*****
        With wsInvoice.PageSetup

            .Zoom = False       '倍率をクリア
            .FitToPagesWide = 1 '横方向に1ページに収める
            .FitToPagesTall = 1 '縦方向に1ページに収める
            .CenterHorizontally = True                          '水平方向に中央配置
            .TopMargin = Application.CentimetersToPoints(1)     '上マージンを1cm
            .BottomMargin = Application.CentimetersToPoints(1)  '下マージンを1cm

        End With

        '*****請求書の各データを入力*****
        wsData.Range(wsData.Cells(startRow, 3), wsData.Cells(i - 1, 5)).Copy wsInvoice.Range("A21") '範囲をコピペ

        On Error Resume Next 'エラーを無視

        strAccount = wsData.Cells(startRow, 2).Value '取引先名
        wsInvoice.Range("A3").Value = strAccount & " 御中" '取引先名
        wsInvoice.Range("A5").Value = "〒" & WorksheetFunction.VLookup(strAccount, rngAccount, 2, False)  '郵便番号
        wsInvoice.Range("A6").Value = WorksheetFunction.VLookup(strAccount, rngAccount, 3, False)  '住所1
        wsInvoice.Range("A7").Value = WorksheetFunction.VLookup(strAccount, rngAccount, 4, False)  '住所2

        If Err.Number <> 0 Then 'エラーが発生したときにメッセージを表示
            MsgBox strAccount & "の情報を取得するVlookupでエラーが発生しました"
            Err.Clear 'Errオブジェクトをクリア
        End If
        
        '*****PDF出力をして保存して閉じる*****
        wsInvoice.ExportAsFixedFormat Type:=xlTypePDF, Filename:=strFile & ".pdf" '選択したシートをPDF出力
        ActiveWorkbook.Close savechanges:=True, Filename:=strFile & ".xlsx" 'アクティブブックを名前を付けて保存して閉じる

        startRow = i

    End If

Loop

End Sub

請求データを年月×取引先の範囲ごとにまとめる

「請求データ」シートはこちら。

エクセルの請求データ

まずこのシートについて、wsDataSortで並び替えをします。

Sub wsDataSort()

With ActiveWorkbook.Worksheets("請求データ")

    '請求データをA列納品日、B列取引先で並び替え(見出しは範囲に含めない)
    .Range("A1").CurrentRegion.Sort Key1:=.Range("B2"), Key2:=.Range("A2"), Header:=xlYes

End With

End Sub

並び替えをした、「請求データ」シートを1行目から走査して、同じ納品月、同じ取引先である範囲をひとまとまりとします。

その判定を行っているIf文が24行目です。firstDayは日付を1日に揃える関数でこちらです。

Function firstDay(ByVal d As Date) As Date

firstDay = DateSerial(Year(d), Month(d), 1)

End Function
【脱エクセルVBA初心者】データが含まれる範囲全体を一発で取得してSortで並び替え
脱エクセルVBA初心者向けのテクニックとして、CurrentRegionプロパティでデータ範囲を塊で取得して、それをSortメソッドで並び替えをする方法についてお伝えしていきます。
【脱エクセルVBA初心者】コピペはRangeが効率的なのでその範囲を見つけるプログラム
脱エクセルVBA初心者向け、請求書を自動で作る際の様々なテクニックについてシリーズ。請求データを塊つまりRangeで見つけられれば一気にコピペできるようになります。その「塊」を効率よく見つける方法です。

年月×取引先ごとにワークブックを作成する

範囲のまとまりごとに請求書を作成(つまり、年月×取引先ごと)しますが、個々のワークブックを新規作成しシート等の準備をしている箇所が28行目~38行目です。

こちらの「請求書ひな形」シートをコピーしてワークブックを作成します。

エクセルの請求書ひな形

【脱エクセルVBA初心者】新規のワークブックを作成、シートのコピーと名前の変更
エクセルVBAで「請求書を自動で作る」をテーマに、新規のワークブックを作成して請求書ひな形シートをコピーする方法、ワークシートのシート名を変更する方法、ブックやシートに関するTIPSについて書きました。

PDF出力の設定と実行

41行目~50行目でPDFの出力に関する設定を行い、69行目で実際に出力をしています。

【脱エクセルVBA初心者】PDFでの出力とファイル名の指定保存そして閉じる
脱エクセルVBA初心者向け、請求書を自動で作る際の様々なテクニックをお伝えしていますが、今回はエクセルVBAでワークブックを別名で保存しつつ、PDF出力して閉じる方法についてお伝えします。

請求データを範囲でコピー&ペースト

行目はたった1行ですが、対象とする範囲をまるっとコピーして、新しく作ったワークブックにペーストをする処理です。

429 Too Many Requests

Vlookupで取引先情報の抽出とエラー処理

57行目~61行目で以下の「取引先マスタ」シートから各種情報を抽出してきて、請求書に転記をします。

エクセルの取引先マスタ

Vlookupで目的のキーワードでヒットしない場合はエラーになってしまうので、それを回避するのが55行目の処理となります。

429 Too Many Requests

今回のお題:請求書を整えていく

上記プログラムを実行して出力されるPDFはこのようになります。

エクセルVBAで作成した請求書

まだいくつか足りない部分がありますね。

  • 価格列と請求額金額総額が計算されていない
  • 請求日・支払期限が正しくない
  • 余計な行がたくさん含まれている

これらを直していく必要がありますね。上記プログラムでいうと67行目の箇所にこれらを直す処理を入れていきます。

数式の再計算と請求金額総額の表示

まずシートの再計算ですが、Worksheetオブジェクトに対するCalculateメソッドです。

Worksheetオブジェクト.Calculate

これで指定したシートの再計算を行います。

ですから今回の場合は

wsInvoice.Calculate

です、次にセルA18セルに請求金額を表示します。

これは、なんてことはないですね。

wsInvoice.Range("A18").Value = "ご請求金額:" & Format(wsInvoice.Range("D54").Value, "#,##0") & " 円"

Formatを使って、カンマ入りにしています。以下の記事で詳しく説明しています。

【初心者向けエクセルVBA】文字列の連結&Format関数での書式変更
エクセルVBAで文字列を連結する、文字列の書式を変更するなどの「文字列」に関するいくつかのテクニックを紹介しつつ、データ一覧から請求書を自動で作成するというシリーズ連載の序盤の完成を目指します。

請求日と支払期限を算出

こちらは事前にdayCutoffというDate型の変数を宣言しておいて

dayCutoff = wsData.Cells(startRow, 1).Value '納品日
wsInvoice.Range("D15").Value = DateSerial(Year(dayCutoff), Month(dayCutoff) + 1, 0) '請求日
wsInvoice.Range("D16").Value = DateSerial(Year(dayCutoff), Month(dayCutoff) + 2, 0) 'お支払期限

とすればOKですね。DateSerialの第3引数をゼロにすると前月末になるというのがミソですね。

301 Moved Permanently

余計な行を隠す

行を隠す場合はRowsオブジェクトに対するHiddenプロパティをTrueにします。

Worksheetオブジェクト.Rows(“開始行:最終行”).Hidden = True

今回の場合、品目の行数は(i-startRow)ですから

wsInvoice.Rows(21 + i - startRow & ":50").Hidden = True

とすればOKです。

【初心者向けエクセルVBA】行の数をカウントする&不要な行を隠す
今回は行数をカウントする、行を隠す、などの「行を取り扱うテクニック」を紹介しています。いずれもデータや帳票を扱ったエクセルVBAではかなり重宝するテクニックですので、知っておいて損はありませんよ。

実行結果

上記の各命令を66行目の下に挿入して実行します。

エクセルVBAで作成した請求書

全てバッチリ、きちんと反映されていますね。

まとめ

これまで8回に渡って、「脱エクセルVBA初心者」を目指して請求書作成プログラムを作成してきました。

  • PDFで出力する
  • データのコピペを範囲単位で実施
  • エラーの回避

など、より実用的かつプログラムの高めるような内容をいくつか習得頂けたのであれば嬉しく思います。

また実用的なVBAプログラムの作り方をお伝えしていきたいと思いますので、どうぞ楽しみにしていてください。

連載目次:【脱エクセルVBA初心者】請求書を自動で作る際のテクニック集

「請求書を自動で作る」というニーズはとても多いですから、その際に便利な機能やテクニックをシリーズにてお伝えしていきます。脱エクセルVBA初心者をターゲットにしています。
  1. 【脱エクセルVBA初心者】新規のワークブックを作成、シートのコピーと名前の変更
  2. 【脱エクセルVBA初心者】確認メッセージを表示させずにワークシートを削除する方法
  3. 【脱エクセルVBA初心者】PDFでの出力とファイル名の指定保存そして閉じる
  4. 【脱エクセルVBA初心者】データが含まれる範囲全体を一発で取得してSortで並び替え
  5. 【脱エクセルVBA初心者】コピペはRangeが効率的なのでその範囲を見つけるプログラム
  6. 【脱エクセルVBA初心者】Copyメソッドで範囲まるごとを一発でコピペする
  7. 【脱エクセルVBA初心者】Vlookupで出てしまうエラーをいい感じに回避する方法
  8. 【脱エクセルVBA初心者】請求書作成マクロの全体おさらいと総仕上げ

コメント

  1. nasu より:

    一生懸命みてやってみていますが、どうしてもできません、、、ここまでの結果のサンプルデータは公開されていないですよね、、、?

    • nasuさん

      コメントありがとうございます!
      当ブログではサンプルデータの配布はさせて頂いておりません。
      配布したツールをそのまま利用いただくのではなくて、VBAを学んでいただきたいという想いがありまして…申し訳ないです。

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