Excel VBAでカレンダーを作るとき、設定値を入力する「情報シート」と、完成したカレンダーを表示する「結果シート」を分けておくと管理しやすくなります。初心者がつまずきやすいのが、Sheet2に入力した月や月末日の情報をSheet1のマクロから取得する方法です。
別シートのセルを参照すること自体は難しくありません。基本はWorksheets("シート名").Range("A1").Valueのように、どのワークシートの、どのセルなのかを明示します。
この記事では、2026年度の月と最終日の情報がSheet2にあり、実行ボタンを押すとSheet1へ日曜日から土曜日のカレンダーを表示するケースを例に、できるだけ単純なVBAコードで解説します。なお、添付画像の具体的なセル番地が分からない場合にも応用できるよう、セル配置は例として示します。
まずSheet1とSheet2の役割を整理する
今回のようなExcelでは、Sheet1を「結果シート」、Sheet2を「情報シート」と考えると分かりやすくなります。Sheet2にはカレンダーを作るための条件を入力し、Sheet1にはVBAで計算した結果を表示します。
例えばSheet2を次のような構成にしたとします。
| セル | 内容 | 入力例 |
|---|---|---|
| A2 | 年 | 2026 |
| B2 | 月 | 4 |
| C2 | 最終日 | 30 |
Sheet1では、例えばA2:G2に「日・月・火・水・木・金・土」という曜日を配置し、A3:G8あたりへ日付を出力します。実際のブックで配置が違う場合は、コード中のセル番地だけ変更すれば対応できます。
別のWorksheetのセルをVBAで取得する基本
Sheet2の情報を引用するという部分は、VBAではワークシートを指定してセルの値を取得するだけです。例えばSheet2のB2に入力された月を取得するなら、次のように書けます。
Dim monthValue As Long
monthValue = Worksheets("Sheet2").Range("B2").Value
年ならA2、最終日ならC2から同じように取得できます。
Dim yearValue As Long
Dim monthValue As Long
Dim lastDay As Long
yearValue = Worksheets("Sheet2").Range("A2").Value
monthValue = Worksheets("Sheet2").Range("B2").Value
lastDay = Worksheets("Sheet2").Range("C2").Value
ポイントは、Rangeだけを書くのではなくWorksheetsを付けて参照元を明確にすることです。これならSheet1が選択されている状態でもSheet2の値を取得できます。
初心者向け:Sheet2を読み込んでSheet1へカレンダーを作るコード
実際のカレンダーでは、「1日が何曜日なのか」を調べ、その位置から1、2、3……と月末まで配置します。日曜始まりならVBAのWeekday関数を利用すると簡単です。
次のコードでは、Sheet2のA2を年、B2を月、C2を最終日として取得し、Sheet1のA3:G8へ日付を表示します。
Sub カレンダー作成()
Dim wsResult As Worksheet
Dim wsInfo As Worksheet
Dim yearValue As Long
Dim monthValue As Long
Dim lastDay As Long
Dim firstDate As Date
Dim startPos As Long
Dim d As Long
Dim pos As Long
Dim rowNo As Long
Dim colNo As Long
Set wsResult = ThisWorkbook.Worksheets("Sheet1")
Set wsInfo = ThisWorkbook.Worksheets("Sheet2")
yearValue = wsInfo.Range("A2").Value
monthValue = wsInfo.Range("B2").Value
lastDay = wsInfo.Range("C2").Value
firstDate = DateSerial(yearValue, monthValue, 1)
startPos = Weekday(firstDate, vbSunday)
wsResult.Range("A3:G8").ClearContents
For d = 1 To lastDay
pos = (startPos - 1) + (d - 1)
rowNo = 3 + (pos \ 7)
colNo = 1 + (pos Mod 7)
wsResult.Cells(rowNo, colNo).Value = d
Next d
End Sub
これを標準モジュールに入れて実行すると、対象月の1日が正しい曜日の列に入り、その後は土曜日まで進むと次の行の日曜日へ移動します。
コードがどのように動いているのか
最初のSetでは、使用する2枚のワークシートを変数へ入れています。これにより、その後は長いWorksheets("Sheet2")を何度も書かず、wsInfoだけで情報シートを指定できます。
Set wsResult = ThisWorkbook.Worksheets("Sheet1")
Set wsInfo = ThisWorkbook.Worksheets("Sheet2")
続いて、Sheet2の設定値を読み込みます。
yearValue = wsInfo.Range("A2").Value
monthValue = wsInfo.Range("B2").Value
lastDay = wsInfo.Range("C2").Value
例えばA2が2026、B2が4、C2が30なら、「2026年4月、最終日は30日」という情報がVBAの変数に入ります。
1日を正しい曜日へ配置する仕組み
DateSerialでは年・月・日から実際の日付を作れます。2026年4月なら、DateSerial(2026, 4, 1)によって2026年4月1日を作ります。
firstDate = DateSerial(yearValue, monthValue, 1)
startPos = Weekday(firstDate, vbSunday)
WeekdayにvbSundayを指定すると、日曜日を1、月曜日を2、火曜日を3……土曜日を7として曜日を取得できます。2026年4月1日は水曜日なので、この場合は水曜日の列から「1」が始まります。
その後、Mod 7で列を計算し、\ 7で何週目の行にするかを計算しています。これによって日曜日から土曜日までの7列を繰り返すカレンダーになります。
最終日はSheet2に入力しなくても自動計算できる
課題として「Sheet2にある最終日を使用する」と指定されているならC2の値を使用すればよいですが、通常のカレンダープログラムなら月末日はVBAで自動計算できます。
例えば次の1行で対象月の最終日を取得できます。
lastDay = Day(DateSerial(yearValue, monthValue + 1, 0))
2026年2月なら28、2026年4月なら30、2026年8月なら31というように自動判定されます。うるう年についても日付計算に任せられるため、実用的なカレンダーではこちらの方法が便利です。
ただし、「情報シートに入力された月と最終日を使用する」という学習課題であれば、勝手に仕様を変更せず、まずはSheet2の値を読み込む形で完成させるのがよいでしょう。
「2026年度」と「2026年」は違うので注意
カレンダーを作る際に注意したいのが「2026年度」という表現です。一般的な年度を意味しているなら、2026年度は2026年4月から2027年3月までとなるため、1~3月は西暦年が2027になります。
例えば「年度=2026」「月=2」と入力したときに2026年2月として計算すると、2026年度の2月にはなりません。2026年度の2月なら2027年2月です。
年度形式で12か月分を作る課題なら、1~3月について年を1増やす処理が必要です。単純に2026年1月~12月のカレンダーを作るだけなら、この処理は不要です。
実行ボタンからマクロを動かす方法
ワークシート上に「実行」ボタンを置く場合は、ボタンに先ほどのカレンダー作成マクロを登録します。フォームコントロールのボタンなら、ボタンを配置した際に表示されるマクロ一覧から「カレンダー作成」を選択できます。
これでSheet2の月を変更して実行ボタンを押すたびに、Sheet1のカレンダーが作り直されます。コード内でClearContentsを実行しているため、前回の31日などが残ることも防げます。
例えば4月から2月へ変更した場合、以前表示されていた29~31などが残ってしまうとカレンダーとして不正確になります。新しい日付を書く前に表示範囲を消す処理は重要です。
シート名が「結果シート」「情報シート」ならコードも変更する
Excel画面下部のシート名が実際に「結果シート」「情報シート」になっている場合は、コードもその名前に合わせます。
Set wsResult = ThisWorkbook.Worksheets("結果シート")
Set wsInfo = ThisWorkbook.Worksheets("情報シート")
ここでよくある初心者のミスが、VBA上のオブジェクト名とシートタブに表示されている名前を混同することです。Worksheets("情報シート")という書き方では、基本的にExcelのシートタブに表示されている名前を指定します。
また、マクロを保存する場合は通常の.xlsxではなく、マクロ有効ブックの.xlsm形式で保存します。せっかく作ったVBAを失わないよう注意しましょう。
Sheet2を参照するときに起こりやすいエラー
「インデックスが有効範囲にありません」などのエラーが出る場合は、まずシート名を確認します。「Sheet2」と書いているのに実際のシート名が「情報」なら、そのままでは見つけられません。
また、月のセルに「4月」という文字列が入っているのか、数値の4が入っていて表示形式によって「4月」に見えているのかでも扱いが変わります。初心者向けには、年を2026、月を4、最終日を30のように数値として入力しておくとコードを単純にできます。
さらにRange("B2")だけのような記述を多用すると、その時点でアクティブなシートが参照されてしまうことがあります。今回のように複数シートを扱う場合は、wsInfo.Range("B2")、wsResult.Range("A3:G8")のようにシートを明示する習慣を付けるとミスを減らせます。
まとめ:別シート参照はWorksheetsとRangeを組み合わせればよい
Excel VBAでSheet2の情報をSheet1の処理に使用する基本形は、Worksheets("Sheet2").Range("B2").Valueです。複数回参照する場合はWorksheet型の変数を用意し、Set wsInfo = ThisWorkbook.Worksheets("Sheet2")としておくとコードが読みやすくなります。
カレンダーについては、Sheet2から年・月・最終日を取得し、DateSerialで1日の日付を作成、Weekday(..., vbSunday)で開始曜日を求めれば、日曜日から土曜日までの正しい位置へ1日から月末まで配置できます。
初心者の場合は、まず「Sheet2から値を取得する」「1日の曜日を調べる」「For文で1日から月末まで書く」という3段階に分けて考えるのがコツです。添付画像と実際のセル配置が異なる場合でも、A2・B2・C2やA3:G8の部分を実際のセル番地へ置き換えれば、同じ考え方で対応できます。


コメント