on 01-06-2016 12:51 AM
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
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
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Steve and the other,
although a solution already exists, I would like to contribute a small example of me.
for example:
'vbs version:
myString = "SAP Easy Access"
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
for mySession = 0 to connection.children.count - 1
Set session = connection.Children(int(mySession))
Position = instr(1,session.findById("wnd[0]").text,myString)
if Position <> 0 then exit for
next
if Position <> 0 then
session.findById("wnd[0]").iconify
session.findById("wnd[0]").maximize
end if
'excel version:
myString = "SAP Easy Access"
Set SapGuiAuto = GetObject("SAPGUI")
Set SapApplication = SapGuiAuto.GetScriptingEngine
Set Connection = SapApplication.Children(0)
Set session = Connection.Children(0)
For mySession = 0 To Connection.Children.Count - 1
Set session = Connection.Children(Int(mySession))
Position = InStr(1, session.findById("wnd[0]").Text, myString)
If Position <> 0 Then Exit For
Next
If Position <> 0 Then
session.findById("wnd[0]").iconify
session.findById("wnd[0]").maximize
End If
The variable myString does not contain the complete name of the SAP window. It reaches only a small part of this. The uppercase and lowercase letters are considered.
In other words:
If after the command ...maximize the SAP window in the foreground is to come, must first be generated the command ... iconify.
Regards,
ScriptMan
Yes, that is how it works.
There is only a small risk if you have an Excel file or SAP session with same/similar Name. Then it could be that you will not activate the Scripting-active session.
This issue was root cause why I switch using User32 API functions and take window handle. This defintely will maximize and activate window in scope.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.