Google 試算表:從URL取得試算表 openByUrl()

 


如果你手上常握著幾個 Google 試算表連結,卻總是在複製貼上間來回跑,openByUrl() 會是很省事的入口。

它讓腳本在後台直接打開指定網址的試算表,接著就能用熟悉的 getSheetByName()、getRange() 讀寫資料。聽起來簡單,但真正影響成敗的是細節:要不要改用 openById()、URL 格式要注意什麼、權限不夠會怎麼報錯、批次處理怎麼寫才不會超時。

場景很常見:多份表要彙整、同事丟你一串連結、或是想做每天自動同步。重點其實不在語法,而是權限、觸發器與配額的眉角:什麼時候該用可安裝觸發器、為什麼自訂函數不行。希望透過本文章能幫助到需要的您。


目錄

{tocify} $title={目錄} 


openByUrl() 是什麼?何時該用?

SpreadsheetApp.openByUrl(url) 會「以伺服器端」打開指定網址的 Google 試算表,回傳一個 Spreadsheet 物件,讓你繼續 .getSheetByName()、.getRange()、.getValues() 等讀寫操作。它不會在你的瀏覽器真正開啟視窗,純粹是給腳本後台操作用。當網址不存在或你沒有存取權,它會直接丟例外。這個方法需要試算表作用域(spreadsheets scope)。


什麼情境選 openByUrl()?

你已經手上就是完整的「試算表網址」,直接丟入最省事。

場景偏向手動維運(例如把 URL 放在屬性或設定檔),可讀性高。

什麼時候改用 openById()?

你只存 ID,或擔心網址格式變動(例如後面多參數);ID 相對穩定。官方也在文件範例中示範如何由 URL 擷取 ID。


小提醒:簡易觸發器(如 onEdit(e)、onOpen(e))在未授權情境不能存取需要授權的服務,也不能碰到其他檔案;要做跨檔案請用可安裝觸發器(time-driven 等)。


開始前的準備


1.    確認權限

你的帳號必須對目標試算表至少有「檢視」或「編輯」權限;否則 openByUrl() 會丟錯。此方法需要 https://www.googleapis.com/auth/spreadsheets 作用域。

2.    拿到正確的 URL

標準格式類似:

https://docs.google.com/spreadsheets/d/<SPREADSHEET_ID>/edit#gid=<SHEET_GID>

只要是該試算表的 URL(不一定要帶 gid),即可被 openByUrl() 接受。

3.    選擇觸發器型態

手動執行或自訂選單 → 直接可用

自訂函數(寫在儲存格裡的 =MYFUNC())不可開別的檔案,會噴權限錯;要改成按鈕/選單/觸發器。

跨檔自動化 → 用可安裝觸發器(時間觸發、表單提交等)。


最小可用範例

範例 1:讀取外部表的資料

function readExternalSheet() {
  const url = 'https://docs.google.com/spreadsheets/d/【你的ID】/edit';
  const ss = SpreadsheetApp.openByUrl(url);          // 伺服器端開啟,不會彈出視窗
  const sheet = ss.getSheetByName('工作表1');          // 換成目標分頁名稱
  const values = sheet.getRange('A1:C10').getValues(); 
  Logger.log(values);
}


這段會回傳 A1:C10 的二維陣列。若 URL 不存在或你沒權限,會直接丟例外。


範例 2:寫回資料

function writeExternalSheet() {
  const url = 'https://docs.google.com/spreadsheets/d/【你的ID】/edit';
  const ss = SpreadsheetApp.openByUrl(url);
  const sheet = ss.getSheetByName('彙整');
  const data = [
    ['日期', '品項', '金額'],
    ['2025-10-03', '測試', 1000],
  ];
  sheet.getRange(1, 1, data.length, data[0].length).setValues(data); // 批次寫入更省配額
}


範例 3:從 URL 擷取 ID,切換 openById()

function openByIdFromUrl(url) {
  const m = url.match(/\/d\/([a-zA-Z0-9-_]+)/);
  if (!m) throw new Error('不是合法的試算表網址');
  return SpreadsheetApp.openById(m[1]); // 官方亦示範由 URL 取 ID 的概念
}


openById() 與 openByUrl() 功能等價;選你手邊資料最順手的那個。


實務開發套路(架構、效能、維運)

1.    打開一次、用到底

把 openByUrl() 放在回圈外;在迭代中重複使用同一個 Spreadsheet / Sheet 物件,避免重複開檔造成延遲與額外風險(尤其在 6 分鐘單次執行時限內)。

2.    批次讀寫、少呼叫多搬運

getValues() 與 setValues() 用大區塊批次處理,比逐格 .getValue() / .setValue() 省資源與配額;當你碰到「每分鐘請求數」的節流(429)時,記得加指數回退。

3.    參數集中管理

把目標 URL/ID 放在 PropertiesService(或單獨的「設定」工作表),避免散落在程式各處。日後換表只改一處。

 4.    觸發器要選對

要跨檔案就用可安裝觸發器(time-driven / on form submit);簡易觸發器(onEdit、onOpen)有權限與時間限制,不適合跨檔。

5.     Quota 與時限觀念

單次執行:6 分鐘;自訂函數:30 秒;觸發器總時數/日:Workspace 6 小時。設計流程時務必切批處理或分段排程。

若遇到「Too many requests / 429」或「Service invoked too many times」,實作重試與暫停。


逐步實作指南(從零到可用)

1.    建立 Apps Script 專案

    在任一試算表「擴充功能 → Apps Script」或前往 script.google.com 新建專案。

2.    貼上基礎程式

    用上面「範例 1/2」修改你的 URL、工作表名與範圍。

3.    第一次執行與授權

    執行時會跳出授權對話框,說明此腳本要「存取與編輯你的試算表」等權限。這是依你的程式自動推導的作用域。

4.    加上自訂選單(可選)

    讓使用者在試算表 UI 點一下就跑同步。

function onOpen() {
  SpreadsheetApp.getUi()
    .createMenu('資料同步')
    .addItem('從外部表讀取', 'readExternalSheet')
    .addItem('寫回彙整表', 'writeExternalSheet')
    .addToUi();
}


注意:onOpen 是簡易觸發器;它可以呼叫需要授權的函式前提是你已安裝授權。但若要跨檔案自動化,仍建議改用可安裝觸發器避免限制。

5. 排程自動執行(可安裝觸發器)

在 Apps Script 編輯器 → 時鐘圖示 → 新增觸發條件(例如每小時跑一次)。


錯誤處理與回退

function safeOpenByUrl(url) {
  try {
    const ss = SpreadsheetApp.openByUrl(url);
    return ss;
  } catch (err) {
    // 常見:URL 無效、沒權限、檔案在垃圾桶、網路暫時性問題
    throw new Error(`開啟失敗:${err.message}\n請檢查:1) URL 是否正確 2) 是否擁有權限 3) 檔案是否存在`);
  }
}

function withBackoff(fn, maxRetry = 5) {
  let wait = 500; // ms
  for (let i = 0; i < maxRetry; i++) {
    try { return fn(); }
    catch (e) {
      if (String(e).includes('429') || String(e).includes('Service invoked too many times')) {
        Utilities.sleep(wait);
        wait *= 2; // 指數回退
      } else {
        throw e;
      }
    }
  }
  throw new Error('重試次數已達上限');
}


權限與安全:最小必要原則

作用域由程式碼自動推導。就算註解掉的程式也可能引出授權提醒,不要把不必要的 API 呼叫留在檔案裡。

跨檔操作前,請先在 Drive 把目標試算表分享給執行腳本的帳號(或加到同網域/群組)。openByUrl() 找不到或沒有權限會直接丟錯。


常見錯誤與「雷點」總整理

1.    在自訂函數使用 openByUrl()

        自訂函數(寫在儲存格的 =FUNC())處於受限環境,不能開啟其他檔案、不能觸發需要授權的服務 → 會噴 You do not have permission to call openByUrl 這類錯誤。請改成選單或觸發器執行。

2.    放在簡易觸發器中跨檔案

        onEdit(e)、onOpen(e) 限制多、時間短(30 秒)且不能存取其他檔案。跨檔自動化請改可安裝觸發器。

3.    URL 不是試算表

        貼了分享頁、預覽頁或「/copy」連結,會報「URL 不存在」或類似錯誤。請貼「docs.google.com/spreadsheets/d/...」的正式網址。

4.    沒有權限或檔案在垃圾桶

        當前帳號沒有權限、檔案被移除/在垃圾桶,都會丟例外。先確認 Drive 權限與檔案狀態。

5.    逐格操作造成限流/逾時

        一格一格 .setValue() 容易撞到每分鐘配額或 6 分鐘時限。改用批次、回退與分段排程。

6.    在迴圈裡重複 openByUrl()

        重複開檔很浪費、也易失敗。請開一次、重用物件。

7.     把 gid 當成工作表名稱

        gid 是分頁的內部 ID,不是名稱。請用 .getSheetByName('分頁名') 或 .getSheets()[index]。

8.    多使用者同時動到同一表

        建議搭配 LockService 控制同時寫入,或切成「讀 → 計算 → 一次寫」的流程,降低競爭。

9.    忽略回傳物件是「伺服器端打開」

        openByUrl() 不會替你在瀏覽器切換頁籤;它只是讓腳本能操作該表。

10.    把 URL/ID 寫死在多處

        之後換表要改很多地方,容易漏。集中到設定或 Properties。


問題集

Q1:openByUrl() 和 openById() 哪個比較快?

    兩者皆為伺服器端開啟,操作體驗接近。就維運性來看,手上有哪個就用哪個;若你只保留 ID 做設定管理也很常見。

Q2:出現「429 Too Many Requests」怎麼辦?

    用批次 API、減少呼叫次數、加入指數回退,必要時切批在不同時間觸發。

Q3:腳本跑一半就停(Exceeded maximum execution time)?

    Apps Script 單次執行上限 6 分鐘;把大任務拆段(多個觸發器)、減少操作次數、避免在回圈開檔。

Q4:為什麼第一次執行會跳授權?

    Apps Script 會依你的程式自動推導需要的作用域(例如存取試算表),因此需要你同意。

Q5:可以在儲存格用 =MYFUNC() 去開另外一份表嗎?

    不行。自訂函數不可呼叫需要授權的服務、也不能操作其他檔案。改用選單或觸發器。



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