我使用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
答案 0 :(得分:1)
从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获取工作表的使用范围,并将其与ExcelReference
相交。一个缺点是,这需要将您的函数标记为IsMacroType=true
,其中(与AllowReference=true
一起)会产生使函数变得不稳定的副作用。
显示如何执行此操作的代码位于:https://gist.github.com/govert/e66c5462901405dc96aab8e77abef24c