Lors de l'automatisation d'Excel, il est souvent nécessaire de vérifier si un Classeur Excel 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. Avec le développement du Cloud, cette fonctionnalité devient même de plus en plus indispensable…
Voici donc une fonction qui vérifie si un fichier Excel 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 de type booléen "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 Excel est (déjà) ouvert
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
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 pratique d'utilisation dans une procédure (Sub)
Et voici comment utiliser cette fonction 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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
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 en VBA…
Voici d'autres articles qui traitent de la gestion des classeurs Excel en VBA et qui pourraient vous intéresser…
- Date d’expiration et autodestruction de fichier Excel – oui, oui, il est bien possible de rendre un fichier Excel inutilisable après un laps de temps choisi!
- Formats des fichiers Excel
- VBA: Ouvrir un Classeur dans une nouvelle instance d’Excel
- VBA: supprimer les liaisons Excel
- Comment utiliser RECHERCHEV en VBA
- Compresser et décompresser avec ZIP dans VBA
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…
26 commentaires sur “VBA: vérifier si un Classeur Excel est ouvert”
Top Merci.
EstClasseurOuvert represente quoi ici? Workbooks?
Merci
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
Merci beaucoup de votre aide
Mais je ne sais pas pourquoi ca ne marche pas chez moi. il ne retrouve pas le chemin du fichier meme s'il existe
ça y est. C'est bon maintenant. Merci
je suis content que vous ayez trouvé la solution…
Cordialement, Martin
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?
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
Arf c'est bien ce qui me semblait.
Merci tout de même Martin.
Cordialement
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.
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
ouFaux
à 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:
😉
Cordialement, Martin
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
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 le5001
(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
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
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
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
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
Friendly Reminder 😊
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
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
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
Bonjour,
Merci encore pour ce code si précieux. Je l'utilise régulièrement.
Mais depuis peu, sur un de mes classeurs, Lorsqu'il passe la ligne "Open MonClasseur For Input Lock Read As #NumeroFichier".
VBA me renvoie la fenêtre d'erreur d'exécution avec le code 70 -> Permission refusée.
En soit c'est drôle puisque c'est bien ce code erreur qui est géré ensuite dans le select case … Je ne comprends pas pourquoi il se met en mode débogage … surtout que j'ai bien gardé le on error resume next au dessus …
C'est perturbant pour l'utilisateur lambda.
Si vous aviez une piste… Merci bcp
Bonjour, pourquoi pointer vers une adresse fixe ?
MonClasseur = "C:\Test\MonClasseur.xlsx"
Ce type de code génère régulièrement des erreurs (si fichier déplacé, si chemin réseau différent selon utilisateur, …)
Je ne sais pas, je n'ai pas encore visionné complètement le code mais en général on peut contourner par quelques chose de plus dynamique.
Je suis d'accord, on peut par exemple écrire :
MonClasseur = ThisWorkbook.Path & "\" & ThisWorkbook.Name
Il y a d'autres variantes possibles, à étudier selon le besoin de portabilité du code.
Bonjour,
ceci est un exemple. Je trouve qu'il est plus simple de mettre un exemple de chemin pour que les visiteurs voient à quoi le core rassemble en pratique.
Ensuite, la manière d'assigner la valeur à la variable varie selon l'utilisation que vous voulez en faire. Ce qui compte c'est que la variable contienne le chemin complet vers le classeur.
Bonjour
Tout d'abord "Merci" beaucoup pour ce super site, qui m'aide beaucoup et que je consulte très souvent !
Cet article répond complètement à mon besoin du moment, mais serait-il possible en complément de savoir par quel utilisateur le fichier est déjà ouvert ?