2016-06-19 66 views
1

我使用Excel DNA爲Excel開發了一個插件。我聲明一個接受範圍作爲輸入的UDF,將ExcelReference轉換爲Range並使用GetEnumerator的枚舉器收集List中的所有單元格值以進行進一步處理,然後將輸出寫入另一個範圍。如何處理UDF中的全列範圍?

作爲一個測試,我試着將整列傳遞給函數(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 

回答

1

這將是不是得到一個COM對象Range更快獲得從ExcelReference一氣呵成所有的值。

無論是從參數中刪除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

+0

再次感謝!我用那個Gist來升級我的函數:我已經在使用'IsMacroType'和'AllowReference',這樣代碼就完全適合了! :d – beppe9000