看過前面一系列文章的朋友,一定會熟悉“重新定義數組維度”的概念。這是一項非常有用且非常重要的技術,使我們可以接受二維數組并將其轉換為一維數組,同時將元素保留在該數組中。
如果希望進一步操縱某二維數組的元素,則需要使用這種技術。例如,由于某種原因,在某種情形下,需要將二維數組中的每個元素傳遞給一個或多個參數進行進一步處理。但是,由于需要使用的Excel函數不能處理多維數組,因此必須首先將原數組轉換為一維數組。
以示例來說明,如下圖1所示的工作表。
圖2
顯然,這里的數據是二維的,是一個10行5列的數組,其Excel表示為:
{“A1″,”B1″,”C1″,”D1″,”E1″;”A2″,”B2″,”C2″,”D2″,”E2″;”A3″,”B3″,”C3″,”D3″,”E3″;”A4″,”B4″,”C4″,”D4″,”E4″;”A5″,”B5″,”C5″,”D5″,”E5″;”A6″,”B6″,”C6″,”D6″,”E6″;”A7″,”B7″,”C7″,”D7″,”E7″;”A8″,”B8″,”C8″,”D8″,”E8″;”A9″,”B9″,”C9″,”D9″,”E9″;”A10″,”B10″,”C10″,”D10″,”E10”}
但是,由于某些原因,我們需要將上述數據放置在一維數組中:
{“A1″;”B1″;”C1″;”D1″;”E1″;”A2″;”B2″;”C2″;”D2″;”E2″;”A3″;”B3″;”C3″;”D3″;”E3″;”A4″;”B4″;”C4″;”D4″;”E4″;”A5″;”B5″;”C5″;”D5″;”E5″;”A6″;”B6″;”C6″;”D6″;”E6″;”A7″;”B7″;”C7″;”D7″;”E7″;”A8″;”B8″;”C8″;”D8″;”E8″;”A9″;”B9″;”C9″;”D9″;”E9″;”A10″;”B10″;”C10″;”D10″;”E10”}
如何得到這個50行1列的數組?
(或者,一個1行50列的數組:
{“A1″,”B1″,”C1″,”D1″,”E1″,”A2″,”B2″,”C2″,”D2″,”E2″,”A3″,”B3″,”C3″,”D3″,”E3″,”A4″,”B4″,”C4″,”D4″,”E4″,”A5″,”B5″,”C5″,”D5″,”E5″,”A6″,”B6″,”C6″,”D6″,”E6″,”A7″,”B7″,”C7″,”D7″,”E7″,”A8″,”B8″,”C8″,”D8″,”E8″,”A9″,”B9″,”C9″,”D9″,”E9″,”A10″,”B10″,”C10″,”D10″,”E10″})
通常使用下面的公式:
=INDEX(A1:E10,N(IF(1,1+(INT((ROW(INDEX(A:A,1):INDEX(A:A,ROWS(A1:E10)*COLUMNS(A1:E10)))-1)/COLUMNS(A1:E10))))),N(IF(1,1+(MOD((ROW(INDEX(A:A,1):INDEX(A:A,ROWS(A1:E10)*COLUMNS(A1:E10)))-1),COLUMNS(A1:E10))))))
其思路是將這個二維數組中的每個元素精確地索引一次,上面的公式轉換為:
=INDEX(A1:E10,N(IF(1,{1;1;1;1;1;2;2;2;2;2;3;3;3;3;3;4;4;4;4;4;5;5;5;5;5;6;6;6;6;6;7;7;7;7;7;8;8;8;8;8;9;9;9;9;9;10;10;10;10;10})),N(IF(1,{1;2;3;4;5;1;2;3;4;5;1;2;3;4;5;1;2;3;4;5;1;2;3;4;5;1;2;3;4;5;1;2;3;4;5;1;2;3;4;5;1;2;3;4;5;1;2;3;4;5})))
這里的關鍵是,傳遞給INDEX函數的數組(用于參數row_num和參數column_num的數組)都是相同的向量類型(均為列向量),從而確保了由INDEX產生的數組也是這種向量類型。根據其定義,列向量當然是一維的。這里使用的技術請參閱《Excel公式技巧03:INDEX函數,給公式提供數組》、《Excel公式練習44:從多列中返回唯一且按字母順序排列的列表》。
可以看出,INDEX結構具有不可否認的優勢,不僅可以將其用于重新定義工作表區域的維度,還可以重新定義公式中某些其他子函數產生的數組的維度。
然而,還可以使用更短的公式:
=T(INDIRECT(TEXT(MODE.MULT(10^5*(1+MOD(ROW(A1:E20)-1,10))+COLUMN(A1:E10)),”R0C00000″),0))
注意,上述公式結構使用了函數T,因此要求單元格區域A1:E10內的值是非數字的。對于由數值組成的單元格區域,可以使用N函數。對于包含混合數據類型的區域,建議使用INDEX方法。
關鍵是要利用MODE.MULT函數的特性來返回返回一維數組,無論傳遞給該函數的數組本身是一維數組還是二維數組,這都同樣適用。然而,MODE.MULT函數自身也存在缺點:傳遞的數組中的任何元素都要至少出現一次,否則將出錯,這意味著我們要強制解決該問題。因此,這里故意使用了擴展的單元格區域A1:E20:
1+MOD(ROW(A1:E20)-1,10)
轉換為:
1+MOD({1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16;17;18;19;20}-1,10)
轉換為:
1+MOD({0;1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16;17;18;19},10)
轉換為:
1+{0;1;2;3;4;5;6;7;8;9;0;1;2;3;4;5;6;7;8;9}
得到:
{1;2;3;4;5;6;7;8;9;10;1;2;3;4;5;6;7;8;9;10}
此時,公式中的:
T(INDIRECT(TEXT(MODE.MULT(10^5*(1+MOD(ROW(A1:E20)-1,10))+COLUMN(A1:E10)),”R0C00000″),0))
轉換為:
T(INDIRECT(TEXT(MODE.MULT(10^5*{1;2;3;4;5;6;7;8;9;10;1;2;3;4;5;6;7;8;9;10}+COLUMN(A1:E10)),”R0C00000″),0))
轉換為:
T(INDIRECT(TEXT(MODE.MULT({100000;200000;300000;400000;500000;600000;700000;800000;900000;1000000;100000;200000;300000;400000;500000;600000;700000;800000;900000;1000000}+{1,2,3,4,5}),”R0C00000″),0))
轉換為:
T(INDIRECT(TEXT(MODE.MULT({100001,100002,100003,100004,100005;200001,200002,200003,200004,200005;300001,300002,300003,300004,300005;400001,400002,400003,400004,400005;500001,500002,500003,500004,500005;600001,600002,600003,600004,600005;700001,700002,700003,700004,700005;800001,800002,800003,800004,800005;900001,900002,900003,900004,900005;1000001,1000002,1000003,1000004,1000005;100001,100002,100003,100004,100005;200001,200002,200003,200004,200005;300001,300002,300003,300004,300005;400001,400002,400003,400004,400005;500001,500002,500003,500004,500005;600001,600002,600003,600004,600005;700001,700002,700003,700004,700005;800001,800002,800003,800004,800005;900001,900002,900003,900004,900005;1000001,1000002,1000003,1000004,1000005}),”R0C00000″),0))
轉換為:
T(INDIRECT(TEXT({100001;100002;100003;100004;100005;200001;200002;200003;200004;200005;300001;300002;300003;300004;300005;400001;400002;400003;400004;400005;500001;500002;500003;500004;500005;600001;600002;600003;600004;600005;700001;700002;700003;700004;700005;800001;800002;800003;800004;800005;900001;900002;900003;900004;900005;1000001;1000002;1000003;1000004;1000005},”R0C00000”),0))
轉換為:
T(INDIRECT({“R1C00001″;”R1C00002″;”R1C00003″;”R1C00004″;”R1C00005″;”R2C00001″;”R2C00002″;”R2C00003″;”R2C00004″;”R2C00005″;”R3C00001″;”R3C00002″;”R3C00003″;”R3C00004″;”R3C00005″;”R4C00001″;”R4C00002″;”R4C00003″;”R4C00004″;”R4C00005″;”R5C00001″;”R5C00002″;”R5C00003″;”R5C00004″;”R5C00005″;”R6C00001″;”R6C00002″;”R6C00003″;”R6C00004″;”R6C00005″;”R7C00001″;”R7C00002″;”R7C00003″;”R7C00004″;”R7C00005″;”R8C00001″;”R8C00002″;”R8C00003″;”R8C00004″;”R8C00005″;”R9C00001″;”R9C00002″;”R9C00003″;”R9C00004″;”R9C00005″;”R10C00001″;”R10C00002″;”R10C00003″;”R10C00004″;”R10C00005”},0))
結果為:
{“A1″;”B1″;”C1″;”D1″;”E1″;”A2″;”B2″;”C2″;”D2″;”E2″;”A3″;”B3″;”C3″;”D3″;”E3″;”A4″;”B4″;”C4″;”D4″;”E4″;”A5″;”B5″;”C5″;”D5″;”E5″;”A6″;”B6″;”C6″;”D6″;”E6″;”A7″;”B7″;”C7″;”D7″;”E7″;”A8″;”B8″;”C8″;”D8″;”E8″;”A9″;”B9″;”C9″;”D9″;”E9″;”A10″;”B10″;”C10″;”D10″;”E10″}
正是我們需要的一維數組。
回到上文中的MID函數示例,我們試圖通過公式:
=MID(A1:C9,{1,2},1)
生成由給定這些參數的所有54個排列組成的數組。使用我們的重新定義維數的技術,只需使用A1:C9對上述公式相應位置進行替換:
MID(T(INDIRECT(TEXT(MODE.MULT(10^5*(1+MOD(ROW(A1:C19)-1,10))+COLUMN(A1:C9)),”R0C00000”),0)),{1,2},1)
轉換為:
MID({“Amapá”;”S?oPaulo”;”Paraná”;”Espírito Santo”;”SantaCatarina”;”Maranh?o”;”Pernambuco”;”Alagoas”;”MatoGrosso”;”Ceará”;”Paraíba”;”Piauí”;”RioGrande do Sul”;”Rond?nia”;”Tocantins”;”Bahia”;”MinasGerais”;”Roraima”;”Mato Grosso doSul”;”Goiás”;”Pará”;”Amazonas”;”RioGrande do Norte”;”Rio de Janeiro”;”Acre”;”DistritoFederal”;”Sergipe”},{1,2},1)
轉換為:
{“A”,”m”;”S”,”?”;”P”,”a”;”E”,”s”;”S”,”a”;”M”,”a”;”P”,”e”;”A”,”l”;”M”,”a”;”C”,”e”;”P”,”a”;”P”,”i”;”R”,”i”;”R”,”o”;”T”,”o”;”B”,”a”;”M”,”i”;”R”,”o”;”M”,”a”;”G”,”o”;”P”,”a”;”A”,”m”;”R”,”i”;”R”,”i”;”A”,”c”;”D”,”i”;”S”,”e”}
生成了想要的54個元素。
同樣,我們可以將這項技術運用到“四維數組”:
=MID(A1:C9,{1,2},{1;2;3})
對于第二次重新定義數組維數,必須使用前面的INDEX構造:
=MID(INDEX(ReDim1,N(IF(1,1+(INT((ROW(INDEX(A:A,1):INDEX(A:A,ROWS(ReDim1)*COLUMNS(ReDim1)))-1)/COLUMNS(ReDim1))))),N(IF(1,1+(MOD((ROW(INDEX(A:A,1):INDEX(A:A,ROWS(ReDim1)*COLUMNS(ReDim1)))-1),COLUMNS(ReDim1)))))),1,{1,2,3})
其中的ReDim1是我們第一次重新定義數組維數的公式:
=MID(T(INDIRECT(TEXT(MODE.MULT(10^5*(1+MOD(ROW($A$1:$C$19)-1,10))+COLUMN($A$1:$C$9)),”R0C00000″),0)),{1,2},MAX(LEN($A$1:$C$9)))
太復雜了!腦筋都不夠用了!