iT邦幫忙

2021 iThome 鐵人賽

DAY 3
4
Modern Web

整合 Google 服務的燃料——透過 Google Apps Script (GAS) 加速你的工作速度系列 第 3

D3- 如何透過 Google Apps Script 的 Trigger 來建立一個自動開啟、調整與關閉的 Google 表單?

  • 分享至 

  • xImage
  •  

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

今天的目標

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

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

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


Q1. 「我要怎麼設定 Google 表單時間到了自動開啟或結束」?

Step 1. 將 Google 表單綁定 GAS

那我們就開始囉!首先先幫我開啟一個全新的 Google 表單,並進入到 GAS 的介面。

跟第二篇提到的一樣,第一次使用會需要按下「允許授權」。

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";

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");
}

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

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

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

這邊也同時說明,要怎麼透過設定的參數來執行。我們透過 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();
};

其他設定 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 就完成囉!好,那這樣我們完成了第一題,那如果我想限定報名人數怎麼辦?


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

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(),這樣他們點開就會看到像這樣的畫面。

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

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

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


Q3. 「我要如何設定客製化表單的回應?」

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

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


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

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 Trigger20 / user / script

好,那今天就是我們的 D3,明天 D4 會繼續介紹結合 Email 的使用方式,如果不想錯過可以訂閱按讚小鈴鐺(?),也歡迎留言跟我說你還想知道什麼做法/主題。我們明天見。


上一篇
D2- Google Apps Script (GAS) 的環境設定、專案結構(Trigger)與四種打包方式
下一篇
D4- 如何透過 Google Apps Script 來整合 Google Form / Google Sheet 並自動寄出客製的 Email?
系列文
整合 Google 服務的燃料——透過 Google Apps Script (GAS) 加速你的工作速度30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言