首先,在 SAP GUI 中执行某些事务之前,我想通过 VBA 检查连接是否已打开。我无法再次登录,因此我需要保持相同的连接。
其次我想打开另一个会话。如果我假设 SAP GUI 已经打开,那么第二个问题已经解决。但我不确定。因此,我需要找到一种方法来访问当前的 SAPGUI、应用程序和连接(如果存在)。如果没有,
If Not IsObject(SAPGUI) Then…
的标准代码就可以了。但是我如何正确定义这些变量来检查它们是否“填充”对象?
感谢您的帮助!
基于 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 Connection:GuiConnection 表示 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")