Cercare e Selezionare una Cartella (Folder
o Directory).
-
pagina vista: volte
Requisiti:
conoscenza VBA e struttura delle Directory.
Utilizzo della
proprietà: FileDialog - Questo articolo
descrive come mostrare una finestra di dialogo per richiedere all'utente di
scegliere una cartella. (testato con Excel 2003 e Excel 2007)
. Risolto Il problema presente con qualsiasi
altra funzione o proprietà che non "leggendo" in modo così semplice e lineare tutte
le cartelle e sottocartelle contenute in un hard-disk, hanno bisogno di
essere implementate in routine o funzioni ricorsive.
L'antefatto.
Mi sono ritrovato
ad avere la necessità di stampare un elenco di files presenti in una
determinata cartella (nomi di file immagini) e volendo realizzare la
procedura con Excel importando l'elenco in una colonna per poi stamparlo,
(esistono programmi free per ottenere dette stampe) e non volendo seguire le
procedure già spiegate in articoli sui miei due siti per comporre un elenco di files
(vedi ad esempio :
vba8.php
o anche
ifvba128.htm ) , ho trovato alcune difficoltà:
-
I metodi che
prevedono l'utilizzo dell'"Oggetto" FileSearch (peraltro il FileSearch
non lavora in Excel 2007) richiedono la definizione del "percorso" che
mira alla Directory (o Folder) da assegnare ad una
variabile, scrivendo il "percorso completo di path " in una InputBox, direttamente nel
codice, o tramite testo in celle del foglio.
-
Anche usando
il metodo CreateObject(Scripting.FileSystemObject) si deve comunque prevedere
il "percorso completo" che mira alla cartella contenente i files, e detto
"percorso" deve essere assegnato come sopra (manualmente ad una variabile o una costante
definita nel codice).
-
i due punti
sopra rendono la scelta dei "percorsi" sicuramente preordinata e niente
affatto automatizzabile.
In Excel quando si
voglia reperire e memorizzare il nome (completo di percorso) di un file,
possiamo usare il metodo GetOpenFileName,
ma quando desideriamo
"sfogliare" l'albero delle Directory per "prendere" il nome (e il "percorso") di una cartella (Directory o Folder) ci troviamo, pare,
senza "armi", cioè diventa difficile individuare il metodo da seguire.
Se infatti
cerchiamo in Internet qualche soluzione, possiamo ad esempio trovare in
questo Link
http://www.cpearson.com/excel/BrowseFolder.aspx
due validi suggerimenti per realizzare una finestra "Browser Folder": uno
è un
metodo basato sull'utilizzo delle Funzioni API di Windows e l'altro
sull'utilizzo della
Shell Controls
Library (vedi articolo al Link segnalato) e comunque l'autore (un autore di
tutto rispetto) dice addirittura che in Excel NON esiste la possibilità di
avere un "Navigatore per le Directory" : "..While
Excel has a built in File Open method (GetOpenFileName), it does not
provide a method to browse for a folder.."(ndr. : alla data inizio 2011 l'articolo citato risulta modificato con l'inserimento di un terzo sistema, rappresentato appunto dal FileDialog....)
Invece Excel
consente in maniera nativa di "sfogliare" le cartelle e di memorizzare il
percorso della cartella scelta, con l'Oggetto
FileDialog.
Perchè
automatizzare la selezione (e la scelta) di una cartella?
Usare una finestra
di dialogo rende
la selezione una scelta indipendente
e veloce consentendoci di rendere veramente variabile il
"percorso", a piacimento.
L'"Oggetto" FileDialog.
(Excel, come Application, possiede la "proprietà" FileDialog che restituisce
appunto l'oggetto FileDialog, cioè una finestra di "scelta")
L'"Oggetto"
FileDialog
ci consente comunque non solo di selezionare una directory o cartella che
dir si voglia, ma consente pure di selezionare uno o più file contenuti in
una cartella (ed importarne, volendo, l'elenco in un foglio di lavoro), oltre ad altre
due azioni interessanti: aprire file o salvare file, vediamo come:
La sintassi
dell'istruzione (vedi guida in linea nel vostro computer) richiede anche la definizione di un
argomento (di tipo MsoFileDialogType)
che qualifichi il tipo di finestra che vogliamo far apparire,
argomento rappresentato da una delle seguenti costanti:
-
msoFileDialogFilePicker
Consente di selezionare un file
-
msoFileDialogFolderPicker
Consente di selezionare una cartella.
-
msoFileDialogOpen
Consente di aprire un file.
-
msoFileDialogSaveAs
Consente di salvare un file.
In questo articolo
ci occuperemo solo di selezionare una cartella
(msoFileDialogFolderPicker)
e di selezionare uno o più file
(msoFileDialogFilePicker) -
l'istruzione base
necessaria per far apparire la finestra per la selezione di una directory
sarà:
per intenderci, ad
esempio, apparirà questa:
Chiaramente
possiamo selezionare cartelle, sottocartelle, sottosotto cartelle, etc. etc.
fino a che non raggiungeremo e selezioneremo la cartella desiderata. In
questo tipo di applicazione scelta
(msoFileDialogFolderPicker), poichè abbiamo
scelto di "Navigare tra Cartelle", nella parte centrale della finestra di
dialogo NON vedremo eventuali file presenti; è normale.
Nella finestra
"Sfoglia" i nomi delle cartelle sono rappresentate da tanti "Item" quante
sono le cartelle presenti nella finestra stessa, cioè vengono viste come
"parti" (Items) di un "insieme" (Collection (le Folder)), e selezionare una
cartella e premere il pulsante "OK" restituisce il "percorso" completo che
porta alla cartella stessa; se assegneremo detto "percorso" ad una variabile
avremo ottenuto con un semplice click quel "percorso" che ci necessita per
raggiungere i nostri files.
Avremo reso cioè
la definizione di un "percorso" una operazione veloce, adattabile
alle esigenze del momento, libera da assegnazioni preordinate nel codice, e
slegata dal path e dalle directory presenti nel computer sul quale la
routine è nata.
Applicazioni
pratiche.
La guida in linea
ci insegna: per poter sfruttare le caratteristiche dell'oggetto
FileDialog, avremo bisogno di creare un
ciclo For Each Next che, scorrendo l'insieme degli
Item (le Cartelle)
presenti nella finestra di dialogo, memorizzi la cartella selezionata al
click sul pulsante "OK", e la "Finestra di dialogo" di selezione delle
cartelle viene visualizzata utilizzando il metodo
Show dell'oggetto
FileDialog ed il percorso selezionato viene
acquisito nell'insieme
FileDialogSelectedItems.
Sarà quindi l'Item
(la cartella) selezionato nell'insieme
SelectedItems che restituirà il "percorso" completo che
mira alla nostra cartella. Assegneremo ad una variabile detto "percorso"
che useremo per le nostre necessità.
Prima di passare
ad esaminare le istruzioni, è meglio chiarire alcuni punti ricordando che:
-
La necessità
è quella di ottenere un elenco di nomi di files presenti in una
cartella, da stampare successivamente.
-
Vogliamo la
possibilità di poter scegliere con semplicità e velocità,
sfogliando le cartelle, di quale cartella ottenere l'elenco dei files
ivi contenuti.
-
NON desideriamo che nell'elenco compaia il "percorso" completo di path e nomi
di cartelle e/o sotto cartelle, ma SOLTANTO il nome del file.
Per il motivo di
cui al punto 3. usiamo la costante msoFileDialogFolderPicker
, (che restituisce il percorso che mira alla cartella, a cui
facciamo seguire istruzioni appropriate per "caricare" i nomi dei files) e
NON già la costante
msoFileDialogFilePicker
che ci consentirebbe di ottenere la lista dei files selezionati nella
finestra di dialogo, MA comprensivi del percorso completo.
Ecco quindi tre
esempi con tre routine diverse:
-
la macro
SelezionaCartella_CaricaNomiFiles()
- oltre al FileDialog(msoFileDialogFolderPicker) usiamo la Funzione CreateObject("Scripting.FileSystemObject") per "caricare" l'elenco
dei soli nomi dei files, senza il "percorso".
-
la macro
SelezionaCartella_e_Seleziona_NomiFiles()
- useremo il FileDialog(msoFileDialogFilePicker) e un ciclo che
per ogni nome di files selezionato nella finestra di dialogo,
scriva il nome del file completo di "percorso" in celle
del foglio di lavoro, creando l'elenco, senza l'utilizzo di
funzioni aggiunte (il CreateObjects)
-
la macro
SelezionaCartella_e_Seleziona_Solo_NomiFiles()
- simile al punto B., ma inseriamo la funzione CreateObject("Scripting.FileSystemObject")
per poter utilizzare il metodo
GetParentFolderName (che restituisce il
percorso di un file MA solo fino alla cartella che lo contiene)
eliminiamo il "percorso" e teniamo SOLO il nome del nome di cui
creeremo l'elenco.
precisazione: le
macro di cui ai punti A. e C. sono simili (restituiscono entrambe il SOLO
nome dei files) ma differiscono in modo sostanziale:
-
la macro
SelezionaCartella_CaricaNomiFiles()
- restituisce TUTTI i nomi dei files presenti nella cartella
selezionata.
-
la macro
SelezionaCartella_e_Seleziona_Solo_NomiFiles()
- restituisce SOLTANTO i nomi dei files che avremo selezionato nella
finestra che ci ha condotto alla cartella selezionata.
Vediamo le macro e
relative spiegazioni:
Sub
SelezionaCartella_CaricaNomiFiles()
Dim fd As FileDialog
'Dichiarazione della variabile "fd"
come una variabile FileDialog object.
Set fd = Application.FileDialog(msoFileDialogFolderPicker)
'creiamo l'oggetto FileDialog
come finestra di dialogo per le cartelle
e lo 'assegniamo alla variabile "fd"
'Sotto: dichiarariamo la variabile
"CartellaSelezionata" che conterrà il percorso della cartella
selezionata. Sebbene il percorso sia una 'Stringa la variabile
deve essere Variant perché il Ciclo For Each... Next lavora solo
con variabili Variant o Objects
Dim CartellaSelezionata As Variant
With fd 'Usiamo
l'istruzione With...End With per eseguire una serie di
istruzioni con l'oggetto FileDialog.
'Usiamo il metodo Show per mostrare
la dialog box ed usiamo la condizione If per verificare se
l'utente ha premuto il pulsante (di azione, 'di conferma) "OK"
If .Show = -1 Then 'se è
stato premuto il pulsante di conferma che restituisce -1
(il pulsante di annullamento restituirebbe 0) allora:
'iniziamo un ciclo For Each Next
necessario per scorrere l'insieme delle cartelle (la Colletion
del FileDialogSelectedItems) nella finestra '"Sfoglia".
For Each CartellaSelezionata In .SelectedItems
miaCartella = CartellaSelezionata
'assegniamo alla variabile "miaCartella"
il percorso della cartella che avremo selezionato
Next
Else
'se invece avremo premuto
annullamento
Exit Sub 'usciamo
dalla routine.
End If
'fine della condizione da verificare
End With 'fine
istruzione With
'Se siamo a questo punto abbiamo automatizzato la
memorizzazione del
"percorso" completo che mira alla cartella al 'cui interno sono i files di cui vogliamo l'elenco, ed ora usiamo la funzione CreateObject per scorrere e leggere tutti i
'nomi dei files nel
percorso "miaCartella", e con un ciclo For Each Next
leggiamo il nome di ogni file e tramite un ciclo 'While..Wend
interno, cerchiamo la prima cella libera dove scrivere quel nome
di file. Il tutto avviene in automatico.
Dim fs, F, Nomefile, Cartella
Set fs = CreateObject("Scripting.FileSystemObject")
Set F = fs.GetFolder(miaCartella)
Set Cartella = F.Files
For Each Nomefile In Cartella
'si inizia il ciclo che per ogni file (Nomefile)
presente in Cartella
DoEvents
'sotto: iniziamo la ricerca di una
cella libera, a partire dalla riga 2 (iRow = 2) e dalla colonna
1 (la A icol = 1) usando il ciclo While..Wend
Dim iRow, icol As Integer
iRow = 2 'inizio la
ricerca dalla riga 2 del foglio come esempio, ognuno deciderà da
quale riga iniziare l'elenco dei nomi dei files
icol = 1 'e
dalla colonna 1 la colonna A
While Cells(iRow, icol).Value <> ""
iRow = iRow + 1
Wend
Cells(iRow, icol) = Nomefile.Name
'nella cella libera andrà il nome del file letto (per ogni "NomeFile"...)
Next 'continua il ciclo fino alla
fine dei files presenti nella cartella scelta.
Set fs = Nothing 'eliminiamo
le variabili dalla memoria
Set Cartella = Nothing
Set F = Nothing
Set fd = Nothing
End Sub |
la seconda macro
che consente invece di selezionare i file di cui vogliamo importare il nome
(però completo di "percorso" (il Path)):
Sub
SelezionaCartella_e_Seleziona_NomiFiles()
Dim fd As FileDialog
'Dichiarazione della variabile "fd" come
FileDialog object.
Set fd = Application.FileDialog(msoFileDialogFilePicker)
'creiamo l'oggetto FileDialog come finestra di dialogo per le
cartelle
e lo 'assegniamo alla variabile "fd"
'Sotto: dichiariamo la variabile
"FileSelezionato" che conterrà il "percorso" completo dei
files
selezionati. Sebbene il percorso sia una 'Stringa la variabile
deve essere Variant perché il Ciclo For Each... Next lavora solo
con variabili Variant o Objects
Dim FileSelezionato As Variant
With fd 'Usiamo
l'istruzione With...End With per eseguire una serie di
istruzioni con l'oggetto FileDialog.
'Usiamo il metodo Show per mostrare
la dialog box ed usiamo la condizione If per verificare se
l'utente ha premuto il pulsante (di azione, 'di conferma) "OK"
If .Show = -1 Then
'se la condizione si è verificata, allora....
'iniziamo un ciclo For Each Next
necessario per scorrere l'insieme dei files che avremo
selezionato (e SOLO QUELLI) (la Colletion
del 'FileDialogSelectedItems) nella finestra '"Sfoglia" - sarà
possibile selezionare anche files non contigui tenendo premuto
il tasto 'CTRL (Control) mentre si selezionano i files.
For Each FileSelezionato In .SelectedItems
'FileSelezionato è ora una stringa che contiene il path (il
percorso) di ogni Item (.In SelectedItems)
selezionato.
'e per ogni FileSelezionato iniziamo un ciclo interno While..Wend
che cerchi la prima cella libera e ci scriva nome e percorso.
Dim iRow, icol As Integer
iRow = 2 'inizio la
ricerca dalla riga 2 del foglio come esempio
icol = 1 'e
dalla colonna 1 la colonna A
While Cells(iRow, icol).Value <> ""
iRow = iRow + 1
Wend
Cells(iRow, icol) = FileSelezionato
Next FileSelezionato
Else
'se invece l'utente avrà premuto il pulsante annulla, si
esce dall'istruzione
End If
End With
' eliminiamo
la variabile oggetto dalla memoria
Set fd = Nothing
End Sub |
vediamo due immagini di come lavora la macro
SelezionaCartella_e_Seleziona_NomiFiles() : a sinistra la dialog box (FileDialog)
"Sfoglia" dove si notano i files selezionati, tra l'altro in modo non
conseguente, e a destra l'elenco con i nomi dei file selezionati,
COMPRENSIVI di percorso (Unità hard-disk, cartella, sottocartella, nome ed
estensione del file)
La terza macro la usiamo quando desideriamo comporre un elenco dei SOLI nomi
(con estensione) dei files ma NON desideriamo far comparire il suo percorso
completo: (commento solo le istruzioni diverse)
Sub
SelezionaCartella_e_Seleziona_Solo_NomiFiles()
Dim FsO
Dim LPT 'lunghezza
totale caratteri stringa del percorso completo di nome del file
Dim LPC ' lunghezza
percorso all'ultima cartella senza il nome del file
Dim SoloNomeFile
'il solo nome di ogni file selezionato
Dim Differenza As Integer
Dim fd As FileDialog
Set fd = Application.FileDialog(msoFileDialogFilePicker)
Set FsO = CreateObject("Scripting.FileSystemObject")
Dim Selezionato As Variant
With fd
If .Show = -1 Then
For Each Selezionato In .SelectedItems
LPC = Len(FsO.GetParentFolderName(Selezionato)) 'usiamo
il metodo GetParentFolderName del FsO che restituisce il
percorso fino
'all'ultima cartella contenente i files cercati
LPT = Len(Selezionato)
Differenza = (LPT - LPC) - 1
'facciamo la differenza sottraendo il
percorso fino all'ultima cartella dal percorso (più lungo)
contenente 'anche il nome del file
SoloNomeFile = Right(Selezionato, Differenza)
'quindi con Right prendiamo nella
stringa, iniziando da destra, solo la quantità di
'caratteri rappresentata dal numero "Differenza" e lo
assegniamo alla variabile SoloNomeFile
Dim iRow, icol As Integer 'ora
cerchiamo la prima cella libera nella colonna 1 dove registra il
nome del file
iRow = 2
icol = 1
While Cells(iRow, icol).Value <> ""
iRow = iRow + 1
Wend
Cells(iRow, icol) = SoloNomeFile
Next Selezionato
Else
End If
End With
Set fd = Nothing
Set FsO = Nothing
End Sub |
e la routine sopra
restituirà solo i nomi dei file (vedi sotto, senza il percorso completo) che
avremo selezionato nella cartella scelta.
buon lavoro.
prelevato sul sito
www.ennius.altervista.org
|