偶然在群裡看到一個關於數字提取的問題,大家一起來看看吧:
這是一個典型的不規則數據,文本和數字混合(還有符號),數字還有小數。如果非要說有規律的話,就是每個單元格只有一個數值,並且是正數。
例子中的公式為:
=MAX(--TEXT(MID(A2,ROW($1:$10),COLUMN(A:H)),"0.00;;0;!0"))
當然這個公式不是唯一的解法,還有一些其他的公式可以實現,我們今天的主要目的也不是一題多解,研究提取數字的問題。而是想借這個例子,來分析裡面涉及到的知識點,下面我們一起來分析一下這個公式:
首先,這是一個數組公式,必須按三鍵完成輸入(有關數組公式的基本知識文末會有推薦閱讀的文章,請根據自己的情況選擇閱讀)。
其次,這個公式裡用到了五個函數:max,text,mid,row和column。
這四個函數之前的文章都有介紹,基本的用法都不是很難:
max是返回一組數字的最大值;
text是按照指定的格式顯示數據;
mid是根據指定位置提取字符串的內容;
row得到行號;
column得到列號。
可是當一些基礎的函數組合起來以後,往往就變得難以理解,這是今天的主要內容。
最後,對於較為複雜的公式,通常都是從最裡層的函數開始分析,本例中最外層的函數是max,text在第二層,mid在第三層,row和column共同作為mid函數的參數,也就是最內層函數。這是我們分析的順序,再就是要藉助f9功能鍵,對於計算過程進行解讀,了解每一個函數實現了什麼樣的效果。
下面進入正題,來解讀這個公式:
先看這部分:MID(A2,ROW($1:$10),COLUMN(A:H))
mid函數的基本含義是:mid(字符串,開始截取的位置,截取長度)
例子中開始截取的位置用到了row,截取長度用到了column;
ROW($1:$10)的結果是1到10的一個數組(10個數字),也就是說將一個字符串截取了10次,從第1個字到第10個字開始進行截取,為了便於理解,我們看看=MID(A2,ROW($1:$10),1)這個公式可以得到什麼內容:
記得是按三鍵(Ctrl、shift、enter),表面上只能看到一個字,實際上應該是10個字,我們按f9看看:
看到了嗎?將單元格的內容分解成了一個一個的字符,從第一個字開始提取一個字符、從第二個字開始提取一個字符……
與之類似,我們再看看
=MID(A2,1,COLUMN(A:H))可以得到什麼內容,這次我是直接按了f9顯示的:
這次結果變了,提取的位置固定,都是從第一個字開始,但是長度增加了。
對比兩個公式的結果,有個細節,使用row得到數據是用分號分隔的,而使用了column得到數據是用逗號分隔的。在數組的計算規則裡,分號和逗號是不同方向的數組(好比行是縱向,列是橫向),單獨存在的時候,看不出區別,但是發生計算的時候,就會有區別了。
現在我們來看看MID(A2,ROW($1:$10),COLUMN(A:H)這部分的結果吧:
這部分看起來是不是非常暈的感覺,其實數據還是非常規則的,注意第一個分號之前的內容,都是從第一個字開始,長度遞增提取的結果,然後就是從第二個字開始提取,長度遞增提取的結果……
這樣做的目的就是把單元格裡內容徹底拆分進行重新組合,把所有的組合都列出來了,在這些新組合的字符串裡,就有我們需要的數字:
好了,說了這么半天,MID(A2,ROW($1:$10),COLUMN(A:H))這部分不知道你看明白沒有,在這部分裡面我們需要注意兩點:
ROW($1:$10)這裡面的10,需要根據單元格的字符長度來調整,如果最長的內容是20個字,這裡的10就要改成20,為了保險起見,我們可以稍微寫大一點,但是不要太大,因為會影響計算速度。
COLUMN(A:H)這裡用的列號,看起來不如數字那麼明顯,能不能也用row呢?
試試看:
公式這樣寫好像也能得到結果,那麼我們f9看看到底都是些什麼數據:
少了很多啊,這是因為兩個數組都是row,方向一致,無法得到完整的組合結果(不同方向數組計算原理可以想想九九乘法表,行列相乘得到一個區域,如果同行或是同列相乘的話,得到的也是一行或者一列數據)。
所以這裡的column是不能用row替換的,明白了吧。
回到我們的問題,COLUMN(A:H)得到的是1到8的數組,在mid函數中的作用是提取內容的長度,所以如果a列數據中有長度超過8位的數字,這裡就要修改,在本例中不會有太長的數字,所以a:h足夠了。
囉嗦了這麼多,總算是把mid這部分理清楚了,就是對數據源的內容進行重新組合,得到一些新的數據,有帶漢字的,也有純數字的,還有空的,接下來就是text函數出手的時候了,將這些新組合的數據進行統一,為了便於閱讀,我將公式TEXT(MID(A2,ROW($1:$10),COLUMN(A:H)),"0.00;;0;!0")中的mid部分用「一組數據」代替,看起來也簡單了很多:TEXT(一組數據,"0.00;;0;!0")。
在text裡,重點是第二參數"0.00;;0;!0"的含義,在text裡,第二參數決定了內容的顯示方式,而用分號進行分段是非常重要的一種用法。
通常用三個分號把數據分成四類,「正數;負數;0;文本」,而對每類數據單獨指定格式,對照來看,"0.00;;0;!0"這裡的四個格式分別是:「0.00」、「」、「0」、和「!0"。怎麼理解呢?
如果第一參數是正數,就按保留兩位小數來顯示;如果是負數,就不顯示;如果是0,原樣顯示為0;如果是文本,則強制顯示為0,"!"在這裡是強制顯示的意思。
因為本例中不會出現負數,所以這裡的第二段實際上沒有起作用。如果以上解釋理解的話,我們再來看看之前用mid得到的那一堆數據,經過了text統一處理後變成了什麼樣的:
這段公式我們按f9看看結果:
可以看到,所有的字符串都變成了數字,只不過這些數字都是加了引號的,不是真正的數值,而是一些文本格式的數字,如果就這樣用max去取最大值的話,是無法得到正確結果的,所以在text前面加了兩個-,這是強行對文本數值進行計算從而實現了將文本數值轉為真正數值的目的。一個符號是負數,再一個負號是減法運算,真正實現計算的是減法運算,通常這種用法叫做」負負得正「,也可以用1*text,或者0+text都行,總之是用加減乘除這幾個運算來實現轉換。
到這裡,這個公式的分析就接近了尾聲,max裡面是通過了層層運算得到的一組數值(現在是真正的數值哦)
注意,數字都沒有引號了。
max自然就得到了最大的一個數,而這個數也就是我們需要提取的數據了。