現在不想直接統計所有人,而是限定條件:
問題二:翠湖山莊有幾人成功開單了?
即:要求門派滿足“翠湖山莊”,統計D列銷售人員不重復值的個數。
可以使用以下公式:
=SUM((IF(C2:C18="翠湖山莊",TRUE,FALSE))*(MATCH(D2:D18,D2:D18,0)=ROW(D2:D18)-1))
按Ctrl+Shift+Enter鍵計算。
思路分析:
門派是否滿足“翠湖山莊”?我們通過IF函數(IF(C2:C18="翠湖山莊",TRUE,FALSE))判斷C2:C18,返回由TRUE或FALSE構成的數組,TRUE代表門派是“翠湖山莊”;
D列銷售人員是否重復?繼續使用MATCH函數(MATCH(D2:D18,D2:D18,0)=ROW(D2:D18)-1)進行判斷,返回TRUE或FALSE構成的數組,TRUE代表不重復;
然后兩個數組相乘,得到由1或0構成的新數組,其中1就代表門派滿足“翠湖山莊”,同時銷售人員還不重復;
所以計算出1的個數即可;
我們這里不直接去數1的個數,而是對這個由1或0構成的新數組應用sum函數求和,sum會把所有的1和0相加,其結果等同于1的個數。
上面的公式理解之后,我們可以簡化一下:
邏輯運算(C2:C18="翠湖山莊")可以直接代替上面的IF判斷:
=SUM((C2:C18="翠湖山莊")*(MATCH(D2:D18,D2:D18,0)=ROW(D2:D18)-1))
上面說到,我沒有直接去數1的個數,那如果用函數去數1的個數可不可以呢?比如寫成:
=((C2:C18="翠湖山莊")*(MATCH(D2:D18,D2:D18,0)=ROW(D2:D18)-1),1)
這就是用函數去數最終常量數組中1的個數,然而Excel會提示錯誤!
想想原因是為什么?答案:最外層的第一個參數不支持常量數組。
延續剛才的思路分析:
如果我們使用神級函數的話,問題會變得簡單一些
=((C2:C18="翠湖山莊")*1,(MATCH(D2:D18,D2:D18,0)=ROW(D2:D18)-1)*1)
=(--(C2:C18="翠湖山莊"),--(MATCH(D2:D18,D2:D18,0)=ROW(D2:D18)-1))
=((C2:C18="翠湖山莊")*(MATCH(D2:D18,D2:D18,0)=ROW(D2:D18)-1))
或者采用和判斷重復值的方式:
=((C2:C18="翠湖山莊")*(1/(D2:D18,D2:D18)))
=((C2:C18="翠湖山莊")*1,(1/(D2:D18,D2:D18)))
我們可以看到(C2:C18="翠湖山莊")可以抹去不是“翠湖山莊”的;
(1/(D2:D18,D2:D18))又可以處理重復值,保持最終1個人就計數為1
3、再進一步,增加更多條件試試:
問題三:翠湖山莊中有幾人成功開單賣出了瑞晶鏡?
答案是3個人,注意,如果只是限定門派是“翠湖山莊”,文創產品是“瑞晶鏡”,再對銷售人員不重復值計數,三個條件合并,通過這種公式的計算結果會是2,你知道為什么嗎?
=((C2:C18="翠湖山莊")*1,(F2:F18="瑞晶鏡")*1,(MATCH(D2:D18,D2:D18,0)=ROW(D2:D18)-1)*1)=2
=((C2:C18="翠湖山莊")*(F2:F18="瑞晶鏡")*(MATCH(D2:D18,D2:D18,0)=ROW(D2:D18)-1))=2
最后限定人員重復重復時,“瓊英”因為不是第一次出現會被判定FALSE,最終不會被計數,所以這里通過這種公式寫法是會產生誤差的。
小結:
問題二:翠湖山莊有幾人成功開單了?
問題三:翠湖山莊中有幾人成功開單賣出了瑞晶鏡?
兩個問題為什么問題二中限定門派的條件和限定人員是否重復的條件一起運算不會產生誤差?
而問題三中限定門派的條件、限定文創產品的條件和限定人員是否重復的條件一起運算會產生誤差?
關鍵在于限定門派的條件后,結果肯定會包括人員第一次賣出產品的條目;
而限定文創產品的條件后提取不重復數據公式添加日期,結果中可能不是賣出這個產品的銷售人員第一次賣出產品的條目,MATCH會認為人員重復得到FALSE,從而乘積時被抹去產生誤差。
就像上面,瓊英的確賣出瑞晶鏡,但不是瓊英第一次賣出產品(瓊英第一次賣出產品是表格第二行的青花翎),因此(MATCH(D2:D18,D2:D18,0)=ROW(D2:D18)-1)會返回FALSE,認為瓊英已經重復了。最后之所以公式結果為2,就是因為瓊英沒有被計算在內。
二、提取構建不重復值列表
經過上面一部分的分析,我們已經可以根據實際情況計算出符合條件的不重復值得個數,但僅有個數還不夠,我還想把不重復值提取出來,注意不是復制粘貼出來,而是通過公式,直接將滿足條件的不重復值提取出來,構建新的列表,那要怎么操作呢?
(一)方法一
(Index函數、Small函數、IF函數、Match函數、Row函數綜合運用)
1、先來介紹一下需要用到的函數
(1)Index函數
Index函數有兩種形式:數組形式和引用形式,我們使用的是數組形式,數組形式非常好理解。
INDEX(array, , [])
INDEX(單元格區域或數組常量,行號, [列號])
返回由行號和列號索引選中的表或數組中元素的值。
舉一個例子:
=INDEX(A1:C2,2,3) 表示的就是返回數組A1:C2中第2行第3列的元素的值,結果就是6
=INDEX(,2,3)的結果也是6
當然,可以省略行號或列號,這時執行數組運算后可以返回整列或整行。
=INDEX(,2)按下Ctrl+Shift+Enter鍵后,得到數組
(2)Small函數
Small函數可以用來返回數據集中的第 k 個最小值,使用此函數以返回在數據集內特定相對位置上的值。
SMALL(array,k)
例如=small(,6)=6.5
表示返回數組中第6個最小值,結果為6.5
當然,數組中的元素沒有排序要求,=SMALL(,6)的結果還是6.5
但是采用數組形式后,small函數可以用來排序,可以把原來的數組排序后輸出:
例如
=SMALL(,)的結果為
如果 k ≤ 0 或 k 超過數據點數,則 SMALL函數返回#NUM!錯誤值
(3)IF函數、MATCH函數、ROW函數之前都介紹過,這里就不再贅述了。
2、提前選擇輸出區域的做法:
提取所有不重復的銷售人員的姓名:
選中AH2:AH18
=INDEX($D$2:$D$18,SMALL(IF(MATCH($D$2:$D$18,$D$2:$D$18,0)=ROW($D$2:$D$18)-1,ROW($D$2:$D$18)-1),ROW($D$2:$D$18)-1))
按Ctrl+Shift+Enter執行數組運算即可
分析:
原理就是先通過match函數找到不重復人員,構成由TRUE或FALSE組成的數組,TRUE為不重復人員;
然后利用if函數,將由TRUE或FALSE組成的數組轉化為不重復人員的行號,TRUE轉換為行號,FALSE仍然會被處理為FALSE(if函數,判斷為真返回第2個參數,判斷為假,返回第3個參數,第3個參數省略時,仍返回FALSE);
然后利用small函數對上面的數組返回第1個最小值,返回第2個最小值……,實質為返回了不重復人員所在的行號,當超出后,會顯示#NUM!
最后利用index函數從D列中取值,行號就是上述small函數的返回值數組。
至于出現的ROW(…)-1這種問題,具體減幾要根據實際的區域來決定。
上面我們選中的是AH2:AH18,公式可以寫為以下兩種形式:
=INDEX($D$2:$D$18,SMALL(IF(MATCH($D$2:$D$18,$D$2:$D$18,0)=ROW($D$2:$D$18)-1,ROW($D$2:$D$18)-1),ROW($D$2:$D$18)-1)) 按Ctrl+Shift+Enter計算
或者
=INDEX($D$2:$D$18,SMALL(IF(MATCH($D$2:$D$18,$D$2:$D$18,0)=ROW($D$2:$D$18)-1,ROW($D$2:$D$18)-1),ROW()-1)) 按Ctrl+Shift+Enter計算
ROW()-1表示所選區域左上角第一個單元格的行號-1。
如果選中AH3:AH19,那么公式可以寫為:
=INDEX($D$2:$D$18,SMALL(IF(MATCH($D$2:$D$18,$D$2:$D$18,0)=ROW($D$2:$D$18)-1,ROW($D$2:$D$18)-1),ROW($D$2:$D$18)-1)) 按Ctrl+Shift+Enter計算
或
=INDEX($D$2:$D$18,SMALL(IF(MATCH($D$2:$D$18,$D$2:$D$18,0)=ROW($D$2:$D$18)-1,ROW($D$2:$D$18)-1),ROW()-2)) 按Ctrl+Shift+Enter計算
實質是修改small函數的參數,確保從1開始,返回第1個最小值、第2個最小值、第3個最小值……
最后如果再套用函數,即可隱藏掉#NUM!錯誤值
=(INDEX($D$2:$D$18,SMALL(IF(MATCH($D$2:$D$18,$D$2:$D$18,0)=ROW($D$2:$D$18)-1,ROW($D$2:$D$18)-1),ROW($D$2:$D$18)-1)),"以上為全部不重復人員")
或
=(INDEX($D$2:$D$18,SMALL(IF(MATCH($D$2:$D$18,$D$2:$D$18,0)=ROW($D$2:$D$18)-1,ROW($D$2:$D$18)-1),ROW($D$2:$D$18)-1)),"")
以上做法輸出的結果都是數組,數組是一個整體,不能單獨更改其中某一個單元格的值。
2、不提前選擇輸出區域的做法:
提取所有不重復的銷售人員的姓名:
選擇一個單元格,例如AO2,輸入公式
=INDEX($D$2:$D$18,SMALL(IF(MATCH($D$2:$D$18,$D$2:$D$18,0)=ROW($D$2:$D$18)-1,ROW($D$2:$D$18)-1),ROW()-1))
按Ctrl+Shift+Enter鍵計算
AO2中會出現一個結果“周婉悅”,然后拖動單元格右下角的填充柄,向下填充,直至出現#NUM!即可完成。
注意此時AO2到AO18的每個單元格都是獨立的,他們不是數組。
套用之后則更加直觀方便。
=(INDEX($D$2:$D$18,SMALL(IF(MATCH($D$2:$D$18,$D$2:$D$18,0)=ROW($D$2:$D$18)-1,ROW($D$2:$D$18)-1),ROW()-1)),"")
這里使用ROW()-1作為small的參數(具體減幾根據選擇的單元格的行號和1的差值確定)。
注意:使用ROW($D$2:$D$18)-1作為small參數的以下寫法不行:=INDEX($D$2:$D$18,SMALL(IF(MATCH($D$2:$D$18,$D$2:$D$18,0)=ROW($D$2:$D$18)-1,ROW($D$2:$D$18)-1),ROW($D$2:$D$18)-1))
拖動則會出錯,結果都是“周婉悅”。
(二)方法二
(函數、Small函數、IF函數、Match函數、Row函數綜合運用)
1、函數是什么?
它使用的是偏移量,以指定的引用為參照系,通過給定偏移量得到新的引用,看一下語法:
(, rows, cols, [], [width])
Rows可為正數(這意味著在起始引用的下方)或負數(這意味著在起始引用的上方)
Cols可為正數(這意味著在起始引用的右側)或負數(這意味著在起始引用的左側)
[],可選,意味著返回引用的行數
[width],可選,意味著返回引用的列數
舉個例,通過一張圖直觀地理解偏移量返回引用的意思。
=(C3,2,1) 以C3單元格為參照系,向下2行,向右1行,返回385
就是根據上面這個特性,通過函數、Small函數、IF函數、Match函數、Row函數綜合運用,也可以提取不重復值。
不過函數對數組的處理和Index函數有些差別。
2、提前選擇輸出區域的做法(該做法不可行):
提取所有不重復的銷售人員的姓名:
提前選擇區域K2:K18
=($D$1,SMALL(IF(MATCH($D$2:$D$18,$D$2:$D$18,0)=ROW($D$2:$D$18)-1,ROW($D$2:$D$18)-1),ROW()-1),)
或
=($D$1,SMALL(IF(MATCH($D$2:$D$18,$D$2:$D$18,0)=ROW($D$2:$D$18)-1,ROW($D$2:$D$18)-1),ROW($D$2:$D$18)-1),)
按下Ctrl+Shift+Enter鍵計算,會發現出錯了提取不重復數據公式添加日期,結果都是#VALUE!
公式的原理和采用Index函數時基本一致,match判斷是否重復,if把不重復的轉換成行號,small再按第1小、第2小依次輸出作為從D1單元格向下的偏移量,從D1向右到偏移量設為0,執行數組運算卻出現了#VALUE!
原因和函數本身對數組參數的處理有關系,這些不展開。
2、不提前選擇輸出區域的做法:
提取所有不重復的銷售人員的姓名:
選擇一個單元格,例如L2,輸入公式:
=($D$1,SMALL(IF(MATCH($D$2:$D$18,$D$2:$D$18,0)=ROW($D$2:$D$18)-1,ROW($D$2:$D$18)-1),ROW()-1),0)
按下Ctrl+Shift+Enter鍵計算,得到一個結果“周婉悅”,
然后拖動右下角的填充柄填充,則可以提取出不重復值!
注意:和使用index時類似,以下寫法不可行:=($D$1,SMALL(IF(MATCH($D$2:$D$18,$D$2:$D$18,0)=ROW($D$2:$D$18)-1,ROW($D$2:$D$18)-1),ROW($D$2:$D$18)-1),) 這種寫法不行!填充出來也都是一個人!
綜上,提取不重復值時,最好是采用拖動填充的方式,small函數的第二個參數最好采用row()-n的形式,n為所選單元格行號和1的差值。這樣index函數和函數均可行。
如果你使用的是Excel 2021、等最新版本,新函數提取不重復值會更簡單。