当前位置: 首页 > 知识库问答 >
问题:

数组推写接受任何类型数组的VBA函数

朱高丽
2023-03-14

我试图编写一个简单的push函数,它可以向VBA数组中添加元素。

我不知道如何允许它接受类型化数组。到目前为止,我可以得到函数来接受显式键入为“variant”的数组。见下文

Function push(arr() As Variant, el As Variant) As Variant()
    ' function to redim an array and increment it by one.  If array is length 1 and element is empty, it will place the "el" param in the first index
    If IsEmpty(arr(UBound(arr))) And UBound(arr) = LBound(arr) Then
        arr(UBound(arr)) = el
    Else
        ReDim Preserve arr(LBound(arr) To UBound(arr) + 1)
        arr(UBound(arr)) = el
    End If
    push = arr
End Function

Sub testPush()
    Dim myArr() As Variant
    Dim newArr() As Variant
    myArr = Array("apple", "banana", "4")
    myArr = push(myArr, "coconut")
    Debug.Print Join(myArr, ", ")
    newArr = Array(1, 2, 3, 4)
    newArr = push(newArr, 7)
    Debug.Print Join(newArr, ", ")
End Sub

当我将myArr维度为字符串时,例如dim myArr()维度为string,我在推送函数中看到一个编译错误:type mismatch:array或user defined type expected。有没有什么方法可以使用一个函数来尝试将元素递增到数组的末尾,而不管数组的类型如何?

共有1个答案

周涵畅
2023-03-14

与我下面写的相反,也许比我更了解的人会告诉你这是可能的,以及你如何做到这一点。

我看到您的函数返回一个变量数组:

Function push(arr() As Variant, el As Variant) As Variant()

如果我理解正确的话,它只能分配给variantvariant()类型的变量。

如果我将函数更改为:

Function push(arr As Variant, el As Variant) As Variant

我认为该函数现在可以接受任意类型的数组1,但它仍然返回变量--我认为不能将其分配给所有类型的数组(这意味着在某些情况下仍然会出现编译器错误)。

更简单的方法可能是将函数更改为sub并让子例程就地修改数组。这样,调用站点上就没有赋值(因为子程序不返回值),代码应该编译。这也意味着任何类型错误2现在都将在运行时发生。

此外,我不清楚下面的观点是什么:

If IsEmpty(arr(UBound(arr)))

您似乎在检查数组的第一个元素是否被分配了默认初始化值以外的其他内容。但是这种检查似乎只适用于variant类型(初始化为空)。我认为字符串初始化为“”,数字初始化为0,对象初始化为nothing,依此类推。简而言之,我认为isempty检查可能会对variant以外的类型返回假阴性。前面提到的行为可能是您想要的,也可能不是(假设您说您希望这个push代码处理任何类型的数组)。

总的来说,一种方法可以是这样的:

Option Explicit

Sub Push(ByRef someArray As Variant, ByVal someElement As Variant)
    ' This routine expects array to be 1-dimensional.
    ' and will modify the array in-place.
    ' The array must by dynamic (cannot Redim an array that
    ' was statically declared).

    Dim lastIndex As Long
    lastIndex = UBound(someArray)

    Dim arrayNeedsExtending As Boolean
    ' If you are using "IsEmpty" to work out if the first element
    ' has been assigned a value other than its default value at initialisation
    ' then you may need to see: https://stackoverflow.com/a/3331239/8811778
    ' as "IsEmpty" might only work for Variants and may return false
    ' negatives otherwise.
    arrayNeedsExtending = (lastIndex <> LBound(someArray)) Or Not IsEmpty(someArray(lastIndex))

    If arrayNeedsExtending Then
        ReDim Preserve someArray(LBound(someArray) To (lastIndex + 1))
    End If

    ' If you have an array of objects (hypothetically, instead of a collection), the line below
    ' will raise a syntax error since Set keyword is required for objects.
    someArray(UBound(someArray)) = someElement
End Sub

Private Sub TestPush()

    Dim someStrings() As String
    someStrings = Split("a,a", ",", -1, vbBinaryCompare)
    Push someStrings, "b"
    Debug.Assert (JoinArray(someStrings) = "a,a,b")

    Dim someBooleans() As Boolean ' Can only Push dynamic arrays
    ReDim someBooleans(0 To 1)
    Push someBooleans, True
    Debug.Assert (JoinArray(someBooleans) = "False,False,True")

    Dim someZeros() As Long
    ReDim someZeros(0 To 1)
    Push someZeros, 0
    Debug.Assert (JoinArray(someZeros) = "0,0,0")

End Sub

Private Function JoinArray(ByRef someArray As Variant, Optional delimiter As String = ",") As String
    ' Expects array to be 1-dimensional.
    ' Attempts to handle non-string types albeit without error handling.

    Dim toJoin() As String
    ReDim toJoin(LBound(someArray) To UBound(someArray))

    Dim arrayIndex As Long
    For arrayIndex = LBound(someArray) To UBound(someArray)
        toJoin(arrayIndex) = CStr(someArray(arrayIndex)) ' Will throw if type cannot be coerced into string.
    Next arrayIndex

    JoinArray = Join(toJoin, delimiter)
End Function

2假设您传递字符串“a”要推入类型的数组--或者任何不能以类型强制进入数组类型的值。

 类似资料:
  • 我正在努力弄清楚是否可以在TypeScript中声明一个静态类型的函数数组。 例如,我可以这样做: 但是,如果我想让foo成为一个函数数组,它接受一个字符串而不返回任何内容,我该怎么做呢? 不起作用,因为TypeScript认为它是一个接受字符串并返回空数组的函数,而且它似乎不喜欢我试图将函数包装在括号中。 有什么想法吗? 答:感谢下面的穆罕默德,这里有一个在TypeScript游戏场中工作的示例

  • 主要内容:数组声明,赋值给数组,多维数组,ReDim语句,数组方法我们都知道,一个变量是一个存储值的容器。 有时,开发人员希望一次可以在一个变量中保存多个值。 当一系列值存储在单个变量中时,则称为数组变量。 数组声明 数组声明的方式与声明变量相同,只是数组变量的声明使用括号。 在下面的例子中,括号里提到了数组的大小。参考以下示例 - 在上面代码中, 虽然数组大小被指定为,但是当数组索引从零开始时,它可以保持个值。 数组索引不能是负数。 VBScript数组可以在

  • 请编写一个名为lastElement的函数,该函数接受单个数组参数。函数应返回数组的最后一个元素(不删除该元素)。如果数组为空,则函数应返回null。 lastElement([3,5,7])//7 lastElement([1])//1 lastElement([])//null 我对最后一部分感到困惑,如果数组为空,函数将返回null。

  • 问题内容: 我想了解为什么下面的代码片段无法编译。将函数接受为可能具有任何返回类型的函数参数的Go方法是什么? 播放:https://play.golang.org/p/CqbuEZGy12 我的解决方案基于Volker的答案: 播放:https://play.golang.org/p/waOGBZZwN7 问题答案: 你绊倒了围棋新人一个非常普遍的误解:空接口并 不能 意味着“任何类型”。确实不

  • 将接受数组的函数改变为可变参数函数。 给定一个函数,返回一个闭包,将所有输入收集到一个接受函数的数组中。 const collectInto = fn => (...args) => fn(args); const Pall = collectInto(Promise.all.bind(Promise)); let p1 = Promise.resolve(1); let p2 = Promis

  • 我对编程和C++相当陌生。我有一个函数,我想接受以模板化值作为参数的函数指针。我的意思是... 我有这个功能: 我试过的: 结果: .h:165:22:注意:已忽略候选模板:无法将“function ,allocator >&)”与“void(*)(bool,std::vectorstd::vectorstd::allocatorstd::tuple &)”void postgrescaller: