−トップへ−

カレンダーを作る
その9 祝日を赤く表示する

 今回は,国民の祝日を赤く表示してみます。
 
 まず国民の祝日について確認します。現在国民の祝日に指定されているのは以下の15個です。
   元旦      …1月1日
   成人の日   …1月第2月曜日
   建国記念の日…2月11日
   春分の日   …3月21日頃(不定日)
   昭和の日   …4月29日
   憲法記念日 …5月3日
   みどりの日  …5月4日
   こどもの日  …5月5日
   海の日    …7月第3月曜日
   敬老の日   …9月第3月曜日
   秋分の日   …9月23日頃(不定日)
   体育の日   …10月第2月曜日
   文化の日   …11月3日
   勤労感謝の日…11月23日
   天皇誕生日 …12月23日
 
 
 この中で日付が定まっているものはよいのですが,「第2月曜日」などという表記のものについて考えてみます。
 
 この「第2月曜日」という場合は,日付が8〜14までの間で月曜日の日と考えることができ,同じように「第3月曜日」は日付が15日〜21日までの間で月曜日の日と考えて祝日を求めていきます。
 
 「春分の日」「秋分の日」は年により日付が変わります。それを計算で求めることもできますが,ここでは頻度の高い3月21と9月23日として処理することにします。

タブシートの追加

 まずform2を開き,休日を書き込むためにタブシートを追加します。追加の仕方は,PageControl1の上で右クリックをして「ページの新規作成」を選択します。
 するとTabsheet2が追加されますので,そこにStringGridコンポーネントを設置します。StringGridコンポーネントはツールパレットのAdditionalの4番目にあります。
 次にStringGridのプロパティを下のように変更します。

ColCount
3
DefaultColWidth
24
DefaultRowHeight
18
FixedCols
0
RowCount
12
Width
172
OptionsgoEditing
True
goAlwaysShowEditor
True

 次にもう一つStringGridを作成します。プロパティは一つ目と同じように設定しますが,RowCountだけは5に設定しておきます。
 
 
 ここまでの設定でForm2は以下のようになりました。
 
 この図では,左がStringGrid1になり,右がStringGrid2になります。
 
 次に休日をプログラムソースで記述していきますが,ここでまた大きな変更をします。
 現在Form1.Createイベントハンドラの中でカレンダーを作成していますが,これからform2で休日の設定を行うと,エラーが起きたりすることもあります。
 それはFormの作成順序によって起こるものです。まず,プログラムの実行を行うと,最初にForm1を作成し,その後Form2を作成します。
 そのため,Form1を作成するときに,休日を呼び出そうとすると,Form2が作成されていないため,エラーが発生します。
 
 それを避けるために,Form1.Createに記述したソースを,すべてForm2.Createに移してしまいます。
 
 
 まず,Form1から変更を加えていきます。

 type
  TForm1 = class(TForm)
   Image1: TImage;
   PopupMenu1: TPopupMenu;
   N1: TMenuItem;
   N2: TMenuItem;
   N3: TMenuItem;
   N4: TMenuItem;
   N5: TMenuItem;
   procedure makec;
    //procedure FormCreate(Sender: TObject);←これを削除
   procedure N1Click(Sender: TObject);
   procedure N2Click(Sender: TObject);
   procedure N4Click(Sender: TObject);
   procedure N5Click(Sender: TObject);
     :
     :
 
  {
  procedure TForm1.FormCreate(Sender: TObject);
  begin
   ye:=formatdatetime('yyyy',date);
   mo:=formatdatetime('m',date);
   size:=300;
   makec;
  end;
  これ全体を削除
  }

 次に,Form2でForm2.Createイベントハンドラを呼び出しそこに記述します。。

 procedure TForm2.FormCreate(Sender: TObject);
 begin
  form1.ye:=formatdatetime('yyyy',date);
  form1.mo:=formatdatetime('m',date);
  form1.size:=300;
  form1.makec;
 end;

 ここで実行をすると,「OnCreateは存在しません。削除しますか?」といった,エラーメッセージがでますので「はい」を押してください。

休日の設定

 次にStringGridに休日を書き込んでいきます。書き込むところはForm2.Createイベントハンドラです。

 procedure TForm2.FormCreate(Sender: TObject);
 begin
  StringGrid1.ColWidths[2]:=100;
  StringGrid1.Cells[0,0]:='月';
  StringGrid1.Cells[1,0]:='日';
  StringGrid1.Cells[2,0]:='祝日名';
  StringGrid1.Cells[0,1]:='1';
  StringGrid1.Cells[1,1]:='1';
  StringGrid1.Cells[2,1]:='元日';
  StringGrid1.Cells[0,2]:='2';
  StringGrid1.Cells[1,2]:='11';
  StringGrid1.Cells[2,2]:='建国記念の日';
  StringGrid1.Cells[0,3]:='3';
  StringGrid1.Cells[1,3]:='21';
  StringGrid1.Cells[2,3]:='春分の日';
  StringGrid1.Cells[0,4]:='4';
  StringGrid1.Cells[1,4]:='29';
  StringGrid1.Cells[2,4]:='昭和の日';
  StringGrid1.Cells[0,5]:='5';
  StringGrid1.Cells[1,5]:='3';
  StringGrid1.Cells[2,5]:='憲法記念日';
  StringGrid1.Cells[0,6]:='5';
  StringGrid1.Cells[1,6]:='4';
  StringGrid1.Cells[2,6]:='みどりの日';
  StringGrid1.Cells[0,7]:='5';
  StringGrid1.Cells[1,7]:='5';
  StringGrid1.Cells[2,7:='こどもの日';
  StringGrid1.Cells[0,8]:='9';
  StringGrid1.Cells[1,8]:='23';
  StringGrid1.Cells[2,8]:='秋分の日';
  StringGrid1.Cells[0,9]:='11';
  StringGrid1.Cells[1,9]:='3';
  StringGrid1.Cells[2,9]:='文化の日';
  StringGrid1.Cells[0,10]:='11';
  StringGrid1.Cells[1,10]:='23';
  StringGrid1.Cells[2,10]:='勤労感謝の日';
  StringGrid1.Cells[0,11]:='12';
  StringGrid1.Cells[1,11]:='23';
  StringGrid1.Cells[2,11]:='天皇誕生日';

  StringGrid2.ColWidths[2]:=100;
  StringGrid2.Cells[0,0]:='月';
  StringGrid2.Cells[1,0]:='週';
  StringGrid2.Cells[2,0]:='祝日名';
  StringGrid2.Cells[0,1]:='1';
  StringGrid2.Cells[1,1]:='2';
  StringGrid2.Cells[2,1]:='成人の日';
  StringGrid2.Cells[0,2]:='7';
  StringGrid2.Cells[1,2]:='3';
  StringGrid2.Cells[2,2]:='海の日';
  StringGrid2.Cells[0,3]:='9';
  StringGrid2.Cells[1,3]:='3';
  StringGrid2.Cells[2,3]:='敬老の日';
  StringGrid2.Cells[0,4]:='10';
  StringGrid2.Cells[1,4]:='2';
  StringGrid2.Cells[2,4]:='体育の日';
 
  form1.ye:=formatdatetime('yyyy',date);
  form1.mo:=formatdatetime('m',date);
  form1.size:=300;
  form1.makec;
end;

 StringGridへの書き込みは,もっと効率的な方法があると思いますが,私はあまり詳しくないため,セルに1つずつ書き込む方法をとりました。
 
 
 いよいよ,休日の色を変えてみたいと思います。書き込むところはForm1のmakecです。

 procedure TForm1.makec;
  var
   i,j,week:integer; //「j」を新たに追加
   str:string;
   furikae:boolean; //振替休日を記録するときに使用

 begin
  form1.ClientWidth:=size;
  form1.ClientHeight:=size;
  image1.Left:=0;
  image1.Top:=0;
  image1.Width:=form1.ClientWidth;
  image1.Height:=form1.ClientHeight;
 
  week:=dayofweek(strtodate(ye+'/'+mo+'/1')); //“今月”の始まりの曜日を求める
  with image1.Canvas do begin
   brush.Color:=clwhite; //塗りつぶしの色を白にする
   fillrect(image1.ClientRect); //image1全体を塗りつぶす
   brush.Style:=bsclear; //塗りつぶしのスタイルを文字だけの塗りつぶしにする

    //月の書き込み
   font.Size:=size div 14; //フォントの大きさをsizeの14分の1にする
   font.Color:=clblue; //フォントの色を青にする
   textout(size div 2 -textwidth(mo+'月') div 2, //X座標は中央
       size*3 div 20-textheight(mo+'月') div 2, //Y座標は20分の3の部分
       mo+'月'); //
    //西暦の書き込み
   font.Size:=size div 22; //フォントの大きさをsizeの22分の1にする
   font.Color:=clblue; //フォントの色を青にする
   textout(size*4 div 5-textwidth(ye+'年') div 2,0,ye+'年');
    //X座標は左から5分の4のところ,Y座標は0に書き込む
   font.Size:=size div 20; //フォントのサイズをsizeの20分の1にする
                    //この大きさはいろいろ試して見てください。

    //曜日の書き込み
   for i:=1 to 7 do begin //曜日を書き込むため7回繰り返す
    case i of
     1:begin
       font.Color:=clred; //フォントの色を赤にして
       str:='日'; //文字を「日」にする。この文字を「Sun」にすることもできます。
      end;
     2:begin
       font.Color:=clblack; //月〜金はフォントの色を黒にする
       str:='月';
      end;
     3:begin
       font.Color:=clblack;
       str:='火';
      end;
     4:begin
       font.Color:=clblack;
       str:='水';
      end;
     5:begin
       font.Color:=clblack;
       str:='木';
      end;
     6:begin
       font.Color:=clblack;
       str:='金';
      end;
     7:begin
       font.Color:=clblue; //土曜日はフォントの色を青にする
       str:='土';
      end;
    end;
    textout(size*((i-1) mod 7+1) div 8 -textwidth(str) div 2,
        size*5 div 20-textheight(str) div 2,
        str); //曜日を書き込む
   end;
    //曜日の書き込み終了

    //区切り線を入れる
   pen.Color:=clblack; //ペンの色を黒にする
   pen.Width:=2; //ペンの太さを2にする
   moveto(size*1 div 16,sizet*1 div 3); //X座標は16等分した1〜15まで
   lineto(size*15 div 16,size*1 div 3); //Y座標は3等分した1番目の場所
    //区切り線を入れる終了

   furikae:=false; //変数furikaeをfalseにする
   for i:=1 to 31 do begin //1日から31日まで繰り返します
     //小の月大の月閏年の判別
    case i of
     29:if mo=2 then begin //29日のとき
       if ye mod 4 >0 then begin
        exit; //4で割りきれなければ閏年でないので終了
       end else begin
        if (ye mod 100=0) and (ye mod 400>0) then exit;
       end; //100で割り切れて,400で割り切れれば閏年でない
       end;
     30:if mo=2 then exit; //30日のとき2月であれば終了
     31:begin //31日のとき
       if mo<=7 then begin
        if mo mod 2=0 then exit;
       end else begin
        if mo mod 2=1 then exit;
       end; //小の月であれば終了
      end;
    end;
     //小の月大の月閏年の判別終了

     //日付の色を変える
    case (week+i-2) mod 7+1 of //日付を書き込むX座標による場合分け
     1:font.Color:=clred; //1のときはフォントの色を赤にする
     7:font.Color:=clblue; //7のときはフォントの色を青にする
     else font.Color:=clblack; //それ以外は黒にする
    end;

     //休日の色を変えるその1
    for j:=1 to 12 do begin
     if form2.StringGrid1.Cells[0,j]+'/'+form2.StringGrid1.Cells[1,j]
      =mo+'/'+inttostr(i) then begin
        //もしStringGrid1に書き込んだ月日と書き込む月日が一致したら
      font.Color:=clred; //フォントの色を赤にする
      if (week+i) mod 7=2 then furikae:=true;
        //もしその日が日曜ならfurikaeをtrueにする
     end;
    end;
     //振替休日
    if ((week+i) mod 7=3) and (furikae=true) then begin
       //もし書き込む日が月曜でfurikaeがtrueなら
     font.Color:=clred; //文字の色を赤にする
     furikae:=false; //furikaeをfalseにする
    end;
     //休日の色を変えるその2
    for j:=1 to 5 do begin
     if (form2.StringGrid2.Cells[0,j]=mo) //もしStringGrid2の月と書き込む月が一緒で
      and (strtoint(form2.StringGrid2.Cells[1,j])*7-7<i) //指定した日より大きく
      and (strtoint(form2.StringGrid2.Cells[1,j])*7>=i) //指定した日より小さく
      and ((week+i) mod 7=3) then begin //書き込む日が月曜日のとき
       font.Color:=clred; //フォントの色を赤にする。
     end;
    end;

    textout(size*((week+i-2) mod 7+1) div 8 -textwidth(inttostr(i)) div 2,
        size*((week+i-2) div 7+4) div 10-textheight(inttostr(i)) div 2,
        inttostr(i)); //日付を書き込む
   end;
  end;
 end;
 
 end.

 これを実行して,5月のカレンダーを表示させてみます。

 上記のようになり連休と振替休日が赤く表示されています。
 
 
 次回は変更した設定を保存して,次に同じ設定で起動できるようにします。

−トップへ−