簡體   English   中英

使用 VBA 在 SAP 中停止事務

[英]Stop transaction in SAP with VBA

我有一個工作的 VBA 宏,它進入 SAP,啟動一個事務,然后在電子表格中提取數據。

但有時計算運行時間太長,或者我只是想阻止它進行干預。 左上角的工具欄上有一個功能,用戶可以在其中手動“停止交易”。

“停止交易”按鈕是否有任何 SAP 腳本代碼,以便我可以避免手動步驟?

SAP工具欄:

SAP 工具欄

假設 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"))

無論是否進行“回滾”,都需要進行測試。

問候, ScriptMan

我想你最好用這個場景錄制一個腳本,然后你可以隨時重復使用它。 否則,我目前正在為同樣的情況苦苦掙扎,但如果運行時間過長,運行時間計數器部分將離開 tcode。 這也是一個棘手的問題,但這是一個不同的話題。

更新:意識到無法記錄“停止交易”步驟,我應用了上述方法 - 謝謝腳本人,這不是你第一次挽救這一天。 對於閱讀此線程的任何人 - 了解如何從 VBA 腳本運行時拆分 SAP 運行時可能很有用。 我引入了一個對象,它是“執行”命令本身。 這樣,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.

或者,查看我剛剛編寫並測試的代碼,以使用 Windows API 運行“停止事務”菜單項。 我在 SAP 論壇上提出了一個關於它的問題,但同時我自己想通了( SAP 論壇

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。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM