來到了第七天。老樣子,先講推薦的速解,如果你很急著用,這些 Add-On 可以幫上忙,第一是 Form to Calendar 但它十個 event 後就要收費; 第二是 Form Scheduler 有七天內要回應的限制。自己寫的好處是,如果你一天突然要客製化,那這篇文章應該幫的上忙。對於想知道怎麼做的人,讓我們開始吧!
答案會在今天的文章中!
電腦還不普及時,會到市立圖書館借電腦,那時需要用圖書證到櫃台,詢問哪個時段可以使用,然後就可以用個三十分鐘;又或是之前在做會議室的簡單借用時,老闆就問說能不能讓行事曆分開,不然這樣看得很累。所以今天的關鍵問題是...
特別提醒,這邊的「客製化」Email,因為會限定是要 Google 產品,一般人會是 Gmail,或是企業與組織的 Google Workspace(簡單來說你的學校、組織的基本上是用 Google Drive 傳檔案的話,基本上就是)。那我們就開始吧!
前三步跟 D6 差不多,會調整程式碼,但借用一下影片。
一樣開啟一個表單,並串回應與GAS。
一樣執行時會有「需要驗證」出現,讓我借用一下 D2 的影片。
假設我們表單搜集到這樣的回應。
這個步驟也跟 D6 差不多,所以直接借用程式碼。
function readData() {
let sheet = SpreadsheetApp.getActiveSheet();
let range = sheet.getRange(2,2,2,5);
let display_data = range.getDisplayValues();
Logger.log(display_data);
return data
}
讀起來的樣子,讀起來沒問題。
這步也跟 D6 很像,主要是做資料的轉換,這次我們先將要處理的時間用 Google Sheet 搞定。
同時調整 Step 2 的程式把,把 let range = sheet.getRange(2,2,2,5);
換成 let range = sheet.getRange(2,2,2,7);
。因為我們多抓了兩欄,也因為我直接把資料處理在 Google Sheet 上搞定,所以不用再 getDisplayValues
,更改過後會長這樣。
function readData() {
let sheet = SpreadsheetApp.getActiveSheet();
let range = sheet.getRange(2,2,2,7);
let data = range.getValues()
return data
}
好,來看看能不能運作。
接著我們一樣來檢查要給 Calendar 的資料。因為比較複雜的 Date Object 已經讓 Google Sheet 搞定,這邊我們就可以簡化程式碼成...
function setUpCalendar() {
let data = readData();
for (let i = 0; i < data.length; i++) {
let request = data[i];
let user = request[0];
let meeting_room = request[1];
let title = user + '_Meeting_Room_' + meeting_room;
let start_time = request[5];
let end_time = request[6];
Logger.log(title + '\n' + start_time + '\n' + end_time);
}
}
一樣試跑看看能不能運作。
看起來可以!好,上面三步驟跟 D6 差不多,就比較快速帶過。接著會是今天的重點,開啟並設置不同的 Calendar。
首先,如果你還沒有固定給「會議室」的日曆的話,就先建立日曆。
建立好後,可以在「設定」這邊取得日曆的 ID。
接著,將兩個 ID 輸入到 GAS 的 environment.gs
當中。下面這段錄影片當時寫太快了,這邊我們用為全域變數,用 var
比較合適。
var room_A_ID = "icqs6thnruqt1fvfrqhel7glns@group.calendar.google.com"
var room_B_ID = "rnd3j7e3end2kjc60eo9ncpens@group.calendar.google.com"
然後在昨日基礎的程式碼上加上「分派給會議室 ID」的部分,就完成了。這邊簡單的寫,如果當會議室很多時,可以考慮另外用一個 Mapping 會議室 和 Calendar ID 的試算表。
function setUpCalendar() {
let data = readData();
for (let i = 0; i < data.length; i++) {
let request = data[i];
let user = request[0];
let meeting_room = request[1];
let title = user + '_Meeting_Room_' + meeting_room;
let start_time = request[5];
let end_time = request[6];
let calendar_id;
if (meeting_room=="A"){
calendar_id = room_A_ID;
} else if (meeting_room=="B"){
calendar_id = room_B_ID;
}
let cal = CalendarApp.getCalendarById(calendar_id);
let event = cal.createEvent(title, start_time, end_time);
Logger.log('Create Calendar of '+ meeting_room +' \n'+ title + '\n' + start_time + '\n' + end_time);
}
}
完整起來長這樣。
以上就完成了我們的 Q1。但我們實際使用上,更想看到的是一但有人填寫了表單,就更新到行事曆上,這個要怎麼做到?讓我們來看看 Q2。
前面四個 Step 跟 Q1 一樣,這邊主要說明「要加上的部分」,也就是 Step 4 。
onEdit
Trigger 來自動更新你的表單onEdit(e)
是一個 Trigger,每當有人更新表單時,這個 Trigger 就會啟動。我們透過一段簡單的程式碼來看它的功能,以下這段程式碼是會跳出說,工作表中剛更動的數值。
function onEdit(e) {
// Set a comment on the edited cell to indicate when it was changed.
var range = e.range;
SpreadsheetApp.getActiveSpreadsheet().toast(range.getValues());
}
實際用起來,會長這樣——
瞭解其基本功能後,我們來看要怎麼樣「結合」起我們 Q1 的部分。
還記得 Step 2 我們有先對「時間」與「日期」做處理嗎?這邊我們要先設定說它的處理是會延續下去的。其實就是很單純的讓公式套用而已——
那接下來,就是將 onEdit()
和 setUpCalendar
進行整合。先給一個最簡單的整合方式,把兩個程式碼合併,這個合併需要一些調整。像是拿掉 setUpCalendar
第一段並加上個可傳入的變數。同時,請將 onEdit()
轉為其他「非預設」的 function Name(onOpen()
也是預設)。簡單來說是改名,主要原因是因為待會我們要用系統的 Trigger。如果用 onEdit(e)
會出現些 BUG(底了很久QQ)。我改成autoUpdate
,並直接寫死說我要取最新更新的那列(e.range / range.getRow()
)的七個欄(let data = ...
)。
function setUpCalendar(data) {
// let data = readData();
...
}
function autoUpdate(e) {
// Set a comment on the edited cell to indicate when it was changed.
let range = e.range;
let new_row = range.getRow();
let data = SpreadsheetApp.getActiveSheet().getRange(new_row,2,1,7).getValues();
setUpCalendar(data)
}
好,接著我們來設定 Trigger,這邊因為是示範,所以我是直接貼上一筆新的資料,如果是實際在使用表單,條件請改成「表單送出時」(要先確認表單有連接到 Google Sheet 喔,請看 Step 1)
好,設定完後我們來看看功能是不是有運作。
看起來有,恭喜!完成了自動設定表單囉!再讓我們看看今天的全部程式碼——
function readData() {
let sheet = SpreadsheetApp.getActiveSheet();
let range = sheet.getRange(2,2,2,7);
let data = range.getValues()
return data
}
function setUpCalendar(data) {
for (let i = 0; i < data.length; i++) {
let request = data[i];
let user = request[0];
let meeting_room = request[1];
let title = user + '_Meeting_Room_' + meeting_room;
let start_time = request[5];
let end_time = request[6];
let calendar_id;
if (meeting_room=="A"){
calendar_id = room_A_ID;
} else if (meeting_room=="B"){
calendar_id = room_B_ID;
}
let cal =CalendarApp.getCalendarById(calendar_id)
let event = cal.createEvent(title, start_time, end_time);
Logger.log('Create Calendar of '+ meeting_room +' \n'+ title + '\n' + start_time + '\n' + end_time);
}
}
function autoUpdate(e) {
// Set a comment on the edited cell to indicate when it was changed.
let range = e.range;
let new_row = range.getRow();
let data = SpreadsheetApp.getActiveSheet().getRange(new_row,2,1,7).getValues();
setUpCalendar(data)
}
一樣提醒,行事曆有 Quota 限制。好,那今天就是我們的 D7,明天 D8 會繼續介紹結合如何將 Google Calendar 上的事件與更新全部列出到 Google Sheet 上。如果有疑問可以到 Facebook Group,想開很久這次鐵人賽才真的開起來哈哈哈,歡迎來當 Founding Member。如果不想錯過可以訂閱按讚小鈴鐺(?),也歡迎留言跟我說你還想知道什麼做法/主題。我們明天見。
您好,非常謝謝您清楚的教學
正在使用教學試著操作
但遇到一個問題
我使用表單回復時會觸發trigger的方式
但當我讀取表單的getLastRow() //讀取最新一筆回復
會顯示[, , , ]
但讀取getLastRow()-1就能讀取到前一次輸入的資料 //讀取上一筆回復
您好,想詢問一下,關於上面這段程式碼,我是參考您的做法下去微調,但卻一直無法成功,我是想做到google表單可以直接同步行事曆的狀態,再麻煩您指教,謝謝。