【業務改善】GASで自動化!忙しい教務主任の先生のための通信印刷&集計自動化ツール

はじめに

いよいよ2024年度が始まりましたね!!

今回は勤務校で通信をクラスルームを通じて配布しよう!ということになったので、それを実現するために、スプレッドシートのテンプレートを作成しました。

今回のスプレッドシートのポイントは以下の3点です。

  • 2024年度の時間割をTemplateからGASで自動作成
  • 学期ごとの累計時数を自動で集計
  • PDFでダウンロードボタンがあるので、クラスルームに投稿したり印刷したりするのが楽!

a

注意点

今回ご紹介するのはGASを利用したプログラムです。

私の手でテストは行なっておりますが、使用する際は自己責任でお願いします。

フィードバックいただけると、とても嬉しいです!

実際に使う方はこちら!

以下のリンクから使用するアカウントのマイドライブにコピーして使用してください。

使用している感じの動画です。

うまいこと喋れていませんが、細かいことは気にせず。

ちなみにマニアックな話ですが、今回使用している機材はMOTUのM2SHUREのSM58です。

音源はLogic Proのループ音源を組み合わせて作りました。

バンドマンのみなさんオススメですよ。笑

コードの解説

開いているシートの任意のセルの範囲をPDF化してダウンロード

function exportRangeToPDF() {
  // 現在のシートを取得
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getActiveSheet();

  // A1:F17の範囲を取得
  var range = sheet.getRange("A1:F17");

  // PDFオプションを設定
  var url = "https://docs.google.com/spreadsheets/d/" + ss.getId() + "/export" +
            "?format=pdf&" +
            "size=A4&" +
            "portrait=false&" +  // 横向きに変更
            "fitw=true&" +
            "fith=true&" +  // 高さを範囲に合わせる
            "top_margin=0.75&" +
            "bottom_margin=0.75&" +
            "left_margin=0.7&" +
            "right_margin=0.7&" +
            "sheetnames=false&" +
            "printtitle=false&" +
            "pagenum=false&" +
            "gridlines=false&" +
            "fzr=true&" +  // 範囲を拡大縮小してA4に収める
            "gid=" + sheet.getSheetId() + "&" +
            "range=" + range.getA1Notation();

  // PDFを生成
  var params = { method: "GET", headers: { "authorization": "Bearer " + ScriptApp.getOAuthToken() } };
  var response = UrlFetchApp.fetch(url, params).getBlob();

  // PDFを直接ダウンロード
  var fileName = sheet.getName() + "_" + new Date().toISOString().slice(0, 10) + ".pdf";
  var contentType = "application/pdf";
  var blob = response.setName(fileName).setContentType(contentType);

  // ダウンロードURLを作成
  var downloadUrl = DriveApp.createFile(blob).getDownloadUrl().replace("?e=download&gd=true", "");

  // JavaScriptを使用してPDFを直接ダウンロード
  var html = '<script>window.location.href="' + downloadUrl + '";</script>';
  SpreadsheetApp.getUi().showModalDialog(HtmlService.createHtmlOutput(html), 'Downloading PDF...');
}

テンプレートを自動で複製

function createTabs() {
  var startDate = new Date("2024/4/8");
  var endDate = new Date("2025/3/31");
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Template");

  while (startDate <= endDate) {
    if (startDate.getDay() == 1) {
      var tabName = Utilities.formatDate(startDate, "JST", "yyyy/MM/dd");
      sheet.copyTo(SpreadsheetApp.getActiveSpreadsheet()).setName(tabName);
    }
    startDate.setDate(startDate.getDate() + 1);
  }
}

カスタムメニューの作成&時数集計の自動化

// @ts-nocheck
function onOpen() {
  var ui = SpreadsheetApp.getUi();
  ui.createMenu('カスタムメニュー')
    .addItem('1学期集計', 'countSubjectsFirstSemester')
    .addItem('2学期集計', 'countSubjectsSecondSemester')
    .addItem('3学期集計', 'countSubjectsThirdSemester')
    .addToUi();
}

function countSubjectsFirstSemester() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  
  var sheetNames = [    
    "2024/04/08", "2024/04/15", "2024/04/22", "2024/04/29", "2024/05/06",
    "2024/05/13", "2024/05/20", "2024/05/27", "2024/06/03", "2024/06/10",
    "2024/06/17", "2024/06/24", "2024/07/01", "2024/07/08", "2024/07/15",
    "2024/07/22", "2024/07/29", "2024/08/05", "2024/08/12", "2024/08/19",
    "2024/08/26"
  ];
  
  var searchRange = "B4:F14";
  
  var excludeRows = [5, 7, 9, 11, 13, 15];
  
  var subjects = [
    "国語", "社会", "算数", "理科", "生活", "音楽", "図工", "家庭", "体育",
    "道徳", "学活", "外国語", "外国語活動", "総合", "自立", "生単", "日生",
    "クラブ", "委員会", "代表委員会", "児童", "儀式", "文化", "健康", "遠足",
    "勤労", "他"
  ];
  
  var result = {};
  
  for (var i = 0; i < sheetNames.length; i++) {
    var sheet = ss.getSheetByName(sheetNames[i]);
    if (sheet) {
      var range = sheet.getRange(searchRange);
      var values = range.getValues();
      
      for (var row = 0; row < values.length; row++) {
        if (excludeRows.indexOf(row + 4) === -1) {
          for (var col = 0; col < values[row].length; col++) {
            var cell = values[row][col];
            if (subjects.indexOf(cell) !== -1) {
              if (result[cell]) {
                result[cell]++;
              } else {
                result[cell] = 1;
              }
            }
          }
        }
      }
    }
  }
  
  var outputSheet = ss.getSheetByName("シート1");
  if (!outputSheet) {
    outputSheet = ss.insertSheet("シート1");
  }
  
  outputSheet.getRange("D2:D28").clearContent();
  
  for (var j = 0; j < subjects.length; j++) {
    var subject = subjects[j];
    var cell = outputSheet.getRange("D" + (j + 2));
    cell.setValue(result[subject] || 0);
  }
}

function countSubjectsSecondSemester() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  
  var sheetNames = [
    "2024/09/02", "2024/09/09", "2024/09/16", "2024/09/23", "2024/09/30",
    "2024/10/07", "2024/10/14", "2024/10/21", "2024/10/28", "2024/11/04",
    "2024/11/11", "2024/11/18", "2024/11/25", "2024/12/02", "2024/12/09",
    "2024/12/16", "2024/12/23"
  ];
  
  var searchRange = "B4:F14";
  
  var excludeRows = [5, 7, 9, 11, 13, 15];
  
  var subjects = [
    "国語", "社会", "算数", "理科", "生活", "音楽", "図工", "家庭", "体育",
    "道徳", "学活", "外国語", "外国語活動", "総合", "自立", "生単", "日生",
    "クラブ", "委員会", "代表委員会", "児童", "儀式", "文化", "健康", "遠足",
    "勤労", "他"
  ];
  
  var result = {};
  
  for (var i = 0; i < sheetNames.length; i++) {
    var sheet = ss.getSheetByName(sheetNames[i]);
    if (sheet) {
      var range = sheet.getRange(searchRange);
      var values = range.getValues();
      
      for (var row = 0; row < values.length; row++) {
        if (excludeRows.indexOf(row + 4) === -1) {
          for (var col = 0; col < values[row].length; col++) {
            var cell = values[row][col];
            if (subjects.indexOf(cell) !== -1) {
              if (result[cell]) {
                result[cell]++;
              } else {
                result[cell] = 1;
              }
            }
          }
        }
      }
    }
  }
  
  var outputSheet = ss.getSheetByName("シート1");
  if (!outputSheet) {
    outputSheet = ss.insertSheet("シート1");
  }
  
  outputSheet.getRange("E2:E28").clearContent();
  
  for (var j = 0; j < subjects.length; j++) {
    var subject = subjects[j];
    var cell = outputSheet.getRange("E" + (j + 2));
    cell.setValue(result[subject] || 0);
  }
}

function countSubjectsThirdSemester() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  
  var sheetNames = [
    "2025/01/06", "2025/01/13", "2025/01/20", "2025/01/27", "2025/02/03",
    "2025/02/10", "2025/02/17", "2025/02/24", "2025/03/03", "2025/03/10",
    "2025/03/17", "2025/03/24"
  ];
  
  var searchRange = "B4:F14";
  
  var excludeRows = [5, 7, 9, 11, 13, 15];
  
  var subjects = [
    "国語", "社会", "算数", "理科", "生活", "音楽", "図工", "家庭", "体育",
    "道徳", "学活", "外国語", "外国語活動", "総合", "自立", "生単", "日生",
    "クラブ", "委員会", "代表委員会", "児童", "儀式", "文化", "健康", "遠足",
    "勤労", "他"
  ];
  
  var result = {};
  
  for (var i = 0; i < sheetNames.length; i++) {
    var sheet = ss.getSheetByName(sheetNames[i]);
    if (sheet) {
      var range = sheet.getRange(searchRange);
      var values = range.getValues();
      
      for (var row = 0; row < values.length; row++) {
        if (excludeRows.indexOf(row + 4) === -1) {
          for (var col = 0; col < values[row].length; col++) {
            var cell = values[row][col];
            if (subjects.indexOf(cell) !== -1) {
              if (result[cell]) {
                result[cell]++;
              } else {
                result[cell] = 1;
              }
            }
          }
        }
      }
    }
  }
  
  var outputSheet = ss.getSheetByName("シート1");
  if (!outputSheet) {
    outputSheet = ss.insertSheet("シート1");
  }
  
  outputSheet.getRange("F2:F28").clearContent();
  
  for (var j = 0; j < subjects.length; j++) {
    var subject = subjects[j];
    var cell = outputSheet.getRange("F" + (j + 2));
    cell.setValue(result[subject] || 0);
  }
}

何かあったらいつでもお気軽にご連絡くださいね!

家庭や自分の学校学級が一番ですが、可能な限りお手伝いしますよ。

追加:一括削除のコード

テンプレートを作成した後、書式等を修正しなければいけなくなったので、以下のコードを新たに組み込みました。

function deleteSheets() {
  var dates = [
    '2024/04/08', '2024/04/15', '2024/04/22', '2024/04/29', '2024/05/06', 
    '2024/05/13', '2024/05/20', '2024/05/27', '2024/06/03', '2024/06/10',
    '2024/06/17', '2024/06/24', '2024/07/01', '2024/07/08', '2024/07/15',
    '2024/07/22', '2024/07/29', '2024/08/05', '2024/08/12', '2024/08/19',
    '2024/08/26', '2024/09/02', '2024/09/09', '2024/09/16', '2024/09/23',
    '2024/09/30', '2024/10/07', '2024/10/14', '2024/10/21', '2024/10/28',
    '2024/11/04', '2024/11/11', '2024/11/18', '2024/11/25', '2024/12/02',
    '2024/12/09', '2024/12/16', '2024/12/23', '2024/12/30', '2025/01/06',
    '2025/01/13', '2025/01/20', '2025/01/27', '2025/02/03', '2025/02/10',
    '2025/02/17', '2025/02/24', '2025/03/03', '2025/03/10', '2025/03/17',
    '2025/03/24', '2025/03/31'
  ];

  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheets = ss.getSheets();

  sheets.forEach(function(sheet) {
    if (dates.indexOf(sheet.getName()) !== -1) {
      ss.deleteSheet(sheet);
    }
  });
}
シェアしていただけると嬉しいです!
  • URLをコピーしました!

この記事を書いた人

福岡の小学校教員 8年目 / 社会科の授業にICTを活用 / GEG Chikuhoリーダー /初心者向けICT研修講師/ 福岡社会科教育実践学会・日本教育工学会所属 / WordPressでICT活用術を発信 / 動画編集・デザイン・Web記事作成・論文執筆・楽曲制作も

コメント

コメントする

CAPTCHA