【问题标题】:Open 2 SAP windows in parallel并行打开 2 个 SAP 窗口
【发布时间】:2026-02-10 09:10:02
【问题描述】:

我想打开 2 个 SAP GUI 窗口并设置相同的事务,但上面有不同的信息。

我知道使用 VBA/VBS 不可能同时运行这些窗口(就像我在这里看到的其他帖子一样),但我不需要它运行,我只需要使用不同信息设置每个窗口的脚本。我可以在设置后手动运行它。

我编写了以下代码:

Sub YI19Nreport()
Dim app As Object
Dim connection As Object
Dim session As Object
Dim plant As String

Set SapGuiAuto = GetObject("SAPGUI")
Set app = SapGuiAuto.GetScriptingEngine
Set connection = app.Children(0)
Set session = connection.Children(0)

Set objExcel = GetObject(, "Excel.Application")
Set objSheet = objExcel.Workbooks("Book1.xlsm").Sheets("Sheet1")

'''''Opening first YI19N
session.ActiveWindow().findById("wnd[0]/tbar[0]/okcd").Text = "/nyi19n"
session.ActiveWindow().findById("wnd[0]").sendVKey 0

session.findById("wnd[0]/usr/btn%_S_WERKS_%_APP_%-VALU_PUSH").press
plant = Workbooks("Book1.xlsm").Sheets("Sheet1").Cells(2, 4)

session.findById("wnd[1]/usr/tabsTAB_STRIP/tabpSIVA/ssubSCREEN_HEADER:SAPLALDB:3010/tblSAPLALDBSINGLE/ctxtRSCSEL_255-SLOW_I[1,0]").Text = plant

session.findById("wnd[1]/tbar[0]/btn[8]").press

'''''Opening second YI19N    
session.ActiveWindow().findById("wnd[0]/tbar[0]/okcd").Text = "/oyi19n"
session.ActiveWindow().findById("wnd[0]").sendVKey 0

session.findById("wnd[0]/usr/btn%_S_WERKS_%_APP_%-VALU_PUSH").press
plant = Workbooks("Book1.xlsm").Sheets("Sheet1").Cells(3, 4)
session.findById("wnd[1]/usr/tabsTAB_STRIP/tabpSIVA/ssubSCREEN_HEADER:SAPLALDB:3010/tblSAPLALDBSINGLE/ctxtRSCSEL_255-SLOW_I[1,0]").Text = plant

session.findById("wnd[1]/tbar[0]/btn[8]").press
End Sub

使用此代码,SAP 打开第一个窗口,输入信息,而不是打开第二个窗口,而是使用第二个窗口所需的字符串完成第一个窗口信息,然后打开第二个窗口并完成 Sub。

我认为这与在 Sub 开头设置的“children”信息有关。

如果有人可以帮助我,那就太好了。

【问题讨论】:

  • 你知道那个“第二个窗口”的ID吗? “第二个”需要哪个字符串? “/oyi19n”?
  • @FaneDuru 字符串“/o...”触发新窗口打开,“...yi19n”是我使用的事务。
  • @SandraRossi 抱歉,我是 SAP/VBA 脚本的新手。我没明白你说的事件是什么意思,是编码吗?
  • 您是否先尝试“/o”,创建一个新会话,然后设置事务?
  • @FaneDuru 是的!我尝试只打开会话,但它一直忽略此命令,在同一会话上完成版本,然后打开新会话(没有事务)。

标签: excel vba scripting sap-gui


【解决方案1】:

我过去处理过类似的话题。它是关于确定 SAP 事务是否可以使用 VBA 并行执行。如果是这样,与 SAP 事务的串行执行相比,它在时间方面节省了多少。

您只能通过变通方法来解决它。这包括从 VBA 程序启动 VB 脚本。

查看我的示例并尝试找出如何将其应用于您的问题。

例如:

Sub Parallel_Sessions()
Set SapGuiAuto = GetObject("SAPGUI")
Set SAP_Application = SapGuiAuto.GetScriptingEngine
Set Connection = SAP_Application.Children(0)
Set session = Connection.Children(0)
Set wshell = CreateObject("Wscript.Shell")

Time_1 = TimeValue(Time)

For mysession = 0 To 5
 Set session = Connection.Children(Int(mysession))
 session.findById("wnd[0]").maximize
 session.findById("wnd[0]/tbar[0]/okcd").Text = "/nreiscn"
 session.findById("wnd[0]").sendVKey 0
 session.findById("wnd[0]/usr/ctxtS_BUKRS-LOW").Text = "2000"
 session.findById("wnd[0]/usr/chkP_USEPTN").SetFocus
 session.findById("wnd[0]/usr/chkP_USEPTN").Selected = True
 session.findById("wnd[0]/usr/chkP_GRID").Selected = True
 session.findById("wnd[0]/usr/chkP_DSPBUP").Selected = True
 session.findById("wnd[0]/usr/ctxtSO_PARTN-LOW").Text = "1"
 session.findById("wnd[0]/usr/ctxtSO_PARTN-HIGH").Text = "1000"
 session.findById("wnd[0]/usr/chkP_DSPBUP").SetFocus

 If mysession < 5 Then session.createSession

 waitTill = Now() + TimeValue("00:00:03")
 While Now() < waitTill
   DoEvents
 Wend

 If mysession = 5 Then
    session.findById("wnd[0]/tbar[1]/btn[8]").press
 Else
    wshell.Run """c:\tmp\Script_parallel_Sessions.vbs""" & " " & mysession
 End If

Next

Time_2 = TimeValue(Time)
Time_0 = Round((Time_2 - Time_1) * 24 * 3600, 2)

MsgBox "This run for 6 sessions lasted " & Time_0 & " s ", vbInformation + vbMsgBoxForeground, "Note"
End Sub

Script_parallel_Sessions.vbs:

If Not IsObject(application) Then
   Set SapGuiAuto  = GetObject("SAPGUI")
   Set application = SapGuiAuto.GetScriptingEngine
End If
If Not IsObject(connection) Then
   Set connection = application.Children(0)
End If
for mysession  = 0 to 5
    if cstr(mysession) = cstr(wscript.arguments(0)) then
       Set session    = connection.Children(int(mysession))
       session.findById("wnd[0]/tbar[1]/btn[8]").press
    end if 
next

现在是串行处理:

Sub Seriell_Sessions()
Set SapGuiAuto = GetObject("SAPGUI")
Set SAP_Application = SapGuiAuto.GetScriptingEngine
Set Connection = SAP_Application.Children(0)
Set session = Connection.Children(0)

Time_1 = TimeValue(Time)
For mysession = 0 To 5
 Set session = Connection.Children(Int(mysession))
 session.findById("wnd[0]").maximize
 session.findById("wnd[0]/tbar[0]/okcd").Text = "/nreiscn"
 session.findById("wnd[0]").sendVKey 0
 session.findById("wnd[0]/usr/ctxtS_BUKRS-LOW").Text = "2000"
 session.findById("wnd[0]/usr/chkP_USEPTN").SetFocus
 session.findById("wnd[0]/usr/chkP_USEPTN").Selected = True
 session.findById("wnd[0]/usr/chkP_GRID").Selected = True
 session.findById("wnd[0]/usr/chkP_DSPBUP").Selected = True
 session.findById("wnd[0]/usr/ctxtSO_PARTN-LOW").Text = "1"
 session.findById("wnd[0]/usr/ctxtSO_PARTN-HIGH").Text = "1000"
 session.findById("wnd[0]/usr/chkP_DSPBUP").SetFocus

 If mysession < 5 Then session.createSession

 waitTill = Now() + TimeValue("00:00:03")
 While Now() < waitTill
   DoEvents
 Wend

 session.findById("wnd[0]/tbar[1]/btn[8]").press

Next
Time_2 = TimeValue(Time)
Time_0 = Round((Time_2 - Time_1) * 24 * 3600, 2)
MsgBox "This run for 6 sessions lasted " & Time_0 & " s ", vbInformation + vbMsgBoxForeground, "Note"
End Sub

问候,脚本人

【讨论】:

    【解决方案2】:

    您可以定义GuiApplication 对象的事件CreateSession 的处理程序。

    以下代码是从链接中提取的 VBScript,经过调整后,全局对象 lastOpenedSession 使用上次打开的会话进行初始化:

    Dim lastOpenedSession ' Global GuiSession object
    Dim objSapGui
    Set objSapGui = GetObject("SAPGUI")
    
    Dim objScriptingEngine
    Set objScriptingEngine = objSapGui.GetScriptingEngine
    WScript.ConnectObject objScriptingEngine,  "Engine_"
    
    Dim Waiting
    Waiting = 1
    
    Do While (Waiting = 1)
     WScript.Sleep(100)
    Loop
    
    Set objScriptingEngine = Nothing
    Set objSapGui = Nothing
    
    Sub Engine_CreateSession(ByVal Session)
      Dim result
      Set lastOpenedSession = Session
      result = MsgBox("Session created", vbOKCancel)
      If result = vbCancel then
        Waiting = 0
      End If
    End Sub
    

    等效的 VBA 代码是:

    • 创建类模块AppHandler:
    Private WithEvents app_ As SAPFEWSELib.GuiApplication
    Private Sub app_CreateSession(ByVal session As SAPFEWSELib.GuiSession)
      Dim result
      Set lastOpenedSession = Session
      result = MsgBox("Session created", vbOKCancel)
      If result = vbCancel then
        Waiting = 0
      End If
    End Sub
    
    • 主要代码:
    Dim lastOpenedSession ' Global GuiSession object
    Dim objSapGui
    Set objSapGui = GetObject("SAPGUI")
    
    Dim objScriptingEngine
    Set objScriptingEngine = objSapGui.GetScriptingEngine
    Set objAppHandler = New AppHandler
    Set objAppHandler.app_ = objScriptingEngine
    
    Dim Waiting
    Waiting = 1
    
    Do While (Waiting = 1)
     Application.Sleep(100)
    Loop
    
    Set objAppHandler = Nothing
    Set objScriptingEngine = Nothing
    Set objSapGui = Nothing
    

    【讨论】:

    • 非常感谢您的解释!但我无法在我的文件中运行此脚本,是否需要设置不同的“引用”?
    • 再次感谢您,我会花点时间研究您的答案,有很多我不熟悉的功能:)