在 Libreoffice Basic 中将日期存储在数组中
Storing dates in an array in Libreoffice Basic
最近几天我一直在研究这个问题,但没有找到答案。我有一个交易列表,我从中过滤了一个子集。对于子集,我将日期和金额存储在数组中,以用于 XIRR 计算。
输入列用'IsDate'测试,发现为True。此外,我在存储日期时使用 'ReDim Preserve (0 to n) As Date'。但是,在测试结果时,数组中包含的不是Dates而是Doubles。
请参考以下代码
Function FundXIRRTotal(ByVal FundISIN As String, ByVal KiesDatum As Date) As Double
Dim wshT As Object
Dim wshS As Object
Dim wshP As Object
Dim wsh As Object
Dim LastRow As Long
Dim i As Long
Dim NumberOfTrans As Long
Dim Guess As Double
Dim arrValues() As Double
Dim arrDates() As Date
Dim oFA As Object
Set wshT = ThisComponent.Sheets.getByName("Transacties")
Set wshP = ThisComponent.Sheets.getByName("Portefeuille")
Set wshS = ThisComponent.Sheets.getByName("Instellingen")
'Find Last Used Row
wsh = wshT.createCursor
wsh.gotoEndOfUsedArea( False )
LastRow = wsh.getRangeAddress().EndRow
NumberOfTrans = 0
'Create Transaction Array
For i = 1 To LastRow
If wshT.getCellByPosition(3, i).String = FundISIN And CDate(wshT.getCellByPosition(0, i).Value) <= KiesDatum Then
ReDim Preserve arrValues(0 To NumberOfTrans) As Double
ReDim Preserve arrDates(0 To NumberOfTrans) As Date
arrDates(NumberOfTrans) = CDate(wshT.getCellByPosition(0, i).Value)
If wshT.getCellByPosition(1, i).String = wshS.getCellRangeByName("FundBuy").String Then
arrValues(NumberOfTrans) = -CDbl(wshT.getCellByPosition(9, i).Value / wshT.getCellByPosition(10, i).Value)
End If
If wshT.getCellByPosition(1, i).String = wshS.getCellRangeByName("FundSell").String Then
arrValues(NumberOfTrans) = CDbl(wshT.getCellByPosition(9, i).Value / wshT.getCellByPosition(10, i).Value)
End If
If wshT.getCellByPosition(1, i).String = wshS.getCellRangeByName("FundDeposit").String Then
arrValues(NumberOfTrans) = CDbl(wshT.getCellByPosition(9, i).Value / wshT.getCellByPosition(10, i).Value)
End If
If wshT.getCellByPosition(1, i).String = wshS.getCellRangeByName("FundDivCash").String Then
arrValues(NumberOfTrans) = CDbl(wshT.getCellByPosition(9, i).Value / wshT.getCellByPosition(10, i).Value)
End If
If wshT.getCellByPosition(1, i).String = wshS.getCellRangeByName("FundDivShares").String Then
arrValues(NumberOfTrans) = CDbl(wshT.getCellByPosition(9, i).Value / wshT.getCellByPosition(10, i).Value)
End If
If wshT.getCellByPosition(1, i).String = wshS.getCellRangeByName("FundSplit").String Then
arrValues(NumberOfTrans) = -CDbl(wshT.getCellByPosition(9, i).Value / wshT.getCellByPosition(10, i).Value)
End If
If wshT.getCellByPosition(1, i).String = wshS.getCellRangeByName("FundFee").String Then
arrValues(NumberOfTrans) = -CDbl(wshT.getCellByPosition(9, i).Value / wshT.getCellByPosition(10, i).Value)
End If
If wshT.getCellByPosition(1, i).String = wshS.getCellRangeByName("FundWarUit").String Then
arrValues(NumberOfTrans) = -CDbl(wshT.getCellByPosition(9, i).Value / wshT.getCellByPosition(10, i).Value)
End If
NumberOfTrans = NumberOfTrans + 1
End If
Next i
'Add current value to Array
'NumberOfTrans = NumberOfTrans + 1
ReDim Preserve arrValues(0 To NumberOfTrans) As Double
ReDim Preserve arrDates(0 To NumberOfTrans) As Date
arrValues(NumberOfTrans) = CDbl(Waarde(FundISIN, KiesDatum))
arrDates(NumberOfTrans) = CDate(KiesDatum)
If Portfolio(FundISIN, KiesDatum) = 0 Then
FundXIRRTotal = 0
Exit Function
End If
'Calculate XIRR
oFA = createUNOService("com.sun.star.sheet.FunctionAccess")
FundXIRRTotal = oFA.callFunction("XIRR", Array(arrValues()), Array(arrDates()))
End Function
我知道 Array 函数存在数据类型丢失的问题。我试图通过创建一个新的 Array As Date 并将其从 arrDates 复制到新数组来克服这个问题。但是运气不好,又翻倍了...
如有任何帮助,我们将不胜感激。
作为解决方法,创建一个名为 "TempSheet" 的 sheet。它可以隐藏,因为它只是用于临时处理。
在 FundXIRRTotal 中,将 arrDates
写入 TempSheet 列 A。然后将该单元格范围传递给 oFA.callFunction()
。
下面是我用来测试这个概念的工作代码。将 "C1:C3" 更改为包含 arrDates
内容的 TempSheet 上的范围,例如 "TempSheet.A1:A" & Ubound(arrDates)
.
Function FundXIRRTotal(ByVal FundISIN As String, ByVal KiesDatum As Date) As Double
Dim wshT As Object
Dim i As Long
Dim arrValues(2, 0) As Double
Dim arrDates(2, 0) As Date
Dim args as Array
Dim oFA As Object
Set wshT = ThisComponent.Sheets.getByName("Transacties")
For i = 0 To 2
arrDates(i, 0) = wshT.getCellByPosition(2, i).Value
arrValues(i, 0) = wshT.getCellByPosition(3, i).Value
Next i
oFA = createUNOService("com.sun.star.sheet.FunctionAccess")
args = Array(arrValues, wshT.getCellRangeByName("C1:C3"))
FundXIRRTotal = oFA.callFunction("XIRR", args)
End Function
注意:我推荐我的另一个答案而不是这个。
数字是日期。 UNO FunctionAccess
调用将不接受 OpenOffice Basic Date
类型,而是需要数字类型。
这是工作示例代码:
Function FundXIRRTotal(ByVal FundISIN As String, ByVal KiesDatum As Date) As Variant
Dim wshT As Object
Dim i As Long
Dim arrValues(0, 2) As Double
Dim unoDates(0, 2) As Double
Dim theDate As Double
Dim oFA As Object
Dim args(2) As Variant
Dim result As Variant
Set wshT = ThisComponent.Sheets.getByName("Transacties")
For i = 0 To 2
arrValues(0, i) = wshT.getCellByPosition(3, i).Value
'The date value will be a number, for example 42020 for 2015-01-16.
theDate = wshT.getCellByPosition(2, i).Value
unoDates(0, i) = theDate
Next i
oFA = createUNOService("com.sun.star.sheet.FunctionAccess")
args = Array(arrValues, unoDates)
result = oFA.callFunction("XIRR", args)
FundXIRRTotal = result
End Function
另见 https://forum.openoffice.org/en/forum/viewtopic.php?f=20&t=67996。
顺便说一句,我也尝试过使用 com.sun.star.util.Date,但似乎没有用。
最近几天我一直在研究这个问题,但没有找到答案。我有一个交易列表,我从中过滤了一个子集。对于子集,我将日期和金额存储在数组中,以用于 XIRR 计算。
输入列用'IsDate'测试,发现为True。此外,我在存储日期时使用 'ReDim Preserve (0 to n) As Date'。但是,在测试结果时,数组中包含的不是Dates而是Doubles。
请参考以下代码
Function FundXIRRTotal(ByVal FundISIN As String, ByVal KiesDatum As Date) As Double
Dim wshT As Object
Dim wshS As Object
Dim wshP As Object
Dim wsh As Object
Dim LastRow As Long
Dim i As Long
Dim NumberOfTrans As Long
Dim Guess As Double
Dim arrValues() As Double
Dim arrDates() As Date
Dim oFA As Object
Set wshT = ThisComponent.Sheets.getByName("Transacties")
Set wshP = ThisComponent.Sheets.getByName("Portefeuille")
Set wshS = ThisComponent.Sheets.getByName("Instellingen")
'Find Last Used Row
wsh = wshT.createCursor
wsh.gotoEndOfUsedArea( False )
LastRow = wsh.getRangeAddress().EndRow
NumberOfTrans = 0
'Create Transaction Array
For i = 1 To LastRow
If wshT.getCellByPosition(3, i).String = FundISIN And CDate(wshT.getCellByPosition(0, i).Value) <= KiesDatum Then
ReDim Preserve arrValues(0 To NumberOfTrans) As Double
ReDim Preserve arrDates(0 To NumberOfTrans) As Date
arrDates(NumberOfTrans) = CDate(wshT.getCellByPosition(0, i).Value)
If wshT.getCellByPosition(1, i).String = wshS.getCellRangeByName("FundBuy").String Then
arrValues(NumberOfTrans) = -CDbl(wshT.getCellByPosition(9, i).Value / wshT.getCellByPosition(10, i).Value)
End If
If wshT.getCellByPosition(1, i).String = wshS.getCellRangeByName("FundSell").String Then
arrValues(NumberOfTrans) = CDbl(wshT.getCellByPosition(9, i).Value / wshT.getCellByPosition(10, i).Value)
End If
If wshT.getCellByPosition(1, i).String = wshS.getCellRangeByName("FundDeposit").String Then
arrValues(NumberOfTrans) = CDbl(wshT.getCellByPosition(9, i).Value / wshT.getCellByPosition(10, i).Value)
End If
If wshT.getCellByPosition(1, i).String = wshS.getCellRangeByName("FundDivCash").String Then
arrValues(NumberOfTrans) = CDbl(wshT.getCellByPosition(9, i).Value / wshT.getCellByPosition(10, i).Value)
End If
If wshT.getCellByPosition(1, i).String = wshS.getCellRangeByName("FundDivShares").String Then
arrValues(NumberOfTrans) = CDbl(wshT.getCellByPosition(9, i).Value / wshT.getCellByPosition(10, i).Value)
End If
If wshT.getCellByPosition(1, i).String = wshS.getCellRangeByName("FundSplit").String Then
arrValues(NumberOfTrans) = -CDbl(wshT.getCellByPosition(9, i).Value / wshT.getCellByPosition(10, i).Value)
End If
If wshT.getCellByPosition(1, i).String = wshS.getCellRangeByName("FundFee").String Then
arrValues(NumberOfTrans) = -CDbl(wshT.getCellByPosition(9, i).Value / wshT.getCellByPosition(10, i).Value)
End If
If wshT.getCellByPosition(1, i).String = wshS.getCellRangeByName("FundWarUit").String Then
arrValues(NumberOfTrans) = -CDbl(wshT.getCellByPosition(9, i).Value / wshT.getCellByPosition(10, i).Value)
End If
NumberOfTrans = NumberOfTrans + 1
End If
Next i
'Add current value to Array
'NumberOfTrans = NumberOfTrans + 1
ReDim Preserve arrValues(0 To NumberOfTrans) As Double
ReDim Preserve arrDates(0 To NumberOfTrans) As Date
arrValues(NumberOfTrans) = CDbl(Waarde(FundISIN, KiesDatum))
arrDates(NumberOfTrans) = CDate(KiesDatum)
If Portfolio(FundISIN, KiesDatum) = 0 Then
FundXIRRTotal = 0
Exit Function
End If
'Calculate XIRR
oFA = createUNOService("com.sun.star.sheet.FunctionAccess")
FundXIRRTotal = oFA.callFunction("XIRR", Array(arrValues()), Array(arrDates()))
End Function
我知道 Array 函数存在数据类型丢失的问题。我试图通过创建一个新的 Array As Date 并将其从 arrDates 复制到新数组来克服这个问题。但是运气不好,又翻倍了...
如有任何帮助,我们将不胜感激。
作为解决方法,创建一个名为 "TempSheet" 的 sheet。它可以隐藏,因为它只是用于临时处理。
在 FundXIRRTotal 中,将 arrDates
写入 TempSheet 列 A。然后将该单元格范围传递给 oFA.callFunction()
。
下面是我用来测试这个概念的工作代码。将 "C1:C3" 更改为包含 arrDates
内容的 TempSheet 上的范围,例如 "TempSheet.A1:A" & Ubound(arrDates)
.
Function FundXIRRTotal(ByVal FundISIN As String, ByVal KiesDatum As Date) As Double
Dim wshT As Object
Dim i As Long
Dim arrValues(2, 0) As Double
Dim arrDates(2, 0) As Date
Dim args as Array
Dim oFA As Object
Set wshT = ThisComponent.Sheets.getByName("Transacties")
For i = 0 To 2
arrDates(i, 0) = wshT.getCellByPosition(2, i).Value
arrValues(i, 0) = wshT.getCellByPosition(3, i).Value
Next i
oFA = createUNOService("com.sun.star.sheet.FunctionAccess")
args = Array(arrValues, wshT.getCellRangeByName("C1:C3"))
FundXIRRTotal = oFA.callFunction("XIRR", args)
End Function
注意:我推荐我的另一个答案而不是这个。
数字是日期。 UNO FunctionAccess
调用将不接受 OpenOffice Basic Date
类型,而是需要数字类型。
这是工作示例代码:
Function FundXIRRTotal(ByVal FundISIN As String, ByVal KiesDatum As Date) As Variant
Dim wshT As Object
Dim i As Long
Dim arrValues(0, 2) As Double
Dim unoDates(0, 2) As Double
Dim theDate As Double
Dim oFA As Object
Dim args(2) As Variant
Dim result As Variant
Set wshT = ThisComponent.Sheets.getByName("Transacties")
For i = 0 To 2
arrValues(0, i) = wshT.getCellByPosition(3, i).Value
'The date value will be a number, for example 42020 for 2015-01-16.
theDate = wshT.getCellByPosition(2, i).Value
unoDates(0, i) = theDate
Next i
oFA = createUNOService("com.sun.star.sheet.FunctionAccess")
args = Array(arrValues, unoDates)
result = oFA.callFunction("XIRR", args)
FundXIRRTotal = result
End Function
另见 https://forum.openoffice.org/en/forum/viewtopic.php?f=20&t=67996。
顺便说一句,我也尝试过使用 com.sun.star.util.Date,但似乎没有用。