2025年3月24日 星期一

「Google Apps Script」時間到自動開啟、關閉Google表單


雖然表單已經有 formLimit 這個外掛程式就已經夠用了,但自己手動做一個的感覺就是不一樣,有需要的夥伴請自行複製貼語法到 表單的 Apps Script 再執行 setFormOpenCloseTimes 這個 function 就能使用囉!大家順便也幫忙測試看看是否正常運作!感謝啦!




3.複製下列語法貼到 Apps Script 中( 只需修改想要的開啟和關閉時間,其他都不用動)
🎯 這邊月份設定比較特別:0 表示1月、1 表示2月、2 表示3月......11 表示 12月


// 全域變數:設定表單開啟和關閉時間 (以 UTC+8 時間表示,並轉換為 UTC)
var OPEN_TIME = convertToUTC(2025, 2, 24, 16, 05); // 2025年3月24日16:05
var CLOSE_TIME = convertToUTC(2025, 2, 24, 16, 10); // 2025年3月24日16:15
var TIMEZONE_UTC8 = 'Asia/Taipei';

function setFormOpenCloseTimes() {
  try {
    var form = FormApp.getActiveForm();
    var now = new Date();
    var nowLocal = formatLocalTime(now);
    var openTimeLocal = formatLocalTime(OPEN_TIME);
    var closeTimeLocal = formatLocalTime(CLOSE_TIME);

    Logger.log('Form ID: ' + form.getId());
    Logger.log('Current Time (UTC+8): ' + nowLocal);
    Logger.log('Open Time (UTC+8): ' + openTimeLocal);
    Logger.log('Close Time (UTC+8): ' + closeTimeLocal);
    Logger.log('Current Form Status: ' + (form.isAcceptingResponses() ? 'Open' : 'Closed'));

    deleteExistingTriggers();

    var minutesToOpen = (OPEN_TIME - now) / (1000 * 60);
    var minutesToClose = (CLOSE_TIME - now) / (1000 * 60);

    Logger.log('Minutes to Open: ' + minutesToOpen);
    Logger.log('Minutes to Close: ' + minutesToClose);

    if (now > CLOSE_TIME) {
      Logger.log('Current time is past close time - keeping form closed');
      form.setAcceptingResponses(false);
    } else if (now >= OPEN_TIME && now < CLOSE_TIME) {
      Logger.log('Within open period - opening form and setting close trigger');
      openForm();
    } else {
      Logger.log('Before open time - setting open trigger');
      form.setAcceptingResponses(false);
      if (minutesToOpen >= 1) {
        var trigger = ScriptApp.newTrigger('openForm')
          .timeBased()
          .after(Math.max(1, minutesToOpen) * 60 * 1000)
          .create();
        Logger.log('Open trigger set for: ' + openTimeLocal + ' [Trigger ID: ' + trigger.getUniqueId() + ']');
        ScriptApp.newTrigger('checkFormStatus')
          .timeBased()
          .after(Math.max(2, minutesToOpen + 1) * 60 * 1000)
          .create();
      }
    }
  } catch (e) {
    Logger.log('Error in setFormOpenCloseTimes: ' + e.toString());
  }
}


// 定義 UTC+8 時間 (小時和分鐘),然後轉換為 UTC
function convertToUTC(year, month, day, hourUTC8, minuteUTC8) {
  var hourUTC = hourUTC8 - 8;
  var dayOffset = 0;
  if (hourUTC < 0) {
    hourUTC += 24;
    dayOffset = -1;
  }
  return new Date(Date.UTC(year, month, day + dayOffset, hourUTC, minuteUTC8));
}

function formatLocalTime(date) {
  return date.toLocaleString('zh-TW', { timeZone: TIMEZONE_UTC8 });
}

function openForm() {
  try {
    var form = FormApp.getActiveForm();
    var now = new Date();

    var nowLocal = now.toLocaleString('zh-TW', { timeZone: 'Asia/Taipei' });
    var closeTimeLocal = CLOSE_TIME.toLocaleString('zh-TW', { timeZone: 'Asia/Taipei' });

    Logger.log('Attempting to open form at: ' + nowLocal);
    Logger.log('Form ID: ' + form.getId());
    form.setAcceptingResponses(true);

    Utilities.sleep(1000);
    if (!form.isAcceptingResponses()) {
      Logger.log('Failed to open form!');
      return;
    }
    Logger.log('Form successfully opened at: ' + new Date().toLocaleString('zh-TW', { timeZone: 'Asia/Taipei' }));

    var minutesToClose = (CLOSE_TIME - now) / (1000 * 60);
    if (minutesToClose >= 1) {
      var trigger = ScriptApp.newTrigger('closeForm')
        .timeBased()
        .after(Math.max(1, minutesToClose) * 60 * 1000)
        .create();
      Logger.log('Close trigger set for: ' + closeTimeLocal + ' [Trigger ID: ' + trigger.getUniqueId() + ']');
    } else {
      Logger.log('Close time too close, closing immediately');
      form.setAcceptingResponses(false);
    }
  } catch (e) {
    Logger.log('Error in openForm: ' + e.toString());
  }
}

function closeForm() {
  try {
    var form = FormApp.getActiveForm();
    var now = new Date();

    var nowLocal = now.toLocaleString('zh-TW', { timeZone: 'Asia/Taipei' });

    Logger.log('Attempting to close form at: ' + nowLocal);
    Logger.log('Form ID: ' + form.getId());
    form.setAcceptingResponses(false);

    Utilities.sleep(1000);
    if (form.isAcceptingResponses()) {
      Logger.log('Failed to close form!');
    } else {
      Logger.log('Form successfully closed at: ' + new Date().toLocaleString('zh-TW', { timeZone: 'Asia/Taipei' }));
    }
  } catch (e) {
    Logger.log('Error in closeForm: ' + e.toString());
  }
}

function deleteExistingTriggers() {
  try {
    var triggers = ScriptApp.getProjectTriggers();
    for (var i = 0; i < triggers.length; i++) {
      if (triggers[i].getHandlerFunction() === 'openForm' ||
          triggers[i].getHandlerFunction() === 'closeForm' ||
          triggers[i].getHandlerFunction() === 'checkFormStatus') {
        ScriptApp.deleteTrigger(triggers[i]);
        Logger.log('Deleted trigger: ' + triggers[i].getHandlerFunction() + ' [ID: ' + triggers[i].getUniqueId() + ']');
      }
    }
  } catch (e) {
    Logger.log('Error in deleteExistingTriggers: ' + e.toString());
  }
}

function checkFormStatus() {
  try {
    var form = FormApp.getActiveForm();
    var now = new Date();

    var nowLocal = now.toLocaleString('zh-TW', { timeZone: 'Asia/Taipei' });
    var openTimeLocal = OPEN_TIME.toLocaleString('zh-TW', { timeZone: 'Asia/Taipei' });
    var closeTimeLocal = CLOSE_TIME.toLocaleString('zh-TW', { timeZone: 'Asia/Taipei' });

    Logger.log('Checking form status at: ' + nowLocal);
    if (now >= OPEN_TIME && now < CLOSE_TIME && !form.isAcceptingResponses()) {
      Logger.log('Form should be open but is closed - fixing');
      form.setAcceptingResponses(true);
      Utilities.sleep(1000);
      if (form.isAcceptingResponses()) {
        Logger.log('Form fixed - now open');
        var minutesToClose = (CLOSE_TIME - now) / (1000 * 60);
        if (minutesToClose >= 1) {
          ScriptApp.newTrigger('closeForm')
            .timeBased()
            .after(Math.max(1, minutesToClose) * 60 * 1000)
            .create();
        }
      } else {
        Logger.log('Failed to fix form status');
      }
    }
  } catch (e) {
    Logger.log('Error in checkFormStatus: ' + e.toString());
  }
}







搞定,收工!快來試試吧~





沒有留言:

張貼留言

歡迎大家一起留言討論!