K.Y. Design
K.Y. Design
K.Y. Design

体調管理フォーム

外観

今回はお客さまから「日々の体調を報告するためのフォームを部署ごとに作り、ある時間になっても提出がない人に自動的にリマインドメールを送れるようにして欲しい。また、各部署の回答内容を全てまとめた集約シートも作って欲しい」とご依頼いただきました。

実際に作成したツールはこちらです。
ご利用される際には、ファイルをご自身のGoogleドライブにコピーしてください。

概要

担当

  • コーディング
  • テスト

使用ツール

  • Google スプレッドシート
  • Google Apps Script

GASのコード(各部署の回答シート)

本日の未提出者リストを出力する関数

「フォームの回答」シートと「全社員リスト」シートの内容を比較してその日の未提出者を割り出し、「未提出者リスト」シートに書き出す関数です。

function unsubmitEmployeesList() {

  var today = new Date();
  var fourDigitToday = Utilities.formatDate(today, 'Asia/Tokyo', 'yyMMdd');

  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var unsubmitEmployeesListSheet = spreadsheet.getSheetByName('未提出者リスト');
  var title = Utilities.formatDate(today, 'Asia/Tokyo', 'yyyy年M月d日の未提出者');
  var titleRange = unsubmitEmployeesListSheet.getRange('B2');
  titleRange.setValue(title);
  unsubmitEmployeesListSheet.getRange('B5:D100').clearContent();

  var submittedEmployeesListSheet = spreadsheet.getSheetByName('フォームの回答');
  var lastRowOfSubmittedEmployeesList = submittedEmployeesListSheet.getLastRow();
  var allSubmittedDataRange = submittedEmployeesListSheet.getRange(2, 1, lastRowOfSubmittedEmployeesList - 1, 4);
  var allSubmittedData = allSubmittedDataRange.getValues();

  var submittedEmployeesIdOfToday = [];
  for (var i = 0; i < allSubmittedData.length; i++) {
    var submittedDate = Utilities.formatDate(allSubmittedData[i][0], 'Asia/Tokyo', 'yyMMdd');
    if (submittedDate === fourDigitToday) {
      submittedEmployeesIdOfToday.push(allSubmittedData[i][1]);
    }
  }

  var allEmployeesListSheet = spreadsheet.getSheetByName('全社員リスト');
  var allEmployeesDataRange = allEmployeesListSheet.getRange('B5:E100');
  var allEmployeesData = allEmployeesDataRange.getValues().filter(v => v[0]);

  var unsubmitEmployeesArray = [];
  for (var i = 0; i < allEmployeesData.length; i++) {
    if (submittedEmployeesIdOfToday.indexOf(allEmployeesData[i][3]) < 0) {
      var employeeId = allEmployeesData[i][0];
      var employeeFullName = allEmployeesData[i][1];
      var employeeEmailAddress = allEmployeesData[i][2];
      var unsubmitEmployeeInfo = [employeeId, employeeFullName, employeeEmailAddress];
      unsubmitEmployeesArray.push(unsubmitEmployeeInfo);
    }
  }

  for (var r = 0; r < unsubmitEmployeesArray.length; r++) {
    for (var c = 0; c < unsubmitEmployeesArray[r].length; c++) {
      unsubmitEmployeesListSheet.getRange(5 + r, 2 + c).setValue(unsubmitEmployeesArray[r][c]);
    }
  }

}

本日の未提出者にリマインドメールを送信する関数

「メール設定」シートで入力した内容を元に未提出者にリマインドメールを送信する関数です。
管理者メールアドレスには未提出者の一覧がメールで送信されます。

function sendReminderEmail() {

  unsubmitEmployeesList();

  var today = new Date();
  var fourDigitToday = Utilities.formatDate(today, 'Asia/Tokyo', 'yyMMdd');

  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var submittedEmployeesListSheet = spreadsheet.getSheetByName('フォームの回答');
  var lastRowOfSubmittedEmployeesList = submittedEmployeesListSheet.getLastRow();
  var allSubmittedDataRange = submittedEmployeesListSheet.getRange(2, 1, lastRowOfSubmittedEmployeesList - 1, 4);
  var allSubmittedData = allSubmittedDataRange.getValues();

  var submittedEmployeesIdOfToday = [];
  for (var i = 0; i < allSubmittedData.length; i++) {
    var submittedDate = Utilities.formatDate(allSubmittedData[i][0], 'Asia/Tokyo', 'yyMMdd');
    if (submittedDate === fourDigitToday) {
      submittedEmployeesIdOfToday.push(allSubmittedData[i][1]);
    }
  }

  var allEmployeesListSheet = spreadsheet.getSheetByName('全社員リスト');
  var allEmployeesDataRange = allEmployeesListSheet.getRange('B5:E100');
  var allEmployeesData = allEmployeesDataRange.getValues().filter(v => v[0]);

  var reminderEmailsheet = spreadsheet.getSheetByName('メール設定');
  var subjectForEmployees = reminderEmailsheet.getRange('B13').getValue();
  var bodyForEmployees = reminderEmailsheet.getRange('B16').getValue();

  var unsubmitEmployeesNameArray = [];
  for (var i = 0; i < allEmployeesData.length; i++) {
    if (submittedEmployeesIdOfToday.indexOf(allEmployeesData[i][3]) < 0) {
      var unsubmitEmployeesEmail = allEmployeesData[i][2]
      MailApp.sendEmail({
        to: unsubmitEmployeesEmail,
        subject: subjectForEmployees,
        body: bodyForEmployees
      });
      var unsubmitEmployeesInfo = allEmployeesData[i][0] + '. ' + allEmployeesData[i][1];
      unsubmitEmployeesNameArray.push(unsubmitEmployeesInfo);
    }
  }

  var supervisorsEmailAddress = reminderEmailsheet.getRange('B5').getValue();
  var subjectForSupervisors = '本日の体調管理フォーム未提出者';
  var bodyForSupervisors = '本日の体調管理フォームの未提出者は下記の通りです。\n' + 'リマインドメールはすでに送信されております。\n\n' + unsubmitEmployeesNameArray.join('\n');

  MailApp.sendEmail({
    to: supervisorsEmailAddress,
    subject: subjectForSupervisors,
    body: bodyForSupervisors
  });

}

フォームのプルダウン項目を更新する関数

「全社員リスト」シートの内容を参照して、フォームの「社員番号&氏名」の項目のプルダウンを作成する関数です。
「全社員リスト」シートの内容を更新するたびに「フォーム編集用URL設定」シートの「プルダウン項目の更新」ボタンを押す必要があります。

function djListMaker() {

  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var allEmployeesListSheet = spreadsheet.getSheetByName('全社員リスト');
  var allEmployeesDataRange = allEmployeesListSheet.getRange('E5:E100');
  var allEmployeesData = allEmployeesDataRange.getValues().filter(v => v[0]);
  var listItems = Array.prototype.concat.apply([], allEmployeesData);
  var formURLsettingSheet = spreadsheet.getSheetByName('フォーム編集用URL設定');
  var formURL = formURLsettingSheet.getRange('B3').getValue();

  var form = FormApp.openByUrl(formURL);
  var items = form.getItems(FormApp.ItemType.LIST);

  items[0].asListItem().setChoiceValues(listItems);

}

指定した時間に「sendReminderEmail」を動作させるトリガーの設定

リマインドメッセージを自動送信するための関数を、「メール設定」シートのB10とD10セルに入力した時間で動作させるためのトリガーを設定する関数です。

function delTrigger() {
  var triggers = ScriptApp.getProjectTriggers();
  for (var trigger of triggers) {
    if (trigger.getHandlerFunction() === 'sendReminderEmail') {
      ScriptApp.deleteTrigger(trigger);
    }
  }
}

function setTrigger() {
  delTrigger();

  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var reminderEmailsheet = spreadsheet.getSheetByName('メール設定');
  var triggerHour = reminderEmailsheet.getRange('B10').getValue();
  var triggerMinutes = reminderEmailsheet.getRange('D10').getValue();
  var time = new Date();
  time.setHours(triggerHour);
  time.setMinutes(triggerMinutes);
  ScriptApp.newTrigger('sendReminderEmail').timeBased().at(time).create();
}

GASのコード(集約シート)

回答の集約シートの関数

「設定」シートに入力した内容を下に、各部署の回答シートと、前部署の集約シートを作成します。
一度作成したシートは回答内容がリアルタイムで反映されます。

function aggregateAnswers() {
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var urlList = spreadsheet.getSheetByName('設定');
  var allAnswersSheet = spreadsheet.getSheetByName('集約');
  var templateSheet = spreadsheet.getSheetByName('原本');

  //既存のシートを削除するプログラム
  var allSheets = spreadsheet.getSheets();
  for (var i = 0; i < allSheets.length; i++) {
    var sheetName = allSheets[i].getSheetName()
    if (sheetName !== '設定' && sheetName !== '集約' && sheetName !== '原本') {
      spreadsheet.deleteSheet(allSheets[i]);
    }
  }

  //個別のクラスのシートを作成&集約するプログラム
  var lastRowOfUrlList = urlList.getLastRow();
  var urlListRange = urlList.getRange(8, 2, lastRowOfUrlList - 7, 1);
  var urlData = urlListRange.getValues();
  urlData = Array.prototype.concat.apply([], urlData);

  var classNameListRange = urlList.getRange(8, 5, lastRowOfUrlList - 7, 1);
  var classNameData = classNameListRange.getValues();
  classNameData = Array.prototype.concat.apply([], classNameData);

  var firstColumn = urlList.getRange('B5').getValue();
  var lastColumn = urlList.getRange('D5').getValue();

  var formulaArray = [];
  for (var i = 0; i < urlData.length; i++) {
    var url = urlData[i];
    var className = classNameData[i];
    var duplicatedSheet = templateSheet.copyTo(spreadsheet);
    duplicatedSheet.setName(className);
    var formulaBox = '=QUERY(IMPORTRANGE("' + url + '","' + firstColumn + ':' + lastColumn + '"),"SELECT *")';
    duplicatedSheet.getRange('A1').setValue(formulaBox);
    duplicatedSheet.showSheet();

    if (i === 0) {
      var partOfFormula = 'QUERY(' + className + '!' + firstColumn + ':' + lastColumn + ', "SELECT * WHERE A IS NOT NULL")';
      formulaArray.push(partOfFormula);
    } else {
      var partOfFormula = 'QUERY(' + className + '!' + firstColumn + '2:' + lastColumn + ', "SELECT * WHERE A IS NOT NULL")';
      formulaArray.push(partOfFormula);
    }

  }

  var allAnswersformula = '=QUERY({' + formulaArray.join(';') + '}, "select *")';
  allAnswersSheet.getRange('A1').setValue(allAnswersformula);

}
«
»