Skip to Content

The programming language Python offers many possibilities. Also it supports with py32win ActiveX automation, and therefore SAP GUI Scripting. The following example shows, how easy it is to take the recorded VBScript code and to use it inside Python.

In the comment lines you see the recorded VBScript code as a direct comparison.

 

Here an example which opens TAC SE16, enters table TADIR and execute the TAC:

#-Begin-----------------------------------------------------------------

#-Includes--------------------------------------------------------------
import sys, win32com.client

#-Sub Main--------------------------------------------------------------
def Main():

  try:

    SapGuiAuto = win32com.client.GetObject("SAPGUI")
    if not type(SapGuiAuto) == win32com.client.CDispatch:
      return

    application = SapGuiAuto.GetScriptingEngine
    if not type(application) == win32com.client.CDispatch:
      SapGuiAuto = None
      return

    connection = application.Children(0)
    if not type(connection) == win32com.client.CDispatch:
      application = None
      SapGuiAuto = None
      return

    session = connection.Children(1)
    if not type(session) == win32com.client.CDispatch:
      connection = None
      application = None
      SapGuiAuto = None
      return

   #session.findById("wnd[0]").resizeWorkingPane 173, 36, 0
    session.findById("wnd[0]").resizeWorkingPane(173, 36, 0)
   #session.findById("wnd[0]/tbar[0]/okcd").text = "/nse16"
    session.findById("wnd[0]/tbar[0]/okcd").text = "/nse16"
   #session.findById("wnd[0]").sendVKey 0
    session.findById("wnd[0]").sendVKey(0)
   #session.findById("wnd[0]/usr/ctxtDATABROWSE-TABLENAME").text = "TADIR"
    session.findById("wnd[0]/usr/ctxtDATABROWSE-TABLENAME").text = "TADIR"
   #session.findById("wnd[0]").sendVKey 0
    session.findById("wnd[0]").sendVKey(0)
   #session.findById("wnd[0]/tbar[1]/btn[8]").press
    session.findById("wnd[0]/tbar[1]/btn[8]").press()

  except:
    print(sys.exc_info()[0])

  finally:
    session = None
    connection = None
    application = None
    SapGuiAuto = None

#-Main------------------------------------------------------------------
if __name__ == "__main__":
  Main()

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

 

And after all we see that it is very easy to use SAP GUI Scripting inside Python. The recorded VBScript code can use almost always unchanged, sometimes it is necessary to set some brackets.

 

As IDE I use VS Code with Python extension, here a look at it:

 

Enjoy it.

Cheers
Stefan

To report this post you need to login first.

13 Comments

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

  1. William Ayd

    Hi Stefan,

    Awesome to see some Python pop up here on the SAP community! Just some suggestions – if you wanted to follow the PEP 8 convention you should keep function names lowercased. You could also simplify your code a bit if you just used “Duck Typing” on the variables you declare, rather than checking of types.

    Great stuff though – keep it coming!

    (1) 
    1. Stefan Schnell Post author

      Hello William,

      thank you very much for your reply and for your interesting suggestions. As you can see I am newbie at Python. I build this bridge in the context of test automation, here in combination with the Robot Framework.

      Best regards
      Stefan

      (0) 
      1. William Ayd

        I’m not familiar with the Robot Framework, but you may find some value in looking at Python’s built-in unittest module which can help consolidate a lot of setup and teardown actions across your test cases. To get you started, I’ve refactored your code above to fit that framework.

        Note that this is just taking your code as is. I’m not too familiar with the COM SDK but I think you might need to find an explicit close method to call for your session object rather than just setting it to None as you do above. Also, there could be some opportunity to simplify a lot of your “findById” calls if you create the window object as a variable, and have your calls work relative to that rather than always starting back with the session object as its root.

        I’m on a Mac and can’t test any of this, but feel free to ping me back if you have any issues or questions 🙂

        import unittest
        import win32com.client
        
        class SapGuiTests(unittest.TestCase):
        
            @classmethod
            def setUpClass(cls):
                '''This runs once when the class is instantiated'''
                cls.gui = win32com.client.CDispatch
                cls.app = gui.GetScriptingEngine
                cls.conn = app.Children(0)
                cls.sess = app.Children(1)
                cls.findById("wnd[0]").resizeWorkingPane(173, 36, 0)        
        
            @classmethod
            def tearDownClass(cls):
                '''This runs once when the class is being destroyed'''
                # Close out any sessions or applications here
                ...
        
            def setUp(self):
                '''This runs before each test case'''
                # Start back at the home screen
                self.sess.findById("wnd[0]/tbar[0]/okcd").text = "/n"
                self.sess.findById("wnd[0]").sendVKey(0)
        
            def tearDown(self):
                '''This runs after each test case'''
                ...
        
            def test_tadir(self):
                '''Test that we can access the TADIR table in SE16'''
                self.sess.findById("wnd[0]/tbar[0]/okcd").text = "/nse16"
                self.sess.findById("wnd[0]").sendVKey(0)
                self.sess.findById("wnd[0]/usr/ctxtDATABROWSE-TABLENAME").text = "TADIR"
                self.sess.findById("wnd[0]").sendVKey(0)
                self.sess.findById("wnd[0]/tbar[1]/btn[8]").press()
        
        
        if __name__=='__main__':
            unittest.main()
        
        (1) 
  2. Mason Hacker

    I have the below python script working to open SAP and then it also runs a t-code after opening.

    For some reason I am able to execute a t-code but I’m not able to access the elements by Id using the FindById(). Any solutions? I think the problem is with the window ID or the session ID.

    import win32com.client
    from win32com import *
    from win32api import *
    from win32com.client import *

    SAPguiAPP = win32com.client.Dispatch(“Sapgui.ScriptingCtrl.1”)
    Connection = SAPguiAPP.OpenConnection(“System_Name_QA”,1)
    Session = SAPguiAPP.ActiveSession
    Session.SendCommand(Command=”/nSE16″)

    (0) 
  3. Mason Hacker

    Interestingly, this format does not cause any error but it does not act upon the Id and transfer a value to the screen either.

    Session.SendCommand(“Session.FindById(‘wnd[0]/usr/ctxtRP50G-PERNR’).text=’9999999′”)

    (0) 
    1. Stefan Schnell Post author

      Hello Mason,

      Session.SendCommand(“/nse16”) sets in the command field combo box the TAC SE16 and execute it. Your examples should not work in my opinion.

      If I try this:

      session.sendcommand(Command = "/nse16")

      I get the result that the transaction 0 doesn’t exists.

      And if I try this:

      Session.SendCommand(“Session.FindById(‘wnd[0]/usr/ctxtRP50G-PERNR’).text=’9999999′”)

      I get an error message.

      Best regards
      Stefan

       

      (0) 
  4. Mason Hacker

    Hi Stefan,

    I have included a more complete code example and indicated the line where it is failing.

    I would like to create the python equivalent of the VBA code below. The problem seems to be the reference to translate the vba Dim SAPguiAPP As SAPFEWSELib.GuiApplication.

    How can I call SAPFEWSELib.GuiApplication from the ocx file in python? There are python ctype method to call dlls.

    #Start of python code

    import win32com.client
    from win32com import *
    from win32api import *
    from win32com.client import *

    SAPguiAPP = win32com.client.Dispatch(“Sapgui.ScriptingCtrl.1”)
    Connection = SAPguiAPP.OpenConnection(“75 – NSP – Production Simple SAP Access”,1)
    session1 = SAPguiAPP.ActiveSession
    print(help(session1)) # proves the FindByID method is now available in the print out
    session1.StartTransaction(“PA20”) # This line works perfectly
    session1.FindById(“wnd[0]/usr/ctxtRP50G-PERNR”).text = ‘999999’ # This line fails without error

    #End of python code

     

    “””

    ”Start of vba example”

    Sub Log_Sap_VBA()
    ”’references C:\Program Files (x86)\SAP\FrontEnd\SAPgui\sapfewse.ocx

    Dim SAPguiAPP As SAPFEWSELib.GuiApplication
    Dim Connection As SAPFEWSELib.GuiConnection
    Dim Session As SAPFEWSELib.GuiSession
    Dim info As SAPFEWSELib.GuiSessionInfo

    If SAPguiAPP Is Nothing Then
    Set SAPguiAPP = CreateObject(“Sapgui.ScriptingCtrl.1”)
    End If
    If Connection Is Nothing Then
    Set Connection = SAPguiAPP.OpenConnection(“75 – NSP – Production Simple SAP Access”,1)
    End If
    If Session Is Nothing Then
    Set Session = Connection.Children(0)
    MsgBox x
    End If

    End Sub

    ”End of VBA example

    “””

     

    (0) 
    1. Stefan Schnell Post author

      Hello Mason,

      in my case is in TAC PA20 the GuiCTextField RP50G-PERNR wrapped by a GuiSimpleContainer. If you don’t use the complete path to your object the access fails, as in your case.

      session.findById("wnd[0]/usr/subSUBSCR_PERNR:SAPMP50A:0110/ctxtRP50G-PERNR").text = "999999"

      Please check your path and let us know your result.

      Cheers
      Stefan

       

       

      (0) 
      1. Mason Hacker

        Hi Stefan,

        On my SAP, it does not appear to be a wrapped element. I have still not been able to get it to transfer a value to the screen. I included my tracking image below.

        import win32com.client
        from win32com import *
        from win32api import *
        from win32com.client import *

        SAPguiAPP = win32com.client.Dispatch(“Sapgui.ScriptingCtrl.1”)
        Connection = SAPguiAPP.OpenConnection(“75 – NSP – Production Simple SAP Access”,1)
        Session1 = SAPguiAPP.ActiveSession
        Session1.StartTransaction(“PA20”) # This works
        Session1 = SAPguiAPP.ActiveSession
        Session1.FindById(“wnd[0]/usr/lblRP50G-PERNR”).text = ‘999999’ # This does not work

         

         

        (0) 
  5. Stefan Schnell Post author

    Hello Mason,

    you open a new connection so you can use this to solve your problem:

    import win32com.client
    from win32com import *
    from win32api import *
    from win32com.client import *
    
    SAPguiAPP = win32com.client.Dispatch(“Sapgui.ScriptingCtrl.1”)
    Connection = SAPguiAPP.OpenConnection(“75 – NSP – Production Simple SAP Access”,1)
    Session1 = Connection.Children(0)
    Session1.StartTransaction(“PA20”)
    Session1.FindById(“wnd[0]/usr/lblRP50G-PERNR”).text = ‘999999’

    Cheers
    Stefan

    (0) 
    1. Mason Hacker

      Hi Stefan,

       

      The last script that you posted works perfectly now! I discovered the issue is that it will not work in python 3.6 but it does work in 32-bit python 2.7 with the 32-bit pywin32 package!

      The following are the collection of errors that I found in python 3.6 with pywin32 for 3.6.

      #Session1 = SAPguiAPP.ActiveSession # Works for the Start Transaction but does not work for FindById
      Session1 = Connection.Children(0) # TypeError: ‘GuiComponentCollection’ object is not callable
      #Session1 = Connection.Children(Index=0) # TypeError: ‘GuiComponentCollection’ object is not callable
      #Session1 = Connection.Children # object has no attribute ‘StartTransaction’
      #Session1 = Connection.Children.Item(0) #object has no attribute ‘StartTransaction’
      #Session1 = Connection.Children[0] # TypeError: ‘GuiComponentCollection’ object does not support indexing
      #Session1 = Connection.Children[‘ses[0]’] # ‘GuiComponentCollection’ object is not subscriptable
      #Session1 = SAPguiAPP.ActiveSession.Children(0) #TypeError: ‘GuiComponentCollection’ object is not callable
      #Session1 = Connection.Children() # TypeError: ‘GuiComponentCollection’ object is not callable
      #Session1 = Connection.Children “0” # Invalid Syntax
      #Session1 = Connection.Children 0 # Invalid Syntax
      #Session1 = Connection.Children # Sets Session1 = to <win32com.gen_py.None.GuiComponentCollection> does not work
      #print(len(Dispatch(SAPguiAPP.Children)))
      #Session1 = len(Dispatch(SAPguiAPP.Children))
      #TypeError: ‘GuiComponentCollection’ object is not iterable
      #TypeError: ‘GuiComponentCollection’ object cannot be interpreted as an integer

      If you find a 3.6 solution please let me know. Otherwise, I’m happy it works in 2.7!

      Regards,

      Mason

      (1) 
  6. Mason Hacker

    I created a cool and re-usable gui connection class example using a Tkinter window to run the script.

    Many buttons could be added to the window re-using the same connection class for each sap gui scripting function.

    # import libraries
    import win32com.client
    from win32com import *
    from win32api import *
    from win32com.client import *
    import win32com.client as win32
    import win32gui, win32con
    import pyautogui, time, webbrowser, datetime
    from Tkinter import *

    # create a reuseable connection class
    class cls_SAP_Gui_Scripting:
    def __init__(self, api, conn):
    self.SAPguiAPP = win32com.client.Dispatch(api)
    self.Connection = self.SAPguiAPP.OpenConnection(conn,1)
    self.Session = self.Connection.Children(0)

    # Create Different SAP Script Functions
    def run_my_sap_script():
    # instantiate the class inside the function
    MySapGui = cls_SAP_Gui_Scripting(“Sapgui.ScriptingCtrl.1”, “75 – NSP – Production Simple SAP Access”)
    MySapGui.Session.StartTransaction(“PA20”)
    MySapGui.Session.FindById(“wnd[0]/usr/ctxtRP50G-PERNR”).Text = ‘9999999’
    # Loop through excel workbook here with excel.application

    # Create a main window with Tkinter and add button to run SAP Script Function
    def main():
    window = Tk()
    window.title(“SAP Script Automation”)
    window.wm_state(‘zoomed’)
    window.configure(bg=’red’)
    b1 = Button(window,text=”Run SAP GUI Script”,font=(“Helvetica”, 16),command=run_my_sap_script)
    b1.grid(row=0, column=0)
    window.mainloop()

    # Call Main
    main()

    (1) 

Leave a Reply