Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Choix d'un repertoire par VBA

12 réponses
Avatar
Bolderic
Bonjour,


voila, j'ai un UserForm sur lequel un bouton déclenche la fonction
ci-dessous.Cette fonction permet d'ouvrir une fenetre pour
sélectionner un répertoire (pour info, cette fonction bien utile n'est
pas de moi mais d'un généreux anonyme).

Mon soucis est que si je clique à côté de la fenetre (sur l'UserForm
par exemple) la fenetre disparait (elle n'est plus au premier plan).

1. Que faut-il rajouter au code pour que la fenêtre reste au premier
plan tant que l'on a pas validé ou annulé?

2. Autre chose, que faut-il rajouter au code pour faire pointer la
fenêtre sur un dossier en particulier lors de l'affichage de la
fenêtre?

3. Dans le même ordre d'idée, dans le cas d'une fenêtre pour
sélectionner un fichier, est-il possible de faire pointer la fenêtre
sur un fichier en particulier à l'ouverture de la fenêtre?


Si quelqu'un a la réponse ou une piste de recherche, je suis preneur


Merci beaucoup!



La fonction est la suivante:

Public Type BROWSEINFO
hOwner As Long
pidlRoot As Long
pszDisplayName As String
lpszTitle As String
ulFlags As Long
lpfn As Long
lParam As Long
iImage As Long
End Type
'32-bit API declarations
Declare Function SHGetPathFromIDList Lib "shell32.dll" _
Alias "SHGetPathFromIDListA" (ByVal pidl As Long, ByVal pszPath As
String) As Long
Declare Function SHBrowseForFolder Lib "shell32.dll" _
Alias "SHBrowseForFolderA" (lpBrowseInfo As BROWSEINFO) As Long


Public Dossier
Public Rap
Public Dossierelec

------------------------------------------------------------------------------------

Function GetDirectory(Optional Msg) As String
Dim bInfo As BROWSEINFO
Dim path As String
Dim r As Long, x As Long, pos As Integer
bInfo.pidlRoot = 0&
If IsMissing(Msg) Then
bInfo.lpszTitle = "Choisissez un dossier de destination pour cette
sauvegarde."
Else
bInfo.lpszTitle = Msg
End If
bInfo.ulFlags = &H1
x = SHBrowseForFolder(bInfo)
path = Space$(512)
r = SHGetPathFromIDList(ByVal x, ByVal path)
If r Then
pos = InStr(path, Chr$(0))
GetDirectory = Left(path, pos - 1) & "\"
Else
GetDirectory = ""
End If
End Function

10 réponses

1 2
Avatar
Jacques93
Bonjour,


voila, j'ai un UserForm sur lequel un bouton déclenche la fonction
ci-dessous.Cette fonction permet d'ouvrir une fenetre pour
sélectionner un répertoire (pour info, cette fonction bien utile n'est
pas de moi mais d'un généreux anonyme).

Mon soucis est que si je clique à côté de la fenetre (sur l'UserForm
par exemple) la fenetre disparait (elle n'est plus au premier plan).

1. Que faut-il rajouter au code pour que la fenêtre reste au premier
plan tant que l'on a pas validé ou annulé?

2. Autre chose, que faut-il rajouter au code pour faire pointer la
fenêtre sur un dossier en particulier lors de l'affichage de la
fenêtre?

3. Dans le même ordre d'idée, dans le cas d'une fenêtre pour
sélectionner un fichier, est-il possible de faire pointer la fenêtre
sur un fichier en particulier à l'ouverture de la fenêtre?


Si quelqu'un a la réponse ou une piste de recherche, je suis preneur



Pour le point n°1, je n'ai pas ce comportement (Word 2003, XP SP2) donc
pas de solution.

Pour les points 2 et 3, dans l'événement Click du bouton :

Private Sub CommandButton1_Click()
Dim s As String
s = BrowseForFolder
s = BrowseForFolder(NomChemin, "Sélectionner un répertoire", False)
s = BrowseForFolder(NomFichier, "Sélectionner un fichier", True)
End Sub

Et dans un Module :
======================================================================= Private Declare Function SHBrowseForFolder Lib "shell32.dll" _
Alias "SHBrowseForFolderA" (lpbi As BrowseInfo) As Long
Private Declare Function SHGetPathFromIDList Lib "shell32.dll" _
Alias "SHGetPathFromIDListA" (ByVal pidl As Long, _
ByVal pszPath As String) As Long
Private Declare Function SendMessage Lib "USER32" _
Alias "SendMessageA" (ByVal hwnd As Long, _
ByVal wMsg As Long, ByVal wParam As Long, _
lParam As Any) As Long
Private Declare Sub CoTaskMemFree Lib "ole32.dll" (ByVal hMem As Long)

Private Const BIF_RETURNONLYFSDIRS As Long = &H1
Private Const BIF_DONTGOBELOWDOMAIN As Long = &H2
Private Const BIF_RETURNFSANCESTORS As Long = &H8
Private Const BIF_BROWSEFORCOMPUTER As Long = &H1000
Private Const BIF_BROWSEFORPRINTER As Long = &H2000
Private Const BIF_BROWSEINCLUDEFILES As Long = &H4000
Private Const MAX_PATH As Long = 260

Private Const WM_USER = &H400
Private Const BFFM_INITIALIZED = 1
Private Const BFFM_SELCHANGED = 2
Private Const BFFM_SETSTATUSTEXTA = (WM_USER + 100)
Private Const BFFM_SETSELECTIONA = (WM_USER + 102)

Private Type BrowseInfo
hwndOwner As Long
pIDLRoot As Long
pszDisplayName As String
lpszTitle As String
ulFlags As Long
lpfn As Long
lParam As Long
iImage As Long
End Type

Private mStartFolder As String

Public Function BrowseForFolder( _
Optional StartFolder As String = "", _
Optional Caption As String = "", _
Optional ShowFiles As Boolean = False) As String
Dim bInfo As BrowseInfo
Dim sResult As String
Dim lResult As Long

With bInfo
.hwndOwner = 0&
.pIDLRoot = 0
.pszDisplayName = String$(MAX_PATH, Chr$(0))
If Len(Caption) > 0 Then
.lpszTitle = Caption
End If
.ulFlags = BIF_RETURNONLYFSDIRS
If ShowFiles Then
.ulFlags = .ulFlags Or BIF_BROWSEINCLUDEFILES
End If
.lpfn = GetAddress(AddressOf BrowseCallbackProc)
.lParam = 0
.iImage = 0
mStartFolder = StartFolder

lResult = SHBrowseForFolder(bInfo)
If lResult <> 0 Then
sResult = String(MAX_PATH, 0)
If SHGetPathFromIDList(lResult, sResult) Then
BrowseForFolder = Left(sResult, InStr(sResult, Chr$(0)) - 1)
End If
CoTaskMemFree lResult
End If
End With
End Function

Private Function BrowseCallbackProc(ByVal hwnd As Long, _
ByVal uMsg As Long, _
ByVal lParam As Long,_
ByVal lpData As Long) As Long
Select Case uMsg
Case BFFM_INITIALIZED
If Len(mStartFolder) > 0 Then
SendMessage hwnd, BFFM_SETSELECTIONA, True, ByVal mStartFolder
End If
End Select
End Function

Private Function GetAddress(Addr As Long) As Long
GetAddress = Addr
End Function
=======================================================================
--
Cordialement,

Jacques.

Avatar
Jacques93
Bonjour,

Bonjour,


voila, j'ai un UserForm sur lequel un bouton déclenche la fonction
ci-dessous.Cette fonction permet d'ouvrir une fenetre pour
sélectionner un répertoire (pour info, cette fonction bien utile n'est
pas de moi mais d'un généreux anonyme).

Mon soucis est que si je clique à côté de la fenetre (sur l'UserForm
par exemple) la fenetre disparait (elle n'est plus au premier plan).

1. Que faut-il rajouter au code pour que la fenêtre reste au premier
plan tant que l'on a pas validé ou annulé?




Une petite idée quand même pour ce point, la variable hwndOwner de la
structure BrowseInfo indique le 'Handle' de la fenêtre propriétaire.
Sous VBA on n'a pas accès directement à cette propriété, mais on peut la
récupérer :

Private Declare Function FindWindow Lib "user32" Alias _
"FindWindowA" (ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long

Private Sub CommandButton1_Click()
Dim s As String
Dim hWnd As Long

' Testé avec Word 2003
hWnd = FindWindow("ThunderDFrame", "UserForm1")
s = BrowseForFolder(Hwnd)
[...]
End Sub

et adapter le module en conséquence ;

Public Function BrowseForFolder( _
ByVal Owner As Long, _
Optional StartFolder As String = "", _
Optional Caption As String = "", _
Optional ShowFiles As Boolean = False) As String
Dim bInfo As BrowseInfo
Dim sResult As String
Dim lResult As Long

With bInfo
.hwndOwner = Owner
[...]
End Function


La fenêtre 'BrowseForFolder' sera une fenêtre fille 'modale' du UserForm.

--
Cordialement,

Jacques.


Avatar
Bolderic
Merci beaucoup Jacques93!!!!


Tout ce que tu m'as donné fonctionne P A R F A I T E M E N T.

Que ce soit le maintient de la fenetre en premier plan ou le pointage
sur un dossier en particulier, tout marche nickel!

Je t'avoue que je n'ai pas compris grand chose aux lignes que tu m'as
adressées, mais dans mon programme, elles ont fait des miracles.

Merci encore.

Sincères salutations.


P.S.: A present va falloir que j'essaie de comprendre ces lignes. ;-)



On Sat, 21 May 2005 15:39:48 +0200, Jacques93
wrote:

Bonjour,


voila, j'ai un UserForm sur lequel un bouton déclenche la fonction
ci-dessous.Cette fonction permet d'ouvrir une fenetre pour
sélectionner un répertoire (pour info, cette fonction bien utile n'est
pas de moi mais d'un généreux anonyme).

Mon soucis est que si je clique à côté de la fenetre (sur l'UserForm
par exemple) la fenetre disparait (elle n'est plus au premier plan).

1. Que faut-il rajouter au code pour que la fenêtre reste au premier
plan tant que l'on a pas validé ou annulé?

2. Autre chose, que faut-il rajouter au code pour faire pointer la
fenêtre sur un dossier en particulier lors de l'affichage de la
fenêtre?

3. Dans le même ordre d'idée, dans le cas d'une fenêtre pour
sélectionner un fichier, est-il possible de faire pointer la fenêtre
sur un fichier en particulier à l'ouverture de la fenêtre?


Si quelqu'un a la réponse ou une piste de recherche, je suis preneur



Pour le point n°1, je n'ai pas ce comportement (Word 2003, XP SP2) donc
pas de solution.

Pour les points 2 et 3, dans l'événement Click du bouton :

Private Sub CommandButton1_Click()
Dim s As String
s = BrowseForFolder
s = BrowseForFolder(NomChemin, "Sélectionner un répertoire", False)
s = BrowseForFolder(NomFichier, "Sélectionner un fichier", True)
End Sub

Et dans un Module :
======================================================================= >Private Declare Function SHBrowseForFolder Lib "shell32.dll" _
Alias "SHBrowseForFolderA" (lpbi As BrowseInfo) As Long
Private Declare Function SHGetPathFromIDList Lib "shell32.dll" _
Alias "SHGetPathFromIDListA" (ByVal pidl As Long, _
ByVal pszPath As String) As Long
Private Declare Function SendMessage Lib "USER32" _
Alias "SendMessageA" (ByVal hwnd As Long, _
ByVal wMsg As Long, ByVal wParam As Long, _
lParam As Any) As Long
Private Declare Sub CoTaskMemFree Lib "ole32.dll" (ByVal hMem As Long)

Private Const BIF_RETURNONLYFSDIRS As Long = &H1
Private Const BIF_DONTGOBELOWDOMAIN As Long = &H2
Private Const BIF_RETURNFSANCESTORS As Long = &H8
Private Const BIF_BROWSEFORCOMPUTER As Long = &H1000
Private Const BIF_BROWSEFORPRINTER As Long = &H2000
Private Const BIF_BROWSEINCLUDEFILES As Long = &H4000
Private Const MAX_PATH As Long = 260

Private Const WM_USER = &H400
Private Const BFFM_INITIALIZED = 1
Private Const BFFM_SELCHANGED = 2
Private Const BFFM_SETSTATUSTEXTA = (WM_USER + 100)
Private Const BFFM_SETSELECTIONA = (WM_USER + 102)

Private Type BrowseInfo
hwndOwner As Long
pIDLRoot As Long
pszDisplayName As String
lpszTitle As String
ulFlags As Long
lpfn As Long
lParam As Long
iImage As Long
End Type

Private mStartFolder As String

Public Function BrowseForFolder( _
Optional StartFolder As String = "", _
Optional Caption As String = "", _
Optional ShowFiles As Boolean = False) As String
Dim bInfo As BrowseInfo
Dim sResult As String
Dim lResult As Long

With bInfo
.hwndOwner = 0&
.pIDLRoot = 0
.pszDisplayName = String$(MAX_PATH, Chr$(0))
If Len(Caption) > 0 Then
.lpszTitle = Caption
End If
.ulFlags = BIF_RETURNONLYFSDIRS
If ShowFiles Then
.ulFlags = .ulFlags Or BIF_BROWSEINCLUDEFILES
End If
.lpfn = GetAddress(AddressOf BrowseCallbackProc)
.lParam = 0
.iImage = 0
mStartFolder = StartFolder

lResult = SHBrowseForFolder(bInfo)
If lResult <> 0 Then
sResult = String(MAX_PATH, 0)
If SHGetPathFromIDList(lResult, sResult) Then
BrowseForFolder = Left(sResult, InStr(sResult, Chr$(0)) - 1)
End If
CoTaskMemFree lResult
End If
End With
End Function

Private Function BrowseCallbackProc(ByVal hwnd As Long, _
ByVal uMsg As Long, _
ByVal lParam As Long,_
ByVal lpData As Long) As Long
Select Case uMsg
Case BFFM_INITIALIZED
If Len(mStartFolder) > 0 Then
SendMessage hwnd, BFFM_SETSELECTIONA, True, ByVal mStartFolder
End If
End Select
End Function

Private Function GetAddress(Addr As Long) As Long
GetAddress = Addr
End Function
========================================================================



Avatar
Anacoluthe
Bonjour !

'Bolderic' nous a écrit ...
Autre chose, que faut-il rajouter au code pour faire pointer la
fenêtre sur un dossier en particulier lors de l'affichage de la
fenêtre?


Hi hi hi Signalons que depuis WD2002 vba peut faire ça
aussi sans 'APInisme' ... :-p

Public Function UnRepertoire(T As String, I As String) As String
With Application.FileDialog(msoFileDialogFolderPicker)
.Title = T ' titre de la boîte de dialogue
.InitialFileName = I ' Chemin initial affiché
If .Show <> 0 Then UnRepertoire = .SelectedItems(1)
End With
End Function

Anacoluthe
« Il est très difficile d'imaginer quelque chose de simple. »
- Pierre MAC ORLAN

Avatar
Jacques93
Bonsoir,
Bonjour !

'Bolderic' nous a écrit ...

Autre chose, que faut-il rajouter au code pour faire pointer la
fenêtre sur un dossier en particulier lors de l'affichage de la
fenêtre?



Hi hi hi Signalons que depuis WD2002 vba peut faire ça
aussi sans 'APInisme' ... :-p

Public Function UnRepertoire(T As String, I As String) As String
With Application.FileDialog(msoFileDialogFolderPicker)
..Title = T ' titre de la boîte de dialogue
..InitialFileName = I ' Chemin initial affiché
If .Show <> 0 Then UnRepertoire = .SelectedItems(1)
End With
End Function

Anacoluthe
« Il est très difficile d'imaginer quelque chose de simple. »
- Pierre MAC ORLAN


Désolé, je ne fais pratiquement plus de VBA depuis Office97,
Un peu d'APInisme de temps en temps ne peux pas faire de mal
En tout cas, comme ça Bolderic aura le choix ;-)

Et en te citant :

« Ce n’est pas si simple que ça d’être simple. »
- Pierre REVERDY

ou,

« Les beaux chemins ne mènent pas loin. »
- Proverbe chinois

et je rajouterai : les API ... si, même très loin, parfois :-D


--
Cordialement,

Jacques


Avatar
Jacques93
Bonsoir,
Merci beaucoup Jacques93!!!!


Tout ce que tu m'as donné fonctionne P A R F A I T E M E N T.

Que ce soit le maintient de la fenetre en premier plan ou le pointage
sur un dossier en particulier, tout marche nickel!

Je t'avoue que je n'ai pas compris grand chose aux lignes que tu m'as
adressées, mais dans mon programme, elles ont fait des miracles.

Merci encore.

Sincères salutations.


P.S.: A present va falloir que j'essaie de comprendre ces lignes. ;-)



Content pour toi, et merci du retour :-)
Jettes un coup d'oeil sur la réponse d'Anacoluthe quand même ;-)

--
Cordialement,

Jacques.

Avatar
Bolderic
Merci beaucoup à Jacques93 et à Anacoluthe!

Merci messieurs pour votre aide précieuse!

Félicitation aussi pour votre dévouement à ce Forum.
Sans vous, que de nuits blanches nous passerions, nous autres
débutants.

Sincères salutations.

Bolderic.
Avatar
Bolderic
Bonjour,

Merci encore, pour vos lignes de codes.

Fonctionnant encore sous Word 2000, j'ai appliqué la solution de
Jacques 93.

Toutefois, j'aurais encore une petite demande à formuler : que
faudrait-il modifier au programme pour n'afficher par exemple que les
fichiers au format *.xls?
(en sachant que parfois il ne faudrait afficher que les *.xls, mais
d'autres fois tous selon le bouton cliqué).

Merci.

Ci-dessous les lignes de code que m'a fournies Jacques93 :

----------------------------------------------------------------------------------
Private Sub CommandButton37_Click()
Dim s As String
Dim hWnd As Long

hWnd = FindWindowA("ThunderDFrame", "UserForm1")
s = BrowseForFolder(hWnd, Fichier_excel, "Sélectionner un fichier",
True)

If s <> "" Then
Fichier_excel = s
UserForm3.Show
End If
End Sub

---------------------------------------------------------------------------------

' Macro écrite par Jacques93
Public Function BrowseForFolder( _
ByVal Owner As Long, _
Optional StartFolder As String = "", _
Optional Caption As String = "", _
Optional ShowFiles As Boolean = False, _
Optional Extension As String) As String
Dim bInfo As BrowseInfo
Dim sResult As String
Dim lResult As Long

With bInfo
.hwndOwner = Owner
'.hwndOwner = 0&
.pIDLRoot = 0
.pszDisplayName = String$(MAX_PATH, Chr$(0))
If Len(Caption) > 0 Then
.lpszTitle = Caption
End If
.ulFlags = BIF_RETURNONLYFSDIRS
If ShowFiles Then
.ulFlags = .ulFlags Or BIF_BROWSEINCLUDEFILES
End If
.lpfn = GetAddress(AddressOf BrowseCallbackProc)
.lParam = 0
.iImage = 0
mStartFolder = StartFolder

lResult = SHBrowseForFolder(bInfo)
If lResult <> 0 Then
sResult = String(MAX_PATH, 0)
If SHGetPathFromIDList(lResult, sResult) Then
BrowseForFolder = Left(sResult, InStr(sResult, Chr$(0)) - 1)
End If
CoTaskMemFree lResult
End If
End With
End Function
l
Avatar
Jacques93
Bonjour,

Merci encore, pour vos lignes de codes.

Fonctionnant encore sous Word 2000, j'ai appliqué la solution de
Jacques 93.

Toutefois, j'aurais encore une petite demande à formuler : que
faudrait-il modifier au programme pour n'afficher par exemple que les
fichiers au format *.xls?
(en sachant que parfois il ne faudrait afficher que les *.xls, mais
d'autres fois tous selon le bouton cliqué).



[...]

C'est peut être possible, mais uniquement à partir de Windows XP me
semble t-il. Jamais utilisé :

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/ifaces/ifolderfilter/ifolderfilter.asp

Par contre, ayant Word 2000, pourrais tu vérifier si tu disposes du
contrôle : Microsoft Common Dialog (ComDlg32.ocx), qui me semble t'il
serait plus adapté dans le cas de sélection d'un fichier
(SHBrowseForFolder étant comme son nom l'indique plus orienté
'Répertoire'), et d'une utilisation relativement proche que celle que
décrit Anacoluthe pour Word 2002.

Ce fichier, s'il est présent, devrait se trouver dans Windowssystem32,
ou dans le répertoire Office.

PS: Le code que j'ai transmis n'est qu'une adaptation de code déjà
existant.

--
Cordialement,

Jacques.

Avatar
Bolderic
Bonjour,

effectivement, j'ai bien trouvé le fichier "ComDlg32.ocx" sous
Windowssystem32.

Niveau API, je débute. Comment fait-on pour trouver la fonction
appropriée à ce que l'on désire faire? Faut-il les passer toutes en
revue ou existe-t-il une sorte de lexique qui en fonction de ce que
l'on souhaite obtenir vous donne la fonction correspondante?

Sincères salutations.



On Sun, 22 May 2005 20:26:39 +0200, Jacques93
wrote:

Bonjour,

Merci encore, pour vos lignes de codes.

Fonctionnant encore sous Word 2000, j'ai appliqué la solution de
Jacques 93.

Toutefois, j'aurais encore une petite demande à formuler : que
faudrait-il modifier au programme pour n'afficher par exemple que les
fichiers au format *.xls?
(en sachant que parfois il ne faudrait afficher que les *.xls, mais
d'autres fois tous selon le bouton cliqué).



[...]

C'est peut être possible, mais uniquement à partir de Windows XP me
semble t-il. Jamais utilisé :

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/ifaces/ifolderfilter/ifolderfilter.asp

Par contre, ayant Word 2000, pourrais tu vérifier si tu disposes du
contrôle : Microsoft Common Dialog (ComDlg32.ocx), qui me semble t'il
serait plus adapté dans le cas de sélection d'un fichier
(SHBrowseForFolder étant comme son nom l'indique plus orienté
'Répertoire'), et d'une utilisation relativement proche que celle que
décrit Anacoluthe pour Word 2002.

Ce fichier, s'il est présent, devrait se trouver dans Windowssystem32,
ou dans le répertoire Office.

PS: Le code que j'ai transmis n'est qu'une adaptation de code déjà
existant.



1 2