Google Apps Script 建立一個自動開啟、調整與關閉的 Google 表單 (2021 鐵人賽 D3)

來到了第三天,想說我們先從一個簡單但實用的 Script 開始。但先講結論,如果你很急著用,可以直接使用這份 Add-On: Email Notification for Google Form。對於想知道怎麼做的人,讓我們開始吧!

本篇的目標

細數常見的 Google 產品,有一個很常用的就是 Google 表單了,有的人拿它來記帳、有的人拿它來處理報名。而在使用上,有時會聽見的是——

  1. 「我要怎麼設定 Google 表單時間到了自動開啟或結束」?
  2. 「要怎麼設定當報名人數到達三十人,自動關閉的表單」?
  3. 「我要如何設定客製化表單的回應?」

我們今天就以回應這三個問題來玩 GAS 囉!


要怎麼設定 Google 表單時間到了自動開啟或結束

Step 1. 將 Google 表單綁定 GAS

那我們就開始囉!首先先幫我開啟一個全新的 Google 表單,並進入到 GAS 的介面。
Google Apps Script 建立一個自動開啟、調整與關閉的 Google 表單 (2021 鐵人賽 D3)插图

跟第二篇提到的一樣,第一次使用會需要按下「允許授權」。
Google Apps Script 建立一個自動開啟、調整與關閉的 Google 表單 (2021 鐵人賽 D3)插图1

Step 2. 設定想要的變數

我習慣將變數弄成一張參數表(Environment.gs),這邊先設定我想要的參數,包括建立一個 form 的 object 呼叫 GAS 的 FormApp 並設定「目前綁定的表單」(如果你是從「第二張」的「進入方式一」,也就是沒有綁定者,這邊可以透過 FormApp.openById 來設定)。

var form = FormApp.getActiveForm();
// or var form = FormApp.openById('1234567890abcdefghijklmnopqrstuvwxyz');

再來我們來設定時間,這邊我希望在中午 12 點開啟,下午 5 點結束,先設定一個簡單的時間。這邊我寫成 “2021-09-03 12:00″(YYYY-MM-DD HH:MM 的形式),實際開發時可以多考慮時區,不管是 GAS 的執行時區,以及設定時間的時區(可以參考第二篇的補充:時區設置)

var start_time = "2021-09-03 12:00";
var end_time = "2021-09-03 17:00";
Google Apps Script 建立一個自動開啟、調整與關閉的 Google 表單 (2021 鐵人賽 D3)插图2

Step 3. 設定表單開啟與結束

我們可以在主要執行的 .gs 檔案中,寫上「開啟」與「結束」的程式。在這邊,我們透過的功能叫 setAcceptingResponses() 。並透過 Logger.log() 來通知執行的程式。

function startAcceptResponse() {
    form.setAcceptingResponses(true);
    Logger.log("Your Google Form is opening");
}

function stopAcceptResponse() {
    form.setAcceptingResponses(false);
    Logger.log("Your Google Form is closing");
}

這邊我們透過無痕模式來測試其功能的結果。

Google Apps Script 建立一個自動開啟、調整與關閉的 Google 表單 (2021 鐵人賽 D3)插图3

Step 4. 設定 Time-Based Trigger 來開啟與關閉表單

在這邊,可以透過程式碼設定,或是直接用 GAS 的 UI 來執行。透過 UI 的方式比較直觀,就是設定你要幾點啟動開啟(startAcceptResponse)或結束(stopAcceptResponse)。

Google Apps Script 建立一個自動開啟、調整與關閉的 Google 表單 (2021 鐵人賽 D3)插图4

這邊也同時說明,要怎麼透過設定的參數來執行。我們透過 ScriptApp.newTrigger() 來創造。其中 newTrigger() 裡面要放的是你要執行的 function 名,以及要設定是以時間為基底(timeBased()),並在指定(at(date))的時間(new Date())會觸發。

function setTrigger(){
   ScriptApp.newTrigger("startAcceptResponse")
            .timeBased()
            .at((new Date(start_time)))
            .create();

    ScriptApp.newTrigger("stopAcceptResponse")
            .timeBased()
            .at((new Date(end_time)))
            .create();
};
Google Apps Script 建立一個自動開啟、調整與關閉的 Google 表單 (2021 鐵人賽 D3)插图5

其他設定 Time-Based Trigger 的方式 還有依據日期(atDate(year, month, day))、設定每小時都 Trigger 一次等(everyHours(n))。

這樣就完成了基本的設定。如果是設定單次性的 Trigger,那其實這樣就可以了,因為到其它會自動關掉。但如果是一個定期檢查的呢?總不會希望它一直吃自己的 GAS Quota吧?那我們可以設定一個「一次性的清理 Trigger 的 Trigger」(有點饒口)

Step 5. 幫專案設定一個不會再啟動的清理時間

這個時候我們可以設定一個時間,透過 deleteTrigger() 把所有 trigger 都刪掉。

function deleteTriggers() {
    var triggers = ScriptApp.getProjectTriggers();
    for (var i = 0; i < triggers.length; i++) {
      ScriptApp.deleteTrigger(triggers[i]);
    }
}

但,那如果我們只打算清理一個 Trigger 呢?可以加入透過加入一個 if 和 getHandlerFunction() 來達到。

function deleteTriggers() {
    var triggers = ScriptApp.getProjectTriggers();
    for (var i = 0; i < triggers.length; i++) {
        if (Triggers[i].getHandlerFunction() == "stopAcceptResponse") {
          ScriptApp.deleteTrigger(triggers[i]);
      }
    }
}

寫完後,最後再透過 Step 4 設定個一次性的 Trigger 來排定刪除 Trigger 就完成囉!好,那這樣我們完成了第一題,那如果我想限定報名人數怎麼辦?


要怎麼設定當報名人數到達三十人,自動關閉的表單

Step 1. 將 Google 表單綁定 GAS(同 Q1 )

Step 2. 設定想要的變數(大部分同 Q1 )

一樣在設定的參數表(Environment.gs)中設定。如果我們希望表單最多只收 30 個回應,這邊就也再設置一個回應數量。如果想綁定不要重複報名,簡單的做法是限定必須登入才能回應(一個帳號只能回應一次)

var max_response_count = "30";

Step 3. 設定表單開啟與結束(沿用 Q1 的程式)

Step 4. 設定 Trigger 來關閉表單

我們先設定一個 Trigger 叫做 checkCount(),我們預期它每次要在每次表單送出(Submit)時檢查人數。

function checkCount(){
    if (FormApp.getActiveForm().getResponses().length >= max_response_count) {
        stopAcceptResponse();
        form.setCustomClosedFormMessage("報名已經額滿了");
    } else{
        Logger.log("報名成功 +1");
    }
}

如果你想讓後進者(也就是關閉表單後才點開連結的人)看到客製化訊息,記得用 setCustomClosedFormMessage(),這樣他們點開就會看到像這樣的畫面。Google Apps Script 建立一個自動開啟、調整與關閉的 Google 表單 (2021 鐵人賽 D3)插图6

再來,我們透過 onFormSubmit() 來在送出時檢查是不是已經超過人數了。也可以設定其他的限制,像是預算表總額金額超過一定時跳提醒等等。那在寫好之後,我們一樣可以透過程式碼來設定,或是一樣透過程式碼來達成。

function setLimitTrigger(){
    ScriptApp.newTrigger("checkCount")
            .forForm(form)
            .onFormSubmit()
            .create();
}
Google Apps Script 建立一個自動開啟、調整與關閉的 Google 表單 (2021 鐵人賽 D3)插图7

這樣就好「檢查數量」囉!但目前的邏輯是「當報名超過人數時,之後的人就不能點開表單」。假設此時有一百人已經正在填表單,我們要怎麼樣讓「正在填表單的人」知道他沒有搶到票呢?此時就是進入我們第三題了。


我要如何設定客製化表單的回應?

在這邊,因為目前 Google 表單並不支援動態調整,也就是說,正在填表單的人,不會更新到最新版本的回應。所以目前的方式比較陽春,是需要透過「另行通知」來執行。

所以目前 work-around 的做法會是,搜集 Email 並在「填完表單」的頁面說「會寄結果信給您」,在結果通知信中顯示「報名成功」或「報名失敗」。因為 Email 的設定也是個不小的主題,詳細的作法會在明天的文章中介紹。

Google Apps Script 建立一個自動開啟、調整與關閉的 Google 表單 (2021 鐵人賽 D3)插图8

好,所以今天完整的程式碼如下——

var form = FormApp.getActiveForm();

function setTrigger(){
   ScriptApp.newTrigger("startAcceptResponse")
            .timeBased()
            .at((new Date(start_time)))
            .create();

    ScriptApp.newTrigger("stopAcceptResponse")
            .timeBased()
            .at((new Date(end_time)))
            .create();
};

function deleteTriggers() {
    var triggers = ScriptApp.getProjectTriggers();
    for (var i = 0; i < triggers.length; i++) {
        if (Triggers[i].getHandlerFunction() == "stopAcceptResponse") {
          ScriptApp.deleteTrigger(triggers[i]);
      }
    }
}

function checkCount(){
    if (FormApp.getActiveForm().getResponses().length >= max_response_count) {
        stopAcceptResponse();
        form.setCustomClosedFormMessage("報名已經額滿了");
    } else{
        Logger.log("報名成功 +1");
    }
}

function setLimitTrigger(){
    ScriptApp.newTrigger("checkCount")
            .forForm(form)
            .onFormSubmit()
            .create();
}

如果沒有程式底子/時間怎麼辦?

沒關係,今天講的內容其實已經有為 Google Developer Expert 將它做成了 Add-On,所以直接使用 Email Notification for Google Form 就可以了。但對於想客製化、開發的人來說,希望透過今天的流程,有幫你更了解一些。

最後小提醒,也別設定太多 Trigger 喔,記得 Quota for Trigger 是 20 / user / script 

目錄

Scroll to Top