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.Count
和 i = x.Columns.Count
似乎都毫无意义。从未使用过i
的那些值。那应该做什么?也许您要初始化的是变量rows
和cols
(而不是i
)。事实上,rows
和 cols
都不会从它们的默认值 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 中粘贴表格然后将表格转换为文本?