日付データから曜日と週数を取得

DatePart関数を使用して曜日の数値と週数を取得するコード、週数に関してのバグに関する注意

'本日の曜日数値を取得(日曜始点)
Debug.Print DatePart("w", Date)
'本日の曜日数値を取得(月曜始点)
Debug.Print DatePart("w", Date, vbMonday)
'本日の週数を取得
Debug.Print DatePart("ww", Date)
'本日の週数を取得(月曜始点)
Debug.Print DatePart("ww", Date, vbMonday)

週数と曜日数値を取得するには「DatePart」関数引数「interval」でそれぞれ「”w”」と「”ww”」を使用します

関数の書式

引数(太字は必須引数)
(interval, date, firstDayOfWeek, firstWeekOfYear)
戻り値の型 variant型(Integer)

関数の解説

関数の引数の1つ目と2つ目の解説は別の記事で行っています
(解説記事はこちらから)

引数の3つ目「firstDayOfWeek」週の始まりを何曜日にするかの設定です
既定では日曜日となっています

指定する際はVBAの定数を使用すると分かり易いです
ワークシート関数と同じように数値での指定をする場合は、日曜日=1でそこから順番に数値と並んでいますので、もし月曜日を始点にする場合は「2」もしくは「vbMonday」(定数)を指定します

ここに関しては計算する際の環境に合わせて任意に合わせてください
曜日数値を取得する際はここで設定した数値で返されるので、設定次第で返される曜日数値も変化する形になります

次に4つ目の引数「firstWeekOfYear」ですが、これは週数を取得する際に年の最初の週をどこにするかの設定です

まず、指定できる内容が3種類あります(「vbUseSystem」はどれかに当てはまるため割愛します)

「vbFirstJan1」は1月1日が週の始まりになります
「vbFirstFourDays」は4日以上ある週を始まりとします
「vbFirstFullWeek」は全ての曜日がある週を始まりとします

DatePart関数の引数の違いによる取得の違い
実際に取得してみた画像

文章では少しイメージしづらいので、取得したものを画像にしました

B列が1月1日から週の計算が始まる設定です
10行目の1月1日から1週目になっています、その前日は53週目ですね
これが既定の設定になりますので、引数を省略した場合の動きになります
ただ、これは1週間=7日にはならないことに注意が必要です
53週目は3日で、1週目は4日になっています
また2020年の第1週目の日~火曜日は存在しないことになりますので、週で業務を管理する際にはこれではうまくいかない可能性が高いですね

C列は後述します

D列は全ての曜日が含まれる週を第1週とします
その為、既定の始まりである最初の日曜日から週を計算する形になります
年が変わっても、週が変わるわけではないので週管理で考えると非常に分かり易いと思います

ただ、これでは年に対する考え方が全くなくなります
そこで使用するのが、C列の設定です
週の4日以上含む週を第1週目とする計算方法です

「vbFirstFourDays」のバグについて

C列の内容になりますが、ここでバグがあるため要注意です
新年に4日以上ある週を第1週とする場合、12/29(日)が本来であれば1週目1日目となります

画像の赤く塗られたセルの箇所になります
画像を確認してもらうと分かるように、「53」となり次の月曜日が「1」となっています
1月5日を確認して分かるように、ちゃんと週の始点は日曜日に指定されています

このバグはこの関数だけでなくFormat関数でも発生するようなので、そちらでも注意してください

この処理に対する対応策は、条件分岐により53を1に強制的に変更して取得する方法しかないようです

以下のページにこのバグの詳細が記載されています
「Format 関数または DatePart 関数で、先週の最後の月曜日の週番号を返すことができません」-MicrosoftOfficeトラブルシューティング