Excel VBA函数:如何传递范围、转换为数组、反转和返回数组

Posted

技术标签:

【中文标题】Excel VBA函数:如何传递范围、转换为数组、反转和返回数组【英文标题】:Excel VBA function: How to pass range, convert to array, reverse, and return array 【发布时间】:2016-10-11 04:03:05 【问题描述】:

我正在尝试在 Excel 中进行一些数组数学运算,这需要我多次反转多个一维范围,因此我想为其编写一个函数,而不是在电子表格中创建反转。

我在 VBA 中编写了一个 reverse() 函数,但它返回 #VALUE!电子表格中的错误。无论数组大小如何,无论是输入相同大小的数组函数还是使用 SUM() 之类的汇总函数,都会发生这种情况。我验证了反转逻辑作为子工作。这让我相信问题在于传递/返回范围/数组,但我不明白出了什么问题。

Function reverse(x As Range) As Variant()
' Array formula that reverses a one-dimensional array (1 row, x columns)
    Dim oldArray() As Variant, newArray() As Variant
    Dim rows As Long: i = x.rows.Count
    Dim cols  As Long: i = x.Columns.Count
    ReDim oldArray(1 To rows, 1 To cols), newArray(1 To rows, 1 To cols)

    oldArray = x.Value
    newArray = oldArray

    For i = 1 To cols / 2 Step 1
        newArray(1, i) = oldArray(1, cols - i + 1)
        newArray(1, cols - i + 1) = oldArray(1, i)
    Next

    reverse = newArray
End Function

请记住,我可以将它扩展到反向二维数组,但这是微不足道的部分。我的问题只是试图确保函数在 (1, N) 范围内工作。

谢谢!

【问题讨论】:

i = x.rows.Counti = x.Columns.Count 似乎都毫无意义。从未使用过i 的那些值。那应该做什么?也许您要初始化的是变量rowscols(而不是i)。事实上,rowscols 都不会从它们的默认值 0 移动。 哇!这是我的疏忽。现在可以了。谢谢约翰。 【参考方案1】:

找到下面的代码......

Function reverse(x As Range) As Variant()
' Array formula that reverses a one-dimensional array (1 row, x columns)
    Dim oldArray() As Variant, newArray() As Variant
    Dim rows As Long
    rows = x.rows.Count
    Dim cols  As Long
    cols = x.Columns.Count
    ReDim oldArray(1 To rows, 1 To cols), newArray(1 To rows, 1 To cols)

    oldArray = x.Value
    newArray = oldArray

    For i = 1 To cols / 2 Step 1
        newArray(1, i) = oldArray(1, cols - i + 1)
        newArray(1, cols - i + 1) = oldArray(1, i)
    Next
reverse = newArray
End Function

【讨论】:

再次感谢,我现在看到我在设置 i 时的错误应该是行/列。好尴尬【参考方案2】:

下面的代码更加通用,它使用可选参数来确定是否应该反转行、列或两者(或不)。默认情况下,它将反转列。

Function ReverseRange(Source As Range, Optional ReverseRows As Boolean = False, Optional ReverseColumns As Boolean = True) As Variant()
    Dim SourceArray() As Variant
    Dim DestArray() As Variant
    SourceArray = Source.value

    Dim nRows As Long, nColumns As Long
    nRows = UBound(SourceArray, 1)
    nColumns = UBound(SourceArray, 2)
    ReDim DestArray(1 To nRows, 1 To nColumns)

    Dim r As Long, r2 As Long, c As Long, c2 As Long
    For r = 1 To nRows
        r2 = IIf(ReverseRows, nRows - r + 1, r)
        For c = 1 To nColumns
            c2 = IIf(ReverseColumns, nColumns - c + 1, c)
            DestArray(r2, c2) = SourceArray(r, c)
        Next c
    Next r
    ReverseRange = DestArray
End Function

请注意,范围有效性没有验证。

【讨论】:

谢谢,这显然不能帮助我发现错误,但可以节省将函数扩展到二维数组的时间。 我不知道为什么,但是如果传递的范围的长度 = 1,您或我的都不起作用。这是一个微不足道的情况,但它不应该返回相同的值吗? 如前所述,我的代码不会对范围有效性进行验证。如果范围只有一个单元格,source.Value 不会返回数组,您将收到错误 13“类型不匹配”。如果范围不连续,代码也可能会失败,并且可能在其他情况下。【参考方案3】:

无论行数如何,这都会反转范围内的列。

Function reverse(Source As Range) As Variant()
    Dim Data, RevData
    Dim x As Long, y As Long, y1 As Long

    Data = Source.Value

    ReDim RevData(1 to UBound(Data, 1),1 to UBound(Data, 2))

    For x = 1 To UBound(Data, 1)
        y1 = UBound(Data, 2)
        For y = 1 To UBound(Data, 2)
            RevData(x, y1) = Data(x, y)
            y1 = y1 - 1
        Next
    Next
    reverse = RevData
End Function

【讨论】:

以上是关于Excel VBA函数:如何传递范围、转换为数组、反转和返回数组的主要内容,如果未能解决你的问题,请参考以下文章

在 Excel 中使用 VBA,如何在 Outlook 中粘贴表格然后将表格转换为文本?

返回数组Excel VBA中元素的索引

如何将 Excel 数组公式传递给 VBA UDF?

Excel VBA - 将参数参数传递给 Sub

Excel VBA:将变体数组返回到选定范围时需要 255 转置字符限制的解决方法

excel vba 数组中第1位字符为0,赋给单元格时如何将0保留?