Web欠席等連絡システムの開発

勤務校で、夕方 17:30〜翌朝 8:00まで留守番電話対応とすることとなりました。

当然、欠席や遅刻等の連絡電話が朝に集中してかかってきてしまいます。それを解消するために、Web上で欠席等の連絡を受け付けるシステムを開発することとなりました。

勤務校を管轄する、教育委員会が教育用のGoogleアカウントを各校に配布しています。

そこで、Google Work Spaceのサービスである、Googleフォームとスプレッドシートを使って作ることにしました。

ですが、結局集計作業は人間が行うのでは意味がありません。自動化させたいと思いました。

調べてみると、Google Apps Script(通称:GAS ガス)でプログラムを組めば、処理を簡単に自動化させられるとわかりました。


ここでは、その作成方法と、プログラムのソースコードを公開したいと思います。

同じものを勤務校で、2021年6月から稼働させて、現在まで不具合なく動作しています。

素人が組んだプログラムですので、効率化できていなかったり、整っていなかったりするかと思いますが、ご了承ください。

準備編(概要紹介・Googleフォームで受付画面を作成する)


フォームGAS編(留守番電話の時間帯のみ受付・いつの連絡を受け付けているかを表示させる等)

// その日の17時29分にトリガーを設定

function setTrigger1() {

var triggerDay = new Date();

triggerDay.setHours(17);

triggerDay.setMinutes(29);

ScriptApp.newTrigger("openFormAcceptance").timeBased().at(triggerDay).create();

}


// その日の8時31分にトリガーを設定

function setTrigger2(){

var triggerDay = new Date();

triggerDay.setHours(8);

triggerDay.setMinutes(31);

ScriptApp.newTrigger("closeFormAcceptance").timeBased().at(triggerDay).create();

}


// その日のトリガーを削除する関数(消さないと残る)

function deleteTrigger1() {

var triggers = ScriptApp.getProjectTriggers();

for(var i=0; i < triggers.length; i++) {

if (triggers[i].getHandlerFunction() == "openFormAcceptance") {

ScriptApp.deleteTrigger(triggers[i]);

}

}

}


// その日のトリガーを削除する関数(消さないと残る)

function deleteTrigger2() {

var triggers = ScriptApp.getProjectTriggers();

for(var i=0; i < triggers.length; i++) {

if (triggers[i].getHandlerFunction() == "closeFormAcceptance") {

ScriptApp.deleteTrigger(triggers[i]);

}

}

}


// フォームの回答を受け付け状態にする(トリガーの時間に応じて)

function openFormAcceptance(){

deleteTrigger1();

var myForm = FormApp.openByUrl("https://docs.google.com/forms/d/ooooooooooooooooooooo/edit");

myForm.setAcceptingResponses(true);

}


// フォームの回答受付を締め切る(トリガーの時間に応じて)

function closeFormAcceptance(){

deleteTrigger2();


var myForm = FormApp.openByUrl("https://docs.google.com/forms/d/ooooooooooooooooooooooo/edit");

myForm.setAcceptingResponses(false);

}


// フォーム上にいつの連絡を受け付けているか表示する

function onTimerSetFormDate(e) {

var form = FormApp.openById('oooooooooooooooooooooooooooooooooooooo');

var items = form.getItems();


// 現在日時を取得

const now = new Date();

var today = now.getDate();

var month = now.getMonth() + 1; // 当月にするには+1をしなくてはならない

var tomorrow = today + 1;


// 2月の月末処理

if (month == 2 && today == 28){

tomorrow = 1;

month = month + 1;

}


// 月末の翌日処理

if (today == 30){

switch(month){

case 4:

case 6:

case 9:

case 11:

tomorrow = 1;

month = month + 1;

break;


default:

break;

}

}else if(today == 31){

switch(month){

case 1:

case 3:

case 5:

case 7:

case 8:

case 10:

case 12:

tomorrow = 1;

month = month + 1;

break;


default:

break;

}

}


// 曜日の配列

const week_list = new Array('日', '月', '火', '水', '木', '金', '土');

// 曜日を表す数値

const weekNum = now.getDay();

// 曜日取得

const week = week_list[weekNum];

var week2 = week_list[weekNum+1];


// 土曜日なら、翌日を日曜日にする

if ( weekNum == 6){

week2 = week_list[0];

}


if (Utilities.formatDate(now, 'Asia/Tokyo', 'HH') > 12) {

// 午後です

items[0].setTitle('ただ今、'+ Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyy年') + month + '月' + tomorrow + '日 (' + week2 + ') ' + 'の連絡を受け付けています');

} else {

// 午前です

items[0].setTitle('ただ今、'+ Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyy年MM月dd日 (' + week + ') の連絡を受け付けています'));

}

}


//フォームの回答をすべて削除する(明日に備える)

function DeleteAllEntries() {

form = FormApp.openByUrl('https://docs.google.com/forms/d/oooooooooooooooooooooooooooooo/edit')

if(form)form.deleteAllResponses();

}


スプレッドシートGAS編(シートの体裁を整える・PDF化してメールで送信等)

//トリガーをセット

function setTrigger(){

const time = new Date();

time.setHours(8);

time.setMinutes(31);


ScriptApp.newTrigger('runOrder').timeBased().at(time).create();

}


//順番にfunctionを実行するため

function runOrder(){

ajustformat();

quickpdf();

}


//スプレッドシートの書式を整える

function ajustformat(){

var sheet = SpreadsheetApp.getActiveSpreadsheet();

var sh = sheet.getActiveSheet();


//最終行・最終列番号取得

const lastRow = sh.getLastRow();

const lastCol = sh.getLastColumn();


//並べ替え(学部ごと、グループごと)

let data = sh.getRange(2, 1, lastRow, lastCol);

data.sort([{column: 2, ascending: false}, {column: 3, ascending: true}]);

//セルの設定

for(let i = 1; i <= lastRow; i++) {

for(let j = 1; j <= lastCol; j++) {

sh.getRange(i,j).setFontSize(12); //フォントサイズを変更

sh.getRange(i,j,lastRow, lastCol).setWrapStrategy(SpreadsheetApp.WrapStrategy.WRAP); //折り返す

sh.getRange(i,j).setBorder(null, null, true, null, true, null); //セルに下線を引く

}

}


//スプレッドシートを更新

SpreadsheetApp.flush();

}


//スプレッドシートをPDF化してメール添付して送信

function quickpdf(){


//自分のスプレッドシートを取得

var pdfname = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyy年MM月dd日現在の連絡状況') + ".pdf";


//スプレッドシートをpdf化

var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();

var key = spreadsheet.getId();

var sheetName = spreadsheet.getSheetByName("フォームの回答 1");

var gid = sheetName.getSheetId();

var token = ScriptApp.getOAuthToken();


// pdfの設定(A4横向き)をしてpdf化

var url = "https://docs.google.com/spreadsheets/d/" + key + "/export?gid=" + gid + "&format=pdf&portrait=false&size=A4&gridlines=false&fitw=true";

var pdf = UrlFetchApp.fetch(url, {headers: {'Authorization': 'Bearer ' + token}}).getBlob().setName(pdfname);



//作成したPDFファイルをメールに添付して送る

var mail = 'ooooooo@oooooooo';

var subject = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyy年MM月dd日現在の連絡状況');

var body = '本日の欠席・遅刻・自主登校の一覧を送信します';

MailApp.sendEmail(mail, subject, body, {attachments:pdf});

}


//スプレッドシートの入力されている行を削除する(明日に備える)

function deleteRow(){

const sheet = SpreadsheetApp.getActiveSheet();

const lastRow = sheet.getLastRow();

sheet.deleteRows(2,lastRow);


}