VBAで祝日を含めた年間予定表を自動生成するには、祝日一覧をDictionaryに読み込んでおき、1月1日から12月31日をループしながら「平日・土日・祝日」を判定して書き出します。毎年手作業でカレンダーを作り直す手間がなくなり、祝日の判定ミスも防げます。
この記事では、次の内容を順番に解説します。
- 祝日シートの準備と読み込み方
- 年間予定表を自動生成する基本コード
- 土日・祝日に背景色をつける書式設定コード
- 対象年をInputBoxで指定できるようにする方法
- よくある質問(祝日の取得先・振替休日の扱い・翌年への流用等)
祝日シートの準備と読み込み方を理解するには?
Excelには祝日を自動判定する機能がないため、あらかじめ「祝日」シートに日付一覧を用意しておく必要があります。A列に日付だけをシンプルに入力してください。
| A列(祝日の日付) |
|---|
| 2026/01/01 |
| 2026/01/12 |
| 2026/02/11 |
| (以下続く) |
祝日データは内閣府の祝日一覧(https://www8.cao.go.jp/chosei/shukujitsu/gaiyou.html)からCSVで取得できます。毎年更新されるため、年初に最新版を確認して「祝日」シートに貼り付けておくのがおすすめです。
この祝日シートをDictionaryに読み込む処理は次の通りです。
' 祝日シートからDictionaryに登録する
Dim dict As Object
Dim holidaySh As Worksheet
Dim i As Long
Set dict = CreateObject("Scripting.Dictionary")
Set holidaySh = Worksheets("祝日")
i = 1
Do While holidaySh.Cells(i, 1).Value <> ""
dict.Add Format(holidaySh.Cells(i, 1).Value, "yyyy/mm/dd"), True
i = i + 1
Loop
日付を Format(..., "yyyy/mm/dd") で文字列に統一しているのがポイントです。後でループ内の日付と照合する際も同じ形式で変換するため、確実に一致判定できます。
年間予定表を自動生成する基本コードを理解するには?
Sub MakeYearlySchedule()
Dim ws As Worksheet
Dim holidaySh As Worksheet
Dim dict As Object
Dim d As Date
Dim i As Long
Dim rowNum As Long
Dim yearVal As Integer
Dim kubun As String
yearVal = Year(Date) ' 今年を対象にする
' 出力シートをリセット
Application.DisplayAlerts = False
On Error Resume Next
Worksheets("年間予定表").Delete
On Error GoTo 0
Application.DisplayAlerts = True
Set ws = Worksheets.Add
ws.Name = "年間予定表"
' 祝日をDictionaryに読み込む
Set dict = CreateObject("Scripting.Dictionary")
Set holidaySh = Worksheets("祝日")
i = 1
Do While holidaySh.Cells(i, 1).Value <> ""
dict.Add Format(holidaySh.Cells(i, 1).Value, "yyyy/mm/dd"), True
i = i + 1
Loop
' ヘッダー
ws.Range("A1:D1").Value = Array("日付", "曜日", "区分", "備考")
ws.Range("A1:D1").Font.Bold = True
' 1月1日〜12月31日をループ
rowNum = 2
For d = DateSerial(yearVal, 1, 1) To DateSerial(yearVal, 12, 31)
ws.Cells(rowNum, 1).Value = d
ws.Cells(rowNum, 1).NumberFormatLocal = "yyyy/m/d"
ws.Cells(rowNum, 2).Value = Format(d, "aaa") ' 月〜日(日本語曜日)
' 区分を判定
If dict.exists(Format(d, "yyyy/mm/dd")) Then
kubun = "祝日"
ElseIf Weekday(d, vbSunday) = 1 Then
kubun = "日曜"
ElseIf Weekday(d, vbSunday) = 7 Then
kubun = "土曜"
Else
kubun = "平日"
End If
ws.Cells(rowNum, 3).Value = kubun
rowNum = rowNum + 1
Next d
ws.Columns("A:D").AutoFit
MsgBox yearVal & "年の年間予定表を作成しました(" & (rowNum - 2) & "行)。", vbInformation, "完了"
End Sub
このコードのポイントは次の通りです。
Format(d, "aaa")で「月」「火」「水」など日本語の短縮曜日が取得できる- 祝日の判定を土日より先に行うことで、祝日が土曜に重なった場合でも「祝日」と表示される
DateSerial(yearVal, 1, 1) To DateSerial(yearVal, 12, 31)でその年の全日付をループする- 出力シートを毎回削除・再作成するため、何度実行しても正しい状態になる
土日・祝日に背景色をつけるには?
区分の判定後に背景色を設定することで、一覧の視認性が大きく上がります。
' 区分に応じて背景色を設定する(上記ループ内の「ws.Cells(rowNum, 3).Value = kubun」の後に追加)
Select Case kubun
Case "祝日"
ws.Rows(rowNum).Interior.Color = RGB(255, 199, 206) ' 薄い赤
Case "日曜"
ws.Rows(rowNum).Interior.Color = RGB(255, 230, 230) ' 淡い赤
Case "土曜"
ws.Rows(rowNum).Interior.Color = RGB(221, 235, 247) ' 淡い青
End Select
祝日を土日より目立たせたい場合は、祝日の色を少し濃くするか太字にするとわかりやすくなります。
対象年をInputBoxで指定できるようにするには?
来年・再来年の予定表を先に作りたい場合など、年を指定して実行できるようにする方法です。
' yearVal = Year(Date) の代わりに使う
Dim input As String
input = InputBox("対象年を入力してください(例:2027)", "年間予定表", Year(Date))
If input = "" Or Not IsNumeric(input) Then
MsgBox "キャンセルされました。", vbInformation
Exit Sub
End If
yearVal = CInt(input)
これにより、コードを変更せずに任意の年の予定表を生成できます。祝日シートに対象年の祝日データが入っていることを確認してから実行してください。
まとめ
- 祝日判定には 「祝日」シートへの事前入力+Dictionary読み込み が必要
- 曜日取得は
Format(d, "aaa")で日本語短縮曜日(月〜日)が取得できる - 祝日・土日・平日の判定順は 祝日を最初に判定 することで重複を避ける
- 背景色は
Select Case kubunで区分ごとに設定する - 対象年を InputBox で入力できると翌年以降もコード変更不要で使い回せる
よくある質問
祝日データはどこから取得すればいい?
内閣府の「国民の祝日について」のページ(https://www8.cao.go.jp/chosei/shukujitsu/gaiyou.html)で毎年更新されるCSVファイルが公開されています。このCSVをExcelで開き、日付列を「祝日」シートのA列に貼り付けるだけで準備完了です。振替休日もこのCSVに含まれているため、別途対応する必要はありません。
振替休日は自動で判定できない?
Excelには振替休日を自動計算する機能がないため、VBAだけでは判定できません。ただし、内閣府のCSVには振替休日も「休日」として記載されているため、そのデータをそのまま「祝日」シートに取り込めば問題なく対応できます。
翌年の予定表を今年中に作りたい場合は?
InputBoxで年を指定する方法(上記「対象年をInputBoxで指定」参照)を使えば、翌年の年を入力するだけです。ただし「祝日」シートに翌年分の祝日データが入っていないと祝日が判定されないため、内閣府サイトで翌年分が公開され次第、シートを更新してください。
祝日名(元日・成人の日など)も表示したい場合は?
「祝日」シートにB列として祝日名を追加しておき、DictionaryのAddの第2引数にTrueの代わりに祝日名を入れることで取得できます。
' B列に祝日名が入っている場合
dict.Add Format(holidaySh.Cells(i, 1).Value, "yyyy/mm/dd"), holidaySh.Cells(i, 2).Value
' ループ内で名前を取得する
If dict.exists(Format(d, "yyyy/mm/dd")) Then
ws.Cells(rowNum, 4).Value = dict(Format(d, "yyyy/mm/dd")) ' D列に祝日名を出力
End If
月ごとに別シートに分けて出力したい場合は?
ループ内で月が変わるタイミング(Month(d) <> Month(d - 1))を検知してシートを切り替える方法があります。シートが12枚になるためファイルが重くなる場合は、1シートに月ごとの区切り行を入れる方が管理しやすいケースも多いです。
動画で学びたい方へ
「記事を読んでも、実際に自分で書けるか不安…」という方には、動画で基礎からじっくり学べる講座がおすすめです。
VBAが初めての方を前提に、つまずきやすいポイントを先回りして解説しています。サンプル動画は無料でご覧いただけます。



