VBA: vérifier si un Classeur est ouvert 21


Lors de l'automatisation d'Excel, il est souvent nécessaire de vérifier si un Classeur est ouvert (déjà). Cette information peut servir pour savoir si le fichier est disponible ou non pour être "manipulé". Il n'est par exemple pas possible de supprimer un fichier ouvert. Tout comme un Classeur déjà ouvert ne peut être ré-ouvert par un autre utilisateur qu'en "lecture seule". Ces événements peuvent facilement perturber le bon fonctionnement de vos macros – autant donc les gérer en amont.

Ceci est d'autant plus important si vous travaillez en réseau et que les fichiers sont partagés par plusieurs utilisateurs.

Voici donc une fonction qui vérifie si un fichier est ouvert ou non – ou plus précisément si le Classeur est disponible à l'utilisation ou non.  Un Classeur ouvert en "lecture seule" par un autre utilisateur reste disponible à l'utilisation et est donc considéré comme "fermé".

Cette fonction retourne une valeur "Vrai" ou "Faux" (= True ou False) selon si le fichier est déjà ouvert ("occupé") ou non.

La fonction utilise un argument: MonClasseur de type String qui contient le chemin complet du Classeur (par ex.: "C:\Test\MonClasseur.xlsx" ).

Voici donc le code VBA de la fonction prêt à l'emploi ainsi qu'un exemple pratique de son utilisation.

Code VBA de la fonction qui vérifie si un Classeur est (déjà) ouvert

Function EstClasseurOuvert(MonClasseur As String)
'par: https://excel-malin.com

Dim NumeroFichier As Long, NumeroErreur As Long

    On Error Resume Next
    NumeroFichier = FreeFile()
    Open MonClasseur For Input Lock Read As #NumeroFichier
    Close NumeroFichier
    NumeroErreur = Err
    On Error GoTo 0

    Select Case NumeroErreur
    Case 0:    EstClasseurOuvert = False
    Case 70:   EstClasseurOuvert = True
    Case Else: Error NumeroErreur
    End Select
End Function

Exemple de l'utilisation en tant que Procédure (Sub)

Et voici comment l'utiliser en pratique

La procédure qui suit vérifie si le classeur "C:\Test\MonClasseur.xlsx" est ouvert. Comme résultat, un message pop-up est affiché informant l'utilisateur si oui ou non le fichier est déjà ouvert.

Sub ExempleTestOuvertureClasseur()
'par: https://excel-malin.com
    Dim Verification As Boolean
    Dim MonClasseur As String
    
    MonClasseur = "C:\Test\MonClasseur.xlsx"
    
    'd'abord le test si le fichier existe
    If Len(Dir(MonClasseur)) = 0 Then 's'il n'existe pas, montrer un avertissement et quitter la macro
        MsgBox "ERREUR: Le Classeur: [" & MonClasseur & "] n'existe pas..."
        Exit Sub
    Else
    End If
    
    'si le Classeur existe, vérifier s'il est déjà ouvert
    Verification = EstClasseurOuvert(MonClasseur)

    If Verification = True Then
        MsgBox "Le Classeur: [" & MonClasseur & "] est déjà ouvert..."
    Else
        MsgBox "Le Classeur: [" & MonClasseur & "] n'est pas ouvert..."
    End If
End Sub

Attention: cette fonction ne fonctionne que pour les Classeurs Excel (.xls, .xlsx, .xlsm etc.). Elle ne fonctionnera pas pour d'autres types de fichiers (vidéos, fichiers texte,…).

Pour aller plus loin…

Voici d'autres articles qui ont pour sujet la gestion des classeurs en VBA et qui pourraient vous intéresser…

Vous pouvez également jeter un coup d’œil à la Liste complète des fonctions VBA et également au Référentiel VBA disponible en PDF…

49 0




Laissez un commentaire

Votre adresse de messagerie ne sera pas publiée.

21 commentaires sur “VBA: vérifier si un Classeur est ouvert

    • excel-malin.com Auteur de l’article

      Bonjour ABD,

      "EstClasseurOuvert" est une fonction. Vous y indiquez, via l'unique argument de cette fonction, le chemin complet vers le Classeur (Workbook) qui doit être vérifié, et la fonction renvoie comme résultat un boolean (Vrai/Faux). "Vrai" ("True") si le Classeur en question est ouvert et "Faux" ("False") si le Classeur est fermé.

      J'espère que cela répond à votre question. Bàv, Martin

  • Laurent

    Bonjour,

    Ce code est parfait si les fichiers sont ouverts en lecture/Ecriture.
    Si un fichier est ouvert en lecture seule, la fonction renvoie systématique "0" puisqu'elle arrive à l'ouvrir.

    J'ai une application que je laisse ouverte longtemps. Elle vient consulter (Sans avoir besoin de les modifier) des fichiers partager.
    D'où le fait que j'ouvre les fichiers en lecture seule.

    Mais j'aimerai faire le test d'ouverture pour ne pas à réouvrir les fichiers régulièrement.

    Comment faire s'il vous plait?

    • excel-malin.com Auteur de l’article

      Bonjour Laurent,
      d'après ce que je sais, et d'après les recherches que je viens de faire, il n'y a pas de moyen fiable de vérifier si un fichier en lecture seule est ouvert.
      Donc là, je ne vais malheureusement pas pouvoir vous aider.
      Cordialement, Martin

  • William

    Bonjour,
    J'aurai souhaité savoir pourquoi cette fonction est utile puisque, quand il est demandé l'ouverture d'un classeur et qu'il est ouvert, cela renvoi faux.donc ça passe et il ne l'ouvre pas (Logique de sauvegarde). s'il est fermé, il l'ouvre, s'il n'existe pas, no fount. Il suffit de mettre uniquement ouverture classeur qu'il existe ou pas, les réponses seront automatiquement apportées, d'une programmation de plusieurs lignes, une ligne suffit dans un module personnel d'ouverture classeur, enclenché par open workbook.

    Parfois c'est idiot mais la simplicité du pragmatisme résout beaucoup de problèmes dans les légions d'ingénieurs.

    • excel-malin.com Auteur de l’article

      Bonojour William,
      l'avantage de ce code est qu'il vous renseigne sur l'état du classeur en question SANS l'ouvrir. Donc si vous voulez uniquement savoir si le classeur est ouvert ou pas, vous utilisez mon code.
      Si le Classeur en question contient du code dans Workbook_Open, avec votre proposition il sera d'office exécuté. Mais ce n'est peut-être pas ce que l'utilisateur veut.

      Donc en gros, le code que je propose ici répond Vrai ou Faux à la question "Le classeur xxxxxx est-il ouvert?".
      Ni plus, ni moins. Pas de fichiers ouverts (ce n'est pas l'objet de la question), ni des erreurs qui traînent, ni un code exécuté involontairement…

      Vous savez, le nombre de lignes est rarement un signe de la qualité de code…
      De plus, utilisateur n'a qu'à prendre mon code et le copier & coller dans son projet tel quel. Ensuite, il appelle la fonction par une ligne. Donc quelle importance pour lui si le code a 5 ou 10 lignes tant qu'il effectue exactement ce qu'il faut en un minimum de temps?

      Je ne suis pas un ingénieur et je me considère moi-même comme pragmatique. Mais cela n'empêche pas de faire des choses précisément et consciencieusement…

      Et si vous tenez tant au nombre de lignes de code, voici mon code en une seule ligne:

      Function EstClasseurOuvert(MonClasseur As String): Dim NumeroFichier As Long, NumeroErreur As Long: On Error Resume Next: NumeroFichier = FreeFile(): Open MonClasseur For Input Lock Read As #NumeroFichier: Close NumeroFichier: NumeroErreur = Err: On Error GoTo 0: Select Case NumeroErreur: Case 0: EstClasseurOuvert = False:    Case 70:   EstClasseurOuvert = True:    Case Else: Error NumeroErreur:    End Select: End Function

      😉
      Cordialement, Martin

  • Olivier

    Bonjour,
    Merci pour cet excellent exemple qui m'a bien aidé ! J'ai cependant une variante que je n'arrive pas à gérer : je dois contrôler qu'un fichier ouvert en WebDav est en lecture seule ou non. Mon chemin n'est plus un chemin classique de type "C:\Test\MonClasseur.xlsx", mais "https://serveur1.myqnapcloud.com:5001/MonClasseur.xlsx".
    Or quand j'exécute la macro ci-dessus, j'ai une "Erreur d'exécution 52 : nom ou numéro de fichier incorrect" …
    Auriez-vous la gentillesse de m'aider à dépasser cet obstacle ?
    U grand merci !
    Olivier

    • excel-malin.com Auteur de l’article

      Bonjour Olivier,
      vous pouvez essayer de transformer le url en quelque chose comme:
      "\Sharepointurl.com@SSL\DavWWWRoot\sitename\folder\MonClasseur.xlsx"
      donc dans votre cas,
      "\serveur1.myqnapcloud.com@SSL\MonClasseur.xlsx".
      Il faudrait peut-être jouer avec des variantes (par ex. \\ au début plutôt que \) + tester s'il faut mettre quelque part le 5001 (si oui où)…

      Une autre possibilité ce serait d'ouvrir un nouveau fichier Excel, d'allumer l'enregistreur des macros et ouvrir le classeur en question à partir d'Excel (pas à partir du explorateur windows!). Ensuite vous stoppez l'enregistrement et vérifier dans le code VBA enregistré la manière dont il a enregistré le chemin du fichier qu'il vient d'ouvrir. Cela devrait alors être réutilisable…

      J'espère que cela va vous aider.
      Tenez moi au courant si cela marche.
      Cordialement, Martin

      • Anonyme

        Bonjour Martin,
        Merci de votre rapidité à répondre. Je cherche toujours depuis ce matin sans succès …
        Le pire c'est que si je fais un Workbooks.Open filename:="https://serveur1.myqnapcloud.com:5001/Terrain/MonFichier.xlsx"; ça ouvre bien le fichier ce qui signifie que le chemin internet est bel et bien reconnu. En revanche il semble que la fonction "Open NomListe For Input Lock Read As #NumeroFichier" ne reconnaisse pas le chemin car elle me renvoie tantôt une erreur 75 quand je n'ai pas préalablement ouvert le chemin d'accès au dossier présent sur le webdav, tantôt une erreur 52 qui semble buter sur le nom du fichier (ou son "numéro de fichier") si j'ai déjà ouvert le dossier webdav … J'ai pourtant cherché du côté de la fonction Open, mais je pédale dans la semoule … Si vous avez une autre idée, elle est SUPER bienvenue !
        Merci encore
        Olivier

    • Olivier

      Bonsoir Martin,
      Merci pour la rapidité de votre réponse.
      J'ai encore cherché toute la journée sans succès …
      Le plus étonnant, c'est que quand je fais un Workbooks.Open filename:="https://serveur1.myqnapcloud.com:5001/Terrain/MonFichier.xlsx", le fichier s'ouvre c'est donc bien que la macro reconnaît le chemin Internet du WebDav.
      En revanche ce chemin n'est pas reconnu par la fonction Open NomListe For Input Lock Read As #NumeroFichier qui me renvoie soit une erreur 75 si je n'ai pas préalablement ouvert le dossier WebDav (erreur d'accès au dossier), soit une erreur 52 qui semble plus relative au nom de fichier ou au "numéro de fichier" évoqué dans la function que vous avez mise sur votre site (NumeroFichier = FreeFile()) que je maîtrise mal.
      Bref si vous avez d'autres idées, elles sont toujours bienvenues !
      Merci
      Olivier

      • Olivier

        Bonjour Martin,
        Bon, finalement après des heures de recherches et … l'aide d'un ami, j'ai trouvé grâce à vos conseils le chemin. Il fallait noter :
        \\serveur1.myqnapcloud.com@SSL@5001\DavWWWRoot\Terrain\MonFichier.xlsx
        J'ai ainsi désormais accès au dossier et au fichier et peux utiliser toutes les macros classiques que l'on peut faire sur un dossier quelconque. Malheureusement votre fonction résiste toujours : que le fichier soit ouvert ou on, elle renvoie toujours l'erreur 0 et non la 70 lorsqu'il est ouvert … Auriez-vous une idée pour contourner ce problème ?
        Merci encore de votre aide.
        Olivier

  • Pierre

    Bonjour Martin,
    je viens de mettre en oeuvre votre fonction EstClasseurOuvert avec succès.
    Merci beaucoup déjà pour cette astuce.

    A l'utilisation de la fonction EstClasseurOuvert dans mon code, je reçois le message que le fichier repris dans la variable FichierPrélèvement n'est pas ouvert.
    FichierPrélèvement contient une chaîne de caractère : "C:\Users\BOP\OneDrive – Group Seco\Documents\…\Monfichier.xlsm"

    Je rencontre cependant un message contradictoire dès la ligne de code suivante dans ma procédure.

    A savoir : Selection.InlineShapes.AddOLEObject FileName:=FichierPrélèvement, LinkToFile:=False, DisplayAsIcon:=False

    a l'exécution de la ligne en question je reçois le message d'erreur suivant :
    "https://mondomaine-my.sharepoint.com/…./Monfichier.xlsm" est ouvert dans une autre application.veuillez fermer ce fichier et réessayer.

    Je ne parviens pas à trouver l'origine de cette contradiction, si ce n'est que je ne dois pas tester le même fichier que celui que Word essaye d'ajouter en temps qu'OLEObject.

    Une explication pour m'aider ?

    Merci d'avance pour votre aide.

    Cordialement,

    Pierre

      • excel-malin.com Auteur de l’article

        Bonjour Pierre, désolé pour la réponse tardive mais avec le nombre de visiteurs en constante augmentation (actuellement autour de 150.000 visites/mois), c'est de moins en moins évident de répondre à tout le monde (et à temps)…

        De votre description, je ne comprends pas très bien le suivant: vous testez et essayez d'intégrer dans Word le même fichier? Car une fois il semble être stocké dans OneDrive et une fois sur un SharePoint?

        Cordialement, Martin

        • Pierre

          Bonsoir Martin,

          Merci beaucoup pour votre réaction

          1. Juste avant d'exécuter la ligne de code
          Selection.InlineShapes.AddOLEObject FileName:=FichierPrélèvement, LinkToFile:=False, DisplayAsIcon:=False

          j'interromps manuellement l'exécution de mon code pour vérifier la valeur de la variable FichierPrélèvement.
          A ce moment la variable FichierPrélèvement est égale à "C:\Users\BOP\OneDrive – Group Seco\Documents\…\Monfichier.xlsm"

          2. Je poursuis l'exécution du code en mode Pas à pas détaillé (F8) et l'exécution de la ligne de code
          Selection.InlineShapes.AddOLEObject FileName:=FichierPrélèvement, LinkToFile:=False, DisplayAsIcon:=False
          me renvois le message d'erreur suivant :
          "https://mondomaine-my.sharepoint.com/…./Monfichier.xlsm" est ouvert dans une autre application.veuillez fermer ce fichier et réessayer.

          3. J'ai donc appliqué votre Function EstClasseurOuvert en lui passant la valeur de la variable FichierPrélèvement
          qui est égale à "C:\Users\BOP\OneDrive – Group Seco\Documents\…\Monfichier.xlsm"
          juste avant l'exécution de la ligne de code
          Selection.InlineShapes.AddOLEObject FileName:=FichierPrélèvement, LinkToFile:=False, DisplayAsIcon:=False

          Elle me confirme que le fichier n'est pas ouvert. Ce qui me paraît correct.

          En conclusion, Il semble que la MéthodeAddOLEObject reçoit la valeur "C:\Users\BOP\OneDrive – Group Seco\Documents\…\Monfichier.xlsm" qui n'est pas ouvert et qu'elle me revoit une erreur qui me signale que le fichier représenté par une autre chaîne de caractères : "https://mondomaine-my.sharepoint.com/…./Monfichier.xlsm" est ouvert dans une autre application.

          C'est l'incohérence que je ne parviens pas à comprendre.
          En vous l'expliquant, il me semble indispensable d'approfondir ma connaissance du fonctionnement de la méthode AddOLEObject de l'objet Inlineshapes mais la documentation disponible n'est pas très explicite sur le traitement du paramètre FileName.

          Je crois qu'on est bien trop loin de votre Function EstClasseurOuvert.

          Merci quand même 🙂

          Pierre

          • excel-malin.com Auteur de l’article

            En effet, c'est étonnant…
            Mais vous n'êtes pas le premier ici à trouver des incohérences quand il s'agit du "cloud & co."
            A votre place, j'essaierais de chercher quel est le lien entre ces deux fichiers "Monfichier.xlsm" aux (apparemment) deux endroits différents.
            – est-ce le même fichier et il y a un certain mapping entre le dossier OneDrive et le SharePoint?
            – est-ce que ce sont deux fichiers différents? Est-ce que AddOLEObject fait une copie (temporaire?) du fichier que l'on ajoute au Word?
            -…

            N'hésitez pas à partager le résultat de vos recherches. Cela m'intéresserait de connaître la fin de l'histoire…
            Cordialement, Martin