General |
6.133 Creare una tabella contenente la struttura di un File System |
Roberto |
La Sub che segue è un'evoluzione della Sub elencafile() pubblicata in questa Sezione del Sito Comune da Lorenzo Coronati nella FAQ intitolata "Creare una tabella contenente i nomi di file presenti in una directory". Con quella Sub era possibile memorizzare in ua tabella solamente i nomi di tutti i file o di solo certi tipi di file contenuti in una directory. Con la Sub pubblicata in questa FAQ è invece possibile: 1) Memorizzare in una tabella la struttura completa contenuta in una directory (nome della directory + nomi delle subdirectory in essa contebute + nomi dei file contenuti nella directory + nomi dei file contenuti nelle subdirectory). 2) Memorizzare in una tabella solo i nomi dei file contenuti in una directory e nelle sue eventuali subdirectory (ovvero quanto al punto 1) esclusi i nomi delle directori e subdirectori) 3) Memorizzare in una tabella solo i nomi delle directory e subdirectory contenute nel file System relativo di una directory (ovvero quanto al punto 1) esclusi i nomi dei file. 4) Memorizzare in una tabella solo i nomi dei file contenuti in una directory (ovvero quello che si otteneva con la Sub di Lorenzo Coronati) 5) Memorizzare in una tabella solo i nomi delle subdirectory contenuti in una directory. Nella tabella verrà registrato un record per ogni directory/subdirectory e per ogni file conenuti nella directory selezionata. La tabella è composta dai seguenti tre campi: Percorso E' un campo di tipo Testo che rappresenta, per un record relativo ad un file il nome della sua directory (p.e. se il path completo di un file è C:\MiaCartella\MioFile.doc, in questo campo verrà memorizzato C:\MiaCartella\), mentre se il record è relativo ad una directory tale campo contiene il nome di detta directory. NomeFile E' un campo di tipo Testo: risulta vuoto in un record relativo ad una directory, mentre in un record relativo ad un file contiene il nome del file e la sua extension (p.e. se il path completo di un file è C:\MiaCartella\MioFile.doc, in questo campo verrà memorizzato MioFile.doc). Livello E' un campo di tipo Numerico che contiele il livello dell'oggetto nella gerarchia del File System; il record relativo alla directory scelta avrà livello 0 (zero), mentre i record relativi ai file ed alle subdirectory contenuti nella directory di livello 0 (zero) avranno livello1, invece i record relativi alle subdirectory ed ai file contenuti nelle subdirectory di livelli 1 avranno livello 2 e così via. Di fatto nella tabella si memorizzerà la struttura ad albero del File System contenuto in una determinata directory. Dalla maschera in cui si impostano i parametri che servono a creare e popolare la tabella (nome della direcory, tipo dei file da prendere in considerazione, ecc.) è possibile, pigiando un pulsante di comando, stampare la rappresentazione grafica di tale struttura ad albero. E' possibile anche stampare una lista del contenuto della tabella dei soli record relativi ai file: tale lista è ordinata per nome file e da essa è possibile vedere se un file è contenuto nella directory più volte, nel qual caso in quali subdirectory. Qui di seguito è mostrato il codice VBA dell sub che ottiene quanto sopra descritto: ' Sub che registra in una tabella la struttura di un File System ' Public Sub ' Sub che registra in una tabella la struttura di un File System ' Public Sub MemoFileSystem(Optional d As Variant, Optional j As String, Optional n As Integer) 'Argomenti: ' d=directory ' j=maschera di match (*.doc *.xls *.txt ecc.) ' n=tipo di dati da memorizzare ' 1 = struttura completa del File System ' 2 = solo i file del File System ' 3 = solo le directory del File System ' 4 = solo i file contenuti nella directory indicata ' 5 = solo le subdirectory contnute nella directory indicata Dim Tabella As DAO.TableDef Dim RstInput As DAO.Recordset Dim RstOutput As DAO.Recordset Dim s As String Dim s1 As String Dim Livello As Long Dim strRecordset As String Livello = 0 If Nz(d, "") = "" Then d = CurDir If j = "" Then j = "*.*" If Right(d, 1) <> "\" Then d = d & "\" If n < 1 Or n > 5 Then n = 1 'Imposta il nome della tabella s = "File System di " & d If EsisteOggetto("Tabella", s) = True Then ' se la tabella già esiste, viene svuotata DoCmd.SetWarnings False DoCmd.RunSQL "DELETE * FROM [" & s & "];" DoCmd.SetWarnings True Else ' se la tabella non esiste, viene creata Set Tabella = CurrentDb.CreateTableDef(s) Tabella.Fields.Append Tabella.CreateField("Percorso", dbText) Tabella.Fields.Append Tabella.CreateField("Livello", dbLong) Tabella.Fields.Append Tabella.CreateField("NomeFile", dbText) CurrentDb.TableDefs.Append Tabella End If ' imposta il recordset che tratterà la tabella in registarzione Set RstOutput = CurrentDb().OpenRecordset(s) ' registra nella tabella il record relativo alla directory RstOutput.AddNew RstOutput!Percorso = d RstOutput!Livello = 0 RstOutput!NomeFile = Null RstOutput.Update ' per ogni directory presente in tabella memorizza un record ' per ogni subdirectory in essa contenuta Do Until 1 = 2 ' imposta il recordset che tratterà la tabella in lettura; ' come si può vedere la stessa tabella verrà trattata ' contempraneamente con un recordset in lettura ' e con l'altro recordset in registrazione strRecordset = "(SELECT * FROM [" & s & "] WHERE Livello= " & Livello & " ;)" Set RstInput = CurrentDb().OpenRecordset(strRecordset) ' se il recordset è vuoto esci dal ciclo che scandisce le subdirectory If RstInput.RecordCount = 0 Then Exit Do RstInput.MoveFirst Do Until RstInput.EOF s1 = Dir(RstInput!Percorso, vbDirectory) Do While s1 <> "" ' Ignora la directory corrente e quella di livello superiore. If s1 <> "." And s1 <> ".." Then ' Usa il confronto bit per bit per verificare se s1 è una directory. If (GetAttr(RstInput!Percorso & s1) And vbDirectory) = vbDirectory Then ' prepara e registra un record relativo alla subdirecory s1 RstOutput.AddNew RstOutput!Percorso = RstInput!Percorso & s1 & "\" RstOutput!Livello = Livello + 1 RstOutput.Update End If End If s1 = Dir Loop RstInput.MoveNext ' leggi il record successivo Loop Livello = Livello + 1 Loop RstInput.Close Set RstInput = Nothing ' reimposta il recordset per la lettura della tabella strRecordset = "(SELECT * FROM [" & s & "] WHERE IsNull(NomeFile);)" Set RstInput = CurrentDb().OpenRecordset(strRecordset) ' leggi il primo record RstInput.MoveFirst Do Until RstInput.EOF If Nz(RstInput!Percorso, "") <> "" Then ' determina il nome di un file contenuto nella directory ' il cui percorso è contenuto nel record corrente s1 = Dir(RstInput!Percorso & j) Do While s1 <> "" ' prepara e registra il record relativo al file s1 RstOutput.AddNew RstOutput!NomeFile = s1 RstOutput!Percorso = RstInput!Percorso RstOutput!Livello = RstInput!Livello + 1 RstOutput.Update ' determina il nome di file successivo s1 = Dir Loop End If ' legi un altro record RstInput.MoveNext Loop Set Tabella = Nothing Set RstInput = Nothing Set RstOutput = Nothing ' la tabella contiene la struttura completa del File System; ' in base al valore dell'argomento n cancella dalla tabella ' i record che non si desidera mantenere memorizzati. DoCmd.SetWarnings False Select Case n Case 2 DoCmd.RunSQL "Delete * FROM [" & s & "] WHERE IsNull(NomeFile);" Case 3 DoCmd.RunSQL "Delete * FROM [" & s & "] WHERE Not IsNull(NomeFile);" Case 4 DoCmd.RunSQL "Delete * FROM [" & s & "] WHERE IsNull(NomeFile) Or Livello <> 1;" Case 5 DoCmd.RunSQL "Delete * FROM [" & s & "] WHERE ((Livello > 0) And (Not IsNull(NomeFile)) Or (Livello <> 1));" End Select DoCmd.SetWarnings True End Sub (Optional d As Variant, Optional j As String, Optional n As Integer) 'Argomenti: ' d=directory ' j=maschera di match (*.doc *.xls *.txt ecc.) ' n=tipo di dati da memorizzare ' 1 = struttura completa del File System ' 2 = solo i file del File System ' 3 = solo le directory del File System ' 4 = solo i file contenuti nella directory indicata ' 5 = solo le subdirectory contnute nella directory indicata Dim Tabella As DAO.TableDef Dim RstInput As DAO.Recordset Dim RstOutput As DAO.Recordset Dim s As String Dim s1 As String Dim Livello As Long Dim strRecordset As String Livello = 0 If Nz(d, "") = "" Then d = CurDir If j = "" Then j = "*.*" If Right(d, 1) <> "\" Then d = d & "\" If n < 1 Or n > 5 Then n = 1 'Imposta il nome della tabella s = "File System di " & d If EsisteOggetto("Tabella", s) = True Then ' se la tabella già esiste, viene svuotata DoCmd.SetWarnings False DoCmd.RunSQL "DELETE * FROM [" & s & "];" DoCmd.SetWarnings True Else ' se la tabella non esiste, viene creata Set Tabella = CurrentDb.CreateTableDef(s) Tabella.Fields.Append Tabella.CreateField("Percorso", dbText) Tabella.Fields.Append Tabella.CreateField("Livello", dbLong) Tabella.Fields.Append Tabella.CreateField("NomeFile", dbText) CurrentDb.TableDefs.Append Tabella End If ' imposta il recordset che tratterà la tabella in registarzione Set RstOutput = CurrentDb().OpenRecordset(s) ' registra nella tabella il record relativo alla directory RstOutput.AddNew RstOutput!Percorso = d RstOutput!Livello = 0 RstOutput!NomeFile = Null RstOutput.Update ' per ogni directory presente in tabella memorizza un record ' per ogni subdirectory in essa contenuta Do Until 1 = 2 ' imposta il recordset che tratterà la tabella in lettura; ' come si può vedere la stessa tabella verrà trattata ' contempraneamente con un recordset in lettura ' e con l'altro recordset in registrazione strRecordset = "(SELECT * FROM [" & s & "] WHERE Livello= " & Livello & " ;)" Set RstInput = CurrentDb().OpenRecordset(strRecordset) ' se il recordset è vuoto esci dal ciclo che scandisce le subdirectory If RstInput.RecordCount = 0 Then Exit Do RstInput.MoveFirst Do Until RstInput.EOF s1 = Dir(RstInput!Percorso, vbDirectory) Do While s1 <> "" ' Ignora la directory corrente e quella di livello superiore. If s1 <> "." And s1 <> ".." Then ' Usa il confronto bit per bit per verificare se s1 è una directory. If (GetAttr(RstInput!Percorso & s1) And vbDirectory) = vbDirectory Then ' prepara e registra un record relativo alla subdirecory s1 RstOutput.AddNew RstOutput!Percorso = RstInput!Percorso & s1 & "\" RstOutput!Livello = Livello + 1 RstOutput.Update End If End If s1 = Dir Loop RstInput.MoveNext ' leggi il record successivo Loop Livello = Livello + 1 Loop RstInput.Close Set RstInput = Nothing ' reimposta il recordset per la lettura della tabella strRecordset = "(SELECT * FROM [" & s & "] WHERE IsNull(NomeFile);)" Set RstInput = CurrentDb().OpenRecordset(strRecordset) ' leggi il primo record RstInput.MoveFirst Do Until RstInput.EOF If Nz(RstInput!Percorso, "") <> "" Then ' determina il nome di un file contenuto nella directory ' il cui percorso è contenuto nel record corrente s1 = Dir(RstInput!Percorso & j) Do While s1 <> "" ' prepara e registra il record relativo al file s1 RstOutput.AddNew RstOutput!NomeFile = s1 RstOutput!Percorso = RstInput!Percorso RstOutput!Livello = RstInput!Livello + 1 RstOutput.Update ' determina il nome di file successivo s1 = Dir Loop End If ' legi un altro record RstInput.MoveNext Loop Set Tabella = Nothing Set RstInput = Nothing Set RstOutput = Nothing ' la tabella contiene la struttura completa del File System; ' in base al valore dell'argomento n cancella dalla tabella ' i record che non si desidera mantenere memorizzati. DoCmd.SetWarnings False Select Case n Case 2 DoCmd.RunSQL "Delete * FROM [" & s & "] WHERE IsNull(NomeFile);" Case 3 DoCmd.RunSQL "Delete * FROM [" & s & "] WHERE Not IsNull(NomeFile);" Case 4 DoCmd.RunSQL "Delete * FROM [" & s & "] WHERE IsNull(NomeFile) Or Livello <> 1;" Case 5 DoCmd.RunSQL "Delete * FROM [" & s & "] WHERE ((Livello > 0) And (Not IsNull(NomeFile)) Or (Livello <> 1));" End Select DoCmd.SetWarnings True End SubNella Sub MemoFileSystem di cui sopra si fa riferimento alla funzione EsisteOggetto() già documentata in un'altra FAQ del Sito Comune e che per comodità del lettore riportiamo anche qui di seguito: 'Funzione che verifica l'esistenza di un determinato oggetto nel ' database corrente. ' Function EsisteOggetto(TipoOggetto As String, NomeOggetto As String) As Integer ' 'TipoOggetto stringa che può assumere il valore "Tabella", o "Query", ' o "Maschera", o "Modulo", o "Report" oppure "Macro" ' 'NomeOggetto è una stringa che contiene il nome dell'oggetto di cui si ' vuole verifivare l'esistenza ne database corrente ' ' la funzione ritorna il valore True o False On Error Resume Next Dim OggettoTrovato As Integer, CercaOggetto As String, NumOggetto As Integer Dim db As DAO.Database, t As DAO.TableDef Dim Q As DAO.QueryDef, C As DAO.Container Dim msg As String OggettoTrovato = False Set db = CurrentDb() Select Case TipoOggetto Case "Tabella" CercaOggetto = db.TableDefs(NomeOggetto).Name Case "Query" CercaOggetto = db.QueryDefs(NomeOggetto).Name Case Else If TipoOggetto = "Maschera" Then NumOggetto = 1 ElseIf TipoOggetto = "Modulo" Then NumOggetto = 2 ElseIf TipoOggetto = "Report" Then NumOggetto = 4 ElseIf TipoOggetto = "Macro" Then NumOggetto = 5 Else msg = "Il nome oggetto """ & TipoOggetto & """ non è un valido" msg = msg & " argomento per la funzione EsisteOggetto!" MsgBox msg, 16, "Funzione EsisteOggetto" Exit Function End If Set C = db.Containers(NumOggetto) CercaOggetto = C.Documents(NomeOggetto).Name End Select If Err = 3265 Or CercaOggetto = "" Then OggettoTrovato = False Else OggettoTrovato = True End If EsisteOggetto = OggettoTrovato End FunctionAnche il codice VBA di questa Sub va memorizzato in un modulo del database. Qui di seguito c'è un esempio di come richiamare la sub nel caso in cui si voglia memorizzare nella tabella sia i nomi delle subdirectory che i nomi dei file Word in esse contenuti: Dim NomeDirecory As String Dim TipoFile As String NomeDirectory = "C:\MiaCartella" TipoFile = "*.doc" Call MemoFileSystem(NomeDirectory, TipoFile,1)NB Nella Sub MemoFileSystem di cui sopra si fa riferimento alla libreria Microoft DAO quindi, se si usa una versione di Access successiva ad Access 97, occorre aggiungere tale libreria ai riferimenti del dataBase. La formattazione del report che disegna la struttura ad albero del File System è abbastanza complessa; durante lo svolgimento dell'elaborazione comparirà sul video la clessidra e sarà possibile seguire l'attuazione della formattazione con la barra di progressione posta nella barra di stato di Access, che si trova nella parte in basso a sinistra del video. Download: |