Google 試算表:刪除指定的單一列 deleteRow()

 


如果你也覺得試算表越整理越亂,八成是卡在「刪除」這一步沒用對方法。

這篇用日常語氣把 deleteRow() 講透:它在什麼時候出場最好、怎麼寫才不會越刪越慢、為什麼大家都說要「從下往上」刪。內容包含五個實戰範例:單列刪除、連續多列、尾端空白列整理、依欄位值條件刪、判斷顯示為空的列。

每個段落都有注意事項與小提醒,像是避免誤傷表頭、遇到保護範圍怎麼辦、以及配額和時間限制的基本概念。讀完之後,你會多一把順手的清理刀,報表維護也能省下不少時間。希望本篇文章能幫助到需要的您。


目錄

{tocify} $title={目錄} 


為什麼要學 deleteRow()?

在自動化清理資料、移除過期列、刪除空白或不合規紀錄時,直接用 Apps Script 刪列最省事。Sheet.deleteRow(rowPosition) 能刪除指定的單一列;若要批次刪好幾列,還有 deleteRows(rowPosition, howMany) 可一次處理連續區塊。兩者皆屬於 Spreadsheet Sheet 類別的方法。


基本觀念與語法

座標從 1 開始:Apps Script 的列、欄索引皆以 1 為起點(第 1 列、第 1 欄)。

deleteRow(row):刪除指定列,並向上位移下方所有列。

deleteRows(row, howMany):自 row 起連續刪除 howMany 列。

搭配常用偵測方法

        getLastRow():最後一列「有內容」的位置。

        getMaxRows():工作表目前擁有的總列數(可能比實際資料多)。

官方 Sheet 類別文件同時列出 deleteRow() / deleteRows()、getLastRow() / getMaxRows() 的定義與回傳值說明。


實作前準備

1.    開啟試算表 → 功能表「擴充功能 → Apps Script」開啟編輯器。

2.    在專案中新增 .gs 檔,貼上本文範例程式。

3.    第一次執行會跳出授權畫面,依指示授權腳本存取該試算表。

4.    回到試算表,可把程式綁定自訂選單或按鈕,方便日常使用。

這些操作依 2025 年介面說法整理;刪列的底層能力仍以 Spreadsheet 服務為準。


快速上手:5 個「最常用」情境範例

刪除單一指定列

function deleteOneRow() {
  const sheet = SpreadsheetApp.getActiveSheet();
  sheet.deleteRow(5); // 刪除第 5 列
}


適合與 UI 事件搭配(例如點選某列後執行)。


刪除連續的多列(用 deleteRows)

function deleteBlock() {
  const sheet = SpreadsheetApp.getActiveSheet();
  const start = 10;     // 從第 10 列開始
  const howMany = 5;    // 刪 5 列 → 10~14 列
  sheet.deleteRows(start, howMany);
}


一次刪一個區段,比迴圈逐列 deleteRow 快很多。


刪除「尾端多餘空白列」

許多表單或匯入流程會留下超多空列,可用 getLastRow() + getMaxRows() 精準縮減。

function trimTrailingEmptyRows() {
  const sh = SpreadsheetApp.getActiveSheet();
  const last = sh.getLastRow();
  const max  = sh.getMaxRows();
  if (max > last) {
    sh.deleteRows(last + 1, max - last);
  }
}


這是社群長年沿用的模式,原理正是以「真實最後列」對齊「目前最大列」做收尾。


依「欄位值」刪除資料列(例如狀態=已關閉)

重點:先把資料一次讀入陣列,再決定要刪哪些列,最後由下往上批次刪除(避免位移問題)。

function deleteRowsByValue() {
  const sh = SpreadsheetApp.getActiveSheet();
  const header = 1;              // 表頭列數
  const keyCol = 3;              // 目標欄(例:第 3 欄是狀態)
  const target = '已關閉';       // 刪除此狀態的列
  const lastRow = sh.getLastRow();
  if (lastRow <= header) return;

  const values = sh.getRange(header + 1, keyCol, lastRow - header, 1).getValues().flat();
  const toDelete = [];
  values.forEach((v, i) => { if (v === target) toDelete.push(i + header + 1); });

  deleteInBatches_(sh, toDelete);
}

// 將不連續列壓成「連續區塊」後,再 bottom-up 刪除
function deleteInBatches_(sheet, rowIndexes) {
  if (!rowIndexes.length) return;
  rowIndexes.sort((a, b) => a - b);

  const blocks = [];
  let start = rowIndexes[0], prev = start;
  for (let i = 1; i < rowIndexes.length; i++) {
    const cur = rowIndexes[i];
    if (cur === prev + 1) {
      prev = cur;
    } else {
      blocks.push([start, prev - start + 1]);
      start = prev = cur;
    }
  }
  blocks.push([start, prev - start + 1]);

  // 由下往上刪,避免索引位移
  for (let i = blocks.length - 1; i >= 0; i--) {
    const [row, count] = blocks[i];
    sheet.deleteRows(row, count);
  }
}


先批次讀寫、再成塊刪除,符合 Apps Script 官方「批次操作」最佳實務。


刪空白列(含公式回傳 "" 的列)

若希望把「看起來空白」的列通通移除,建議用 getDisplayValues() 來判斷。

function deleteEmptyDisplayRows() {
  const sh = SpreadsheetApp.getActiveSheet();
  const header = 1;
  const lastRow = sh.getLastRow();
  const lastCol = sh.getLastColumn();
  if (lastRow <= header) return;

  const values = sh.getRange(header + 1, 1, lastRow - header, lastCol).getDisplayValues();
  const toDelete = [];
  values.forEach((row, i) => {
    const joined = row.join('').trim();
    if (joined === '') toDelete.push(i + header + 1);
  });
  deleteInBatches_(sh, toDelete);
}


getDisplayValues() 會以顯示結果判斷空白,更貼近使用者觀感。


效能與穩定度:把時間花在對的地方

1.    一次讀寫、多筆處理

        避免在迴圈中頻繁呼叫 deleteRow();盡量用 deleteRows() 成批處理。這是 Apps Script 官方建議的「批次操作」做法。

2.    由下往上刪

        刪除會改變後續列的索引;從底部開始可避免位移造成的錯刪。

3.    合併區塊

        先把要刪的列整理成「連續區塊」,每塊只呼叫一次 deleteRows(),明顯提速。(上面 deleteInBatches_ 已示範)

4.    批量刪除的另一條路:Sheets API

        若你需要在跨試算表或大量分散的列上刪除,亦可改用 Google Sheets API batchUpdate 的 DeleteDimensionRequest。Apps Script 內可啟用 Advanced Service 或使用外部憑證;這條路適合「一次組裝許多刪除請求」再送出。


權限與保護範圍(你能刪的,程式才刪得動)

列若落在受保護的範圍或工作表受保護,且目前執行者沒有權限,刪除會拋出例外。

相關權限判斷、移除保護等可用 Protection 類別處理;必要時以擁有者身分(如 Web App / 安裝觸發器)執行。


風險控管:Undo 與版本記錄

可否 Undo? Google 在新版 Sheets 的釋出說明中提到:Undo 能回復由腳本造成的變更;但實務上若一次做了很多步驟,有時需要多次 Undo 才能回到原狀。因此大規模刪除前,仍建議先備份或用版本記錄。

版本記錄:從「檔案 → 版本記錄 → 檢視版本記錄」可回到任一早期版本,是最保險的後悔藥。


常見錯誤與雷點

1.    用 deleteRow() 逐列往上刪,結果「跳刪」

        原因:刪除會位移索引。

        對策:改成自底向上,或先壓成連續區塊用 deleteRows() 一次刪。

2.    把表頭也刪掉

        原因:條件篩選時忘了跳過第 1 列(或多列表頭)。

        對策:取值時從 header + 1 開始。

3.    看起來空白但刪不掉

        原因:儲存格含公式,顯示為空字串 ""。

        對策:使用 getDisplayValues() 判斷空白(見上方範例)。

4.    刪列很慢

        原因:在迴圈裡多次呼叫 deleteRow(),反覆觸發與雲端通訊。

        對策:一次讀取 → 彙總目標 → deleteRows() 成批刪;必要時考慮 Sheets API batchUpdate。

5.    受到保護範圍阻擋

        原因:無權修改受保護的範圍/工作表。

        對策:檢查 Protection 物件,或改以擁有者身分執行(Web App / 安裝觸發器)。

6.    超過執行時間限制(常見於大量刪除)

        Apps Script 單次執行有時間與配額限制;遇到大檔可能中途停止。

        對策:切分工作、批次化、或改用時間驅動觸發器分段跑。


進階:安全的刪除流程(確認視窗/試跑模式)

為避免誤刪,可在執行前顯示確認對話框,或先列出將被刪除的列數量(試跑)。

function confirmAndDeleteByStatus() {
  const ui = SpreadsheetApp.getUi();
  const resp = ui.alert('刪除確認', '即將刪除狀態=已關閉 的資料列,是否繼續?', ui.ButtonSet.YES_NO);
  if (resp !== ui.Button.YES) return;
  deleteRowsByValue(); // 呼叫前述的刪除函式
}


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