Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 是否有一种方法可以构建高效的vba函数,该函数将范围作为其参数并返回一个唯一值数组(无重复)?_Arrays_Vba_Function - Fatal编程技术网

Arrays 是否有一种方法可以构建高效的vba函数,该函数将范围作为其参数并返回一个唯一值数组(无重复)?

Arrays 是否有一种方法可以构建高效的vba函数,该函数将范围作为其参数并返回一个唯一值数组(无重复)?,arrays,vba,function,Arrays,Vba,Function,我想创建一个vba函数(Public function),给定一个1列范围,它将返回一个包含唯一值的数组。它必须执行与RemovedUpplicates方法相同的工作,但在不更改任何内容的情况下,它应该只返回一个唯一值数组 我写了这段代码 Public varData() As Variant Public Sub Suplem(rng As Range) Dim tempSheet As Worksheet Size = rng.Rows.Count On Error GoTo tuda1

我想创建一个vba函数(Public function),给定一个1列范围,它将返回一个包含唯一值的数组。它必须执行与RemovedUpplicates方法相同的工作,但在不更改任何内容的情况下,它应该只返回一个唯一值数组

我写了这段代码

Public varData() As Variant

Public Sub Suplem(rng As Range)

Dim tempSheet As Worksheet
Size = rng.Rows.Count
On Error GoTo tuda1
    Worksheets.Add.Name = "temp"
tuda1:
    Set tempSheet = ActiveWorkbook.Worksheets("temp")
With tempSheet
    tempSheet.Range(tempSheet.Cells(1, 1), tempSheet.Cells(Size, 1)).Select
    Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
                :=False, Transpose:=False
    tempSheet.Range(tempSheet.Cells(1, 1), tempSheet.Cells(Size, 1)).RemoveDuplicates
    varData = tempSheet.Range(tempSheet.Cells(1, 1), tempSheet.Cells(Size, 1)).Value
End With
tempSheet.Delete

End Sub


Public Function UniqueVals(rng As Range)

ReDim varData(rng.Rows.Count - 1)
Call Suplem(rng)
Dim a() As Variant
UniqueVals = varData
Erase varData

End Function
这里的UniqueVals函数调用Sub-Suplem,它创建临时工作表,将初始范围的副本粘贴到其中,并从中删除重复项。然后,它将从重复项中释放的最终范围记录到全局数组varData中。之后,UniqueVals函数返回varData中的数据并将其清除


问题是这个函数返回#VALUE!由于Sub内部创建和修改了临时工作表,您对如何避免此错误有何想法?我可以改为使用数组,但使用范围方式,即通过公式对其进行修改吗?

如果没有动态数组公式
UNIQUE()
,则使用此使用字典的函数

Public Function UniqueVals(rng As Range) As Variant
    Dim rngArray As Variant
    rngArray = Intersect(rng, rng.Parent.UsedRange).Value

    Dim dict As Object
    Set dict = CreateObject("Scripting.Dictionary")

    Dim t As Variant
    For Each t In rngArray
        On Error Resume Next
            dict.Add t, t
        On Error GoTo 0
    Next t

    Dim temp() As Variant
    ReDim temp(1 To dict.Count, 1 To 1)

    Dim x As Long
    x = 1
    Dim key As Variant
    For Each key In dict.Keys
        temp(x, 1) = key
        x = x + 1
    Next key

    UniqueVals = temp
End Function

如果您有动态公式,则有一个
UNIQUE()
公式可以执行此操作。Office 365订阅中提供了动态数组公式。或者使用字典并利用
.exists()
来避免错误,您可以使用现有工作表上的最后一列来执行相同的操作。我假设您的数据集不跨16384列,所以应该没有问题。代码完成后,只需在
End Sub
之前清除此列的内容即可。其他解决方案都是理想的,这只是一个例子FYI@urdearboy但是,如果从工作表中调用此函数,它将不起作用,因为从工作表中调用的函数无法对其他单元格进行更改。必须没有使用UDFSE。与仅返回字典键数组相比,在最后创建临时数组做了什么?1d数组不能与工作表函数等一起使用吗?@NickSlash它将是一个水平数组,OP声明数组将是垂直的。我这样做是为了避免
应用程序。转置
限制项目的大小或数量。@NickSlash,据我所知,如果不转换为数组,就不能简单地将字典放入单元格中。实际上,这种方法是可行的,尽管我不确定在处理10k+行数据时是否会很快。但问题是,它只能用于完全相同的工作表的范围,而如果它来自不同的工作表,则会发生错误(#VALUE!)@MarkRoyale请参见编辑。它不会在不同的工作表上工作。而且,它应该是非常迅速,即使与大范围。