空腹おやじのログと備忘録

VBA(主にExcel)でいろいろな実験的な事とか、Linuxのコマンドとか設定とかについて忘れないように、あれこれと・・・

指定日が、月内で第何度目の何曜日かを求める(VBA)

最近、表題の処理を2件ほど、はてなブログで見かけた。
いずれの処理も、月始めから指定日までループ処理をしていたが、この手の処理は1週間(7日)の周期性があるので、それを利用してループ処理なしで求めてみた。

thom.hateblo.jp
b004nws862zx.hatenablog.com

抑えておくべきこと

第1の日曜日から土曜日は、毎月1日から7日にある。
第2の日曜日から土曜日は、毎月8日から15日にある。
以下同様

従って、

1~7
8~14
15~21
22~28
29~31

となる。

7日の周期で、週が1加算されていくので、7で割った商を使えばよい。
ただし、そのまま日を7で割ってしまっては求めたい値(週)は得られない。
7で割って商が1となる整数は、7から13である。そこで1から7を7から13に補正するため、6を加算した上で、7で割ることで目的の値が得られる。
これは商が2以上の場合でも同じである。

コード

Public Function 第N○曜日(ByVal dtTargetDate As Date) As String

    Const DAY_OF_WEEK As String = "日月火水木金土"

    Dim lNthWeek        As Long
    Dim sWeek           As String

    '第N
    lNthWeek = (Day(dtTargetDate) + 6) \ 7

    '曜日
    sWeek = Mid$(DAY_OF_WEEK, Weekday(dtTargetDate), 1)

    第N○曜日 = "第" & CStr(lNthWeek) & sWeek & "曜日"

End Function

第何週目の何曜日なのかの場合

基本は上の例と同じ。
違うのは、日に対する補正値。
上の例では、単純に6を加算すればよかったが、この場合には、第1土曜日が13(7で割って商が1になる最大の整数)になるようにすればよい。

しかし、第1土曜日が何日かによって補正値が変わってくる。

1日の曜日 第1土曜日の日 第1土曜日の日を13にするために必要な値
10
11
12

となることから、
第1土曜日の日+5+Weekday(1日の日付)
とすることで13を得る事が出来るので、目的の補正値が得られる。

コード

Public Function 第N週の○曜日(ByVal dtTargetDate As Date) As String

    Const DAY_OF_WEEK  As String = "日月火水木金土"

    Dim dtFirstDate     As Date
    Dim lCorrection     As Long
    Dim lNthWeek        As Long
    Dim sWeek           As String

    '指定日の月の1日
    dtFirstDate = DateAdd("d", -Day(dtTargetDate) + 1, dtTargetDate)

    '第N週計算のための補正値
    lCorrection = Weekday(dtFirstDate) + 5

    '第N週
    lNthWeek = (Day(dtTargetDate) + lCorrection) \ 7

    '曜日
    sWeek = Mid$(DAY_OF_WEEK, Weekday(dtTargetDate), 1)

    第N週の○曜日 = "第" & CStr(lNthWeek) & "週の" & sWeek & "曜日"

End Function

実行結果

確認用コード

Public Sub 第○曜日テスト()

    Dim d   As Date

    For d = #3/1/2019# To #3/31/2019#
        Debug.Print Format$(d, "yyyy/mm/dd");
        Debug.Print vbTab;
        Debug.Print 第N週の○曜日(d);
        Debug.Print vbTab;
        Debug.Print 第N○曜日(d)
    Next d

End Sub

結果

call 第○曜日テスト
2019/03/01 第1週の金曜日 第1金曜日
2019/03/02 第1週の土曜日 第1土曜日
2019/03/03 第2週の日曜日 第1日曜日
2019/03/04 第2週の月曜日 第1月曜日
2019/03/05 第2週の火曜日 第1火曜日
2019/03/06 第2週の水曜日 第1水曜日
2019/03/07 第2週の木曜日 第1木曜日
2019/03/08 第2週の金曜日 第2金曜日
2019/03/09 第2週の土曜日 第2土曜日
2019/03/10 第3週の日曜日 第2日曜日
2019/03/11 第3週の月曜日 第2月曜日
2019/03/12 第3週の火曜日 第2火曜日
2019/03/13 第3週の水曜日 第2水曜日
2019/03/14 第3週の木曜日 第2木曜日
2019/03/15 第3週の金曜日 第3金曜日
2019/03/16 第3週の土曜日 第3土曜日
2019/03/17 第4週の日曜日 第3日曜日
2019/03/18 第4週の月曜日 第3月曜日
2019/03/19 第4週の火曜日 第3火曜日
2019/03/20 第4週の水曜日 第3水曜日
2019/03/21 第4週の木曜日 第3木曜日
2019/03/22 第4週の金曜日 第4金曜日
2019/03/23 第4週の土曜日 第4土曜日
2019/03/24 第5週の日曜日 第4日曜日
2019/03/25 第5週の月曜日 第4月曜日
2019/03/26 第5週の火曜日 第4火曜日
2019/03/27 第5週の水曜日 第4水曜日
2019/03/28 第5週の木曜日 第4木曜日
2019/03/29 第5週の金曜日 第5金曜日
2019/03/30 第5週の土曜日 第5土曜日
2019/03/31 第6週の日曜日 第5日曜日


こちらも参考になります。(かなりオススメ)
www.waenavi.com