Google 試算表:設定單一儲存格的值 setValue()

 


如果你常在試算表寫自動化腳本,八成遇過這一幕:只想改一格,結果整塊區域都被蓋成同一個值。兇手通常就是 setValue()——它很直覺,卻也很容易被誤用。

本篇文章會用最貼近實務的方式,把 setValue() 從零到一講清楚:怎麼選到正確的 Range、什麼時候該用它、什麼時候要改成 setValues(),還有日期、時間、公式、核取方塊這些「麻煩值」的正確寫法。

中間會穿插小範例與排雷清單,像是時區導致的時間戳跑掉、格式只改外觀不改內容、在迴圈裡狂呼叫導致變慢等狀況。看完你會知道:要單點寫值就乾脆用 setValue(),要批次回寫就一次丟陣列,同時把效能與穩定度顧好。希望本篇文章能夠幫助到需要的您。


目錄

{tocify} $title={目錄} 


setValue() 是什麼?

setValue(value) 會把「一個值」寫進 你選到的整個 Range。如果那個 Range 包含多個儲存格,所有儲存格都會被寫成同一個值。

與 setValues() 的差異

setValue(value):一個值 → 套用到整個 Range(多格同值)。

setValues(values):二維陣列 → 尺寸必須與 Range 完全一致,常用於批次寫入大量不同值(效能更好)。

實務上,一個 setValues() 幾乎一定比在迴圈裡呼叫很多次 setValue() 快。這點在實戰經驗與社群討論中屢被驗證。


從零開始:最小可用範例

建立腳本與取得工作表

1.    開啟你的 Google 試算表 → 擴充功能 → Apps Script。

2.    新增專案,將預設的 Code.gs 內容替換為下列程式。

function demoSetValue() {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = ss.getActiveSheet();       // 或 ss.getSheetByName('工作表名稱')
  const range = sheet.getRange('A1');      // 指向單一儲存格
  range.setValue('Hello setValue');        // 寫入文字
}
 

Range 可以是 A1 標記、或用列/欄/高/寬指定,兩者都行。


一次寫滿多格、但同一個值

function fillSameValue() {
  const sh = SpreadsheetApp.getActive().getActiveSheet();
  const rng = sh.getRange(1, 1, 5, 5); // A1:E5
  rng.setValue('Hello');               // A1:E5 全部變成 "Hello"
}
 

這個用法官方語意與教學實例都成立:多格 Range 會被同值覆寫。


批次寫入不同值(用 setValues())

function writeMatrix() {
  const sh = SpreadsheetApp.getActive().getActiveSheet();
  const rng = sh.getRange(2, 1, 3, 2); // A2:B4
  const data = [
    ['品項', '數量'],
    ['鉛筆', 12],
    ['筆記本', 5],
  ];
  rng.setValues(data);
}
 

當你要「一格一格都不一樣」時,使用 setValues() 搭配二維陣列,速度與穩定度都更好。


資料型別與格式:把「看起來」跟「實際值」都處理對

日期與時間(最容易踩雷)

在 Apps Script 裡,Date 物件寫進儲存格後,顯示樣式要靠數字格式控制,否則看起來可能不對。

function writeDate() {
  const sh = SpreadsheetApp.getActive().getActiveSheet();
  const cell = sh.getRange('B2');
  cell.setValue(new Date());                   // 寫入真正的日期值
  cell.setNumberFormat('yyyy-mm-dd hh:mm');    // 控制顯示樣式
}


若地區/語系不同(例如表單是美式 MM/DD/YYYY,你卻想要 YYYY-MM-DD),請務必搭配 setNumberFormat()。

看到正確畫面但底層仍是日期物件,這是正確的;別把格式化後的樣式誤認為文字。


直接寫出「時間戳」

function writeTimestamp() {
  const sh = SpreadsheetApp.getActive().getActiveSheet();
  const cell = sh.getRange('C2');
  cell.setValue(new Date());
  cell.setNumberFormat('yyyy-mm-dd hh:mm:ss');
}


公式:要值還是要公式?

寫入公式:cell.setValue('=SUM(A2:A10)') → 儲存格會持有公式,並顯示計算結果。

寫入計算後的值:先在腳本端算完或貼值,避免後續被資料變動影響。


布林與核取方塊

function writeCheckbox() {
  const sh = SpreadsheetApp.getActive().getActiveSheet();
  const cell = sh.getRange('D2');
  // 先把儲存格設為核取方塊(UI 或資料驗證)
  cell.insertCheckboxes();
  cell.setValue(true);  // 勾選
}


效能最佳化:避免「慢到想睡」

什麼時候用 setValue()?

    你只改一格或多格同一個值(像是整塊標記「N/A」)。

    事件觸發器(onEdit)裡,只需要落一個時間戳或旗標。

什麼時候改用 setValues()?

    你在迴圈中對很多儲存格重複 setValue()。把資料先組成二維陣列,一次 setValues() 會快非常多。

示例:把慢速迴圈寫法改成一次寫入

function slowToFast() {
  const sh = SpreadsheetApp.getActive().getActiveSheet();
  const values = [];
  for (let r = 0; r < 1000; r++) {
    values.push([`Row ${r+1}`, r+1]); // 二維陣列:每列兩欄
  }
  sh.getRange(2, 1, values.length, values[0].length).setValues(values);
}
  

實戰情境

情境 A:表單送出後自動補上處理狀態

function markSubmitted(e) {
  const sh = SpreadsheetApp.getActive().getSheetByName('Responses');
  const lastRow = sh.getLastRow();
  sh.getRange(lastRow, 5).setValue('Received'); // 第 5 欄寫入狀態
}


情境 B:根據條件把一塊區域全數標記「N/A」

function markNAIfClosed() {
  const sh = SpreadsheetApp.getActive().getActiveSheet();
  const status = sh.getRange('A1').getValue();
  const block = sh.getRange('B2:D20');
  if (status === 'Closed') block.setValue('N/A'); // 多格同值
}


常見錯誤與雷點

1.「我只想改一格,結果整排都被改了」

你選到的其實是整列/整塊 Range;setValue() 自然把同一值寫進整個 Range。先確認 getRange() 的座標或 A1 標記;必要時改用單一儲存格的 Range。

2.  日期顯示怪、或不同地區格式互相打架

資料本體(Date)正確,但顯示格式沒設。請加上 setNumberFormat();若表單/工作表地區不同,請統一地區設定再寫入。

3.  把「樣式」當「值」

setNumberFormat() 只改外觀,不改底層資料型別;若你需要字串(例如要輸出 "2025-10-04"),請在程式端格式化成字串再 setValue()。

4.  在迴圈中大量 setValue() → 變慢

把資料先組成二維陣列,一次 setValues();避免呼叫界面 API 的次數。

5.  多格不同值卻用 setValue()

結果整塊都變同值。要不同值 → 改用 setValues(),而且陣列尺寸要正確對齊 Range。

6.  寫入文字「看起來像日期」卻被自動轉型

想「強制寫成文字」,可以先設定格式為 @,或在字串前加前導單引號 '2025/10/04。

7.  寫入公式但期望固定值

setValue('=...') 會留下公式;若要固定值,請改在腳本端計算後再寫入。

8.  跨時區的時間戳記誤差

使用 new Date() 會以伺服器時區為準;如果有時區需求,請在 Apps Script 端用 Utilities.formatDate() 轉為目標時區的字串再寫入。

9.  一次把同值寫滿整塊的正確用法

這正是 setValue() 的強項;想快速把一大片標記為「N/A」「清空成空字串」都很適合。

10. 多處位置同時寫入不同值

請抓一個覆蓋面足夠的 Range,先 getValues()、在陣列裡改動多個點,再 setValues() 回去。


問題集

Q1:我可不可以對「非連續」區塊一次寫入?

Apps Script Range 代表的是連續區域。非連續寫入得拆成多個 Range 操作,或用「大範圍陣列→內文定位修改→一次 setValues() 回寫」的策略。

Q2:setValue() 真的會把多格都改成同值嗎?

是。你選到多格 Range,它就對那整塊寫同一個值;示例與文檔皆有展示。

Q3:效能到底差多少?

場景不同、資料量不同,但「一口氣回寫陣列」通常顯著更快,這是 Apps Script 社群長年共識與最佳實務。


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