Search code examples
excelvbasap-gui

delay SAP GUI until dialog window open


I need to use Application.Wait Now + [some time value] between commands. But sometimes it doesn't work, when SAP working too slow. How to do it? I need some Loop with Application.Wait when each dialog windows showing up.

This is my VBA code:

Sub logowanie()
    
    UserForm1.Show
    
    vSAP = Shell("C:\Program Files (x86)\SAP\FrontEnd\SAPgui\saplogon.exe", vbNormalFocus)
    Call Shell("C:\Program Files (x86)\SAP\FrontEnd\SAPgui\saplogon.exe", vbNormalFocus)
    Set WSHShell = CreateObject("WScript.Shell")
    
    Do Until WSHShell.AppActivate("SAP Logon")
    Application.Wait Now + TimeValue("0:00:01")
    Loop
    Set SapGui = GetObject("SAPGUI")
    Set Appl = SapGui.GetScriptingEngine
    
    Application.Wait Now + TimeValue("0:00:01")
    Set connection = Appl.Openconnection("xxxxxxxxxx", True)
    
    Application.Wait Now + TimeValue("0:00:02")
    WSHShell.SendKeys UserForm1.TextBox1.Value
    WSHShell.SendKeys "{TAB}"
    WSHShell.SendKeys UserForm1.TextBox2.Value
    WSHShell.SendKeys "{ENTER}"
    Application.Wait Now + TimeValue("0:00:01")
    WSHShell.SendKeys "y_ecd_96000032"
    WSHShell.SendKeys "{ENTER}"
    Application.Wait Now + TimeValue("0:00:01")
    WSHShell.SendKeys "{DOWN}"
    WSHShell.SendKeys "{DOWN}"
    WSHShell.SendKeys "{DOWN}"
    WSHShell.SendKeys "{TAB}"
    WSHShell.SendKeys "22:00:00"
    WSHShell.SendKeys "{TAB}"
    WSHShell.SendKeys "*"
    WSHShell.SendKeys "{ENTER}"
    Application.Wait Now + TimeValue("0:00:02")
    WSHShell.SendKeys "DC15"
    Application.Wait Now + TimeValue("0:00:02")
    WSHShell.SendKeys "{ENTER}"
    Application.Wait Now + TimeValue("0:00:02")
    WSHShell.SendKeys "{DOWN}"
    WSHShell.SendKeys "{TAB}"
    WSHShell.SendKeys "{TAB}"
    WSHShell.SendKeys "{ENTER}"
    Application.Wait Now + TimeValue("0:00:02")
    WSHShell.SendKeys "^{TAB}"
    WSHShell.SendKeys "{TAB}"
    WSHShell.SendKeys "{TAB}"
    WSHShell.SendKeys "{TAB}"
    WSHShell.SendKeys "{TAB}"
    WSHShell.SendKeys "{TAB}"
    WSHShell.SendKeys "{TAB}"
    WSHShell.SendKeys "{TAB}"
    WSHShell.SendKeys "{TAB}"
    WSHShell.SendKeys "{ENTER}"
    Application.Wait Now + TimeValue("0:00:02")
    WSHShell.SendKeys "U:\[...]\a.txt"
    WSHShell.SendKeys "{ENTER}"
    Application.Wait Now + TimeValue("0:00:03")
    WSHShell.SendKeys "{F8}"
    Application.Wait Now + TimeValue("0:00:03")
    WSHShell.SendKeys "{F8}"
    Application.Wait Now + TimeValue("0:00:03")
    WSHShell.SendKeys "+{F4}"
    Application.Wait Now + TimeValue("0:00:02")
    WSHShell.SendKeys "U:\[...]\SRET.xlsx"
    WSHShell.SendKeys "{ENTER}"
    'Application.Wait Now + TimeValue("0:00:03")
    WSHShell.SendKeys "{LEFT}"
    WSHShell.SendKeys "{ENTER}"
    Application.Wait Now + TimeValue("0:00:04")
    AppActivate (vSAP)
    Application.Wait Now + TimeValue("0:00:02")
    WSHShell.SendKeys "%{F4}"
    Application.Wait Now + TimeValue("0:00:02")
    WSHShell.SendKeys "{TAB}"
    WSHShell.SendKeys "{ENTER}"
    
End Sub

Solution

  • I think the easiest way is to use WinAPI to test the name of the current window. Try this:

    Public Declare Function GetForegroundWindow Lib "user32" () As Long
    Public Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal HWnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
    
    Sub Test()
        WaitForWindow "Notepad"
        Debug.Print "Notepad is opened"
    End Sub
    
    Sub WaitForWindow(Title As String)
        Dim TopWindow As String
        Do
            DoEvents
            TopWindow = WindowTitle
            Application.Wait Now + TimeValue("0:00:01")
        Loop Until InStr(1, TopWindow, WindowTitle, vbTextCompare) > 0
    End Sub
    
    Function WindowTitle()
        Dim WinText As String
        Dim HWnd As Long
        Dim L As Long
        HWnd = GetForegroundWindow()
        WinText = String(255, vbNullChar)
        L = GetWindowText(HWnd, WinText, 255)
    
        WindowTitle = Left(WinText, InStr(1, WinText, vbNullChar) - 1)
    End Function
    

    When you run the Test method, it will wait for something with Notepad in the title. Put your dialog title in the call instead.