Google Apps Script 寫入 Google Sheet 入門

掌握 GAS 資料操作技巧

發布日期:2025年1月

1. 簡介

Google Apps Script (Google Apps Script, GAS) 是一種基於 JavaScript 的自動化工具,廣泛用於操作 Google Sheet。本教材介紹如何透過 GAS 取得 工作表 (Sheet) 物件並寫入資料,包含五種取得方法與六個實用範例,幫助初學者掌握資料處理技巧。

2. 取得 Sheet 物件的方法

  • 根據工作表名稱getSheetByName()
    var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("工作表名稱");

    適用於已知名稱,穩定性高,注意名稱區分大小寫。

  • 根據索引getSheets()[index]
    var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0]; // 第一個工作表

    適合已知順序,但順序變動易出錯。

  • 指定 Spreadsheet IDopenById()
    var ss = SpreadsheetApp.openById("你的Spreadsheet_ID");
    var sheet = ss.getSheetByName("工作表名稱");

    適合跨檔案操作,穩定性高,ID 從網址取得。

  • 使用網址openByUrl()
    var ss = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/你的Spreadsheet_ID/edit");
    var sheet = ss.getSheetByName("工作表名稱");

    類似 openById(),使用完整網址。

  • 取得當前工作表getActiveSheet()
    var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();

    適合互動操作,但自動化腳本中不穩定。

總結

方法 適用場景 穩定性 備註
getSheetByName() 已知工作表名稱 ✅ 高 名稱需正確
getSheets()[index] 已知順序 ❌ 低 易因順序改變而錯誤
openById() 跨檔案操作 ✅ 高 建議使用
openByUrl() 跨檔案操作 ✅ 高 和 openById 類似
getActiveSheet() 使用者互動或即時操作 ❌ 低 非互動腳本中不建議

3. 寫入資料的實務範例

  • 範例 1:寫入單一儲存格
    function writeToSpecificSheet() {
      var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("資料表");
      if (sheet) {
        sheet.getRange("A1").setValue("Hello GAS!");
      } else {
        Logger.log("找不到名為『資料表』的工作表");
      }
    }

    檢查工作表存在後,寫入 A1 儲存格。

  • 範例 2:跨檔案追加一列資料
    function appendDataToExternalSheet() {
      var sheetId = "你的Spreadsheet_ID";
      var ss = SpreadsheetApp.openById(sheetId);
      var sheet = ss.getSheetByName("報表");
      var data = ["2025/06/09", "王小明", 5000];
      sheet.appendRow(data);
    }

    使用 appendRow() 追加資料至指定工作表。

  • 範例 3:根據索引寫入多行資料
    function writeBatchDataToIndexedSheet() {
      var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[1];
      var values = [
        ["姓名", "分數"],
        ["張三", 80],
        ["李四", 92]
      ];
      sheet.getRange(1, 1, values.length, values[0].length).setValues(values);
    }

    使用 setValues() 寫入 2D 陣列至第二工作表。

  • 範例 4:遍歷工作表寫入特定前綴
    function writeToSheetWithPrefix() {
      var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
      var prefix = "部門_";
      sheets.forEach(function(sheet) {
        if (sheet.getName().startsWith(prefix)) {
          sheet.getRange("B2").setValue("部門更新完成");
        }
      });
    }

    篩選名稱前綴為「部門_」的工作表,寫入 B2。

  • 範例 5:寫入當前工作表
    function writeToActiveSheet() {
      var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
      sheet.getRange("A1").setValue("使用者當前頁籤");
    }

    使用 getActiveSheet() 寫入當前選中工作表。

  • 範例 6:批次寫入多行資料
    function batchWriteData() {
      var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("輸入");
      var data = [
        ["2025-06-09", "A100", 120],
        ["2025-06-10", "A101", 200],
        ["2025-06-11", "A102", 180]
      ];
      var startRow = sheet.getLastRow() + 1;
      sheet.getRange(startRow, 1, data.length, data[0].length).setValues(data);
    }

    高效批次寫入,追加至最後一列後。

Google Sheet 寫入結果截圖

4. 小提醒與最佳實務

  • setValue():寫入單一儲存格,適合小量資料。
  • setValues():寫入 2D 陣列,適合批次操作,效率高。
  • appendRow():追加一列資料,效率較低,適合簡單應用。
  • getRange(row, column, numRows, numCols):精確指定寫入範圍。
  • 檢查工作表存在(如範例 1),避免執行錯誤。
  • 跨檔案操作時,優先使用 openById()openByUrl()
  • 避免過度依賴 getActiveSheet() 或索引,確保腳本穩定性。

Google Apps Script 編輯器介面截圖

5. 成功將資料傳送至 Google Sheet 的重點整理

1. Google Apps Script (GAS) 設定

程式碼重點

  • doPost 函數:處理表單 POST 請求,寫入 Google Sheet
  • SpreadsheetApp.openById():使用正確的試算表 ID
  • appendRow():將資料寫入新的一行
  • CORS 標頭:雖然 TextOutput 無法用 setHeader,但 GAS Web App 會自動處理簡單請求

實際 GAS 程式碼範例

function doPost(e) {
  try {
    var sheet = SpreadsheetApp.openById('你的Spreadsheet_ID').getActiveSheet();
    Logger.log('收到 POST 請求');
    Logger.log('e.parameter: ' + JSON.stringify(e.parameter));
    var data = e.parameter;
    var row = [
      data.name || '',
      data.email || '',
      data.phone || '',
      data.message || '',
      new Date()
    ];
    sheet.appendRow(row);
    Logger.log('已寫入試算表');
    
    return ContentService.createTextOutput(
      JSON.stringify({result: "success"})
    ).setMimeType(ContentService.MimeType.JSON);
  } catch(error) {
    Logger.log('錯誤: ' + error.toString());
    return ContentService.createTextOutput(
      JSON.stringify({result: "error", message: error.toString()})
    ).setMimeType(ContentService.MimeType.JSON);
  }
}

function doGet(e) {
  return ContentService.createTextOutput("此服務僅支援 POST 請求。");
}

權限授權

  • 第一次寫入必須手動授權:在 GAS 編輯器執行測試函數,點選「允許」
  • Web App 部署權限:「任何人(甚至未登入者)」可存取

2. 前端表單設定

HTML 表單格式

<form action="https://script.google.com/macros/s/你的ID/exec" method="POST" target="hidden_iframe">
  <input name="name" ...>
  <input name="email" ...>
  <!-- 其他欄位 -->
</form>

完整實務範例:邀請演講表單

// GAS 端程式碼
function doPost(e) {
  try {
    var sheet = SpreadsheetApp.openById('1ubnN1u18UGJfFXNMXbeUyPWKe5Gmj0JI11ozei-N1hc').getActiveSheet();
    Logger.log('收到邀請演講表單');
    var data = e.parameter;
    var row = [
      data.name || '',           // 邀請人姓名
      data.title || '',          // 職稱與單位
      data.email || '',          // 聯絡信箱
      data.phone || '',          // 聯絡電話
      data.orgurl || '',         // 所屬機構網址
      data.eventname || '',      // 活動名稱
      data.eventdate || '',      // 活動日期
      data.eventtime || '',      // 活動時間
      data.eventplace || '',     // 活動地點
      data.topic || '',          // 邀請主題
      data.duration || '',       // 預期講授長度
      data.audience || '',       // 對象與人數
      data.fee || '',            // 是否提供講師費
      data.invoice || '',        // 是否需要開立發票
      data.desc || '',           // 說明
      new Date()                 // 提交時間
    ];
    sheet.appendRow(row);
    Logger.log('已寫入試算表');
    
    // 寄信通知
    var mailBody = "有新邀請演講表單:\\n姓名:" + data.name + "\\n信箱:" + data.email;
    MailApp.sendEmail({
      to: "your-email@gmail.com",
      subject: "新邀請演講表單",
      body: mailBody
    });
    
    return ContentService.createTextOutput(
      JSON.stringify({result: "success"})
    ).setMimeType(ContentService.MimeType.JSON);
  } catch(error) {
    Logger.log('錯誤: ' + error.toString());
    return ContentService.createTextOutput(
      JSON.stringify({result: "error", message: error.toString()})
    ).setMimeType(ContentService.MimeType.JSON);
  }
}

此範例展示如何處理複雜的表單資料,包含資料驗證、寫入試算表、寄送通知等功能。

關鍵設定

  • method="POST":確保觸發 GAS 的 doPost 而非 doGet
  • action:必須是已部署的 Web App `/exec` 網址
  • name 屬性:必須與 GAS 端的 `data.name`、`data.email` 等完全對應

3. 避免 CORS 問題

解決方案

  • 使用純 HTML 表單提交:不用 JavaScript fetch/ajax
  • 避免 application/json:用預設的 form-urlencoded 格式
  • target="hidden_iframe":避免頁面跳轉,保持使用者體驗

4. 資料流程

  1. 使用者填寫表單 → 點擊送出
  2. 瀏覽器發送 POST 請求 → 到 GAS Web App
  3. GAS doPost 接收資料 → 從 `e.parameter` 取得
  4. 寫入 Google Sheet → 使用 `sheet.appendRow()`
  5. 回傳成功訊息 → 前端顯示 alert

5. 常見問題與解決

資料未寫入

  • 檢查 GAS 權限授權
  • 確認 Spreadsheet ID 正確
  • 檢查表單欄位 name 對應

CORS 錯誤

  • 改用純 HTML 表單
  • 不用 JavaScript fetch
  • 確認 Web App 部署權限

觸發 doGet 而非 doPost

  • 確認 `method="POST"`
  • 檢查 action 網址是否正確
  • 移除會攔截表單的 JavaScript

6. 測試與除錯

GAS 執行記錄

  • 查看「收到 POST 請求」日誌
  • 檢查「已寫入試算表」訊息
  • 確認沒有錯誤訊息

前端測試

  • 檢查表單是否真的送出
  • 確認沒有 JavaScript 錯誤
  • 驗證欄位資料正確傳送

總結:這個架構確保了穩定可靠的資料傳送,避免了跨域問題,並提供了良好的使用者體驗。

6. 學習路徑與下一步

建議學習順序

  1. 基礎操作:先掌握基本的 Sheet 物件取得方法
  2. 資料寫入:練習 setValue()、setValues()、appendRow() 等方法
  3. Web App 部署:學習如何建立和部署 GAS Web App
  4. 表單整合:實作前端表單與 GAS 的整合
  5. 進階功能:加入資料驗證、郵件通知、錯誤處理等

進階學習方向

  • 資料讀取與處理:學習如何從 Google Sheet 讀取和分析資料
  • 觸發器設定:使用時間觸發器自動執行腳本
  • API 整合:結合外部 API 進行資料處理
  • 使用者介面:建立自訂的 GAS 網頁介面
  • 效能優化:處理大量資料時的效能考量

提示:建議從簡單的範例開始,逐步增加複雜度。實作過程中遇到問題時,可以查看 GAS 的執行記錄和錯誤訊息來進行除錯。