Drivelist, DirList e Filelist. - dal 04/09/04 pagina vista: volte

Gli "Oggetti" ActiveX : DriveListBox, DirListBox e FileListBox e le relative funzioni, disponibili per progetti in VB, NON esistono in VBA. E' possibile, con un pò di pazienza, "costruirsi" dei "surrogati" che sostituiscano questi oggetti, ricorrendo alla funzione "CreateObject", ed usando una ComboBox e alcune ListBox.

Esiste una documentazione ampia nella guida in linea, che invito a leggersi, corredata da numerosi esempi, riguardo alla funzione CreateObject, Folder, ecc. e agli argomenti correlati. Comunque, a grandi linee, la funzione Create Object si avvale dell'oggetto FileSystemObject per accedere al FileSystem. Infatti CreateObject  serve per creare e restituisce un riferimento a un oggetto ActiveX. La sua sintassi di base viene costruita in questo modo:  CreateObject(classe,[nomeserver]) dove per "classe" si intende il nome dell'applicazione e la classe dell'oggetto da creare. "Nomeserver" è opzionale e indicherebbe il nome del server di rete su cui verrà creato l'oggetto. Se è una stringa vuota (""), viene utilizzato il nome del computer locale.

Per avvicinarsi ai concetti, impostiamo un esempio per visualizzare un insieme di cartelle (folders):

Dim fs, f  'dichiarazione di variabili di tipo Variant
folderspec =  "C:\"  'variabile che indica il percorso di cui visualizzare le cartelle
Set fs = CreateObject("Scripting.FileSystemObject")
'assegnazione alla variabile "fs" dell"oggetto" restituito dalla funzione CreateObject
Set f = fs.GetFolder(folderspec)
'assegnazione alla variabile "f" dell'oggetto ottenuto tramite "fs" che col metodo GetFolder restituisce un oggetto Folder corrispondente a una cartella nel percorso specificato (folderspec =  "C:\").

in questo esempio mancano le istruzioni di come fare per visualizzare le cartelle, ma lo vedremo tra poco. Basandoci dunque su questo tipo di istruzioni, ecco cosa possiamo realizzare:

Come si nota, è presente una combobox che serve a selezionare l'unità di cui vogliamo l'elenco delle cartelle, che appaiono nella ListBox sotto. Da questa è possibile selezionare una cartella ed otterremo le sue sottocartelle nella ListBox successiva, ed i file della cartella nella ListBox più grande a destra. Se selezioniamo una sottocartella, otterremo nella ListBox a destra l'elenco dei file della sottocartella selezionata. Mi fermo a questi esempi, ma sarebbe possibile continuare a cercare tutte le sottocartelle che vorremo con i relativi files. Lo scopo finale di quest'esercizio, oltre a quello di vederne le istruzioni, è quello di ottenere nel contempo un elenco delle cartelle e file selezionati, sul foglio di lavoro, in modo da crearsi un database della composizione del nostro/i hard-disk. Una cosa del genere:

Il tutto è migliorabile, ma lascio ai volenterosi il compito di apportarsi le modifiche. Ma vediamo come lavorare:

Per prima cosa provvediamo a "caricare" la Combobox con l'elenco delle unità di memorizzazione presenti sul nostro computer (hard-disk, floppy, lettori CD, ecc. ecc.) e sfrutteremo l'evento Activate dell'userform:

Private Sub UserForm_Activate()
Dim fs, d, dc
'inizializiamo le variabili
Set fs = CreateObject("Scripting.FileSystemObject")
'usiamo CreateObject assegn. a fs
Set dc = fs.Drives
 'impostiamo dc come insieme dei drives (delle unità)
For Each d In dc 
'per ogni d (unità) nell'insieme dc (drives)

ComboBox1.AddItem d.DriveLetter 
'aggiungiamo la lettera del drive "d" nella combo
Next
Set fs = Nothing 
'poi si cancellano le tre variabili dalla memoria
Set d = Nothing
Set dc = Nothing
End Sub

 

in modo da ottenere l'elenco da cui poter selezionare l'unità che ci interessa, così............................................................................>

Poi sfrutteremo l'evento Change della Combobox, per caricare i nomi delle cartelle presenti nell'unità selezionata, come elenco nella ListBox1

Private Sub ComboBox1_Change()
On Error Resume Next
'usiamo il controllo errori in quanto, selezionando una unità  (il 'lettore di floppy o un lettore CD), se vuoti, si genera un errore di run-time. In questo 'modo, sfruttando il codice errore, avvisiamo con un messaggio ed usciamo dalla routine 'senza bloccare.
ListBox1.Clear 
'puliamo la Listbox1 per il refresh (lista cartelle)


X = ComboBox1.Text 
'usiamo una variabile (la X) che rappresenta la lettera dell'unità 'selezionata, concatenandola poi ai due punti e la backslash per formare la sintassi giusta 'di identificativo unità, da assegnare alla variabile folderspec

folderspec = "" & X & ":" & "\" & ""
'folderspec sarà ad esempio uguale a  C:\
Label3.Caption = folderspec 
'usiamo la caption di una label posta sulla form, per 'indicare il percorso selezionato
[b1].Value = "FILES IN " & Label3.Caption '
e prepariamo nella cella B1 la scritta 'FILES IN + percorso come scritto nella label


Dim fs, f, f1, fc
'dichiariamo le variabili per le istruzioni relative al CreateObject
Set fs = CreateObject("Scripting.FileSystemObject")
Set f = fs.GetFolder(folderspec)
'vedi spiegazioni nel primo esempio a inizio pagina


If Err.Number = 76 Then
'se si verifica che l'unità è vuota, si genera questo errore che 'sfruttiamo per avvisare col messaggio sotto
MsgBox "" & folderspec & " Unità vuota"
Exit Sub
'ed usciamo dalla routine
End If


Set fc = f.SubFolders
'impostiamo con "fc" l'insieme delle cartelle (SubFolders) reperite 'con la variabile "f" (fs.GetFolder)
For Each f1 In fc 
' per ogni cartella (f1) presente in "fc"
ListBox1.AddItem f1.Name
 'inseriamo il nome cartella nella ListBox1
Next
Set fs = Nothing 
'poi si cancellano le tre variabili dalla memoria
Set f = Nothing
Set f1 = Nothing
Set fc = Nothing
Resume
End Su
b

e dopo questa operazione, troveremo l'elenco di tutte le cartelle presenti nell'unità selezionata, nella nostra ListBox1. Non ho inserito in questo passaggio il caricamento della ListBox2 dei nomi dei files presenti nell'unità selezionata, perchè un elenco dei files in genere lo troviamo all'interno di una cartella, e visto che vorremo memorizzare il contenuto di una cartella, questo passaggio l'ho saltato. Basterà però vedere le istruzioni che seguono qua sotto, per reperire le istruzioni necessarie ed integrarle nella routine sopra.

Il secondo passaggio riguarda la selezione di una cartella nell'elenco della ListBox1, in modo da ottenere un elenco di sottocartelle nella ListBox3 (quella in basso a sinistra nella foto), e un elenco di file contenuti nella cartella selezionata nella ListBox2 (la grande a destra). Contemporaneamente otterremo che l'elenco delle sottocartelle venga scritto sul foglio di lavoro nella colonna A, tante righe per quante saranno le sottocartelle, e a partire dalla colonna B il nome dei files. In questo caso ho inserito un ciclo che consente di riempire fino alla riga 62, e se il numero dei files sono maggiori di 62, il ciclo si sposta nella colonna successiva, continuando fino alla riga 62 e scalando ancora di colonna fino a che non sia completato l'elenco dei files. Questa ultima operazione, in realtà non era necessaria, bastava lasciarli inserire verso il basso solo nella colonna B, ma l'ho inserita per far vedere come eventualmente occupare più colonne nel caso si preferisca riempire verso destra anzichè solo verso il basso. Queste comunque le istruzioni, che assegneremo all'evento Click della ListBox1: (le istruzioni simili alle soprastanti non saranno commentate)

Private Sub ListBox1_Click()
pulisci
 'si chiama la macro "pulisci" che serve a pulire tutte le celle del foglio di lavoro
ListBox2.Clear  'si pulisce la ListBox2 (quella dei files, a destra)
ListBox3.Clear 
'si pulisce la ListBox3 (quella delle sottocartelle, in basso a destra)
unita = (ComboBox1.Text & ":" & "\")
'si prende con "unita" l'unità selezionata
dire = ListBox1.Text
 'con "dire" leggiamo il nome della cartella selezionata

folderspec = (unita & dire & "\")
'con folderspec componiamo il percorso
Label3.Caption = folderspec  
 'e lo mostriamo nella Label3
[b1].Value = "FILES IN " & Label3.Caption
 'vedi routine precedente
Dim fs, f, f1, fc, fd
Set fs = CreateObject("Scripting.FileSystemObject")
Set f = fs.GetFolder(folderspec)
Set fc = f.Files 
'impostiamo con "fc" l'insieme dei Files (nomi dei) reperiti con la variabile "f" '(fs.GetFolder)

For Each f1 In fc  
' per ogni NomeFile (f1) presente in "fc"
ListBox2.AddItem f1.Name 
'aggiungiamo il nome del file nella ListBox2

'sotto iniziamo la ricerca di una cella libera, a partire dalla riga 2 (iRow = 2) e dalla 'colonna 2 (la B)(icol = 2) usando il ciclo While... Wend, con la condizione che quando il 'numero riga sarà uguale a 62, incrementiamo di 1 il numero colonna spostandoci quindi 'alla colonna successiva verso destra per continuare a cercare celle libere. Modificando 'questi valori : iRow, icol e 62 (limite riga inferiore) potrete decidere dove e come vorrete 'il vostro elenco files

Dim iRow, icol As Integer
iRow = 2
icol = 2
While Cells(iRow, icol).Value <> ""
iRow = iRow + 1
If iRow = 62 Then
iRow = 2
icol = icol + 1
End If
Wend
Cells(iRow, icol) = f1.Name
'nella cella libera andrà il nome del vettore f1

Next
'continua il ciclo fino alla fine degli f1.Name

'sotto: finito il ciclo per riportare i nomi dei files nella ListBox2 e sul foglio di lavoro, 'iniziamo il ciclo con l'assegnazione alla variabile "fd" non più dei nomi files legati alla 'variabile "fc" (f.Files) , ma delle sottocartelle presenti nella cartella selezionata, 'riempendo con i nomi trovati la ListBox3 e la colonna A sul foglio di lavoro, e 'impostando il carattere grassetto e il colore rosso ai nomi sul foglio.I commenti sono i 'soliti visti appena sopra.

Set fd = f.SubFolders
For Each f1 In fd

ListBox3.AddItem f1.Name

iRow = 1
While Cells(iRow, 1).Value <> ""
iRow = iRow + 1
Wend
Cells(iRow, 1) = f1.Name
Cells(iRow, 1).Font.Bold = True
Cells(iRow, 1).Font.ColorIndex = 3
Next
Set fs = Nothing
Set fd = Nothing
Set f = Nothing
End Sub

Con le spiegazioni mi fermo qui perchè sarebbero ripetitive. Ovviamente sono presenti istruzioni anche nell'evento Click della ListBox3, ma potrete scoprirle scaricando il file. Se si volesse aggiungere una ListBox per sottocartelle di sottocartelle, oppure usare le stesse ListBox facendo apparire il contenuto delle sottocartelle (ListBox3) nella ListBox1 al posto delle cartelle, dopo aver selezionato una cartella, in modo da usare le sotto/sottocartelle nella ListBox3 e i relativi files nella ListBox2, un pò come avviene con le vere DriveListBox, DirListBox e FileListBox . Ma altrimenti che piacere vi lascerei, se proponessi tutto io? Uno sguardo alle due macro "pulisci" e "puliscifile"

  • Sub pulisci:

  • Sub pulisci()
    With ActiveSheet
    .UsedRange.ClearContents 
    'con UsedRange si puliscono tutte le celle con dati
    .Cells(1, 1) = "CARTELLE" 
    'in A1 si scrive la parola CARTELLE
    .Cells(1, 2) = "FILES IN"   
    'in B1 si scrive la parola FILES IN
    End With
    End Sub

  • Sub puliscifile

  • Sub puliscifile()
    ult = [b2].End(xlToRight).Address
    'con ult prendiamo l'ultima colonna a destra occupata, riga 2
    Set zonafile = Range([b1].End(xlDown), Range(ult))
    'con zonafile reperiamo l'area da B1 all'ultima
    zonafile.ClearContents                                            
     'cella in basso e fino a ult e puliamo.
    With ActiveSheet
    .Cells(1, 2) = "FILES IN"  
    'in B1 si scrive la parola FILES IN
    End With
    End Sub

I fogli potranno essere salvati come singoli fogli, in modo da formarsi un database dei contenuti dell'hard-disk, e ovviamente potranno essere stampati.

File da scaricare e consultare :  ElencoFile2000.zip   26 Kb

Se invece vogliamo caricare la lista dei nomi dei files presenti in una determinata cartella, (sempre la solita), saranno necessarie minori istruzioni. Basta ovviamente impostare nel codice il percorso che mira alla cartella, e poi decidere in quale colonna e da quale riga iniziare ad importare i nomi dei files. La routine è simile a quelle sopra, solo un pò più "alleggerita".

Poichè usiamo un ciclo While per cercare una cella libera dove "scrivere" ogni nome di file trovato nella cartella specificata, dovremo "pulire" le celle se vogliamo che ogni volta che chiamiamo la macro, i nomi non si accodino a quelli esistenti, caricati con lanci precedenti (altrimenti creeremmo solo dei duplicati). Potremo anche sfruttare l'evento Open del Workbook, per lanciare la macro all'apertura della cartella di lavoro. Vediamo la macro; nell'esempio ho scelto di iniziare dalla cella A2, quindi riga 2, colonna 1: (le istruzioni simili a quelle sopra non le commento)

Sub CaricaNomiFile()
Range([a2], [a2].End(xlDown)).ClearContents
 'puliamo la zona con i nomi dei files

folderspec = ("C:\Temp\")
'con folderspec indichiamo il percorso che mira alla cartella di cui 'vogliamo l'elenco files, ognuno dovrà modificare secondo le proprie esigenze

Dim fs, f, Nomefile, Cartella
Set fs = CreateObject("Scripting.FileSystemObject")
Set f = fs.GetFolder(folderspec)
Set Cartella = f.Files
'sotto: si inizia il ciclo che per ogni file (Nomefile) presente in Cartella
For Each Nomefile In Cartella
'
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
icol = 1
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...)

Next
'continua il ciclo fino alla fine dei files presenti nella cartella scelta.

Set fs = Nothing
Set Cartella = Nothing
Set f = Nothing
End Sub

e nell'evento Open del Workbook, basterà chiamare il nome della macro, così:

  • Private Sub Workbook_Open()
    CaricaNomiFile
      'nome della macro
    End Sub

Buon lavoro.

prelevato sul sito www.ennius.altervista.org