Vérifier si un répertoire est déjà ouvert ou pas dans l'explorateur Windows

Bonjour,

Je cherche à coder une macro qui, au lancement d'une procédure, vérifie si un répertoire est ouvert dans l'explorateur de Windows puis, selon le cas (déjà ouvert ou fermé), soit ouvre le répertoire s'il n'est pas déjà ouvert dans l'explorateur de Windows, soit, lorsqu'il est déjà ouvert, place au premier plan la fenêtre de l'explorateur Windows (ou lui redonne une taille "normale" dans le cas où l'utilisateur l'aurait réduite auparavant) afin de permettre à l'utilisateur d'y accéder tout de suite.

Je travaille avec la version 14.0.7166.5000 (32 bits) d'Excel sous WIndows 7 (64 bits).

J'ai trouvé ce code qui m'affiche bien que le répertoire considéré est fermé lorsqu'il n'est pas ouvert dans l'explorateur Windows (il ne me restera plus qu'à commander l'ouverture mais je sais coder cela) mais, en revanche, rien ne se passe quand il est ouvert.

Je ne maîtrise pas très bien le VBA mais il me semble que le problème vient de la fonction Public Declare Function ShowWindow Lib "user32". Je pense que son rôle est "d'ouvrir" la fenêtre considérée mais cela ne fonctionne pas et je ne trouve pas la raison de ce problème.

Voici le code trouvé :

Public Declare Function ShowWindow Lib "user32" _
 (ByVal hWnd As Long, ByVal nCmdShow As Long) As Long

Const SW_SHOW = 5
Const SW_RESTORE = 9

Function FolderIsOpen(Folder$) As Boolean
        Dim OpenFold$, strFolder$
        Dim oShell As Object, Wnd As Object

        OpenFold = Folder
        strFolder = OpenFold
        Set oShell = CreateObject("Shell.Application")

        For Each Wnd In oShell.Windows
             FolderIsOpen = Wnd.Document.Folder.Self.Path = strFolder
        Next Wnd
End Function
Sub testII()
Dim oShell As Object, Wnd As Object
Set oShell = CreateObject("Shell.Application")
If FolderIsOpen("D:\1) Données") Then
For Each Wnd In oShell.Windows
Call ShowWindow(Wnd.hWnd, SW_RESTORE)
Next Wnd
Else
MsgBox "Fermé"
End If
End Sub

Je vous remercie par avance de vos réponses et vous souhaite à tous une bonne journée.

Je viens de tester à nouveau ce code. Mea culpa ; contrairement à ce que j'ai écrit, je viens de constater qu'il redonne une taille "normale" à la fenêtre de l'explorateur Windows lorsque celle-ci a été réduite. En revanche, si la fenêtre est ouverte en arrière plan, elle ne passa pas au premier plan. Je reformule donc ma question. Comment compléter le code pour la faire passer au premier plan ? Merci d'avance et je vous prie de bien vouloir m'excuser pour mon erreur.

Bonjour,

Voici un essai reposant sur une toute autre méthode, à savoir fermer le dossier puis le rouvrir. C'est un peu moins technique mais ça pourrait marcher :

Sub testII()
SetFocus "D:\1) Données"
End Sub

Sub SetFocus(FolderPath$)
CloseFolder FolderPath
Shell Environ("WINDIR") & "\explorer.exe " & FolderPath, vbNormalFocus 'ou vbMaximizedFocus
End sub

Sub CloseFolder(FolderPath$)
with createobject("Shell.Application").windows
    for i = .count - 1 to 0 step - 1
        currentpath = ConvertPath(.item(i).locationurl)
        if currentpath = FolderPath then .item(i).quit: exit sub
    next i
end with
end sub

function ConvertPath(sUrl as string) as string
ConvertPath = replace(replace(sUrl, "file:///", ""), "/", "\")
end function

Sinon, avez-vous essayé d'utiliser 2 fois la fonction ShowWindow :

Public Declare Function ShowWindow Lib "user32" _
 (ByVal hWnd As Long, ByVal nCmdShow As Long) As Long

Const SW_SHOW = 5
Const SW_RESTORE = 9

Function FolderIsOpen(Folder$) As Boolean
        Dim OpenFold$, strFolder$
        Dim oShell As Object, Wnd As Object

        OpenFold = Folder
        strFolder = OpenFold
        Set oShell = CreateObject("Shell.Application")

        For Each Wnd In oShell.Windows
             FolderIsOpen = Wnd.Document.Folder.Self.Path = strFolder
        Next Wnd
End Function
Sub testII()
Dim oShell As Object, Wnd As Object
Set oShell = CreateObject("Shell.Application")
If FolderIsOpen("D:\1) Données") Then
For Each Wnd In oShell.Windows
Call ShowWindow(Wnd.hWnd, SW_RESTORE) 'restaurer
Call ShowWindow(Wnd.hWnd, SW_SHOW) 'afficher (si j'en crois mon anglais) ?
Next Wnd
Else
MsgBox "Fermé"
End If
End Sub

Cdlt,

Après essais, ce code semble fonctionner :

Sub testII()
Restore "D:\1) Données"
End Sub

Sub Restore(FolderPath$)
With CreateObject("Shell.Application")
    For Each Wnd In .Windows
        If ConvertPath(Wnd.locationurl) = FolderPath Then
            ShowWindow Wnd.hWnd, SW_SHOWNORMAL
            Exit Sub
        End If
    Next Wnd
End With
End Sub

function ConvertPath(sUrl as string) as string
ConvertPath = replace(replace(sUrl, "file:///", ""), "/", "\")
end function

Cdlt,

Bonjour,

Je vous remercie sincèrement. Je viens de le tester en dehors de mon code. Cela semble fonctionner parfaitement. Vous m'avez sauvé...

Il ne me reste plus qu'à l'incorporer dans mon programme mais cela ne devrait poser aucun problème.

C'est très gentil à vous.

Bonne journée et bonne continuation,

Bien cordialement

Bonjour,

Merci de ce retour ! Très bonne journée à vous aussi !

Cdlt,

Rebonjour,

Je viens d'incorporer le code que vous m'avez gentiment proposé dans mon projet et d'effectuer une dizaine d'essais successifs et, bizarrement, cela ne fonctionne pas toujours. En désespoir de cause, j'ai essayé d'incorporer le premier code dont je disposais et que je joins ci-dessous. Et là, tout aussi bizarrement, j'ai fait plus de quinze essais et cela fonctionne parfaitement.

En effet, d'une part, lorsque le répertoire est fermé, il est bien reconnu comme fermé et la procédure d'ouverture se lance et le répertoire s'ouvre.

D'autre part, lorsque le répertoire a déjà été ouvert dans l'explorateur Windows mais, préalablement au lancement de la procédure VBA, a été réduit par l'utilisateur, le code redonne bien sa taille à la fenêtre de l'explorateur Windows.

En revanche, lorsque la fenêtre du répertoire est déjà ouverte mais en arrière plan, rien ne se passe alors que, pour le confort de l'utilisateur, j'aimerais que la fenêtre du répertoire déjà ouverte mais en arrière plan passe au premier plan pour permettre à l'utilisateur de l'utiliser. Je ne sais pas si cela est possible mais ce serait un vrai plus.

J'en reviens donc à la question que j'avais formulée précédemment : comment compléter le code pour faire passer une fenêtre de l'explorateur Windows ouverte de l'arrière plan au premier plan ?

Merci d'avance à tous et bonne journée

Public Declare Function ShowWindow Lib "user32" _
 (ByVal hWnd As Long, ByVal nCmdShow As Long) As Long

Const SW_SHOW = 5
Const SW_RESTORE = 9

Function FolderIsOpen(Folder$) As Boolean
        Dim OpenFold$, strFolder$
        Dim oShell As Object, Wnd As Object

        OpenFold = Folder
        strFolder = OpenFold
        Set oShell = CreateObject("Shell.Application")

        For Each Wnd In oShell.Windows
             FolderIsOpen = Wnd.Document.Folder.Self.Path = strFolder
        Next Wnd
End Function
Sub testII()
Dim oShell As Object, Wnd As Object
Set oShell = CreateObject("Shell.Application")
If FolderIsOpen("D:\1) Données") Then
For Each Wnd In oShell.Windows
Call ShowWindow(Wnd.hWnd, SW_RESTORE)
Next Wnd
Else
MsgBox "Fermé"
Shell Environ("WINDIR") & "\explorer.exe " & "D:\1) Données", vbNormalFocus
End If
End Sub

Bonjour,

En fait, selon moi, la fonction est incomplète puisque la boucle sur les fenêtres se poursuit même s'il y a correspondance, ce qui conduit à fausser le résultat.

En outre, cette fonction (que j'ai modifiée) est bien mais il y a une redondance (double boucle sur les fenêtres) dont on peut se passer. Donc voici une fonction Restore qui renvoie Vrai lorsqu'un répertoire est ouvert (teste donc l'existence parmi les fenêtres) et qui devrait en principe le remettre en premier plan. Sinon, elle renvoie faux et le répertoire en question est ouvert dans la macro testII :

Public Declare Function ShowWindow Lib "user32" _
 (ByVal hWnd As Long, ByVal nCmdShow As Long) As Long
Const SW_SHOWNORMAL = 1
Const SW_SHOW = 5
Const SW_RESTORE = 9

Sub testII()
sRep$ = "D:\1) Données"
If not Restore(sRep) Then 'si dossier fermé
    'MsgBox "Fermé"
    Shell Environ("WINDIR") & "\explorer.exe " & sRep, vbNormalFocus 'on l'ouvre (premier plan auto)
End If
End Sub

function Restore(FolderPath$) as boolean
Dim Wnd As Object
With CreateObject("Shell.Application")
    For Each Wnd In .Windows 'pour chaque fenetre
        If Wnd.Document.Folder.Self.Path = FolderPath Then 'si le repertoire de la fenetre vaut le repertoire entré en argument
            Restore = true 'renvoie vrai (la fenetre est ouverte)
            ShowWindow Wnd.hWnd, SW_RESTORE 'met au premier plan ???
            Exit function 'sortie de fonction
        End If
    Next Wnd
End With
End function 'sinon, renvoie faux, valeur booléenne par défaut

'Function FolderIsOpen(Folder$) As Boolean
'Dim Wnd As Object
'with CreateObject("Shell.Application")
'    For Each Wnd In .Windows
'        if Wnd.Document.Folder.Self.Path = Folder then FolderIsOpen = true: exit function
'    Next Wnd
'end with
'End Function

Il demeure 2 incertitudes :

- la condition

If Wnd.Document.Folder.Self.Path = FolderPath Then

car je ne l'ai pas testée mais j'ai peu de doutes...

- la fonction ShowWindow :

ShowWindow Wnd.hWnd, SW_RESTORE

et en particulier son comportement en fonction de son second argument car je n'ai pas suffisamment testée...

Cdlt,

Bonjour,

Tout d'abord, je tenais à vous remercier encore pour tous les efforts que vous avez fournis et pour tout le temps passé pour essayer d'apporter une solution à mon problème. C'est vraiment très gentil.

J'ai essayé le nouveau code que vous m'avez proposé. Il est vrai qu'il fonctionne de façon stable. Cependant, il ne répond qu'à deux des conditions que je cherchais à faire remplir au code pour le confort de l'utilisateur mais pas à la troisième. Je me dis que soit j'exprime mal ma requête, ce qui est fort possible car, d'une part, même si je progresse chaque jour, je suis encore loin de maîtriser tout cela parfaitement et, d'autre part, il suffit parfois d'une erreur de vocabulaire pour induire en erreur son interlocuteur ; soit ma demande n'est peut-être pas possible à réaliser.

En effet, le code que vous avez eu la gentillesse de me proposer répond bien au deux premiers critères ; à savoir :

1) soit ouvrir le répertoire visé si celui n'a pas été ouvert préalablement par l'utilisateur dans l'explorateur Windows,

2) soit restaurer la fenêtre de l'explorateur Windows affichant le contenu du répertoire visé si cette fenêtre a été préalablement ouverte par l’utilisateur mais réduite dans la barre des tâches.

Mais il ne respecte pas le troisième critère. En effet, dans le cas de figure où la fenêtre de l'explorateur a déjà été ouverte mais qu'elle se retrouve en arrière plan (derrière d'autres fenêtres ouvertes après, dont la fenêtre de l'instance depuis laquelle l'userform contenant le code a été lancé) sans avoir été réduite, lorsque je lance votre code rien ne se passe ; la fenêtre reste en arrière plan alors que j'aimerais qu'elle s'affiche en premier plan pour que l'utilisateur puisse l'utiliser tout de suite. Comme je l'évoquais plus haut, je me dis que ce n'est peut-être tout simplement pas possible...

Par ailleurs, avançant dans mon projet et toujours au sujet des répertoires, je me demande s'il n'existerait pas un code pour qu'Excel ferme automatiquement un répertoire ouvert ; par exemple soit en cliquant sur un bouton soit à la fermeture d'un formulaire.

Dans l'attente du plaisir de vous lire, je vous souhaite une excellente journée.

Bonjour,

Ce que vous cherchez à faire est fort probablement réalisable. Seulement, je n'ai pas fait assez d'essais pour déterminer la bonne façon d'y parvenir.

Vous pouvez essayer de tester tous les arguments possibles de la fonction showWindow qui figurent à cette page : https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow

Sinon, en cas d'échec persistant, vous pouvez tester ma première idée qui était de fermer puis rouvrir automatiquement un répertoire, ce qui a pour effet de le placer au premier plan quelque soit le cas de figure :

Sub testII()
SetFocus "D:\1) Données" 'donne le focus au dossier
End Sub

Sub SetFocus(FolderPath$)
CloseFolder FolderPath 'ferme si ouvert
OpenFolder FolderPath 'ouvre si existe
End sub

Sub CloseFolder(FolderPath$)
with createobject("Shell.Application").windows
    for i = .count - 1 to 0 step - 1
        if ConvertPath(.item(i).locationurl) = FolderPath then .item(i).quit: exit sub
    next i
end with
end sub

Sub OpenFolder(FolderPath$, Optional WindowStyle As VbAppWinStyle = vbNormalFocus)
If Dir(FolderPath, vbDirectory) = "" Then Exit Sub
Shell Environ("WINDIR") & "\explorer.exe " & FolderPath, WindowStyle
end sub

function ConvertPath(sUrl as string) as string
ConvertPath = replace(replace(sUrl, "file:///", ""), "/", "\")
end function

Cdlt,

Bonjour,

Encore mille mercis pour ces propositions. Je suis désolé de ne répondre qu'aujourd'hui et je vous prie de bien vouloir m'en excuser mais j'ai eu une semaine particulièrement chargée.

J'ai juste eu le temps d'essayer votre dernière proposition "set focus" avec fermeture du dossier avant ouverture pour éviter d'avoir plusieurs instances ouvertes mais cela ne fonctionne pas correctement. Le code ouvre bien une nouvelle fenêtre de visualisation du contenu du répertoire en la mettant au premier plan mais ne ferme pas les fenêtre précédemment ouvertes tant et si bien que je me suis retrouvé avec autant de fenêtres ouvertes que de tentatives effectuées.

Dès que j'aurai un peu plus de temps, j'essaierai de consulter le lien que vous avez eu la gentillesse de m'indiquer concernant la fonction ShowWindow mais j'espère que cela ne dépassera pas mes capacités de "codeur débutant" .

J'espère avoir le temps dans la semaine qui vient mais j'ai un nouveau problème plus embêtant et pour lequel je n'ai trouvé aucune solution sur le Net et concernant la possibilité ou non de contrôler la hauteur du menu déroulant d'une combobox. En effet, dans le cadre du code que je développe et pour le confort de l'utilisateur, je dois ouvrir un formulaire en bas d'écran, collé à la barre des tâches, de façon à laisser le haut de l'écran libre pour les tâches à effectuer par l'utilisateur en laissant le formulaire visible en bas. Le souci c'est que ce formulaire contient des combobox pour lesquelles la partie basse du menu déroulant disparait sous la barre des tâches rendant l'accès aux valeurs situées en bas de liste impossible. Étant donné que le menu déroulant s'ouvre en affichant un ascenseur, l'utilisateur n'a pas besoin d'un menu déroulant aussi grand, c'est pour cette raison que je cherchais un moyen de limiter la hauteur du menu déroulant (affichage de 3 ou 4 valeurs pas plus) mais je n'ai pas trouvé. Et, je crois qu'il faut que je lance une nouvelle discussion pour cela...

En tout cas, encore merci de votre aide et de votre serviabilité, c'est génial.

Je vous tiens au courant de ma consultation du lien sur la focntion ShowWindow. D'ici là prenez bien soin de vous.

Bien cordialement

Bonsoir,

Pas de souci, c'est déjà sympa d'avoir pensé à répondre !

Ca m'étonne un peu que la fermeture échoue... Les répertoires testés sont sur un réseau j'imagine ?

Essayez de modifier la procédure CloseFolder ainsi (seule la condition change) :

Sub CloseFolder(FolderPath$)
with createobject("Shell.Application").windows
    for i = .count - 1 to 0 step - 1
        if .item(i).Document.Folder.Self.Path = FolderPath Then .item(i).quit: exit sub
    next i
end with
end sub

Et vous pouvez essayer celui-ci aussi :

Sub CloseFolder(FolderPath$)
with createobject("Shell.Application").windows
    for i = .count - 1 to 0 step - 1
        if .item(i).Document.Folder.Self.Path = FolderPath Then .item(i).quit
    next i
end with
end sub

Ce dernier code, contrairement au premier, ferme tous les répertoires ouverts dont le chemin est FolderPath.

Bon courage pour votre autre problème !

Cordialement,

Répondre, pour moi, est la moindre des choses ; comme le disait ma défunte maman : "on a un peu d'élevage ou on n'en a pas". Vous prenez de votre temps pour m'aider...

Non, mon dossier n'est pas sur un réseau mais sur le second disque dur de mon PC.

Je n'ai encore pas eu le temps d'essayer votre dernière proposition ; je vous tiendrai au courant du résultat de mes essais.

Encore merci et bonne journée.

Rechercher des sujets similaires à "verifier repertoire deja ouvert pas explorateur windows"