VBA:从每日价值计算月度回报

时间:2015-05-17 21:24:16

标签: excel vba excel-vba

我有两列,日期和每日回报。我每天有7000左右的回报,我希望按每年每个月的复合回报对它们进行分组。

我创建了一个VBA函数来解决这个问题:

Function MonthlyRet(YearNum, MonthNum, DateData, RetData) As Double
Dim nValues As Integer
nValues = DateData.Rows.Count

MonthlyRet = 1
For i = 2 To nValues
    If (IsNumeric(RetData(i)) And Year(DateData(i)) = YearNum And Month(DateData(i)) = MonthNum) Then
        MonthlyRet = MonthlyRet * RetData(i)
    End If
Next i
End Function

我可以使用以下方法在我的数据上运行:

=MonthlyRet(2015,1,Data!$A$1:$A$7000,Data!$AR$1:$AR$7000)-1

这将在我的数据集中返回2015年1月的复合回报。然而,这似乎有效,当我将方程复制并粘贴到1990年至2015年的所有月份,大约300个单元时,在快速计算机上完成操作需要相当长的时间。

该算法通过7000条if语句循环300次。这对我来说似乎不是那么多迭代,但我的计算机将需要一两分钟来计算它们。在java中,我知道结果将是毫秒,但我是VBA新手。

有没有办法在VBA中提高此例程的性能?

2 个答案:

答案 0 :(得分:0)

有很多方法可以提高性能。你有什么限制?

选项1:坚持使用VBA UDF

如果您只想提高UDF的VBA性能,我认为您无法做到。这些变化可能会有所帮助:

Function MonthlyRet(YearNum, MonthNum, DateData, RetData) As Double
   Dim nValues As Integer, i as Integer:nValues = DateData.Rows.Count:MonthlyRet = 1
   For i = 2 To nValues
     If (IsNumeric(RetData(i)) And Year(DateData(i)) = YearNum And Month(DateData(i)) = MonthNum) Then MonthlyRet = MonthlyRet * RetData(i)
   Next i
End Function

我写了一篇关于提高VBA表现的帖子here

选项2:基于Excel XLL UDF的功能

Excel XLL将为您的UDF功能启用多线程。一个很好的视频: 点击此处:https://www.youtube.com/watch?v=L2ALSgK1LLY

选项3:编写VBA宏并手动运行而不是使用UDF函数

我个人会将此选项作为(a)使用它可以让您更好地控制函数何时刷新并防止“冻结Excel”和(b)这将比单独的UDF函数运行稍快一些。

答案 1 :(得分:0)

正如我上面所写,当使用VBA查看大范围时,最好将该范围读入数组,然后通过数组。修改你的UDF;并且明确声明所有变量和数据类型 - 在VBA中总是一件好事,我们最终得到:

Option Explicit
Function MonthlyRet(YearNum As Long, MonthNum As Long, DateData As Range, RetData As Range) As Double
Dim vDates As Variant, vReturns As Variant
Dim I As Long
Dim D As Double

vDates = DateData
vReturns = RetData

D = 1
For I = 2 To UBound(vDates, 1)
    If (IsDate(vDates(I, 1)) And Year(vDates(I, 1)) = YearNum And Month(vDates(I, 1)) = MonthNum) Then
        D = D * vReturns(I, 1)
    End If
Next I
MonthlyRet = D
End Function

但是,我建议您查看数据透视表。在我看来,这对于显示您的数据是理想的。例如,您可以将日期拖动到行区域;将数据返回到列区域;将值字段设置更改为产品;然后按月和年对行进行分组 - 最后会找到一个可以显示相同结果的漂亮表格。

顺便说一句,我不确定你的算法会返回你期望的值。一旦你对它进行了排序,不确定是否更容易使用Pivot或UDF。