做 Google 試算表自動化,第一步常卡在「到底要改哪個分頁?」getSheetByName() 就是那把鑰匙:用分頁名稱,準確拿到要動手的頁籤。
本篇文章會盡可能說明內容,內容涵蓋最小可用的範例、怎麼避免找不到分頁、名稱改了怎麼辦。也會補上常見坑點(例如大小寫、空白字元、綁定腳本 vs. 獨立腳本)和實用的可複用函式。
希望讀完你不只會用,還能寫出耐改名、耐擴充、可交接的腳本。
目錄
{tocify} $title={目錄}
為什麼一定要會 getSheetByName()
在自動化報表、資料清洗或產生月報時,你幾乎都會「按工作表名稱」去定位資料頁籤。getSheetByName(name) 就是拿到指定分頁(Sheet)的最快方式:給它一個精準的分頁名稱,回傳對應的 Sheet 物件,沒有就回傳 null。這是官方行為定義,不是鄉野傳說。
快速上手:基本語法與最小可用範例
基本語法
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName('原始資料'); // 找不到會回傳 null
if (!sheet) throw new Error('找不到「原始資料」工作表');
getSheetByName() 精準比對名稱,大小寫、空白、全形半形都算數;找不到只會回傳 null,不會直接丟例外。
讀寫範例:把 A1 寫進時間戳記
function writeTimestamp() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName('原始資料');
if (!sheet) throw new Error('找不到「原始資料」工作表');
sheet.getRange('A1').setValue(new Date());
}
建立後再取用:不存在就新建
function getOrCreateSheetByName(name) {
const ss = SpreadsheetApp.getActiveSpreadsheet();
let sheet = ss.getSheetByName(name);
if (!sheet) sheet = ss.insertSheet(name);
return sheet;
}
insertSheet(name) 可以直接用名稱建立分頁
正確的專案開檔方式(超重要)
綁定腳本(從試算表 → 擴充功能 → Apps Script 進入)時,用 SpreadsheetApp.getActiveSpreadsheet() 才有「作用中的檔案」。如果你在獨立腳本環境跑它,getActiveSpreadsheet() 可能是 null,任何串接方法都會變成 Cannot read properties of null 這類錯。
若腳本必須跨檔案操作,改用 openByUrl() 或 openById() 自行指向目標檔案,而不要期待「作用中」檔案。
進階:用 Sheet ID 穩固指向,避免「被改名就爆」
名字會被改,但 Sheet ID 幾乎不會變。Apps Script 現在提供:
sheet.getSheetId() 取得分頁的唯一 ID
ss.getSheetById(id) 直接以 ID 取回分頁
這對「月度複製樣板後重新命名」這類流程很重要:先抓到 ID,之後就算名稱被改寫,仍能穩定取到同一個分頁。
示例:寫入時盯 ID 而非名稱
function safeWriteById(sheetId, a1, value) {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetById(sheetId);
if (!sheet) throw new Error(`找不到 ID=${sheetId} 的工作表`);
sheet.getRange(a1).setValue(value);
}
樣板複製:先以樣板建立,再改名
你可以用 insertSheet(newName, index, { template: templateSheet }) 直接以某分頁為模板,產生新分頁並命名。這招在建置週/月度報表超好用。
function createFromTemplate(newName, templateName = 'TEMPLATE') {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const tpl = ss.getSheetByName(templateName);
if (!tpl) throw new Error('找不到樣板分頁');
// 在第 1 個位置插入,並以樣板複製內容/格式
ss.insertSheet(newName, 1, { template: tpl });
}
常見錯誤與雷點
1. TypeError: Cannot read properties of null (...)
成因:
getActiveSpreadsheet() 在獨立腳本或特定執行環境拿不到作用中檔案 → 變 null。
解法:
改用 openByUrl() / openById() 明確指定;或把腳本綁回試算表再跑。
2. getSheetByName() 回傳 null(名稱對不起來)
成因:
名稱打錯、含多餘空白(特別是全形空白)、大小寫不同、或分頁真的不存在。
排查:
直接在 UI 檢查分頁名稱;也可以在程式中列出 ss.getSheets().map(s => s.getName()) 幫自己核對。
公式世界裡,工作表名稱與儲存格引用用 ! 分隔,若名稱內有空白或特殊字元,公式需要單引號包起來('表名 with space'!A1),這常導致你以為「名字沒問題」,其實程式碼與 UI 名稱仍不一致。
3. 「未解析的工作表名稱」(Unresolved sheet name)
情境:你改了分頁名稱,但一堆公式或外掛、串接工具仍指向舊名,報錯。
解法:
先建立新分頁,再把資料搬過去、最後才刪舊分頁;或改以 Sheet ID 綁定資料流程。
4. 名稱衝突
情境:複製分頁或改名時,系統回你「名稱已存在」。
說明:工作表內部名稱通常必須唯一;若你用 API/自動化做批次複製,流程設計不良會撞名而失敗。先建立再延後改名,或以時間戳記附尾避免衝突。
5. 你以為抓到「工作表」,其實抓到「作用中的分頁」
常見錯把 getActiveSheet()(回傳 Sheet)當成 Spreadsheet,接著又呼叫 getSheetByName() 就爆「XXX 不是函式」。
記得:getSheetByName() 是 Spreadsheet 的方法,不是 Sheet 的。
6. 執行逾時 / 偶發卡住
偶爾社群回報 getSheetByName() 在特定檔案卡住的案例(大量分頁、外部資料源、權限異常)。建議用重試或降頻處理,並先確認檔案本身沒有資料來源執行中的衝突。
問題集
Q1. 我需要跨檔案操作特定分頁,還能用 getSheetByName() 嗎?
A:可以,但你得先用 openByUrl()/openById() 打開「那一份檔案」後再呼叫 getSheetByName()。不要用 getActiveSpreadsheet(),因為那是「眼前作用中」的檔案。
Q2. 改名會不會讓程式掛掉?
A:會。如果你是用名稱取分頁,改名就取不到。把關鍵流程改成 sheetId 方式最穩。
Q3. 為什麼我用 getActiveSpreadsheet() 會拿到 null?
A:大多是因為你不是在綁定腳本環境跑,或用到了不會產生「作用中試算表」的執行路徑。
Q4. 表內可以有兩個同名分頁嗎?
A:一般 UI 流程不會讓你重名;若自動化流程撞名,API 會回錯。請在複製/改名的流程上設計避重邏輯。
