工具服務
這一組服務不操作任何 Google 產品,而是幫你的程式本身做事:存設定、暫存資料、排隊、格式轉換、除錯、管理觸發。它們幾乎可以在任何觸發裡使用,多半不需要額外授權。總表與星等說明見 內建服務。
Logger 與 console
常用度:★★★★★ 常搭配的觸發:任何觸發
印出除錯訊息。Logger.log() 簡單直接;console 則有等級(log、info、warn、error),可以在 執行 頁依等級篩選,也能直接印出物件。
範例:在函式裡記錄關鍵步驟
function debugDemo() {
Logger.log("開始處理");
console.log({ rows: 12, sheet: "訂單" }); // 物件會展開顯示
console.warn("有 3 筆缺電話");
console.error("這行會被標成錯誤");
}
由觸發(沒有人在旁邊按執行)跑的函式,紀錄要到編輯器左側 執行 頁查。排查方法見 授權、配額與除錯。
PropertiesService
常用度:★★★★☆ 常搭配的觸發:任何觸發
一個「鍵 → 字串值」的小型儲存區,關掉腳本後仍然保留。分三種範圍:getScriptProperties()(整個專案共用)、getUserProperties()(每個使用者各一份)、getDocumentProperties()(綁在某個檔案)。單一值最大 9 KB,總量 500 KB。兩大用途:存金鑰(不要寫進程式碼),與記住處理進度。
範例:只處理上次之後新增的列
function processNewRows() {
const props = PropertiesService.getScriptProperties();
const sheet = SpreadsheetApp.getActive().getSheetByName("訂單");
const done = Number(props.getProperty("lastRow") || 1); // 上次處理到第幾列
const end = sheet.getLastRow();
if (end <= done) return; // 沒有新資料
const rows = sheet.getRange(done + 1, 1, end - done, 3).getValues();
rows.forEach((r) => Logger.log("處理:" + r[0])); // 換成你自己的處理
props.setProperty("lastRow", String(end)); // 成功後才更新進度
}
值一律是字串,存數字要轉字串、取出要轉回數字。放金鑰的做法見 LINE Bot 建立機器人。
CacheService
常用度:★★★☆☆ 常搭配的觸發:任何觸發
暫存區:值最大 100 KB、預設保留 10 分鐘、最長 6 小時,過期自動消失。用來避免重複讀取「不常變、又常被查」的東西。get 回傳 null 就代表沒有或已過期,要重新取得。
範例:把「設定」工作表快取 5 分鐘
function getSettings() {
const cache = CacheService.getScriptCache();
const cached = cache.get("settings");
if (cached) return JSON.parse(cached);
const values = SpreadsheetApp.getActive().getSheetByName("設定").getDataRange().getValues();
const settings = Object.fromEntries(values.map(([key, value]) => [key, value]));
cache.put("settings", JSON.stringify(settings), 300); // 300 秒
return settings;
}
快取只能存字串,物件要 JSON.stringify。另一個實用場景是 LINE Bot 的重複事件去重,見 上線注意事項。
LockService
常用度:★★☆☆☆ 常搭配的觸發:多人同時觸發的情境(onEdit、Web App、表單提交)
讓多個同時執行的腳本排隊。只要做的事是「先讀、再改、再寫回」,又可能被同時觸發,就要加鎖,否則兩個執行讀到同一個舊值,後寫的會蓋掉先寫的。
範例:產生不重複的流水號
function nextOrderNumber() {
const lock = LockService.getScriptLock();
lock.waitLock(10000); // 最多等 10 秒,逾時會丟例外
try {
const props = PropertiesService.getScriptProperties();
const n = Number(props.getProperty("orderNo") || 0) + 1;
props.setProperty("orderNo", String(n));
return "A" + String(n).padStart(4, "0"); // A0001、A0002…
} finally {
lock.releaseLock(); // 不管成功失敗都要釋放
}
}
Utilities
常用度:★★★★☆ 常搭配的觸發:任何觸發
各種小工具:日期格式化(formatDate)、暫停(sleep)、產生唯一編號(getUuid)、Base64、雜湊與簽章(computeHmacSha256Signature)、解析 CSV(parseCsv)。
範例一:日期、UUID 與 CSV
function utilitiesDemo() {
const now = Utilities.formatDate(new Date(), "Asia/Taipei", "yyyy-MM-dd HH:mm");
const id = Utilities.getUuid();
const rows = Utilities.parseCsv("姓名,分數\n小明,90\n小美,95"); // 二維陣列
Logger.log([now, id, rows.length]);
}
範例二:計算 HMAC-SHA256 簽章(許多 Webhook 服務用它驗證請求來源)
function sign(body, secret) {
const bytes = Utilities.computeHmacSha256Signature(body, secret);
return Utilities.base64Encode(bytes);
}
LINE 的 x-line-signature 就是這個算法,但 GAS 拿不到請求標頭,所以無法比對,原因見 LINE Bot 上線注意。
Session
常用度:★★★☆☆ 常搭配的觸發:任何觸發
取得執行者資訊:getEffectiveUser() 是「腳本以誰的身分在跑」,getActiveUser() 是「目前操作的人」,getScriptTimeZone() 是專案時區。在簡易觸發裡無法可靠取得目前使用者的身分;getActiveUser() 在某些情況也會回傳空字串。
範例:確認腳本是以誰的身分跑
function whoAmI() {
Logger.log("腳本執行身分:" + Session.getEffectiveUser().getEmail());
Logger.log("目前使用者:" + Session.getActiveUser().getEmail()); // 有時是空字串
Logger.log("專案時區:" + Session.getScriptTimeZone());
}
排查「為什麼信是用我的帳號寄出」時,就是先看 getEffectiveUser()。
ScriptApp
常用度:★★★☆☆ 常搭配的觸發:手動執行一次的設定函式
管理觸發器本身:建立、列出、刪除。還可以取得目前 Web App 的網址、取得 OAuth token 去呼叫 Google API。
範例:一次把專案的觸發設定好
function installTriggers() {
// 先清掉舊的,避免重複執行時疊出一堆
ScriptApp.getProjectTriggers().forEach((t) => ScriptApp.deleteTrigger(t));
ScriptApp.newTrigger("sendReport")
.timeBased()
.everyDays(1)
.atHour(8)
.create();
ScriptApp.newTrigger("onEditInstalled")
.forSpreadsheet(SpreadsheetApp.getActive())
.onEdit()
.create(); // 可安裝的 onEdit,能寄信、開別的檔案
}
installTriggers 只在編輯器手動跑一次。可安裝觸發的完整選項見 觸發條件。
XmlService
常用度:★☆☆☆☆ 常搭配的觸發:時間驅動、doPost
解析與產生 XML。現在多數 API 用 JSON,主要用在讀 RSS 或舊系統。
範例:讀取 RSS 並印出文章標題
function readRss() {
const xml = UrlFetchApp.fetch("https://example.com/feed.xml").getContentText(); // 換成你的 RSS 網址
const items = XmlService.parse(xml)
.getRootElement()
.getChild("channel")
.getChildren("item");
items.forEach((item) => Logger.log(item.getChildText("title")));
}
GroupsApp
常用度:★☆☆☆☆ 常搭配的觸發:時間驅動、選單。僅限 Google Workspace 網域
查詢 Google 群組的成員。一般用途是「用群組當權限名單」:把同事加進群組,程式就依群組判斷誰能用某個功能。
範例:檢查某人是否在「staff」群組
function isStaff(email) {
const group = GroupsApp.getGroupByEmail("staff@your-domain.com");
return group.hasUser(email);
}
進階 Google 服務
常用度:★★★☆☆ 常搭配的觸發:依用途而定
進階服務是官方 Google API 的薄包裝,內建服務做不到,或需要更完整的功能時使用,例如 Sheets API、Drive API、Gmail API、Calendar API、Docs API、People API(用來取代已棄用的 ContactsApp)。它們必須先啟用:編輯器左側 服務 旁的 +,選服務後按 新增。官方建議:有進階服務時優先用它,找不到才用 UrlFetchApp 自己呼叫。
範例:用 Sheets API 讀取一段範圍
function readWithSheetsApi() {
const id = SpreadsheetApp.getActive().getId();
const res = Sheets.Spreadsheets.Values.get(id, "工作表1!A1:C10");
Logger.log(res.values);
}
Sheets 這個全域物件要先啟用進階服務才存在。官方說明:進階 Google 服務。