在Excel单元格中删除重复数据

7

假设我在一个 Excel 单元格中有以下文本字符串:

John John John Mary Mary

我希望创建一个公式(不使用菜单功能或VBA),以便在另一个单元格上给出结果。

John Mary

我该怎么做呢?

到目前为止,我尝试在互联网和SO上搜索相关问题,但是我只找到了涉及Excel内置重复项删除或涉及countif以及将重复项替换为""的解决方案。我还查看了Excel函数列表,特别是“文本”类别中的函数,但没有找到任何有趣的内容,可以在一个单元格中完成。


1
你尝试过什么?你采取了什么样的方法?使用VBA解决这个问题很简单,但只用公式就不那么简单了。你可以尝试使用辅助列来解决它。 - Ron Rosenfeld
@RonRosenfeld,我会更新问题,并分享我微不足道的解决尝试。 - Waldir Leoncio
我能理解只使用公式的必要性,但我可以问一下为什么您不能使用一些VBA并将其附加到工作表上的形状或按钮的宏吗?我只是好奇。甚至可以在工作表中构建一个事件。嗯? - peege
1
@PJRosenburg,我们的许多用户使用Calc而不是Excel;从我的经验来看,除了最简单的VBA宏之外,Calc并不能很好地解释其他内容。 - Waldir Leoncio
8个回答

6
答案在这里:https://www.extendoffice.com/documents/excel/2133-excel-remove-duplicate-characters-in-string.html
Function RemoveDupes2(txt As String, Optional delim As String = " ") As String
Dim x
'Updateby20140924
With CreateObject("Scripting.Dictionary")
    .CompareMode = vbTextCompare
    For Each x In Split(txt, delim)
        If Trim(x) <> "" And Not .exists(Trim(x)) Then .Add Trim(x), Nothing
    Next
    If .Count > 0 Then RemoveDupes2 = Join(.keys, delim)
End With
End Function

将上面的代码放在一个模块中。
使用=RemoveDupes2(A2,","),其中A2包含以逗号分隔的重复文本。您可以更改分隔符。

这对于我来说不起作用,针对13个字符的数字。 - Devil07

1
假设您的单元格中最多只有两个不同的名称,那么这应该可以工作:
=MID(A1&" ",1,FIND(" ",A1&" "))&
 MID(SUBSTITUTE(A1&" ",MID(A1&" ",1,FIND(" ",A1&" ")),"")&" ",1,
 FIND(" ",SUBSTITUTE(A1&" ",MID(A1&" ",1,FIND(" ",A1&" "))&" ","")))

对于所有这些情况,它将显示John Mary

John John John Mary Mary
John Mary
John Mary John Mary
John Mary Mary
John John Mary

它将会显示以下所有内容的 John:
John
John John
John John John

如果 A1 为空,则不会显示任何内容。


这确实适用于两个不同的名称。我会看看能否将其推广到最多16个名称。谢谢! - Waldir Leoncio
1
这种特定策略对于三个名字会变得非常复杂,甚至在你处理16个名字之前就可能遇到一些Excel的限制。它基本上是一个递归算法:A)获取第一个单词,B)从其余字符串中删除它,C)将A和B连接起来,[在步骤B结果上重复执行步骤A-C,...]。你的问题突显了Excel字符串操作的弱点。(特别是无法使用正则表达式。)另外,Excel缺少类似于“eval”的功能,使得在不使用VBA或使用“隐藏”单元格的情况下进行此类操作变得困难。 - Rick Hitchcock
@RickHitchcock有没有办法在不使用尾随逗号的情况下,对最多3个唯一字符串进行操作? - Devil07
不确定您所说的尾随逗号是什么意思,但我肯定不建议使用此策略处理超过2个唯一字符串。Excel在没有使用VBA的情况下无法很好地处理这种情况。 - Rick Hitchcock

0

正如我所写的那样,使用VBA很容易解决。如果您无法使用VBA,则可以使用辅助列的方法。

假设:您的字符串在A1中

输入以下公式:

C1:  =IFERROR(INDEX(TRIM(MID(SUBSTITUTE($A$1," ",REPT(" ",99)),(ROW(INDIRECT("1:" & LEN($A$1)-LEN(SUBSTITUTE($A$1," ",""))+1))-1)*99+((ROW(INDIRECT("1:" & LEN($A$1)-LEN(SUBSTITUTE($A$1," ",""))+1))=1)),99)),ROWS($1:1),1),"")

D1:  =IF(COUNTIF(C1:$C$5,C1)=1,C1,"")

选择C1和D1,向下填充直到出现空白

E1:  =D1
E2:  =TRIM(CONCATENATE(D2," ",E1))

选择单元格E2并向下填充。

在列E中填写的最后一个单元格的内容将是您的结果。

如果您想要一个单元格自动返回列E范围内最后一个单元格的内容,您可以使用如下公式:

=LOOKUP(REPT("z",99),$E$1:$E$100)

谢谢,Ron。这似乎对我的实际情况并不适用,但我会再仔细考虑一下。 - Waldir Leoncio
@WaldirLeoncio 这个程序在你提供的示例数据上能够工作。如果你的样本数据不具有代表性,请编辑你原来的问题并提供更多失败信息。 - Ron Rosenfeld

0

如果您也是制作列表的人,那么可能会找到一个解决方案。

当您通过将上面的单元格与当前行组合来制作列表时,可以使用以下代码检查上面的单元格中是否已经存在该值:

if(iserror(find(value_to_be_added,previous_concatenation)),
    previous_concatenation&" "&value_to_be_added,previous_concatenation)

0

没有公式:使用空格作为分隔符的“文本到列”功能,转置输出,对每个列单独应用“删除重复项”,然后再次转置结果。


谢谢您的建议,但我真的需要让它在用户不干预的情况下工作。这是为客户设计的一个复杂的电子表格,我不想让他除了填写单元格以外做任何事情。 - Waldir Leoncio

0

如果有访问TEXTJOIN的权限,可以使用以下方法:

=TEXTJOIN(" ",,FILTERXML("<t><s>"&SUBSTITUTE(A1," ","</s><s>")&"</s></t>","//s[not(preceding::*=.)]"))

当我在一个包含“John John John Mary Mary”的单元格上尝试时,它只返回了“John”。我希望这个能够运行,但对我来说不行。我希望我更好地理解它在做什么。 - Jay Brown

0

你尝试过textjoin函数吗?(Excel 2016可用,之前的版本不确定)。我刚刚在寻找类似的东西,这个函数似乎可以在我有多个重复值的列上完成工作。

=TEXTJOIN(delimiter;ignore_empty;text)
  • 以任何你需要的方式定义分隔符
  • 忽略空值可以是 true 或 false,取决于你的需求
  • 文本将是你的值数组 - 在此使用 unique 函数(参见下面的示例)将过滤掉任何字符串的多个实例(我在用它来处理数字,它很有效)

示例:

=TEXTJOIN(" ";TRUE;UNIQUE($A$1:$A$16))

猜测这可能是Excel中等同于Google Sheets的连接函数。如果您键入=join,则会出现Textjoin - 我使用了user11308575帖子中提供的公式,但删除了括号及其内容,然后进行了修改。

希望这能有所帮助(尽管这个线程已经过时);)


1
理论已经在那里了,但你只是忽略了一个重点,即 OP 在单个单元格中有一个字符串需要去除重复项。 - JvdV

-1

3
原回答涉及在Google Sheets中使用该函数。Microsoft Excel没有"join"函数。 - Waldir Leoncio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接