2012-07-20 57 views
1

我對excel vba相當陌生,似乎無法用vbArrays解決這個問題。我創建了vba中的函數cumsum,只是爲了讓我的生活更輕鬆。不過,我想讓代碼更加靈活,以便我可以從函數和範圍中傳遞兩種變體。在我的代碼中,當我添加了vec = vec.value這一行時,如果我傳入了一個範圍,它可以很好地工作,但如果我希望它在我調用該函數並傳入非範圍類型。我注意到的是,如果我的代碼中沒有vec = vec.value行,並且我傳入一個範圍,它的維數爲0,我通過編寫自己的函數進行檢查。有人可以向我解釋我如何解決這個問題?謝謝。vba variant array bug

Public Function cumsum(vec As Variant) As Variant 
    Dim temp() As Variant 
    MsgBox (getDimension(vec)) 
    'works if i use vec=vec.value if vec is a range but has 0 if i do not vec = vec.values 
    ReDim temp(LBound(vec, 1) To UBound(vec, 1), 1 To 1) As Variant 
    Dim intCounter As Integer 
    For intCounter = LBound(vec) To UBound(vec) 
     If intCounter = LBound(vec) Then 
      temp(intCounter, 1) = vec(intCounter, 1) 
     Else 
      temp(intCounter, 1) = temp(intCounter - 1, 1) + vec(intCounter, 1) 
     End If 
    Next 
    cumsum = temp() 
End Function 
Function getDimension(var As Variant) As Integer 
On Error GoTo Err: 
    Dim i As Integer 
    Dim tmp As Integer 
    i = 0 
    Do While True: 
     i = i + 1 
     tmp = UBound(var, i) 
    Loop 
Err: 
    getDimension = i - 1 
End Function 

回答

1

來自@Jake和@chris的答案暗示了正確的方向,但我認爲它們遠遠不夠。

如果你是絕對相信你會永遠只能調用這個例程的UDF(即從你的工作表中公式),那麼你真正需要做的是這樣的補充:

If IsObject(vec) Then 
    Debug.Assert TypeOf vec Is Range 

    vec = vec.Value2 
End If 

到你的功能開始。作爲一個UDF被調用,它唯一應該通過的對象類型是Range。另外,作爲一個UDF,你可以依靠這樣一個事實,任何通過的數組都將從1開始索引。

我可以挑出其他問題與你的例程,但他們會離你的原始點題。簡而言之:這隻適用於列向量,對於單元格範圍將失效等。

請注意,您的getDimension函數爲Range返回零的原因是因爲UBound在此範圍上窒息。您的錯誤處理程序會愉快地捕捉到一個錯誤(類型不匹配),您並不是真正期望得到並返回零。 (找到「維度」的方法是假設錯誤將是下標超出範圍的錯誤。)

我寫了一段回答,回想一下爲什麼在使用Excel時,我不認爲一般的getDimension方法是一個很好的一個:

https://stackoverflow.com/a/6904433/58845

最後,VarType的問題是,當通過具有默認屬性的對象,它實際上將返回屬性的類型。所以VarType(<range>)會告訴你範圍內的東西的類型,而不是對象的代碼,因爲Range有一個默認屬性,Range.Value

2

你爲什麼不只是使用VarTypeTypeName然後vec

Public Function cumsum2(vec As Variant) As Variant 
    MsgBox TypeName(vec) 
    MsgBox VarType(vec) 

    cumsum2 = 0 
End Function 
+0

我試過了。當你對範圍進行vartype時,它仍然認爲它是一個vbarray,對於變體也一樣 – Andrew 2012-07-20 16:35:22

+0

當你使用TypeName時會發生什麼? – Jake 2012-07-20 16:38:36

+0

兩者都是長類型 – Andrew 2012-07-20 16:57:18

0

進行必要的操作修改檢查vec數據類型的getDimension包括

If TypeName(var) = "Range" Then 
    var = var.Value 
End If