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 :

  1. Lance SAP
  2. Ouvre le serveur défini
  3. Connecte l’utilisateur
  4. Ouvre une transaction spécifique
  5. Renseigne des données prédéfinies dans les champs
  6. Exécute la transaction
  7. Récupère une valeur donnée
  8. 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]").SetFocus

Voici 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 Sub

Merci 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 mais cela te donnera une idée

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 Sub

Pour 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 If
Rechercher des sujets similaires à "perte fenetre sap login"