Google 試算表:工作表copy()與copyTo()

 

為什麼要「複製工作表」?

日常數據工作裡,很多報表其實是「同一模型,換月份或客戶」。

最省時的做法不是重做,而是把既有的 模板工作表 直接複製,改個名稱、更新參數就能上線。

這篇從最基本的滑鼠右鍵,到用 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:複製後,某些公式或資料驗證跑掉?

跨檔複製時,外部引用、命名範圍、驗證來源容易是關鍵。建議把參數集中、引用路徑改成相對/命名範圍,或在初始化步驟裡重新指定。


延伸閱讀推薦:

張貼留言 (0)
較新的 較舊