【问题标题】:Stop transaction in SAP with VBA使用 VBA 在 SAP 中停止事务
【发布时间】:2018-07-04 11:29:38
【问题描述】:

我有一个有效的 VBA 宏,它进入 SAP,启动事务,然后提取电子表格中的数据。

但有时计算运行时间过长,或者我只是想阻止它进行干预。左上角的工具栏上有一个功能,用户可以手动“停止交易”。

“停止事务”按钮是否有任何 SAP 脚本代码,这样我就可以避免手动步骤?

SAP 工具栏:

【问题讨论】:

  • 请注意,VBA 和 VBScript 是两种完全不同的语言。请澄清您的实际意思并调整您的问题和标签。
  • 问得好,但我猜你可能做不到
  • 我仍然希望有一个解决方案。我在谷歌到处搜索,但没有运气。

标签: excel vba sap-gui


【解决方案1】:

假设 VBA 宏在第一个会话中运行。如果在启动宏之前打开了第二个会话,则可以使用它来关闭第一个会话。

例如:

Set SapGuiAuto  = GetObject("SAPGUI")
Set SAPapp = SapGuiAuto.GetScriptingEngine
Set SAPconnection = SAPapp.Children(0)
Set session    = SAPconnection.Children(1)

session.findById("wnd[0]/tbar[0]/okcd").text = "/i1"
session.findById("wnd[0]").sendVKey 0
session.createSession

Application.Wait (Now + TimeValue("0:00:05"))

session.findById("wnd[0]/tbar[0]/okcd").text = "/i3"
session.findById("wnd[0]").sendVKey 0
session.createSession

Application.Wait (Now + TimeValue("0:00:05"))

是否进行“回滚”,待测试。

问候, 脚本人

【讨论】:

  • 嗨!很抱歉很晚才回复。解决了这个问题,谢谢!
【解决方案2】:

我想你最好用这个场景录制一个脚本,然后你可以随时重复使用它。 否则,我此刻正在为同样的情况而苦苦挣扎,但是如果运行时间过长,运行时间计数器部分会离开 tcode。 这也是一个很难理解的问题,但主题不同。

更新:意识到无法记录“停止事务”步骤,我应用了上述方法 - 谢谢 Script Man,这不是你第一次挽救这一天。 对于阅读此线程的任何人 - 了解如何将 SAP 运行时与 VBA 脚本运行时分开可能会很有用。 我介绍了一个对象,即“执行”命令本身。这样,SAP 接受命令并开始执行,而宏将跳过,因为它不是实际命令,而是仅应用新对象。这个技巧可以帮助用户编写时间计数器并在运行时间过长时删除会话。 作为参考,请在此处查看我的代码 - 我引用了包含相关方法的代码部分。

'check whether you already have an extra session open to close the long running session
'open one if needed
On Error Resume Next
Set session1 = Connection.Children(1)
If Err.Number <> 0 Then
   session.CreateSession
    Application.Wait (Now + TimeValue("0:00:05"))
    're-set the sessions, ensuring you use the first session for actual work and keep session1 in background
    Set session = Connection.Children(0)
    Set session1 = Connection.Children(1)
    SesCount = Connection.Sessions.Count()
    Err.Clear
On Error GoTo 0
End If

'get the ID of first session, so you can enter the correct terminating transaction code when needed
sessionID = Mid(session.ID, (InStrRev(session.ID, "[") + 1), 1)
Terminator = "/i" & sessionID + 1
session.FindById("wnd[0]").Maximize

'some code comes here

'here I use an object to apply the execute button - this way parallel with the SAP runtime, the VBA script can proceed.
perec = session.FindById("wnd[0]/tbar[1]/btn[8]").press

'here we set a loop to check whether system is busy over a certain time then we may interrupt:
Do
Application.Wait (Now + TimeValue("0:00:05"))
SecondsElapsed = SecondsElapsed + 5
fityirc = session.Busy()
if fityirc = False then
exit Do
end if
Loop Until SecondsElapsed >= 100


If fityirc = True Then
session1.FindById("wnd[0]/tbar[0]/okcd").Text = Terminator
session1.FindById("wnd[0]").sendVKey 0
End If

'...and so on. This solution is applied in a loop to extract datasets massively without human interaction.

【讨论】:

    【解决方案3】:

    或者,看看我刚刚编写和测试的代码,以使用 Windows API 运行停止事务菜单项。我在 SAP 论坛上提出了一个问题,但同时我自己也想通了 (SAP Forum)

    Private Declare PtrSafe Function FindWindowA Lib "user32.dll" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
    Private Declare PtrSafe Function GetSystemMenu Lib "user32" (ByVal hWnd As LongPtr, ByVal bRevert As Long) As LongPtr
    Private Declare PtrSafe Function GetMenuItemCount Lib "user32" (ByVal hMenu As LongPtr) As Long
    Private Declare PtrSafe Function GetMenuItemInfoA Lib "user32" (ByVal hMenu As LongPtr, ByVal un As Long, ByVal b As Long, lpMenuItemInfo As MENUITEMINFO) As Long
    Private Declare PtrSafe Function SendMessageA Lib "user32" (ByVal hWnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, lParam As Any) As LongPtr
    
    Public Const MIIM_STRING As Integer = &H40
    Public Const MIIM_ID = &H2
    Public Const WM_COMMAND = &H111
    Public Const WM_SYSCOMMAND = &H112
    
    Public Type MENUITEMINFO
        cbSize As Long
        fMask As Long
        fType As Long
        fState As Long
        wID As LongPtr
        hSubMenu As Long
        hbmpChecked As Long
        hbmpUnchecked As Long
        dwItemData As Long
        dwTypeData As String
        cch As Long
    End Type
    
    Public Function RunMenuItemByString(ByVal sMenuItem As String, _
                                        ByVal sWindowClass As String, _
                                        ByVal sWindowText As String, _
                                        ByVal iCommandType As Integer) As Boolean
    
        Dim hWnd As LongPtr, hMenu As LongPtr, lpMenuItemID As LongPtr
    
        Dim lngMenuItemCount As Long, lngMenuItem As Long, lngResultMenuItemInfo As Long
    
        Dim typMI As MENUITEMINFO
    
        Dim s As String
    
        Dim blnRet As Boolean
    
        hWnd = FindWindowA(sWindowClass, sWindowText)
    
        hMenu = GetSystemMenu(hWnd, 0&)
    
        lngMenuItemCount = GetMenuItemCount(hMenu)
    
        For lngMenuItem = 0 To lngMenuItemCount - 1
    
            typMI.cbSize = Len(typMI)
            typMI.dwTypeData = String$(255, " ")
            typMI.cch = Len(typMI.dwTypeData)
            typMI.fMask = MIIM_STRING Or MIIM_ID
            lngResultMenuItemInfo = GetMenuItemInfoA(hMenu, lngMenuItem, 1, typMI)
            s = Trim$(typMI.dwTypeData)
            lpMenuItemID = typMI.wID
            If InStr(1, s, sMenuItem, vbTextCompare) > 0 Then
                blnRet = SendMessageA(hWnd, iCommandType, lpMenuItemID, 0&) = 0
                Exit For
            End If
    
        Next lngMenuItem
    
        RunMenuItemByString = blnRet
    
    End Function
    
    Public Function TestRunMenuItemByString()
    
        lpHwndSAPSession = oSAPSession.FindById("wnd[0]").Handle
    
        sWindowText = GetWindowText(lpHwndSAPSession)
    
        TestRunMenuItemByString = RunMenuItemByString("Stop Transaction", "SAP_FRONTEND_SESSION", sWindowText, WM_SYSCOMMAND)
    
    End Function
    

    TestRunMenuItemByString 函数只能在会话启动后使用,并且只有在实际执行事务时才会起作用。您需要弄清楚如何引用您的 sap 会话对象 (oSAPSession) 才能使用其中的 Handle 值。

    声明应在 32 位和 64 位版本的 VBA 中工作,并且 LongPtr 已用于句柄 (h) 和指针 (lp) 变量以反映这一点。

    这已在 Microsoft Access 中进行了测试,但我看不出它为什么不能在其他 Office 应用程序的 VBA 中工作。我不能保证它适用于 VBScript。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-05
      相关资源
      最近更新 更多