如何处理 UDF 中的全列范围?

How to handle full-column ranges in UDF?

我使用 Excel DNA 为 Excel 开发了一个插件。我声明了一个接受范围作为输入的 UDF,将 ExcelReference 转换为 Range 并使用 GetEnumerator 中的枚举器收集 List 中的所有单元格值以进行进一步处理和然后将输出写入另一个范围。

作为测试,我尝试将一整列传递给函数 (A:A),但一切都冻结了,因为枚举器在最后一个有值的单元格之后继续枚举空单元格。

有没有更快的方法来检测整列范围并获取其所有不为空的单元格?

目前我正在使用这段代码,但在上述情况下速度非常慢。

            Dim ue = inputRange.GetEnumerator    
            Dim L As New List(Of String)

            Do
                If ue.MoveNext Then
                    Dim c As Range = ue.Current
                    Dim V As String = c.FormulaLocal
                    If String.IsNullOrWhiteSpace(V) Then Continue Do
                    L.Add(V)
                Else
                    Exit Do
                End If
            Loop

我将使用以下解决方法,但我想从根本上防止这种情况。

            Dim ue = inputRange.GetEnumerator
            Dim counter as integer=0
            Dim L As New List(Of String)
            Do
                If counter>10 Then Exit Do
                If ue.MoveNext Then
                    Dim c As Range = ue.Current
                    Dim V As String = c.FormulaLocal
                    If String.IsNullOrWhiteSpace(V.Trim) Then
                        counter = counter + 1
                        Continue Do
                    End If
                    L.Add(V)
                Else
                    Exit Do
                End If
            Loop

一次性从 ExcelReference 获取所有值比获取 COM Range 对象要快得多。

从参数中删除 AllowReference=true(然后您将直接获取值)或从 ExcelReference:

中获取值
object value = inputRef.GetValue();

if (value is object[,])
{ 
    object[,] valueArr = (object[,])value;
    int rows = valueArr.GetLength(0);
    int cols = valueArr.GetLength(1);
    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < cols; j++)
        {    
            object val = valueArr[i,j];
            // Do more here...
        }
    }
}

如果单元格为空,您获得的对象将是 ExcelEmpty 类型。如果您对空单元格不感兴趣,可以忽略这些。

另一种方法是使用 C API 获取 sheet 的使用范围,并将其与 ExcelReference 相交。一个缺点是这需要将您的函数标记为 IsMacroType=true,这(与 AllowReference=true 一起)具有使您的函数易变的副作用。

此处显示如何执行此操作的代码:https://gist.github.com/govert/e66c5462901405dc96aab8e77abef24c