【问题标题】:Create a Unique list of names from 2 given ranges从 2 个给定范围创建一个唯一的名称列表
【发布时间】:2019-11-07 09:34:09
【问题描述】:

我的这组代码运行不正确。

它从 Sheets("one")Sheets("two") 中获取名称列表,并且应该找到唯一的名称并将它们放在 表格(“三个”)

  • 两个列表都只是文本字符串。
  • 两个列表不是连续的,这意味着一个名字可能在 与其他范围不同的行。它没有特定的顺序。

从外观上看,它只是取了一个完整的范围并使其输出,没有过滤掉任何名称。

对于这个例子,我在工作表“一”上有 150 个名字,而工作表“二”上有 160 个名字。我应该只在“三”表上看到大约 10 个唯一值。但是我得到的返回值正好是 160。

有什么想法吗?

Sub dupes()

Dim arrRanges(1) As Excel.Range
Dim dDedupe As New Scripting.Dictionary
Dim lngCounter As Long
Dim rngInspect As Excel.Range

Set arrRanges(0) = Sheets("one").Range("A2:A1000")
Set arrRanges(1) = Sheets("two").Range("A2:A1000")

For lngCounter = 0 To 1

    For Each rngInspect In arrRanges(lngCounter).cells
        If Not dDedupe.Exists(CStr(rngInspect.Value)) Then
            dDedupe.Add CStr(rngInspect.Value), dDedupe.count
        End If
    Next rngInspect

Next lngCounter

'Output
Sheets("three").Range("A2").Resize(dDedupe.count).Value = Application.Transpose(dDedupe.Keys())

End Sub

【问题讨论】:

  • WAY 01 复制第三张表中的名称。使用 Data | Remove Duplicates WAY 02 在 VBA 中使用 Dictionary WAY 03 在 VBA 中使用 Collection
  • 把list放在eachother下面看看RemoveDuplicates
  • 如果您正在使用Dictionary,但仍然出现重复,请检查是否有任何不可见的问题(例如额外的空格)使 VBA 认为字符串不同。也许使用Trim(Replace(CStr(rngInspect.Value)," ", " "))
  • 您是要删除重复项还是只提取一次出现的值?

标签: excel vba for-loop filter unique


【解决方案1】:

从问题的措辞来看,我假设您只想提取在数据中出现一次的名称(这就是为什么比较 150 和 160 个名称的列表应该只输出 10 个名称,这些名称只出现一次) .

您的代码本身很好,但您的代码中没有任何地方实际处理/删除重复项,试试这个调整后的代码:

Sub dupes()

Dim arrRanges(1) As Excel.Range
Dim dDedupe As New Scripting.Dictionary
Dim lngCounter As Long
Dim rngInspect As Excel.Range
Dim strKey As String

Set arrRanges(0) = Sheets("one").Range("A2:A" & Sheets("one").Cells(Rows.Count, 1).End(xlUp).Row)
Set arrRanges(1) = Sheets("two").Range("A2:A" & Sheets("two").Cells(Rows.Count, 1).End(xlUp).Row)

For lngCounter = 0 To 1

    For Each rngInspect In arrRanges(lngCounter).Cells
        strKey = CStr(rngInspect.Value)
        If dDedupe.Exists(strKey) Then
            dDedupe(strKey) = dDedupe(strKey) + 1
        Else
            dDedupe.Add strKey, 1
        End If
    Next rngInspect

Next lngCounter

For Each Key In dDedupe.Keys()
    If dDedupe(Key) > 1 Then dDedupe.Remove Key
Next Key
'Output
Sheets("three").Range("A2").Resize(dDedupe.Count).Value = Application.Transpose(dDedupe.Keys())

End Sub

这个sub会统计每个名字出现的次数,然后删除所有出现多次的名字。

一种更有效的方法是将所有名称存储在一个数组中(而不是将两个不同的范围存储在一个数组中)并循环遍历该数组而不是逐个访问每个单元格。

【讨论】:

  • 我认为 OP 的 If Not dDedupe.Exists(CStr(rngInspect.Value)) Then 行正在检查重复项...
  • @Chronocidal 你说得对,我应该措辞更好。代码会检查 是否有重复项,但它不会对这些信息做任何事情。正如 OP 所说,他只希望得到只出现一次的名称的输出(因此他期待 10 个名称,而不是 160 个)
  • 绝对粉碎它 M.Schalk!谢谢您的帮助。我现在可以看到哪里出错了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-12
  • 1970-01-01
  • 2017-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多