VBA SAP GUI 脚本检查 SAP 是否已经打开

VBA SAP GUI Scripting Check if SAP is already open

首先我想通过 VBA 检查,然后再在 SAP 中进行一些交易,SAP 是否已经打开。我无法第二次登录,所以我需要保持同一个连接。其次我想再开一个session。第二个问题已经解决了,如果我假设 SAP 已经打开的话。但我不确定。所以我需要找到一种方法来访问当前的 SAPGUI 和应用程序和连接,如果它们存在的话。如果不是,If Not IsObject(SAPGUI) Then…的标准代码就可以了。但是我如何正确定义这些变量以检查它们是否“已填充”Objects?

感谢帮助!

基于 S. Schnell 的script,您可以使用以下功能查找免费会话

Function findGuiSession(ByVal sapSID As String, Optional tCode As String) As SAPFEWSELib.GuiSession
    ' this will find a free session using the systemnam resp. SID
    ' and optional one can also supply a transaction to

    Dim CollCon As SAPFEWSELib.GuiComponentCollection
    Dim CollSes As SAPFEWSELib.GuiComponentCollection
    Dim guiCon As SAPFEWSELib.GuiConnection
    Dim guiSes As SAPFEWSELib.GuiSession
    
    Dim guiSesInfo As SAPFEWSELib.GuiSessionInfo
    
    Dim i As Long, j As Long
    Dim SID As String, transaction As String


    'On Error GoTo EH
    
    Dim guiApplication As SAPFEWSELib.guiApplication
    Set guiApplication = getGuiApplication
    
    If guiApplication Is Nothing Then
        Exit Function
    End If
    
    Set CollCon = guiApplication.Connections
    
    If Not IsObject(CollCon) Then
        Exit Function
    End If

    ' Loop through all existing connections
    For i = 0 To CollCon.Count() - 1

        Set guiCon = guiApplication.Children(CLng(i))

        If Not IsObject(guiCon) Then
            Exit Function
        End If

        Set CollSes = guiCon.Sessions
        If Not IsObject(CollSes) Then
            Exit Function
        End If

        ' Now loop through all existing sessions
        For j = 0 To CollSes.Count() - 1

            Set guiSes = guiCon.Children(CLng(j))
            If Not IsObject(guiSes) Then
                Exit Function
            End If

            If guiSes.Busy = vbFalse Then

                Set guiSesInfo = guiSes.Info

                If guiSesInfo.user = "" Or guiSesInfo.user = "SAPSYS" Then
                    ' Logon Screen - cannot be used
                Else
                    If IsObject(guiSesInfo) Then
                        SID = guiSesInfo.SystemName()
                        transaction = guiSesInfo.transaction()
                        ' Take the first one  - In case one could also use the transactionaction addtionally
                        If Len(tCode) = 0 Then
                            If SID = sapSID Then
                                Set findGuiSession = guiSes
                                'FindSession = True
                                Exit Function
                            End If
                        Else
                            If SID = sapSID And transaction = tCode Then
                                Set findGuiSession = guiSes
                                'FindSession = True
                                Exit Function
                            End If
                        End If
                    End If
                End If
            End If
        Next
    Next

    Exit Function

'EH:

End Function

Function getGuiApplication() As SAPFEWSELib.guiApplication
    
    On Error GoTo EH
    Set getGuiApplication = GetObject("SAPGUI").GetScriptingEngine

EH:

End Function

对于此代码 运行 您需要添加对 SAP 库的引用,描述

以下代码使用上述函数连接到名为 P11 的系统,启动事务 MB52 并将结果下载到 Excel 文件

Option Explicit

    Sub getMB52_data()
    
        Dim guiSes As SAPFEWSELib.GuiSession
        Set guiSes = getGuiSession("P11")
        
        If Not guiSes Is Nothing Then
            
            With guiSes
                .StartTransaction "MB52"
                .FindById("wnd[0]/usr/ctxtMATNR-LOW").Text = "<MATNR_LOW<"  ' replace with a material nr
                .FindById("wnd[0]/usr/ctxtMATNR-HIGH").Text = "<MATNR_HIGH<"  ' replace with a material nr
                .FindById("wnd[0]/usr/ctxtWERKS-LOW").Text = "<WERKS>"  ' replace wiht a plant  
                .FindById("wnd[0]/tbar[1]/btn[8]").Press
                .FindById("wnd[0]/tbar[0]/okcd").Text = "&XXL"
                .FindById("wnd[0]/tbar[0]/btn[0]").Press
                .FindById("wnd[1]/tbar[0]/btn[0]").Press
                .FindById("wnd[1]/usr/ctxtDY_PATH").Text = "<xlPath>" ' Pathname   
                .FindById("wnd[1]/usr/ctxtDY_FILENAME").Text = "<xlFile>"  ' filename
                .FindById("wnd[1]/tbar[0]/btn[11]").Press
            End With
            
        Else
            MsgBox "No free SAP Session", vbOKOnly + vbInformation, "SAP Verbindung"
        End If
    
    End Sub
Function getGuiSession(sapSID As String, Optional tCode As String) As SAPFEWSELib.GuiSession

    Dim guiApp As SAPFEWSELib.guiApplication
    Set guiApp = getGuiApplication

    If Not guiApp Is Nothing Then
        Set getGuiSession = findGuiSession(sapSID, tCode)
    End If

End Function

补充说明:(希望能回答评论中的一些问题)

Gui Connection: GuiConnection代表SAP GUI和应用服务器之间的连接。可以从 SAP Logon 或 GuiApplication 的 openConnection 和 openConnectionByConnectionString 打开连接 方法

因此,换句话说,GUI 连接是一种登录 SAP 系统的方式。通常您的组织中有多个 SAP 系统。如果您遵循指南,您将拥有针对给定系统环境的 DEV、QUAL 和 PROD。每个系统都由 SID

标识

什么是 SID? SID是每个R/3安装(SAP系统)的唯一标识码,由一个数据库服务器和多个应用程序服务器组成。 SID 代表 SAP 系统标识。 SAPSID — three-character 代码,例如 C11、PRD、E56 等)

SID 在组织内是唯一的。通常 SAP 许可证只允许一个用户登录生产系统一次,即你不能在不同的计算机上使用同一个用户,你甚至不能在同一台计算机上用同一个用户登录 SAP 系统两次。

话虽如此:人们可能会想使用 guiApplication.Children(0) 而不是像 findGuiSession 那样遍历所有连接。只要您可以确保您只登录到一个 SAP 系统并且它是正确的,这就会起作用。但根据我的经验,情况通常并非如此。

findGuiSession中的参数SID告诉函数要查找哪个系统。如上所述,SID 是唯一的,因此可以识别您要使用的系统。

findGuiSession 中使用 tCode 是可选的,只是强制用户在给定的 tCode 已经启动的情况下进行会话。我很少用这个。

OpenConnection:如果你用函数OpenConnection("<SYSTEM>")打开一个连接,你当然可以使用返回的对象为了使用它。但是,如果您在您的组织中有一种单点登录,这只会登录到系统。否则,您必须提供登录凭据。我不使用它,因为我不想处理它。并且在登录期间请求更改密码也可能发生,我肯定不想编写脚本。

示例代码

Rem Open a connection in synchronous mode
Set Connection = Application.OpenConnection( "U9C [PUBLIC]", True)
Set Session = Connection.Children(0)
Rem Do something: Either fill out the login screen 
Rem or in case of Single-Sign-On start a transaction.
Session.SendCommand( "/nbibs")