加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

Excel单列数据去重 提取唯一值列表  不重复值提取

(2015-07-03 14:30:50)
标签:

杂谈

分类: Excel

方法一:高级筛选法,适用于所有版本的excel,步骤多,稍显麻烦

  单击“数据”选项卡--》“排序和筛选”功能区--》“高级”按钮,弹出“高级筛选”对话框,如下图所示:

http://s2/middle/002nAbw2zy6TxVWj2k991&690提取唯一值列表  不重复值提取" />

  选中“将筛选结果复制到其他位置”,选择“列表区域”和“复制到”的位置,同时勾选“选择不重复的记录”复选框,如下图所示,单击“确定”就完成了重复值的筛选。

http://s13/middle/002nAbw2zy6TxVW9qi0bc&690提取唯一值列表  不重复值提取" />

  


方法二:菜单按钮,最方便直接,仅适用于07及以上版本操作如下:

  如下图,是本次操作的源数据。

http://s1/middle/002nAbw2zy6TxVWc8o0d0&690提取唯一值列表  不重复值提取" />

  单击“数据”选项卡--》“数据工具”功能区--》“删除重复项”,弹出“删除重复项”对话框,单击“确定”即可删除单列数据 重复值。如下图所示:

http://s12/middle/002nAbw2zy6TxVWw5LBdb&690提取唯一值列表  不重复值提取" />

  


方法三:数据透视表法,适用于大批量数据,但是局限在于只能通过过渡方式,对于有些想直接处理的数据不便

  依然使用上面的数据源,单击“插入”选项卡--》“表格”功能区--》“数据透视表”,出现如下图的提示框,这里我选择现有工作表 的C1单元格(大家根据需要可以选择新工作表),单击“确定”完成数据透视表的创建,如下图:

http://s2/middle/002nAbw2zy6TxVWDppDa1&690提取唯一值列表  不重复值提取" />
http://s15/middle/002nAbw2zy6TxVWGQgeae&690提取唯一值列表  不重复值提取" />

  接着,勾选“姓名”前面的复选框,“姓名”字段就出现在《行》字段的框框里,如下图:

  然后,我们对数据透视表的数据进行修饰,单击“行标签”所在的单元格,将单元格的文字改成“姓名”,然后单击数据透视表内的任意单元格,单击“数据透视表工具”--》“设计”选项卡--》“布局”功能区--》“总计”下的“对行和列禁用”按钮就完成了,如下图所示:

http://s5/middle/002nAbw2zy6TxVWvum014&690提取唯一值列表  不重复值提取" />

  


方法四:公式法


4.1.{=INDEX($A$1:$A$30,MATCH(0,COUNTIF($B$1:B1,$A$1:$A$30),0))&""}

1)当没有标题行时,Excel会提示循环引用,计算结果不对;开启“允许迭代计算”可以解决这个问题(默认情况下是关闭的)

 


2)在不开启迭代计算的模式下,添加标题行可有效规避这个问题,公式要修改为如下:

{=INDEX($A$1:$A$31,MATCH(0,COUNTIF($B$1:B1,$A$1:$A$31),0))&""}


公式解析:

 

  1. COUNTIF($B$1:B1,$A$1:$A$31),将countif函数的range和criteria换位思考,即用目标列表的值在结果列表中查找,得出个数,{0;0;0........;0;0;1}的数组,这里之所以31比目标列多一行是为了避免当目标全部为唯一值时match函数出错,即到最后一行查找0时,还有31行满足条件;

  2. MATCH(0,?,0)),在第一步的数组里查找0所在的位置,返回第一个0值,精确返回;

  3. INDEX($A$1:$A$30,?),返回序列里第几行的数据,第三参数列号默认则等于1;

  4. &“”是为了当前面的值返回第31行的空值时,让单元格不显示错误信息

4.2


{=IFERROR(INDEX(A:A,SMALL(IF(MATCH($A$2:$A$13,$A$2:$A$13,0)=ROW($1:$12),ROW($2:$13)),ROW(1:1))),"")}

D:\Useful提取唯一值列表  不重复值提取" TITLE="Excel单列数据去重 提取唯一值列表  不重复值提取" />

公式解析:

  1. MATCH($A$2:$A$13,$A$2:$A$13,0)=ROW($1:$12),{TRUE;TRUE;TRUE;TRUE;FALSE;TRUE;FALSE;TRUE;FALSE;TRUE;FALSE;TRUE},找出每个值在序列中对应出现的位置

  2. IF(MATCH($A$2:$A$13,$A$2:$A$13,0)=ROW($1:$12),ROW($2:$13)),{2;3;4;5;FALSE;7;FALSE;9;FALSE;11;FALSE;13},找出为true的值即唯一值在序列中的位置

  3. SMALL(IF(MATCH($A$2:$A$13,$A$2:$A$13,0)=ROW($1:$12),ROW($2:$13)),ROW(1:1)),{2},按顺序找到对应的行号

  4. INDEX(A:A,SMALL(IF(MATCH($A$2:$A$13,$A$2:$A$13,0)=ROW($1:$12),ROW($2:$13)),ROW(1:1))),32465,返回行号所对应的序列值

  5. IFERROR(INDEX(A:A,SMALL(IF(MATCH($A$2:$A$13,$A$2:$A$13,0)=ROW($1:$12),ROW($2:$13)),ROW(1:1))),""),容错

     

如图,在C1单元格输入如下公式,然后同时按Ctrl+Shift+Enter三个键结束,接着拖动输入公式单元格右下角的填充柄,完成此次不重复数据的筛选。

D:\Useful提取唯一值列表  不重复值提取" TITLE="Excel单列数据去重 提取唯一值列表  不重复值提取" />
D:\Useful提取唯一值列表  不重复值提取" TITLE="Excel单列数据去重 提取唯一值列表  不重复值提取" />

  接着我们对公式进行逐步的讲解,首先,MATCH($A$1:$A$10,$A$1:$A$10,)=ROW($1:$10)表示查找A1至A10单元格在引用区域$A$1:$A$10的位置是否等于当前单元格行号所在的位置,如果相等,则说明该数据在这个区域中唯一,然后通过IF(MATCH())组合函数返回这个字段的行号,否则返回2^20=1048576,接着用SMALL函数对获取的行号进行升序排序,最后通过INDEX函数查找行号所在位置的值,&“”主要是为了容错处理,试想,如果数据都取完了,就剩下1048576的位置了,然后INDEX(A:A,1048576)=0,加个&“”则返回空文本。


4.3

{=INDEX(A:A,MIN(IF(COUNTIF(C$1:C1,$A$2:$A$13),2^20,ROW($2:$13))))&""}

2^20=1048576

D:\Useful提取唯一值列表  不重复值提取" TITLE="Excel单列数据去重 提取唯一值列表  不重复值提取" />


 

 


方法五:VBA法

5.1

感觉与我常用的数组去重是一样的(我是通过两层循环判断比较,重复的清为空值,但是我的做法中,对于后面遇到的空值会跳过,提高运行效率,楼主的,在最后几个单元格会无意义的跑空……),不过,巧妙的是利用了单元格删除后,后面单元格自动上移一格的特点,在内存数组中相当于是把元素前赶了一个位置,如此,不需要另行清除空值了……

 


  1. Sub 矩形1_Click()
  2. i = Range("A65536").End(xlUp).Row
  3. For s = 1 To i
  4. For ss = i To s + 1 Step -1
  5. If Cells(ss, 1) = Cells(s, 1) Then
  6. Cells(ss, 1).Delete shift:=xlUp
  7. End If
  8. Next ss
  9. Next s
  10. End Sub
5.2函数思维,巧妙利用了单元格删除上移,只需要一个从下往上的单层循环即可,没有跑空……但是每次操作单元格,尤其在循环内部,是效率低的原因吧……

  1. Sub 矩形2_Click()
  2. i = Range("A65536").End(xlUp).Row
  3. For s = i To 1 Step -1
  4. If Application.WorksheetFunction.CountIf(Range(Cells(1, 1), Cells(s, 1)), Cells(s, 1)) > 1 Then
  5. Cells(s, 1).Delete shift:=xlUp
  6. End If
  7. Next
  8. End Sub
5.3字典去重

  1. Sub 矩形3_Click()
  2. i = Range("A65536").End(xlUp).Row
  3. Dim dic As Object, ii&, arr, ra
  4. Set dic = CreateObject("Scripting.Dictionary")
  5. arr = Range("a1:a" & i)
  6. For ii = 1 To UBound(arr)
  7. ra = dic(arr(ii, 1))
  8. Next
  9. Range("a:a").ClearContents
  10. Range("a1").Resize(dic.Count, 1) = Application.Transpose(dic.Keys)
  11. End Sub


  1. Sub 矩形3_Click()
  2. i = Range("A65536").End(xlUp).Row
  3. Dim dic As Object, ii&, arr
  4. Set dic = CreateObject("Scripting.Dictionary")
  5. arr = Range("a1:a" & i)
  6. For ii = 1 To UBound(arr)
  7. dic(arr(ii, 1)) = ii
  8. Next
  9. Range("a:a").ClearContents
  10. Range("a1").Resize(dic.Count, 1) = Application.Transpose(dic.Keys)
  11. End Sub
5.4

  1. Sub 矩形4_Click()
  2. Columns(1).RemoveDuplicates 1
  3. End Sub
咋一看,吓一跳,如此简洁,赶紧F1,才稍稍明白了些真相:
“Excel 开发人员参考 
Range.RemoveDuplicates 方法 
从值区域中删除重复的值。
版本信息
已添加版本:  Excel 2007

语法

表达式.RemoveDuplicates(Columns, Header)

表达式   一个代表 Range 对象的变量。

参数

名称 必选/可选 数据类型 说明 
Columns 可选 Variant 包含重复信息的列的索引数组。如果没有传递任何内容,则假定所有列都包含重复信息。 
Header 可选 XlYesNoGuess 指定第一行是否包含标题信息。xlNo 是默认值;如果希望 Excel 确定标题,则指定 xlGuess。 


5.5 别整那么多花里胡哨的方法……都不实用。

VBA去重复只有两种方法:
① 整数数值型数据,可以直接使用数组下标去重复

② 通用方法:字典去重复

其它的方法都没啥意思。给你整理个数组循环去重复排序的自定义过程吧,

以后凡是VBA内的一维数组排序,都可以直接拿去用:

  1. Sub RecSortTest()
  2. arr = Array(5, 4, 2, 1, 5, 8, 7, 2, 7, 9, 3, 6, "22", "23", "221", 22, 23, 221, "a", "z", "c") '测试数组
  3. ' arr = WorksheetFunction.Transpose([a1].CurrentRegion) '如果工作表区域要转为一维数组
  4. trr = RecSort(arr) '仅排序(按默认格式)
  5. trr1 = RecSort(arr, 1) '去重复排序(按默认格式)
  6. trr2 = RecSort(arr, 1, 1) '去重复排序 数值不按文本格式
  7. Stop
  8. End Sub
  9. Function RecSort(arr, Optional z& = 0, Optional c& = 0) 'A-Z 升序排序(/可去重复)的自定义过程
  10. Dim i&, j&, k&, l&, n&, u&, t
  11. l = LBound(arr): n = l: u = UBound(arr)
  12. ReDim trr(l To u)
  13. For i = l To u
  14. t = arr(i): If c Then If IsNumeric(t) Then t = Val(t) 'c=1 按数值/c=0 按源数据格式
  15. For j = l To n
  16. If z Then If trr(j) = t Then n = n - 1: Exit For 'z=1 去重复/z=0 保留
  17. If trr(j) > t Then '检查直到比当前值t大位置时停止
  18. For k = n To j + 1 Step -1 '倒序向后移动所有比当前值大的已排序内容 以便腾出空位
  19. trr(k) = trr(k - 1)
  20. Next
  21. trr(k) = t '空位写入t
  22. Exit For
  23. End If
  24. Next
  25. If j > n Then trr(j - 1) = t '如果都没有比当前值大 则在最后新的位置写入t
  26. n = n + 1
  27. Next
  28. If z Then ReDim Preserve trr(l To n - 1)
  29. RecSort = trr
  30. End Function
具体算法过程呢,你慢慢研究吧。

这个代码是用了比较插入排序算法,但已由我做了改进。


如果需要降序排序,把比较部分语句中>改成<即可。
If trr(j) > t Then '检查直到比当前值t大位置时停止 结果为A-Z升序排序
If trr(j) < t Then '检查直到比当前值t小位置时停止 结果为Z-A降序排序



方法六:SQL法

  单击“数据”选项卡--》"获取外部数据"功能区--》现有连接,打开“现有连接”对话框,单击左下角的“浏览更多”,然后找到你操作数据源所在的工作簿的路径,单击“打开”,出现“选择表格”对话框,保持默认状态,单击“确定”按钮,如下图所示:

  接着我们选择“表”单选按钮,这里我选择现有工作表的C1单元格(大家根据需要可以选择新工作表),单击“属性”按钮,打开"连接属性"对话框,找到“定义"选项卡,然后清除”命令文本“ 的文本,输入以下语句:SELECT DISTINCT * FROM [Sheet1$](这里Sheet1是我的源数据名称,你要输入自己工作表的名称哦,还有[]和$都不能少哦,若单元格区域还有其他字段或者数据不在行首,还要输入你的数据源区域哦,比如[Sheet1$].A4:A12),如下图所示:

http://s5/middle/002nAbw2zy6TxVXSYp6a4&690提取唯一值列表  不重复值提取" />
-1提取唯一值列表  不重复值提取" />

  





0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有