為什麼要「複製工作表」?
日常數據工作裡,很多報表其實是「同一模型,換月份或客戶」。
最省時的做法不是重做,而是把既有的 模板工作表 直接複製,改個名稱、更新參數就能上線。
這篇從最基本的滑鼠右鍵,到用 Apps Script 自動化(含整份活頁簿複製的 copy())、批量產生多張分頁、只複製部分範圍、以及常見錯誤與雷點,幫你把各種情境一次打包。希望能幫助到有需要的您。
目錄
{tocify} $title={目錄}
介面版:在試算表裡用滑鼠「複製」工作表
最直覺的方式:在下方分頁標籤右鍵 → 複製(Duplicate)。系統會在同一份試算表裡產生一張一模一樣的新分頁,命名通常是「某分頁 的副本(Copy of …)」;你可以再立即改名。這招適合臨時產生一張工作表,不用寫任何程式。
小提醒:若你要把分頁複製到「另一份試算表」,可在右鍵選單找「複製到…(或移到 / Copy to)」再選目標檔。
初階自動化:用 Apps Script 複製工作表(同檔/跨檔)
Google Apps Script(GAS)能把「複製」變成一鍵自動化。核心是 Sheet.copyTo(spreadsheet) 這個方法:把某張工作表複製到指定的試算表裡(也可以是自己)。官方文件把它歸在 Sheet 類別下。
在同一份檔案內複製一張工作表
function duplicateSheetInSameFile() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const src = ss.getSheetByName('Template'); // 你的模板分頁
const copied = src.copyTo(ss); // 複製到自己
copied.setName('2025-10 報表'); // 改新名稱(要唯一)
ss.setActiveSheet(copied);
}
重點:setName() 的名稱不可和現有分頁重複,否則會報錯。
複製到另一份試算表
function duplicateSheetToAnotherFile() {
const srcSs = SpreadsheetApp.getActiveSpreadsheet();
const srcSheet = srcSs.getSheetByName('Template');
const targetSs = SpreadsheetApp.openById('目標SpreadsheetID');
const copied = srcSheet.copyTo(targetSs);
copied.setName('客戶A_月報_模板');
targetSs.setActiveSheet(copied);
}
權限要點:你必須對目標試算表有「可編輯」權限,Apps Script 執行時也要授權對試算表的存取。
copy() 與 makeCopy():整份檔案複製 vs. 雲端硬碟複製
不少人會搜尋「copy() 怎麼用?」這裡要先釐清兩個常被混用的族譜:
Spreadsheet.copy(name):
複製整份試算表(活頁簿),回傳新的 Spreadsheet 物件。適合把整本「年度範本」一口氣生出一份全新檔,再進檔內做細部調整。官方文件列明 copy(name) 為 Spreadsheet 類別的方法。
DriveApp.File.makeCopy(...):
從「雲端硬碟檔案」角度複製,能指定名稱與目的資料夾,適合管控檔案歸檔位置。官方 Drive 服務文件清楚列出 makeCopy(name) / makeCopy(destination) 等多種多載。
Spreadsheet.copy(name) 範例(整份檔案一鍵複製)
function copyWholeSpreadsheet() {
const src = SpreadsheetApp.getActiveSpreadsheet();
const newName = `${src.getName()}_副本_${new Date().toISOString().slice(0,10)}`;
const copied = src.copy(newName); // 回傳全新 Spreadsheet
Logger.log('New file URL: ' + copied.getUrl());
}
DriveApp 的 makeCopy() 指定資料夾版本
function copyToSpecificFolder() {
const src = SpreadsheetApp.getActiveSpreadsheet();
const srcFile = DriveApp.getFileById(src.getId());
const dstFolder = DriveApp.getFolderById('目標資料夾ID');
const newFile = srcFile.makeCopy(`${src.getName()}_月結`, dstFolder);
Logger.log('New file URL: ' + newFile.getUrl());
}
補充:若你看到錯誤訊息「makeCopy is not a function」,通常是你對錯物件(不是 File)呼叫了 makeCopy();先用 DriveApp.getFileById() 取得 File 物件再呼叫即可。
只複製「範圍」:Range.copyTo() 的幾種常見用法
有時你只想複製表格的一塊資料、或只要格式不要公式,這時用 Range.copyTo() 最自由。官方 Range 文件提供多種多載,包含複製內容、格式、以及是否轉置。
複製資料+格式(貼到同一張或另一張)
function copyRangeAll() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const src = ss.getSheetByName('Template');
const dst = ss.getSheetByName('Working');
src.getRange('A1:F50').copyTo(dst.getRange('A1')); // 內容+格式
}
只貼「值」(去公式)
function copyValuesOnly() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const src = ss.getSheetByName('Template');
const dst = ss.getSheetByName('Working');
src.getRange('A1:F50').copyTo(dst.getRange('A1'), {contentsOnly: true});
}
只複製「格式」)
function copyFormatsOnly() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const src = ss.getSheetByName('Template');
const dst = ss.getSheetByName('Working');
const range = src.getRange('A1:F50');
range.copyTo(dst.getRange('A1'), SpreadsheetApp.CopyPasteType.PASTE_FORMAT, false);
}
大量複製模板分頁:一次產 12 個月份、100 張工作表
產 12 個月份分頁(以「Template」為藍本))
function bulkCreateMonthlySheets() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const src = ss.getSheetByName('Template');
const months = ['01','02','03','04','05','06','07','08','09','10','11','12'];
months.forEach(m => {
const sheet = src.copyTo(ss);
sheet.setName(`2026-${m}`);
});
}
一次產 100 張(自動流水號命名)
function bulkCreateNumberedSheets() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const src = ss.getSheetByName('Template');
const count = 100;
for (let i = 1; i <= count; i++) {
const s = src.copyTo(ss);
s.setName(`Workout${i.toString().padStart(3,'0')}`);
}
}
常見錯誤與避坑清單
1. 「找不到 copy()」或「copy() 用了卻不是我要的」
澄清:copy() 是 Spreadsheet 類別用來複製「整份檔案」的方法;若你想複製「單一工作表」,應該用 Sheet.copyTo()。
2. makeCopy is not a function
代表你不是在 File 物件上呼叫 makeCopy()。先用 DriveApp.getFileById(id) 取得 File 再呼叫。
3. 命名衝突
setName() 命名必須全檔唯一,重複會丟錯。做大量複製時先規劃命名規則(年月、流水號)避免踩雷。
4. 權限不足/授權錯誤
跨檔複製需要你對「目標試算表」有編輯權限;REST 或 DriveApp 操作也要有對應的授權 scope(Sheets / Drive)。
5. 外部引用與資料連動
被複製的工作表若有 IMPORTRANGE、外部檔案連結或外掛函數,複製後邏輯仍指向原來源;到新檔或新分頁後請逐一確認授權與範圍是否要改。
6. 保護範圍、篩選檢視、圖表
多數格式與物件會跟著複製,但跨檔時難免有遺漏(尤其權限與保護規則);實務上建議跑一次「驗證清單」。
7. 只想貼值、不想帶公式
請改用 Range.copyTo(..., {contentsOnly: true})。
問題集
Q1:copy() 和 copyTo() 差在哪?
copy() 屬於 整份活頁簿(Spreadsheet) 的複製;
copyTo() 是 單一工作表(Sheet) 的複製;
另外 Range.copyTo() 只針對「儲存格範圍」搬運資料/格式。官方 Spreadsheet、Sheet、Range 文件各自說明這些方法。
Q2:不寫程式,只用滑鼠能不能複製到別的檔?
可以。分頁標籤右鍵有「移到/複製到」,可把分頁複製到其他試算表。
Q3:大規模複製時,名字老是撞名怎麼辦?
規劃命名規則(年月+流水號),或程式裡檢查是否存在、存在就遞增數字。
Q4:複製後,某些公式或資料驗證跑掉?
跨檔複製時,外部引用、命名範圍、驗證來源容易是關鍵。建議把參數集中、引用路徑改成相對/命名範圍,或在初始化步驟裡重新指定。
延伸閱讀推薦:
Google 試算表:工作表重新命名與 rename() 功能
Google 試算表:拿到正在操作的試算表 getActiveSpreadsheet()
Google 試算表:用檔案 ID 開啟試算表 openById()
Google 試算表:取得顯示的工作表getActiveSheet()
Google 試算表:藉由名稱取得工作表getSheetByName()
Google 試算表:取得所有工作表 getSheets()
Google 試算表:取得工作表數量 getNumSheets()
Google 試算表:焦點切到指定工作表 setActiveSheet()
Google 試算表:刪除工作表 deleteSheet()
