この記事でできること
- VBAで今日の曜日を判定し、土日ならスキップ・平日なら処理を実行できる
- 月末最終営業日(土日除外)を自動判定できる
- 月次処理を「毎回カレンダーで確認→手動実行」から「マクロ1つで自動判定&実行」に変えられる
月末になるたびに手作業で締め日を確認して集計していた。祝日や土日がからむと毎回カレンダーとにらめっこ。もっと早く自動化すればよかったと思った。
どんな場面で使う?
- 月末最終営業日にだけ締め処理や集計マクロを実行したい
- 土日・祝日を除外した営業日数を自動計算したい
- 毎月の報告書提出日を曜日判定で自動リマインドしたい
- 日付ベースの条件分岐で、月初・月末・四半期末の処理を切り替えたい
完成イメージ(Before / After)
Before(手動確認):
- カレンダーを開く
- 「今日は月末?」「何曜日?」を確認
- 月末が土日なら「じゃあ金曜にやるべきだった?」と混乱
- 該当日なら手動でマクロを実行
After(自動判定):
- マクロを実行(またはファイルを開く)
- 今日が月末最終営業日かを自動判定
- 該当すれば処理が走る。該当しなければ「今日は対象外です」と表示されて終了
経理の月次処理で毎月末に「今日は最終営業日?」とカレンダーを見ていた。月末が土曜なら金曜にやるべきだし、うっかり忘れて翌月頭にバタバタすることもあった。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(デモ用) |
コードの流れ
Weekday(Date, vbMonday)で今日の曜日番号を取得(月曜=1〜日曜=7)- 番号が6以上(土曜 or 日曜)ならメッセージを出してスキップ
- 平日なら処理を実行
重要: 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(デモ用) |
コードの流れ
- 月末日の取得:
DateSerial(Year(Date), Month(Date) + 1, 0)で翌月の0日 = 今月の末日を取得 - 営業日にずらす:
Do Whileループで月末日が土日なら1日ずつ前にずらす - 今日と比較:
Date <> lastDayなら対象外としてスキップ - 処理の実行: 今日が月末最終営業日なら、★の箇所に書いた処理を実行
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つで実行する方法 — 月末判定マクロをボタンに割り当てて、ワンクリックで月末処理を実行したい場合に
次に読むと理解しやすい関連記事
- 勤怠管理表を自動作成する方法 – 日付や曜日の処理を実務表に使う例です。
- 見積書・請求書を自動作成する方法 – 月末日や請求日を扱う実務例につながります。
- Excelダッシュボードを自動更新する方法 – 月次集計の日付管理に応用できます。
月末処理に入れるべき実務ルール
月末処理の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を定時実行する方法 が役立ちます。


コメント