Perte de la fenetre SAP apres login
Bonjour à tous,
J’ai besoin d’un petit coup de pouce concernant un problème dont je ne comprends pas l’origine.
Je développe une macro pour automatiser des actions répétitives. Globalement, je souhaite que la macro :
- Lance SAP
- Ouvre le serveur défini
- Connecte l’utilisateur
- Ouvre une transaction spécifique
- Renseigne des données prédéfinies dans les champs
- Exécute la transaction
- Récupère une valeur donnée
- Copie cette valeur dans une colonne
Les trois premières étapes fonctionnent parfaitement. Cependant, une fois connecté au serveur, la fenêtre SAP n’est plus trouvée par la macro.
La fenêtre est pourtant bien ouverte : "SAP Easy Access - xxx" (xxx étant le nom de l’utilisateur).
J’obtiens alors le message d’erreur suivant :
"La méthode 'FindById' de l'objet 'ISapSessionTarget' a échoué"
A la ligne suivante :
session.findById("wnd[0]").SetFocusVoici ma macro :
#If VBA7 Then
Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As LongPtr)
#Else
'Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#End If
Sub ConnectToSAP()
Dim SapGuiAuto As Object
Dim application As Object
Dim connection As Object
Dim session As Object
Dim user As String
Dim password As String
' Lancer l'application SAP
Shell "C:\Program Files (x86)\SAP\FrontEnd\SAPGUI\saplogon.exe", vbNormalFocus
' Pause pour permettre le lancement de l'application
Sleep 5000 ' Pause de 5 secondes pour permettre le lancement complet de l'application
' Récupérer les informations de connexion
user = Range("A1").Value
password = Range("A2").Value
' Initialiser SAP GUI
Set SapGuiAuto = GetObject("SAPGUI")
Set application = SapGuiAuto.GetScriptingEngine
Set connection = application.OpenConnection("nom_serveur", False)
Set session = connection.Children(0)
' Se connecter à SAP
session.findById("wnd[0]/usr/txtRSYST-BNAME").Text = user
session.findById("wnd[0]/usr/pwdRSYST-BCODE").Text = password
session.findById("wnd[0]/tbar[0]/btn[0]").press
' Pause pour permettre la connexion
Sleep 1000 ' Pause de 1 seconde pour permettre la connexion
session.findById("wnd[0]").SetFocus
session.findById("wnd[0]/tbar[0]/okcd").Text = "nom_transaction"
session.findById("wnd[0]").sendVKey 0
MsgBox "Transaction ouverte."
End SubMerci infiniment pour votre aide :)
Bonjour florentdoug,
Ca m'intéresse
perso, je n'ai jamais réussi à me connecter à SAP via le VBA
J'ai une boite de dialogue que demande à l'utilisateur s'il est bien sur le menu principal SAP, il a juste à cliquer sur "OUI" pour lancer la procédure
A+
Effectivement, je n’en suis pas encore à l’étape de l’auto-connexion via VBA, et ce n’est d’ailleurs pas l’objectif de ma démarche.
Dans ma macro, j’utilise un simple copier-coller pour renseigner les champs « utilisateur » et « mot de passe », en lisant les informations contenues dans les cellules A1 et A2. Cette partie fonctionne correctement.
Le problème survient après l’authentification : une fois la fenêtre principale (SAP Easy Access) ouverte, la macro ne parvient plus à retrouver la session active. Elle semble « perdue » à ce stade.
Re,
C'est bien ce que j'essayais de vous dire
Effectivement, je n’en suis pas encore à l’étape de l’auto-connexion via VBA
Ou alors, vous ne comprenez pas ce que vous faites et vous codez...
Entrer le login et mot de passe d'un utilisateur est à mes yeux un connexion à l'interface, après vous l'appelez comme vous voulez !
Je me suis confronté à un mur sur ce sujet, j'ai donc laissé tombé.
L'utilisateur à juste à lancer sa session, avant de lancer la macro
Bonne soirée
Effectivement, nous ne nous étions pas bien compris. Je pensais que tu voulais intégrer une connexion en arrière-plan, par exemple en récupérant les données depuis une autre base de données : quelque chose de transparent pour l’utilisateur. Mais je comprends mieux ton point maintenant.
Cela dit, c’est une remarque intéressante : même si l’utilisateur est connecté et que la page SAP Easy Access est ouverte, VBA ne parvient pas à détecter cette fenêtre.
Serais-tu en mesure de me partager ton code, afin que je puisse éventuellement m’inspirer de ta logique ?
Re,
Alors voici déjà le lien que j'avais trouvé
https://simpleexcelvba.com/sap-session-findbyid-10-code-lines-you-can-identify/
Ensuite, voici un des codes que j'utilise (pour créer une commande client)
Mais dedans, j'utilise des fonctions perso que j'ai créé et ne veut pas partager
Sub CréerCommande(Sh As Worksheet, Lig As Long)
Dim sDevis As String, sCde As String, sDateCde As String, sTmp As String
' Variables objet pour SAP
Dim App, Connection, Session, Wscript
Dim SapGui As Object
' Demander à l"utilisateur avant lancement
If MsgBox("Vous devez être sur le menu général de SAP !" & vbCr & vbCr _
& "Avant de continuer, est-ce bien le cas ?", vbQuestion + vbYesNo, "ATTENTION...") = vbNo Then Exit Sub
' Si OK, minimiser cette fenêtre
ThisWorkbook.Windows.Application.WindowState = xlMinimized
FlgOk = False
' Suite pour SAP
If Not IsObject(App) Then
Set SapGui = GetObject("SAPGUI")
Set App = SapGui.GetScriptingEngine
End If
If Not IsObject(Connection) Then
Set Connection = App.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 App, "on"
End If
Session.findById("wnd[0]/tbar[0]/okcd").Text = "VA01"
Session.findById("wnd[0]").sendVKey 0
Session.findById("wnd[0]/usr/ctxtVBAK-AUART").Text = "ZI01"
Session.findById("wnd[0]/usr/ctxtVBAK-VKORG").Text = "IERS"
Session.findById("wnd[0]/usr/ctxtVBAK-VTWEG").Text = "TD"
sTmp = "": sTmp = ValChamp(Sh, Lig, "Seg. Métier")
Session.findById("wnd[0]/usr/ctxtVBAK-SPART").Text = sTmp
sTmp = "": sTmp = VParam("ParamCodeAV")
Session.findById("wnd[0]/usr/ctxtVBAK-VKBUR").Text = sTmp
Session.findById("wnd[0]/usr/ctxtVBAK-VKGRP").Text = sTmp
Session.findById("wnd[0]").sendVKey 0
Application.Wait Now + TimeValue("00:00:02") ' Attendre
sTmp = "": sTmp = ValChamp(Sh, Lig, "Code Client DO") ' Donneur d'ordre
Session.findById("wnd[0]/usr/subSUBSCREEN_HEADER:SAPMV45A:4021/subPART-SUB:SAPMV45A:4701/ctxtKUAGV-KUNNR").Text = sTmp
Session.findById("wnd[0]").sendVKey 0
If sTmp = "1287" Then
Application.Wait Now + TimeValue("00:00:01") ' Attendre
'Session.findById("wnd[1]/usr/lbl[4,8]").SetFocus
'Session.findById("wnd[1]/usr/lbl[4,8]").caretPosition = 1
Session.findById("wnd[1]/usr/lbl[4,9]").SetFocus
'Session.findById("wnd[1]/usr/lbl[4,9]").caretPosition = 7
Session.findById("wnd[1]").sendVKey 2
End If
' Vérifier si message blocage
Dim MsgSAP As String
MsgSAP = Session.findById("wnd[0]/sbar").Text
If InStr(1, MsgSAP, "blocage", vbTextCompare) > 0 Then
' Maximise ce classeur
ThisWorkbook.Windows.Application.WindowState = xlMaximized
' Message
MsgBox "Un blocage de client c'est produit !" & vbCr _
& " Merci de vérifier son statut dans SAP", vbCritical, "OUPS..."
FlgOk = False
GoTo FinProc
End If
' Si aucun message = SAP est bloqué et pas de Réceptionnaire
sTmp = Session.findById("wnd[0]/usr/subSUBSCREEN_HEADER:SAPMV45A:4021/subPART-SUB:SAPMV45A:4701/ctxtKUWEV-KUNNR").Text
If MsgSAP = "" And sTmp = "" Then
ThisWorkbook.Windows.Application.WindowState = xlMaximized
MsgBox "SAP est bloqué sur une fenêtre," & vbCr _
& " merci de débloquer SAP puis de cliquer sur OK", vbExclamation, "BLOCAGE"
ThisWorkbook.Windows.Application.WindowState = xlMinimized
End If
' Clic sur bouton Valider [ENTREE]
'Session.findById("wnd[1]/tbar[0]/btn[0]").press
' Devis
sDevis = ValChamp(Sh, Lig, "Devis n°")
' Réf. Commande
sCde = "": sCde = ValChamp(Sh, Lig, "Commande n°")
sDateCde = "": sDateCde = Replace(ValChamp(Sh, Lig, "Date Cde"), "/", ".")
' Si la commande est un BPA
If InStr(1, sCde, "BPA", vbTextCompare) > 0 Then
sTmp = "BPA S/DEVIS " & Replace(sDevis, "02.", "")
Else
sTmp = sCde
End If
Session.findById("wnd[0]/usr/subSUBSCREEN_HEADER:SAPMV45A:4021/txtVBKD-BSTKD").Text = sTmp
sTmp = "": sTmp = ValChamp(Sh, Lig, "Date Cde"): sTmp = Replace(sTmp, "/", ".")
Session.findById("wnd[0]/usr/subSUBSCREEN_HEADER:SAPMV45A:4021/ctxtVBKD-BSTDK").Text = sTmp
Session.findById("wnd[0]/usr/tabsTAXI_TABSTRIP_OVERVIEW/tabpT\01/subSUBSCREEN_BODY:SAPMV45A:4400/subHEADER_FRAME:SAPMV45A:4440/ctxtVBKD-PRSDT").Text = sTmp
Session.findById("wnd[0]").sendVKey 0
Session.findById("wnd[0]").sendVKey 0
' Commande individuelle
On Error Resume Next
Session.findById("wnd[0]/usr/tabsTAXI_TABSTRIP_OVERVIEW/tabpT\01/subSUBSCREEN_BODY:SAPMV45A:4400/subHEADER_FRAME:SAPMV45A:4440/cmbVBAK-AUGRU").Key = "Z00"
' En cas de blocage avec la fenêtre d'information
If Err.Number <> 0 Then
Err.Clear: On Error GoTo 0
Session.findById("wnd[0]").sendVKey 0
Session.findById("wnd[0]").sendVKey 0
Session.findById("wnd[0]/usr/tabsTAXI_TABSTRIP_OVERVIEW/tabpT\01/subSUBSCREEN_BODY:SAPMV45A:4400/subHEADER_FRAME:SAPMV45A:4440/cmbVBAK-AUGRU").Key = "Z00"
End If
On Error GoTo 0
' Changer l'eOTP
sTmp = "": sTmp = ValChamp(Sh, Lig, "eOTP")
Session.findById("wnd[0]/usr/tabsTAXI_TABSTRIP_OVERVIEW/tabpT\01/subSUBSCREEN_BODY:SAPMV45A:4400/subHEADER_FRAME:SAPMV45A:4440/ctxtVBAK-PS_PSP_PNR").Text = sTmp
' Si client X Changer la condition de paiement à 60 jours
If InStr(1, ValChamp(Sh, Lig, "Nom Client"), "X") > 0 Then
Session.findById("wnd[0]/usr/tabsTAXI_TABSTRIP_OVERVIEW/tabpT\01/subSUBSCREEN_BODY:SAPMV45A:4400/subHEADER_FRAME:SAPMV45A:4440/ctxtVBKD-ZTERM").Text = "C003"
End If
' Si client Y changer la condition de paiement à 45 jours
If InStr(1, ValChamp(Sh, Lig, "TYPE MARCHES / CDE"), "Y") > 0 Then
Session.findById("wnd[0]/usr/tabsTAXI_TABSTRIP_OVERVIEW/tabpT\01/subSUBSCREEN_BODY:SAPMV45A:4400/subHEADER_FRAME:SAPMV45A:4440/ctxtVBKD-ZTERM").Text = "C016"
End If
' Objet de la commande
Dim sCmne As String, sTx0 As String, sTx As String, sLibArt As String
sCmne = Sh.Cells(Lig, ColFind(Sh, "COMMUNE")): sCmne = Abrev(sCmne, True)
'
sTx0 = Sh.Cells(Lig, ColFind(Sh, "TRAVAUX")): sTx = Abrev(sTx0, False)
sTmp = "": sTmp = Left(sCmne & "-" & sTx, 40)
Session.findById("wnd[0]/usr/tabsTAXI_TABSTRIP_OVERVIEW/tabpT\01/subSUBSCREEN_BODY:SAPMV45A:4400/subHEADER_FRAME:SAPMV45A:4440/txtVBAK-KTEXT").Text = sTmp
' Création du poste avec TVA ou non
Dim SsT As String
SsT = ValChamp(Sh, Lig, "Nom Client DO")
' Si pas de TVA = SOUS-TRAITANT
If ValChamp(Sh, Lig, "TVA") = "N" Then
sLibArt = "ST_EXTERNE"
Else
If InStr(1, sTx0, "ETUDE", vbTextCompare) > 0 Then
sLibArt = "ETUDE"
Else
sLibArt = "TRAVAUX_AGENCE"
End If
End If
' Inscrire le libellé article Session.findById("wnd[0]/usr/tabsTAXI_TABSTRIP_OVERVIEW/tabpT\01/subSUBSCREEN_BODY:SAPMV45A:4400/subSUBSCREEN_TC:SAPMV45A:4900/tblSAPMV45ATCTRL_U_ERF_AUFTRAG/ctxtRV45A-MABNR[1,0]").Text = sLibArt
' S'il s'agit de sous-traitance
If sLibArt = "ST_EXTERNE" Then
Session.findById("wnd[0]").sendVKey 0
Application.Wait Now + TimeSerial(0, 0, 1) ' Attendre
Session.findById("wnd[1]/usr/btnDY_VAROPTION1").press
End If
' Libellé du poste
If InStr(1, sCde, "BPA", vbTextCompare) > 0 Then
sTmp = "MT HT des TX suivant DEVIS"
Else
If InStr(1, Sh.Range("C" & Lig), "ENEDIS") > 0 Then
sTmp = "RECEPTION n° "
Else
If InStr(1, sTx0, "ETUDE", vbTextCompare) > 0 Then
sTmp = "MT HT de L'ETUDE suivant CDE"
Else
sTmp = "MT HT des TX suivant CDE"
End If
End If
End If
Session.findById("wnd[0]/usr/tabsTAXI_TABSTRIP_OVERVIEW/tabpT\01/subSUBSCREEN_BODY:SAPMV45A:4400/subSUBSCREEN_TC:SAPMV45A:4900/tblSAPMV45ATCTRL_U_ERF_AUFTRAG/txtVBAP-ARKTX[5,0]").Text = sTmp
' Montant de la commande HT
sTmp = "": sTmp = Round(ValChamp(Sh, Lig, "MONTANT H.T."), 2)
Session.findById("wnd[0]/usr/tabsTAXI_TABSTRIP_OVERVIEW/tabpT\01/subSUBSCREEN_BODY:SAPMV45A:4400/subSUBSCREEN_TC:SAPMV45A:4900/tblSAPMV45ATCTRL_U_ERF_AUFTRAG/txtKOMV-KBETR[6,0]").Text = sTmp
' Se positionner dans l'entête de commande
Session.findById("wnd[0]/usr/subSUBSCREEN_HEADER:SAPMV45A:4021/btnBT_HEAD").press
Application.Wait Now + TimeSerial(0, 0, 1) ' Attendre
' Inscrire la MB
Session.findById("wnd[0]/usr/tabsTAXI_TABSTRIP_HEAD/tabpT\06").Select
Application.Wait Now + TimeSerial(0, 0, 2) ' Attendre 2 seconde
Session.findById("wnd[0]/usr/tabsTAXI_TABSTRIP_HEAD/tabpT\06/ssubSUBSCREEN_BODY:SAPLV69A:6201/tblSAPLV69ATCTRL_KONDITIONEN/ctxtKOMV-KSCHL[1,8]").Text = "ZMAR"
sTmp = Round(ValChamp(Sh, Lig, "% MB"), 2)
Session.findById("wnd[0]/usr/tabsTAXI_TABSTRIP_HEAD/tabpT\06/ssubSUBSCREEN_BODY:SAPLV69A:6201/tblSAPLV69ATCTRL_KONDITIONEN/txtKOMV-KBETR[3,8]").Text = sTmp
' Choix du partenaire
Session.findById("wnd[0]/usr/tabsTAXI_TABSTRIP_HEAD/tabpT\08").Select
sTmp = "": sTmp = TabFindR("TabListeRA[Initiales]", Sh.Range("B" & Lig), "Code SAP")
Session.findById("wnd[0]/usr/tabsTAXI_TABSTRIP_HEAD/tabpT\08/ssubSUBSCREEN_BODY:SAPMV45A:4352/subSUBSCREEN_PARTNER_OVERVIEW:SAPLV09C:1000/tblSAPLV09CGV_TC_PARTNER_OVERVIEW/ctxtGVS_TC_DATA-REC-PARTNER[1,3]").Text = sTmp
Session.findById("wnd[0]/usr/tabsTAXI_TABSTRIP_HEAD/tabpT\08/ssubSUBSCREEN_BODY:SAPMV45A:4352/subSUBSCREEN_PARTNER_OVERVIEW:SAPLV09C:1000/tblSAPLV09CGV_TC_PARTNER_OVERVIEW/ctxtGVS_TC_DATA-REC-PARTNER[1,6]").Text = sTmp
Session.findById("wnd[0]").sendVKey 0
Session.findById("wnd[0]").sendVKey 0
' Inscrire le libellé du marché
Session.findById("wnd[0]/usr/tabsTAXI_TABSTRIP_HEAD/tabpT\09").Select
' Inscrire le libellé détaillé de la commande
sTmp = "": sTmp = ValChamp(Sh, Lig, "Libellé de la commande")
'sTmp = Replace(sTmp, Chr(10), vbCr)
Session.findById("wnd[0]/usr/tabsTAXI_TABSTRIP_HEAD/tabpT\09/ssubSUBSCREEN_BODY:SAPMV45A:4152/subSUBSCREEN_TEXT:SAPLV70T:2100/cntlSPLITTER_CONTAINER/shellcont/shellcont/shell/shellcont[1]/shell").Text = sTmp
' Inscrire les données de commande
Session.findById("wnd[0]/usr/tabsTAXI_TABSTRIP_HEAD/tabpT\10").Select
Session.findById("wnd[0]/usr/tabsTAXI_TABSTRIP_HEAD/tabpT\10/ssubSUBSCREEN_BODY:SAPMV45A:4351/txtVBKD-IHREZ").Text = "NA"
Session.findById("wnd[0]/usr/tabsTAXI_TABSTRIP_HEAD/tabpT\10/ssubSUBSCREEN_BODY:SAPMV45A:4351/txtVBKD-IHREZ_E").Text = "NA"
' Inscrire la date de prix (Fait buguer le code par la suite)
Session.findById("wnd[0]/usr/tabsTAXI_TABSTRIP_HEAD/tabpT\04").Select
Session.findById("wnd[0]/usr/tabsTAXI_TABSTRIP/tabpT\04/ssubSUBSCREEN_BODY:SAPLV60F:4203/ctxtFPLA-BEDAT").Text = sDateCde
Session.findById("wnd[0]").sendVKey 0
Session.findById("wnd[0]").sendVKey 0
' Attendre 2 s
Application.Wait Now + TimeSerial(0, 0, 1)
' En cas d'erreur
On Error Resume Next
' Revenir
Session.findById("wnd[0]/tbar[0]/btn[3]").press
Session.findById("wnd[0]/mbar/menu[1]/menu[12]").Select
Session.findById("wnd[0]").sendVKey 11
' Vérifier si pas d'erreur à ce niveau
If Err.Number <> 0 Then
sTmp = Session.findById("wnd[0]/sbar").Text
AppActivate ThisWorkbook.Name
MsgBox "Attention ! Il y'a un message SAP" & vbCr & vbCr & sTmp
GoTo FinProc
End If
' Mois ouvert
sTmp = Application.WorksheetFunction.EDate(DateValue("01/" & Format(Date, "mm/yyyy")), 1)
sTmp = Format(sTmp, "ddmmyy")
Session.findById("wnd[1]/usr/txtGV_TARGETTEXT").Text = sTmp
Session.findById("wnd[1]").sendVKey 0
On Error GoTo 0
' Récupérer le numéro de commande à ce moment
sTmp = Session.findById("wnd[0]/sbar").Text
sTmp = Mid(sTmp, InStr(1, sTmp, "5"), 10)
' Sortir de la saisie et récupérer le numéro de commande
Session.findById("wnd[0]/tbar[0]/btn[3]").press
Session.findById("wnd[0]/tbar[0]/btn[3]").press
Dim sNumCde As String
If sTmp <> "" Then
sNumCde = sTmp
Else
Session.findById("wnd[0]/tbar[0]/okcd").Text = "VA03"
Session.findById("wnd[0]").sendVKey 0
sNumCde = Session.findById("wnd[0]/usr/ctxtVBAK-VBELN").Text
' revenir en arrière
Session.findById("wnd[0]/tbar[0]/btn[3]").press
End If
Suite:
Application.EnableEvents = False
Sh.Cells(Lig, ColFind(Sh, "CDE SAP")).Value = sNumCde
Application.EnableEvents = True
Application.ScreenUpdating = True
' Indiquer que tout c'est bien passé
FlgOk = True
FinProc:
' Effacer la variable objet
Set Session = Nothing: Set Connection = Nothing: Set App = Nothing: Set SapGui = Nothing
' Maximise ce classeur
ThisWorkbook.Windows.Application.WindowState = xlMaximized
End SubPour trouver le script, j'ai utilisé l'enregistreur de Script de SAP et fait mes actions, j'ai ensuite récupéré le code
A+
Merci pour ce partage.
J'ai testé et comparé, ma logique est bien bonne mais la sessions SAP une fois connecté est introuvable pour VBA.
Que je test avec ma macro ou la tienne meme erreur : erreur 614
Je ne sais pas si c'est une limitation IT sur mon poste ou juste un petit contournement à réaliser. Je bloque
J'ai créé une petit boucle pour trouver la session, et ca me renvoie le message d'erreur. Je ne sais pas aller plus loin sans aide.
Set Connection = App.Children(0)
If Connection.Children.Count = 0 Then
MsgBox "Aucune session SAP active trouvée. Veuillez vous connecter à SAP.", vbExclamation
Exit Sub
End IfBonsoir,
Peut-être un bout de réponse ici
https://joelting.com/articles/sap-gui-script/running-your-first-sap-gui-automation-with-excel-vba
A+