ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

[求助] 两列数据互相比对,求优化

[复制链接]

TA的精华主题

TA的得分主题

发表于 2023-6-3 01:31 | 显示全部楼层 |阅读模式
本帖最后由 ·遁去的一· 于 2023-6-3 13:33 编辑

两列数据互相比对,求优化 sub 双向2()的代码,提高速度,本机测试100万记录,100万KEY的情况下,要4分钟跑
  1. Sub 双向2()
  2. Dim s1, s2, jg1, jg2, jgwz1, jgwz2 '定义比对数据源的位置列变量

  3. Dim s1arr, s2arr, jg1arr, jg2arr, jgwz1arr, jgwz2arr '定义数据源数组和各个行列的变量

  4. Dim row1, row2 '定义总行数

  5. Dim i, k, js, pr, sk, sk1, j '定义循环计数

  6. Dim dic1(1 To 10) As Object

  7. Dim t, key, Key_Is_Exist
  8. t = Timer


  9. Application.ScreenUpdating = False


  10. s1 = [b1]
  11. s2 = [b2]
  12. jg1 = [d1]
  13. jg2 = [d2]
  14. jgwz1 = [f1]
  15. jgwz2 = [f2]

  16. row1 = Range(s1 & Rows.count).End(xlUp).Row
  17. row2 = Range(s2 & Rows.count).End(xlUp).Row


  18. '清理数据显示区

  19. Range(jgwz1 & ":" & jgwz1).Clear

  20. Range(jgwz2 & ":" & jgwz2).Clear


  21. 'For i = 2 To 1000001
  22.   ' Range(s1 & i) = i
  23. 'Next

  24. '将数据源,结果位置分别赋值

  25. '数据源

  26. s1arr = Range(s1 & "2:" & s1 & row1)

  27. s2arr = Range(s2 & "2:" & s2 & row2)


  28. '提取数据
  29. jg1arr = Range(jg1 & "2:" & jg1 & row1)
  30. jg2arr = Range(jg2 & "2:" & jg2 & row2)

  31. '结果位置
  32. jgwz1arr = Range(jgwz1 & "2:" & jgwz1 & row1)

  33. jgwz2arr = Range(jgwz2 & "2:" & jgwz2 & row2)



  34. '数据2在数据1中有几个相同结果

  35. For i = 1 To 10 '生成10个字典
  36.    Set dic1(i) = CreateObject("scripting.dictionary")
  37. Next

  38. sk1 = 0
  39. For i = 1 To UBound(s1arr)  '循环数据1生成字典
  40.     key = s1arr(i, 1)
  41.     k = sk1 \ 100000 + 1  '计算字典号
  42.     Key_Is_Exist = False
  43.    
  44.     For j = 1 To 10 '在原字典中查找是不是已有
  45.         If dic1(j).exists(key) Then
  46.             Key_Is_Exist = True
  47.             Exit For
  48.         End If
  49.     Next

  50.         
  51.      If Key_Is_Exist Then
  52.         dic1(k)(s1arr(i, 1)) = dic1(k)(s1arr(i, 1)) & "," & jg1arr(i, 1) & "$" & jg1 & "$" & i + 1
  53.         Else
  54.         dic1(k).Add s1arr(i, 1), jg1arr(i, 1) & "$" & jg1 & "$" & i + 1
  55.         sk1 = sk1 + 1
  56.      End If

  57. Next

  58. For k = 1 To 10
  59.     'Debug.Print dic1(k).count
  60. If dic1(k).count > 0 Then
  61. js = dic1(k).keys

  62. pr = dic1(k).items

  63. sk = UBound(Split(pr(0), ",")) + 1

  64. For i = 0 To UBound(js)

  65. If dic1(k).exists(js(i)) Then
  66.    sk = UBound(Split(pr(i), ",")) + 1
  67.    dic1(k)(js(i)) = "(" & sk & ")" & dic1(k)(js(i))
  68. End If

  69. Next

  70. End If

  71. Next

  72. pr = dic1(k - 1).items

  73. '数据2在数据1中比较,提取结果到jgwz2


  74. For i = 1 To UBound(s2arr)
  75.     key = s2arr(i, 1)
  76.    
  77.     For j = 1 To 10
  78.         If dic1(j).exists(key) Then
  79.             jgwz2arr(i, 1) = dic1(j)(key)
  80.             Exit For
  81.         End If
  82.     Next
  83.      
  84. Next

  85. Range(jgwz2 & "1").Value = s2 & "比较" & s1 & "返回" & jg1
  86. Range(jgwz2 & "2").Resize(UBound(jgwz2arr), 1) = jgwz2arr
  87.   
  88. For k = 1 To 10
  89. Set dic1(k) = Nothing
  90. Next
  91. Set jgwz2arr = Nothing



  92. '数据1在数据2中有几个相同结果

  93. For i = 1 To 10
  94.    Set dic1(i) = CreateObject("scripting.dictionary")
  95. Next


  96. sk1 = 0
  97. For i = 1 To UBound(s2arr)  '循环数据2生成字典
  98.     key = s2arr(i, 1)
  99.     k = sk1 \ 100000 + 1
  100.     Key_Is_Exist = False
  101.    
  102.     For j = 1 To 10
  103.         If dic1(j).exists(key) Then
  104.             Key_Is_Exist = True
  105.             Exit For
  106.         End If
  107.     Next

  108.         
  109.      If Key_Is_Exist Then
  110.         dic1(k)(s2arr(i, 1)) = dic1(k)(s2arr(i, 1)) & "," & jg2arr(i, 1) & "$" & jg2 & "$" & i + 1
  111.         Else
  112.         dic1(k).Add s2arr(i, 1), jg2arr(i, 1) & "$" & jg2 & "$" & i + 1
  113.         sk1 = sk1 + 1
  114.      End If

  115. Next

  116. For k = 1 To 10
  117.    ' Debug.Print dic1(k).count
  118. If dic1(k).count > 0 Then
  119. js = dic1(k).keys

  120. pr = dic1(k).items

  121. sk = UBound(Split(pr(0), ",")) + 1

  122. For i = 0 To UBound(js)

  123. If dic1(k).exists(js(i)) Then
  124.    sk = UBound(Split(pr(i), ",")) + 1
  125.    dic1(k)(js(i)) = "(" & sk & ")" & dic1(k)(js(i))
  126. End If
  127. Next
  128. End If


  129. Next

  130. pr = dic1(k - 1).items

  131. '数据1在数据2中比较,提取结果到jgwz1


  132. For i = 1 To UBound(s1arr)
  133.     key = s1arr(i, 1)
  134.    
  135.     For j = 1 To 10
  136.         If dic1(j).exists(key) Then
  137.             jgwz1arr(i, 1) = dic1(j)(key)
  138.             Exit For
  139.         End If
  140.     Next
  141.      
  142. Next

  143. Range(jgwz1 & "1").Value = s1 & "比较" & s2 & "返回" & jg2
  144. Range(jgwz1 & "2").Resize(UBound(jgwz1arr), 1) = jgwz1arr
  145. MsgBox "核对完成,共用时" & Timer - t & "秒" & "共核对" & row1 - 1 & "/" & row2 - 1 & "条记录"
  146. Application.ScreenUpdating = True

  147. For k = 1 To 10
  148. Set dic1(k) = Nothing
  149. Next
  150. Set jgwz1arr = Nothing


  151. End Sub


复制代码

完一次,追问一个问题,能否把2次互比,合成一次比对,达到相同效果,主要是互相提取指定的列数据,比重是可以一次完成的

万能对比数组字典.7z

39.63 KB, 下载次数: 19

TA的精华主题

TA的得分主题

发表于 2023-6-3 09:49 | 显示全部楼层

  1. Sub CheckDataDiff()
  2.     Dim d As Object
  3.     Dim aData1, aData2, aRes, aKeys
  4.     Dim strKey As String, strMsg As String
  5.     Dim i As Long, k As Long
  6.     Dim intSame As Long, intShtA As Long, intShtB As Long
  7.     Set d = CreateObject("scripting.dictionary") '后期绑定字典
  8.     With Worksheets("表1") '表1 A列数据存入数组
  9.         aData1 = .Range("a1:a" & .Cells(Rows.Count, 1).End(xlUp).Row)
  10.     End With
  11.     With Worksheets("表2") '表2 A列数据存入数组
  12.         aData2 = .Range("a1:a" & .Cells(Rows.Count, 1).End(xlUp).Row)
  13.     End With
  14.     For i = 2 To UBound(aData1) '遍历表1数据存入字典
  15.         strKey = aData1(i, 1)
  16.         d(strKey) = "表1" '将来源作为item
  17.     Next
  18.     ReDim aRes(1 To UBound(aData1) + UBound(aData2), 1 To 3) '定义结果数组大小
  19.     For i = 2 To UBound(aData2) '遍历表2数据
  20.         strKey = aData2(i, 1)
  21.         If d.exists(strKey) Then '如果存在关键字……
  22.             If d(strKey) = "表1" Then '如果该关键字属于表1,这层判断是为了避免表2存在重复值
  23.                 intSame = intSame + 1 '累加相同个数
  24.                 aRes(intSame, 1) = strKey '存入结果数组第1列
  25.                 d(strKey) = "相同" '将关键字对应的item修改为相同
  26.             End If
  27.         Else '如果字典不存在该关键字,说明是表2独有
  28.             intShtB = intShtB + 1 '累加B表独有个数
  29.             aRes(intShtB, 3) = strKey '存入结果数组第3列
  30.             d(strKey) = "表2" '存入字典,item为来源表2
  31.         End If
  32.     Next
  33.     aKeys = d.keys '字典的keys集合
  34.     For i = 0 To UBound(aKeys) '遍历字典剔除tiem相同的即为A表独有值
  35.         strKey = aKeys(i)
  36.         If d(strKey) = "表1" Then
  37.             intShtA = intShtA + 1 '累加A表独有个数
  38.             aRes(intShtA, 2) = strKey '存入结果数组第2列
  39.         End If
  40.     Next
  41.     If k < intSame Then k = intSame
  42.     If k < intShtA Then k = intShtA
  43.     If k < intShtB Then k = intShtB
  44.     Worksheets("结果").Select
  45.     Range("a:e").ClearContents
  46.     Range("a1").Resize(UBound(aData1), 1) = aData1 'A列放表1数据
  47.     Range("b1").Resize(UBound(aData2), 1) = aData2 'B列放表2数据
  48.     Range("a1:e1") = Array("A表数据", "B表数据", "相同项", "A表独有", "B表独有")
  49.     Range("c2").Resize(k, UBound(aRes, 2)) = aRes '结果数组数据
  50.     strMsg = "两表相同项:" & intSame & vbCrLf _
  51.             & "A表独有项:" & intShtA & vbCrLf _
  52.             & "B表独有项:" & intShtB
  53.     MsgBox strMsg, , "公众号Excel星球"
  54.     Set d = Nothing
  55. End Sub
复制代码

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-6-3 11:22 来自手机 | 显示全部楼层
是太菜还是太难啊,没人理吗?

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-6-3 11:52 来自手机 | 显示全部楼层

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-6-3 12:50 | 显示全部楼层
经坛友指点,发现82行 161行 dic1(k)(s1arr(i, 1)) = dic1(k)(s1arr(i, 1)) & "," & jg1arr(i, 1) & "$" & jg1 & "$" & i + 1应改为: dic1(j)(s1arr(i, 1)) = dic1(j)(s1arr(i, 1)) & "," & jg1arr(i, 1) & "$" & jg1 & "$" & i + 1

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-6-3 18:31 | 显示全部楼层

代码很牛,但是有几个我的要求没达到,一是两列数据值相同时,提取指定的列数据给对方,二是没有对方的地址这项,重复的项要累加起来并计算重复的次数,每个返回的值都要是指定列的value+address这样的形式。经测100万行数据用时4分多钟,谢谢老大

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-6-4 02:48 | 显示全部楼层

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-6-4 16:15 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
呼叫版主大人来帮忙解决,是太难还是太菜啊,没人理的

TA的精华主题

TA的得分主题

发表于 2023-6-4 20:00 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
没人跟贴是因为你的附件中没有数据,如果附件有数据,而且需求清晰,相信会有很多人跟贴的。你只是放了一堆代码上来,那是很少有人愿意看的,因为读别人写的代码是一件比较痛苦的事情
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

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

GMT+8, 2024-11-16 09:33 , Processed in 0.040573 second(s), 10 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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