Google 試算表:取得目前作用中的儲存格 getCurrentCell()

 


寫試算表腳本時,很多操作都圍著「我現在點到哪一格?」打轉。

比方說,把正在看的那一列打上完成記號、把那一格的值轉成純文字、或從這裡一路往下找到下一筆資料。

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()
.getSelection().getCurrentCell()
適合配合 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 範例與社群片段常見這種用法)


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