【VBA】日付・曜日を判定して月末処理を自動化する方法(コピペOK)

【VBA】日付・曜日を判定して月末処理を自動化する方法の解説用アイキャッチ画像 VBA
VBAで月末最終営業日を判定する流れ
月末処理は営業日判定と対象外ログを入れておくと運用しやすくなります。
  1. この記事でできること
  2. どんな場面で使う?
  3. 完成イメージ(Before / After)
  4. 実行前の準備
    1. バックアップを取る
  5. コード(最小版)– 今日の曜日を判定して処理を分岐
    1. 書き換えポイント
    2. コードの流れ
  6. コード(実務版)– 月末最終営業日を判定して処理を実行
    1. 書き換えポイント
    2. コードの流れ
  7. よくある落とし穴5選
    1. 1. Weekday の第2引数を省略して曜日がずれる
    2. 2. DateSerial の「月+1, 0」が理解できない
    3. 3. 祝日を考慮していない
    4. 4. 月末処理が2回走ってしまう
    5. 5. Date と Now を間違えて日付比較がうまくいかない
    6. VBAで月末日の判定が正しくできないときの対処法
    7. VBAの曜日判定で土曜・日曜の処理がずれるときの対処法
  8. 実務で日付判定を使うときの設計ポイント
    1. 対象日が空なら止める例
  9. FAQ
    1. Q1: 祝日も除外した営業日判定をしたい
    2. Q2: 月初の最初の営業日を取得したい
    3. Q3: 月末最終営業日に色分けも自動実行したい
    4. Q4: ファイルを開いたら自動で月末判定させたい
    5. Q5: 判定結果をセルに書き出したい
  10. まとめ
    1. 関連記事
  11. 次にやりたくなること
  12. 次に読むと理解しやすい関連記事
  13. 月末処理に入れるべき実務ルール
    1. 祝日一覧を使った判定例
    2. 対象外の日はログを残す
  14. 月末自動化のFAQ
    1. 祝日一覧は毎年作り直す必要がありますか?
    2. ブックを開いたときに自動実行しても大丈夫?
    3. 関連して読むとよい記事は?

この記事でできること

  • VBAで今日の曜日を判定し、土日ならスキップ・平日なら処理を実行できる
  • 月末最終営業日(土日除外)を自動判定できる
  • 月次処理を「毎回カレンダーで確認→手動実行」から「マクロ1つで自動判定&実行」に変えられる

月末になるたびに手作業で締め日を確認して集計していた。祝日や土日がからむと毎回カレンダーとにらめっこ。もっと早く自動化すればよかったと思った。

どんな場面で使う?

  • 月末最終営業日にだけ締め処理や集計マクロを実行したい
  • 土日・祝日を除外した営業日数を自動計算したい
  • 毎月の報告書提出日を曜日判定で自動リマインドしたい
  • 日付ベースの条件分岐で、月初・月末・四半期末の処理を切り替えたい

完成イメージ(Before / After)

Before(手動確認):

  1. カレンダーを開く
  2. 「今日は月末?」「何曜日?」を確認
  3. 月末が土日なら「じゃあ金曜にやるべきだった?」と混乱
  4. 該当日なら手動でマクロを実行

After(自動判定):

  1. マクロを実行(またはファイルを開く)
  2. 今日が月末最終営業日かを自動判定
  3. 該当すれば処理が走る。該当しなければ「今日は対象外です」と表示されて終了

経理の月次処理で毎月末に「今日は最終営業日?」とカレンダーを見ていた。月末が土曜なら金曜にやるべきだし、うっかり忘れて翌月頭にバタバタすることもあった。VBAのWeekdayとDateSerialを使えば月末最終営業日を自動判定できる。この判定をVBAに任せてからは月末処理の漏れがなくなった。同じストレスを抱えている人に、この記事で自動化を試してほしい。

月末最終営業日の確認は、VBAに任せれば一瞬で終わる。

実行前の準備

バックアップを取る

マクロ実行前に、Excelファイルのコピーを別フォルダに保存しておく。

コード(最小版)– 今日の曜日を判定して処理を分岐


'============================================================
' ■ 曜日判定で処理を分岐(最小版)
'   → 今日が平日(月〜金)なら処理を実行、土日ならスキップ
'============================================================
Sub CheckWeekdayMinimal()

    '--- 今日の曜日番号を取得(vbMonday指定: 月=1, 火=2, ... 土=6, 日=7)
    '    ★重要: vbMonday を省略すると日曜始まりになり、土日の番号がずれる
    Dim wDay As Integer
    wDay = Weekday(Date, vbMonday)

    '--- 土日判定(6=土曜, 7=日曜)
    If wDay >= 6 Then
        MsgBox "今日は " & WeekdayName(Weekday(Date)) & " です。" & vbCrLf & _
               "平日ではないため、処理をスキップします。", vbInformation
        Exit Sub
    End If

    '--- ★ここに平日に実行したい処理を書く ---
    MsgBox "今日は " & WeekdayName(Weekday(Date)) & "(平日)です。" & vbCrLf & _
           "処理を実行します。", vbInformation

End Sub

書き換えポイント

変数・箇所 説明 初期値
wDay >= 6 土日判定の条件。6=土曜, 7=日曜 >= 6
'--- ★ここに〜 平日に実行したい処理をここに書く MsgBox(デモ用)

コードの流れ

  1. Weekday(Date, vbMonday) で今日の曜日番号を取得(月曜=1〜日曜=7)
  2. 番号が6以上(土曜 or 日曜)ならメッセージを出してスキップ
  3. 平日なら処理を実行

重要: Weekday の第2引数に vbMonday を必ず指定する。省略するとデフォルトの日曜始まり(vbSunday)になり、土日の番号がずれる。

コード(実務版)– 月末最終営業日を判定して処理を実行

月次処理で一番ニーズが高いのは「今日が月末最終営業日かどうか」の判定。月末が土日なら前倒しで金曜になる。

この仕組みを入れてからは、月末のカレンダー確認が不要になった。「今日は最終営業日だっけ?」という確認作業が完全に消えたのは想像以上に楽だった。月末処理の結果をそのままPDF出力(「ExcelファイルをPDFに一括変換」)すれば、報告書の自動化まで一気に進められる。


'============================================================
' ■ 月末最終営業日を判定して処理を実行(実務版)
'   → 今日が月末最終営業日なら処理を実行、それ以外はスキップ
'   → 土日を除外(祝日は対象外。祝日も含めたい場合は別途マスタが必要)
'============================================================
Sub RunOnLastBusinessDay()

    '--- 今月の月末日を取得(翌月の0日 = 今月の末日)
    '    ※ 12月でも Month(Date)+1=13 → DateSerial が自動で繰り上げるため正常動作
    Dim lastDay As Date
    lastDay = DateSerial(Year(Date), Month(Date) + 1, 0)

    '--- 月末日が土日なら前にずらして最終営業日を求める
    '    vbMonday指定: 月=1, 火=2, 水=3, 木=4, 金=5, 土=6, 日=7
    Do While Weekday(lastDay, vbMonday) > 5
        lastDay = lastDay - 1
    Loop

    '--- 判定結果を表示
    Dim lastBusinessDayText As String
    lastBusinessDayText = Format(lastDay, "yyyy/mm/dd") & "(" & _
                          WeekdayName(Weekday(lastDay)) & ")"

    '--- 今日が月末最終営業日かどうか判定
    If Date <> lastDay Then
        MsgBox "今月の最終営業日は " & lastBusinessDayText & " です。" & vbCrLf & _
               "今日は対象外のため、処理をスキップします。", vbInformation
        Exit Sub
    End If

    '--- ★ここに月末最終営業日に実行したい処理を書く ---
    MsgBox "今日は月末最終営業日(" & lastBusinessDayText & ")です。" & vbCrLf & _
           "月末処理を実行します。", vbInformation

    '--- 例:月末処理の内容をここに追加 ---
    ' Call MonthlyReport      ' 月次レポート作成
    ' Call ExportToPDF         ' PDF出力
    ' Call SendMailNotification ' メール通知

End Sub

書き換えポイント

変数・箇所 説明 初期値
Month(Date) + 1, 0 月末日取得の計算式。変更不要
Weekday(lastDay, vbMonday) > 5 土日判定。変更不要
'--- ★ここに〜 月末最終営業日に実行したい処理 MsgBox(デモ用)

コードの流れ

  1. 月末日の取得: DateSerial(Year(Date), Month(Date) + 1, 0) で翌月の0日 = 今月の末日を取得
  2. 営業日にずらす: Do While ループで月末日が土日なら1日ずつ前にずらす
  3. 今日と比較: Date <> lastDay なら対象外としてスキップ
  4. 処理の実行: 今日が月末最終営業日なら、★の箇所に書いた処理を実行

DateSerial(年, 月+1, 0) は「翌月の0日目 = 今月の最終日」を意味する。VBAの日付処理では定番のテクニック。初見では分かりにくいが、覚えると月末取得がこの1行で済む。

よくある落とし穴5選

1. Weekday の第2引数を省略して曜日がずれる

原因: Weekday(Date) とだけ書くと、デフォルトで日曜始まり(vbSunday)になる。この場合、土曜=7、日曜=1 になり、>= 6 の判定では土曜しか引っかからない。

自分もこれでハマった。vbMonday を指定し忘れて金曜日に処理が走らなくなった。上司に「金曜の数字が出てない」と指摘されて気づいた。あのときは冷や汗だった。

対策: Weekday(Date, vbMonday) と必ず第2引数を書く。月曜=1〜日曜=7 で統一すれば > 5 で土日判定ができる。

2. DateSerial の「月+1, 0」が理解できない

原因: DateSerial(2026, 4, 0)2026/03/31 になる仕組みが分かりにくい。

対策: 「翌月の0日目 = 今月の最終日」と覚える。VBAが自動的に日付を繰り下げてくれる。12月の場合も DateSerial(2026, 13, 0)2026/12/31 で正常に動く。

3. 祝日を考慮していない

原因: この記事のコードは土日のみ除外。祝日(元日、成人の日、etc.)は営業日として扱われる。

自分も最初、土日だけ除外して安心していたら、1月の月末最終営業日が「成人の日」にあたっていた。祝日なのにマクロが「今日は最終営業日です」と判定して処理が走ってしまい、上司から「祝日にデータ送ってきたけど?」と言われた。

対策: 祝日も除外したい場合は、シートに祝日一覧(マスタ)を用意し、Application.Match で突き合わせる。この記事の範囲では土日除外のみ対応。

4. 月末処理が2回走ってしまう

原因: マクロを同じ日に2回実行すると、当然2回走る。

対策: 処理済みフラグをセルに書き込む方法がある。フラグ用セルはデータと被らない空きセルや別シートに置くことを推奨。


If Range("A1").Value = Format(Date, "yyyy/mm/dd") Then
    MsgBox "本日は処理済みです。", vbInformation
    Exit Sub
End If
' --- 処理 ---
Range("A1").Value = Format(Date, "yyyy/mm/dd")

5. Date と Now を間違えて日付比較がうまくいかない

原因: Now は日付+時刻を返す(例:2026/03/07 14:30:00)。Date は日付のみ(例:2026/03/07)。日付比較に Now を使うと時刻部分のせいで一致しない。

対策: 日付の比較には必ず Date を使う。時刻が不要なら Now は使わない。

VBAで月末日の判定が正しくできないときの対処法

「月末処理が実行されない」という場合、原因は Date ではなく Now を使って日付比較していることが多い。Now は日付+時刻を返すため、日付のみの比較で一致しない。日付比較には必ず Date を使い、DateSerial(Year(Date), Month(Date) + 1, 0) で月末日を取得すれば正確に判定できる。

VBAの曜日判定で土曜・日曜の処理がずれるときの対処法

「土曜のはずなのに平日扱いになる」という場合、原因は Weekday 関数の週の開始曜日設定が想定と違うことだ。Weekday(Date, vbSunday) のように第2引数を明示的に指定すれば、日曜=1、月曜=2…土曜=7として確実に判定できる。

実務で日付判定を使うときの設計ポイント

日付判定のマクロは、請求書作成、月末締め、営業日判定、定期レポート作成などで使いやすい処理です。ただし、Date 関数で今日の日付をそのまま使うと、PCの日付設定がずれていた場合や、前月分を後から処理したい場合に意図しない結果になります。実務では、今日の日付で判定する処理と、セルに入力した対象日で判定する処理を分けて考えると安全です。

月末最終営業日を判定する場合も、土日だけでは足りないことがあります。祝日、会社独自の休業日、棚卸日、年末年始などは業務によって違います。そのため、祝日や休業日はコードに直接書くより、シート上のマスタで管理するほうが後から直しやすくなります。自動化に慣れていない場合でも、日付マスタを1列用意するだけなら始めやすく、請求や締め処理のミスを減らしやすいです。

判定方法向いている場面注意点
Dateで今日を判定毎日同じタイミングで実行する処理PCの日付設定に依存する
セルの日付を判定過去分・翌月分を手動で処理する場面入力漏れや日付形式を確認する
祝日マスタを参照営業日判定や月末締めマスタ更新の担当を決める
手動確認を残す請求・送信・削除など影響が大きい処理自動実行前に件数や対象日を表示する

対象日が空なら止める例

Dim targetDate As Variant
targetDate = Range("B2").Value

If Not IsDate(targetDate) Then
    MsgBox "B2に判定したい日付を入力してください。"
    Exit Sub
End If

If Weekday(CDate(targetDate), vbMonday) <= 5 Then
    MsgBox "平日です。"
End If

日付の自動化は、慣れるととても使いやすい分野です。最初から完全自動にせず、対象日をセルに入力して、実行前に確認メッセージを出す形にすると、業務で使うときの心理的なハードルも下げられます。

FAQ

Q1: 祝日も除外した営業日判定をしたい

シートに祝日一覧を用意し、月末日から遡りながら祝日にも該当しないか確認する。この記事では土日のみ除外する方法を紹介しているが、祝日テーブルとの組み合わせはカスタマイズの範囲。

Q2: 月初の最初の営業日を取得したい

DateSerial(Year(Date), Month(Date), 1) で月初日を取得し、土日なら+1する:


Dim firstDay As Date
firstDay = DateSerial(Year(Date), Month(Date), 1)
Do While Weekday(firstDay, vbMonday) > 5
    firstDay = firstDay + 1
Loop

Q3: 月末最終営業日に色分けも自動実行したい

月末判定の★部分に色分けマクロを呼び出す行を追加する。色分けの方法は「【VBA】セルの値に応じて行を自動色分けする方法」を参照。


'--- ★ここに月末処理 ---
Call ColorByValue  ' 色分けマクロを呼び出す

Q4: ファイルを開いたら自動で月末判定させたい

ThisWorkbook モジュール(標準モジュールではない)に Workbook_Open イベントを書く:


Private Sub Workbook_Open()
    Call RunOnLastBusinessDay
End Sub

注意: このコードは VBE 左側のプロジェクトエクスプローラーで「ThisWorkbook」をダブルクリックして開くウィンドウに貼る。標準モジュールに貼っても動かない。

これでファイルを開くたびに自動判定される。セルの値が変わったら自動実行する方法(「セルの値が変わったら自動実行」)と同じイベント駆動の考え方。

Q5: 判定結果をセルに書き出したい

MsgBoxの代わりにセルに書く:


Range("A1").Value = "最終営業日: " & Format(lastDay, "yyyy/mm/dd")
Range("A2").Value = IIf(Date = lastDay, "今日は対象日", "今日は対象外")

まとめ

  • Weekday(Date, vbMonday) で曜日番号を取得し、土日を判定できる
  • DateSerial(Year(Date), Month(Date) + 1, 0) で月末日を取得できる
  • 月末日が土日なら前にずらして最終営業日を求める
  • vbMonday の指定忘れが最大の落とし穴。必ず第2引数を書く

関連記事

  • 【VBA】マクロをボタン1つで実行する方法 — 月末判定マクロをボタンに割り当てればワンクリックで済む
  • 【VBA】セルの値に応じて行を自動色分けする方法 — 月末行や期限切れの行を色分けする
  • 【VBA】ExcelファイルをPDFに一括変換する方法 — 月末レポートをPDFにして保存・配布

次にやりたくなること

  • 【VBA】セルの値に応じて行を自動色分けする方法 — 月末処理で期限切れの行を自動でハイライトしたい場合に
  • 【VBA】営業日を計算する方法 — 土日だけでなく祝日も含めた営業日計算をしたい場合に
  • 【VBA】マクロをボタン1つで実行する方法 — 月末判定マクロをボタンに割り当てて、ワンクリックで月末処理を実行したい場合に


次に読むと理解しやすい関連記事

月末処理に入れるべき実務ルール

月末処理のVBAは「月末かどうか」だけでなく、「土日なら前倒しするのか」「祝日はどう扱うのか」「対象外の日は何もしないのか」を決めておくと運用で迷いません。特に経理・在庫・売上集計では、月末日と最終営業日がずれる月にミスが起きやすいです。

確認項目おすすめの決め方理由
土日の扱い月末が土日なら直前の金曜日に実行月をまたいでから気づく手戻りを防げます。
祝日の扱い祝日一覧シートを作り、営業日判定から除外会社カレンダーに合わせて調整できます。
対象外の日メッセージを出して終了マクロが動いていないのか、対象外なのかを区別できます。

祝日一覧を使った判定例

祝日まで考慮したい場合は、シート「祝日」のA列に日付を並べておき、土日または祝日なら営業日ではないと判定します。会社独自の休業日も同じ一覧に入れられます。

Function IsBusinessDay(ByVal targetDate As Date) As Boolean
    Dim holidayRange As Range
    Set holidayRange = Worksheets("祝日").Range("A:A")

    If Weekday(targetDate, vbMonday) > 5 Then
        IsBusinessDay = False
    ElseIf WorksheetFunction.CountIf(holidayRange, CLng(targetDate)) > 0 Then
        IsBusinessDay = False
    Else
        IsBusinessDay = True
    End If
End Function

対象外の日はログを残す

自動実行にする場合、何も表示せずに終了すると「処理されたのか分からない」状態になります。対象日ではないときも、メッセージやログ用シートに結果を残すと運用確認が楽になります。

If IsLastBusinessDay(Date) Then
    Call RunMonthlyClose
Else
    Worksheets("ログ").Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Value = _
        Format(Now, "yyyy/mm/dd hh:nn:ss") & " 対象外のため処理なし"
End If

月末自動化のFAQ

祝日一覧は毎年作り直す必要がありますか?

会社で使う営業日カレンダーに合わせるなら、年初に1年分をシートへ登録しておく運用が分かりやすいです。祝日だけでなく、会社独自の休業日も同じ列に追加できます。

ブックを開いたときに自動実行しても大丈夫?

可能ですが、最初は手動実行で動作確認してからにしてください。自動実行する場合も、対象外の日は処理しない分岐とログ出力を入れておくと安心です。

関連して読むとよい記事は?

月末ファイルを保存するなら 日付やセル値でファイル名を付けて保存する方法、進捗を見せたい場合は ステータスバーに進捗を表示する方法、定期実行まで自動化したい場合は タスクスケジューラでVBAを定時実行する方法 が役立ちます。

コメント

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