下面的代码返回一个数组。我想在电子表格中使用它作为 Excel 公式来返回数组。但是,当我这样做时,它只将第一个值返回到单元格。无论如何,是否可以返回与数组大小相同的范围内的数组?
Function LoadNumbers(Low As Long, High As Long) As Long()
'''''''''''''''''''''''''''''''''''''''
' Returns an array of Longs, containing
' the numbers from Low to High. The
' number of elements in the returned
' array will vary depending on the
' values of Low and High.
''''''''''''''''''''''''''''''''''''''''
'''''''''''''''''''''''''''''''''''''''''
' Declare ResultArray as a dynamic array
' to be resized based on the values of
' Low and High.
'''''''''''''''''''''''''''''''''''''''''
Dim ResultArray() As Long
Dim Ndx As Long
Dim Val As Long
'''''''''''''''''''''''''''''''''''''''''
' Ensure Low <= High
'''''''''''''''''''''''''''''''''''''''''
If Low > High Then
Exit Function
End If
'''''''''''''''''''''''''''''''''''''''''
' Resize the array
'''''''''''''''''''''''''''''''''''''''''
ReDim ResultArray(1 To (High - Low + 1))
''''''''''''''''''''''''''''''''''''''''
' Fill the array with values.
''''''''''''''''''''''''''''''''''''''''
Val = Low
For Ndx = LBound(ResultArray) To UBound(ResultArray)
ResultArray(Ndx) = Val
Val = Val + 1
Next Ndx
''''''''''''''''''''''''''''''''''''''''
' Return the array.
''''''''''''''''''''''''''''''''''''''''
LoadNumbers = ResultArray()
End Function
UDF 当然可以返回一个数组,并且您的函数可以正常工作。只需选择范围 B2:D2,将
=LoadNumbers(1, 3)
放入公式栏中,然后按 Ctrl+Shift+Enter 告诉 Excel 这是一个数组函数。
现在,你不能让 UDF 根据其输入自动调整范围的大小 它是从 调用的(至少不是没有一些丑陋的
Application.OnTime
hack),但你无论如何都不需要这样做。只需将函数放在 1000 个单元格宽度的范围内,然后让 UDF 用空白单元格填充未使用的空间,如下所示:
Function LoadNumbers(ByVal Low As Long, ByVal High As Long) As Variant()
Dim ResultArray() As Variant
Dim Ndx As Long
Dim Val As Long
Dim SourceCols As Long
SourceCols = Application.Caller.Columns.Count
If Low > High Then
Exit Function
End If
If High - Low + 1 > SourceCols Then High = Low + SourceCols - 1
ReDim ResultArray(1 To SourceCols)
Val = Low
For Ndx = LBound(ResultArray) To (High - Low + 1)
ResultArray(Ndx) = Val
Val = Val + 1
Next Ndx
For Ndx = (High - Low + 2) To UBound(ResultArray)
ResultArray(Ndx) = vbNullString
Next Ndx
LoadNumbers = ResultArray()
End Function
工作表公式只能将值输出到写入公式的同一单元格。就目前情况而言,代码已经生成了一个数组。如果您希望在向下复制公式时显示值,请使用这样的公式(在您想要的任何单元格中),然后向下复制:
=INDEX(LoadNumbers(1,10),ROWS($A$1:$A1))
如果你复制太多,你会得到#REF!错误,因为 LoadNumbers 的数字用完了。
我一直在寻找类似的东西(在宏中创建一个函数,从工作表中获取输入,输出一个多维数组),我希望下面的用例有助于回答。如果没有,我很抱歉:
用例: 创建并应用众所周知的数值期权估值函数,并将股票价格、估值和收益输出为函数中指定的 #rows 的 3 维数组(3 列)(在本例中为 20,作为 NAS 变量)。代码被复制 - 但想法是将输出放入工作表中......
a) 这些输入在工作表中是静态的。 b)我通过我想要开始的输出单元格中的“fx”函数列表调用宏公式“optval”,并将起始输入放入公式中。 b) 输出将根据代码使用 20 行的 NAS 边界传播到单元格。微不足道,但有效。 c) 您可以自动执行此操作并将其输出到工作表 - 但无论如何,我希望这种方式有帮助。
模块功能如下(复制!) - 但只需将启动器输入放入即中即可 Vol=.2,Int 汇率 = 0.05,Strike=120,Exp = 1,P type = C(或 P),US?= N,即欧洲,,NAS=20(或者您想查看的任意行数,以及它影响数值方法的粒度)
Function optval(Vol, Intrate, Strike, Expn, Ptype, Etype, NAS)
ReDim S(0 To NAS) As Double
ReDim VOld(0 To NAS) As Double
ReDim VNew(0 To NAS) As Double
ReDim dummy(0 To NAS, 1 To 3)
dS = 2 * Strike / NAS
dt = 0.9 / NAS / NAS / Vol / Vol
NTS = Int(Expn / dt) + 1
dt = Expn / NTS
q = 1
If Ptype = "P" Then q = -1
For i = 0 To NAS
S(i) = i * dS
VOld(i) = Application.Max(q * (S(i) - Strike), 0)
dummy(i, 1) = S(i)
dummy(i, 2) = VOld(i) 'Payoff
Next i
For k = 1 To NTS
For i = 1 To NAS - 1
Delta = (VOld(i + 1) - VOld(i - 1)) / 2 / dS
Gamma = (VOld(i + 1) - 2 * VOld(i) + VOld(i - 1)) / dS / dS
Theta = -0.5 * Vol * Vol * S(i) * S(i) * Gamma - _
Intrate * S(i) * Delta + Intrate * VOld(i)
VNew(i) = VOld(i) - Theta * dt 'BSE
Next i
VNew(0) = VOld(0) * (1 - Intrate * dt) 'S=0
VNew(NAS) = 2 * VNew(NAS - 1) - VNew(NAS - 2) 'Infty
For i = 0 To NAS
VOld(i) = VNew(i)
Next i
If Etype = "Y" Then
For i = 0 To NAS
VOld(i) = Application.Max(VOld(i), dummy(i, 2))
Next i
End If
Next k
For i = 0 To NAS
dummy(i, 3) = VOld(i)
Next i
optval = dummy
End Function
=INDEX(LoadNumbers(1,10),ROWS($A$1:$A1),COLUMNS($B$1,B$1))
您可以添加一个参数作为输出的索引,类似于聚合函数中的键
Function LoadNumbers(Low As Long, High As Long, index As Integer) As Long()
Dim ResultArray() As Long
Dim Ndx As Long
Dim Val As Long
If Low > High Then
Exit Function
End If
ReDim ResultArray(1 To (High - Low + 1))
Val = Low
For Ndx = LBound(ResultArray) To UBound(ResultArray)
ResultArray(Ndx) = Val
Val = Val + 1
Next Ndx
LoadNumbers = ResultArray(index)
End Function