如果你也常把資料橫著擴充,卻老是抓不準「最後一欄」在哪,那你需要認識 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() 指定,並加上空值保護。
