2016-04-25 14 views
0

Excelでは、my UDFが255文字を超える文字列を返したときにExcelが#VALUE!と表示されます。excelセルに> 255文字を表示する

xlwingsは0.7.1です.Excelは2007年で、マイクロソフトのように、セルに32767文字まで使用できます。

どこが問題なのですか?

答えて

2

私が知る限り、Py.CallUDF(xlwings udfsで使用)は2Dバリアント配列を返します。

純粋なVBA UDFから255より大きい文字列長のVariant配列を返すことによって、Excelで呼び出されたときに#VALUEエラーが発生することもあります。 VBAエディタの配列に時計を置くと、データがそのまま残っていることがわかります。正しく渡されていないだけです。少しの検索で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 

エクセル、リターン(Nのために失敗した> 255)からの呼び出し:

255 aaaaaaaaaaaaa....aaaaaaaaa 
256 #VALUE! 

バリアント配列の戻り要素:

Excelから呼び出す
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 

、リターン(> 255 Nのために成功した):

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

戻り文字列配列:エクセル、リターン(Nのために成功した> 255から呼び出す

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 

):

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文字を超える文字列をExcelに正常に反映させます。あなたは配列の結果に似たようなことをすることができます。ただ、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

は、2D文字列配列に2次元バリアント配列を変換する上記の@ schoolieの提案に基づいて、私は私のローカルxlwingsでVBA関数生成ロジックのソース修飾:(udfs.generate_vba_wrapperで

)を

置き換えます。

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) 

のTh:と

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

他のオプションは、 'Import Python UDFs'を実行した後に、VBエディタで生成されたVBマクロをパッチすることです。しかし、この変更は再インポートすると失われます。コードはすでに上記の@schoolieで与えられています

関連する問題