操作没有循环的数组

时间:2015-08-28 14:01:55

标签: excel excel-vba vba

学习VBA for Excel,我试图在不使用循环的情况下完成我的编码。作为练习,将两个相邻范围的数字相乘,我想出了这个:

Sub multiply_range()

Dim a, b, c As Range
Set a = Range("a1:a5")
Set b = Range("b1:b5")
Set c = Range("c1:c5")

a.Value = Evaluate("row(" & a.Address & ")")
b.Value = Evaluate("row(" & b.Address & ")")
c.Value = Evaluate(a.Address & "*" & b.Address)

End Sub

哪个效果很好。现在我想做类似的事情,但改为使用数组。从这段代码开始:

Sub multiply_array()

Dim aArr(), bArr(), cArr()
ReDim aArr(5), bArr(5), cArr(5)

For i = 0 To 4
    aArr(i) = i + 1
    bArr(i) = i + 1
Next

For i = 0 To 4
    cArr(i) = aArr(i) * bArr(i)
Next

For i = 0 To 4
    Range("D" & i + 1).Value = cArr(i)
Next

End Sub

如何使用不使用循环的代码替换这些FOR循环中的任何一个?

3 个答案:

答案 0 :(得分:7)

你走了:

ynn = withColumn(yn, "balance", yn[[3]] - yn[[2]])

<强>更新

这是一个不使用循环且没有范围的变体:

Sub Squares()
    Dim n&
    n = 5
    [d1].Resize(n) = Evaluate("row(1:" & n & ")^2")
End Sub

答案 1 :(得分:3)

对于乘以任意数组,您可以尝试在新模块中粘贴此代码:

Dim X, Y

Sub MultiplyArrays()
Dim Z
X = Array(1, 2, 3, 4, 5)
Y = Array(1, 2, 3, 4, 5)
Z = [GetX()*GetY()]
Range("D1").Resize(UBound(Z)) = Application.Transpose(Z)   
End Sub

Function GetX()
GetX = X
End Function

Function GetY()
GetY = Y
End Function

另一种稍微棘手的方法是使用工作表函数方法:

Sub MultiplyArrays2()
Dim X, Y, Z
X = Array(1, 2, 3, 4, 5)
Y = Array(1, 2, 3, 4, 5)
With Application
    Z = .PV(, 1, .PV(, X, Y))
    Range("D1").Resize(UBound(Z)) = .Transpose(Z)
End With
End Sub

另见:Adding or multiplying variants in VBA

答案 2 :(得分:1)

您可以创建一些受函数式编程启发的辅助函数。您可以将它们存储在模块中(与其他用于操作数组的函数一起)并根据需要导入它们。

Function Map(f As String, A As Variant) As Variant
    'assumes that A is a 1-dimensional variant array
    'and f is the name of a function that can be applied to it

    Dim i As Long
    Dim M As Variant

    ReDim M(LBound(A) To UBound(A))
    For i = LBound(A) To UBound(A)
        M(i) = Application.Run(f, A(i))
    Next i
    Map = M
End Function

Function ZipWith(f As String, A As Variant, B As Variant)
    'assumes that A,B are 1-dimensional variant arrays with the same bounds
    'and f is the name of a function with two variables
    Dim i As Long
    Dim M As Variant

    ReDim M(LBound(A) To UBound(A))
    For i = LBound(A) To UBound(A)
        Select Case f:
            Case "+":
                M(i) = A(i) + B(i)
            Case "-":
                M(i) = A(i) - B(i)
            Case "*":
                M(i) = A(i) * B(i)
            Case "/":
                M(i) = A(i) / B(i)
            Case "&":
                M(i) = A(i) & B(i)
            Case "^":
                M(i) = A(i) ^ B(i)
            Case Else:
                M(i) = Application.Run(f, A(i), B(i))
        End Select
    Next i
    ZipWith = M
End Function

如此测试:

Function square(x As Variant) As Variant
    square = x * x
End Function

Sub test()
    Dim A As Variant, B As Variant, squares As Variant, products As Variant

    A = Array(2, 3, 4)
    B = Array(5, 6, 7)

    squares = Map("square", A)
    products = ZipWith("*", A, B)

    Debug.Print Join(squares, " ")
    Debug.Print Join(products, " ")
End Sub

注意测试子中没有循环。输出符合预期:

4 9 16
10 18 28