I'm currently trying to fix some issues in a SAP procedure using VBA.
By now I have a piece of code that can correctly handle the error pop-up that sometimes appears:
If session.findById("wnd[2]/usr/txtMESSTXT1").Text = "Material já atualizado para esta operação" Then
'Saves error text
ThisWoorkbook.Worksheets("ExpandirMateriais").Cells(i, "d") = "error"
ThisWoorkbook.Worksheets("ExpandirMateriais").Cells(i, "e") = Now
ThisWoorkbook.Worksheets("ExpandirMateriais").Cells(i, "f") = session.findById("wnd[2]/usr/txtMESSTXT1").Text
'Goes to the inicial SAP window
session.findById("wnd[0]/tbar[0]/okcd").Text = "/nBPMDG/UTL_BROWSER"
session.findById("wnd[0]/tbar[0]/btn[0]").Press
'Goes to the last line of the while loop
GoTo end_while
End If
The issue is this: this error is triggered by just some of the lines of my database. If I leave the code this way, it will cause an error in the lines that don't need the error handling. I need to verify if the active session is the error pop-up and then proceed to handle the error, ie, I need something like this:
If ActiveSession.Name = "wnd[2]/usr/txtMESSTXT1" Then
If session.findById("wnd[2]/usr/txtMESSTXT1").Text = "Material já atualizado para esta operação" Then
'Saves error text
ThisWoorkbook.Worksheets("ExpandirMateriais").Cells(i, "d") = "error"
ThisWoorkbook.Worksheets("ExpandirMateriais").Cells(i, "e") = Now
ThisWoorkbook.Worksheets("ExpandirMateriais").Cells(i, "f") = session.findById("wnd[2]/usr/txtMESSTXT1").Text
'Goes to the inicial SAP window
session.findById("wnd[0]/tbar[0]/okcd").Text = "/nBPMDG/UTL_BROWSER"
session.findById("wnd[0]/tbar[0]/btn[0]").Press
'Goes to the last line of the while loop
GoTo end_while
End If
End If
but I don't know how to properly verify if the active windows is THE error window I'm working with.
I appreciate any help with this syntax.
You could use the following 2 methods to find the relevant SAP session:
the easy way
Set SapGuiAuto = GetObject("SAPGUI")
Set SapApplication = SapGuiAuto.GetScriptingEngine
Set connection = SapApplication.Children(0)
set session = SapApplication.activeSession
...
If session.Name = "wnd[2]/usr/txtMESSTXT1" Then
...
the complicated method
Set SapGuiAuto = GetObject("SAPGUI")
Set SapApplication = SapGuiAuto.GetScriptingEngine
Set connection = SapApplication.Children(0)
for mySession = 0 to connection.children.count - 1
Set ActiveSession = connection.Children(int(mySession))
If ActiveSession.Name = "wnd[2]/usr/txtMESSTXT1" Then
set session = ActiveSession
exit for
end if
next
If session.Name = "wnd[2]/usr/txtMESSTXT1" Then
...
You will have to find out for yourself which of the two methods is applicable to you.
Regards, ScriptMan
Related
I have this script below copied from a video tutorial somewhere. I recorded the SAP GUI script in 'development' system and tested. It worked fine for me. Now, when other users are trying to use the script using the 'production' system, they get
Compile error: variable not defined
in this line:
Set objConn = objGui.Children(0)
Option Explicit
Public SapGuiAuto, WScript, msgcol
Public objGui As GuiApplication
Public objConn As GuiConnection
Public session As GuiSession
Sub COGS_Report()
Set SapGuiAuto = GetObject("SAPGUI")
Set objGui = SapGuiAuto.GetScriptingEngine
Set objConn = objGui.Children(0)
Set session = objConn.Children(0)
Any tip what to modify in the code?
Regards
I had almost the same issue, where some code needed to be commented away
Try using this code that should only start IE02 transaction (Change equipment). Depending on our system and your user, SAP should respond that a Script is trying to access the Scripting object of SAP. And if you have a Session open it should pick this to use.
SystemName = "KO3" 'change as needed or use a variable
Transaction = "SESSION_MANAGER" 'change as needed or use a variable
On Error GoTo ErrorHandler:
If Not IsObject(Sap_Applic) Then
Set SapGuiAuto = GetObject("SAPGUI")
Set Sap_Applic = SapGuiAuto.GetScriptingEngine
End If
On Error GoTo 0
koniec:
qConnections = Sap_Applic.Connections.Count
If qConnections = 0 Then
MsgBox "No connection to SAP"
End
End If
'MsgBox Sap_Applic.Children(0).info.SystemName
bSession = False
For iConnectionCounter = 0 To qConnections - 1
Set Connection = Sap_Applic.Children(Int(iConnectionCounter))
'MsgBox Connection.Description
'If Not Connection.Description = "" Then
qSessions = Connection.Children.Count
For iSessionCounter = 0 To qSessions - 1
Set Session = Connection.Children(Int(iSessionCounter))
'MsgBox Session.info.SystemName
If Session.info.SystemName <> SystemName Then Exit For
If Session.info.Transaction = Transaction Then
bSession = True
Exit For
End If
Next
'End If
If bSession Then Exit For
Next
If Not bSession Then
MsgBox SystemName & " not available or free session not available"
End
End If
'Stop
Session.findById("wnd[0]").resizeWorkingPane 154, 24, False
Session.findById("wnd[0]/tbar[0]/okcd").Text = "ie02"
Session.findById("wnd[0]").sendVKey 0
Exit Sub
ErrorHandler:
MsgBox "No connection to SAP"
End
I was able to edit this code and make VBA connect with SAP.
When I make the call the code stops working on the first line of second code - Session.findById... and gives the error
Run time error 424: Object Required
Follow the codes and the error occurs on the commented line in the second code.
Full code of the SAP connection module:
Global Session
Sub SAP_Login(ByVal Transacao As String)
Dim SapGui
Dim Applic
Dim Connection
Dim Session
Dim WshShell
Dim mensagem As String
On Error GoTo DESLOGADO
Set Session = GetObject("SAPGUI").GetScriptingEngine.Children(0).Children(0)
GoTo LOGADO
DESLOGADO:
'Abre o Sap instalado na sua máquina
Shell "C:\Program Files (x86)\SAP\FrontEnd\SAPgui\saplogon.exe", vbNormalFocus
'inicia a variável com o objeto SAP
Set WshShell = CreateObject("WScript.Shell")
Do Until WshShell.AppActivate("SAP Logon ")
Application.Wait Now + TimeValue("0:00:01")
Loop
Set WshShell = Nothing
Set SapGui = GetObject("SAPGUI")
Set Applic = SapGui.GetScriptingEngine
Set Connection = Applic.OpenConnection("NEA Dow Prod - ERP Central Component (ECC) (SSO) (001)", True)
Set Session = Connection.Children(0)
Session.findById("wnd[0]").maximize
'DADOS PARA FAZER O LOGIN NO SISTEMA
'On Error Resume Next
'Session.findById("wnd[0]/usr/txtRSYST-MANDT").Text = "800" 'client do sistema
Session.findById("wnd[0]").sendVKey 0
LOGADO:
With Session
.findById("wnd[0]/tbar[0]/okcd").Text = "/o"
.findById("wnd[0]").sendVKey 0
.findById("wnd[0]/tbar[0]/okcd").Text = "/n"
.findById("wnd[0]").sendVKey 0
.findById("wnd[0]/tbar[0]/okcd").Text = Transacao
.findById("wnd[0]").sendVKey 0
'possivel texto de erro sap vai aparecer no excel
mensagem = .findById("wnd[0]/sbar").Text
If mensagem <> Empty Then
Application.StatusBar = mensagem
End If
End With
'ESSA PARTE SAI DO SISTEMA POS A EXECUÇÃO DO CÓDIGO
'Set session = Nothing
'Application.Wait Now + TimeValue("0:00:05")
'connection.CloseSession ("ses[0]")
'Set connection = Nothing
'Set sap = Nothing
End Sub
Second code that makes the call and continues the SAP script (it's on a button):
Private Sub EXTRAIR_Click()
Call SAP_Login("coois")
Session.findById("wnd[0]/mbar/menu[2]/menu[0]/menu[0]").Select 'THIS IS WHERE THE ERROR BEGINS!!!
Session.findById("wnd[1]/usr/txtENAME-LOW").Text = "nd87309"
Session.findById("wnd[1]").sendVKey 8
Session.findById("wnd[0]/usr/tabsTABSTRIP_SELBLOCK/tabpSEL_00/ssub%_SUBSCREEN_SELBLOCK:PPIO_ENTRY:1200/ctxtS_ECKST-LOW").Text = "07062022"
Session.findById("wnd[0]/usr/tabsTABSTRIP_SELBLOCK/tabpSEL_00/ssub%_SUBSCREEN_SELBLOCK:PPIO_ENTRY:1200/ctxtS_ECKST-HIGH").Text = "07062022"
Session.findById("wnd[0]").sendVKey 8
Session.findById("wnd[0]/usr/cntlCUSTOM/shellcont/shell/shellcont/shell").SetCurrentCell -1, ""
Session.findById("wnd[0]/usr/cntlCUSTOM/shellcont/shell/shellcont/shell").SelectAll
Session.findById("wnd[0]/usr/cntlCUSTOM/shellcont/shell/shellcont/shell").ContextMenu
Session.findById("wnd[0]/usr/cntlGRID1/shellcont/shell").SelectContextMenuItemByPosition "0"
Range("A2").PasteSpecial
MsgBox "Copiado com Sucesso"
End Sub
You have
Dim Session
inside SAP_Login: that variable will "hide" the Global variable with the same name, so when that sub exits the Global is still Nothing. Remove the local variable declaration so only the Global one remains.
I have a program in Microsoft Access. I have VBS script files to automate SAP GUI screens ("transactions"). Using VBA in Access opens these different VBS script files using the Scriptcontrol object and performs a transaction in a SAP system.
Now, sometimes there is an error while running the transaction and then the script stops. I have written the error handler in every VBS script files.
My goal is that if there is an error in the SAP while running .VBS then it should close the active SAP session and store the status information in a string called "ScriptStatus". Then I pull this string to the calling vba back and again run the same .vbs script.
Code in the .VBS
dim ScriptStatus
Function (DoWork)
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
on error resume Next
'SAP Code
session.findById("wnd[0]").maximize
'Furhter SAP Code
'Change the ScriptStatus to completed
ScriptStatus = "Script Completed"
If Err.Number <> 0 Then
'Change ScriptStatus
ScriptStatus = "Script Error"
'Close SAP Session
session.findById("wnd[0]").Close
End If
End Function
The code in the calling VBA
Sub Foo()
Dim vbsCode As String, result As Variant, script As Object, ScriptInfo As String
ReRunScript:
'// load vbs source
Open "x.vbs" For Input As #1
vbsCode = Input$(LOF(1), 1)
Close #1
On Error GoTo ERR_VBS
Set script = CreateObject("ScriptControl")
script.Language = "VBScript"
script.AddCode vbsCode
result = script.Run("DoWork")
ScriptInfo = script.Eval("ScriptStatus")
If ScriptInfo = "Script Completed" Then
Exit Sub
Elseif ScriptInfo = "Script Error" Then
Goto ReRunScript
End if
ERR_VBS:
MsgBox Err.Description
MsgBox script.Eval("ScriptStatus")
End Sub
Rather than running them via cscript you can execute them directly using the ScriptControl (32 bit only) - this would let you catch the errors directly in Access with a standard On Error (As well as allowing you to capture a return value).
Example .VBS file:
function DoWork
'// do some work
msgbox 1
'// error
x = 100 / 0
DoWork = "OK"
end function
VBA:
Sub Foo()
Dim vbsCode As String, result As Variant
'// load vbs source
Open "x.vbs" For Input As #1
vbsCode = Input$(LOF(1), 1)
Close #1
On Error GoTo ERR_VBS
With CreateObject("ScriptControl")
.Language = "VBScript"
.AddCode vbsCode
result = .Run("DoWork")
End With
Exit Sub
ERR_VBS:
MsgBox Err.Description
End Sub
Edit - To capture your Status variable make it global in the script (declared outside of a sub/function) and use the .Eval() method to read in in VBA.
Example .VBS file:
dim Status
function DoWork
'// do some work
msgbox 1
Status = "Hello World"
'// error
x = 100 / 0
DoWork = "OK"
end function
VBA:
Sub Foo()
Dim vbsCode As String, result As Variant, script As Object
'// load vbs source
Open "x.vbs" For Input As #1
vbsCode = Input$(LOF(1), 1)
Close #1
On Error GoTo ERR_VBS
Set script = CreateObject("ScriptControl")
script.Language = "VBScript"
script.AddCode vbsCode
result = script.Run("DoWork")
Exit Sub
ERR_VBS:
MsgBox Err.Description
'// read VBS global
MsgBox script.Eval("Status")
End Sub
I'm trying to solve a relatively straight forward problem. I would like to be able to use excel VBA to find a component in the SAP GUI window.
The Script can be found below:
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
session.findById("wnd[0]").maximize
session.findById("wnd[0]/tbar[1]/btn[42]").press
session.findById("wnd[1]/usr/txtSEARCH_BY-MATNR").text = "53211"
session.findById("wnd[1]/usr/txtSEARCH_BY-MATNR").caretPosition = 5
session.findById("wnd[1]/tbar[0]/btn[0]").press
The Code can be found below:
More Scripting here
-----------------------------------------------
For Each row In [Multi_Lvl_BOM].Rows
If (Cells(Row_Num, 1).Value = "") Then
Exit For
End If
If (row.Columns(9).Value = "N/A") Then GoTo NextIteration2b
session.findById("wnd[0]/tbar[1]/btn[42]").press
-----------------------------------------------------------
Everything works fine until here
session.findById("wnd[1]/usr/txtSEARCH_BY-MATNR").text = "53211"
-----------------------------------------------------------
On that line Excel Throws an Error
session.findById("wnd[1]/usr/txtSEARCH_BY-MATNR").caretPosition = 5
session.findById("wnd[1]/tbar[0]/btn[0]").press
NextIteration2b:
Row_Num = Row_Num + 1
Next
I recorded a script in SAP, and when I run it there, it works fine. However, when I try to use it in VBA it works until the line where I try to insert the search text. So any interaction with the new open search window would throw an error.
Could it be just a matter of a reference that I am not using? See my references below:
Any help is highly appreciated!
I am having trouble with Windows 10 and my connection code in VBA to automatically open SAP, login for me, and begin the macro, Is there a standard piece of code for Windows 10?
I have the code for the older version of Windows , but I keep getting a run time error because it doesn't exactly know what/where the new version of SAP that installed is.
If Sheets("Start").Range("E9") = "Yes" Then
On Error Resume Next
Set SapGuiAuto = CreateObject("Sapgui.ScriptingCtrl.1")
On Error GoTo 0
If SapGuiAuto Is Nothing Then
MsgBox "Please start SAPlogon"
Exit Sub
End If
On Error Resume Next
Set SAP_Applic = SapGuiAuto.GetScriptingEngine
On Error GoTo 0
If SAP_Applic Is Nothing Then
MsgBox "Scripting disabled"
Exit Sub
End If
Set Connection = SAP_Applic.OpenConnection("", True) 'Enter your system here
Set session = Connection.Children(0)
If IsObject(WScript) Then
WScript.ConnectObject session, "on"
WScript.ConnectObject SAP_Applic, "on"
End If