File .csv importati in una tabella tramite vba

di il
10 risposte

File .csv importati in una tabella tramite vba

Ciao a tutti.
Sto provando a far importare una serie di file .csv tramite codice vba.
Il codice è questo:
Sub aggiorna_deal()
Dim dire As String, db_transit As Database, recset_transit As Recordset, sqlstatement As String
Dim qdef As QueryDef, db As Database, recordsettt As Recordset


dire = CurrentProject.Path
Dim nomefile As String
nomefile = Dir(dire & "\")
Do While nomefile <> ""


        Set db_transit = OpenDatabase(dire, dbDriverNoPrompt, True, "Text;Database=" & nomefile & ".CSV")

        Set recset_transit = db_transit.OpenRecordset("SELECT * FROM " & nomefile & """", dbOpenDynaset)

        Set db_transit = Nothing


        Set db = CurrentDb
        Set qdef = db.CreateQueryDef("")


        sqlstatement = ("INSERT INTO recordsettt SELECT * from recset_transit;")
        Set recordsettt = db.OpenRecordset("Silente")
        qdef.SQL = sqlstatement
    

    nomefile = Dir
Loop
End Sub
In sostanza:
1. creo un database (chiamato db_transit) dal file .csv
2. creo un recordset (chiamato recset_Transit) dal database
3. chiudo il database e ne apro un altro sul file su cui è scritta la macro (currentdb)

E FINO A QUA TUTTO BENE (lo so perché se faccio un debug.print scrive il valore del recordset)

4. apro un recordset (chiamato Silente) del database corrente
5. dico di scrivere i dati nella tabella del recordset "Silente"

nonostante non mi dia nessun messaggio di errore, la tabella Silente rimane vuota.
Qualcuno sa dove sbaglio?
grazie in anticipo!

10 Risposte

  • Re: File .csv importati in una tabella tramite vba

    Manca
    qdef.execute
    per eseguire la query (intervento telegrafico, scrivo da cell)
  • Re: File .csv importati in una tabella tramite vba

    Philcattivocarattere ha scritto:


    Manca
    qdef.execute
    per eseguire la query (intervento telegrafico, scrivo da cell)
    Integro suggerendo di valutare l'utilizzo di dbFailOnError e di inserire il tutto in una transaction

    E senza entrare nel merito e nell'opportunità dell'uso di quel codice, c'è anche TransferText
  • Re: File .csv importati in una tabella tramite vba

    Ciao Phil.
    Grazie della risposta. Gentile come sempre.
    Purtroppo non riesco a farla funzionare, aggiungendo il comando qdef.execute
    Mi appare un messaggio che dice:

    run-time '3078':
    the Microsoft access database engine cannot find the input table or query 'recset-transit'. Make sure it exists and that its name is spelled correctly.

    Questo messaggio di errore mi appare anche se uso la funziona
    CurrentDb.Execute sqlstatement
    oppure
    Docmd.RunSQL sqlstatement
    E' come se recset-transit, che nn è una tabella reale ma "di passaggio", non la riconoscesse.
    Qualche idea?
  • Re: File .csv importati in una tabella tramite vba

    galantik ha scritto:


    Ciao Phil.
    Grazie della risposta. Gentile come sempre.
    Purtroppo non riesco a farla funzionare, aggiungendo il comando qdef.execute
    Mi appare un messaggio che dice:

    run-time '3078':
    the Microsoft access database engine cannot find the input table or query 'recset-transit'. Make sure it exists and that its name is spelled correctly.
    ...
    E' come se recset-transit, che nn è una tabella reale ma "di passaggio", non la riconoscesse.
    Qualche idea?
    Ora non vorrei che fosse un errore di trascrizione ma in quello che avevi postato all'inizio era recset_transit, non recset-transit. Non può essere una cosa del genere.
  • Re: File .csv importati in una tabella tramite vba

    Si si. è un errore di trascrizione. il messaggio fa riferimento effettivamente a "recset_transit" (ho sbagliato a riportarti il messaggio di errore).
    Ma la cosa che mi sembra strana è che recset_transit lo compila correttamente.
    Questo lo posso verificare dicendogli:
    recset_transit.MoveFirst
            Debug.Print recset_transit
    e in effetti scrive quello che deve scrivere. Quindi il problema è proprio l'istruzione di INSERT tramite SQL, che si blocca con il comando di esecuzione (tipo qdef.execute o gli altri con cui ho provato).
  • Re: File .csv importati in una tabella tramite vba

    galantik ha scritto:


    si si. è un errore di trascrizione. il messaggio fa riferimento effettivamente a "recset_transit" (ho sbagliato a riportarti il messaggio di errore).
    Ma la cosa che mi sembra strana è che recset_transit lo compila correttamente.
    Questo lo posso verificare dicendogli:
    recset_transit.MoveFirst
            Debug.Print recset_transit
    e in effetti scrive quello che deve scrivere. Quindi il problema è proprio l'istruzione di INSERT tramite SQL, che si blocca con il comando di esecuzione (tipo qdef.execute o gli altri con cui ho provato).
    Tutto troppo difficile per me.
    Torno a riproporre quindi TransferText che in una situazione come questa mi sembra perfetto
    Con il tempo imparerò anche a copiare da recorset a recorset.
  • Re: File .csv importati in una tabella tramite vba

    NOOOOOO CHE DELUSIONE!!!! IL MIO MENTORE!!!!!
    scherzo ovviamente... grazie lo stesso del tentativo.
    transferText lo avevo valutato, ma ci sono 2 cose che me lo hanno fatto mettere da parte:
    1. mi sembra più adatto a trasferire tutto il contenuto di un file, e poco adatto a selezionare solo alcuni campi del file (ma questo credo sia risolvibile in qualche modo)
    2. la seconda query che ti ho proposo (INSERT INTO recsettt SELECT * FROM rec_transit) dovrebbe fare l'inserimento solo in presenza di un nuovi record, anche perché ogni giorno dovrebbe fare il controllo di questi file .csv e li duplicherebbe ogni volta.
    In sostanza l'idea è che apra uno alla volta i file .csv di una certa directory, selezioni alcuni campi e crei cosi la tabella temporanea e poi vada a scrivere il contenuto di questa tabella temporanea nella tabella reale "Silente" solo se non sono già presenti.
    NOn ho ancora compilato la query finale per bene, perché già si blocca così...
    Grazie lo stesso Phil.
  • Re: File .csv importati in una tabella tramite vba

    galantik ha scritto:


    NOOOOOO CHE DELUSIONE!!!! IL MIO MENTORE!!!!!
    scherzo ovviamente... grazie lo stesso del tentativo.
    transferText lo avevo valutato, ma ci sono 2 cose che me lo hanno fatto mettere da parte:
    1. mi sembra più adatto a trasferire tutto il contenuto di un file, e poco adatto a selezionare solo alcuni campi del file (ma questo credo sia risolvibile in qualche modo)...
    Ci sono le specifiche di importazione che permettono di selezionare quali campi importare.

    galantik ha scritto:


    2. la seconda query che ti ho proposo (INSERT INTO recsettt SELECT * FROM rec_transit) dovrebbe fare l'inserimento solo in presenza di un nuovi record, anche perché ogni giorno dovrebbe fare il controllo di questi file .csv e li duplicherebbe ogni volta.
    In sostanza l'idea è che apra uno alla volta i file .csv di una certa directory, selezioni alcuni campi e crei cosi la tabella temporanea e poi vada a scrivere il contenuto di questa tabella temporanea nella tabella reale "Silente" solo se non sono già presenti.
    e quello come pensi di farlo? come è questo file csv? Con intestazioni nella prima riga? Come verifichi se i dati ci sono già oppure no?
    Ci sono troppe cose nuove che spuntano solo adesso.
    Se il file csv lo permette io creerei una tabella collegata al file di testo e ad ogni file da analizzare lavori con il relativo oggetto TableDef, in particolare con le proprietà Connect e SourceTableName e con il metodo RefreshLink (appena guardate qui , non li conosco a memoria.
    Una volta elaborato il file, poi, farei anche un'operazione di "spostamento" del file csv in una sottodirectory tipo "\fileimportati" così non ti devi nemmeno preoccupare di ricordarti di toglierli dalla successiva elaborazione.
    Vogliamo creare anche una tabella dei file importati, con nome e data di importazione così da evitare di reimportare lo stesso file se accidentalmente è ancora presente nella directory o almeno creare un avviso che chiede se si vuole procedere alla reimportazione? Anche se questo contrasta con quanto detto sopra:

    galantik ha scritto:


    poi vada a scrivere il contenuto di questa tabella temporanea nella tabella reale "Silente" solo se non sono già presenti.
    Questa non è una vendetta per

    galantik ha scritto:


    NOOOOOO CHE DELUSIONE!!!! IL MIO MENTORE!!!!!
    ovviamente ( )
  • Re: File .csv importati in una tabella tramite vba

    Alla fine ho fatto come hai suggerito tu, usando il transfertext.
    Mi rimane il dubbio del perché non funzionasse la modalità con query inglobata, ma mi sono convinto che non si possano fare query di comando basate su tabelle di transito... se mi sbaglio e qualcuno sa il contrario, per favore me lo faccia sapere.

    Il file .csv contiene la prima riga di intestazione. IL codice che ho usato è questo:
    Sub aggiorna()
    Dim dire As String, sqlstatement As String, nomefile As String
    Dim qdef As QueryDef, db As Database
    
    
    dire = CurrentProject.Path
    nomefile = Dir(dire & "\")
    
    Do While nomefile <> ""
         
            Set db = CurrentDb
            On Error Resume Next: db.TableDefs.Delete "tblImport": On Error GoTo 0
            db.TableDefs.Refresh
            
            DoCmd.TransferText transfertype:=acImportDelim, tablename:="TblImport", FileName:=nomefile, hasfieldnames:=True
            db.TableDefs.Refresh
        
            Set qdef = db.CreateQueryDef("")
            sqlstatement = ("insert into Silente SELECT * FROM TblImport;")
            qdef.SQL = sqlstatement
            qdef.Execute
    
        nomefile = Dir
    Loop
    
    End Sub
    Come vedi è la stessa soluzione che hai proposto: import in una tabella fisica tblImport e da li poi inserimento nella tabella Silente.
    Ho solo due dubbi a questo punto:
    1. la tabella, essendo un .csv, usa i punti some separazione per i decimali. Ma i decimali la mia macchina li separa con le virgole. Devo quindi convertire tutti i separatori della tabella Silente (ovviametne dopo averli importati) da punti a virgole.
    2. Come dici tu rimane il problema del confronto tra i recordset dei file csv e quelli della tabella silente. Potrei spostare i file come hai detto tu in un'altra directory e creare una tabella dei log (anzi questo lo avevo già pensato e sviluppato). Ma provando col codice sopra riportato mi sono accorto che facendo girare la macro 10 volte, non sovrascrive i record 10 volte, come mi aspettavo originariamente. Sembra che importi solo i record nuovi. E questo credo sia motivato dal fatto che c'è una chiave primaria impostata che ovviamente non può prevedere duplicazioni. Quindi il problema si è risolto da solo. Il dubbio che mi rimane è che non evidenzia alcun segnale di errore...
  • Re: File .csv importati in una tabella tramite vba

    galantik ha scritto:


    2. Come dici tu rimane il problema del confronto tra i recordset dei file csv e quelli della tabella silente. Potrei spostare i file come hai detto tu in un'altra directory e creare una tabella dei log (anzi questo lo avevo già pensato e sviluppato). Ma provando col codice sopra riportato mi sono accorto che facendo girare la macro 10 volte, non sovrascrive i record 10 volte, come mi aspettavo originariamente. Sembra che importi solo i record nuovi. E questo credo sia motivato dal fatto che c'è una chiave primaria impostata che ovviamente non può prevedere duplicazioni. Quindi il problema si è risolto da solo. Il dubbio che mi rimane è che non evidenzia alcun segnale di errore...
    Dov'è la chiave primaria, solo su Silente? oppure c'è un corrispondente campo in tblImport che va a popolare la chiave primaria di Silente? nel file csv successivi possono esserci quindi dati già presenti in csv caricati-importati in precedenza?
    Pubblica la prima riga del csv e scrivi le caratteristiche dei campi. Pure della tblImport. E spiega cosa deve passare da tblImport a Silente e in base a quali criteri deve individuare cosa accodare (o non accodare) a Silente.

    galantik ha scritto:


    Come vedi è la stessa soluzione che hai proposto: import in una tabella fisica tblImport e da li poi inserimento nella tabella Silente.
    Ho solo due dubbi a questo punto:
    1. la tabella, essendo un .csv, usa i punti some separazione per i decimali. Ma i decimali la mia macchina li separa con le virgole. Devo quindi convertire tutti i separatori della tabella Silente (ovviametne dopo averli importati) da punti a virgole.
    ce devo pensa'
Devi accedere o registrarti per scrivere nel forum
10 risposte