【Excel VBA】4月始まりの年間カレンダー自動作成マクロをリファクタリング

昔こんなマクロを作ったのですが、当時はまだVBAを使えるようになったばかりの頃でした。

今見てみると「これはひどい」なコードでした。簡単にバグを起こしそうな感じです。

そういうわけで基本的な機能はそのまま、コードをリファクタリングしてみました。

スポンサーリンク

マクロの内容

サンプルファイルは下記のリンクからダウンロードしてください。ZIP圧縮しています。

こんな感じの年間のカレンダーがあるとします。年が変わると曜日も変わりますので全部書きかえるのはとてもめんどくさいということで自動化するマクロです。元々はトイレ掃除のチェック表用に作ったものでした。

「年間」シートの右上らへんにある「実行」ボタンを押すと、インプットボックスが出てくるので、そこに作成したい西暦を半角4桁の数字で入力します。

そしたらできあがりです。下の方に隠れて見えませんが、1~3月は翌年分です。

ついでに月間カレンダーがシート別にありまして、そっちも変わります。

VBA

Sub カレンダー作成()
    Const NENKAN_SHEET_NAME As String = "年間"  '年間シート名
    Dim thisYear As Variant                     '入力された西暦
    Dim firstWeekday As Integer                 '4月1日の曜日
    Dim monthLength As Integer                  '1か月の日数
    Dim setRow As Long                          '入力行
    Dim setCol As Long                          '入力列
    Dim isLeapYear As Boolean                   '閏年の判定
    Dim monthlySheetArray As Variant            '月間カレンダーのシート名を格納する配列
    
    '月間カレンダーのシート名を配列に格納する
    monthlySheetArray = Split("4月,5月,6月,7月,8月,9月,10月,11月,12月,1月,2月,3月", ",")
    
    '年度のカレンダーを作成するか入力
    thisYear = Application.InputBox("西暦を半角4桁の数字で入力してください。")
    
    'キャンセル時の処理
    If thisYear = False Then
        Exit Sub
    End If
    
    '西暦以外の文字列が入力されたら処理を中止する
    If IsDate(thisYear & "/4/1") = False Then
        MsgBox "西暦以外の文字列が入力されました。処理を中止します。"
        Exit Sub
    End If
    
    '次年度分の変数を用意
    nextYear = thisYear + 1
    
    '閏年を判定
    isLeapYear = False
    If nextYear Mod 400 = 0 Then
        isLeapYear = True
    ElseIf nextYear Mod 100 <> 0 And nextYear Mod 4 = 0 Then
        isLeapYear = True
    End If
    
    '年間カレンダーの中身をリセットする
    For i = 3 To 48 Step 15
        Worksheets(NENKAN_SHEET_NAME).Range(Cells(i, 1), Cells(i + 11, 23)).ClearContents
    Next
    
    '月間カレンダー各シートの中身をリセットする
    For i = 0 To 11
        Worksheets(monthlySheetArray(i)).Range("A3:G14").ClearContents
    Next i
    
    '年を入力
    With Worksheets(NENKAN_SHEET_NAME)
        .Range("A1").Value = thisYear & "年"
        .Range("A46").Value = nextYear & "年"

        '4月1日の曜日を取得、最初に入力する列を決定
        firstWeekday = Weekday(thisYear & "/04/01")
        setCol = firstWeekday

        '年間カレンダーを作成
        For i = 1 To 46 Step 15     'm月が書かれている行
            For j = 7 To 23 Step 8  '土曜日のある列
                setRow = i + 2

                '各月の日数を算出
                Select Case .Cells(i, j).Value
                    Case "4月", "6月", "9月", "11月"
                        monthLength = 30

                    Case "2月"
                        If isLeapYear = True Then
                            monthLength = 29
                        Else
                            monthLength = 28
                        End If

                    Case Else
                        monthLength = 31
                End Select

                '1か月分の日付を入力
                For k = 1 To monthLength
                    .Cells(setRow, setCol).Value = k
                    If setCol = j Then
                        setRow = setRow + 2
                        setCol = j - 6
                    Else
                        setCol = setCol + 1
                    End If
                    
                    If k = monthLength Then
                        If j = 23 Then
                            setCol = setCol - 16
                        Else
                            setCol = setCol + 8
                        End If
                    End If
                Next k
            Next j
        Next i
    End With
    
    '月間カレンダーを作成
    setCol = firstWeekday
    For i = 0 To 11
        With Worksheets(monthlySheetArray(i))
            '年を入力
            If i >= 9 Then
                .Range("F1").Value = nextYear & "年"
            Else
                .Range("F1").Value = thisYear & "年"
            End If
            
            '各月の日数を算出
            Select Case i
                Case 0, 2, 5, 7
                    monthLength = 30
                    
                Case 10
                    If isLeapYear = True Then
                        monthLength = 29
                    Else
                        monthLength = 28
                    End If
                    
                Case Else
                    monthLength = 31
                    
            End Select
            
            setRow = 3
            '各シートに1ヶ月分の日付を入力
            For j = 1 To monthLength
                .Cells(setRow, setCol).Value = j
                If setCol = 7 Then
                    setRow = setRow + 2
                    setCol = 1
                Else
                    setCol = setCol + 1
                End If
            Next j
        End With
    Next i
End Sub

コメント

コメントする前にお読みください

迷惑コメント防止のために初回のコメント投稿は承認制のため、投稿が反映されるまで少し時間がかかります。もちろん荒らしは承認しません。

教えて君やクレクレ君に対しては回答しませんのでご了承ください。