寫試算表腳本時,很多操作都圍著「我現在點到哪一格?」打轉。
比方說,把正在看的那一列打上完成記號、把那一格的值轉成純文字、或從這裡一路往下找到下一筆資料。
getCurrentCell() 就是為了這種日常情境生的:它抓的是「此刻真的被外框框住、游標正在上面」的那一格。
本篇文章會盡可能帶你搞懂它跟 getActiveCell() 的差別、什麼時候會拿到 null、怎麼結合選取變更觸發器做出貼手的小工具。文中有實例、有避雷清單,也會補上幾個常見誤會(像多重選取與篩選檢視的陷阱)。看完你就能把「人看到哪,腳本做到哪」這件事安穩落地。希望本篇文章能夠幫助到需要的您。
目錄
{tocify} $title={目錄}
為什麼要學 getCurrentCell()?
做 Google 試算表自動化時,很多任務都跟「使用者此刻選到哪一格」有關:像是把目前這一列標記完成、把目前這格的值轉格式、從目前位置往下找到下一筆資料、或把目前的公式抓出來做分析。getCurrentCell() 就是專門回傳「現在 UI 上深色外框框起來、真正被聚焦的那一格」的工具。依官方文件,它會回傳一個 Range 物件;沒有聚焦時會回傳 null(空值)。
順帶一提:Spreadsheet 服務底下其實有多個地方能拿到「目前格」
像 SpreadsheetApp.getCurrentCell()、Spreadsheet.getCurrentCell()、Sheet.getCurrentCell()、或 Selection.getCurrentCell(),
核心意思一致:傳回「目前那一格」的 Range ;差別只在你是從哪個入口物件拿到它。
getCurrentCell() 到底跟 getActiveCell() 有何不同?
這兩個名字超像,但行為不同:
getCurrentCell():回傳「UI 上深色外框高亮的那一格」。
getActiveCell():回傳「目前選取範圍的左上角那一格」。
所以當你同時選了多格(例如 B2:D4),目前鍵盤移動到 C3 時:
getCurrentCell() → C3
getActiveCell() → B2
這點在實作上很關鍵,尤其做導覽、標註與「從目前格出發」的動作時,應選 getCurrentCell()。這個差異也有社群實測與說明可供參考
基本語法與回傳型別
以下都是合法寫法(回傳型別皆為 Range;若沒有目前格,會是 null):
// 1) 從全域入口拿
const cur = SpreadsheetApp.getCurrentCell();
// 2) 從活頁簿物件拿
const ss = SpreadsheetApp.getActiveSpreadsheet();
const cur2 = ss.getCurrentCell();
// 3) 從工作表物件拿
const sheet = ss.getActiveSheet();
const cur3 = sheet.getCurrentCell();
// 4) 從 Selection 物件拿(可搭配更多選取工具)
const selection = ss.getSelection();
const cur4 = selection.getCurrentCell();
官方文件皆指出「回傳目前(高亮)那一格的 Range,或在沒有時回 null」。
10 個常用範例(從「目前格」出發的實戰)
把目前格標上螢光色與粗體
function markCurrentCell() {
const cell = SpreadsheetApp.getCurrentCell();
if (!cell) return;
cell.setBackground('#FFF2CC').setFontWeight('bold');
}
在目前列加上「完成」時間戳
function stampDoneAt() {
const cell = SpreadsheetApp.getCurrentCell();
if (!cell) return;
const row = cell.getRow();
const sheet = cell.getSheet();
const lastCol = sheet.getLastColumn();
sheet.getRange(row, lastCol).setValue(new Date());
}
從目前格一路往下找到「下一筆資料」並框選
function selectNextDataDown() {
const cell = SpreadsheetApp.getCurrentCell();
if (!cell) return;
const target = cell.getNextDataCell(SpreadsheetApp.Direction.DOWN);
target.activate(); // 把游標移到那格
}
getNextDataCell() 是 Range 的方法,會從目前格朝指定方向尋找下一個有資料的格子,很適合跳格導覽。
把目前格的值轉成「純值」貼上(清除公式)
function pasteAsValuesHere() {
const cell = SpreadsheetApp.getCurrentCell();
if (!cell) return;
const val = cell.getDisplayValue();
cell.setValue(val);
}
把目前格所在的整列設為灰底(做「條列完成」效果)
function greyOutRow() {
const cur = SpreadsheetApp.getCurrentCell();
if (!cur) return;
const sheet = cur.getSheet();
sheet.getRange(cur.getRow(), 1, 1, sheet.getLastColumn())
.setBackground('#EEEEEE');
}
把目前格的公式抓出來(做公式分析、紀錄)
function logCurrentFormula() {
const cell = SpreadsheetApp.getCurrentCell();
if (!cell) return;
const formula = cell.getFormula(); // 抓公式字串,沒有就空字串
Logger.log(formula);
}
從目前格開始,取得一個固定大小的區塊做格式化
function formatBlockFromCurrent() {
const cur = SpreadsheetApp.getCurrentCell();
if (!cur) return;
const block = cur.offset(0, 0, 10, 3); // 往下10列、往右3欄的區塊
block.setNumberFormat('#,##0.00').setHorizontalAlignment('right');
}
在目前格下方插入一列並複製標題格式
function insertRowBelowWithHeaderStyle() {
const cur = SpreadsheetApp.getCurrentCell();
if (!cur) return;
const sheet = cur.getSheet();
const row = cur.getRow();
sheet.insertRowsAfter(row, 1);
const header = sheet.getRange(1, 1, 1, sheet.getLastColumn());
const newRow = sheet.getRange(row + 1, 1, 1, sheet.getLastColumn());
header.copyFormatToRange(sheet, 1, sheet.getLastColumn(), row + 1, row + 1);
newRow.clearContent();
}
建立自訂選單:一鍵在目前列加上「☑」
function onOpen() {
SpreadsheetApp.getUi()
.createMenu('快捷動作')
.addItem('目前列打勾', 'checkRow')
.addToUi();
}
function checkRow() {
const cur = SpreadsheetApp.getCurrentCell();
if (!cur) return;
const sheet = cur.getSheet();
sheet.getRange(cur.getRow(), 1).setValue('☑');
}
配合選取觸發器:選到某格就顯示提示
// 先在 Apps Script 介面 → 觸發器,新增「當選取變更時」觸發 onSelectionChange
function onSelectionChange(e) {
const cur = SpreadsheetApp.getActiveSpreadsheet().getSelection().getCurrentCell();
if (!cur) return;
const msg = `目前在工作表「${cur.getSheet().getName()}」的 R${cur.getRow()}C${cur.getColumn()}`;
SpreadsheetApp.getActiveSpreadsheet().toast(msg, '提示', 3);
}
Selection.getCurrentCell() 是官方推薦在「處理選取」情境時使用的入口,語意最貼近「這次選取事件的當下目前格」。
問題集
Q1:為什麼我用 getCurrentCell() 總是拿到 A1?
常見原因是你前面的鏈結不是用「active」物件;社群經驗指出:在取得相關物件的整條鍊路上,若中間插了 getSheetByName() 等「不是目前活頁或工作表」的取得方式,最後可能會落回預設的第一張表 A1。建議一路使用 getActiveSpreadsheet() → getActiveSheet() 再取目前格 。
Q2:套用篩選檢視(Filter view)時,getCurrentCell().getValue() 拿到的值怪怪的?
曾經有回報指出在特定情境下(有篩選檢視、由腳本觸發)會取得錯誤值的問題單;如果你的腳本嚴重仰賴篩選檢視下的精準定位,建議要多做防呆或改以 getActiveRange()+相對位移等替代策略 。
Q3:自訂函數(=MYFUNC())裡能不能用 getCurrentCell() 抓使用者正在點的那一格?
不建議也不可靠。自訂函數在試算表內執行時有沙盒限制,不能任意存取或改動 UI 選取狀態;一般建議以 e.range(在觸發器或巨集中)取得上下文,或者改走選單/按鈕觸發。社群答覆也提醒自訂函數無法修改儲存格格式,只能回傳值 。
Q4:我要「從目前格往下跳到下一筆資料」有沒有更直覺的方法?
Range.getNextDataCell(direction) 正是為這用途設計的 API;你也可以用 Selection.getNextDataRange(direction) 以整段選取範圍為基準移動。
getCurrentCell() 與常見 API 的對照表
| 目的 | 推薦方法 | 備註 |
|---|---|---|
| 取得目前 UI 聚焦的一格 |
SpreadsheetApp.getCurrentCell() 或
Spreadsheet.getCurrentCell()
|
回傳 Range,無聚焦時
null
|
| 取得「這次選取」的目前格 |
SpreadsheetApp.getActive()
|
適合配合 onSelectionChange 使用 |
| 取得選取範圍的左上角 | getActiveCell() |
與「目前格」不同,常被混淆 |
| 由目前格往某方向跳到下一筆資料 |
getNextDataCell(dir) /getSelection().getNextDataRange(dir)
|
快速導覽資料區塊 |
常見錯誤與雷點
1. 把 getCurrentCell() 當成永遠有值
沒有選到任何儲存格(例如程式在沒有開啟 UI 的情況執行)時會是 null。必加判斷:
const cur = SpreadsheetApp.getCurrentCell();
if (!cur) return; // 防呆
2. 把它當成自訂函數的「輸入」
自訂函數在儲存格內呼叫,不能可靠讀取 UI 選取;改用選單或觸發器。社群答覆亦提醒自訂函數不能改格式,只能回傳資料 。
3. 範圍多選時誤以為「目前格 = 左上角」
多選範圍下,getActiveCell()≠getCurrentCell(),動手前先想清楚你要的是「左上角」還是「真正正在編輯的那格」 。
4. 前置鍊路混用非 active 物件導致永遠回 A1
請一條龍用 getActiveSpreadsheet() → getActiveSheet(),再拿目前格,避免回到預設 A1 的坑 。
5. 搭配篩選檢視時讀到不預期的值
留意類似議題,關鍵流程加上比對或改用其他 API 兜實(例如用 getActiveRange() 計算目標) 。
6. 忽略鍵盤導覽與滑鼠點選的差異
getCurrentCell() 追的是 UI 聚焦;若你是透過程式 activate() 改變了焦點,也會改變 getCurrentCell() 的結果(這是預期行為)。善用 activate() 先把焦點引導到定位點,再做後續動作(Spreadsheet 範例與社群片段常見這種用法)
