【GAS】Googleスプレッドシートでカレンダーを自動作成するスクリプト

これまでExcel VBAばかり使ってきましたが、そろそろGoogleスプレッドシートとGASを使った開発もやってみたいところ。

僕が過去に作ったVBAマクロをGASで作成するというやり方で学習します。

題材はExcel VBAで作ったカレンダー自動作成マクロにしました。

分岐と循環構造を使ってますし、そんなに難しいことをしていませんので基礎練習にはちょうどいいです。

スポンサーリンク

プログラムの内容

データを公開用として複製して現物を見てもらおうと思いましたが、スクリプトは承認がないと動かせないとのことで断念。

スクリーンショットとコードだけでよろしくお願いします。

年間カレンダーは4月始まりです。下の方まで写せませんでしたがちゃんと3月末まであります。

A3縦で印刷する想定です。Googleスプレッドシートは印刷時に随時設定するんですかね。改ページがめんどくさいです。

右上の実行ボタンをクリックするとスクリプトが実行されます。操作としては西暦4桁を入れるだけで終わります。

各シートに月間カレンダーがあり、これらも更新されます。

こっちはA4横で印刷する想定です。

実際にスクリプトを実行してみた感想ですが、VBAと比べて結構遅いですね。

これぐらい簡単な処理ならいいですが、実行時間に6分の制限もありますし、あまり複雑なものは作れないのかも。

プログラミング (GAS)

function autoCalendar() {
  let thisYear;
  let nextYear;
  let mySheet;
  let firstDay;
  let dayNum;
  let days;
  let setRow;
  let setCol;
  let value;
  let febFlg;
  let ss;
  // 何年度のカレンダーを作成するか入力
  thisYear = Browser.inputBox("西暦を半角4桁の数字で入力してください。", Browser.Buttons.OK_CANCEL);
  // キャンセル時の処理
  if(thisYear == "cancel"){
    return;
  };
  // 4桁でない場合の処理
  if(thisYear.length != 4){
    Browser.msgBox("西暦は4桁で入力してください。 \\n 処理を中止します。");
    return;
  };
  // 次年の変数を用意
  nextYear = Number(thisYear) + 1;
  // 年間カレンダーの中身をクリア
  mySheet = SpreadsheetApp.getActiveSheet();
  mySheet.getRange("A3:W14").clearContent();
  mySheet.getRange("A18:W29").clearContent();
  mySheet.getRange("A33:W44").clearContent();
  mySheet.getRange("A48:W59").clearContent();
  // 西暦を入力
  mySheet.getRange("A1").setValue(thisYear + "年");
  mySheet.getRange("A46").setValue(nextYear + "年");
  // 4月1日の曜日を取得、最初に入力する列を決定
  firstDay = thisYear + "/4/1"
  dayNum = new Date(firstDay).getDay() + 1;
  setCol = dayNum;
  // 年間カレンダーを作成
  for(let i=1;i<=46;i=i+15){
    for(let j=7;j<=23;j=j+8){
      setRow = i + 2;
      value = mySheet.getRange(i,j).getValue();
      // 各月の日数を算出
      if(value=="4月"||value=="6月"||value=="9月"||value=="11月"){
        days = 30;
      } else if(value=="2月"){
        febFlg = "false"
        if(nextYear % 400 != 0){
          if(nextYear % 100 == 0){
            days = 28;
          } else if(nextYear % 4 == 0){
            days = 29;
            febFlg = "true";
          } else {
            days = 28;
          }
        } else {
          days = 29;
          febFlg = "true";
        }
      } else {
        days = 31;
      }
      // 1ヶ月分の日付を入力
      for(let k=1;k<=days;k++){
        mySheet.getRange(setRow,setCol).setValue(k);
        if(setCol==j){
          setRow = setRow + 2;
          setCol = j - 6;
        } else {
          setCol++;
        }
        if(k==days){
          if(j==23){
            setCol = setCol - 16;
          } else {
            setCol = setCol + 8;
          }
        }
      }
    }
  }
  // 月間カレンダーを作成
  setCol = dayNum;
  ss = SpreadsheetApp.getActiveSpreadsheet();
  for(let i=1;i<=12;i++){
    setSheet = ss.getSheets()[i];
    // 西暦を入力
    if(i<=9){
      setSheet.getRange("F1").setValue(thisYear + "年");
    } else {
      setSheet.getRange("F1").setValue(nextYear + "年");
    }
    setSheet.getRange("A3:G14").clearContent();
    // 各月の日数を算出
    if(i==1||i==3||i==6||i==8){
      days = 30;
    } else if(i==11){
      if(febFlg=="true"){
        days = 29;
      } else {
        days = 28;
      }
    } else {
      days = 31;
    }
    // 1ヶ月分の日付を入力
    setRow = 3;
    for(let j=1;j<=days;j++){
      setSheet.getRange(setRow,setCol).setValue(j);
      if(setCol==7){
        setRow = setRow + 2;
        setCol = 1;
      } else {
        setCol++;
      }
      if(j==days){
        setRow = 3;
      }
    }
  }
  Browser.msgBox("処理完了");
}

コメント

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

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

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