避免在VBA中循环遍历数组?

时间:2016-11-25 18:01:20

标签: vba

我的目标是编写一个将回报转换为价格的函数。 我有一个存储在excel范围内的返回向量,如下所示:

r1
r2
...
rn

现在假设这些回报存储在B列中。 在VBA中编写了以下代码

Dim r As Range

Set r = ThisWorkbook.Sheets("Foglio1").Range("B2:B" & _
ThisWorkbook.Sheets("Foglio1").Range("B" & Rows.Count).End(xlUp).Row) 

Dim temp() As Variant   
temp = r

所以我成功地将值r1,r2,...,rn分配给我称为 temp 的数组。

现在如果我在R或MATLAB中,我会做以下事情,以便将回报转换为价格:

temp = cumprod(1 + temp)

使用一行命令我会将回报转换为价格

(1 + temp) 应该为数组的每个元素加1, cumprod 应该返回给我一个矢量与累积产品。

是否有可能实现相同的结果我被迫在VBA中使用循环?

非常感谢你的时间 周末很棒

3 个答案:

答案 0 :(得分:4)

是的,在VBA中直接执行此操作的唯一方法是使用循环。

也可以使用Excel工作表函数间接地在VBA中执行此操作,但实际上通常可以更快地将范围复制到VBA数组中,然后使用循环处理它。

您还可以编写(或查找和下载)具有可调用函数和子例程的库来隐藏循环,但它们仍在执行循环。

正如一条评论所说“学会爱循环”。这就是它在VBA中的运作方式。

具有讽刺意味的是,我认为实现这一目标的实际最快方法是添加一个新列,假设从Z2开始,其中Z2为=B2+1,其他所有行/单元格为Z * =(B*+1)*Z[*-1]

答案 1 :(得分:0)

你可以用SQL吗?

这适用于我的测试

Public Function PRODUCT_FUNCTION(strRange As String)

Dim c As ADODB.Connection
Dim r As ADODB.Recordset

strInputFile = ThisWorkbook.FullName
Set c = New ADODB.Connection

strConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & strInputFile & ";" & _
                            "Extended Properties=""Excel 12.0 Xml;HDR=No"";"

c.ConnectionString = strConnectionString
c.Open

strsql = "Select Exp(Sum(Log([F1]))) from [Sheet1$" & strRange & "]"

Set r = New ADODB.Recordset

r.Open strsql, c, 1

PRODUCT_FUNCTION = r.Fields(0).Value

r.Close
c.Close

Set r = Nothing
Set c = Nothing

End Function

答案 2 :(得分:0)

实际上有一种方法可以利用Range对象和PasteSpecial()方法的WorksheetFunction.Product()方法:

Function CumulativeDiscount(discountsRng As Range) As Double
    With discountsRng
        .Copy
        With .Offset(, .Parent.UsedRange.Columns.Count)
            .Value = 1
            .PasteSpecial , Operation:=xlPasteSpecialOperationAdd
            Application.CutCopyMode = False
            CumulativeDiscount = WorksheetFunction.Product(Application.Transpose(.Cells))
            .ClearContents
        End With
    End With
End Function

您可以在“主要”代码中使用如下:

Sub main()
    With ThisWorkbook.Sheets("Foglio1")
        MsgBox CumulativeDiscount(.Range("B2", .Cells(.Rows.Count, "B").End(xlUp)))
    End With
End Sub

唯一的限制是WorksheetFunction.Product()最多可接受30个参数,即要乘以的最大折扣数为30