如何使用Python 3登录到SAPGUI?

如何使用Python 3登录到SAPGUI?,python,sap-gui,Python,Sap Gui,我试图用Python登录到SAPGUI,以便创建一个脚本来自动运行事务,我遇到了一个问题。每当我尝试登录时,都会出现错误。我不知道为什么会出现这个错误。这是我第一次尝试导航到SAP GUI,因此我不确定是否错过了建立成功登录的重要一行 我们以前使用过VBA,但我的同事表示有兴趣将我们的自动化脚本从Excel移动到Python,因为我是Python方面最有经验的人,所以我的任务是让它工作起来 # Importing the Libraries import win32com.client impo

我试图用Python登录到SAPGUI,以便创建一个脚本来自动运行事务,我遇到了一个问题。每当我尝试登录时,都会出现
错误。我不知道为什么会出现这个错误。这是我第一次尝试导航到SAP GUI,因此我不确定是否错过了建立成功登录的重要一行

我们以前使用过VBA,但我的同事表示有兴趣将我们的自动化脚本从Excel移动到Python,因为我是Python方面最有经验的人,所以我的任务是让它工作起来

# Importing the Libraries
import win32com.client
import sys
import subprocess
import time


# This function will Login to SAP from the SAP Logon window

def saplogin():

    try:

        path = r"C:\Program Files (x86)\SAP\FrontEnd\SAPgui\saplogon.exe"
        subprocess.Popen(path)
        time.sleep(10)


        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]/usr/txtRSYST-BNAME").text = "USER"
        session.findById("wnd[0]/usr/pwdRSYST-BCODE").text = "PASS"
        session.findById("wnd[0]").sendVKey(0)

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

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


saplogin()

在回答您关于登录自动化的问题时,是这样做的:

import subprocess
subprocess.check_call(['C:\Program Files (x86)\SAP\FrontEnd\SAPgui\\sapshcut.exe', '-system=DCG210', '-client=100', '-user=USERNAME', '-pw=PASSWORD'])

其中,
DG210
-SAP系统的名称已在SAPGui中设置

回答您关于登录自动化的问题,操作如下:

import subprocess
subprocess.check_call(['C:\Program Files (x86)\SAP\FrontEnd\SAPgui\\sapshcut.exe', '-system=DCG210', '-client=100', '-user=USERNAME', '-pw=PASSWORD'])

其中
DG210
-SAP系统的名称已在SAPGui中设置

我可能会回答多个问题。我认为人们可以自动化SAP以实现长时间的可重复操作。无论如何,下面的信息将是有用的。在SAP客户端7.20和7.50、Python 3.8.3上测试

首先,您可以使用config.py:

import os  # for path join

SAP_SID = 'SID'
SAP_MANDANT = '1000'
SAP_USER = 'login'
SAP_PASS = 'secret'
SAP_EXE = "C:\Program Files (x86)\SAP\FrontEnd\SAPgui\sapshcut.exe"

# minimize SAP window, enable it after debugging is completed; unfortunately small windows still appear with this setting
ICONIFY = False

# screenshots for debug and visual logging
SCR_ERR = os.path.join('path', 'err_screen.png')
其次,主脚本执行连接,然后打开一个Transactions:

import config
import pyautogui as pya  # for screenshots
import time  # for count seconds for approx. measuring
import subprocess
import win32com.client
from win32gui import GetWindowText, GetForegroundWindow


def saplogin():
    try:
        # 1.1. Connect to SAP
        subprocess.check_call([config.SAP_EXE,
                               '-user=%s' % config.SAP_USER,
                               '-pw=%s' % config.SAP_PASS,
                               '-system=%s' % config.SAP_SID,
                               '-client=%s' % config.SAP_MANDANT])

        time.sleep(10)  # need to ensure SAP created a session

        # Get session
        sap_gui_auto = win32com.client.GetObject('SAPGUI').GetScriptingEngine
        session = sap_gui_auto.findById("con[0]/ses[0]")  # 1 - to run the second session comment this line and uncomment the next, with con[1] and so on; probably it may work with a param stored in config
        # session = sap_gui_auto.findById("con[1]/ses[0]")  # 2
        # session = sap_gui_auto.findById("con[2]/ses[0]")  # 3
        # session = sap_gui_auto.findById("con[3]/ses[0]")  # 4

        # 1.2. Check if dialog window appears
        if session.children.count > 1:
            try:
                # 1.2.1 License window (this code was written for different PCs with the same ses[0]; 
                # to run this code on the same machine it shoild be modified by adding a check for ses[1] and so on)
                # Open new session if the title equals to <your title>
                if (GetWindowText(GetForegroundWindow())) == "<Информация по лицензии при многократной регистрации>":
                    print("Title: %s" % session.children(1).text)  # you may use this instead of GetWindowText in the line above
                    
                    # Choose an option to create additional session
                    try:
                        session.findById("wnd[1]/usr/radMULTI_LOGON_OPT2").select()
                        session.findById("wnd[1]/usr/radMULTI_LOGON_OPT2").setFocus()
                        session.findById("wnd[0]").sendVKey(0)

                    except Exception as ex:
                        print("Cannot perform an operation (%s)" % ex)
                        pya.screenshot(config.SCR_ERR)
                        exit(1)

                time.sleep(1)  # for case if new dialog window appears

                try:
                    # Now we are about to be logged. Often at this moment the system message is shown 
                    if session.children(1).text == "<Системные сообщения>":  # replace to your text
                        print("Title: %s" % session.children(1).text)
                        # in my case this window always has two lines of text; you may safely delete these two lines of code
                        print("%s | %s" % (session.findById("wnd[1]/usr/lbl[4,1]").text,
                                                       session.findById("wnd[1]/usr/lbl[17,1]").text))
                        print("%s | %s" % (session.findById("wnd[1]/usr/lbl[4,3]").text,
                                                       session.findById("wnd[1]/usr/lbl[17,3]").text))
                        
                        print("The window is closed '%s', please wait..." % session.children(1).text)
                        session.findById("wnd[1]").sendVKey(0)
                    else:
                        # Exit if the window has unknown title
                        print("Title: %s. Exit." % session.children(1).text)
                        pya.screenshot(config.SCR_ERR)
                        exit(1)

                except Exception as ex:
                    # Exit for unknown window
                    print("Unknown window: %s. Exit (%s)" % (session.children(1).text, ex))
                    pya.screenshot(config.SCR_ERR)
                    exit(1)

            except Exception as ex:
                # Finally, exit for unknown reason
                print("Unknown error: %s. Exit (%s)" % (session.children(1).text, ex))
                pya.screenshot(config.SCR_ERR)
                exit(1)

        print("Logged to SAP.")
        return session

    except Exception as ex:
        print("Error. Cannot create session. Exit (%s)" % ex)
        pya.screenshot(config.SCR_ERR)
        exit(1)


def export_npp(session, params):
    # 2.1. Start counter (for those who cares about statistics and measuring)
    start = time.time()

    if config.ICONIFY:
        # minimize main window
        session.findById("wnd[0]").iconify()
    else:
        # or resize it
        session.findById("wnd[0]").resizeWorkingPane(84, 40, 0)

    # 2.2. Open transation
    session.findById("wnd[0]/tbar[0]/okcd").text = 'transaction'
    session.findById("wnd[0]").sendVKey(0)

    """
    startx = time.time()
    'doing some repeatable stuff'
    finish = time.time()
    total_time = finish - startx
    print("Time %02d seconds added to dict" % total_time)
    """
    total_finish = time.time()
    total_time = total_finish - start
    print("Total: %02d seconds" % total_time)


# Begin, start session
ses = saplogin()

# Use params of session to use it in transaction 'export_npp' and so on
npp = export_npp(ses, params)
导入配置
将pyautogui作为pya导入屏幕截图
导入时间#用于大约测量的计数秒
导入子流程
导入win32com.client
从Win32 GUI导入GetWindowText、GetForegroundWindow
def saplogin():
尝试:
# 1.1. 连接到SAP
子进程。检查调用([config.SAP_EXE,
'-user=%s'%config.SAP\u用户,
'-pw=%s'%config.SAP\u PASS,
'-system=%s'%config.SAP\u SID,
'-client=%s'%config.SAP\u MANDANT])
时间。睡眠(10)#需要确保SAP创建会话
#获取会话
sap\u gui\u auto=win32com.client.GetObject('SAPGUI').GetScriptingEngine
session=sap_gui_auto.findById(“con[0]/ses[0]”)1-要运行第二个会话,请使用con[1]注释此行并取消注释下一行,依此类推;它可能与存储在配置中的参数一起工作
#session=sap_gui_auto.findById(“con[1]/ses[0]”)2
#session=sap_gui_auto.findById(“con[2]/ses[0]”)3
#session=sap_gui_auto.findById(“con[3]/ses[0]”)4
# 1.2. 检查对话框窗口是否出现
如果session.children.count>1:
尝试:
#1.2.1许可证窗口(此代码是为具有相同ses的不同PC编写的[0];
#要在同一台机器上运行此代码,应通过添加ses检查[1]等方式对其进行修改)
#如果标题等于,则打开新会话
如果(GetWindowText(GetForegroundWindow())==“”:
打印(“标题:%s”%session.children(1.text)#您可以使用它而不是上面一行中的GetWindowText
#选择一个选项以创建其他会话
尝试:
session.findById(“wnd[1]/usr/radMULTI\u LOGON\u OPT2”)。选择()
session.findById(“wnd[1]/usr/radMULTI_LOGON_OPT2”).setFocus()
session.findById(“wnd[0]”)。sendVKey(0)
例外情况除外,例如:
打印(“无法执行操作(%s)”%ex)
pya.screenshot(config.SCR\u ERR)
出口(1)
时间。睡眠(1)#如果出现新的对话框窗口
尝试:
#现在我们就要被记录了。通常此时会显示系统消息
如果session.children(1.text==”:#替换为您的文本
打印(“标题:%s”%session.children(1.text)
#在我的例子中,这个窗口总是有两行文本;您可以安全地删除这两行代码
打印(“%s |%s”%)(session.findById(“wnd[1]/usr/lbl[4,1]”)文本,
session.findById(“wnd[1]/usr/lbl[17,1]”文本)
打印(“%s |%s”%”(session.findById(“wnd[1]/usr/lbl[4,3]”)文本,
session.findById(“wnd[1]/usr/lbl[17,3]”文本)
打印(“窗口已关闭“%s”,请稍候…”%session.children(1.text)
session.findById(“wnd[1]”)。sendVKey(0)
其他:
#如果窗口的标题未知,请退出
打印(“标题:%s.退出”。%session.children(1.text)
pya.screenshot(config.SCR\u ERR)
出口(1)
例外情况除外,例如:
#退出未知窗口
打印(“未知窗口:%s。退出(%s)”%(会话。子项(1)。文本,例如))
pya.screenshot(config.SCR\u ERR)
出口(1)
例外情况除外,例如:
#最后,出于未知原因退出
打印(“未知错误:%s.退出(%s)”%(会话.子项(1).text,ex))
pya.screenshot(config.SCR\u ERR)
出口(1)
打印(“登录到SAP”)
返回会话
例外情况除外,例如:
打印(“错误。无法创建会话。退出(%s)”%ex)
pya.screenshot(config.SCR\u ERR)
出口(1)
def导出npp(会话,参数):
# 2.1. 启动计数器(适用于那些关心统计和测量的人)
开始=时间。时间()
如果config.ICONIFY:
#最小化主窗口
session.findById(“wnd[0]”).iconify()
其他:
#或者调整它的大小
session.findById(“wnd[0]”)。调整工作窗格的大小(84,40,0)
# 2.2. 开放式交易
session.findById(“wnd[0]/tbar[0]/okcd”)。text='transaction'
session.findById(“wnd[0