Skip to Content

Activating the SAP window

Hi All,

I have a script which I run from Excel and it works fine... it simply opens a work order, the only problem is that the SAP window is not activated?

The line Session.findByID("wnd[0]").maximize  doesn't display the SAP window?

I can Alt Tab to the window and it showing what I want but how do I do this as part of the macro.

What am I missing here?

Regards

Steve Bayliss

Add comment
10|10000 characters needed characters exceeded

  • Get RSS Feed

2 Answers

  • Best Answer
    Jan 08, 2016 at 06:09 PM

    Hello.

    Setup two functions. ActivateWindow and DeActivateWindow:

    Public Declare Function FindWindow Lib "user32" Alias _
        "FindWindowA" (ByVal lpClassName As String, _
                       ByVal lpWindowName As String) As Long
                      
    Public Declare Function GetWindowPlacement Lib "user32" _
        (ByVal hwnd As Long, lpwndpl As WINDOWPLACEMENT) As Long
       
    Public Declare Function SetWindowPlacement Lib "user32" _
        (ByVal hwnd As Long, lpwndpl As WINDOWPLACEMENT) As Long
       
    Public Declare Function SetForegroundWindow Lib "user32" _
        (ByVal hwnd As Long) As Long
       
    Public Declare Function GetForegroundWindow Lib "user32" () As Long

    Public Declare Function BringWindowToTop Lib "user32" _
        (ByVal hwnd As Long) As Long   

    Const SW_SHOWNORMAL = 1
    Const SW_SHOWMINIMIZED = 2

    Public Type POINTAPI
        X As Long
        Y As Long
    End Type

    Public Type RECT
        Left As Long
        Top As Long
        Right As Long
        Bottom As Long
    End Type

    Public Type WINDOWPLACEMENT
        Length As Long
        flags As Long
        showCmd As Long
        ptMinPosition As POINTAPI
        ptMaxPosition As POINTAPI
        rcNormalPosition As RECT
    End Type

    Public Function ActivateWindow(xhWnd&) As Boolean

        Dim Result&, WndPlcmt As WINDOWPLACEMENT
     
        With WndPlcmt
       
            .Length = Len(WndPlcmt)
            Result = GetWindowPlacement(xhWnd, WndPlcmt)
           
            If Result Then
           
                If .showCmd = SW_SHOWMINIMIZED Then
                    .flags = 0
                    .showCmd = SW_SHOWNORMAL
                    Result = SetWindowPlacement(xhWnd, WndPlcmt)
                  Else
                    Call SetForegroundWindow(xhWnd)
                    Result = BringWindowToTop(xhWnd)
                End If
               
                If Result Then ActivateWindow = True
               
            End If
           
        End With
       
      End Function

    Public Function DeActivateWindow(xhWnd&) As Boolean

        Dim Result&, WndPlcmt As WINDOWPLACEMENT
     
        With WndPlcmt
       
            .Length = Len(WndPlcmt)
            Result = GetWindowPlacement(xhWnd, WndPlcmt)
           
            If Result Then
                    .flags = 0
                    .showCmd = SW_SHOWMINIMIZED
                    Result = SetWindowPlacement(xhWnd, WndPlcmt)
                    If Result Then DeActivateWindow = True
            End If
           
        End With
       
    End Function

    Then you can set Windows in fore- and/or background.

    SessionHWND = Session.FindById("wnd[0]").Handle
    ActivateWindow (SessionHWND)

    'Start of your code
          'Your code
    'End of your code

    DeActivateWindow (SessionHWND)
    ActivateWindow (Application.hwnd) 'ExcelWBInFront

    Best regards

    Holger

    Add comment
    10|10000 characters needed characters exceeded

  • Jan 12, 2016 at 08:53 PM

    I wrote a little bit of code to pull some material master text data from SAP that I could not retrieve in any other way but via a specific transaction.

    Dim session

    Function NOTES()

    Dim DataObj As MSForms.DataObject

    Set DataObj = New MSForms.DataObject

    Dim Application

    Dim material, plant As String

    Dim xMATERIAL As String

    Dim sbarmessage As String

    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

    If Not IsObject(session) Then

       Set session = Connection.Children(0)

    End If

    If IsObject(WScript) Then

       WScript.ConnectObject session, "on"

       WScript.ConnectObject Application, "on"

    End If

        InputRow = InputBox("Enter the Starting Row", "Starting Row", 3)

        Row = CInt(InputRow)

    xMATERIAL = Worksheets("NOTES").Cells(Row, 1)

    While xMATERIAL <> ""

        xMATERIAL = Worksheets("NOTES").Cells(Row, 1)

        xNOTES = Worksheets("NOTES").Cells(Row, 2)

                Call ClearClipboard

            session.findById("wnd[0]/tbar[0]/okcd").Text = "/nmd04"

            session.findById("wnd[0]").sendVKey 0

            session.findById("wnd[0]/usr/tabsTAB300/tabpF01/ssubINCLUDE300:SAPMM61R:0301/ctxtRM61R-MATNR").Text = xMATERIAL

            session.findById("wnd[0]/usr/tabsTAB300/tabpF01/ssubINCLUDE300:SAPMM61R:0301/ctxtRM61R-WERKS").Text = "VQ02"

                AppActivate "Stock/Requirements List: Initial Screen"

            session.findById("wnd[0]").sendVKey 0

            session.findById("wnd[0]/usr/subINCLUDE8XX:SAPMM61R:0800/btnRM61R-MNTXT").press

            SendKeys ("^(a)")

                Call Wait

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

            DataObj.GetFromClipboard

            On Error Resume Next

            myString = DataObj.GetText(1)

    Whoa:

            If Err <> 0 Then

                Err.Clear

                GoTo ADVANCE

            End If

            Worksheets("NOTES").Cells(Row, 2).Select

            Worksheets("NOTES").Cells(Row, 2) = myString

    ADVANCE:

            X = X + 1

            Row = Row + 1

            xMATERIAL = Worksheets("NOTES").Cells(Row, 1)

            Worksheets("NOTES").Cells(Row, 1).Select

    Wend

    End Function

    Sub Wait()

        l = 1

        While l < 10000

            l = l + 1

            Wend

    End Sub

    I had a second module stating the following:

    Private Declare Function OpenClipboard Lib "User32.dll" _

    (ByVal hWndNewOwner As Long) As Long

    Private Declare Function EmptyClipboard Lib "User32.dll" () As Long

    Private Declare Function CloseClipboard Lib "User32.dll" () As Long

        Public Function ClearClipboard()

            Dim Ret

            Ret = OpenClipboard(0&)

            If Ret <> 0 Then Ret = EmptyClipboard

            CloseClipboard

        End Function

    Anyway... after putting all of that down... What i want to say is that you can call the specific window you're looking for by the specific name.  In my script, i was running transaction MD04 to access material plant data.  That transaction labels as "Stock/Requirements List: Initial Screen".  It can be called via:

    AppActivate "Stock/Requirements List: Initial Screen"


    Likewise, if i had wanted to open a work order, I could have called via:


    AppActivate "Change Order: Initial Screen"


    So long as you had navigated to that transaction in SAP prior to enabling it, you would have had an active IW32 screen for order maintenance.

    The rest of my code was for manipulation of the clipboard data and clearing in order to enter multiple lines or paragraphs of information into a single Excel cell.  Excel tends to spread data over multiple cells.  My script modifies the clipboard data to bypass that.

    Anyway... that's how i called MD04 directly via AppActivate.

    Add comment
    10|10000 characters needed characters exceeded

    • If the script starts from Excel the object session knows, which sessionnumber it is. And this session has to be once again minimized and then maximized. Here is no need to search for the window name.