和風スパゲティのレシピ

日本語でコーディングするExcelVBA

VBA課題004「カレンダー入力フォームを作ってみよう」回答コード

Excel・VBA総合コミュニティ「Excel-Fun.xls*」にて毎月出題される、
VBAの問題に対する私の回答ソースコードを掲載いたします。


今回掲載するコードは第3回課題共有会の課題でもあった、
カレンダー入力フォームを作ってみよう」問題です。
VBA課題004「カレンダー入力フォームを作ってみよう」

今回も読みやすさ重視で書いてみましたので、
よろしければご参考ください(´∀`)

課題の内容

今回はシンプルに
ユーザーフォームで表示したカレンダーから選択日付をセルに出力する
課題です。

シンプルだけに参加者の個性が試された問題でした(´∀`)


詳細は下記リンク内にある「課題説明」シートをご確認ください。


せっかくなので回答を見る前に皆さんも挑戦してみましょう。

一度自分が作ってから他の人のコードを見ることで、
学習効果が何倍にも高まります。

完成させなくても、出来る範囲で解くだけでも十分効果がありますので、
是非ともトライしてみてください!

課題共有会とは

ExcelVBAに関する1つのお題にみんなで回答し、
各自のコードを解説しあう勉強会です。


他者のコードを見る機会が少ないVBAユーザーにとって、
いろいろな手法・記法に触れることができる貴重な機会です。

もちろん聞き専での参加もできますので、
ご興味がある方はコミュニティを覗いてみてください。


今回の「カレンダー入力フォームを作ってみよう」に対する私以外の回答コードも公開されています。

これだけたくさんの方のソースコードを見れる機会はなかなかないと思いますので、
是非ともVBAの勉強にお役立ていただければと思います。


◇ 「カレンダー入力フォームを作ってみよう」の課題ファイルはこちら
Discord:★出題【VBA】#004 カレンダー入力フォームを作ってみよう


◇ 「カレンダー入力フォームを作ってみよう」への回答集はこちら
Discord:☆回答【VBA】#004 カレンダー入力フォームを作ってみよう


※上記はDiscord参加済みの方用のURLです
 未参加の方は下記からご参加ください!
www.limecode.jp

課題の回答ファイル

実際の回答ファイルはこちらをご覧ください。
(和風スパ)【VBA】004_カレンダー入力フォームを作ってみよう.xlsm

ソースコード

今回の回答はこんなフォームを表示するプログラムです。
カレンダー入力フォーム画像

フォームモジュール:UFカレンダー入力

UFカレンダー入力

Option Explicit

' UserFormカレンダー入力

Rem -------- 宣言セクション ----------
Private Clctコントロール As Collection

' 日付ボタンレイアウト
Const btn日付_開始位置_Top = 50
Const btn日付_開始位置_Left = 10
Const btn日付_Width = 25
Const btn日付_Height = 25
Const btn日付_間隔_Width = 3
Const btn日付_間隔_Height = 3
Const btn日付_BackColor_通常 = Color原色.Const btn日付_BackColor_土 = Color背景_薄色.Const btn日付_BackColor_日 = Color背景_薄色.Const btn日付_BackColor_祝 = Color背景_薄色.Const btn日付_BackColor_本日 = Color背景_濃色.Const btn日付_BackColor_別月 = Color背景_薄色.Const btn日付_BackColor_別月本日 = Color背景_薄色.Const btn日付_FontSize = 10
Const btn日付_FontName = "Meiryo UI"

' 曜日ボタンレイアウト
Const btn曜日_Height = 18
Const btn曜日_BackColor_平 = Color背景_濃色.Const btn曜日_BackColor_土 = Color背景_濃色.Const btn曜日_BackColor_日 = Color背景_濃色.Const btn曜日_FontSize = 8
Const btn曜日_FontName = "BIZ UDゴシック"

' 日付ボタン連動配列
Private DateArr日付ボタン() As Date

Rem -------- 目次 ----------
Private Sub 目次()

    ♯日付ボタンオブジェクト仕様
    ♯表示月の更新
    ♯各コントロールのコード
    ♯コンストラクタ
    ♯ボタンの初期設置

End Sub
Rem -------- 目次 ----------


Rem -------- 日付ボタンオブジェクト仕様 -----------------
Private Sub ♯日付ボタンオブジェクト仕様(): 目次: End Sub
Rem -----------------------------------------------------

' 7曜日×6週間のボタンを「オブジェクト名:Btn日付_R_C」で設置し、
' 同一レイアウトの配列に対象日を格納する
Private Function BtnName日付ボタン(R As Long, C As Long) As String
    BtnName日付ボタン = "Btn日付_" & R & "_" & C
End Function
Private Function GetDateボタン設定日(btn As MSForms.CommandButton) As Date
    Dim R As Long: R = GetRボタン(btn.Name)
    Dim C As Long: C = GetCボタン(btn.Name)

    If R > 0 And C > 0 Then
        GetDateボタン設定日 = DateArr日付ボタン(R, C)
    End If

End Function
Private Function GetRボタン(ボタン名 As String) As Long
    On Error Resume Next
    GetRボタン = Split(ボタン名, "_")(1)
End Function
Private Function GetCボタン(ボタン名 As String) As Long
    On Error Resume Next
    GetCボタン = Split(ボタン名, "_")(2)
End Function
Private Function BtnName曜日ボタン(C As Long) As String
    BtnName曜日ボタン = "Btn曜日_" & C
End Function


Rem ---------- ♯表示月の更新 -------------
Private Sub ♯表示月の更新(): 目次: End Sub
Rem ---------------------------------------

Sub 表示月を更新する(Optional y As Long = -1, Optional m As Long = -1)

    ' ymを渡して実行した場合はTextBoxの値をその値に変更して更新
    ' ymを省略して実行した場合はTextBoxの値で更新
    On Error Resume Next
    If y = -1 Then
        y = TextBox年.Text
    Else
        TextBox年.Text = y
    End If
    If m = -1 Then
        m = TextBox月.Text
    Else
        TextBox月.Text = m
    End If
    On Error GoTo 0

    ' ◇ 実行条件
    If m < 1 Or 12 < m Then Exit Sub
    If y < 1900 Or y > 2100 Then Exit Sub

    ' 初日の曜日からカレンダー左上セルの日付を取得
    Dim date当月初日 As Date
    date当月初日 = DateSerial(y, m, 1)
    Dim dateカレンダー初日 As Date
    dateカレンダー初日 = date当月初日 - Fx.Weekday(date当月初日, 3)

    ' △ 日付を42日分ループ
    Dim i As Long, R As Long, C As Long, date対象日 As Date
    For i = 1 To 6 * 7
        R = (i - 1) \ 7 + 1
        C = (i - 1) Mod 7 + 1
        date対象日 = dateカレンダー初日 + i - 1

        ' 日付を配列に格納
        DateArr日付ボタン(R, C) = date対象日

        ' 対象ボタンを取得
        Dim btn日付 As MSForms.CommandButton
        Set btn日付 = Me.Controls(BtnName日付ボタン(R, C))

        ' 日付を表示し各色を設定
        btn日付.Caption = Day(date対象日)
        btn日付.Font.Bold = True

        If Month(date対象日) <> m Then
            btn日付.Font.Size = btn日付_FontSize
            btn日付.Font.Bold = False
            If date対象日 = Date Then
                btn日付.BackColor = btn日付_BackColor_別月本日
            Else
                btn日付.BackColor = btn日付_BackColor_別月
            End If

        ElseIf date対象日 = Date Then
            btn日付.BackColor = btn日付_BackColor_本日

        ElseIf Dic祝日リスト.Exists(date対象日) = True Then
            btn日付.BackColor = btn日付_BackColor_祝

        ElseIf Fx.Text(date対象日, "aaa") = "土" Then
            btn日付.BackColor = btn日付_BackColor_土

        ElseIf Fx.Text(date対象日, "aaa") = "日" Then
            btn日付.BackColor = btn日付_BackColor_日

        Else
            btn日付.BackColor = btn日付_BackColor_通常
        End If

    Next ' ▽  日付を42日分ループ

    ' デバッグ用
    Call 二次元配列をセルに出力する(WSデバッグ.Range("A1"), DateArr日付ボタン)

End Sub


Rem -------- ♯各コントロールのコード ---------------
Private Sub ♯各コントロールのコード(): 目次: End Sub
Rem -------------------------------------------------

' 日付ボタン
Sub btn_Click_クラスCall(btn As MSForms.CommandButton)

    If GetDateボタン設定日(btn) = 0 Then Exit Sub

    If IsCellの表示形式が日付系(ActiveCell) Then
        ActiveCell.Value = GetDateボタン設定日(btn)
    Else
        MsgBox "日付セル以外に入力することはできません。"
    End If

End Sub

' スピンボタン
Private Sub SpinButton月更新_SpinUp()

    On Error Resume Next
    If TextBox月.Text = 12 Then
        Call 表示月を更新する(TextBox年.Text + 1, 1)
    Else
        Call 表示月を更新する(TextBox年.Text, TextBox月.Text + 1)
    End If

End Sub
Private Sub SpinButton月更新_SpinDown()

    On Error Resume Next
    If TextBox月.Text = 1 Then
        Call 表示月を更新する(TextBox年.Text - 1, 12)
    Else
        Call 表示月を更新する(TextBox年.Text, TextBox月.Text - 1)
    End If

End Sub

' 年月テキストボックス
Private Sub TextBox月_Change()
    Call 表示月を更新する
End Sub
Private Sub TextBox年_Change()
    Call 表示月を更新する
End Sub


Rem -------- ♯コンストラクタ ---------------
Private Sub ♯コンストラクタ(): 目次: End Sub
Rem -----------------------------------------


Private Sub UserForm_Initialize()

    ' 配列・コレクションの初期化
    ReDim DateArr日付ボタン(1 To 6, 1 To 7)
    Set Clctコントロール = New Collection

    ' ボタンの生成
    Call 曜日ボタンを設置する
    Call 日付ボタンを設置する

    ' 初期値として今月を表示
    Call 表示月を更新する(Year(Date), Month(Date))

End Sub


Rem -------- ♯ボタンの初期設置 ---------------
Private Sub ♯ボタンの初期設置(): 目次: End Sub
Rem -------------------------------------------

' 曜日ボタン
Private Sub 曜日ボタンを設置する()

    Dim C As Long
    For C = 1 To 7

        ' ボタンの設置
        Dim btn曜日 As MSForms.CommandButton
        Set btn曜日 = Me.Controls.Add("Forms.CommandButton.1", BtnName曜日ボタン(C))

        ' ボタンの書式設定
        With btn曜日
            .Font.Size = btn曜日_FontSize
            .Font.Bold = True
            .Font.Name = btn曜日_FontName
            .Width = btn日付_Width
            .Height = btn曜日_Height
            .Left = (C - 1) * (btn日付_Width + btn日付_間隔_Width) + btn日付_開始位置_Left
            .Top = btn日付_開始位置_Top

            .BackColor = btn日付_BackColor_通常

            Dim 曜日 As String
            曜日 = Format(#12/1/2019# + C, "aaa")

            .Caption = 曜日

            Select Case 曜日
            Case "土": .BackColor = btn曜日_BackColor_土
            Case "日": .BackColor = btn曜日_BackColor_日
            Case Else: .BackColor = btn曜日_BackColor_平
            End Select


            ' イベントの設置
            Dim cls As EvClassUFカレンダー入力
            Set cls = New EvClassUFカレンダー入力
            Set cls.btn = btn曜日
            Clctコントロール.Add cls

        End With

    Next

End Sub

' 日付ボタン
Private Sub 日付ボタンを設置する()

    Dim R As Long, C As Long
    For R = 1 To 6
        For C = 1 To 7

        ' ボタンの設置
        Dim btn日付 As MSForms.CommandButton
        Set btn日付 = Me.Controls.Add("Forms.CommandButton.1", BtnName日付ボタン(R, C))

            ' ボタンの書式設定
            With btn日付
                .Font.Size = btn日付_FontSize
                .Font.Bold = True
                .Font.Name = btn日付_FontName
                .BackColor = btn日付_BackColor_通常
                .Width = btn日付_Width
                .Height = btn日付_Height
                .Left = (C - 1) * (btn日付_Width + btn日付_間隔_Width) + btn日付_開始位置_Left
                .Top = (R - 1) * (btn日付_Height + btn日付_間隔_Height) + btn日付_開始位置_Top + btn曜日_Height + btn日付_間隔_Height


                ' イベントの設置
                Dim cls As EvClassUFカレンダー入力
                Set cls = New EvClassUFカレンダー入力
                Set cls.btn = btn日付
                Clctコントロール.Add cls

            End With
        Next
    Next

End Sub

クラスモジュール:EvClassUFカレンダー入力

Option Explicit

' カレンダー入力フォームイベント
Public WithEvents btn As MSForms.CommandButton

Private Sub btn_Click()
    Call UFカレンダー入力.btn_Click_クラスCall(btn)
End Sub

標準モジュール:UF_ユーザーフォーム表示

Option Explicit

Sub ★カレンダー起動()
    Call UFカレンダー入力.Show(vbModeless)
End Sub

標準モジュール:Ut_汎用関数

Option Explicit

Public Enum Colorテキスト色
    白 = 16777215= 0= 8421504= 255= 3243501= 49407= 5287936= 12611584= 10498160
End Enum
Public Enum Color背景_薄色
    白 = 16777215= 14277081= 14013951= 13886463= 13431551= 14348258= 16247773= 16771059
End Enum
Public Enum Color背景_濃色
    白 = 16777215= 12566463= 12040191= 10079487= 10088703= 11854022= 16307380= 16762328
End Enum
Public Enum Color原色
    白 = 16777215= 0= 8421504= 255= 49407= 65535= 5287936= 16711680= 10498160
End Enum

' セルが日付か判定
Function IsCellの表示形式が日付系(cell As Range) As Boolean

    Dim 表示形式 As String
    表示形式 = cell.NumberFormatLocal

    ' y か e か d を含むなら即True
    If InStr(表示形式, "y") > 0 Or InStr(表示形式, "e") > 0 Or InStr(表示形式, "d") > 0 Then
        IsCellの表示形式が日付系 = True
    
    ' mはあるがyedがない場合は、hかsがなければTrue
    ElseIf InStr(表示形式, "m") > 0 Then
        If InStr(表示形式, "h") = 0 And InStr(表示形式, "s") = 0 Then
            IsCellの表示形式が日付系 = True
        End If
    End If

End Function

' 祝日リスト
Function Dic祝日リスト() As Dictionary
    Static Dic As Dictionary
    
    If Not Dic Is Nothing Then
        Set Dic祝日リスト = Dic
        Exit Function
    End If
    
    Set Dic = New Dictionary
    
    Dic.Add #1/1/2020#, "元日"
    Dic.Add #1/13/2020#, "成人の日"
    Dic.Add #2/11/2020#, "建国記念の日"
    Dic.Add #2/23/2020#, "天皇誕生日"
    Dic.Add #2/24/2020#, "振替休日"
    Dic.Add #3/20/2020#, "春分の日"
    Dic.Add #4/29/2020#, "昭和の日"
    Dic.Add #5/3/2020#, "憲法記念日"
    Dic.Add #5/4/2020#, "みどりの日"
    Dic.Add #5/5/2020#, "こどもの日"
    Dic.Add #5/6/2020#, "振替休日"
    Dic.Add #7/23/2020#, "海の日"
    Dic.Add #7/24/2020#, "スポーツの日"
    Dic.Add #8/10/2020#, "山の日"
    Dic.Add #9/21/2020#, "敬老の日"
    Dic.Add #9/22/2020#, "秋分の日"
    Dic.Add #11/3/2020#, "文化の日"
    Dic.Add #11/23/2020#, "勤労感謝の日"
    Dic.Add #1/1/2021#, "元日"
    Dic.Add #1/11/2021#, "成人の日"
    Dic.Add #2/11/2021#, "建国記念の日"
    Dic.Add #2/23/2021#, "天皇誕生日"
    Dic.Add #3/20/2021#, "春分の日"
    Dic.Add #4/29/2021#, "昭和の日"
    Dic.Add #5/3/2021#, "憲法記念日"
    Dic.Add #5/4/2021#, "みどりの日"
    Dic.Add #5/5/2021#, "こどもの日"
    Dic.Add #7/22/2021#, "海の日"
    Dic.Add #7/23/2021#, "スポーツの日"
    Dic.Add #8/8/2021#, "山の日"
    Dic.Add #8/9/2021#, "振替休日"
    Dic.Add #9/20/2021#, "敬老の日"
    Dic.Add #9/23/2021#, "秋分の日"
    Dic.Add #11/3/2021#, "文化の日"
    Dic.Add #11/23/2021#, "勤労感謝の日"
    Dic.Add #1/1/2022#, "元日"
    Dic.Add #1/10/2022#, "成人の日"
    Dic.Add #2/11/2022#, "建国記念の日"
    Dic.Add #2/23/2022#, "天皇誕生日"
    Dic.Add #3/21/2022#, "春分の日"
    Dic.Add #4/29/2022#, "昭和の日"
    Dic.Add #5/3/2022#, "憲法記念日"
    Dic.Add #5/4/2022#, "みどりの日"
    Dic.Add #5/5/2022#, "こどもの日"
    Dic.Add #7/18/2022#, "海の日"
    Dic.Add #8/11/2022#, "山の日"
    Dic.Add #9/19/2022#, "敬老の日"
    Dic.Add #9/23/2022#, "秋分の日"
    Dic.Add #10/10/2022#, "スポーツの日"
    Dic.Add #11/3/2022#, "文化の日"
    Dic.Add #11/23/2022#, "勤労感謝の日"
    Dic.Add #1/1/2023#, "元日"
    Dic.Add #1/2/2023#, "振替休日"
    Dic.Add #1/9/2023#, "成人の日"
    Dic.Add #2/11/2023#, "建国記念の日"
    Dic.Add #2/23/2023#, "天皇誕生日"
    Dic.Add #3/21/2023#, "春分の日"
    Dic.Add #4/29/2023#, "昭和の日"
    Dic.Add #5/3/2023#, "憲法記念日"
    Dic.Add #5/4/2023#, "みどりの日"
    Dic.Add #5/5/2023#, "こどもの日"
    Dic.Add #7/17/2023#, "海の日"
    Dic.Add #8/11/2023#, "山の日"
    Dic.Add #9/18/2023#, "敬老の日"
    Dic.Add #9/23/2023#, "秋分の日"
    Dic.Add #10/9/2023#, "スポーツの日"
    Dic.Add #11/3/2023#, "文化の日"
    Dic.Add #11/23/2023#, "勤労感謝の日"
    Dic.Add #1/1/2024#, "元日"
    Dic.Add #1/8/2024#, "成人の日"
    Dic.Add #2/11/2024#, "建国記念の日"
    Dic.Add #2/12/2024#, "振替休日"
    Dic.Add #2/23/2024#, "天皇誕生日"
    Dic.Add #3/20/2024#, "春分の日"
    Dic.Add #4/29/2024#, "昭和の日"
    Dic.Add #5/3/2024#, "憲法記念日"
    Dic.Add #5/4/2024#, "みどりの日"
    Dic.Add #5/5/2024#, "こどもの日"
    Dic.Add #5/6/2024#, "振替休日"
    Dic.Add #7/15/2024#, "海の日"
    Dic.Add #8/11/2024#, "山の日"
    Dic.Add #8/12/2024#, "振替休日"
    Dic.Add #9/16/2024#, "敬老の日"
    Dic.Add #9/22/2024#, "秋分の日"
    Dic.Add #9/23/2024#, "振替休日"
    Dic.Add #10/14/2024#, "スポーツの日"
    Dic.Add #11/3/2024#, "文化の日"
    Dic.Add #11/4/2024#, "振替休日"
    Dic.Add #11/23/2024#, "勤労感謝の日"
    Dic.Add #1/1/2025#, "元日"
    Dic.Add #1/13/2025#, "成人の日"
    Dic.Add #2/11/2025#, "建国記念の日"
    Dic.Add #2/23/2025#, "天皇誕生日"
    Dic.Add #2/24/2025#, "振替休日"
    Dic.Add #3/20/2025#, "春分の日"
    Dic.Add #4/29/2025#, "昭和の日"
    Dic.Add #5/3/2025#, "憲法記念日"
    Dic.Add #5/4/2025#, "みどりの日"
    Dic.Add #5/5/2025#, "こどもの日"
    Dic.Add #5/6/2025#, "振替休日"
    Dic.Add #7/21/2025#, "海の日"
    Dic.Add #8/11/2025#, "山の日"
    Dic.Add #9/15/2025#, "敬老の日"
    Dic.Add #9/23/2025#, "秋分の日"
    Dic.Add #10/13/2025#, "スポーツの日"
    Dic.Add #11/3/2025#, "文化の日"
    Dic.Add #11/23/2025#, "勤労感謝の日"
    Dic.Add #11/24/2025#, "振替休日"
    Dic.Add #1/1/2026#, "元日"
    Dic.Add #1/12/2026#, "成人の日"
    Dic.Add #2/11/2026#, "建国記念の日"
    Dic.Add #2/23/2026#, "天皇誕生日"
    Dic.Add #3/20/2026#, "春分の日"
    Dic.Add #4/29/2026#, "昭和の日"
    Dic.Add #5/3/2026#, "憲法記念日"
    Dic.Add #5/4/2026#, "みどりの日"
    Dic.Add #5/5/2026#, "こどもの日"
    Dic.Add #5/6/2026#, "振替休日"
    Dic.Add #7/20/2026#, "海の日"
    Dic.Add #8/11/2026#, "山の日"
    Dic.Add #9/21/2026#, "敬老の日"
    Dic.Add #9/22/2026#, "振替休日"
    Dic.Add #9/23/2026#, "秋分の日"
    Dic.Add #10/12/2026#, "スポーツの日"
    Dic.Add #11/3/2026#, "文化の日"
    Dic.Add #11/23/2026#, "勤労感謝の日"
    
    Set Dic祝日リスト = Dic
    
End Function

' 二次元配列 → セル
Sub 二次元配列をセルに出力する(出力始点セル As Range, Arr出力配列 As Variant)

    出力始点セル.Resize(Count配列の要素数(Arr出力配列, 1) _
                              , Count配列の要素数(Arr出力配列, 2)).Value = Arr出力配列

End Sub

' 配列要素数の取得
Function Count配列の要素数(Arr, Optional 次元 = 1) As Long
    Count配列の要素数 = UBound(Arr, 次元) - LBound(Arr, 次元) + 1
End Function

' WorksheetFunctionの短縮取得
Function Fx() As WorksheetFunction
    Set Fx = WorksheetFunction
End Function

コードの解説

目的のフォームがこちら↓でしたが、
カレンダー入力フォーム画像

フォームモジュールの設定がこちら↓であることを見てわかる通り、
UFカレンダー入力

今回は「コントロール(ボタン)の動的配置」をテーマに取り組みました。

↓のコードでユーザーフォームを立ち上げるごとにボタンを生成しています。

For R = 1 To 6
    For C = 1 To 7

        ' ボタンの設置
        Dim btn日付 As MSForms.CommandButton
        Set btn日付 = Me.Controls.Add("Forms.CommandButton.1", BtnName日付ボタン(R, C))


この動的生成のやり方を解説しだすとそれだけで1記事になっちゃうので、
ここでは割愛させてください。


動的生成と聞くと「ボタン数が変動する場合の対応」が目的に聞こえますが、
今回は「6×7のボタンが整列したカレンダー」ですのでボタン配置は静的です。

ではなぜ動的生成を用いたかと言いますと、
デザインの調整をかなり楽にできるから」が目的でした。


ユーザーフォームのコントロールをたくさん(今回は49個)並べると、
余白を少し増やしたり、色を少し変更するだけで結構面倒な作業が発生します。

2列目を1グリッド右に、3列目を2グリッド右に、、、といった作業ですね。


これを動的生成にしたことで、フォームモジュール上部の定数群

' 日付ボタンレイアウト
Const btn日付_開始位置_Top = 50
Const btn日付_開始位置_Left = 10
Const btn日付_Width = 25
Const btn日付_Height = 25
Const btn日付_間隔_Width = 3
Const btn日付_間隔_Height = 3
Const btn日付_BackColor_通常 = Color原色.Const btn日付_BackColor_土 = Color背景_薄色.Const btn日付_BackColor_日 = Color背景_薄色.Const btn日付_BackColor_祝 = Color背景_薄色.Const btn日付_BackColor_本日 = Color背景_濃色.Const btn日付_BackColor_別月 = Color背景_薄色.Const btn日付_BackColor_別月本日 = Color背景_薄色.Const btn日付_FontSize = 10
Const btn日付_FontName = "Meiryo UI"

これらの値をいじるだけで、ボタンの大きさや余白、色を設定できます。


もうちょっと小さめにしたいなとか、もうちょっと色を濃くとか、
そのあたりの試行錯誤のスピードがかなり上がるというのがメリットです。


今回のように規則正しく並んだユーザーフォームのデザインを調整するときにも、
コントロールの動的配列はなかなか便利ですので気が向いたら勉強してみてください。


最後におまけになりますが、今回新しい手法を試してみました。

それがこちら↓の目次機能になります。

Rem -------- 目次 ----------
Private Sub 目次()

    ♯日付ボタンオブジェクト仕様
    ♯表示月の更新
    ♯各コントロールのコード
    ♯コンストラクタ
    ♯ボタンの初期設置

End Sub
Rem -------- 目次 ----------


Rem -------- 日付ボタンオブジェクト仕様 -----------------
Private Sub ♯日付ボタンオブジェクト仕様(): 目次: End Sub
Rem -----------------------------------------------------

 
これは単純に「冒頭の目次と各見出しでお互いにCallし合っておく」ことで、
Shift+F2を使った移動機能」をクラスモジュールに実装したものです。

Private Subとありますが実際にはプログラム(実行コード)ではありません。


クラスモジュールはモジュール分割ができないためコード量が多くなりがちで、
それぞれコード群のまとまりができやすいモジュールです。

例えばProperty Get群とか、○○処理をするためのプロシージャ群とか。


そいう言ったコードに見出しもどきのダミープロシージャを置いておくことで、
Shift+F2を使ってコード群の間を移動できるようにしています。


さらにこれらのプロシージャ名を記号「♯」で始めたことで、
コードウィンドウ上部選択肢で上に来てくれるため、ここからも移動ができます。
コードウィンドウ上選択肢

実行しないプロシージャを作るという一風変わった実装ですが、
使ってみたらなかなか便利でしたので気に入ったら採用してみてください。



ちなみに「♯」は音楽記号のシャープです。

Shift+3で入力できる「#:ナンバーサイン」は型指定文字のため、
使うとエラーとなりますのでご注意ください。


そうまでしてわざわざ「♯」を使っているのは、
マークダウン形式の見出し記号が#だから」です。

マークダウンに慣れている方は、すごく見出しっぽく見えるのではないでしょうか?


ということで、この記号に♯をつかっているのは完全に私の好みなので、
皆さんが実装する場合は別にどんな名前にしても問題ありません。

しっくりくる名前を模索してみてください。


この目次機能の実装アイデアはいきさんから、
命名のアイデアはゅぇ。さんからいただきました!


面白いアイデアをありがとうございました(´∀`)