查找为给定 SAP 系统打开的 SAP GUI 会话

问题描述 投票:0回答:1

首先,在 SAP GUI 中执行某些事务之前,我想通过 VBA 检查连接是否已打开。我无法再次登录,因此我需要保持相同的连接。

其次我想打开另一个会话。如果我假设 SAP GUI 已经打开,那么第二个问题已经解决。但我不确定。因此,我需要找到一种方法来访问当前的 SAPGUI、应用程序和连接(如果存在)。如果没有,

If Not IsObject(SAPGUI) Then…
的标准代码就可以了。但是我如何正确定义这些变量来检查它们是否“填充”对象?

感谢您的帮助!

vba sap-gui
1个回答
1
投票

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

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 ConnectionGuiConnection 表示 SAP GUI 和应用程序服务器之间的连接。可以从 SAP Logon 或 GuiApplication 的 openConnection 和 openConnectionByConnectionString 打开连接 方法

所以,换句话说,GUI 连接是 SAP 系统的一种登录。通常,您的组织中拥有多个 SAP 系统。如果您遵循这些指南,您就拥有了给定系统环境的 DEV、QUAL 和 PROD。每个系统都由一个 SID 来标识

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

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

话虽如此:人们可能会想使用

guiApplication.Children(0)
,而不是像
findGuiSession
中那样循环遍历所有连接。只要您能够确保您只登录到一个 SAP 系统并且该系统是正确的,这一方法就可以发挥作用。但根据我的经验,情况往往并非如此。

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

tCode
中使用
findGuiSession
是可选的,只是强制用户使用已启动的给定 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")
© www.soinside.com 2019 - 2024. All rights reserved.