在Libreoffice Basic中以数组形式存储日期

时间:2016-01-28 17:59:36

标签: arrays date macros libreoffice basic

在过去的几天里,我一直在研究这个问题而没有找到答案。我有一个交易列表,我从中过滤了一个子集。对于子集,我将日期和数量存储在数组中,以便在XIRR计算中使用。

输入列使用' IsDate'进行测试。并被发现是真的。此外,我使用ReDim Preserve(0到n)作为日期'存储日期时。但是,在测试结果时,数组不包含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函数的问题。我试图通过创建一个新的数组作为日期,并从arrDates复制到新的数据来克服这个问题。但没有运气,再次双打......

任何帮助都将不胜感激。

2 个答案:

答案 0 :(得分:0)

作为解决方法,创建一个名为“TempSheet”的工作表。它可以隐藏,因为它只用于临时处理。

在FundXIRRTotal中,将arrDates写入TempSheet列A.然后将该单元格范围传递给oFA.callFunction()

下面是我用来测试这个概念的工作代码。将“C1:C3”更改为TempSheet上包含arrDates内容的范围,例如"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

注意:我推荐我的另一个答案,而不是这个答案。

答案 1 :(得分:0)

数字的日期。 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,但这似乎不起作用。