エクセル(Excel)の学習で自動生成のカレンダーは、様々な要素を学べる題材です。
エクセルには祝日を判定する関数はないため、カレンダー生成には 祝日テーブル を用意する必要があります。
ここでは、できる限りメンテナンス不要な祝日テーブルを作成します。
永続的にメンテナンス不要な祝日テーブルは無理
カレンダー自動生成を説明するサイトのほとんどは、祝日テーブルは手作業でメンテナンスする前提にしています。
また、メンテナンス不要な祝日テーブルをExcelAPIから自動反映させる手順を解説しているサイトもあります。
これから式を使って、できる限りメンテナンスしなくていよい祝日テーブルを検討しますが、完全にメンテナンス不要にはできません。
春分の日と秋分の日は永久的に正確な日付を生成することができないことに加えて、天皇が代替わりすると天皇誕生日は変わります。
また、2020年と2021年のオリンピックのための祝日移動や2019年の天皇即位による祝日扱いの休日設定など、1年限定の例外的な祝日設定が行われることもあります。
ちなみに、「祭日」とは明治から戦前にかけてあったもので、現在は法的に定義されているものはありません。
このことを踏まえて、できる限り毎年メンテナンスしなくてよい祝日テーブルを作成します。
祝日テーブルのレイアウト
作成する祝日テーブルのレイアウトです。
大晦日がありますが、ここからの説明の対象外なので無視してください。
「年」のセルを用意して、年が変わっても年以外は原則編集しなくてよい形式にします。
「説明」列はこの記事のために用意したもので基本的には不要です。
祝日の分類と設定式
祝日を分類し、それぞれに設定する式を説明します。
私は「 年 」をセル"B2"に設定しています。
日付指定
まず、最も簡単な日付が決まっている祝日です。
具体例としては、1/1の元日や4/29の昭和の日などです。
設定式は説明するまでもないですが、mm月dd日の祝日の場合
= DATE ( [年] , mm, dd )
具体的には、2/11の建国記念の日であれば "= DATE ($B$2, 2, 11) " といった式になります。
ハッピーマンデー
日付でなく月曜日に指定されている祝日です。
具体例としては、1月第2月曜日の成人の日や10月第2月曜日のスポーツの日などです。
設定式はちょっと複雑なため段階を踏んで説明しますが、まずはmm月の第n月曜日の祝日の場合
= DATE ( [年] , mm, n*7 - WEEKDAY ( DATE ([年], mm, 0), 3 ) )
具体的には、9月第3月曜日の敬老の日であれば "= DATE ($B$2, 9, 21-WEEKDAY ( DATE ($B$2, 9, 0), 3) ) " といった式になります。
分解して説明すると、 " DATE ([年], mm, 0) " は「DATE ([年], mm, 1) - 1」と同義で、mm月の前月末日を意味します。
可読性が悪いと感じる方は置き換えてください。
WEEKDAY関数は曜日を調べるもので、引数を省略すると1~7を返しますが引数に"3"を指定すると0~6を返します。
(それぞれが表す曜日が何かの説明は省略します。)
これで前月末日の曜日がわかったので、第1月曜日が何日かを算出してみます。
前月末日が日曜日(6)なら第1月曜日は翌日の1日、前月末日が月曜日(0)なら第1月曜日は翌週の7日になります。
つまり、第1月曜日は「7 - WEEKDAY ( [前月末日], 3 ) 」となるので、第n月曜日は「7*n - WEEKDAY ( [前月末日], 3 ) 」で算出できます。
春分の日と秋分の日
春分の日と秋分の日は、日付は固定でなく前年2月の官報で公表されます。
そうすると式設定できなさそうですが、ときの政権が勝手に決めているわけではなく天文学的な定義に基づき決まるので、原則式で求めることができます。
Excel界隈では昔から知られた式ですが、私には数式の解説はできません。
また、この数式で算出できるのは2099年までですが、私が死ぬまでは問題なく使えます(笑)。
春分の日は
=DATE([年],3,INT(20.8431+0.242194*([年]-1980)-INT(([年]-1980)/4)))
秋分の日は
=DATE([年],9,INT(23.2488+0.242194*([年]-1980)-INT(([年]-1980)/4)))
振替休日
祝日が日曜日のときに発生します。
原則として翌日(月曜日)が振替休日となりますが、翌日が休日(祝日)の場合繰り越していき休日があけたとき、すなわち(祝日)連休最終日の翌日が振替休日になります。
2000年から2100年まで現在の休日体系の場合、原則月曜日が振替休日にならない例外はゴールデンウイークのみに発生します。
ハッピーマンデーに対して振替休日が発生することはないので、日付指定と春分の日・秋分の日の下の行に振替休日行を挿入します。
連休となる5/3憲法記念日と5/4みどりの日の下には行を挿入しません。
設定式は、5/5こどもの日の下の行を除き
= IF ( WEEKDAY ( [祝日] ) = 1, [祝日] + 1, [表示したい文言] )
祝日が日曜日のときは必ず翌日の月曜日が振替休日です。
具体的には、セル B8 に対する振替休日であれば "= IF ( WEEKDAY ( B8 ) = 1, B8 + 1, "" ) " といった式になります。
日曜日でないときの [表示したい文言] はカレンダーとのかかわりも考えて設定します。
例ではカレンダーの日付に空白がないことを前提に「""」としていますが、カレンダーの日付に空白がある場合、XLOOKUP(VLOOKUP)関数などで祝日名を拾うときに空白日付に対して「振替休日」という祝日名を拾ってしまいます。
「""」でなく「0」など別の内容を検討してください。
また、祝日名にも式をセットして日曜日の場合のみ祝日名を表示させるようにセットする回避策で問題ないなら、それでもいいでしょう。
5/5こどもの日の下の行に設定する式ですが、
= IF ( OR( WEEKDAY ( [憲法記念日] ) = 1, WEEKDAY ( [みどりの日] ) = 1, WEEKDAY ( [こどもの日] ) = 1 ), [こどもの日] + 1, [表示したい文言] )
5/3憲法記念日または5/4みどりの日または5/5こどもの日のいずれかが日曜日のときは必ず5/6が振替休日です。
具体的には、こどもの日がセル B17 なら "= IF ( OR ( WEEKDAY ( B15 ) = 1, WEEKDAY ( B16 ) = 1, WEEKDAY ( B17 ) = 1 ), B17 + 1, "" ) " といった式になります。
国民の休日
前日と翌日が祝日となる平日は休日にするという決まりがあります。
原則これが起こりうるのはシルバーウイークのみです。
ただし過去には、前述した2019年に5/1が即位日として祝日になったため、ゴールデンウイークに2日の国民の休日が発生しています。
2100年までの秋分の日は、9/22か9/23のいずれかです。
つまり、少なくとも2100年までは原則敬老の日、秋分の日の順になります。
それを踏まえて、国民の休日用に敬老の日と秋分の日の間に1行追加します。
設定式は、
具体的には、敬老の日がセル B21 、秋分の日がセル B23 なら "= IF ( AND ( WEEKDAY ( B21 + 1 ) <> 1, B23 - B21 = 2 ), B21 + 1, "" ) " といった式になります。
敬老の日と秋分の日が2日違いでかつ敬老の日の翌日が日曜でなければ、敬老の日の翌日は国民の休日となります。
法定ではない休日
大晦日のように法定ではない休日を定義したい場合のため、別途追加できる欄も設けてします。
私のように年を表示していない場合は特にですが、「年」が間違ってしないか注意しましょう。
日付が合っていても年が異なっていると、カレンダーの仕掛けがうまく動作しない可能性があります。
まぁ、ここの部分を毎年メンテナンスしないといけない場合はこのようなテーブルを用意するメリットはないのですが。
ご質問は下の 「コメントを書く」 からお願いします。
ExcelやVBA全般に関わる質問で、比較的簡単にお答えできるものはできる限り回答したいと思います。
回答を公開でなくメールでやり取りしたいという場合は、その旨記載していただければ非公開で回答することも可能です。
有償での作業依頼は非公開にしますので、条件等をお知らせください。