167話から始まったかずのExcel VBAプログラミングの目的は,カレンダー作成を自動化すること。前回はユーザーフォームを作り,年,月をテキストボックスに入力し,コマンドボタンをクリックすると,年と月の値が正しいかどうかチェックするところまでで,あっさり終わった。実は翌日が陸上部の大会だったのだ。

 100Mと200M走に出場するかずを,作りかけの高速道路の無料の1区間をそれなりに飛ばして,応援に行った。それにしても北陸の高速道路はどうしてこう曲がりくねっているのか。カーブの中に申し訳程度に直線がある。

 「1年男子200M決勝」とアナウンスが流れ,出場者の名前が呼び上げられる。かずが手を上げて応える。なんか,かっこいいが,実は5名しかエントリーしていないので,予選なし全員決勝進出で,それにもかかわらずレーンはいくつも空いているのだ。オリンピックで末續選手や朝原選手が,がんばっているのに陸上はもう一つ人気がないのか。

 よーい,スタート。ひとり速い子がいて,あとは団子でゴニョゴニョとゴールして3位。めでたし。めでたし(ビリだと,かける言葉を探さなくてはいけない)。

 VBAでカレンダープログラムもゴールに向けてトントンと進んでいく。先に完成したイメージから見てください。

 枠と曜日は先に書き込んであり,指定した年月の日を書き込んでいくことが,主な処理である。

 「まず,どこのセルに1を入れるか,一日(ついたち)の曜日を取得する必要がある」と説明を始めたが,その前に「セルとは一つひとつのマスのこと」だとか,関数は「Functionに続けて関数名を書き,えーっ,引数をとって,値を返すことができる」というところから説明をはじめなくてはいけない。モーグで紹介されている関数を参考に作ってみせた。

-------------------------------------------------------------------------
 
Function 曜日取得(myYear As Integer, myMonth As Integer) As Integer
 Dim MyDate As Date
 MyDate = myYear & "/" & myMonth & "/1"
 曜日取得 = Weekday(MyDate)
End Function

---------------------------------------------------------------
 引数として受け取った年,月,そして1を”/”でつないで日付としWeekday関数で曜日を取り出している。イミディエイトウィンドウでテストして,曜日が数値で返ってくることをかずに示す。好都合なことに,日曜日は1,土曜日は7が返ってくる。「かず,この返り値をセルを指定する列番号に使えばいいがや」と説明するが,わかっているのか,わからんのか,はっきりしない顔をしている。

 何日まで,日を入れればいいか判断するために,「月末日を求める処理も必要だろう」と,かずに言うと「4で割り切れる年はうるう年だけど,100で割切れる年はうるう年ではない。でも400でも割り切れればうるう年だ」と難しいことを言う。聞けばHSPでプログラムを作るときに勉強したのだと言う。
-------------------------------------------------------------------------
 
Function 月末日取得(myYear As Integer, myMonth As Integer) As Integer
 Dim myDay As String
 myDay = myYear & "/" & myMonth & "/1"
 月末日取得 = Day(DateAdd("d", -1, DateAdd("m", 1, myDay)))
End Function

---------------------------------------------------------------

 「なーん,次の月の一日の前日を求めればいいが」とかずの理屈を今時のプログラム環境は打ち砕く。
 「セルはRangeでも指定できるし, Cellsでも指定できるよ」と,試しに少しシートに日を書き込んで,「7で割ったあまりが0のときに行を替えれば,うまくいくよ」と説明した。
-------------------------------------------------------------------------

Sub カレンダー()
 Dim 開始曜日 As Integer
 Dim Now曜日 As Integer
 Dim 行NO  As Integer
 Dim Now日 As Integer
 Range("A1") = UserForm1.txt年 & "年" & UserForm1.txt月 & "月"
 Range("A4:G8") = ""
 開始曜日 = 曜日取得(Val(UserForm1.txt年), Val(UserForm1.txt月))
 行NO = 4
 Now日 = 1
 Now曜日 = 開始曜日
 For Now日 = 1 To 月末日取得(Val(UserForm1.txt年), Val(UserForm1.txt月))
  Cells(行NO, Now曜日) = Now日
  If Now曜日 Mod 7 = 0 Then
   行NO = 行NO + 1
   Now曜日 = 1
  Else
   Now曜日 = Now曜日 + 1
  End If
 Next Now日
End Sub

---------------------------------------------------------------

 Forのループで月末日まで日を入れる。開始曜日に1を入れて,カウントアップしていき,Now曜日 Mod 7が0を返したら(modは剰余を求める演算子),行を替える。
 「かず,どうや。こういうロジックを考えるのはおもしろいやろ」「うん,おもしろい」

 ぜひ,知識だけでなく,こんなロジックを考えるITの授業を中学でもやってくれないだろうか。コンピュータを使うと結果が出しやすいので,考える楽しさが存分に味わえると思うのだが。
-------------------------------------------------------------------------

Private Sub Workbook_Open()
 UserForm1.Show
End Sub

---------------------------------------------------------------

 最後に,ブックを開くとユーザーフォームが表示されるようにして,おしまい。「でも,祝日はまだ,自分で赤色にせんなん」,「えーっと,それは別シートに祝日の一覧表を作って,そこに登録されている日だったら…」。