來到了第三天,想說我們先從一個簡單但實用的 Script 開始。但先講結論,如果你很急著用,可以直接使用這份 Add-On: Email Notification for Google Form。對於想知道怎麼做的人,讓我們開始吧!
細數常見的 Google 產品,有一個很常用的就是 Google 表單了,有的人拿它來記帳、有的人拿它來處理報名。而在使用上,有時會聽見的是——
我們今天就以回應這三個問題來玩 GAS 囉!
那我們就開始囉!首先先幫我開啟一個全新的 Google 表單,並進入到 GAS 的介面。
跟第二篇提到的一樣,第一次使用會需要按下「允許授權」。
我習慣將變數弄成一張參數表(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";
我們可以在主要執行的 .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");
}
這邊我們透過無痕模式來測試其功能的結果。
在這邊,可以透過程式碼設定,或是直接用 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」(有點饒口)
這個時候我們可以設定一個時間,透過 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 就完成囉!好,那這樣我們完成了第一題,那如果我想限定報名人數怎麼辦?
一樣在設定的參數表(Environment.gs
)中設定。如果我們希望表單最多只收 30 個回應,這邊就也再設置一個回應數量。如果想綁定不要重複報名,簡單的做法是限定必須登入才能回應(一個帳號只能回應一次)
var max_response_count = "30";
我們先設定一個 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();
}
這樣就好「檢查數量」囉!但目前的邏輯是「當報名超過人數時,之後的人就不能點開表單」。假設此時有一百人已經正在填表單,我們要怎麼樣讓「正在填表單的人」知道他沒有搶到票呢?此時就是進入我們第三題了。
在這邊,因為目前 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 Trigger 是 20 / user / script
。
好,那今天就是我們的 D3,明天 D4 會繼續介紹結合 Email 的使用方式,如果不想錯過可以訂閱按讚小鈴鐺(?),也歡迎留言跟我說你還想知道什麼做法/主題。我們明天見。