的確可以,而且這種保持多值的能力,還能被進一步強化,構成所謂的「陣列公式(array formula)」,提供類似傳統電腦程式語言中的迴圈功能。
1. 單值旗標:Keep-single
Google試算表提供了許多的函式,每個函式通常都會接受一些參數,作為該函式運算時的依據。如果觀察這些函式的參數,會隱隱約約感覺到,每個參數似乎有個(看不見的)旗標,控制該參數在遇到陣列時應該如何反應。想像這個旗標,也許稱它為「單值旗標」。凡是被標上這個旗標的參數,都會期待傳給它的值是一個單值(non-array; single-value; scalar)。如果傳給它一個陣列(array; multiple-value),那麼在把值傳入函式之前,系統會先想辦法從這個陣列中找出一個單值(也就是,交集規則),然後才傳入該函式中。
相反的,對於那些沒有被標上單值旗標的參數,即使接收到陣列,系統也不會進行什麼特別的處理,就只是原封不動的把整個陣列傳入函式中。
2. 沒有單值旗標:Keep-array
先看看最單純的情況:沒有單值旗標。有些函式的參數,不論傳入的是單值(純量;scalar)、還是多值(陣列;array),它都會照單全收(Keep-array),不會試著把多值轉成單值(也就是不會使用交集規則)。函式FILTER()與SUM()就是這樣的例子:不管傳入的陣列是「儲存格範圍」、還是「函式傳回陣列」,FILTER()與SUM()對它們的處理方式都相同,就是全部拿來使用。這種參數,可以想像它們就是沒有被標示單值旗標。
3. 兩種單值旗標
由於陣列的來源有兩種(儲存格範圍、函式傳回陣列),這個單值旗標似乎也有兩個,控制該參數在遇到這兩種陣列時,是否要取單值。註:上例中,欄位F、G、H這三欄,是把同列欄位B中的公式,加上ARRAYFORMULA()之後,例如,把ADD($A$1:$C$1,500)變成ARRAYFORMULA(ADD($A$1:$C$1,500)),所得到的結果。
3.1 單值旗標:針對「儲存格範圍」取單值:Keep-single for cell range
具有這個旗標的參數,在傳入「儲存格範圍」時,就會試著取得該範圍中的某個單值。取值的規則,就是交集規則(把該範圍與公式所在儲存格的欄或列位址進行交集)。ADD()的所有參數。
IF()的所有參數。
CHOOSE()的所有參數。
INDEX()的第二個參數。
VLOOKUP()的第一、第三個參數。
INDEX()的第一個參數:Keep-array。
VLOOKUP()的第二個參數:Keep-array。
3.2 單值旗標:針對「函式傳回陣列」取單值:Keep-single for returned array
具有這個旗標的參數,在傳入「儲存格範圍」時,就會試著取得該範圍中的某個單值。取值的規則,是只取陣列最左上角的元素(而不是與公式所在儲存格的欄或列位址進行交集)。ADD()的所有參數。
IF()的第一個參數。
CHOOSE()的第一個參數。
INDEX()的第二個參數。
VLOOKUP()的第一、第三個參數。
例外
IF()的第二個參數:Keep-array。
CHOOSE()的第二個參數:Keep-array。
INDEX()的第一個參數:Keep-array。
VLOOKUP()的第二個參數:Keep-array。
3.3 有規則嗎?
感覺上,規則似乎有點混亂(說不定根本就沒有規則)。為了容易記憶起見,也許可以這樣歸納:
- 一般的函式
- FILTER()、SUM()、ADD()
- 單值的參數,傾向於同時具有兩種單值旗標。
- 多值的參數,傾向於沒有任何單值旗標。
- 選擇型函式
- IF()、CHOOSE()、INDEX()、VLOOKUP()、HLOOKUP()
- 特徵:根據索引值從多個值中選擇出一個值的函式。
- 擔任索引值的參數,似乎都傾向於取用單值(Keep-single)。
- IF(1st,...)、CHOOSE(1st,...)、INDEX(...,2nd,3rd)、VLOOKUP(1st,...,3rd,...)、HLOOKUP(1st,...,3rd,...)
- 而要被從中選擇的參數,則似乎傾向於維持多值(Keep-array)。
- IF(...,2nd,3rd)、CHOOSE(...,2nd,3rd,4th)、INDEX(1st,...)、VLOOKUP(...,2nd,...)、HLOOKUP(...,2nd,...)
- 但這不是絕對的規則,個別函式,仍可能有不同的特性。
- IF(...,2nd,3rd)、CHOOSE(...,2nd,3rd,4th)雖然是被選擇的標的,但是具有Keep-single for cell range旗標,卻不具有Keep-single for returned array旗標。
4. 抑制單值旗標:強制維持多值(Forcibly Keep-array)
為什麼要「想像」可能有所謂的單值旗標(Keep-single)呢?這是因為如果沒有這種維持單值的概念,似乎就不容易理解ARRAYFORMULA()這個函式的效果。簡單的說,函式ARRAYFORMULA()會抑制單值旗標,強迫它涵蓋下的每個參數,在接收到陣列時,都會盡可能維持多值(Keep-array)。
- 這在某些函式的身上,效果十分明顯而純粹。
- 例如:ADD()。
- 但是在另外一些函式身上,好像沒有效果。
- Cell Range仍然維持Keep-single for cell range的效果(交集規則)。
- 例如:CHOOSE(1st,...)。在上例中,由於公式ARRAYFORMULA( CHOOSE( $A$1:$C$1, 4, 5, 6 ) )所在儲存格$F$9的欄位址$F:$F,已經無法與參數範圍$A$1:$C$1產生交集,所以得到#NUM!的錯誤值。
- 例如:INDEX(...,2nd,3rd)。在上例中,由於公式ARRAYFORMULA( INDEX( {1,2,3;4,5,6}, 2, $A$1:$B$1 ) )所在儲存格$F$12的欄位址$F:$F,已經無法與參數範圍$A$1:$B$1產生交集,所以似乎被使用0取代,得到等同於ARRAYFORMULA( INDEX( {1,2,3;4,5,6}, 2, 0 ) )的效果,傳回一整列。
- Function Returned Array也似乎仍維持Keep-single for returned array的效果。
- 例如:INDEX(...,2nd,3rd)。在上例中,儲存格$F$25的公式ARRAYFORMULA( INDEX( {1,2,3;4,5,6}, 2, { $A$1:$B$1 } ) ),仍然固定取用傳入陣列的最左上角元素。
4.1 ARRAYFORMULA()的涵蓋範圍
ARRAYFORMULA()的影響範圍會遞迴,會從它出現的位置開始,往它所包含的運算式,逐層遞迴,直到最深最內層的函式為止。相關文章
1. Google Sheets: Array Lesson 1: 建立陣列 (Creating an array)2. Google Sheets: Array Lesson 2: 陣列-交集-單值 (Array-Intersection-Single value)
3. Google Sheets: Array Lesson 4: 陣列-擴展 (Array-Expansion)
參考資料
1. Open Formula: Non-Scalar Evaluation (aka 'Array expressions')2. Apache OpenOffice: Documentation/How Tos/Using Arrays
3. LibreOffice: Calc: Array Functions