Excel精英培训网

 找回密码
 注册
数据透视表40+个常用小技巧,让你一次学会!
12
返回列表 发新帖
楼主: 张雄友

[已解决]提取重复中的不重复数据

[复制链接]
发表于 2014-5-4 16:20 | 显示全部楼层
写完了,好长好长 {:281:} 晚上师傅帮我讲另一种思路

  1. Sub 查询重复中的第一条记录()
  2.     Dim dic As Object, Arr(), Brr(), MyR&, s&, MyS$, T
  3.     T = Timer
  4.     Sheets("重复").Range("b2:d10000").ClearContents
  5.     Set dic = CreateObject("scripting.dictionary")
  6.     Arr = Worksheets("基本信息").UsedRange.Value
  7.     For MyR = 1 To UBound(Arr)
  8.         If Not dic.Exists(Arr(MyR, 3)) Then
  9.             dic.Add Arr(MyR, 3), ""
  10.         Else
  11.             k = k + 1
  12.             If k = 1 Then
  13.                 s = s + 1
  14.                 ReDim Preserve Brr(1 To s)
  15.                 Brr(s) = Arr(MyR, 3)
  16.             End If
  17.         End If
  18.         k = 0
  19.     Next MyR
  20.     Set dic = Nothing
  21.     Set dic = CreateObject("scripting.dictionary")
  22.     For MyR = 1 To UBound(Brr)
  23.         dic(Brr(MyR)) = dic(Brr(MyR)) + 1
  24.     Next MyR
  25.     Sheets("重复").Range("D2").Resize(dic.Count, 1) = Application.Transpose(dic.Keys)
  26.     For MyR = 2 To UBound(Arr)
  27.         MyS = Arr(MyR, 1) & vbTab & Arr(MyR, 2)
  28.         dic(Arr(MyR, 3)) = MyS
  29.     Next MyR
  30.     With Sheets("重复")
  31.         Brr = .Range("b1:d" & Cells(Rows.Count, 4).End(xlUp).Row).Value
  32.         For MyR = 2 To UBound(Brr)
  33.             Brr(MyR, 1) = Split(dic.Item(Brr(MyR, 3)), vbTab)(0)
  34.             Brr(MyR, 2) = Split(dic.Item(Brr(MyR, 3)), vbTab)(1)
  35.         Next MyR
  36.         .Range("B1").Resize(UBound(Brr), UBound(Brr, 2)) = Brr
  37.     End With
  38.     MsgBox "查询完毕,用时:" & Format(Timer - T, "0.00秒")
  39. End Sub
复制代码

评分

参与人数 1 +3 收起 理由
张雄友 + 3 感谢支持!

查看全部评分

回复

使用道具 举报

发表于 2014-5-6 11:03 | 显示全部楼层
不要嫌我啰嗦啊嘿嘿,这个题我也学到了很多,给你看下另外两种方法,船长那个思路的速度最快
方法二思路:先排序,再循环判断

  1. Sub 查询重复中的不重复记录2()
  2.     Dim Arr(), Brr(), MyR&, MyC&, k&, s&, T
  3.     T = Timer
  4.     Application.ScreenUpdating = False
  5.     Arr = Sheets("基本信息").UsedRange.Value
  6.     Sheets("重复").Columns("G").NumberFormatLocal = "@"
  7.     Sheets("重复").Range("E1").Resize(UBound(Arr), UBound(Arr, 2)) = Arr
  8.     ReDim Brr(1 To UBound(Arr), 1 To 3)
  9.     Worksheets("重复").Select
  10.     With Worksheets("重复").Sort
  11.         .SortFields.Clear
  12.         .SortFields.Add Key:=Range("F1"), Order:=xlDescending
  13.         .SetRange Range("E1:G" & Cells(Rows.Count, 7).End(xlUp).Row)
  14.         .Header = xlYes
  15.         .Apply
  16.     End With
  17.     Arr = Sheets("重复").Range("e1:g" & Cells(Rows.Count, 7).End(xlUp).Row).Value
  18.     For MyR = 2 To UBound(Arr)
  19.         If Arr(MyR, 3) = Arr(MyR - 1, 3) Then
  20.             k = k + 1
  21.             If k = 1 Then
  22.                 s = s + 1
  23.                 For MyC = 1 To 3
  24.                     Brr(s, MyC) = Arr(MyR - 1, MyC)
  25.                 Next MyC
  26.             End If
  27.         Else
  28.             k = 0
  29.         End If
  30.     Next MyR
  31.     With Sheets("重复")
  32.         .Columns("d").NumberFormatLocal = "@"
  33.         .Range("B2").Resize(s, 3) = Brr
  34.         .Columns("E:G").Clear
  35.     End With
  36.     MsgBox "用时:" & Format(Timer - T, "0.00秒")
  37.     Application.ScreenUpdating = True
  38. End Sub
复制代码
方法三思路:双字典单循环(船长提供)

  1. Sub 提取重复数据中的不重复记录3()
  2.     Dim dic1 As Object, dic2 As Object, Arr(), Brr(), MyR&, MyC%, k&, T
  3.     T = Timer
  4.     Application.ScreenUpdating = False
  5.     Set dic1 = CreateObject("scripting.dictionary")
  6.     Set dic2 = CreateObject("scripting.dictionary")
  7.     Arr = Sheets("基本信息").Range("b1:d" & Sheets("基本信息").Cells(Rows.Count, 4).End(xlUp).Row).Value
  8.     ReDim Brr(1 To UBound(Arr), 1 To 3)
  9.     For MyR = 1 To UBound(Arr)
  10.         If dic1.Exists(Arr(MyR, 3)) Then
  11.             If Not dic2.Exists(Arr(MyR, 3)) Then '重复中出现第一次
  12.                 k = k + 1
  13.                 For MyC = 1 To 3
  14.                     Brr(k, MyC) = Arr(MyR, MyC)
  15.                 Next MyC
  16.                 dic2(Arr(MyR, 3)) = ""
  17.             End If
  18.         Else
  19.             dic1(Arr(MyR, 3)) = ""
  20.         End If
  21.     Next MyR
  22.     Sheets("重复").Range("b2").Resize(k, 3) = Brr
  23.     Application.ScreenUpdating = True
  24.     MsgBox "用时:" & Format(Timer - T, "0.00秒")
  25. End Sub
复制代码

提取重复中的不重复数据(改).zip

714.85 KB, 下载次数: 17

评分

参与人数 1 +3 收起 理由
张雄友 + 3 很给力!

查看全部评分

回复

使用道具 举报

 楼主| 发表于 2014-5-6 12:52 | 显示全部楼层
sayloveyou2010 发表于 2014-5-6 11:03
不要嫌我啰嗦啊嘿嘿,这个题我也学到了很多,给你看下另外两种方法,船长那个思路的速度最快
方法二思路: ...

怎么可能,谢谢你才对。
回复

使用道具 举报

发表于 2014-5-6 13:52 | 显示全部楼层
{:1712:}
回复

使用道具 举报

发表于 2014-5-6 15:42 | 显示全部楼层
算法最好、速度最快的代码在这里:
  1. Sub test4() 'kagawa
  2.     Dim ar, br, cr, dic, i&, j&, m&, n&, r&, t$, tms#
  3.    
  4.     tms = Timer
  5.     ar = Sheets(1).[b1].CurrentRegion
  6.     m = UBound(ar)
  7.     n = UBound(ar, 2)
  8.     ReDim br(m, 1 To n)
  9.     For j = 1 To n
  10.         br(0, j) = ar(1, j)
  11.     Next
  12.    
  13.     Set dic = CreateObject("Scripting.Dictionary")
  14.     For i = 2 To m
  15.         t = ar(i, n)
  16.         r = dic(t)
  17.         If r Then
  18.             If r > 1 Then
  19.                 dic(t) = 1
  20.                 k = k + 1
  21.                 For j = 1 To n
  22.                     br(k, j) = ar(r, j)
  23.                 Next
  24.             End If
  25.         Else
  26.             dic(t) = i
  27.         End If
  28.     Next
  29.     Exit Sub
  30.     Application.StatusBar = Format(Timer - tms, "0.000s ") & k & "/" & dic.Count
  31.    
  32.     Sheets(2).Activate
  33.     [b1].CurrentRegion = ""
  34.     [d1].Resize(k + 1).NumberFormat = "@"
  35.     [b1].Resize(k + 1, n) = br
  36.     MsgBox Format(Timer - tms, "0.000s ") & k & "/" & dic.Count
  37. End Sub
复制代码
仅比较计算部分,速度比2楼和船长的代码要快1倍。

但由于输出耗时较多,整个代码的耗时差异不大。


另,生成5万个重复模拟数据的代码如下:
  1. Sub test()
  2.     m = 50000
  3.     ReDim a(1 To m, 1 To 3)
  4.     Do
  5.         t1 = ChrW(Int(Rnd * 1000) + 20000) & ChrW(Int(Rnd * 5000) + 20000) & ChrW(Int(Rnd * 5000) + 20000)
  6.         t2 = Format(Int(Rnd * 1000000), "000000") & Format(Date - 20000 + Int(Rnd * 20000), "yyyymmdd") & Format(Int(Rnd * 10000), "0000")
  7.         r = Int(Rnd * 1000)
  8.         For i = 100 To IIf(r < 100, 100, r)
  9.             k = k + 1
  10.             a(k, 1) = Int(Rnd * 500000)
  11.             a(k, 2) = t1
  12.             a(k, 3) = t2
  13.             If k = m Then Exit Do
  14.         Next
  15.     Loop
  16.     [b2].Resize(m, 3) = a
  17.     [b2].Resize(m, 3).Sort [b2], 1, , , 2
  18. End Sub
复制代码

评分

参与人数 1 +3 收起 理由
张雄友 + 3 很给力!

查看全部评分

回复

使用道具 举报

发表于 2014-5-6 21:55 | 显示全部楼层
张熊友你的词汇也太贫乏了……只会“很给力”三个字么?



回复

使用道具 举报

 楼主| 发表于 2014-5-6 22:01 | 显示全部楼层
香川群子 发表于 2014-5-6 21:55
张熊友你的词汇也太贫乏了……只会“很给力”三个字么?

不好意思,我语文从来不及格的,只有这水平,但是你就不同了,以你的知识完全可以进中科院了。
回复

使用道具 举报

发表于 2014-5-6 22:51 | 显示全部楼层
VBA不懂学习中
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|Excel精英培训 ( 豫ICP备11015029号 )

GMT+8, 2024-5-5 19:23 , Processed in 0.284110 second(s), 10 queries , Gzip On, Yac On.

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

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