2016-04-25 137 views
0

Excel顯示#VALUE!,當我的UDF返回超過255個字符的字符串時。在excel單元格中顯示> 255個字符

xlwings是0.7.1和Excel是2007年,正如每微軟,可以包含在細胞多達32767個字符。

問題出在哪裏?

回答

2

如最好能告訴我,Py.CallUDF(由xlwings UDF的使用)返回一個2D Variant數組。

它也出現,由於某些原因返回Variant數組與串在Excel中調用時大於255從一個純VBA UDF導致#VALUE錯誤長度。在VBA編輯器中放置一個監視器的數組顯示數據是完整的,它只是沒有得到正確的傳遞到Excel。一點搜索返回了幾個關於VBA中最大字符串長度的問題,但沒有具體解決這個問題。

返回字符串數組或單個字符串> 255個字符似乎工作正常,但。

下面是表示問題的幾個純VBA例子:

返回變量數組:

Function variant_long_string(n) 
    Dim temp(0 To 0, 0 To 0) As Variant 
    temp(0, 0) = String(n, "a") 
    variant_long_string = temp 
End Function 

從Excel調用,返回(失敗爲N> 255):

255 aaaaaaaaaaaaa....aaaaaaaaa 
256 #VALUE! 

變量數組的歸元:

Function variant_long_string_element(n) 
    Dim temp(0 To 0, 0 To 0) As Variant 
    temp(0, 0) = String(n, "a") 
    variant_long_string_element = temp(0, 0) 
End Function 

從Excel調用,返回(成功爲N> 255):

255 aaaaaaaaaaaaa....aaaaaaaaa 
256 aaaaaaaaaaaaa....aaaaaaaaaa 

返回字符串數組:

Function string_long_string(n) 
    Dim temp(0 To 0, 0 To 0) As String 
    temp(0, 0) = String(n, "a") 
    string_long_string = temp 
End Function 

從Excel調用,返回(成功爲N> 255 ):

255 aaaaaaaaaaaaa....aaaaaaaaa 
256 aaaaaaaaaaaaa....aaaaaaaaaa 

解決方法

如果你的Python UDF只返回一個字符串值,就像這樣:

@xw.func  
def build_long_string(n): 
    res = 'a'*int(n) 
    return res 

xlwings將自動生成的xlwings_udfs模塊下面的VBA宏:

Function build_long_string(n) 
     If TypeOf Application.Caller Is Range Then On Error GoTo failed 
     build_long_string = Py.CallUDF(PyScriptPath, "build_long_string", Array(n), ThisWorkbook) 
     Exit Function 
failed: 
     build_long_string = Err.Description 
End Function 

作爲一個快速補丁,讓您的UDF的工作,改變宏觀略微這樣:

Function build_long_string(n) 
     If TypeOf Application.Caller Is Range Then On Error GoTo failed 
     temp = Py.CallUDF(PyScriptPath, "build_long_string", Array(n), ThisWorkbook) 
     build_long_string = temp(0, 0) 
     Exit Function 
failed: 
     build_long_string = Err.Description 
End Function 

允許字符串> 255的長度使其成功成功。你可以爲數組結果做類似的事情,你只需要通過循環/重新指定temp中的所有值到結果來將Variant數組轉換爲String數組。

+0

以上詳細說明和解決方法非常有用。我的UDF主要返回字符串,所以轉換爲String 2D數組適用於我。我做了些修改,通過改變編寫VBA函數的代碼(import_udfs.py)來修改解決方法。這樣我在重新導入udfs後不會失去編輯。 – Jorge

+0

作爲參考,我在這裏的xlwings github頁面上打開了一個問題:[link](https://github.com/ZoomerAnalytics/xlwings/issues/456) – schoolie

2

基於上述二維Variant數組轉換爲2D字符串數組的@ schoolie的建議,我修改VBA函數生成邏輯的源極在我的本地xlwings:

在udfs.generate_vba_wrapper()

取代:

vba.write('{fname} = Py.CallUDF("{module_name}", "{fname}", {args_vba}, ThisWorkbook)\n', 
        module_name=module_name, 
        fname=fname, 
        args_vba=args_vba, 
       ) 

有:

vba.write('r = Py.CallUDF("{module_name}", "{fname}", {args_vba}, ThisWorkbook)\n', 
             module_name=module_name, 
             fname=fname, 
             args_vba=args_vba, 
            )      
       vba.write('ReDim strarray(UBound(r, 1), UBound(r, 2)) As String\n') 
       vba.write('For i = 0 To UBound(r, 1)\n') 
       vba.write(' For j = 0 To UBound(r, 2)\n') 
       vba.write(' strarray(i, j) = CStr(r(i, j))\n') 
       vba.write(' Next\n') 
       vba.write('Next\n') 
       vba.write('{fname} = strarray\n', fname=fname) 

釷另一種選擇是在執行「導入Python UDF」後,在VB編輯器中修補生成的VB宏。但是,如果您重新導入,此更改將會丟失。代碼已在上面由@schoolie提供

相關問題