【簡単エクセル/Excel VBA マクロ】カレンダーを作成する|アプリ事例 #005【ファイルダウンロード可】



いつもありがとうございます。
ノンプログラマー向け「Excel VBA マクロ アプリ事例解説シリーズ」へようこそ。
本稿では、「カレンダーを作成するアプリ」をお届けいたします。
皆さんは、カレンダーを作成したいときはないでしょうか。例えば、勤務シフト表や当番表を作成するときなどです。
カレンダの作成を手作業で行うのは、非常に時間がかかりますし、ミスも起こりがちです。しかし、このような作業は、VBAを使えば簡単に自動化することができます。
にVBAで自分やコミュニティに合ったアプリを作成し、仕事量は半分に、成果は2倍にしていきましょう。初心者でも理解しやすいように、分かりやすく解説していきます。ぜひご覧ください。
VBAでカレンダを作成する方法

アプリの仕様
Excelシート上で、対象年月を指定してカレンダーを自動作成します。カレンダーは、新しいブックを作成し、そのシートに表示します。作成したブックは保存はせず、新規ブックとして開いたままにします。必要に応じて「名前を付けて保存」などの操作を手動で行うことを想定しています。
Excelシートの設計
まず、年月を指定するためのExcelワークシートを準備します。下図のようなワークシートを作成しましょう。メニューからマクロを実行するのは手間がかかるため、下図にあるような「カレンダー作成実行」ボタンも作成しておきます。このボタンにマクロを登録し、クリックするとマクロが動作するように設定します。マクロの登録手順については、後述します。

コードの実装

カレンダーを作成するコードと、その実行結果を示します。
Option Explicit
Sub CreateCalendar()
' 変数宣言
Dim this_wb As Workbook ' このワークブック
Dim this_ws1 As Worksheet ' this_wb のワークシート1
Dim new_wb As Workbook ' 新しく作成するワークブック
Dim new_ws1 As Worksheet ' new_wb のワークシート1
Dim new_window As Window ' new_wb のウィンドウ
Dim user_input_year As Long ' ユーザーが指定した年
Dim user_input_month As Long ' ユーザーが指定した月
Dim last_day_of_month As Long ' ユーザー名が指定した月の最終日
Dim column_index As Long ' 曜日に基づく列インデックス
Dim row_index As Long ' 行インデックス
Dim day_counter As Long ' 日数カウンター
Dim weekday_name As String ' 曜日名
Dim row_position As Long ' 枠線調整のための行の位置
' 定数設定
Const START_COLUMN As Long = 2 ' カレンダーの開始列
Const START_ROW As Long = 3 ' カレンダーの開始行
' 現在のワークブックとワークシートを取得
Set this_wb = ThisWorkbook
Set this_ws1 = this_wb.Worksheets(1)
' 新しいカレンダー用のワークブックとワークシートを作成
Set new_wb = Workbooks.Add
Set new_ws1 = new_wb.Worksheets(1)
' カレンダー作成対象の年と月をワークシートから取得
user_input_year = this_ws1.Cells(17, 4)
user_input_month = this_ws1.Cells(17, 5)
' カレンダーのタイトル(年と月)を新しいシートに書き込み
new_ws1.Cells(START_ROW - 1, START_COLUMN).Value = _
"'" & user_input_year & "年" & user_input_month & "月"
' カレンダ作成対象月の最終日を取得
last_day_of_month = Day( _
DateSerial(user_input_year, user_input_month + 1, 1) - 1 _
)
' 行インデックスの初期化
row_index = START_ROW
' 各日付をイテレーション
For day_counter = 1 To last_day_of_month
' 曜日名(例: 月、火、水...)を取得
weekday_name = WeekdayName( _
Weekday( _
DateSerial( _
user_input_year, user_input_month, day_counter _
), vbSunday _
), True _
)
' 曜日から列インデックスを計算(列の位置を設定)
column_index = Weekday( _
DateSerial( _
user_input_year, user_input_month, day_counter _
), vbSunday _
) + START_COLUMN - 1
' 日付と曜日をカレンダーに入力(土曜日は青字、日曜日は赤字で表示)
With new_ws1.Cells(row_index, column_index)
.Value = day_counter
If weekday_name = "土" Then .Font.Color = RGB(0, 112, 192)
If weekday_name = "日" Then .Font.Color = RGB(192, 0, 0)
End With
With new_ws1.Cells(row_index + 1, column_index)
.Value = weekday_name
If weekday_name = "土" Then .Font.Color = RGB(0, 112, 192)
If weekday_name = "日" Then .Font.Color = RGB(192, 0, 0)
End With
' 日付と曜日のセルを中央寄せに設定
Range( _
new_ws1.Cells(row_index, column_index), _
new_ws1.Cells(row_index + 3, column_index) _
).HorizontalAlignment = xlCenter
' もし土曜日なら次の行インデックスに移動
If Not day_counter = last_day_of_month Then
If column_index = START_COLUMN + 6 Then
row_index = row_index + 3
End If
End If
Next day_counter
' カレンダー全体に枠線を設定
Range( _
new_ws1.Cells(START_ROW, START_COLUMN), _
new_ws1.Cells(row_index + 2, START_COLUMN + 6) _
).Borders.LineStyle = xlContinuous
' カレンダーの水平枠線の調整
For row_position = START_ROW To row_index Step 3 ' 3行ごとに処理
' 日付と曜日の間の枠線を非表示に
Range( _
new_ws1.Cells(row_position, START_COLUMN), _
new_ws1.Cells(row_position + 1, START_COLUMN + 6) _
).Borders(xlInsideHorizontal).LineStyle = xlNone
' 曜日の下の枠線を薄い線に
Range( _
new_ws1.Cells(row_position + 1, START_COLUMN), _
new_ws1.Cells(row_position + 2, START_COLUMN + 6) _
).Borders(xlInsideHorizontal).Weight = xlHairline
Next row_position
' グリッド線を非表示にする
Set new_window = Application.Windows(new_wb.Name)
new_window.DisplayGridlines = False
End Sub
このコードを実行すると、下図のようなカレンダーが表示されます。


解説していきます。
Option Explicit
ここでは、Option Explicit
を有効にしています。この設定を使うと、変数を使用する前に必ず宣言が必要になります。これにより、変数のタイプミスや未定義変数によるエラーを防ぎ、コードの安全性と信頼性を高めることができます。
' 変数宣言
Dim this_wb As Workbook ' このワークブック
Dim this_ws1 As Worksheet ' this_wb のワークシート1
Dim new_wb As Workbook ' 新しく作成するワークブック
Dim new_ws1 As Worksheet ' new_wb のワークシート1
Dim new_window As Window ' new_wb のウィンドウ
Dim user_input_year As Long ' ユーザーが指定した年
Dim user_input_month As Long ' ユーザーが指定した月
Dim last_day_of_month As Long ' ユーザー名が指定した月の最終日
Dim column_index As Long ' 曜日に基づく列インデックス
Dim row_index As Long ' 行インデックス
Dim day_counter As Long ' 日数カウンター
Dim weekday_name As String ' 曜日名
Dim row_position As Long ' 枠線調整のための行の位置
ここでは、コード内で使用する変数が宣言されています。変数は Dim 変数名 As データ型
の構文で宣言します。これにより、各変数は As
以降で指定したデータ型のデータを格納できるようになります。
' 定数設定
Const START_COLUMN As Long = 2 ' カレンダーの開始列
Const START_ROW As Long = 3 ' カレンダーの開始行
ここでは、カレンダーがExcelワークシートのどの位置から始まるかを指定する「開始列」と「開始行」を定数として定義しています。
定数は、Const
キーワードを使って宣言します。START_COLUMN
はカレンダが始まる列番号を、START_ROWは
カレンダが始まる行番号を指定しています。
' 現在のワークブックとワークシートを取得
Set this_wb = ThisWorkbook
Set this_ws1 = this_wb.Worksheets(1)
ここでは、オブジェクト変数 this_wb
と this_ws1
に、それぞれワークブックオブジェクトThisWorkbook
とワークシートオブジェクトthis_wb.Worksheets(1)
を格納しています。
これにより、以降の処理で this_wb
を通じてワークブック全体を、this_ws1
を通じて特定のワークシートを操作できるようになります。
なお、ThisWorkbook
は、このコードが記述されているワークブック自身を指します。
' 新しいカレンダー用のワークブックとワークシートを作成
Set new_wb = Workbooks.Add
Set new_ws1 = new_wb.Worksheets(1)
ここでは、オブジェクト変数 new_wb
と new_ws1
に、それぞれ新しく作成したワークブックオブジェクトとそのワークシートオブジェクトを格納しています。
これにより、以降の処理で new_wb
を通じてワークブック全体を、new_ws1
を通じてワークシートを操作できるようになります。
Workbooks.Add
は、新しいワークブックを作成するためのメソッドです。このメソッドを使うことで、現在のブックとは別に新しいブックが開かれ、それを new_wb
に代入しています。
' カレンダー作成対象の年と月をワークシートから取得
user_input_year = this_ws1.Cells(17, 4)
user_input_month = this_ws1.Cells(17, 5)
ここでは、シートに入力されている年と月の情報をそれぞれ user_input_year
と user_input_month
という変数に代入しています。
this_ws1.Cells(17, 4)
は、シートの17行目の4列目、つまりセル D17
を表します。

同様に、this_ws1.Cells(17, 5)
は、セル E17
を表しています。
' カレンダーのタイトル(年と月)を新しいシートに書き込み
new_ws1.Cells(START_ROW - 1, START_COLUMN).Value = _
"'" & user_input_year & "年" & user_input_month & "月"
ここでは、カレンダーのタイトルとして「年」と「月」の情報を、新しく作成したシート(new_ws1
)に書き込んでいます。先ほど定義した定数START_COLUMN
、START_ROW
を活用して、書き込む位置を決めています。
' カレンダ作成対象月の最終日を取得
last_day_of_month = Day( _
DateSerial(user_input_year, user_input_month + 1, 1) - 1 _
)
ここでは、指定した年 (user_input_year
) と月 (user_input_month
) の最終日を取得し、last_day_of_month
に格納しています。DateSerial
関数を用いて翌月の1日を生成し、そこから1日引くことで、対象月の最終日を求めています。
この処理は、次のように動作しています。
DateSerial(user_input_year, user_input_month + 1, 1)
:
ここでは、DateSerial
関数を使用して翌月の1日を生成しています。具体的には、ここでは、ユーザーが入力した年 (user_input_year
) と月 (user_input_month
) に対して、月を1つ増やして「次の月の1日」を生成しています。
なお、DateSerial
関数の構文は、DateSerial(Year, Month, Day)
のようになっています。DateSerial(user_input_year, user_input_month + 1, 1) - 1 _
の-1の意味:
「次の月の1日」から1日引くことで、ユーザーが入力した月(user_input_month
)の最終日を取得しています。例えば、10月の最終日を知りたい場合は、11月1日から1日引くことで10月31日を得ることができます。Day
関数:Day
関数は、指定された日付から日(1〜31)を抽出する関数です。この一連のコードの中では、DateSerial
で得られた日付(例えば10月31日)の「日」の部分だけを取得、それをlast_day_of_month
に格納する役割を持っています。
' 行インデックスの初期化
row_index = START_ROW
' 各日付をイテレーション
For day_counter = 1 To last_day_of_month
' 曜日名(例: 月、火、水...)を取得
weekday_name = WeekdayName( _
Weekday( _
DateSerial( _
user_input_year, user_input_month, day_counter _
), vbSunday _
), True _
)
' 曜日から列インデックスを計算(列の位置を設定)
column_index = Weekday( _
DateSerial( _
user_input_year, user_input_month, day_counter _
), vbSunday _
) + START_COLUMN - 1
' 日付と曜日をカレンダーに入力(土曜日は青字、日曜日は赤字で表示)
With new_ws1.Cells(row_index, column_index)
.Value = day_counter
If weekday_name = "土" Then .Font.Color = RGB(0, 112, 192)
If weekday_name = "日" Then .Font.Color = RGB(192, 0, 0)
End With
With new_ws1.Cells(row_index + 1, column_index)
.Value = weekday_name
If weekday_name = "土" Then .Font.Color = RGB(0, 112, 192)
If weekday_name = "日" Then .Font.Color = RGB(192, 0, 0)
End With
' 日付と曜日のセルを中央寄せに設定
Range( _
new_ws1.Cells(row_index, column_index), _
new_ws1.Cells(row_index + 3, column_index) _
).HorizontalAlignment = xlCenter
' もし土曜日なら次の行インデックスに移動
If Not day_counter = last_day_of_month Then
If column_index = START_COLUMN + 6 Then
row_index = row_index + 3
End If
End If
Next day_counter
ここでは、指定された月の日付を順番に処理して、各日付とその曜日をカレンダーに入力するループ処理を行っています。
ひとつずつ解説していきます。
' 行インデックスの初期化
row_index = START_ROW
ここでは、カレンダーの開始位置を示す row_index
を START_ROW
に設定しています。これにより、日付の入力が適切な行から始まります。
' 各日付をイテレーション
For day_counter = 1 To last_day_of_month
ここでは、For
ステートメントを使い、1日から最終日 (last_day_of_month
) までの日付を順に処理しています。day_counter
は各日の日付を表します。
' 曜日名(例: 月、火、水...)を取得
weekday_name = WeekdayName( _
Weekday( _
DateSerial( _
user_input_year, user_input_month, day_counter _
), vbSunday _
), True _
)
ここでは、指定された年・月・日 (day_counter
) の曜日を取得し、カレンダーに反映させています。
この処理は、次のように動作しています。
DateSerial(user_input_year, user_input_month, day_counter)
で指定の日付を作成する。Weekday
関数でその日付の曜日を 数値(1=日, 2=月...) で取得する(vbSunday
により週の始まりは日曜に設定)。WeekdayName
関数で、その数値を対応する 曜日名(「月」「火」など) に変換する。True
を指定し、曜日名を短縮形(「月曜日」→「月」、「火曜日」→「火」)で取得する。
' 曜日から列インデックスを計算(列の位置を設定)
column_index = Weekday( _
DateSerial( _
user_input_year, user_input_month, day_counter _
), vbSunday _
) + START_COLUMN - 1
ここでは、取得した曜日をもとに、カレンダーのどの列に日付を入力するかを計算しています。
Weekday
関数で曜日の数値を取得し、START_COLUMN
に加算して列の位置を決定しています。START_COLUMN - 1
をすることで、適切な列位置に調整しています。
' 日付と曜日をカレンダーに入力(土曜日は青字、日曜日は赤字で表示)
With new_ws1.Cells(row_index, column_index)
.Value = day_counter
If weekday_name = "土" Then .Font.Color = RGB(0, 112, 192)
If weekday_name = "日" Then .Font.Color = RGB(192, 0, 0)
End With
ここでは、new_ws1.Cells(row_index, column_index)
で、計算された行 (row_index
) と列 (column_index
) に日付を入力しています。
合わせて、土曜日はフォントカラーを青(ColorIndex = 5
)、日曜日は赤(ColorIndex = 3
)に設定することで、カレンダー上で見やすくしています。
With new_ws1.Cells(row_index + 1, column_index)
.Value = weekday_name
If weekday_name = "土" Then .Font.Color = RGB(0, 112, 192)
If weekday_name = "日" Then .Font.Color = RGB(192, 0, 0)
End With
ここでは、日付の下の行に、その日の曜日を入力しています。こちらも、土曜日は青、日曜日は赤に設定しています。
' 日付と曜日のセルを中央寄せに設定
Range( _
new_ws1.Cells(row_index, column_index), _
new_ws1.Cells(row_index + 3, column_index) _
).HorizontalAlignment = xlCenter
ここでは、row_index
から3行分の範囲に対して、セルの内容を中央寄せに設定しています。これにより、カレンダーが整ったレイアウトになります。
' もし土曜日なら次の行インデックスに移動
If Not day_counter = last_day_of_month Then
If column_index = START_COLUMN + 6 Then
row_index = row_index + 3
End If
End If
ここでは、月の最終日でない土曜日が来た場合に、カレンダーの次の行へ移動する 処理を行っています。
If Not day_counter = last_day_of_month Then
は、現在の day_counter
が最終日でない場合にのみ、行の移動処理を実行するための条件です。これにより、不要な行移動を防ぎます。
If column_index = START_COLUMN + 6 Then
は、現在の曜日が土曜日かどうかを判定する条件です。START_COLUMN + 6
は土曜日の列を示し、これに一致する場合、row_index
を +3
して次の週の行へ移動します。これにより、カレンダーのレイアウトが崩れず、正しい位置に日付が配置されます。
' カレンダー全体に枠線を設定
Range( _
new_ws1.Cells(START_ROW, START_COLUMN), _
new_ws1.Cells(row_index + 2, START_COLUMN + 6) _
).Borders.LineStyle = xlContinuous
ここでは、カレンダー全体に枠線を設定しています。
Range(new_ws1.Cells(START_ROW, START_COLUMN), new_ws1.Cells(row_index + 2, START_COLUMN + 6))
では、カレンダーの最初のセルから最後のセルまでの範囲を指定しています。つまり、START_ROW
と START_COLUMN
はカレンダーの開始位置、row_index + 2
と START_COLUMN + 6
はカレンダーの終端位置を指しています。
' カレンダーの水平枠線の調整
For row_position = START_ROW To row_index Step 3 ' 3行ごとに処理
' 日付と曜日の間の枠線を非表示に
Range( _
new_ws1.Cells(row_position, START_COLUMN), _
new_ws1.Cells(row_position + 1, START_COLUMN + 6) _
).Borders(xlInsideHorizontal).LineStyle = xlNone
' 曜日の下の枠線を薄い線に
Range( _
new_ws1.Cells(row_position + 1, START_COLUMN), _
new_ws1.Cells(row_position + 2, START_COLUMN + 6) _
).Borders(xlInsideHorizontal).Weight = xlHairline
Next row_position
ここでは、カレンダーの水平枠線を調整しています。3行ごとに処理を行い、日付と曜日の間の枠線を非表示にした後、曜日の下の枠線を薄い線(xlHairline
)に設定します。これにより、カレンダーの見た目を整えています。
ひとつずつ解説すると、次のようになります。
' カレンダーの水平枠線の調整
For row_position = START_ROW To row_index Step 3 ' 3行ごとに処理
ここでは、カレンダーの行ごとに処理を行う For
ステートメントを開始しています。START_ROW
から row_index
まで、3行ずつ (Step 3
) 移動しながら処理を進めます。カレンダーでは1週間を3行で表しているため、この間隔で処理を行います。
' 日付と曜日の間の枠線を非表示に
Range( _
new_ws1.Cells(row_position, START_COLUMN), _
new_ws1.Cells(row_position + 1, START_COLUMN + 6) _
).Borders(xlInsideHorizontal).LineStyle = xlNone
ここでは、日付と曜日のセル範囲(row_position
から row_position + 1
まで)に対し、水平の内側枠線(xlInsideHorizontal
)を非表示にしています。LineStyle = xlNone
を指定することで、枠線が消えます。
' 曜日の下の枠線を薄い線に
Range( _
new_ws1.Cells(row_position + 1, START_COLUMN), _
new_ws1.Cells(row_position + 2, START_COLUMN + 6) _
).Borders(xlInsideHorizontal).Weight = xlHairline
次に、曜日の下のセル範囲(row_position + 1
から row_position + 2
まで)に対し、水平枠線を最も薄い線(xlHairline
)で描画しています。これにより、曜日とその下のセルの区切りが視覚的に整い、カレンダーがすっきり見えます。
' グリッド線を非表示にする
Set new_window = Application.Windows(new_wb.Name)
new_window.DisplayGridlines = False
ここでは、新しく作成したワークブックのワークシート(new_ws1
)のグリッド線を非表示にしています。
この処理は、次のように動作しています。
Set new_window = Application.Windows(new_wb.Name)
新しく作成したブック(new_wb
)のウィンドウオブジェクトを取得し、new_window
に格納します。これにより、新しいブックのウィンドウに対して設定を変更できるようになります。new_window.DisplayGridlines = False
取得したウィンドウのDisplayGridlines
プロパティをFalse
に設定し、シートのグリッド線(デフォルトのセルの境界線)を非表示にします。グリッド線を消すことで、カレンダーのレイアウトがすっきりと見やすくなります。

以上で、「コードの実装」の解説は終了です。ありがとうございました。
ボタンへのマクロの登録
次にボタンにマクロを登録する方法を解説します。
ボタンにマクロを登録し、このボタンをクリックすることによりマクロが実行されるようにします。これにより、毎回メニューからマクロを実行する手間が省け、作業効率が向上します。
アプリをコミュニティに配布するのであれば、ユーザーの使いやすさを考慮し、ボタン操作でマクロを実行できるようにすると親切です。

まず、ボタンの上で「右クリック」し、「マクロの登録」を選択します。

次のようなダイアログが表示されますので、該当のマクロ名(今回は、CreateCalendar)を選択し、「OK」を押下します。

以上でマクロの登録は完了です。
これで、ボタンをクリックするとマクロが動くようになりました。

以上で、「マクロの登録」の解説は終了です。ありがとうございました。
ファイルのダウンロードはこちら
本稿で使用したExcelファイルは、「note」の有料記事の中で提供しております。「note」は、誰でも気軽に記事を読んだり購入したりできるコンテンツプラットフォームです。
コードを自身のExcelファイルに実装していくのは、とても素晴らしいことですが、完成品をすぐに使いたい方や、実際のファイル内に実装されている様子をご覧になりたい方などには、便利な内容となっています。
このExcelファイルは、必要な構成要素をひとつにまとめた、シンプルで使いやすいオールインワンアプリです。また、装飾を最小限に抑え、どなたでも直感的に操作できる、クセのないデザインになっています。


ご興味のある方は、ぜひチェックしてみてください。途中までは無料で閲覧することが出来ます。
おわりに


ご覧いただきありがとうございました。
本稿では、「カレンダを作成するアプリ」の紹介をいたしました。
お問い合わせやご要望等ございましたら、「お問い合わせ/ご要望」またはコメントにて、ご連絡いただければ幸いでございます。
皆様の人生がより一層素晴らしいものになるよう、少しでもお役に立てれば幸いでございます。
なお、当サイトでは様々な情報を発信しております。もしよろしければ、トップページもご確認いただけると幸いでございます。
関連記事
本稿と関連の深い記事です。もしよろしければ、合わせてご活用ください。
- 【簡単エクセル/Excel VBA マクロ】Excel VBA マクロの全体像 | みんなの実用学 (jitsuyogaku.com)
- 【簡単エクセル/Excel VBA マクロ】通常使用編目次 | みんなの実用学 (jitsuyogaku.com)
- 【簡単エクセル/Excel VBA マクロ】ワンポイントテクニック編目次 | みんなの実用学 (jitsuyogaku.com)
- 【簡単エクセル/Excel VBA マクロ】アプリ事例編目次 | みんなの実用学 (jitsuyogaku.com)
VBAプログラミングスキルアップのための参考情報
ここでは参考図書を紹介いたしますが、これらに限らず自分に合うものを選ぶことが重要だと考えております。皆様の、より一層のご成功を心よりお祈りしております。
VBAプログラミングのスキルアップ
学習用としてもハンドブックとしても役立つ便利な書籍がこちらです。価格はやや高めですが、その内容は非常に充実しています。相応のスキルを身に付けるためには、こうしたしっかりとした書籍を一冊持っておくと良いでしょう。
入門書に関しては、どの書籍も大きな違いはありません。あまり迷うことに時間をかけるよりは、手頃なものを一冊選んでみると良いでしょう。VBAの入門書は数多く出版されていますので、興味がある方はぜひチェックしてみてください。
甲乙つけがたい場合、私はインプレス社の「いちばんやさしい」シリーズを選ぶことが多いです。
\チェックしてみよう/
\チェックしてみよう/
\チェックしてみよう/
VBAのプログラミング能力を客観的に証明したい場合には「VBAエキスパート試験」があります。この試験はVBAの知識を公式に認定するものです。VBAの総合的な能力獲得を目指す方に適しています。以下の公式テキストが販売されております。
プログラミングの一般教養
「独学プログラマー」というプログラミングの魅力を解説した書籍があります。これはVBAではなくPythonを題材としていますが、プログラミングの基本的な知識や思考法、仕事の進め方まで幅広く学べます。
こちらの記事でも紹介しております。もしよろしければご覧ください。
