Excel精英培训网

 找回密码
 注册
数据透视表40+个常用小技巧,让你一次学会!
查看: 2841|回复: 4

[已解决]多列数据交集

[复制链接]
发表于 2015-11-2 06:21 | 显示全部楼层 |阅读模式
本帖最后由 张雄友 于 2015-11-2 19:12 编辑

求多列数据交集,已有效果,但没有数据出来。
  1. Option Explicit

  2. Sub 多列交集()
  3.     Dim arr, brr, i&, j&, m&, n&, tms#, tmp$, s As Boolean, k&
  4.     tms = Timer
  5.     arr = Range("A2:G17")
  6.     m = UBound(arr)
  7.     n = UBound(arr, 2)
  8.     ReDim brr(1 To m, 1 To 1)
  9.     For i = 1 To m
  10.         s = True
  11.         tmp = arr(i, 1)
  12.         For j = 2 To n
  13.             If tmp <> arr(i, j) Then s = False: Exit For
  14.         Next
  15.         If s Then brr(i, 1) = tmp: k = k + 1
  16.     Next
  17.     [I2].Resize(Rows.Count - 1, 1).ClearContents: [I2].Resize(UBound(brr), 1) = brr
  18.     MsgBox Format(Timer - tms, "0.00s ") & Chr(10) & "共找到" & Chr(10) & k & "个交集!"
  19. End Sub
复制代码
最佳答案
2015-11-2 14:15
换个思路
  1. Sub 多列交集()
  2.     Dim arr, i&, j&, tms#, k&, d, x
  3.     tms = Timer
  4.     arr = Range("A2:G17")
  5.     Set d = CreateObject("scripting.dictionary")
  6.     For j = 1 To UBound(arr, 2)
  7.         For i = 1 To UBound(arr)
  8.             x = arr(i, j)
  9.             If Val(d(x)) = j - 1 Then d(x) = j       '如果本列d(x)的值为列数-1,则d(x)取值为本列数
  10.         Next
  11.     Next
  12.     For Each x In d.Keys
  13.         If Len(x) = 0 Or d(x) < UBound(arr, 2) Then d.Remove x      '如果d(x)不等于总列数(说明不是每列都出现过,去掉)
  14.     Next
  15.     [J2].Resize(Rows.Count - 1, 1).ClearContents
  16.     [J2].Resize(d.Count) = Application.Transpose(d.Keys)
  17.     MsgBox Format(Timer - tms, "0.00s ") & Chr(10) & "共找到" & Chr(10) & d.Count & "个交集!"
  18. End Sub
复制代码

求交集问题.rar

16.84 KB, 下载次数: 4

excel精英培训的微信平台,每天都会发送excel学习教程和资料。扫一扫明天就可以收到新教程
发表于 2015-11-2 11:42 | 显示全部楼层
QQ截图20151102113546.jpg


如果不对,就说明一下需求



Sub test()
    Dim A, d, i, j, k, s, dKeys, dItems
    Set d = CreateObject("scripting.dictionary")
    A = Range("a1").CurrentRegion

    '1)求不重复值
    For i = 2 To UBound(A)
        For j = 1 To UBound(A, 2)
            If A(i, j) <> "" Then d(A(i, j)) = d(A(i, j)) + 1
        Next j
    Next i
    dKeys = d.Keys: dItems = d.items

    '2)判断次数
    For k = 0 To UBound(dItems)
        If dItems(k) < UBound(A, 2) Then
            d.Remove dKeys(k)
        Else
            '如果在某出现,则s=s+1
            s = 0
            For j = 1 To UBound(A, 2)
                For i = 2 To UBound(A)
                    If dKeys(k) = A(i, j) Then s = s + 1: Exit For
                Next i
            Next j
            '如果 s 达不到7次,就不是。
            If s < UBound(A, 2) Then d.Remove dKeys(k)
        End If
    Next k

    '3)结果
    [j2].Resize(d.Count) = Application.Transpose(d.Keys)
End Sub


评分

参与人数 1 +9 收起 理由
张雄友 + 9 ok

查看全部评分

回复

使用道具 举报

发表于 2015-11-2 14:15 | 显示全部楼层    本楼为最佳答案   
换个思路
  1. Sub 多列交集()
  2.     Dim arr, i&, j&, tms#, k&, d, x
  3.     tms = Timer
  4.     arr = Range("A2:G17")
  5.     Set d = CreateObject("scripting.dictionary")
  6.     For j = 1 To UBound(arr, 2)
  7.         For i = 1 To UBound(arr)
  8.             x = arr(i, j)
  9.             If Val(d(x)) = j - 1 Then d(x) = j       '如果本列d(x)的值为列数-1,则d(x)取值为本列数
  10.         Next
  11.     Next
  12.     For Each x In d.Keys
  13.         If Len(x) = 0 Or d(x) < UBound(arr, 2) Then d.Remove x      '如果d(x)不等于总列数(说明不是每列都出现过,去掉)
  14.     Next
  15.     [J2].Resize(Rows.Count - 1, 1).ClearContents
  16.     [J2].Resize(d.Count) = Application.Transpose(d.Keys)
  17.     MsgBox Format(Timer - tms, "0.00s ") & Chr(10) & "共找到" & Chr(10) & d.Count & "个交集!"
  18. End Sub
复制代码

评分

参与人数 1 +6 金币 +6 收起 理由
爱疯 + 6 + 6 学习一个!

查看全部评分

回复

使用道具 举报

发表于 2015-11-2 15:32 | 显示全部楼层
grf1973 发表于 2015-11-2 14:15
换个思路

学习了!

val可以不用吧,是测试后忘删了么?
回复

使用道具 举报

发表于 2015-11-2 15:35 | 显示全部楼层
应该可以吧,我怕d(x)为空的时候和j-1比较出现数据类型不匹配的错误。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-4-27 04:36 , Processed in 0.326680 second(s), 14 queries , Gzip On, Yac On.

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

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