ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 27308|回复: 52

[分享]字典+数组的多列数据不重复值查询.应用实例

[复制链接]

TA的精华主题

TA的得分主题

发表于 2007-11-21 17:29 | 显示全部楼层 |阅读模式

本例的靓点:字典+数组,两种不同的处理方式;
较好地表达了,字典,数组,的应用方法.
仔细体会一下,字典+数组,的不同运用.

'方法一,是Long_III版的(有注释).

Private Sub CommandButton1_Click()
Dim ds
Dim i&, irow&, m&, m1&, s&
Dim arr, Xarr(), Yarr()
Dim aa As Double
aa = Timer
Range("f:i").ClearContents    '清除f:i列的内容
Application.ScreenUpdating = False
Set ds = CreateObject("scripting.dictionary")
m = 1
For j = 1 To 4    '在A~D列里做一个循环
irow = Cells(65536, j).End(xlUp).Row
arr = Range(Cells(1, j), Cells(irow, j))    '用数组取单元格的值
On Error Resume Next
For i = 1 To irow
If arr(i, 1) <> "" Then
ds.Add arr(i, 1), m
If Err.Number = 0 Then
ReDim Preserve Xarr(1 To 2, 1 To m)
Xarr(1, m) = arr(i, 1)
Xarr(2, m) = Choose(j, "A", "B", "C", "D")
m = m + 1
Else
s = ds(arr(i, 1))
Xarr(2, s) = Xarr(2, s) & Choose(j, "A", "B", "C", "D")    '出现重复的时候就统计它的列数
End If
Err.Clear    '清除错误数字
End If
Next
Next
On Error GoTo 0    '重新恢复错误捕捉功能,以后出现错误还是会报错
'重新统计各种出现情况的次数
ds.RemoveAll    '清除字典里的所有数据
m1 = 1
On Error Resume Next    '此过程与上一个过程极其相似
For i = 1 To m - 1
ds.Add Xarr(2, i), m1
If Err.Number = 0 Then
ReDim Preserve Yarr(1 To 2, 1 To m1)
Yarr(1, m1) = Xarr(2, i)
Yarr(2, m1) = 1
m1 = m1 + 1
Else
s = ds(Xarr(2, i))
Yarr(2, s) = Yarr(2, s) + 1    '次数就是加1的效果
End If
Err.Clear
Next
On Error GoTo 0
[f1].Resize(m - 1, 2) = Application.WorksheetFunction.Transpose(Xarr)    '计算各个数在ABCD列中的出现情况
[h1].Resize(m1 - 1, 2) = Application.WorksheetFunction.Transpose(Yarr)    '计算各种出现情况的次数
Application.ScreenUpdating = True
MsgBox "Total:=" & Format(Timer - aa, "0.00") & "s"
End Sub

'方法二,是本人所写.代码相对容易理解.

Sub tiger744990()
Dim dic As Object, i&, n&, arr, Xarr, str As String, j As Byte
Dim aa As Double
aa = Timer
Set dic = CreateObject("Scripting.Dictionary")
Application.ScreenUpdating = False
With dic
For j = 1 To 4
With Sheet1
n = .Cells(65536, j).End(xlUp).Row: arr = .Range(.Cells(1, j), .Cells(n, j))
End With
For i = 1 To n
If Len(arr(i, 1)) <> 0 Then
str = Choose(j, "A", "B", "C", "D")
If Not .exists(arr(i, 1)) Then
.Add arr(i, 1), str
Else
.Item(arr(i, 1)) = .Item(arr(i, 1)) & str
End If
End If
Next
Next
Xarr = .Items
Sheet1.[f:i].ClearContents
Sheet1.[f1].Resize(.Count, 1) = WorksheetFunction.Transpose(.keys)
Sheet1.[g1].Resize(.Count, 1) = WorksheetFunction.Transpose(.Items)
.RemoveAll
For i = 0 To UBound(Xarr)
If Not .exists(Xarr(i)) Then .Add Xarr(i), 1 Else .Item(Xarr(i)) = .Item(Xarr(i)) + 1
Next
Sheet1.[h1].Resize(.Count, 1) = WorksheetFunction.Transpose(.keys)
Sheet1.[i1].Resize(.Count, 1) = WorksheetFunction.Transpose(.Items)
End With
Application.ScreenUpdating = True
Set dic = Nothing
MsgBox "Total:=" & Format(Timer - aa, "0.00") & "s"
End Sub


ulXkLYST.rar (26.64 KB, 下载次数: 1743)
[此贴子已经被作者于2007-11-22 13:08:28编辑过]

sDOOgnqb.rar

27.17 KB, 下载次数: 1719

[分享]字典+数组.应用实例(一)

TA的精华主题

TA的得分主题

 楼主| 发表于 2007-11-21 18:24 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助

TA的精华主题

TA的得分主题

 楼主| 发表于 2007-11-21 18:38 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册

再来一个:

Sub tiger744990()
Dim dic As Object, arr, arr1, i%, j%, n%
Dim aa As Double
aa = Timer
Application.ScreenUpdating = False
Set dic = CreateObject("Scripting.Dictionary")
n = Cells(65536, 1).End(xlUp).Row
arr = [a1].CurrentRegion.Value
For i = 2 To n
If Not dic.exists(arr(i, 2) & arr(i, 3)) Then dic.Add arr(i, 2) & arr(i, 3), ""
Next
arr1 = dic.keys
ReDim temp(0 To dic.Count - 1, 1 To 7)
For j = 0 To dic.Count - 1
For i = 2 To n
If arr(i, 2) & arr(i, 3) = arr1(j) Then
temp(j, 1) = arr(i, 1)
temp(j, 2) = arr(i, 2)
temp(j, 3) = arr(i, 3)
temp(j, 4) = arr(i, 4)
temp(j, 5) = temp(j, 5) + arr(i, 5)
temp(j, 6) = temp(j, 6) + arr(i, 6)
temp(j, 7) = temp(j, 7) + arr(i, 7)
End If
Next
Next
Sheet2.[a1:g1] = Sheet1.[a1:g1].Value
Sheet2.[a2].Resize(dic.Count, 7) = temp
Set dic = Nothing
Application.ScreenUpdating = True
MsgBox "Total:= " & Format(Timer - aa, "0.00") & "s"
End Sub

TA的精华主题

TA的得分主题

发表于 2007-11-21 19:31 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
thanks

TA的精华主题

TA的得分主题

发表于 2007-11-21 19:45 | 显示全部楼层
应该给标题加一个清晰的说明:字典+数组的多列数据不重复值查询.应用实例。否则就给人看的一头雾水,不知道该示例到底是做什么的!

TA的精华主题

TA的得分主题

 楼主| 发表于 2007-11-21 19:52 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
是的,修改一下,标题.谢谢.

TA的精华主题

TA的得分主题

发表于 2007-11-21 20:12 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助

收藏學習

謝謝樓主提供分享 !!!

[em23][em23][em23]

[em24][em24][em24]

[em27][em27][em27]

TA的精华主题

TA的得分主题

发表于 2007-11-21 22:43 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册

我的机器上试都是0.08秒

不过还是要谢谢你们

[此贴子已经被作者于2007-11-21 22:45:25编辑过]

TA的精华主题

TA的得分主题

发表于 2007-11-21 23:28 | 显示全部楼层

这样写简单些:

Sub tiger744990()
  Dim dic As Object, rng, i%, k$
  Dim aa!
  aa = Timer
  Set dic = CreateObject("Scripting.Dictionary")
  rng = Range([a2], [g2].End(xlDown))
  For i = 1 To UBound(rng)
    k = rng(i, 2) & rng(i, 3)
    If Not dic.exists(k) Then
      dic(k) = Array(rng(i, 1), rng(i, 2), rng(i, 3), rng(i, 4), rng(i, 5), rng(i, 6), rng(i, 7))
    Else
      rng(i, 5) = rng(i, 5) + dic(k)(4): rng(i, 6) = rng(i, 6) + dic(k)(5): rng(i, 7) = rng(i, 7) + dic(k)(6)
      dic(k) = Array(rng(i, 1), rng(i, 2), rng(i, 3), rng(i, 4), rng(i, 5), rng(i, 6), rng(i, 7))
    End If
  Next
  Sheet2.[a1:g1] = Sheet1.[a1:g1].Value
  Sheet2.[a2].Resize(dic.Count, 7) = Application.Transpose(Application.Transpose(dic.items))
  Set dic = Nothing
  MsgBox "Total:= " & Format(Timer - aa, "0.000") & "s"
End Sub

TA的精华主题

TA的得分主题

发表于 2007-11-21 23:35 | 显示全部楼层

针对楼主的那个再来一个

大致看了一下,典和数组之间是有矛盾的.可以这么说后面的数组根本就没有用上字典.即没有省时反而费时.

不信你算一下3W条记录的,1W不重复的,你这种方法就和死机差不多.

If Not dic.exists(arr(i, 2) & arr(i, 3)) Then

x=x+1

 dic.Add arr(i, 2) & arr(i, 3),x

end if

X是什么,是位置,可直接查找位置而不是用For j = 0 To dic.Count - 1

这样才能体现字典意思,代码我就不帮你改了,慢慢理解吧,这样对你有好处

当然除了字典之外还有好方法,就是先排序之后上下比较再求和,速度不一定比字典慢

[此贴子已经被作者于2007-11-21 23:38:19编辑过]
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

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

GMT+8, 2024-12-23 11:00 , Processed in 0.037523 second(s), 10 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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