Rintracciare il File di un collegamento Fonte Dati esterna ad Excel. - dal 04/09/04 pagina vista: volte

Ho letto in un Forum, una domanda di cui riporto una sintesi : " per una cartella di Excel in cui esiste una tabella formata da dati provenienti da un database Access ( file .mdb ), come fare se si cambia posto al database ? Infatti Excel memorizza il percorso che mira al database, e cambiandogli collocazione, Excel non trova più il file e non può fare gli aggiornamenti."

Premesso che non mi occupo di Access, il problema riguarda Excel e come tale propongo una soluzione, può darsi che interessi anche qualche lettore di questo sito.

Quando in Excel si usa fare importazione di dati esterni (o dal menù Dati/Importa dati esterni/Importa dati..seguendo poi le istruzioni che chiedono dove si trova la fonte dati (quindi il percorso che mira alla fonte dati, che potrà anche essere un file .mdb cioè un database realizzato in Access, e quindi ad una tabella contenuta nel database stesso), o predisponendo istruzioni vba per ottenere lo stesso scopo), viene memorizzata una query che serve ad Excel per trovare, alle successive aperture della cartella, la fonte dati che alimenta la tabella su Excel, per poter effettuare aggiornamenti alla tabella stessa. Sia nella query che nelle eventuali istruzioni in vba (o macro che dir si voglia) viene memorizzato il nome del file fonte dei dati, completo del percorso, cioè il nome dell'hard-disk e della cartella e/o sotto cartelle dove si trova il file fonte dati.

Tanto per capirci, supponendo che la fonte dati si chiami "Mioesempiodb.mdb" il percorso che mira a questo file potrebbe essere : "C:\Documents and Settings\Nomeutente\Documenti\Mioesempiodb.mdb". Se noi spostiamo il file .mdb mettendolo in una ipotetica cartella "C:\MieiDati\", quando apriremo la cartella di Excel che contiene il collegamento a Mioesempiodb.mdb il file non verrà più trovato e i dati non potranno essere aggiornati.

L'esercizio che vedremo si avvale della proprierà FileSearch dell'oggetto Application, che serve, dato un percorso ed il tipo di file da cercare, a reperire il file cercato ottenendo in restituzione il percorso completo dove si trova il file. Affideremo questo percorso ad una variabile.

Supponendo quindi che la gestione del collegamento la si effettui tramite una macro, forniremo alle istruzioni la variabile (ottenuta con FileSearch) come sostitutivo del percorso al file.mdb che è necessario dichiarare. Associeremo la macro ad un pulsante, e quando avremo bisogno di aggiornare o reintegrare i dati, agiremo sul pulsante. Nella macro avremo inserito come inizio istruzioni, quelle relative al FileSearch, e tutte le volte verrà prima cercato il file.mdb, e se questo sarà stato spostato, verrà comunque trovato. Mi sembra una soluzione accettabile, che ne dite?

Esiste tuttavia una possibilità, che del file che cerchiamo ne esistano più di uno, magari perchè ne avremo creata una copia mettendola in un'altra cartella; FileSearch esegue la ricerca di tutti i file che si chiamano col nome cercato, e troverebbe quindi tutte e due, (o più) file con lo stesso nome, anche se in cartelle diverse; a questo punto quale è il giusto file? per evitare problemi creeremo una condizione che verifichi SE del file cercato ne esiste uno solo, e passeremo questo nome col suo percorso alla variabile, altrimenti per ogni file con lo stesso nome, porremo una domanda se il file col relativo percorso sarà quello voluto, e quando confermeremo, quello sarà il nome/percorso assegnato alla variabile. Aggiungiamo anche un controllo che ci faccia uscire dalla routine se, nel caso di più file, NON avremo comunque scelto nessuno dei file/percorso trovati; questo per impedire la prosecuzione delle istruzioni del collegamento, che trovando la variabile vuota, genererebbe un errore di run-time.

Vediamo quindi il blocco di istruzioni relativo al FileSearch, e dopo una routine completa di collegamento.

Sub CercaFonteDati()
Set fs = Application.FileSearch
'con la variabile "fs" impostiamo la proprietà FileSearch
With fs
.LookIn = "C:\" 
'con LookIn dobbiamo indicare l'hard-disk dove cercare il file
.SearchSubFolders = True
'poi diciamo di cercare in tutte le cartelle e sottocartelle
.Filename = "Mioesempiodb.mdb"
'indi forniamo il nome del file fonte dei dati da cercare

'sotto: usiamo il metodo Execute che inizia la ricerca per il file specificato. Restituisce un oggetto 'Long; zero (0) se non viene trovato alcun file o un numero positivo se vengono trovati uno o più 'file. Poichè abbiamo bisogno di reperire il nome del file+percorso, identificato da un numero, 'creiamo un ciclo che, contando il numero di file trovati, ci restituisca attraverso il numero, il 'percorso completo
If .Execute() = 1 Then
'quindi creiamo la prima condizione, cioè se viene trovato un solo file, 'assegnamo alla variabile X il nome+percorso rappresentato dalla "i" del ciclo (sotto):
For i = 1 To .FoundFiles.Count
X = .FoundFiles(i)
Next i
Else
'se invece verranno trovati più file con lo stesso nome, avvisiamo con un messaggio il numero 'di files trovati
MsgBox "Ci sono " & .FoundFiles.Count & file trovati."

'e quindi ripetiamo il ciclo che per ogni "i" trovato
For i = 1 To .FoundFiles.Count
'ci pone la domanda se è il file+percorso che interessa:
domanda = MsgBox("Trovato " & .FoundFiles(i) & " Vuoi questo?", vbYesNo)
If domanda = vbYes Then
 'se rispondiamo di si, allora X sarà uguale al nome+percorso "i"
X = .FoundFiles(i)
Exit For
 'e usciremo dal ciclo
End If
Next i
'altrimenti ripetiamo la domanda per ogni file+percorso trovato
End If

If IsEmpty(X) Then Exit Sub 'alla fine del ciclo, se non avremo scelto nessun file, usciremo da 'tutta la routine
End With

ecc.ecc.

Ora vediamo la routine completa delle istruzioni per il collegamento alla fonte dati, soprattutto per vedere come legare la variabile X alle due istruzioni che identificano il file fonte dati. Tenete presente che la ricerca del o dei files, può richiedere un pò di tempo; dipenderà (il tempo) dalla quantità di files presenti sull'hard-disk, oltre che dal numero di cartelle e sottocartelle. Non scordiamo che FileSearch dovrà "spulciare" tutto l'hard-disk. Per farvi un esempio, su un computer Pentium4 2400, facendo contare tutti i file presenti (*.*) indipendentemente dall'estensione, per cercare e contare 61154 files sono occorsi 4 minuti e 47 secondi. Mentre per cercare e contare tutti i file .mdb sono occorsi 8 secondi per un totale di 277 files. Quindi non sono tempi impossibili specialmente se il numero di files .mdb sarà più limitato. Se volete divertirvi a controllare il vostro computer, copiatevi queste istruzioni e inseritele in un modulo di una cartella excel, lanciando poi la macro.

Sub CercaFonteDati()
Set fs = Application.FileSearch
With fs
.LookIn = "C:\"
.SearchSubFolders = True
.Filename = "Mioesempiodb.mdb"
If .Execute() = 1 Then
For i = 1 To .FoundFiles.Count
X = .FoundFiles(i)
Next i
Else
MsgBox "Ci sono " & .FoundFiles.Count & file trovati."
For i = 1 To .FoundFiles.Count
domanda = MsgBox("Trovato " & .FoundFiles(i) & " Vuoi questo?", vbYesNo)
If domanda = vbYes Then
X = .FoundFiles(i)
Exit For
End If
Next i
End If
If IsEmpty(X) Then Exit Sub
End With

'a questo punto, se siamo qui, è perchè la variabile X contiene un percorso. Ad ogni successivo lancio della macro, 'i dati importati verrebbero di nuovo inseriti a partire dalla cella scelta come inizio tabella (nell'esempio la A5), 'SOLO SE LA CELLA SCELTA risulta vuota, altrimenti verrà selezionata la prima cella libera, stessa riga 5, dove 'importare i nuovi dati, NON aggiornando i dati vecchi, MA ricreando una nuova tabella a destra della prima. Sarà 'opportuno quindi cancellare i vecchi dati per far posto ai nuovi, e dovremo provvedere a cancellare la tabella e 'LA QUERY che Excel ha memorizzato. Poichè al primo lancio, con il foglio vuoto, si presume che la query non 'esista, per evitare un errore di run-time con l'istruzione QueryTable.Delete che non trovando nessuna query da 'cancellare genera l'errore, inseriamo questo semplice controllo: Se la cella A5 contiene dati (diversa da vuoto) si cancella l'area tabella e la query, altrimenti le istruzioni di cancellazione NON verranno eseguite.

If Range("A5") <> "" Then
ActiveSheet.UsedRange.Select
'per reperire tutta la tabella ho usato UsedRange e la seleziono
Selection.ClearContents 
'poi si cancellano i dati nella selezione
Selection.QueryTable.Delete
'e quindi si cancella la query
End If


'--------inizio istruzioni per il collegamento, in grassetto evidenzio la sintassi da usare per la variabile X - per la cella del foglio dalla quale inizierà l'importazione dati, ho usato la A5 a titolo di esempio.


Range("A5").Select
With ActiveSheet.QueryTables.Add(Connection:=Array( _
"OLEDB;Provider=Microsoft.Jet.OLEDB.4.0;Password="""";User ID=Admin;Data Source=" & X  & "; _  Mode=Share Deny Write;Extended Properties="""";Jet OLEDB:System database="""";Jet OLEDB:Registry Path="""";Jet OLEDB:Database Password="""";Jet OLEDB:Engine Type=5;Jet OLEDB:Database Locking _ Mode=0;Jet OLEDB:Global Partial Bulk Ops=2;Jet OLEDB:Global Bulk Transactions=1;Jet OLEDB:New Database Password="""";Jet OLEDB:Create System Database=False;Jet OLEDB:Encrypt Database=False;Jet _ OLEDB:Don't Copy Locale on Compact=False;Jet OLEDB:Compact Without Replica Repair=False;Jet _ OLEDB:SFP=False"), Destination:=Range("A5"))
.CommandType = xlCmdTable
.CommandText = Array("Tabella1")
.Name = "Mioesempiodb"
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.BackgroundQuery = True
.RefreshStyle = xlInsertDeleteCells
.SavePassword = True
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.PreserveColumnInfo = True
.SourceDataFile = " & X & "
.Refresh BackgroundQuery:=False
End With
End Sub

 

Ognuno di voi potrà, attivando il "registratore di macro", registrare i vari passaggi per l'importazione dati esterni, ottimizzando in proprio la parte "collegamento" della routine sopra. Poi potrà avvalersi della prima parte con FileSearch per adattare il tutto alle proprie esigenze.

L'importante era mettere in evidenza una routine che consentisse di trovare un file ovunque sia.

Buon lavoro.

prelevato sul sito www.ennius.altervista.org