IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Macros et VBA Excel Discussion :

Fermer fichier Excel dans une seconde application


Sujet :

Macros et VBA Excel

  1. #1
    Membre averti
    Homme Profil pro
    Technicien
    Inscrit en
    Octobre 2020
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Technicien

    Informations forums :
    Inscription : Octobre 2020
    Messages : 15
    Par défaut Fermer fichier Excel dans une seconde application
    Bonjour,

    J'ai une application qui génère un fichier Excel (.xls) et je souhaiterais fermer ce fichier à partir d'un code VBA.

    Ma problématique est que l'application exécute une seconde fois Excel (cf. capture d'écran ci-dessous) pour ouvrir le fichier ce qui me rend le fichier inaccessible à partir de mon premier document.
    Nom : Capture.PNG
Affichages : 142
Taille : 28,1 Ko

    Lorsque j'exécute le code suivant : Workbooks(nomFichier ou nomChemin).Close SaveChanges:=False
    J'ai le message d'erreur suivant : "L'indice n'appartient pas à la sélection".

    En effet, lorsque j'exécute le code suivant :
    For Each Wb In application.Workbooks
    MsgBox Wb.Name
    Next Wb

    Je ne retrouve pas le classeur que je chercher à fermer. Est ce que quelqu'un aurait une solution à ma problématique ?

    Quelques petites précisions :
    Le classeur de travail est "Compilateur - V2".
    Le classeur a fermer est l'autre

    Je vous remercie par avance pour toute aide.

  2. #2
    Membre Expert
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 466
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 466
    Par défaut
    Salut,

    D'abord pour répondre à ta question, il est normal que tu ne puisse accéder au fichier ouvert par une autre application, cette dernière instancie sa propre application Excel.
    Hors, lorsque tu lance Excel, tu instancie également un nouvelle application.
    Les 2 instances sont distinct et ne se connaissent pas (elles n'ont aucune raison de se connaitre).

    En général, il n'est pas recommandé d'interférer avec les ressources contrôlées par le voisin, ca peut réserver de très vilaines surprises.
    Pour quelle raison souhaites-tu accéder à ces instances ?

  3. #3
    Membre averti
    Homme Profil pro
    Technicien
    Inscrit en
    Octobre 2020
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Technicien

    Informations forums :
    Inscription : Octobre 2020
    Messages : 15
    Par défaut
    Bonjour,

    Je vous remercie beaucoup pour votre retour.

    Je souhaite fermer les fichiers ouverts pour m'éviter d'avoir à le faire manuellement pour quand il va m'en avoir ouvert 30.
    Le "voisin" ouvre les fichiers pour que l'utilisateur puisse en prendre connaissance mais le fichier n'est ensuite pas exploité.

    Cordialement.

  4. #4
    Expert confirmé

    Homme Profil pro
    Curieux
    Inscrit en
    Juillet 2012
    Messages
    5 169
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Curieux
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2012
    Messages : 5 169
    Billets dans le blog
    5
    Par défaut
    Bonjour,

    y-a-t-il une raison légitime à travailler sur une autre instance ?

    Peux-tu nous montrer le code qui réalise ceci ?

  5. #5
    Membre averti
    Homme Profil pro
    Technicien
    Inscrit en
    Octobre 2020
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Technicien

    Informations forums :
    Inscription : Octobre 2020
    Messages : 15
    Par défaut
    J'extrais des données issus d'un logiciel. Le code n'est pas très intéressant car il s'agit de sendclick. Le logiciel extrait les données au format .xls et ouvre le fichier créé dans une autre instance.
    Mon code VBA a pour vocation à m'éviter d'avoir à faire l'opération manuellement des dizaines de fois car le logiciel ne permet une extraction massive des données...

  6. #6
    Membre averti
    Homme Profil pro
    Technicien
    Inscrit en
    Octobre 2020
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Technicien

    Informations forums :
    Inscription : Octobre 2020
    Messages : 15
    Par défaut
    Bonjour,

    Voici le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    Sub Convertisseurvi2EnExcel(ByVal control As IRibbonControl)
    'Converti les fichier testo vi2 en fichier excel
     
        'Défini le logiciel
        Dim cheminLogiciel As String 'Chemin du logiciel utilisé
        cheminLogiciel = "C:\Program Files (x86)\Testo\Comfort Software Basic 5.0\ComSoft.exe"
     
        'Vérifie que le logiciel existe
        If Dir(cheminLogiciel) = "" Then 'Si le chemin n'existe pas
     
            MsgBox "Le logiciel Comfort Software Basic 5.0 n'est pas trouvable." & Chr(10) & "Veuillez vérifier qu'il se trouve à l'emplacement C:\Program Files (x86)\Testo\Comfort Software Basic 5.0\ComSoft.exe", vbOKOnly + vbInformation, "Logiciel introuvable"
            Exit Sub 'Fin de la macro
     
        End If
     
        'Préviens l'utilisateur de la durée d'exécution
        If MsgBox("La durée d'exécution peut durer plusieurs minutes." & Chr(10) & "Etes vous sur de vouloir continuer ?", vbYesNo + vbInformation, "Vérification") = vbNo Then 'Si la personne ne veut pas continuer
            Exit Sub 'Sort de la procédure
        End If
     
        'Selection des fichiers
        Dim fichierSelectionné As Variant
        fichierSelectionné = selectionFichier("vi2") 'Appelle la fonction selectionFichier
     
        'Importation des données
        If Not IsEmpty(fichierSelectionné) Then 'Si fichiers sélectionnées
     
            'MEssage d'avertissement
            MsgBox "Traitement en cours ! Nous vous demandons de ne toucher à rien." & Chr(10) & _
            "Veuillez patienter cela peut prendre plusieurs minutes.", vbCritical + vbOKOnly
     
            'Converti les fichier
            For i = LBound(fichierSelectionné) To UBound(fichierSelectionné) 'parcour tableau des fichiers selectionné
     
                Shell cheminLogiciel & " " & fichierSelectionné(i), vbNormalFocus 'Ouvre le fichier
     
                Sleep (10000) 'Pause de 10 secondes pour laisser le temps au logiciel de se lancer
     
                AppActivate ("Testo - ComSoft Basic") 'Active l'application
     
                'Exécute 8 tabulations pour aller sur le menu "Analyser"
                For a = 1 To 8
                    SendKeys "{TAB}"
                Next
     
                SendKeys "{DOWN}" 'Descend pour rentrer dans l'encart analyser
     
                'Exécute 15 tabulations pour aller sur le menu Réglage diagramme
                For a = 1 To 15
                    SendKeys "{TAB}"
                Next
     
                SendKeys "{ENTER}" 'Entre dans le menu
     
                'Exécute 4 tabulations pour aller sur le menu Réglage Rapport
                For a = 1 To 4
                    SendKeys "{TAB}"
                Next
     
                SendKeys "{ENTER}" 'Entre
     
                'Sélectionne le tableau
                SendKeys "{TAB}"
                SendKeys "{DOWN}"
     
                'Sélectionne le format d'exportation
                SendKeys "{TAB}"
                SendKeys "{TAB}"
                SendKeys "{DOWN}"
     
                'Démare l'exportation
                SendKeys "{TAB}"
                SendKeys "{ENTER}"
     
                'Saisie le nom du fichier
                Dim nomFichier As String
                nomFichier = Mid(Dir(fichierSelectionné(i)), 1, InStrRev(Dir(fichierSelectionné(i)), ".") - 1) & ".xls" 'Défini le nom du fichier avec xls a la place de vi2
                SendKeys nomFichier 'Renseigne le nom du fichier
                SendKeys "{ENTER}" 'Valide l'enregistrement
     
                Sleep (10000) 'Pause de 10 secondes pour laisser le temps a l'excel de s'ouvrir
     
                'Ferme l'application
                AppActivate ("Testo - ComSoft Basic") 'Active l'application
                For a = 1 To 6 'Va jusqu'à la croix
                    SendKeys "{TAB}"
                Next
                SendKeys "{ENTER}" 'Clique sur la croix
     
                'Ferme l'excel
                Dim cheminFichierExcel As String
                cheminFichierExcel = Mid(Dir(fichierSelectionné(i)), 1, InStrRev(Dir(fichierSelectionné(i)), ".") - 1) 'Mid(fichierSelectionné(i), 1, InStrRev(fichierSelectionné(i), ".") - 1) & ".xls"
                'MsgBox cheminFichierExcel
                'Workbooks("test").Close SaveChanges:=False
     
                Sleep (1000) 'Pause de 1 secondes pour laisser le temps de se fermer
     
            Next
     
        End If
     
         MsgBox "L'opération a été éxutée avec succès !", vbInformation + vbOKOnly, "Information" 'Message d'information d'éxécution
     
    End Sub
    Cordialement.

  7. #7
    Expert confirmé

    Homme Profil pro
    Curieux
    Inscrit en
    Juillet 2012
    Messages
    5 169
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Curieux
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2012
    Messages : 5 169
    Billets dans le blog
    5
    Par défaut
    Bonjour,

    dans la mesure où c'est l'application tierce qui créée l'instance, c'est plus complexe.


    En partant du postulat que lorsque qu'une nouvelle instance est créée, elle se met en première position de la pile des instances référencées dans le gestionnaire, on pourrait envisager de la détecter comme telle pour la manipuler.

    C'est quand même délicat, je rejoins l'avis de deedolith sur ce point

    les fonctions/procédures/API pour réaliser l'inspection

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    Private Type GUID
        lData1 As Long
        iData2 As Integer
        iData3 As Integer
        aBData4(0 To 7) As Byte
    End Type
     
    Private Declare PtrSafe Function FindWindowEx Lib "user32" Alias "FindWindowExA" _
      (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
     
    Private Declare PtrSafe Sub AccessibleObjectFromWindow Lib "OLEACC.DLL" _
      (ByVal hwnd As Long, ByVal dwId As Long, riid As GUID, ppvObject As Any)
     
    Private Const OBJID_NATIVEOM = &HFFFFFFF0
     
    Private Sub SetIDispatch(ByRef ID As GUID)
        With ID
            .lData1 = &H20400
            .iData2 = &H0
            .iData3 = &H0
            .aBData4(0) = &HC0
            .aBData4(1) = &H0
            .aBData4(2) = &H0
            .aBData4(3) = &H0
            .aBData4(4) = &H0
            .aBData4(5) = &H0
            .aBData4(6) = &H0
            .aBData4(7) = &H46
        End With
    End Sub
     
    Public Function ApplicationFromHwnd() As Application
    Dim IDispatch As GUID
    Dim oWB As Object
    Dim lXLhwnd As Long
    Dim lXLDESKhwnd As Long
    Dim lWBhwnd As Long
    Do
        lXLhwnd = FindWindowEx(0, lXLhwnd, "XLMAIN", vbNullString)
        If lXLhwnd = 0 Then
            Exit Do
        ElseIf lXLhwnd <> Application.hwnd Then
            lXLDESKhwnd = FindWindowEx(lXLhwnd, 0&, "XLDESK", vbNullString)
            lWBhwnd = FindWindowEx(lXLDESKhwnd, 0&, "EXCEL7", vbNullString)
            If lWBhwnd Then
                SetIDispatch IDispatch
                Call AccessibleObjectFromWindow _
                (lWBhwnd, OBJID_NATIVEOM, IDispatch, oWB)
                Set ApplicationFromHwnd = oWB.Application
                Exit Do
            End If
        End If
    Loop
    Set oWB = Nothing
    End Function

    Une procédure qui ferme le classeur actif de la première instance de la pile

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Sub Supprimer_classeurX()
    Dim oXLApp As Object
    Set oXLApp = ApplicationFromHwnd()
        With oXLApp
          .ActiveWorkbook.Close False
          .Quit
        End With
    End Sub
    Que tu peux intégrer directement dans ta procédure, avant le Next i de la ligne 98

    Attention à bien tester dans un environnement de sécurité, je ne suis pas responsable des effets de bord

  8. #8
    Membre averti
    Homme Profil pro
    Technicien
    Inscrit en
    Octobre 2020
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Technicien

    Informations forums :
    Inscription : Octobre 2020
    Messages : 15
    Par défaut
    Bonjour,

    Cela fonctionne parfaitement ! Je vous remercie beaucoup !

    Je vous souhaite une excellente journée !

  9. #9
    Membre averti
    Homme Profil pro
    Technicien
    Inscrit en
    Octobre 2020
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Technicien

    Informations forums :
    Inscription : Octobre 2020
    Messages : 15
    Par défaut
    Par contre, je n'ai rien compris au code. Je ne sais pas s'il possible de l'expliquer ?

    Je vous remercie par avance.

    Cordialement.

  10. #10
    Expert confirmé

    Homme Profil pro
    Curieux
    Inscrit en
    Juillet 2012
    Messages
    5 169
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Curieux
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2012
    Messages : 5 169
    Billets dans le blog
    5
    Par défaut
    Le code paraît complexe (il l'est un peu à vrai dire), mais le principe est très logique

    Grosso modo :

    - on cherche des instances liées à excel (XLMAIN)
    - si on en trouve pas : on fait rien
    - si on en trouve une : on teste si c'est pas l'instance qu'on souhaite conserver (lXLhwnd <> Application.hwnd)
    - si l'instance trouvée n'est pas celle qu'on souhaite conserver : on y accède en appelant la fonction AccessibleObjectFromWindow
    - cette instance est transmise à la procédure appelante Supprimer_Classeurx où là on peut la manipuler (en l'occurence ici on ferme le fichier actif PUIS on quitte l'application)

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Copier/coller une ligne active d'un premier fichier excel dans un second
    Par Guillaume B. dans le forum Macros et VBA Excel
    Réponses: 0
    Dernier message: 01/12/2022, 14h53
  2. Réponses: 0
    Dernier message: 15/11/2021, 12h15
  3. Importation Fichier Excel dans une application Lotus Web
    Par djaminebiz dans le forum Lotus Notes
    Réponses: 2
    Dernier message: 29/04/2015, 12h13
  4. [AC-2003] Problème d'importation d'un fichier Excel dans une application ACCES
    Par zahira87 dans le forum VBA Access
    Réponses: 3
    Dernier message: 05/03/2013, 14h08
  5. Réponses: 7
    Dernier message: 04/10/2005, 18h21

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo