ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 Excel Home精品图文教程库
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
300集Office 2010微视频教程 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
楼主: iamtheleader

[分享] VBA去重复的几种方法

  [复制链接]

TA的精华主题

TA的得分主题

发表于 2014-12-12 18:44 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
本帖已被收录到知识树中,索引项:去重复
谢谢,学习

TA的精华主题

TA的得分主题

发表于 2014-12-12 22:15 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
以下是楼主的方法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
复制代码
感觉与我常用的数组去重是一样的(我是通过两层循环判断比较,重复的清为空值,但是我的做法中,对于后面遇到的空值会跳过,提高运行效率,楼主的,在最后几个单元格会无意义的跑空……),不过,巧妙的是利用了单元格删除后,后面单元格自动上移一格的特点,在内存数组中相当于是把元素前赶了一个位置,如此,不需要另行清除空值了……

TA的精华主题

TA的得分主题

发表于 2014-12-12 22:17 | 显示全部楼层
楼主方法二:
  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
复制代码
函数思维,巧妙利用了单元格删除上移,只需要一个从下往上的单层循环即可,没有跑空……但是每次操作单元格,尤其在循环内部,是效率低的原因吧……

TA的精华主题

TA的得分主题

发表于 2014-12-12 22:20 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
楼主方法三:
  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
复制代码
字典去重,我不习惯这句:ra = dic(arr(ii, 1)),便改成了下面习惯的:
  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
复制代码

TA的精华主题

TA的得分主题

发表于 2014-12-12 22:22 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
楼主方法四:
  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。

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2014-12-12 22:38 | 显示全部楼层
aoe1981 发表于 2014-12-12 22:20
楼主方法三:字典去重,我不习惯这句:ra = dic(arr(ii, 1)),便改成了下面习惯的:

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

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

② 通用方法:字典去重复

其它的方法都没啥意思。

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2014-12-12 22:57 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
香川群子 发表于 2014-12-12 22:38
别整那么多花里胡哨的方法……都不实用。

VBA去重复只有两种方法:

如果考虑普遍性的话,看来只剩下字典去重一种方法了……

我习惯整的是双层循环比对,重复值置空,后次判断跳过空值不再比对的方法……

呵呵……

确实,您的比如:递归组合、经典数组洗牌法等代码都极为经典,在解决很多问题时,都成了我的不二选择……

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2014-12-13 09:47 | 显示全部楼层
本帖最后由 香川群子 于 2014-12-13 09:51 编辑
aoe1981 发表于 2014-12-12 22:57
如果考虑普遍性的话,看来只剩下字典去重一种方法了……

我习惯整的是双层循环比对,重复值置空,后次 ...

给你整理个数组循环去重复排序的自定义过程吧,

以后凡是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.    
  14.     For i = l To u
  15.         t = arr(i): If c Then If IsNumeric(t) Then t = Val(t) 'c=1 按数值/c=0 按源数据格式
  16.         For j = l To n
  17.             If z Then If trr(j) = t Then n = n - 1: Exit For 'z=1 去重复/z=0 保留
  18.             If trr(j) > t Then '检查直到比当前值t大位置时停止
  19.                 For k = n To j + 1 Step -1 '倒序向后移动所有比当前值大的已排序内容 以便腾出空位
  20.                     trr(k) = trr(k - 1)
  21.                 Next
  22.                 trr(k) = t '空位写入t
  23.                 Exit For
  24.             End If
  25.         Next
  26.         If j > n Then trr(j - 1) = t '如果都没有比当前值大 则在最后新的位置写入t
  27.         n = n + 1
  28.     Next
  29.     If z Then ReDim Preserve trr(l To n - 1)
  30.     RecSort = trr
  31. End Function
复制代码
具体算法过程呢,你慢慢研究吧。

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


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

评分

4

查看全部评分

TA的精华主题

TA的得分主题

发表于 2015-9-14 23:24 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
字典加数组

TA的精华主题

TA的得分主题

发表于 2015-11-4 11:23 | 显示全部楼层
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-6-10 08:59 , Processed in 0.033869 second(s), 8 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表