Google 試算表:取得最後一欄 欄號 getLastColumn()

 


如果你也常把資料橫著擴充,卻老是抓不準「最後一欄」在哪,那你需要認識 getLastColumn()。它看的是整張工作表的右邊界(有內容才算),非常適合拿來決定接下來寫入的位置、或產生動態範圍。本文不繞圈,直接用清楚的例子示範:從在最後一欄後新增標題欄,到把一整塊資料一次寫進去、再到自動延伸公式。最後再附上錯誤排查與避雷清單,幫你少走冤枉路。希望本篇文章能夠幫助到需要的您。


目錄

{tocify} $title={目錄} 


為什麼要懂 getLastColumn()?


做資料自動化的時候,最後一欄在哪是很關鍵的訊息。你可能要把新資料貼在最右側、要動態擴充報表欄位、或更新圖表資料範圍。getLastColumn() 就像「房子的右邊界」,告訴你目前工作表中最右側仍有內容的欄位編號(以 1 起算:A=1、B=2、…、Z=26)。

一句話版:getLastColumn() 回傳「這張工作表有東西填到第幾欄」。


基礎觀念先釐清

它是 Sheet 的方法:

        Sheet.getLastColumn() 會看整張工作表(不是單一列/單一儲存格)。

1 為起點:

        Apps Script 在試算表世界裡的列、欄都是 1-based,不是 0。

「有內容才算」:

        包含手打文字、數字、公式(即便顯示為 "" 空字串)、日期、TRUE/FALSE。單純上色或設定邊框不算內容。

隱藏欄/篩選視圖:

        即使被隱藏,它們有內容就會被計入。

合併儲存格:

        內容實際存放在合併區塊的左上角;右側被合併覆蓋但本身沒有內容,通常不會被視為「有內容」。

Range 也有 getLastColumn(),但意義不同:

        Range.getLastColumn() 是這個 Range 幾欄寬的「右邊界欄號」(= 起始欄 + 欄數 - 1),跟內容無關。本文主角以 Sheet.getLastColumn() 為主。


最基本的用法

function demoLastColumn() {
  const sheet = SpreadsheetApp.getActive().getActiveSheet();
  const lastCol = sheet.getLastColumn(); // 例如:26 表示最後一欄是 Z 欄
  Logger.log('Last column = ' + lastCol);
}


小提醒:getActive() 取得的是活頁簿(Spreadsheet),getActiveSheet() 才是工作表(Sheet)。把對象搞錯,最容易報錯。


常見場景與範例實作

在最後一欄右邊新增一欄,填上今天日期當欄名

需求:每天產生一個新欄位,欄名是當天日期,之後再往下填資料。

function addDailyColumn() {
  const sheet = SpreadsheetApp.getActive().getActiveSheet();
  const lastCol = sheet.getLastColumn();
  const newCol = lastCol + 1;
  sheet.insertColumnAfter(lastCol); // 在最後一欄後面插入新欄
  const header = Utilities.formatDate(new Date(), Session.getScriptTimeZone(), 'yyyy-MM-dd');
  sheet.getRange(1, newCol).setValue(header); // 第 1 列當作標題列
}


避雷:如果你的表頭不是在第 1 列,請把 1 換成實際的表頭列號。


取得「已使用範圍」:搭配 getLastRow() 動態選取資料區

需求:把整張表中「真的有資料的矩形範圍」一次抓出來。

function getUsedRangeValues() {
  const sh = SpreadsheetApp.getActive().getActiveSheet();
  const lastRow = sh.getLastRow();
  const lastCol = sh.getLastColumn();
  if (lastRow === 0 || lastCol === 0) return []; // 空表保險
  const range = sh.getRange(1, 1, lastRow, lastCol);
  return range.getValues(); // 二維陣列
}


這段等於 Excel 的「Ctrl+End」那個矩形,只看有內容的邊界。


將一列資料「貼到最右側空欄」:寬度自動跟著跑

需求:每次腳本跑,都把新資料「橫著」往右長。

function appendRowHorizontally(values) {
  // values 例如:['10/06', 123, 456, 789]
  const sh = SpreadsheetApp.getActive().getActiveSheet();
  const startRow = 2; // 表頭占第 1 列
  const lastCol = sh.getLastColumn();
  const startCol = Math.max(lastCol + 1, 2); // 如果 A 欄是固定資訊,從 B 之後開始長
  const numRows = values.length; // 要塞幾筆「列」?
  const numCols = 1;            // 橫著長=每筆占 1 欄

  // 這個例子把每個值往「下一列」塞到新欄(直向資料 → 橫向欄)
  sh.getRange(startRow, startCol, numRows, numCols).setValues(values.map(v => [v]));
}


常見失誤:setValues() 的陣列維度要跟 Range 尺寸一樣(上例是 N×1)。尺寸不合會直接報錯。


 取最後一欄的欄名(A、B、C…)

需求:UI 需要顯示 Z、AA 這種欄名;或要產生公式範圍字串。

function columnToLetter(col) {
  let temp = '';
  while (col > 0) {
    const rem = (col - 1) % 26;
    temp = String.fromCharCode(65 + rem) + temp;
    col = Math.floor((col - 1) / 26);
  }
  return temp;
}

function getLastColumnLetter() {
  const sh = SpreadsheetApp.getActive().getActiveSheet();
  const lastCol = sh.getLastColumn();
  return columnToLetter(lastCol); // 例如:26 -> Z、27 -> AA
}


 動態更新圖表或命名範圍(程式生成)

需求:每次資料增長時,圖表自動吃到新欄位。以下示範更新命名範圍(Chart Builder 也同理,用 setRange() 指定)。

function updateNamedRangeToLastColumn() {
  const ss = SpreadsheetApp.getActive();
  const sh = ss.getActiveSheet();
  const lastRow = sh.getLastRow();
  const lastCol = sh.getLastColumn();

  const name = 'DATA_RANGE';
  const existing = ss.getNamedRanges().find(n => n.getName() === name);
  const rng = sh.getRange(1, 1, lastRow, lastCol); // A1 到最後一格

  if (existing) {
    existing.setRange(rng);
  } else {
    ss.setNamedRange(name, rng);
  }
}


清掉「右邊多餘空欄」:視覺整潔 + 準確邊界

需求:有人把格式刷到很右邊,或曾經貼過資料又刪掉,導致 getLastColumn() 感覺「偏大」。可以把純空欄位刪除,讓右邊界回到該回的位置。

function trimTrailingEmptyColumns() {
  const sh = SpreadsheetApp.getActive().getActiveSheet();
  const maxCols = sh.getMaxColumns();
  const lastCol = sh.getLastColumn();
  const extra = maxCols - lastCol;
  if (extra > 0) {
    sh.deleteColumns(lastCol + 1, extra);
  }
}


注意:這是刪欄(不是清空)。若你只是想保留欄位但清內容,請用 getRange().clearContent()。


操作步驟

1.    開啟 Apps Script 編輯器

試算表上方選單 → 擴充功能 → Apps Script。

2.    建立空白專案

會自動綁定到當前試算表。

3.    貼上本文範例

譬如先從 demoLastColumn() 開始。

4.    第一次執行 & 權限授權

按「執行」→ 按畫面指示授權 → 完成後再次執行。

5.    檢查輸出

檢視 → 日誌(或在新版 IDE 看 Execution log)確認結果。


實務眉角與效能建議

別在迴圈裡一直呼叫 getLastColumn()

        先呼叫一次存到變數再用。Apps Script 每次呼叫都要打到文件模型,重複呼叫會慢。

搭配 getValues() 做一次性批次處理

        盡量把讀寫合併,避免多次 setValue()。例如一次寫整個矩形區塊。

遇到公式顯示空白,邊界卻很遠?

        這是正常現象,因為有「公式」就算有內容。若不想計入,請改由純值(值為空)或在腳本層加上自訂判斷。

格式≠內容

        單純上色、畫框、資料驗證都不會讓 getLastColumn() 變大;但貼過資料又清空,有時會殘留物件或命名範圍,建議用「刪欄」把尾巴收乾淨。

合併儲存格要小心

        如果你用合併把 A1:D1 合成一格,內容其實落在 A1。右邊界是否延伸到 D,視右側儲存格是否真的有內容而定。保守做法是盡量少用跨大範圍的合併。


常見錯誤與排查

 1.    TypeError: sheet.getLastColumn is not a function

成因:sheet 其實不是 Sheet,而是 Spreadsheet 或 Range。

排查:

你是不是寫了 SpreadsheetApp.getActive().getLastColumn()?(少了 getActiveSheet())

或是 SpreadsheetApp.getActiveRange().getLastColumn()?那會回 Range 的最後欄(幾乎等於起始欄 + 欄寬 - 1),跟你想像的「整張表最後欄」不同。

正解:

const sheet = SpreadsheetApp.getActive().getActiveSheet();
const lastCol = sheet.getLastColumn();


2.    Cannot call method "getLastColumn" of null

成因:用 getSheetByName('名字') 拿不到表(名字錯、或被刪了)。

排查:Logger.log(ss.getSheets().map(s=>s.getName())) 看看實際名稱。

修正:

const sh = ss.getSheetByName('報表') || ss.getActiveSheet();


3.    The number of columns in the data does not match the number of columns in the range

成因:setValues() 的二維陣列尺寸跟 Range 的列×欄不一致。

排查:確認 values.length 與 values[0].length,以及 getRange(rows, cols) 指定的長寬。

速修模式:在寫入前 Utilities.sleep(1) 無濟於事,根本原因是維度不合,請對齊尺寸。


4.    右邊界「卡」在很大的欄位號

成因:表裡某列曾被貼過很遠的資料、或有看不見的公式/物件。

處理:

嘗試 trimTrailingEmptyColumns() 直接刪欄。

確認是否有跨到很右側的命名範圍、圖表或保護範圍。


5.    混淆 Range.getLastColumn() 與 Sheet.getLastColumn()

症狀:你以為拿到「整張表」最後欄,實際卻只拿到「該 Range 的右界」。

心法:記口訣——「Sheet 看內容,Range 看幾欄寬」。


進階技巧:用 getLastColumn() 做動態報表

A. 產生最新一欄的統計摘要

需求:把最後一欄當成「最新期」,抓欄名與本期合計。

function summarizeLatestColumn() {
  const sh = SpreadsheetApp.getActive().getActiveSheet();
  const lastCol = sh.getLastColumn();
  const lastColLetter = columnToLetter(lastCol);

  const header = sh.getRange(1, lastCol).getDisplayValue();
  const values = sh.getRange(2, lastCol, sh.getLastRow() - 1, 1).getValues()
                   .flat().filter(v => v !== '' && !isNaN(v));
  const sum = values.reduce((a, b) => a + Number(b), 0);

  sh.getRange('A1').setNote(`最新欄 ${lastColLetter}(${header})合計:${sum}`);
}


亮點:getDisplayValue() 取得顯示字串,不影響公式;flat() 把二維陣列壓成一維好運算。


B. 定位「下一個可用欄」並一次寫入整塊資料

需求:你有一個 100×5 的報表,要往右「開新欄組」塞進去。

function writeBlockToNextColumns(data) {
  // data 是 100×5 的二維陣列
  const sh = SpreadsheetApp.getActive().getActiveSheet();
  const lastCol = sh.getLastColumn();
  const startCol = lastCol + 1;
  const startRow = 1;
  const numRows = data.length;
  const numCols = data[0].length;

  sh.getRange(startRow, startCol, numRows, numCols).setValues(data);
}


技巧:一次寫入整塊比逐格寫入快很多,Apps Script 配額也更省。


C. 動態公式填充到最後一欄

需求:每次資料變長,都把計算公式自動撐到最右邊。

function fillFormulaToLastColumn() {
  const sh = SpreadsheetApp.getActive().getActiveSheet();
  const lastCol = sh.getLastColumn();
  const formulaRow = 2; // 假設第 2 列是要放公式
  const startCol = 2;   // 從 B 欄開始
  if (lastCol < startCol) return;

  const width = lastCol - startCol + 1;
  const range = sh.getRange(formulaRow, startCol, 1, width);
  // 以第一格的公式為樣板
  const baseFormula = sh.getRange(formulaRow, startCol).getFormula();
  const row = Array(width).fill(baseFormula);
  range.setFormulas([row]);
}


問題集

Q1:getDataRange() 跟 getLastColumn() 要怎麼選?

        getDataRange() 一次給你整個「有內容的矩形範圍」,很方便;

但若你只需要邊界數字去計算(像新增欄),getLastColumn() 更輕量、語意更準。

Q2:格式被刷到很右邊,getLastColumn() 會不會變大?

        單純格式不會;但若格式是伴隨貼上內容產生的,清掉內容後仍覺得邊界太大,請用刪欄收尾。

Q3:最後一欄若是公式顯示空白(""),會算嗎?

        會。因為有公式就算內容。若不想計入,改用值、或在腳本層把「公式但顯示空」當例外處理。

Q4:多工作表切換要注意什麼?

        不要一直 getActiveSheet() 假設永遠是同一張;用 getSheetByName() 指定,並加上空值保護。


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