2015-05-18 159 views
2
龍陣列式

假設我們有A1保存在細胞一些長式:VBA - 經由Application.Evaluate

=SomeArrayFunction(
IF(SUM(D3:D6)>1,"A-B-C-D-E-F-G-H-I-J-K-L-M-N-O-P-Q-R-S-T-U-V-W-X 01", 
"part_one"), 
IF(SUM(D3:D6)>1,"A-B-C-D-E-F-G-H-I-J-K-L-M-N-O-P-Q-R-S-T-U-V-W-X 02", 
IF(SUM(D3:D6)>1,"A-B-C-D-E-F-G-H-I-J-K-L-M-N-O-P-Q-R-S-T-U-V-W-X 03", 
"part_two")) 
) 

它採用下面的VBA函數

Public Function SomeArrayFunction(sOne As String, sTwo As String) As Variant 
    Dim V() As Variant 
    ReDim V(1 To 2, 1 To 1) 
    V(1, 1) = sOne 
    V(2, 1) = sTwo 
    SomeArrayFunction = V 
End Function 

返回一個2×1陣列。


現在,當我把這個VBA函數

Public Sub EvaluateFormula() 
    Dim vOutput As Variant 

    vOutput = Application.Evaluate(Selection.Formula) 

    If VarType(vOutput) >= vbArray Then 
     MsgBox "Array:" & vbCrLf & vOutput(1, 1) & vbCrLf & vOutput(2, 1) 
    Else 
     MsgBox "Single Value: " & vbCrLf & vOutput 
    End If 
End Sub 

同時具有選定單元格A1 得到一個錯誤,因爲Application.Evaluate不能超過255個字符處理公式(例如,見VBA - Error when using Application.Evaluate on Long Formula) 。另一方面,如果我寫

vOutput = Application.Evaluate(Selection.Address) 

改爲(如上面的鏈接中提出的),那麼它工作得很好。除了陣列不再被重新調整角色,即MsgBox「單值:」被調用而不是MsgBox「Array:」

所以我的問題是:如何評估使用VBA的長公式(返回數組)?


編輯:我要強調,我需要這個工作的時候,我只選擇一個細胞是conains公式(不是一個區域或幾個單元)。我還沒有進入它作爲一個數組公式(即沒有大括號): enter image description here


EDIT2:我來回答的原因:我目前的工作需要我有這麼大的公式的一個長長的清單在電子表格中。而且由於它們被組織在一個列表中,所以每個這樣的公式只能佔用一個單元格。在幾乎所有情況下,公式都返回單個值(因此一個單元足以存儲/顯示輸出)。但是,如果在評估公式時發生內部錯誤,則公式會返回錯誤消息。這些錯誤消息通常很長,因此會返回爲不同大小的數組(取決於錯誤消息的長度)。所以我的目標是編寫一個VBA函數,該函數首先會從列表中獲取並輸出給定​​選定條目的完整錯誤消息。

+0

感謝您的原因。現在這變得越來越有趣。在閱讀你的描述之後,我首先想到的是:你能輸入填充到當前列(「列表」)旁邊的列中的數組公式嗎?您可以在公式上調用TRANSPOSE來將列變爲行。這有點「髒」,但如果足夠大以捕獲所有錯誤輸出,您可以將它們全部設置爲10個單元。我真的不認爲你會得到一個數組輸出沒有像公式的數組。問題將是如何最好地做到這一點。 –

+0

您的錯誤消息是否真的超過了32k(或者您是否試圖解決單元內顯示限制)?在任何情況下,您似乎都可以使用「scratch」範圍來放置公式,然後對它們調用Evaluate。 –

+0

@Byron:我也想過轉置它,但是我經常有幾個列表相鄰,這使得這種方法變得不可能。 –

回答

1

嘗試

vOutput = Application.Evaluate(Selection.CurrentArray.Address) 

(假設你有兩個小區=SomeArrayFunction(...)輸入作爲數組公式)

我覺得差異可能是評估一個單細胞,只會讓你返回的值到該單元格:整個數組不返回那裏,只有第一個值。

+0

我忙於排隊Excel,VBA編輯器和Watch窗口以及時得到答案。我同意它只是評估單個單元的想法。這也是有趣的行爲。 –

+0

也許這可能有助於解釋*爲什麼它需要以這種方式工作。 –

2

我相信Application.Evaluate將返回一個匹配輸入地址大小的結果。我懷疑你的Selection是一個單元,所以它返回一個單一的值。

如果您使用Selection.CurrentArray.Address來調用它,您將得到與正確數組大小相同的答案。 VBA的

圖片和Excel

enter image description here

代碼與

Public Function Test() As Variant 

    Test = Array(1, 2) 


End Function 

Sub t() 

    Dim a As Variant 

    a = Application.Evaluate(Selection.CurrentArray.Address) 

End Sub 

編輯測試的基礎上,這裏的評論是一種通過創建評估這一關表一張新表。我正在使用剪切/粘貼方法來確保公式的所有工作都一樣。如果單元格沒有引用剪切的單元格,這可能會更好。從技術上講,由於我使用剪切/粘貼,所以不會破壞任何其他細胞。

在下面的代碼中,我在單元格J2中有一個數組公式,它引用了其他幾個單元格。它被擴展爲3行,然後調用Evaluate。這就像你想要的那樣返回一個數組。然後它縮小到一個單元並將其移回。

我已經測試了一個簡單的例子。我不知道它是否適用於您想要的應用程序。

Sub EvaluateArrayFormulaOnNewSheet() 

    'cut cell with formula 
    Dim str_address As String 
    Dim rng_start As Range 
    Set rng_start = Sheet1.Range("J2") 
    str_address = rng_start.Address 

    rng_start.Cut 

    'create new sheet 
    Dim sht As Worksheet 
    Set sht = Worksheets.Add 

    'paste cell onto sheet 
    Dim rng_arr As Range 
    Set rng_arr = sht.Range("A1") 
    sht.Paste rng_arr 

    'expand array formula size.. resize to whatever size is needed 
    rng_arr.Resize(3).FormulaArray = rng_arr.FormulaArray 

    'get your result 
    Dim v_arr As Variant 
    v_arr = Application.Evaluate(rng_arr.CurrentArray.Address) 

    ''''do something with your result here... it is an array 


    'shrink the formula back to one cell 
    Dim str_formula As String 
    str_formula = rng_arr.FormulaArray 

    rng_arr.CurrentArray.ClearContents 
    rng_arr.FormulaArray = str_formula 

    'cut and paste back to original spot 
    rng_arr.Cut 

    Sheet1.Paste Sheet1.Range(str_address) 

    Application.DisplayAlerts = False 
    sht.Delete 
    Application.DisplayAlerts = True 

End Sub 
+0

我更喜歡你的版本 - @Tom - 你應該接受這個。 –

+0

我認爲這可能是打破駱駝背的人。 Excel的數組公式很好,超過255個字符,通過Eval但可能不是單個單元格。我會回覆@TimWilliams:爲什麼?使用一個單元格來存儲一個數組公式比較容易,它通過評估來獲取比Excel存儲的信息更多的信息,然後通過單元格訪問VBA中的對象。是否有一個原因,你不只是在VBA中做公式,因爲除了保持公式之外,單元似乎對解決方案沒有影響?我們缺少什麼? –

+0

@TimWilliams和Byron:我爲我的問題添加了一個原因。 –