【VBA】祝日・土日を除いた営業日を自動計算する方法(コピペOK)

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

この記事でできること

VBAで祝日・土日を除いた営業日を自動計算できるようになる。N営業日後の日付を出したり、2つの日付間の営業日数を数えたり、一覧表の支払期限を一括計算できる。

  • 対象:納期・支払期限の計算で毎回カレンダーを手で数えている人
  • 所要時間:コピペ → 動作確認まで約5分(目安)

自分も以前、支払期限を「月末締め翌月末払い」で計算していたが、年末年始を考慮し忘れて先方から催促メールが来たことがある。正直あれは焦った。営業日計算をVBAで自動化してからは、どの取引先にも正確な期限を出せるようになり、催促が来ることはなくなった。

日付や曜日の基本的な判定方法は日付・曜日の判定で月末処理を自動化する方法で解説しているので、あわせて確認すると理解が深まる。

この記事で、同じように営業日計算で困っている方がサクッと自動化できるようになればうれしい。


完成イメージ(Before / After)

Before(実行前)

請求日から支払期限を手計算。カレンダーを見ながら土日祝を除外して数える。

A(取引先) B(案件名) C(請求日) D(支払期限)
1 取引先 案件名 請求日 支払期限
2 A商事 部品納入 2026/01/06 (手計算…)
3 B工業 設備保守 2026/01/15 (手計算…)
4 C物産 原材料 2026/02/03 (手計算…)

After(実行後)

マクロを実行すると、C列の請求日から30営業日後(祝日・土日除外)がD列に自動出力される。

A(取引先) B(案件名) C(請求日) D(支払期限)
1 取引先 案件名 請求日 支払期限
2 A商事 部品納入 2026/01/06 2026/02/17
3 B工業 設備保守 2026/01/15 2026/02/26
4 C物産 原材料 2026/02/03 2026/03/17

事前準備

バックアップを取る

既存のデータが入っているExcelファイルで試す場合は、先にファイルをコピーしてバックアップを取ること。

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

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

.xlsx のままだとマクロが保存されない。必ず .xlsm にすること。

「祝日」シートを作る

実務版・一括計算で使う祝日リストを準備する。シート名は 「祝日」 にすること。

A(日付) B(祝日名)
1 日付 祝日名
2 2026/01/01 元日
3 2026/01/12 成人の日
4 2026/02/11 建国記念の日
5 2026/02/23 天皇誕生日
6 2026/03/20 春分の日
7 2026/04/29 昭和の日
8 2026/05/03 憲法記念日
9 2026/05/04 みどりの日
10 2026/05/05 こどもの日
11 2026/05/06 振替休日
12 2026/07/20 海の日
13 2026/08/11 山の日
14 2026/09/21 敬老の日
15 2026/09/23 秋分の日
16 2026/10/12 スポーツの日
17 2026/11/03 文化の日
18 2026/11/23 勤労感謝の日

ポイント:

  • A列は日付型で入力する(文字列ではない)
  • 振替休日も忘れずに入れる(内閣府の「国民の祝日について」ページで確認)
  • 会社独自の休業日(年末年始の12/29〜1/3、お盆など)があれば追加する
  • 毎年1月に翌年分の祝日を追加するのがおすすめ

注意: 上記の祝日リストは参考例です。実際に使用する際は、内閣府の公式情報で正確な日付を確認してください。


コード(最小版)– WorkDayで簡単にN営業日後を計算

まずはこれだけで動く。祝日リストなしで、土日のみ除外した5営業日後を計算する。


Sub N営業日後を計算する()
    Dim startDate As Date
    Dim resultDate As Date

    startDate = Date  ' 今日の日付

    ' 5営業日後を計算(土日のみ除外)
    resultDate = WorksheetFunction.WorkDay(startDate, 5)

    MsgBox "今日: " & Format(startDate, "yyyy/mm/dd") & vbCrLf & _
           "5営業日後: " & Format(resultDate, "yyyy/mm/dd")
End Sub

コードの動作:

  1. Date で今日の日付を取得
  2. WorksheetFunction.WorkDay で5営業日後の日付を計算(土日を自動で飛ばす)
  3. MsgBox で結果を表示

重要:WorkDayの数え方

WorkDay関数は開始日の翌日からカウントする。つまり WorkDay(1月5日, 5) は 1月6日を1日目として数え始める。当日を含めたい場合は nDays - 1 にするか、開始日を1日前にする。

MsgBoxの使い方の詳細はMsgBoxの使い方と実務パターンを参照。


コード(実務版)– 祝日リスト対応のN営業日後

業務で使うなら祝日の除外が必須。「祝日」シートのリストを参照して、土日+祝日を除外したN営業日後を計算する。

自分はこの方法を使うようになってから、年末年始やGWを跨ぐ期限計算でミスがなくなった。特に12月〜1月は祝日+年末年始休業が重なるので、手計算だとまず間違える。


Sub N営業日後を計算する_祝日対応()
    Dim ws As Worksheet
    Dim startDate As Date
    Dim nDays As Long
    Dim holidays As Variant
    Dim resultDate As Date
    Dim lastRow As Long

    Set ws = Worksheets("祝日")
    startDate = Date
    nDays = 5

    ' 祝日リストを配列に読み込み
    lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
    If lastRow >= 2 Then
        holidays = ws.Range("A2:A" & lastRow).Value
    End If

    ' WorkDay関数に祝日リストを渡す
    If IsArray(holidays) Then
        resultDate = WorksheetFunction.WorkDay(startDate, nDays, _
                     ws.Range("A2:A" & lastRow))
    Else
        resultDate = WorksheetFunction.WorkDay(startDate, nDays)
    End If

    MsgBox nDays & "営業日後: " & Format(resultDate, "yyyy/mm/dd(aaa)")
End Sub

コードの動作:

  1. 「祝日」シートからA列の最終行を取得して祝日リストを読み込む
  2. WorksheetFunction.WorkDay に祝日範囲を渡してN営業日後を計算
  3. 結果を曜日付きで表示(aaa は「月」「火」などの曜日表記)

2つの日付間の営業日数を計算する

「1月6日〜1月31日の間に何営業日あるか?」を計算する。稼働日数やリードタイムの算出に使える。


Sub 営業日数を計算する()
    Dim ws As Worksheet
    Dim startDate As Date
    Dim endDate As Date
    Dim bizDays As Long
    Dim lastRow As Long

    Set ws = Worksheets("祝日")
    startDate = #1/6/2026#
    endDate = #1/31/2026#

    lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row

    If lastRow >= 2 Then
        bizDays = WorksheetFunction.NetworkDays(startDate, endDate, _
                  ws.Range("A2:A" & lastRow))
    Else
        bizDays = WorksheetFunction.NetworkDays(startDate, endDate)
    End If

    MsgBox Format(startDate, "yyyy/mm/dd") & " ~ " & _
           Format(endDate, "yyyy/mm/dd") & vbCrLf & _
           "営業日数: " & bizDays & " 日"
End Sub

WorkDay と NetworkDays の使い分け:

関数 用途 戻り値
WorkDay N営業日後の日付を知りたい 日付
NetworkDays 2日付間の営業日数を知りたい 数値

実務で使う:支払期限を一括計算する

一覧表の請求日から支払期限を一括で計算するコード。実務ではこのパターンが最も使える。

「一覧」シートのレイアウト:

A(取引先) B(案件名) C(請求日) D(支払期限)
1 取引先 案件名 請求日 支払期限
2 A商事 部品納入 2026/01/06 (自動で入る)

Sub 支払期限を一括計算する()
    Dim wsData As Worksheet
    Dim wsHoliday As Worksheet
    Dim lastRow As Long
    Dim lastRowH As Long
    Dim i As Long
    Dim cnt As Long

    ' --- 祝日シートの存在チェック ---
    Dim sheetExists As Boolean
    Dim tmpSheet As Worksheet
    sheetExists = False
    For Each tmpSheet In ThisWorkbook.Worksheets
        If tmpSheet.Name = "祝日" Then
            sheetExists = True
            Exit For
        End If
    Next tmpSheet

    If Not sheetExists Then
        MsgBox "「祝日」シートが見つかりません。" & vbCrLf & _
               "シート名を確認してください。", vbExclamation
        Exit Sub
    End If

    Set wsData = Worksheets("一覧")
    Set wsHoliday = Worksheets("祝日")

    lastRow = wsData.Cells(wsData.Rows.Count, 1).End(xlUp).Row
    lastRowH = wsHoliday.Cells(wsHoliday.Rows.Count, 1).End(xlUp).Row

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

    On Error GoTo ErrHandler
    Application.ScreenUpdating = False

    For i = 2 To lastRow
        If IsDate(wsData.Cells(i, 3).Value) Then
            ' C列の請求日から30営業日後をD列に出力
            If lastRowH >= 2 Then
                wsData.Cells(i, 4).Value = _
                    WorksheetFunction.WorkDay( _
                        wsData.Cells(i, 3).Value, 30, _
                        wsHoliday.Range("A2:A" & lastRowH))
            Else
                wsData.Cells(i, 4).Value = _
                    WorksheetFunction.WorkDay(wsData.Cells(i, 3).Value, 30)
            End If
            wsData.Cells(i, 4).NumberFormat = "yyyy/mm/dd"
            cnt = cnt + 1
        End If
    Next i

    Application.ScreenUpdating = True
    MsgBox cnt & " 件の支払期限を計算しました。"
    Exit Sub

ErrHandler:
    Application.ScreenUpdating = True
    MsgBox "エラーが発生しました(行 " & i & "): " & Err.Description, vbExclamation
End Sub

コードの動作:

  1. 「祝日」シートの存在を確認(見つからなければエラーメッセージを表示して終了)
  2. 「一覧」シートのA列で最終行を取得
  3. 2行目から最終行までループ
  4. C列が日付型の行だけ処理(IsDateチェック)
  5. C列の請求日から30営業日後を計算してD列に出力
  6. D列の書式を yyyy/mm/dd に設定
  7. 処理件数をMsgBoxで報告
  8. エラー発生時も Application.ScreenUpdating = True に戻してからエラー内容を表示

営業日数の変更: 30 の部分を変えれば、任意のN営業日後に変更できる。


よくある落とし穴5選

# 症状 原因 対策
1 期限日が1日ズレる WorkDay関数は開始日の翌日からカウントする 当日を含めるなら nDays - 1 にする
2 祝日が除外されていない 祝日リストの年度が古い(去年のまま) 毎年1月に祝日リストを更新する。内閣府の祝日一覧を参照
3 実行時にエラーが出る 祝日シートのA列に文字列(日付型でないデータ)が混ざっている IsDate で事前チェック。セルの表示形式を「日付」に設定してから入力する
4 振替休日が営業日扱いになる 祝日リストに振替休日が入っていない 内閣府の祝日一覧で振替休日・国民の休日を確認して追加する
5 会社の休業日が考慮されない 年末年始(12/29〜1/3)やお盆は祝日ではないが休業日 祝日リストに会社独自の休業日も追加する

自分も2番でやらかしたことがある。年明けに祝日リストを更新し忘れて、1月4日(仕事始め)を休日扱いにしてしまい、取引先への支払期限がズレた。それ以来、毎年1月の最初の出勤日に「祝日シート更新」をルーティンにしている。


FAQ

Q1: 当日を含めて営業日を計算したい場合は?

WorkDay関数は翌日からカウントするため、当日を含めたい場合は営業日数を1つ減らす。例:「今日を含めて5営業日以内」なら WorkDay(startDate, 4) にする。

Q2: 土曜日も営業日に含めたい場合は?

WorksheetFunction.WorkDay_Intl を使う。第3引数に曜日パターンを指定できる。よく使うパターンは以下のとおり。

パターン値 休日の曜日
1(既定) 土曜・日曜
11 日曜のみ
12 月曜のみ
17 なし(祝日リストのみで制御)

例:WorkDay_Intl(startDate, nDays, 11, 祝日範囲) で土曜を営業日に含める。

Q3: 祝日リストを自動で作成できる?

VBAだけで祝日リストを自動生成するのは困難。内閣府の「国民の祝日について」ページから一覧をコピーして祝日シートに貼り付けるのが現実的。

Q4: マイナスの日数を指定したらどうなる?

N営業日の日付が返る。WorkDay(Date, -5) で5営業日前を計算できる。支払いの起算日を遡る場合に使える。

Q5: 結果がシリアル値(数値)で表示される

D列のセルにNumberFormatが設定されていない場合、日付がシリアル値(例:46044)で表示される。コード内で wsData.Cells(i, 4).NumberFormat = "yyyy/mm/dd" を設定するか、事前にD列の書式を「日付」に設定しておく。

Q6: 「祝日」シートが見つからないとエラーになる

シート名が全角・半角で異なっていたり、前後にスペースが入っているとシートが見つからずエラーになる。シート名は正確に 「祝日」(全角2文字)にすること。一括計算コードでは存在チェックを入れているが、実務版コードで同じエラーが出る場合はシート名を再確認する。


まとめ

この記事で、VBAを使って祝日・土日を除いた営業日を自動計算できるようになった。

  • 最小版:WorkDayでN営業日後を簡単計算(土日のみ除外)
  • 実務版:祝日リスト対応のN営業日後
  • 営業日数計算:NetworkDaysで2日付間の営業日数を取得
  • 一括計算:一覧表の支払期限を一括で自動出力

重要なのは以下の2点:

  1. WorkDayは翌日からカウントする(当日含むなら-1)
  2. 祝日リストは毎年更新する(振替休日・会社休業日も忘れずに)

関連記事

次にやりたくなること

コメント

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