Google 試算表提供數百種內建函式,例如 AVERAGE
、SUM
和 VLOOKUP
。如果這些函式無法滿足您的需求,您可以使用 Google Apps Script 編寫自訂函式 (例如將公尺轉換為英里或從網際網路擷取即時內容),然後像內建函式一樣在 Google 試算表中使用這些函式。
開始使用
使用標準 JavaScript 建立自訂函式。如果您是 JavaScript 新手,Codecademy 提供了適合新手的課程。(注意:本課程並非由 Google 製作,與 Google 毫無關聯)。
以下是名為 DOUBLE
的簡易自訂函式,會將輸入值乘以 2:
/**
* Multiplies an input value by 2.
* @param {number} input The number to double.
* @return The input multiplied by 2.
* @customfunction
*/
function DOUBLE(input) {
return input * 2;
}
如果您不知道如何編寫 JavaScript,且沒有時間學習,請查看外掛程式商店,確認是否有其他人已建立您需要的自訂函式。
建立自訂函式
如要編寫自訂函式:
- 在 Google 試算表中建立或開啟試算表。
- 在選單項目中依序選取「Extensions」>「Apps Script」。
- 刪除指令碼編輯器中的任何程式碼。對於上述
DOUBLE
函式,只要複製程式碼並貼到指令碼編輯器中即可。 - 按一下頂端的「 」。
您現在可以使用自訂函式了。
從 Google Workspace Marketplace取得自訂函式
Google Workspace Marketplace 提供多個自訂函式,做為 Google 試算表外掛程式。如何使用或探索這些外掛程式:
- 在 Google 試算表中建立或開啟試算表。
- 依序按一下頂端的「外掛程式」>「取得外掛程式」。
- Google Workspace Marketplace 開啟後,按一下右上角的搜尋框。
- 輸入「自訂函式」,然後按下 Enter 鍵。
- 如果發現感興趣的自訂函式外掛程式,請按一下「Install」進行安裝。
- 對話方塊可能會顯示外掛程式需要授權。如果是,請詳閱通知,然後按一下「Allow」。
- 即可在試算表中使用外掛程式。如要在其他試算表中使用這個外掛程式,請開啟另一個試算表,然後在頂端依序點選「add-ons」>「Manage plugin」。找到要使用的外掛程式,然後依序點選「選項」圖示 >「用於本文件」。
使用自訂函式
編寫自訂函式或從Google Workspace Marketplace安裝函式後,即可輕鬆做為內建函式使用:
- 按一下您想要使用函式的儲存格。
- 輸入等號 (
=
),後面接著函式名稱和任何輸入值 (例如=DOUBLE(A1)
),然後按下 Enter 鍵。 - 儲存格會立即顯示
Loading...
,然後傳回結果。
自訂函式規範
編寫自己的自訂函式之前,請先瞭解一些準則。
命名
除了為 JavaScript 函式命名的標準慣例之外,請注意下列事項:
- 自訂函式的名稱必須與內建函式 (例如
SUM()
) 的名稱不同。 - 自訂函式的名稱不能以底線 (
_
) 結尾,表示 Apps Script 的私人函式。 - 自訂函式的名稱必須使用
function myFunction()
語法宣告,而非使用var myFunction = new Function()
。 - 儘管大寫並不重要,但試算表函式的名稱傳統是大寫。
引數
自訂函式和內建函式一樣,可以使用引數做為輸入值:
- 如果使用單一儲存格參照做為引數 (例如
=DOUBLE(A1)
) 來呼叫函式,引數將是儲存格的值。 如果您使用對儲存格範圍參照作為引數 (例如
=DOUBLE(A1:B10)
) 來呼叫函式,引數將是儲存格值的二維陣列。例如,在下方的螢幕截圖中,Apps Script 會將=DOUBLE(A1:B2)
中的引數解讀為double([[1,3],[2,4]])
。請注意,上述的DOUBLE
程式碼範例必須經過修改,才能接受陣列做為輸入內容。自訂函式引數必須為確定性。也就是說,內建試算表函式無法在每次計算時傳回不同的結果,例如
NOW()
或RAND()
,都不能做為自訂函式的引數。如果自訂函式嘗試根據其中一個揮發性內建函式傳回值,就會無限期顯示Loading...
。
傳回值
每個自訂函式都必須傳回要顯示的值,因此:
- 如果自訂函式傳回值,該值會顯示在呼叫函式的來源儲存格中。
- 如果自訂函式傳回值的二維陣列,只要這些儲存格為空,值就會溢位到相鄰的儲存格中。如果這樣會導致陣列覆寫現有的儲存格內容,自訂函式會改為擲回錯誤。如需範例,請參閱「最佳化自訂函式」一節。
- 自訂函式只能對傳回值的目標儲存格造成影響。 也就是說,自訂函式無法編輯任意儲存格,只有呼叫它的來源儲存格和相鄰的儲存格。如要編輯任意儲存格,請改用自訂選單來執行函式。
- 自訂函式呼叫必須在 30 秒內傳回。否則儲存格會顯示錯誤訊息:
Internal error executing the custom function.
資料類型
Google 試算表會根據資料性質,以不同格式儲存資料。在自訂函式中使用這些值時,Apps Script 會將這些值視為 JavaScript 中的適當資料類型。以下是最常見的讓使用者感到困惑:
- 試算表中的時間和日期會成為 Apps Script 中的 Date 物件。如果試算表和指令碼使用不同的時區 (罕見問題),自訂函式將需要補償。
- 試算表中的時間長度值也會成為
Date
物件,但處理這類物件的方式可能很複雜。 - 試算表中的百分比值在 Apps Script 中會變成十進位數字。舉例來說,值為
10%
的儲存格在 Apps Script 中會變成0.1
。
自動完成
Google 試算表支援自訂函式的自動完成功能,與內建函式非常類似。當您在儲存格中輸入函式名稱時,系統會顯示與您輸入內容相符的內建和自訂函式清單。
如果自訂函式的指令碼含有 JsDoc
@customfunction
標記 (如下方的 DOUBLE()
範例所示),則該自訂函式就會顯示在清單中。
/**
* Multiplies the input value by 2.
*
* @param {number} input The value to multiply.
* @return The input multiplied by 2.
* @customfunction
*/
function DOUBLE(input) {
return input * 2;
}
進階
使用 Google Apps Script 服務
自訂函式可以呼叫某些 Google Apps Script 服務以執行更複雜的工作。舉例來說,自訂函式可以呼叫語言服務,將英文詞組翻譯成西班牙文。
與大多數其他類型的 Apps Script 不同,自訂函式一律不會要求使用者授予個人資料的存取權。因此只能呼叫無法存取個人資料的服務,特別是以下幾個:
支援的服務 | 附註 |
---|---|
快取 | 可在自訂函式中運作,但較不實用 |
HTML | 可以產生 HTML,但無法顯示 (極少用) |
JDBC | |
語言 | |
鎖定 | 可在自訂函式中運作,但較不實用 |
地圖介面集 | 可計算路線,但不顯示地圖 |
資源 | getUserProperties() 只會取得試算表擁有者的屬性。試算表編輯者無法在自訂函式中設定使用者屬性。 |
試算表 | 唯讀 (可使用大多數 get*() 方法,但 set*() 不支援)。無法開啟其他試算表 ( SpreadsheetApp.openById() 或 SpreadsheetApp.openByUrl() )。 |
網址擷取 | |
實用工具 | |
XML |
如果您的自訂函式擲回 You do not have permission to
call X service.
錯誤訊息,服務需要使用者授權,因此無法用於自訂函式。
如要使用上方未列出的服務,請建立可執行 Apps Script 函式的自訂選單,而非編寫自訂函式。從選單觸發的函式會在必要時要求使用者授權,因此可能會使用所有 Apps Script 服務。
分享
自訂函式會開始「繫結」至其建立的試算表。也就是說,除非您使用以下其中一種方法,否則無法在其他試算表中使用編寫於某份試算表的自訂函式:
- 依序點選「Extensions」>「Apps Script」開啟指令碼編輯器,然後複製原始試算表中的指令碼文字,然後貼到其他試算表的指令碼編輯器中。
- 依序按一下「File」>「Create a copy」,建立包含自訂函式的試算表副本。複製試算表時,系統也會複製試算表中的所有附加指令碼。凡是擁有試算表存取權的使用者,都可以複製指令碼。(只有檢視權限的協作者無法在原始試算表中開啟指令碼編輯器。不過,建立副本時,他們會成為副本的擁有者,並且看到該指令碼)。
- 以 Google 試算表編輯器外掛程式發布指令碼。
最佳化
每當試算表中使用自訂函式時,Google 試算表就會分別呼叫 Apps Script 伺服器。如果您的試算表包含數十個 (或數百個,甚至數千個) 的自訂函式呼叫,這項程序可能相當緩慢。
因此,如果您打算對大量資料多次使用自訂函式,請考慮修改函式,使其接受二維陣列形式的輸入範圍,然後傳回可溢位至適當儲存格的二維陣列。
舉例來說,您可以重新編寫上述的 DOUBLE()
函式,使其接受單一儲存格或儲存格範圍,如下所示:
/**
* Multiplies the input value by 2.
*
* @param {number|Array<Array<number>>} input The value or range of cells
* to multiply.
* @return The input multiplied by 2.
* @customfunction
*/
function DOUBLE(input) {
return Array.isArray(input) ?
input.map(row => row.map(cell => cell * 2)) :
input * 2;
}
上述做法使用 JavaScript Array
物件的 map 方法,可針對 2D 儲存格陣列中的每個值,以遞迴方式呼叫 DOUBLE
。這個方法會傳回包含結果的二維陣列。這樣一來,您只可以呼叫 DOUBLE
一次,但它可以一次計算大量儲存格,如下方螢幕截圖所示。(您可以使用巢狀 if
陳述式 (而非 map
呼叫) 完成相同的操作)。
同樣地,下列自訂函式可有效率地從網際網路擷取即時內容,並使用二維陣列顯示單一函式呼叫來顯示兩欄結果。如果每個儲存格都需要專屬的函式呼叫,由於 Apps Script 伺服器每次都必須下載和剖析 XML 動態饋給,因此作業的執行時間會大幅增加。
/**
* Show the title and date for the first page of posts on the
* Developer blog.
*
* @return Two columns of data representing posts on the
* Developer blog.
* @customfunction
*/
function getBlogPosts() {
var array = [];
var url = 'https://gsuite-developers.googleblog.com/atom.xml';
var xml = UrlFetchApp.fetch(url).getContentText();
var document = XmlService.parse(xml);
var root = document.getRootElement();
var atom = XmlService.getNamespace('http://www.w3.org/2005/Atom');
var entries = document.getRootElement().getChildren('entry', atom);
for (var i = 0; i < entries.length; i++) {
var title = entries[i].getChild('title', atom).getText();
var date = entries[i].getChild('published', atom).getValue();
array.push([title, date]);
}
return array;
}
這些技巧幾乎適用於整個試算表重複使用的任何自訂函式,不過實作詳細資料會因函式行為而有所差異。