VBA 将多个数组作为参数或生成数组的 LO Calc 的 UDF

VBA UDF for LO Calc that takes several arrays as arguments or produces array

我很难找到如何为 LO Calc 编写简单 UDF(用户定义函数)的简单示例,它使用数组作为参数或给出数组作为输出,例如数组函数。

我需要一个简单的示例 UDF,它采用数组并给出单个数字作为输出,例如 count() 函数。

我需要一个简单的示例,其中 UDF 是数组函数,它采用两个数组并生成两个数组的笛卡尔积数组。

如果每一步都有评论就好了。

第一种情况的最简单 UDF 如下所示:

Function MyCount1(aSourceData As Variant) As Long 
Dim i As Long, j As Long    ' Loop variables for two dimensions of an array '
Dim iResult As Long     ' Temporary variable for counting non-empty values (counter) '
    iResult = 0         ' Init counter '
    For i = LBound(aSourceData,1) To UBound(aSourceData,1)      ' Loop row by row (first dimension) '
        For j = LBound(aSourceData,2) To UBound(aSourceData,2)  ' Loop cell by cell in current row (second dimension) '
            If Not IsEmpty(aSourceData(i,j)) Then iResult = iResult + 1 ' If the cell contains any value (not empty) - increase the counter '
        Next j
    Next i
    MyCount1 = iResult  ' Set counter as result of UDF '
End Function

如果您将单元格区域或值数组作为参数(=MYCOUNT1(A2:C10)=MYCOUNT1({1;2;3;4;5;;7;8}))传递给函数,这将正常工作

但是,如果您将参数列表留空 (=MYCOUNT1()),程序将因错误而停止

如果您指定的不是范围,而是一个单元格作为参数(=MYCOUNT1(B5)),则程序将停止并出现另一个错误

要避免此类错误,您可以使用此技巧

Function MyCount2(Optional aSourceData As Variant) As Variant
Rem Here param aSourceData is optional, can be skipped
Dim i As Long, j As Long, iResult As Long   ' Same as previous
    On Error GoTo wrongData ' On any error jump to the end of function
    iResult = 0
    For i = LBound(aSourceData,1) To UBound(aSourceData,1)
        For j = LBound(aSourceData,2) To UBound(aSourceData,2)
            If Not IsEmpty(aSourceData(i,j)) Then   ' Skip empty cells `
                If IsNumeric(aSourceData(i,j)) Then iResult = iResult + 1   ' Count numeric values only (skip texts) '
            EndIf 
        Next j
    Next i
    MyCount2 = iResult
    Exit Function 
wrongData:
    MyCount2 = "Wrong param"
End Function

对于 return 计数器值(数字)或消息文本(字符串)的函数,必须指定函数类型 As Variant

这个解决方案也不够好。例如,用户可能想处理二维以上的数组,但程序无法做到这一点。要涵盖所有用例,程序将不得不非常复杂。

将UDF的结果return作为数组,以任何方便的方式在函数内部形成它,return结果As Variant。请记住,一维数组将是一个字符串 - 它的值将出现在从左到右的 table 个单元格中:

Function MyCartesian(Optional aSourceA As Variant, Optional aSourceB As Variant) As Variant
Dim iA As Long, jA As Long  ' Loop by first array
Dim iB As Long, jB As Long  ' Loop by second array
Dim aResult As Variant, iLen As Long    ' Result array and count rows (height of array)
    On Error GoTo wrongData ' On any error jump to the end of function
    iLen = (UBound(aSourceA,1)-LBound(aSourceA,1)+1) * _
        (UBound(aSourceA,2)-LBound(aSourceA,2)+1) * _
        (UBound(aSourceB,1)-LBound(aSourceB,1)+1) * _
        (UBound(aSourceB,2)-LBound(aSourceB,2)+1)
Rem Create result array
    ReDim aResult(1 To iLen, 1 To 2)
    iLen = 0
Rem Loop by each element of first array:
    For iA = LBound(aSourceA,1) To UBound(aSourceA,1)   
        For jA = LBound(aSourceA,2) To UBound(aSourceA,2)
Rem Loop by each element of second array:
            For iB = LBound(aSourceB,1) To UBound(aSourceB,1)
                For jB = LBound(aSourceB,2) To UBound(aSourceB,2)
Rem Fill result array
                    iLen = iLen + 1
                    aResult(iLen, 1) = aSourceA(iA,jA)
                    aResult(iLen, 2) = aSourceB(iB,jB)
                Next jB
            Next iB
        Next jA
    Next iA
    MyCartesian = aResult
    Exit Function 
wrongData:
    MyCartesian = "Wrong param"
End Function

在单元格中输入类似=MYCARTESIAN(A2:C10; F2:G6)的内容,按Ctrl+Shift+Enter并得到一个数组