Skip to Content

Hello community,

I presented until now in the series “How to use actual SAPNetWeaver RFC Library with Pyhton” :

Here now an example how to read a table with the function module (FM) RFC_READ_TABLE. You need the file sapnwrfc.py from here – look at the end of the posting.

After the connection we get the function description of the FM, in our case RFC_READ_TABLE. We set the arguments QUERY_TABLE, in our case USR01, and the DELIMITER. We invoke the FM and print the result line by line. The result is in the DATA table, in the field WA.

# -*- coding: iso-8859-15 -*-
#-Begin-----------------------------------------------------------------

#-Include---------------------------------------------------------------
FileName = "sapnwrfc.py"
exec(compile(open(FileName).read(), FileName, "exec"))

#-Main------------------------------------------------------------------

#-Connection parameters-------------------------------------------------
RfcConnParams[0].name = "ASHOST"; RfcConnParams[0].value = "ABAP"
RfcConnParams[1].name = "SYSNR" ; RfcConnParams[1].value = "00"
RfcConnParams[2].name = "CLIENT"; RfcConnParams[2].value = "001"
RfcConnParams[3].name = "USER"  ; RfcConnParams[3].value = "BCUSER"
RfcConnParams[4].name = "PASSWD"; RfcConnParams[4].value = "minisap"

TableName = "USR01"

hRFC = SAP.RfcOpenConnection(RfcConnParams, 5, RfcErrInf)
if hRFC != None:

  charBuffer = create_unicode_buffer(512 + 1)

  hFuncDesc = SAP.RfcGetFunctionDesc(hRFC, "RFC_READ_TABLE", RfcErrInf)
  if hFuncDesc != 0:
    hFunc = SAP.RfcCreateFunction(hFuncDesc, RfcErrInf)
    if hFunc != 0:

      rc = SAP.RfcSetChars(hFunc, "QUERY_TABLE", TableName, \
        len(TableName), RfcErrInf)
      rc = SAP.RfcSetChars(hFunc, "DELIMITER", "~", 1, RfcErrInf)

      if SAP.RfcInvoke(hRFC, hFunc, RfcErrInf) == RFC_OK:

        hTable = c_void_p(0)
        if SAP.RfcGetTable(hFunc, "DATA", hTable, RfcErrInf) == RFC_OK:

          RowCount = c_ulong(0)
          rc = SAP.RfcGetRowCount(hTable, RowCount, RfcErrInf)
          rc = SAP.RfcMoveToFirstRow(hTable, RfcErrInf)
          for i in range(0, RowCount.value):
            hRow = SAP.RfcGetCurrentRow(hTable, RfcErrInf)
            rc = SAP.RfcGetChars(hRow, "WA", charBuffer, 512, RfcErrInf)
            print(charBuffer.value)
            if i < RowCount.value:
              rc = SAP.RfcMoveToNextRow(hTable, RfcErrInf)

      rc = SAP.RfcDestroyFunction(hFunc, RfcErrInf)

  rc = SAP.RfcCloseConnection(hRFC, RfcErrInf)

else:
  print(RfcErrInf.key)
  print(RfcErrInf.message)

del SAP

#-End-------------------------------------------------------------------

2017/04/24: I check the method above with Python release 3.6.1 x64 and with the SAP NetWeaver RFC library 721 PL42 x64 and it works perfect.

Cheers
Stefan

To report this post you need to login first.

15 Comments

You must be Logged on to comment or reply to a post.

  1. Former Member

    Hi Stefan,

    It’s nice meet another pythoner in this community(recently I’m studaying PyRFC from Srdjan Boskovi).

    As new comer,would you please explain more detail in your RFC_READ_TABLE,especially how to define fields that I want to load.I have try to FIELDS=[‘fields1′,’fields2′,’fields2’] and FIELDS=[[‘fields1’],[‘fields2’],[‘fields2’]],neither successe.

    Best regards.

    Davis Han

    (0) 
    1. Stefan Schnell Post author

      Hello Davis,

      thanks for your reply. I am a newbie in Python, this is my really first Project – except this.

      The FM RFC_READ_TABLE has the following Interface:

      FUNCTION RFC_READ_TABLE.
      *"----------------------------------------------------------------------
      *"*"Local Interface:
      *"  IMPORTING
      *"     VALUE(QUERY_TABLE) LIKE  DD02L-TABNAME
      *"     VALUE(DELIMITER) LIKE  SONV-FLAG DEFAULT SPACE
      *"     VALUE(NO_DATA) LIKE  SONV-FLAG DEFAULT SPACE
      *"     VALUE(ROWSKIPS) LIKE  SOID-ACCNT DEFAULT 0
      *"     VALUE(ROWCOUNT) LIKE  SOID-ACCNT DEFAULT 0
      *"  TABLES
      *"      OPTIONS STRUCTURE  RFC_DB_OPT
      *"      FIELDS STRUCTURE  RFC_DB_FLD
      *"      DATA STRUCTURE  TAB512
      *"  EXCEPTIONS
      *"      TABLE_NOT_AVAILABLE
      *"      TABLE_WITHOUT_DATA
      *"      OPTION_NOT_VALID
      *"      FIELD_NOT_VALID
      *"      NOT_AUTHORIZED
      *"      DATA_BUFFER_EXCEEDED
      *"----------------------------------------------------------------------
      

      With RfcGetFunctionDesc you get the handle to the function description. Now you create with the RfcCreateFunction a data container. So you have access to the fields and tables of the interface. E.g. you can set the import parameter direct via RfcSetChars or you can get via RfcGetTable a data container to a table of the interface. With RfcAppendRow you can add an empty line and with RfcSetChars you can set the fields. On this way you can set each part of the interface of a FM. If you have a definite FM, we can explicate this example.

      Cheers

      Stefan

      (0) 
      1. Former Member

        Hi Stefan,

        Thanks for so prompt response.

        I think I’v found what I want in PyRFC:

        connecton.call(‘RFC_READ_TABLE’,QUERY_TABLE=’LFA1′,FIELDS=[{‘FIELDNAME’:’MANDT’},{‘FIELDNAME’:’LAND1′}]) .

        Thanks again for you work.

        Regards

        Davis Han

        (0) 
  2. Former Member

    Hi Stefan,

    Hope you are doing well 🙂

    Thank you for this post and I perceived that you have used the table – “USR01” which holds number of fields in single digit. If I am using the tables like “BUT000” which holds 50+ fields, the script is not extracting the data. I believe that we need to adjust the memory buffer value in “RfcGetChars” function, but this is not helping me. Could you please recommend a way to grip more records.

    Regards

    Ramesh

    (0) 
    1. Stefan Schnell Post author

      Hello Ramesh,

      thanks for your reply.

      The table BUT000 has 86 fields with a length of 1131. The function module RFC_READ_TABLE allows a maximum of 512 characters. If you call the function module with the table BUT000 you must get an DATA_BUFFER_EXCEEDED exception. You can find here a solution with an extended function module how to get 8192 characters – search for Z_RFC_READ_TABLE. The solution is over six years old, but it still works.

      Cheers

      Stefan

      (0) 
      1. Former Member

        Good Day Stefan,

        Thank you for the clarification and its awesome.


        Now I got a condition, where I need to extract few fields like BPEXT, PARTNER, PERSNUMBER from BUT000, but the field BPEXT(Datatype – CHAR20) is passing null value and other fields are populating the values well.

        Even I tried to do the data type conversion in SAP and tried to import using RfcGetChars command, but no luck. Could you please suggest a solution for this.

        Below is the statement which I am using:

        hFuncDesc = SAP.RfcGetFunctionDesc(hRFC, “MY Function Module”, RfcErrInf)

        if hFuncDesc != 0:

        hFunc = SAP.RfcCreateFunction(hFuncDesc, RfcErrInf)

        if hFunc != 0:

        rc = SAP.RfcSetChars(hFunc, “IV_ACCOUNT”, acc_num, len(acc_num), RfcErrInf)

        if SAP.RfcInvoke(hRFC, hFunc, RfcErrInf) == RFC_OK:

        rc = SAP.RfcGetChars(hFunc, “EV_ACCOUNT”, Export, 256, RfcErrInf) # This line is passing the values well

        rc = SAP.RfcGetChars(hFunc, “EV_IBT”, Export1, 256, RfcErrInf) # This line is passing the null values

        rc = SAP.RfcGetChars(hFunc, “EV_SALES_PROD”, Export, 256, RfcErrInf) # This line is passing the values well


        Regards

        Ramesh

        (0) 
        1. Stefan Schnell Post author

          Hello Ramesh,

          I tried it with the following RFC-enabled function module:

          FUNCTION Z_BUT000
            IMPORTING
              VALUE(I_PARTNER) TYPE BU_PARTNER
            EXPORTING
              VALUE(E_BPEXT) TYPE BU_BPEXT.
          
          SELECT SINGLE BPEXT FROM BUT000 INTO e_bpext WHERE partner = i_partner.
          
          ENDFUNCTION.

          and the following VBScript:

          '-Begin-----------------------------------------------------------------
          
            '-Directives----------------------------------------------------------
              Option Explicit
          
            '-Constants-----------------------------------------------------------
              Const RFC_OK = 0
          
            '-Variables-----------------------------------------------------------
              Dim SAP, hRFC, rc, hFuncDesc, hFunc, charBuffer
          
            '-Sub Main------------------------------------------------------------
              Sub Main()
          
                Set SAP = CreateObject("COMNWRFC")
                If Not IsObject(SAP) Then
                 Exit Sub
                End If
          
                hRFC = SAP.RfcOpenConnection("ASHOST=NSP, SYSNR=00, " & _
                  "CLIENT=001, USER=BCUSER")
                If hRFC = 0 Then
                  Set SAP = Nothing
                  Exit Sub
                End If
          
                hFuncDesc = SAP.RfcGetFunctionDesc(hRFC, "Z_BUT000")
                If hFuncDesc = 0 Then
                  SAP.RfcCloseConnection(hRFC)
                  Set SAP = Nothing
                  Exit Sub
                End If
          
                hFunc = SAP.RfcCreateFunction(hFuncDesc)
                If hFunc = 0 Then
                  SAP.RfcCloseConnection(hRFC)
                  Set SAP = Nothing
                  Exit Sub
                End If
          
                rc = SAP.RfcSetChars(hFunc, "I_PARTNER", "4711004711")
          
                If SAP.RfcInvoke(hRFC, hFunc) = RFC_OK Then
          
                  rc = SAP.RfcGetChars(hFunc, "E_BPEXT", charBuffer, 20)
                  MsgBox charBuffer
          
                End If
          
                rc = SAP.RfcDestroyFunction(hFunc)
                rc = SAP.RfcCloseConnection(hRFC)
                Set SAP = Nothing
          
              End Sub
          
            '-Main----------------------------------------------------------------
              Main
          
          '-End-------------------------------------------------------------------
          

          All works well and expected. I don’t what is wrong in your case.

          What delivers RfcGetChars as return code? Delivers the error info structure information?

          Let us know your results.

          Cheers

          Stefan

          (0) 
  3. Former Member

    Hello Stefan,

    Thank you for all your blogs, you are a real inspiration for automation.

    I could succesfully connect however I am failing to use the FM BAL_DB_SEARCH

    I want to use the I_S_LOG_FILTER, which is a structure that contains table. When I try to get the range ALDATE, I have the error message

    exception: access violation writing 0x0000000000000000

    Here is my code below

    	hRFC = SAP.RfcOpenConnection(RfcConnParams, 5, RfcErrInf)
    	if hRFC != None:
    		
    		charBuffer = create_unicode_buffer(256 + 1)
    		hFuncDesc = SAP.RfcGetFunctionDesc(hRFC, "BAL_DB_SEARCH", RfcErrInf)
    		hFunc = SAP.RfcCreateFunction(hFuncDesc, RfcErrInf)
    		
    		hStruct = c_void_p(0)
    		hTable = c_void_p(0)
    		
    		if SAP.RfcGetStructure(hFunc, "I_S_LOG_FILTER", hStruct, RfcErrInf) == RFC_OK:
    			print("I_S_LOG_FILTER")
    			
    			SAP.RfcSetChars(hFunc, "I_CLIENT", "100", 3, RfcErrInf)
    						
    			try: 
    				SAP.RfcGetTable(hStruct, "ALDATE", hTable, RfcErrInf)
    			except Exception as e: 
    					print(e)
    					

    Do you see anything wrong with my statements ?

    (1) 
    1. Stefan Schnell Post author

      Hello Quentin,

      thank you very much for your reply.

      Is it possible for you to post here the missing prototypes. On this way it is possible for other members of the community to add it to their prototype definition. Thanks a lot for this.

      Cheers
      Stefan

      (0) 
  4. Raghavendran Ramasubramanian

    Hi Stephan,

     

    I’m trying to extract values from KNVV table using some filter conditions in SAP GUI, and now learning to use the SAP NW RFC python script to perform similar operation on the table KNVV, The table used in example is USR01 and if i try to modify it to KNVV and execute it doesn’t work for me. Though I’m new to understand and use the SAP NW RFC python script provided , would like to know what can be fixed in the below code or the approach should be different while accessing different tables using this script.

     

    Any Help would be appreciated 🙂

     

    # -*- coding: iso-8859-15 -*-
    #-Begin-----------------------------------------------------------------
    
    #-Include---------------------------------------------------------------
    from ctypes import *
    
    from pysaf.util.sapnwrfc import SAP, RfcConnParams, RfcErrInf, RFC_OK
    
    FileName = "C:\\Users\\rrama3\\PycharmProjects\\pysaf_core\\pysaf\\util\\sapnwrfc.py"
    exec(compile(open(FileName).read(), FileName, "exec"))
    
    #-Main------------------------------------------------------------------
    
    #-Connection parameters-------------------------------------------------
    RfcConnParams[0].name = "ASHOST"; RfcConnParams[0].value = "sap-pte-pas.nike.com" # PTE
    RfcConnParams[1].name = "SYSNR" ; RfcConnParams[1].value = "00"
    RfcConnParams[2].name = "CLIENT"; RfcConnParams[2].value = "300"
    RfcConnParams[3].name = "USER"  ; RfcConnParams[3].value = "rrama3"
    RfcConnParams[4].name = "PASSWD"; RfcConnParams[4].value = "********"
    
    TableName = "KNVV"
    
    hRFC = SAP.RfcOpenConnection(RfcConnParams, 5, RfcErrInf)
    if hRFC != None:
    
      charBuffer = create_unicode_buffer(512 + 1)
    
      hFuncDesc = SAP.RfcGetFunctionDesc(hRFC, "RFC_READ_TABLE", RfcErrInf)
      if hFuncDesc != 0:
        hFunc = SAP.RfcCreateFunction(hFuncDesc, RfcErrInf)
    
        if hFunc != 0:
    
          rc = SAP.RfcSetChars(hFunc, "QUERY_TABLE", TableName, len(TableName), RfcErrInf)
          rc = SAP.RfcSetChars(hFunc, "DELIMITER", "~", 1, RfcErrInf)
          if SAP.RfcInvoke(hRFC, hFunc, RfcErrInf) == RFC_OK:
    
            hTable = c_void_p(0)
            if SAP.RfcGetTable(hFunc, "DATA", hTable, RfcErrInf) == RFC_OK:
    
              f = open("Output.txt", "w+")
              RowCount = c_ulong(0)
              rc = SAP.RfcGetRowCount(hTable, RowCount, RfcErrInf)
              rc = SAP.RfcMoveToFirstRow(hTable, RfcErrInf)
              for i in range(0, RowCount.value):
                hRow = SAP.RfcGetCurrentRow(hTable, RfcErrInf)
                rc = SAP.RfcGetChars(hRow, "WA", charBuffer, 512, RfcErrInf)
                f.write(charBuffer.value + '\n')
                if i < RowCount.value:
                  rc = SAP.RfcMoveToNextRow(hTable, RfcErrInf)
    
    
          rc = SAP.RfcDestroyFunction(hFunc, RfcErrInf)
    
      rc = SAP.RfcCloseConnection(hRFC, RfcErrInf)
    
    else:
      print(RfcErrInf.key)
      print(RfcErrInf.message)
    
    del SAP
    
    #-End-------------------------------------------------------------------
    (0) 
    1. Stefan Schnell Post author

      Hello Raghavendran,

      this is not a problem of your Python code, RFM RFC_READ_TABLE can’t read KNVV completly.

      This is exact the error which delivers the Python program after the invoke.

      Use the fields table to reduce the size of the data less than 512 characters.

      Append this code and your Python code works:

            hFields = c_void_p(0)
            rc = SAP.RfcGetTable(hFunc, "FIELDS", hFields, RfcErrInf)
            hRow = SAP.RfcAppendNewRow(hFields, RfcErrInf)
            rc = SAP.RfcSetChars(hRow, "FIELDNAME", "KUNNR", 5, RfcErrInf)
            hRow = SAP.RfcAppendNewRow(hFields, RfcErrInf)
            rc = SAP.RfcSetChars(hRow, "FIELDNAME", "VKORG", 5, RfcErrInf)

      Best regards
      Stefan

       

      (0) 
      1. Raghavendran Ramasubramanian

        Hi Stephan,

        Thanks for your quick response, I tried providing the fields the reduce the buffer size while reading the KNVV table, getting a new issue “RFC_MEMORY_INSUFFICIENT”.

         

        Below are the things i’m trying to figure out as well –

        1. Read the Table (of any type from SAP using RFC) – KNVV etc.
        2. Provide Filter values to the fields for the table to reduce the outcome from the RFC_READ_TABLE (to make sure not to get MEMORY error or BUFFER error)

        Let me know if something else can be done to resolve this , also i’m trying to understand on how to provide filter values as we do in the front end SAP GUI for different fields.

        Current Issue Snapshot –

        Updated Code Snippet –

        # -*- coding: iso-8859-15 -*-
        #-Begin-----------------------------------------------------------------
        
        #-Include---------------------------------------------------------------
        from ctypes import *
        
        from pysaf.util.sapnwrfc import SAP, RfcConnParams, RfcErrInf, RFC_OK
        
        FileName = "C:\\Users\\rrama3\\PycharmProjects\\pysaf_core\\pysaf\\util\\sapnwrfc.py"
        exec(compile(open(FileName).read(), FileName, "exec"))
        
        #-Main------------------------------------------------------------------
        
        #-Connection parameters-------------------------------------------------
        RfcConnParams[0].name = "ASHOST"; RfcConnParams[0].value = "sap-pte-pas.nike.com" # PTE
        RfcConnParams[1].name = "SYSNR" ; RfcConnParams[1].value = "00"
        RfcConnParams[2].name = "CLIENT"; RfcConnParams[2].value = "300"
        RfcConnParams[3].name = "USER"  ; RfcConnParams[3].value = "rrama3"
        RfcConnParams[4].name = "PASSWD"; RfcConnParams[4].value = "**********"
        
        TableName = "KNVV"
        
        hRFC = SAP.RfcOpenConnection(RfcConnParams, 5, RfcErrInf)
        if hRFC != None:
          charBuffer = create_unicode_buffer(512 + 1)
          hFuncDesc = SAP.RfcGetFunctionDesc(hRFC, "RFC_READ_TABLE", RfcErrInf)
          if hFuncDesc != 0:
        
            hFunc = SAP.RfcCreateFunction(hFuncDesc, RfcErrInf)
        
            if hFunc != 0:
        
              rc = SAP.RfcSetChars(hFunc, "QUERY_TABLE", TableName, len(TableName), RfcErrInf)
              rc = SAP.RfcSetChars(hFunc, "DELIMITER", "~", 1, RfcErrInf)
        
              hFields = c_void_p(0)
              rc = SAP.RfcGetTable(hFunc, "FIELDS", hFields, RfcErrInf)
              hRow = SAP.RfcAppendNewRow(hFields, RfcErrInf)
              rc = SAP.RfcSetChars(hRow, "FIELDNAME", "KUNNR", 5, RfcErrInf)
              hRow = SAP.RfcAppendNewRow(hFields, RfcErrInf)
              rc = SAP.RfcSetChars(hRow, "FIELDNAME", "VKORG", 5, RfcErrInf)
              hRow = SAP.RfcAppendNewRow(hFields, RfcErrInf)
              rc = SAP.RfcSetChars(hRow, "FIELDNAME", "VTWEG", 5, RfcErrInf)
              hRow = SAP.RfcAppendNewRow(hFields, RfcErrInf)
              rc = SAP.RfcSetChars(hRow, "FIELDNAME", "SPART", 5, RfcErrInf)
              if SAP.RfcInvoke(hRFC, hFunc, RfcErrInf) == RFC_OK:
        
                hTable = c_void_p(0)
        
                if SAP.RfcGetTable(hFunc, "DATA", hTable, RfcErrInf) == RFC_OK:
        
                  f = open("Output.txt", "w+")
                  RowCount = c_ulong(0)
                  rc = SAP.RfcGetRowCount(hTable, RowCount, RfcErrInf)
                  rc = SAP.RfcMoveToFirstRow(hTable, RfcErrInf)
                  for i in range(0, RowCount.value):
                    hRow = SAP.RfcGetCurrentRow(hTable, RfcErrInf)
                    rc = SAP.RfcGetChars(hRow, "WA", charBuffer, 512, RfcErrInf)
                    f.write(charBuffer.value + '\n')
                    if i < RowCount.value:
                      rc = SAP.RfcMoveToNextRow(hTable, RfcErrInf)
        
        
              rc = SAP.RfcDestroyFunction(hFunc, RfcErrInf)
        
          rc = SAP.RfcCloseConnection(hRFC, RfcErrInf)
        
        else:
          print(RfcErrInf.key)
          print(RfcErrInf.message)
        
        del SAP
        
        #-End-------------------------------------------------------------------

         

        (0) 
        1. Stefan Schnell Post author

          Hello Raghavendran,

          it seems that your KNVV table contains to many entries for the RFM. Please try the ROWCOUNT parameter of the RFM to reduce the data e.g. like this:

          rc = SAP.RfcSetChars(hFunc, "ROWCOUNT", "100", 3, RfcErrInf)

          On this way the RFM delivers the first 100 entries of the table.

          Let us know your results.

          Cheers
          Stefan

          (0) 
          1. Raghavendran Ramasubramanian

            Hi Stephan,

             

            The ROWCOUNT worked for me as it got me only 100 records. I was also able to get the filtered out value for One Field (e.g. KUNNR) with multiple values (0000469612, 0000469613,0000469614) ?

             

            As providing filter values to a specific field/fields would get only filtered out data from SAP and would be helpful in my case.

            This is the current code snippet update –

            hOptions = c_void_p(0)
            if SAP.RfcGetTable(hFunc, "OPTIONS", hOptions, RfcErrInf ) == RFC_OK:
            hRow = SAP.RfcAppendNewRow(hOptions, RfcErrInf)
            rc = SAP.RfcSetChars(hRow, "TEXT","KUNNR = '0000469612'",len("KUNNR = '0000469612'"),RfcErrInf)
            rc = SAP.RfcSetChars(hFunc, "ROWCOUNT", "100", 3, RfcErrInf)

             

             

            (1) 

Leave a Reply