如何删除 Excel 中区分大小写的重复项(对于 100k 条记录或更多)?

How to remove duplicates that are case SENSITIVE in Excel (for 100k records or more)?

我已尝试使用此公式字段并将其复制到我拥有的所有 >100k 记录。

=IF(SUMPRODUCT(--EXACT(A2,$B:B1)),"",A2)

其中:

  1. A 列 = 包含所有数据(包括重复项)的列
  2. B 列 = 显示数据的列(来自 A 列)如果唯一,否则为空字符串

但是我遇到了这个问题:

是的,我的 Excel 2016 是 32 位的,是的,我的笔记本电脑只有 8GB 内存。但是我已经读到,使用 64 位和 16GB RAM 的人遇到了与我相同的错误。

我知道 Excel 函数中有一个函数:数据 > Select 列 > 删除重复项。但是,此函数仅删除不区分大小写的数据。

请告诉我如何解决这个问题。我愿意使用 Crystal 报告之类的东西或某种免费软件来解决这个问题。请指教

您可以试试这样的方法。 在尝试此备份您的数据之前。 下面的代码将从 A 列中删除重复项,并且区分大小写。

Sub GetUniqueValues()
Dim x, dict
Dim lr As Long
lr = Cells(Rows.Count, 1).End(xlUp).Row
x = Range("A2:A" & lr).Value
Set dict = CreateObject("Scripting.Dictionary")
For i = 1 To UBound(x, 1)
    dict.Item(x(i, 1)) = ""
Next i
Range("A2:A" & lr).ClearContents
Range("A2").Resize(dict.Count).Value = Application.Transpose(dict.keys)
End Sub

编辑代码:

Sub GetUniqueValues()
Dim x, dict, y
Dim lr As Long
Application.ScreenUpdating = False

lr = Cells(Rows.Count, 1).End(xlUp).Row
x = Range("A2:A" & lr).Value
Set dict = CreateObject("Scripting.Dictionary")
For i = 1 To UBound(x, 1)
    dict.Item(x(i, 1)) = ""
Next i
ReDim y(1 To dict.Count, 1 To 1)

i = 0
For Each it In dict.keys
   i = i + 1
   y(i, 1) = it
Next it

Range("A2:A" & lr).ClearContents
Range("A2").Resize(dict.Count).Value = y

Application.ScreenUpdating = True
End Sub

对于一般解决方案,可能更喜欢已经建议的 VBA 方法。但是对于只工作一次的东西,你可能只需稍微调整一下你的应用方式就可以让它按照你想要的方式工作 =IF(SUMPRODUCT(--EXACT(A2,$B:B1)),"",A2)。我还尝试使用 COUNTIF 算法,它比 SUMPRODUCT 快得多,但不区分大小写。

由于我也是 运行宁 32 位 Excel 和 8GB 内存,我很好奇我是否可以复制内存问题。我在 A 列中生成了一个包含 100,000 个 运行dom 5 字母字符串的列表。只使用了 10 个字母 (ABCDEFGHJK),因此在 100,000 个字符串中,有些字符串会出现不止一次。然后,我在 B 列中应用了 OP 建议的公式来仅过滤掉唯一值。它确实有效,但需要相当长的时间。但我从来没有 运行 进入 OP 所造成的内存问题。

建议解决方案:
根据这些观察,针对您的特定问题的一种可能解决方案可能是将 A 列复制到一个新的临时工作簿,并在所有其他工作簿关闭时将 运行 您的 SUMPRODUCT 公式复制到那里。完成后,您可以将结果粘贴回原始文件中的原始列。实际上可以通过简单地对该列进行过滤来删除重复项,以便将所有重复项(空单元格)组合在一起,然后删除这些行。可以在下面找到我尝试复制的详细信息。

SUMPRODUCT:大约 1 小时
首先,我尝试了与 OP 中相同的公式,=IF(SUMPRODUCT(--EXACT(A2,$B:B1)),"",A2),但一次只做 10,000 行(通过在第 10,000、20,000 行等处插入空行并一次复制一万行。)每组10,000 行需要几分钟才能完成。当我一次对所有 100,000 个单元执行整个 shebang 作为一个巨大的复制操作时,该操作大约需要一个小时才能完成,同时 Excel 没有响应。内存使用量为 1.4 GB,CPU 平均超过 50% 的容量(使用 Windows 任务管理器监控)。当我已经以各种方式处理数据(因此消耗更多内存)时,我还尝试 运行 公式,这将 CPU 容量推到 100% 并导致了几次崩溃。我设法通过简单地关闭 Excel 来清除内存并在没有打开其他工作簿的情况下重新启动 运行 再次操作来避免这种情况。

正如您在下面的屏幕截图中看到的那样,该公式有效并且唯一条目在列表的下方变得越来越少(正如预期的那样,因为它们是 运行dom)。我将 1 分配给包含重复项的单元格,以便我可以轻松地计算它们。有 36,843 个这样的实例。

第一行,无重复:

最后一行,大部分重复(包含 1 的单元格):

COUNTIF:8.5 分钟
与需要大约 1 小时完成的 SUMPRODUCT 算法相比,下面的 COUNTIF 公式只用了 8.5 分钟就完成了同样的工作,但它不会区分大小写。这种方法需要使用帮助栏。 COUNTIF returns 特定字符串在当前单元格上方的 运行ge 中使用的实例数,因此每次第一次遇到字符串时,它都会 return 1. 单元格 B2 包含 =COUNTIF($A:$A2,A2),复制所有 100,000 行需要大约八分半钟。然后,在一个单独的列中,我只使用了一个简单的 IF 公式来过滤掉列 A 中的唯一值;单元格 C2 包含 =IF(B2=1,A2,1),其中 return 是 A 列中的字符串(如果它是唯一的);否则 1 是 returned(以便与 SUMPRODUCT 轻松比较)。为所有 100,000 行向下复制此 IF 公式几乎是瞬时的。令人欣慰的是,此操作后 C 列中 1 的总和与 SUMPRODUCT 的情况相同,为 36,843。

索引:失败
我还使用 INDEX 和 MATCH 函数玩弄了一个数组公式。此公式与 COUNTIF 的作用相同,但还会过滤掉空行: =INDEX($A:$A0001,MATCH(0,COUNTIF($E:E1,$A:$A0001),0))。这应该作为数组公式输入到单元格 B2 (Ctrl + Shift + Enter) 然后复制下来。一次复制一个单元格对于几十行来说效果很好,但超出此范围会导致 Excel 崩溃。我什至在一夜之间尝试了 运行ning,但操作从未完成。 (公式可以扩展为区分大小写,但我懒得尝试。)

但是,对于失败的 INDEX 公式,需要注意的一点是,当在 单独的 工作簿中应用该公式时,会发生上述行为。我还尝试在与 COUNTIF 公式相同的工作簿中的 D 列中 运行 这个公式。然后我确实 运行 进入了 OP 中描述的内存问题,毫不奇怪,这表明内存问题取决于工作簿中的其余数据。

利用排序的力量获得唯一值。不需要图书馆。可以轻松转换为 select 完整行:

Sub GetUniqueValues()
    'Sort once so we can run through the list without nested loops
    Sheet1.Range("$A:$A").Sort Key1:=Sheet1.Range("$A:$A"), Header:=xlYes, MatchCase:=True
    count = Application.WorksheetFunction.CountA(Sheet1.Range("$A:$A"))
    LastCell = 1

    For i = 2 To count
        If Sheet1.Cells(i, 1).Value = Sheet1.Cells(LastCell, 1).Value Then
            'Remove second/third/fourth occurrences
            Sheet1.Cells(i, 1).Clear
        Else
            'If its first occurrence of this value, make a note of its position
            LastCell = i
        End If
    Next

    'Sort again to move the cells emptied out to the bottom
    Sheet1.Range("$A:$A").Sort Key1:=Sheet1.Range("$A:$A"), Header:=xlYes, MatchCase:=True
End Sub