SAP / PyRFC

Asynchronous, non-blocking SAP NW RFC SDK bindings for Python
http://sap.github.io/PyRFC
Apache License 2.0
510 stars 137 forks source link

How to send a table (Python array) to RFC function #78

Closed thattejada closed 6 years ago

thattejada commented 6 years ago

I'm trying to send a table to a RFC in this way:

customers = [
    {
        "ALTKN": "1234567",
        "EVENT": "CR",
        "KTOKD": "",
        "TITLE_MEDI": "",
        "NAME1": "TEST1"
    },
    {
        "ALTKN": "1234567",
        "EVENT": "AC",
        "KTOKD": "",
        "TITLE_MEDI": "",
        "NAME1": "TEST1"
    }
]

data = {'TAB_DATA': customers}
result = conn.call('ZSAPRFC_CUSTOMERS', data)

print(result)

But the result I get is:

{'TAB_O_IDREG': [], 'TAB_DATA': [], 'EXP_RETURN': 'ERRO: BUKRS EMPTY'}

How can I pass that customers data for saving with the RFC?

bsrdjan commented 6 years ago

It looks technically correct and no errors from PyRFC perspective. "BUKRS EMPTY" error could be related to Accounting Area (German Buchungskreis) and it depends on inner ABAP logic of ZSAPRFC_CUSTOMERS, if should accept input array.

You could open ABAP transaction SE37 and test the ZSAPRFC_CUSTOMERS module, enter the same input parameters and check if the same error happens also in ABAP. If that is the case, either the ABAP logic or input values should be fixed.

If no error in SE37, conversion exits might be attached to some of input fields: https://github.com/SAP/PyRFC/blob/master/doc/remarks.rst

thattejada commented 6 years ago

Thank you @bsrdjan, I'm going to see what you suggested!

thattejada commented 6 years ago

After look the RFC it receives another param IMP_BUKRS, but after adding it, the error persists, our SAP provider sent us an VBA Excel macro with an example, but I can't figure out how to pass those params with PyRFC.

From the Excel example they send:

obj_RFC.exports("IMP_BUKRS").Value = Worksheets("Inicial").Cells(5, 3).Value

 count = 0
    Do While obj_wkst.Cells(vl_lin, 2).Value <> ""

        count = count + 1
        obj_RFC.tables("TAB_DATA").AppendRow
        obj_RFC.tables("TAB_DATA").Value(count, "ALTKN") = obj_wkst.Cells(vl_lin, 1).Value
        obj_RFC.tables("TAB_DATA").Value(count, "EVENTO") = obj_wkst.Cells(vl_lin, 2).Value
        obj_RFC.tables("TAB_DATA").Value(count, "KTOKD") = obj_wkst.Cells(vl_lin, 3).Value
        obj_RFC.tables("TAB_DATA").Value(count, "TITLE_MEDI") = obj_wkst.Cells(vl_lin, 4).Value
        obj_RFC.tables("TAB_DATA").Value(count, "NAME1") = obj_wkst.Cells(vl_lin, 5).Value
...

How can I use PyRFC into an equal way to pass those params? they send the IMP_BUKRS and a table "TAB_DATA".

thattejada commented 6 years ago

Hi @bsrdjan,

Finally with some additional help the answer is that each param of the RFC should be passed individually to the call function, IMP_BUKRS is a code, and TAB_DATA is a table of records with required fields.

In my particular case this code works for me:

customers = [
    {
        'ALTKN': '12345678',
        'EVENT': 'CR',
        'KTOKD': '',
        'TITLE_MEDI': '',
        'NAME1': 'TEST NAME',
    },
    {
        'ALTKN': '3456789',
        'EVENT': 'AC',
        'KTOKD': '',
        'TITLE_MEDI': '',
        'NAME1': 'OTHER TEST',
    }
]

# The result is a Dictionary
result = conn.call('ZSAPRFC_CUSTOMERS', IMP_BUKRS=u'123', TAB_DATA=customers)

Thank you @bsrdjan

iospetrosky commented 6 years ago

This does not work for RFC_READ_TABLE if I try

RfcCallTransaction = Functions.Add("RFC_READ_TABLE")
RfcCallTransaction.Call("AGR_DEFINE",";","",100,10)

I get a "TypeError: 'bool' object is not callable"

Instead this works, but I can't figure out how to fill the FIELDS and OPTIONS tables before the call

    RfcCallTransaction = Functions.Add("RFC_READ_TABLE")
    strExport1 = RfcCallTransaction.exports("QUERY_TABLE")
    strExport2 = RfcCallTransaction.exports("DELIMITER")
    strExport3 = RfcCallTransaction.exports("ROWSKIPS")
    strExport4 = RfcCallTransaction.exports("ROWCOUNT")
    tblOptions = RfcCallTransaction.Tables("OPTIONS")
    #RETURNED DATA
    tblData = RfcCallTransaction.Tables("DATA")
    tblFields = RfcCallTransaction.Tables("FIELDS")

    strExport1.Value = 'AGR_DEFINE'
    strExport2.Value = ";"
    strExport3.Value = 2000
    strExport4.Value = 10

    if RfcCallTransaction.Call == True:
        print ("Function call successful")
        print (tblData.RowCount)
        j = 1
        while j < tblData.RowCount:
            print (tblData(j,"WA"))
            j = j + 1