2014年12月7日 星期日

(終極版)用Google Sheet搭配APP做出掃描QR code報到系統

晚上11:16 Posted by Envisioning U-Commerce Lab

這篇文章大部分介紹程式開發過程中循序漸進寫出來的九個版本,然後在課堂上逐一解說程式設計重點。如果要直接使用,請參考合作夥伴品科技撰寫的使用教學.....part1part2part3part4part5part6


在開始介紹此程式開發歷程之前,應有認知:  Google Apps Script: 3.3B weekly executions; 8.7M weekly end users; and 270K weekly developers.Container-bound Scripts v.s. Standalone Scripts




首先,參考第一版Google Sheet「報到 (v.1 GAS 取得 linked form's pre-filled response URL)」建立副本,由於原來的Google Sheet是已經有一個連動的Google Form(如下圖的[報到]工作表名稱前有紫色圖示),所以建立副本也應該有產生出兩個檔案(至雲端硬碟查看)




這個版本要解決的是本來要用人工操作查出Google Form的「取得預先填入的連結」之相關參數 :



複製起來的連結,重點就是能讓我們取得標示的這些參數: https://docs.google.com/forms/d/e/1FAIpQLSevp8h-1JsvRGBUu-1wqaKVqSvy1yqmFFhWinUDQTPAOUmCzQ/viewform?usp=pp_url&entry.897434678=111111111

但在這個版本已經改成用Script執行
getFormUrlopenByUrlgetItems自動取得,並以toPrefilledUrl產生(程式語法和邏輯會在課堂上說明,而且在程式碼裡面也有語法範例參考網址。)




然後,執行 > 執行函式 > getPrefilledResponse函式,第一次會跳出對話框要求授權,當然後續每一步都要同意允許(就省略擷取畫面囉)



等到函式執行完畢,查看 > 記錄,就可看到確實取得以往要人工操作「取得預先填入的連結」才能知道的相關參數









接著,用第二版Google Sheet「報到 (v.2 GAS 加上 launch QR code Apps' callback URLs)」建立副本,這個版本要解決的是本來要用人工操作準備寄給報到處工作人員的說明信件,改成由程式產生可自動呼叫QR Droid Private APP(Android版)QRafter APP(iOS版)執行掃描QRcode報到程序之啟動語法



Script程式重點是兜出啟動QR Droid Private APP(Android版)的語法以及啟動QRafter APP(iOS版)的語法。同樣,執行 > 執行函式 > getPrefilledResponse函式,就會再往下執行到callAppsLaunch函式。




等到函式執行完畢,查看 > 記錄,就可看到確實產生前述的啟動語法: http://qrdroid.com/scan?q=https://docs.google.com/forms/表單序號/formResponse?usp=pp_url%26entry.編號={CODE}    https://qrafter.com/x-callback-url/scan?browser=external&x-success=https://docs.google.com/forms/表單序號/formResponse?usp=pp_url%26entry.編號={CODE}







為了將前述產生的啟動語法能自動寄給報到處工作人員,就必須再寫個寄發郵件的函式,這部分放在第三版Google Sheet「報到 (v.3 GAS 加上 sendmail QR code Apps' callback URLs)」用它來建立副本吧。Script程式重點是在callAppsLaunch函式後半段把啟動語法準備好並傳給sendmail2buddy函式,加以組成MailApp.sendEmail的htmlBody,就能寄發郵件了。


同樣,執行 > 執行函式 > getPrefilledResponse函式,就會再往下執行到callAppsLaunch函式及sendmail2buddy函式 


但是你會發現一直停著"正在執行..."呢? 其實,這時候要到Spreadsheet從跳出的對話框(prompt)輸入收件人信箱(注意在Script程式第80行有此註解)就能寄發郵件了。



 
收到郵件後,就可看到內容確實有前述的啟動語法: http://qrdroid.com/scan?q=https://docs.google.com/forms/表單序號/formResponse?usp=pp_url%26entry.編號={CODE}    https://qrafter.com/x-callback-url/scan?browser=external&x-success=https://docs.google.com/forms/表單序號/formResponse?usp=pp_url%26entry.編號={CODE}







其實我們可以在Spreadsheet自訂選單來執行函式(如下圖的[自訂功能]選單就是用Script程式產生出來的),這樣就不用教使用者進入Script程式編輯模式去執行函式。接著,我們就來做自訂選單以執行getPrefilledResponse函式吧,這部分放在第四版Google Sheet「報到 (v.4 GAS 加上 a new menu in the Spreadsheet UI)」,用它來建立副本。Script程式重點是用addMenu自訂選單,並將其寫在onOpen函式內就能在Spreadsheet開啟後隨即呈現自訂選單。








剛剛試過跳出對話框,我們再來試另一種浮動視窗可呈現HTML語法的資訊這部分放在第五版Google Sheet「報到 (v.5 GAS 加上 a menu item of showModalDialog)」,用它來建立副本。Script程式重點是在自訂選單裡面多加個項目,來執行showModalDialog產生浮動視窗呈現宣告資訊




 






再來要處理報到通知信內需要顯示的QRcode了,用第六版Google Sheet「報到 (v.6 GAS 加上 [名單] 及 QR Code Generator API)」建立副本,會看到多了一個[名單]工作表,在這個工作表的第2列起的B,C,D欄就是讓使用者存放名單資料的,而點選自訂選單第二項功能就會執行generateQRcode函式,將A欄內容自動產生相對應的QRcode。Script程式重點是以getSheetByName指定要存取的是[名單]工作表,並以setActiveSheet生讓[名單]工作表被看到,再以getRange選定B欄資料以取得每個序號,用QR Gode Generator API產生QRcode,最後以setValues整批存入A欄(用到"=IMAGE()"公式儲存格裡的圖可顯示)






 



以往要將報到QRcode寄通知信給名單裡的人,是用Yet Another Mail Merge這個外掛程式來幫忙寄信,但現在就可以寫Script程式來寄信(在前述產生QRcode之後執行),這部分的處理程序較複雜,分成兩個版本來寫,前半段放在第七版Google Sheet「報到 (v.7 GAS 加上 display Sidebar inside Sheets editor)」,用它來建立副本。Script程式重點是以showSidebar產生側邊欄,有個表單讓使用者輸入要寄信的主旨及對象,表單填好送出就會依sendForm設定去執行sendmail2recipients函式,而其callback設定會回到ready執行google.script.host.close()側邊欄關閉





不過,以Script程式發送郵件數量是有限制的,每日額度一般Gmail是100人次、G Suite教育版則是1500人次,所以要用getRemainingDailyQuota得知當日餘額,顯示在側邊欄的表單按鈕上方紅字提醒使用者。










寫Script程式寄出報到QRcode通知信(要測試記得把D欄改成正確的信箱喔)這部分的後半段放在第八版Google Sheet「報到 (v.8 GAS 加上 seadmail QR code to each recipient)」,用它來建立副本。Script程式重點是getFomula取得A欄資料(裡面的公式為'=IMAGE("網址")'),並移除公式的'=IMAGE("")'而取得QRcode網址,再抓取圖檔準備做為信件內嵌圖像(inlineImage)加以組成MailApp.sendEmail的htmlBody,就能寄發郵件了。












暫時來到最後一個版本,要處理的是掃描QRcode進行報到(自動化完成Google Form報到提交)後能觸發執行一段檢查程式,以往必須要人工操作新增觸發條件,但現在就可以寫Script程式來執行觸發動作,這部分放在第九版Google Sheet「報到 (v.9 GAS 加上 TriggerBuilder for markAttendence)」,用它來建立副本。Script程式重點是newTrigger對於forSpreadsheet設定onFormSubmit表單資料進來時就觸發markAttendence函式執行。另外也做了檢查,若重複執行就要刪除先前設定的觸發條件





測試如下所示,工作人員事先安裝QR Droid Private APP(Android版)QRafter APP(iOS版),點擊網址就會執行掃描自動呼叫APP執行掃描QRcode報到程序。掃瞄報到通知信裡的QRcode就是報到序號,被掃描後(其內容就會置於網址的{CODE}位置)自動化完成Google Form提交回到Google Sheet查看[報到]工作表確實有一筆資料進來了,而因為已經設定資料進來就觸發markAttendence函式,自動檢查[名單]工作表對應的那筆編號被自動標示成綠底,這樣就可以核對整個報名表的報到狀況了















最後,要了解第九版的使用方式,請參考合作夥伴品科技撰寫的使用教學.....part1part2part3part4part5part6這次的終極版使用方式變得非常簡單了,使用者不需要管連動的Google Form參數、不需要進入Script程式編輯模式、不需要自己設定觸發條件、寄信動作也全部自動執行而不需要另找外掛程式來做。歡迎各位使用後給我們任何建議或經驗分享,請與品科技連繫。






完成第九版之後,我們又再加了一個彩蛋功能,提供現場查序號QRcode的網頁服務,這部分放在第X版Google Sheet「報到 (v.X GAS 加上 Query Web Page after Deployed)」,用它來建立副本。原本程式雖然是Container-bound Script,但也可以 發佈 > 部署為網路應用程式 成為Web APP,也就多了一個可用來查序號QRcode的網頁程式。而這個網頁程式的網址,就可以用自訂選單的第五項寄給報到處相關工作人員,只要在對話框輸入收件人信箱就能寄發郵件了。






不過,發佈為Web APP的設定沒辦法以程式做到,所以就只能自己手動設定囉,先在Spreadsheet執行 工具 > 指令碼編輯器。


在指令碼編輯器視窗開啟之後(什麼都不要亂動喔,切記! 切記! ),就只要執行 發佈 > 部署為網路應用程式,這裡要做的設定必須是 [專案版本 : 新增]、[將應用程式執行為 : 我]、[具有應用程式存取權的使用者 : 任何人,甚至是匿名使用者],再按下部署,最後就能得到該網頁程式的網址(與信件內的網址相同)







開啟該網頁程式,就可以測試查詢看看。不過,這個程式能正確執行的前提是[名單]工作表的A欄QRcode都已經產生了。輸入姓名或序號,就能顯示其QRcode,而在使用教學part5提到的可能有人沒帶QRcode,報到處最好還是安排一台電腦或平板開著這個網頁程式做為查詢之用,查到了就能執行掃描自動呼叫APP執行掃描QRcode報到程序。


這個程式也能判斷輸入的姓名或序號是否已經完成報到了,若是就不會出現QRcode







這個彩蛋中,網頁程式的網址則是透過getServicegetUrl取得。另外,更重要的配合 Container-bound Script 發佈 > 部署為網路應用程式 成為Web APP (Scripts bound to Sheets, Docs, Slides, or Forms can also become web apps, although this is uncommon.),程式碼.gs裡就要加上部署Web App的入口doGet()方式,以及跟其他後端程式一樣也要了解如何產生前端網頁的語法,就是用HtmlService.createHtmlOutputFromFile()向前端"吐出"呈現網頁,而前端網頁呈現的表單在按下submit按鈕的onclick設定是執行google.script.run,它是一個非同步的客戶端JavaScript API,它允許HTML頁面呼叫服務器端的Apps Script function