いきなり答える備忘録

Google Workspace・Microsoft 365・LibreOfficeなどに関するメモ

(Excel)1か月分の平日の日付を自動入力する

 Excelで関数を使い、指定された月のすべての平日(土日祝日以外)の日付を1列に表示する方法についてです。
 各セルに式を配置する方法と、SEQUENCE関数を使って1つの式で出力する方法を紹介します。

出力の内容と表示形式の設定について

 まずは出力する内容についてです。
 B3,C3セルにはそれぞれ年,月の値が入力されて与えられます。また、E列には祝日リストが設置されています。
 これらのデータに基づき、B6セル以降に関数を入力して指定月のすべての平日(土日祝日以外)を表示させるものとします。
 画像は入力を行った後の様子ですが、結果が理解しやすいようにあらかじめ日付に曜日を併記する表示形式を適用しています。

 この表示形式の設定の方法については次の記事で紹介しています。

www.officeisyours.com

各セルに式を入力する方法

 具体的に1か月分の平日を求める方法の1つ目です。
 まずは最初の日付欄であるB6セルに次のような式を入力します。

 B6セル

=WORKDAY(DATE(B3,C3,0),1,E3:E5)

 「DATE(B3,C3,0)」の部分は単純に解釈すると「指定月の0日目」ですが、これにより「指定月の前月の末日」が求められます。これとWORKDAY関数を組み合わせて「指定月の前月の末日からみた次の平日」つまり指定月の最初の平日を求めています。
 2023年10月1日は日曜日ですので、最初の平日として10月2日が表示されているのがわかります。



 続いて1つ下のB7セルに次のように入力します。

 B7セル

=IFS(B6="","",DAY(WORKDAY(B6,1,E$3:E$5))<DAY(B6),"",TRUE,WORKDAY(B6,1,E$3:E$5))

 ちょっと長いですがこの式は次のように機能します。

  1. 1つ上のセルが空文字列であれば空文字列を出力する
  2. 「1つ上の日付からみた次の平日の『日』の値」が「1つ上の日付の『日』の値」より小さければ(つまり月をまたいで翌月になろうとしていたら)空文字列を出力する
  3. 上記のいずれにも該当しなければ「1つ上の日付の次の平日の日付」を出力する
 この式を下方のセルにコピーするとき祝日リストへの参照がズレないように、絶対参照($)を含む式としています。



 そしてB7セルだけを選択し、セルの右下のフィルハンドル(小さい四角)を下方にドラッグします。

 


 これで各セルに平日が並んで表示されます。土日だけでなく祝日である10月9日がスキップされているのがわかります。
 もちろん年、月の指定を変更すると表示される内容も変化します。

 


 上記の関数のはたらきにより、いくら下方のセルにドラッグ(コピー)しても翌月の日付は表示されません。
 ただしこの例では罫線をB6~B28の23個のセルに表示し、ドラッグもB28セルで止めています。これは1か月の平日が最大23日(祝日がなく31日まである12月が月曜から始まる場合)であるためです。

1つの式ですべての日付を求める方法

 連番を生成するSEQUENCE関数の機能を利用して1つの式だけで1か月分の平日を求めることができます。
 指定月を変更すれば出力される日数も変化し、余分なセルが出力されません。

 B6セル

=LET(d,SEQUENCE(DAY(DATE(B3,C3+1,0)),,DATE(B3,C3,1)),
FILTER(d,NETWORKDAYS(d,d,E3:E5))
)

 SEQUENCE関数の第1引数(生成する行数)の「DAY(DATE(B3,C3+1,0))」は指定月の日数です。単純にみると「指定月の翌月の0日目が何日か」ですが結果的にそうなります。第3引数(初期値)は「DATE(B3,C3,1)」で、これは指定月の1日の日付を意味します。
 このSEQUENCE関数により指定月の1日から末日までの日付が一括して得られるのでLET関数で「d」と名付け、あとはFILTER関数を使い「d」のうち平日であるものだけを抽出しています。
 平日かどうかの判定にNETWORKDAYS関数を用いています。第1引数(開始日)と第2引数(終了日)に同じ日付を指定し、その期間(1日間)に含まれる平日の日数が1であればその日付は平日、0であれば土日祝日であるという理屈です。

 ちなみにNETWORKDAYS関数の第1引数と第2引数にセル範囲を指定してもスピルせずエラーになるのですが、上記のようにLET関数を使えばうまくいくようです。

「今月1か月分の平日」を求める場合

 上記の各セルに式を入力する方法において、最初の平日(B6セル)を次のような式で求めれば「今月1か月の平日」が求められます。2日目(B7セル)以降の式は上記例のままでOKです。

 B6セル

=WORKDAY(EOMONTH(TODAY(),-1),1,E3:E5)

 「EOMONTH(TODAY(),-1)」で先月末日を求めています。年,月の値が与えられている場合はDATE関数で前月末日を求める方が簡単ですが、日付から前月末日を求める場合はEOMONTH関数を使った方が短く済みます(使い分けるのもややこしいですが)。
 ちなみに「TODAY()」を「NOW()」に代えてもOKです(次の例も同様)。



 1つの式で済ませる場合は次のような式に代えればOKです。

 B6セル

=LET(d,SEQUENCE(DAY(EOMONTH(TODAY(),0)),,EOMONTH(TODAY(),-1)+1),
FILTER(d,NETWORKDAYS(d,d,E3:E5))
)

 「今月の1日」と「今月の日数」を求めるのにTODAY関数を使っています。