你如何将范围内的所有值转换为文本?

我有一个Range对象引用工作表上的列。 此列包含混合的数据types(数字,文本和其他一些东西)。

我想从列中删除重复项:

 rge.RemoveDuplicates Columns:=1, Header:xlNo 

但是由于混合的数据types,这并不能正确删除所有的重复项。

我知道混合数据types是问题所在,因为在尝试从这些值的副本中删除重复项之前手动转换单元格使用TEXT($REF, "0")是成功的。


我怎样才能replace范围内的所有值与他们的文本等值?

我已经尝试了显而易见的:

 rge = rge.Text rge.Value = rge.Text 

但没有成功。


请注意,迭代不是一个选项; 我正在处理数以万计的数据行,单个写入单元的性能损失太高。 我需要一个能够在整个范围内一次操作的东西。

(如果事实certificate迭代是唯一的解决scheme,那么使用.RemoveDuplicates进行第一次.RemoveDuplicates ,对数据进行sorting,然后在n次手动取出剩余的数据将更快。


编辑:其他信息

如果我复制并粘贴不包含重复项的范围的子集,然后手动运行“删除重复项”,则删除重复值。

但是,如果复制也包含数字的范围的子集,则不会删除重复项, 即使重复项不是自己的数字

我的猜测(这只是一个猜测)是,内部的Excel使用混合数据types值比纯粹的文本值不同的比较algorithm。


最小工作示例: https : //dl.dropboxusercontent.com/u/1402749/dups.xlsx

我没有尝试使用RemoveDuplicates方法,因为它似乎无法为您工作。

我使用字典对象来做肮脏的工作,并帮助确保唯一性。 基于这个例子的(明显的)成功,我不确定你需要担心将值转换为文本。 此迭代仅使用这些 ,然后重新写入该范围。 如果你需要额外的格式 ,请澄清:)

 Sub Test() Dim d As Object 'Scripting.Dictionary ' requires reference to Microsoft Scripting Runtime if you ' want to use early-binding Dim rng As Range Dim cl As Variant Dim var As Variant '#Define our range Set rng = Range("A1:A22") '#Store values in an array var = rng.Value '#Instantiate our dictioanry object Set d = CreateObject("Scripting.Dictionary") '#store unique vals in the dictionary For Each cl In var d(cl) = cl Next '#Clear the original range rng.Clear '#Put the unique vals in to the range rng.Resize(UBound(d.Keys) + 1).Value = Application.Transpose(d.Keys()) Set d = Nothing End Sub 

在示例数据上,我最终得到了17个独特的值:

在这里输入图像说明

Selection.NumberFormat =“@”

我会认为rge.NumberFormat =“@”将工作

我相信这将提供你正在寻找的结果。 将此函数插入​​到VBA编辑器中。

 Public Sub ConvertToText() Dim c As Range Dim a As Areas Dim v As Variant Set c = Selection Set a = c.Areas If a.Count > 1 Then ' IF DESIRED YOU CAN EXTEND THE LOGIC FOR MULTIPLE AREAS | CURRENT FUNCTION DOES NOT SUPPORT MsgBox "Select one continuous range.", vbCritical, "Error" Exit Sub End If v = WorksheetFunction.Transpose(WorksheetFunction.Transpose(c.Value)) c.Clear c.NumberFormat = "@" c = v End Sub 

我认为使用RemoveDuplicates语法存在一个问题。

尝试:

 rge.RemoveDuplicates Columns:=Array(1), Header:=xlNo 

我会build议运行其他代码,首先将格式标准化为文本。 这个语法对我来说工作得很好。

我不知道为什么removeduplicates不起作用。 但是我不能用你的样本数据。 作为一个“解决方法”,我会build议尝试高级filter。 唯一的缺点是,它会一直把第一行看作一个标题,所以你可能需要补偿。 这是一个适用于您的示例数据的例程。 我select复制到一个新的目的地,然后覆盖原来的,但你可能希望使用不同的scheme。

另外,如果它适用于您,您可能想在macros运行时禁用屏幕更新。

顺便说一句,该例程与通用格式和混合数字和文本数据也工作。 可能不需要将所有内容都转换为文本。

 Sub RemDups() Dim R As Range Dim rDest As Range Set R = Range("a1", Cells(Rows.Count, "A").End(xlUp)) Set rDest = Range("D1") rDest.EntireColumn.Clear R.AdvancedFilter xlFilterCopy, , rDest, True R.EntireColumn.Clear Set rDest = Range(rDest, Cells(Rows.Count, rDest.Column).End(xlUp)) rDest.Copy R(1) rDest.Clear End Sub 

你可以去这里:

如果您的数据大小<= 30k行:Excel的RemoveDuplicates相当的0.2秒的消逝时间

 Dim arr As Variant, i As Long '~~> pass range values to array With SheetCodename '~~> Change to suit arr = Application.Transpose(.Range("A1", .Range("A" & .Rows.Count).End(xlUp))) End With '~~> use Dictionary to remove dupes With CreateObject("Scripting.Dictionary") For i = LBound(arr) To UBound(arr) .Item(CStr(arr(i))) = CStr(arr(i)) Next SheetCodename.Range("A:A").ClearContents '~~> Clear source range '~~> Return unique items to range SheetCodename.Range("A1", "A" & .Count) = Application.Transpose(.Items) End With 

我在样本数据上testing了这个数据,并返回了17个唯一的值。
对于较大的数据集,这可能由于Excel内存的缺陷而失败。

EDIT1:
我真的有兴趣做这个工作在10万行以上。
然后我偶然发现了这个 ,下面是我想到的。
实际testing的数据数量: 168091

 Dim rng As Range, cel As Range Dim arr() As Variant, i As Long, key, start start = Timer With Sheet4 Set rng = .Range("A1", .Range("A" & .Rows.Count).End(xlUp)) rng.RemoveDuplicates 1, xlNo End With Debug.Print Timer - start '3.585938 sec start = Timer With Sheet2 Set rng = .Range("A1", .Range("A" & .Rows.Count).End(xlUp)) End With '~~> Use Dictionary to remove duplicates With CreateObject("Scripting.Dictionary") '~~> need to loop through range since Array have limitations as well For Each cel In rng .Item(CStr(cel.Value2)) = CStr(cel.Value2) Next '~~> array limit workaround ReDim arr(.Count, 2): i = 0 For Each key In .Keys arr(i, 0) = .Item(key) i = i + 1 Next '~~> Return unique items to range Sheet2.Range("A:A").ClearContents Sheet2.Range("A1", "A" & .Count) = arr End With Debug.Print Timer - start '5.257813 sec 

结果与使用Excels RemoveDuplicates (我的意思是唯一的输出)相同。
在性能上有1.671875秒的差别,但对我来说还是可以控制的。

您的示例数据集已被格式化为文本…我将几行更改为数字格式,并能够使用以下代码删除重复项(而不是将所有内容格式化为文本):

 Sub RemoveDuplicates() Dim r As Range Dim w As Worksheet Set w = ActiveSheet Set r = w.Range("A1:A100000") r.AdvancedFilter Action:=xlFilterCopy, CopyToRange:=r.Offset(0, 1), Unique:=True End Sub 

上面的代码将唯一的值放在B列,所以你必须修改这个以适应你的需要。 如果您希望数据保留在列A中,则可以创build临时表来放置唯一值,删除原始数据集,然后将唯一值移回到原始表单中。

上面的代码假定你有一个数据集标题。 我也不知道这将在大型数据集上performance如何,所以你可能需要做一些testing,看看它是否会为你工作。


编辑

我只是在100K行testing了这个,花了大约50秒才完成…所以我猜这个解决scheme是不可行的。 而我刚才看到你select了David的答案。 :)我会留下来,以防将来帮助别人。

编辑2

在我发布之前,我错过了Ron的回答。 我们使用相同的function,但他的答案比我的function更多。