Excel顯示#VALUE!
,當我的UDF返回超過255個字符的字符串時。在excel單元格中顯示> 255個字符
xlwings是0.7.1和Excel是2007年,正如每微軟,可以包含在細胞多達32767個字符。
問題出在哪裏?
Excel顯示#VALUE!
,當我的UDF返回超過255個字符的字符串時。在excel單元格中顯示> 255個字符
xlwings是0.7.1和Excel是2007年,正如每微軟,可以包含在細胞多達32767個字符。
問題出在哪裏?
如最好能告訴我,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數組。
基於上述二維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提供
以上詳細說明和解決方法非常有用。我的UDF主要返回字符串,所以轉換爲String 2D數組適用於我。我做了些修改,通過改變編寫VBA函數的代碼(import_udfs.py)來修改解決方法。這樣我在重新導入udfs後不會失去編輯。 – Jorge
作爲參考,我在這裏的xlwings github頁面上打開了一個問題:[link](https://github.com/ZoomerAnalytics/xlwings/issues/456) – schoolie