如果你常在試算表裡新增分頁、做月報或日報,應該遇過「命名一團亂、連結對不上」的慘劇。
其實只要用到一個方法——setName()——就能把改名這件事變得可預測、可複用。
本篇文章用白話步驟帶你上手:怎麼安全改名、什麼時候要先比對再改、要不要幫名字做清洗,以及批次改名該注意哪些節點。也會示範幾個日常情境:從 A1 取名、複製模板自動加日期、避免撞名加尾碼。文末整理雷點清單與最佳實務,讓你少走彎路,交出去的表格可讀又耐看。希望能幫助到需要的您。
目錄
{tocify} $title={目錄}
為什麼要在程式裡改「工作表名稱」?
把工作表(Sheet)命名這件事自動化,有幾個直接好處:
資料管控更穩:自動命名可避免手動拼錯、漏改,報表鏈結(查詢、驗證、保護、命名範圍…)就不會亂。
排程&版本化:例如每天複製模板 → 以日期命名,舊表自動封存或鎖權限。
大規模作業:一次處理數十/上百張分頁,靠程式比手改可靠太多。
在 Google Apps Script 中,工作表物件 Sheet 提供 setName(name),可以把分頁名稱改成你指定的字串,方法本身也支援鏈式呼叫(回傳 Sheet)。官方參考文件白紙黑字寫得很清楚,還附範例程式碼與授權範圍說明。
核心概念 3 行搞懂
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName('原本名稱');
sheet.setName('新的名稱'); // 回傳 Sheet,可繼續鏈式呼叫
setName(name: string)
把分頁改名,回傳同一張 Sheet(便於鏈式寫法)。
權限/授權範圍:需要 spreadsheets 或 spreadsheets.currentonly。
getName() 可讀取目前名稱,常見於比對「舊名 ≠ 新名才改」。
快速上手:4 個最常見情境
直接把目前分頁改名
function renameActive() {
const sheet = SpreadsheetApp.getActiveSheet();
sheet.setName('報表v2');
}
省話重點:改名動作是立即的,不用 flush()
先確認不同再改,避免不必要動作
function renameIfNeeded() {
const sheet = SpreadsheetApp.getActiveSheet();
const want = '銷售月報';
if (sheet.getName() !== want) sheet.setName(want);
}
這招能避開一些觸發器(例如 onEdit)被重複觸發的意外。
批次把一串分頁依照清單改名
function batchRenameByList() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const map = [
['Sheet1', '概況'],
['Sheet2', '訂單'],
['Sheet3', '庫存']
];
map.forEach(([from, to]) => {
const sh = ss.getSheetByName(from);
if (sh && sh.getName() !== to) sh.setName(to);
});
}
複製模板 → 依日期(或欄位值)命名
function duplicateTemplateWithDateName() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const tpl = ss.getSheetByName('TEMPLATE');
const ymd = Utilities.formatDate(new Date(), Session.getScriptTimeZone(), 'yyyy-MM-dd');
const copy = tpl.copyTo(ss).setName(`日報_${ymd}`); // 鏈式改名
}
這種流程常見在「每日產生工作表」的排程腳本。遇到「名稱已存在」要先處理(下面雷點有解)。官方文件也示範 copyTo() 的用法;setName() 的鏈式呼叫是被支援的。
進階:從儲存格動態命名
從 A1 讀值當作新名稱,並做一點清洗(去頭尾空白、換行、過長截斷):
function renameByCellA1() {
const sh = SpreadsheetApp.getActiveSheet();
const raw = String(sh.getRange('A1').getValue() || '');
let name = raw.trim().replace(/\s+/g, ' ');
if (name.length === 0) throw new Error('A1 為空,無法命名');
if (name.length > 100) name = name.slice(0, 100); // 和 UI 體感一致,保守截斷
if (name !== sh.getName()) sh.setName(name);
}
備註:官方 setName() 文件沒有硬性「長度上限」說明,但實務上工作表分頁在 UI 呈現過長會難讀,建議自訂上限(例如 60–100 字元)。setName() 本身的使用與授權屬性以官方文件為準。
命名規範&限制:哪些要注意?
名稱必須在同一份試算表中唯一:
同名會失敗(實務上常見於「先複製、後改名」但同名已存在)。工作流程或第三方工具也會拋出「name already exists」之類的錯誤。
字元:
Google Sheets 分頁名相對寬鬆(包含空白、中文、Emoji 通常可用)。遇到跨系統對接(例如把分頁名拿去當檔名或資料表鍵)才需要限制字元集。
觸發器:
onEdit、onChange 之類事件可能因為改名而連鎖觸發其它流程,要小心迴圈或重複執行。
官方對 Sheet.setName() 的定義與授權需求請以參考文件為準;若你同時在 Drive 端改檔名(DriveApp.File.setName()),是另一個不同層級,別混淆。
常見錯誤與雷點
1. 同名衝突(名字已被用)
症狀:複製模板後馬上改名,偶發失敗;或報「名稱已存在」。
處理:
function safeSetName(sh, want) {
const ss = sh.getParent();
const exists = ss.getSheets().some(s => s.getName() === want);
if (exists) {
const ts = Utilities.formatDate(new Date(), Session.getScriptTimeZone(), 'HHmmss');
want = `${want}_${ts}`; // 或加流水號
}
return sh.setName(want);
}
在某些整合工具/流程裡,確實會看到「name already exists」的錯誤訊息,需要先做重名檢查。
2. onEdit/onChange 觸發「雙重複製」
症狀:用 onEdit 搭 copyTo(),有時產生兩張副本(其中一張留著「Copy of …」)。
原因:同一事件被多次觸發(例如多儲存格編輯、保護規則、外掛同步),或你的邏輯在改名前後又被呼叫一次。
對策:
用「旗標欄位」或「鎖」機制(PropertiesService)保證單次執行。
嚴格限定觸發條件(只在特定欄/列變動時執行)。
把「複製→改名」封成一個函式並加上重入保護。
社群討論曾提到 .copyTo() 在事件環境下偶見雙生,實務要做好防呆。
3. 從儲存格取名含不適合字元
症狀:名稱包含過多空白、換行、看起來像公式片段,之後難以搜尋或外部系統不吃。
對策:前面「清洗字元」的範例直接收斂成單一空白、刪除控制字元,必要時自訂白名單(例如只留中英數、空白、底線)。
4. 誤把「命名範圍」的 setName() 當「工作表改名」
NamedRange.setName() 是命名範圍用,不是改分頁名;兩者 API 不同、行為不同。官方也各自有文件。
5. 改名後公式「找不到分頁」
症狀:跨表參照或 Apps Script 程式碼還在使用舊名稱,導致 #REF! / 未解析的工作表名稱。
對策:
在改名前列出受影響的範圍(用 TextFinder 找 '舊名'! 片段),改名後一起更新。
程式碼端盡量用 sheet.getSheetId()(數字 ID)當索引,名稱只用於呈現;需要時用 ID 反查 Sheet 再 .setName()。官方文件提供 getSheetId() 與 getSheets() 等存取方式。
與「檔案命名」的區別(Drive File.setName())
工作表分頁名:
Sheet.setName()(變的是分頁標籤)。
試算表檔名:
DriveApp.getFileById(id).setName('新檔名')(變的是雲端硬碟檔案)。
兩者常一起用:先把分頁標籤標準化,再把整份檔案依專案規則改名(例如 專案-客戶-日期)
問題集
Q1. 可以用 setName() 把分頁名設成空字串嗎?
不行。名稱必須有內容(實務上請先驗證字串長度),否則會拋錯或在 UI 上直接拒絕。官方文件雖未逐條列出這種驗證,但以實務與 UI 規則須避免空名;方法定義照官方。
Q2. 可以用斜線、冒號、Emoji 嗎?
多數情況可行(Sheets 不像 Excel 那麼嚴格)。但若要把分頁名拿去當檔名/外部系統鍵值,建議自行限制字元集並做清洗。
Q3. 批次改名會不會很慢?
setName() 是改結構的操作,批量數十張一般無感;大量(數百張)建議分批或減少事件觸發。必要時可先 SpreadsheetApp.flush() 讓 UI 盡快同步(非必須)。
Q4. 改名後公式壞掉(未解析工作表名)怎麼辦?
先用 TextFinder 搜 '<舊名>'!,改完名再批次替換;或設計上改用 sheetId 追蹤對應關係,減少對名稱的硬繫結。
延伸閱讀推薦:
Google 試算表:工作表重新命名與 rename() 功能
Google 試算表:拿到正在操作的試算表 getActiveSpreadsheet()
Google 試算表:用檔案 ID 開啟試算表 openById()
Google 試算表:取得顯示的工作表getActiveSheet()
Google 試算表:藉由名稱取得工作表getSheetByName()
Google 試算表:取得所有工作表 getSheets()
Google 試算表:取得工作表數量 getNumSheets()
Google 試算表:焦點切到指定工作表 setActiveSheet()
Google 試算表:刪除工作表 deleteSheet()
