Leggere il valore di una cella excel da VBA MS Access

di il
16 risposte

Leggere il valore di una cella excel da VBA MS Access

Buongiorno,

sto cercando di impostare la lettura di alcune celle di un foglio excel in modo che i rispettivi valori vengano memorizzati in una tabella di MSAccess.
Le celle che sto leggendo da IlMioFile.xlsx contengono un valore in formato ORARIO (HH:MM) e anche se la routine sembra funzionare, i valori "letti" sono solo degli 1 e così vengono memorizzati nella tabella.

Il codice è il seguente:

Private Sub LeggiValori()

Dim xl As Excel.Application
Dim xlWrkBk As Excel.Workbook
Dim xlsht As Excel.Worksheet

Dim myRec As DAO.Recordset

Set xl = CreateObject("Excel.Application")
Set xlWrkBk = GetObject("D:/IlMioFile.xlsx")
Set xlsht = xlWrkBk.Worksheets(1)

Set myRec = CurrentDb.OpenRecordset("000LeggiOrari")

myRec.AddNew
myRec.Fields("OreNovembre") = xlsht.Cells(6, "I")
myRec.Fields("OreDicembre") = xlsht.Cells(7, "I")
myRec.Fields("OreGennaio") = xlsht.Cells(8, "I")
myRec.Fields("OreFebbraio") = xlsht.Cells(9, "I")
myRec.Fields("OreMarzo") = xlsht.Cells(10, "I")
myRec.Fields("OreAprile") = xlsht.Cells(11, "I")
myRec.Fields("OreMaggio") = xlsht.Cells(12, "I")
myRec.Fields("OreGiugno") = xlsht.Cells(13, "I")
myRec.Update


End Sub

Dove sto sbagliando?

Vi ringrazio in anticipo

M.

16 Risposte

  • Re: Leggere il valore di una cella excel da VBA MS Access

    Marco anche in questo forum è vietato effettuare il crossposting.

  • Re: Leggere il valore di una cella excel da VBA MS Access

    Ciao,

    1. verifica che sia le celle del foglio excel che la Fields della tabella siano dello stesso tipo Data in formato ore:minuti
      1. se sono dello stesso tipo dovrai fare semplicemente una cosa di questo tipo:
        myRec.Fields("OreGennaio") = xlsht.Cells(8, "I").Value
    2. se le celle e le fields non sono dello stesso tipo,  allora dovrai importare i dati formattandoli.
  • Re: Leggere il valore di una cella excel da VBA MS Access

    28/04/2025 - Sgrubak ha scritto:

    è vietato

    Oltre che essere un comportamento antipatico... anche se non tutti la pensano così

  • Re: Leggere il valore di una cella excel da VBA MS Access

    28/04/2025 - Marco195 ha scritto:

    Il codice è il seguente:

    Private Sub LeggiValori()
    
    Dim xl As Excel.Application
    Dim xlWrkBk As Excel.Workbook
    Dim xlsht As Excel.Worksheet
    
    Dim myRec As DAO.Recordset
    
    Set xl = CreateObject("Excel.Application")
    Set xlWrkBk = GetObject("D:/IlMioFile.xlsx")
    Set xlsht = xlWrkBk.Worksheets(1)
    
    Set myRec = CurrentDb.OpenRecordset("000LeggiOrari")
    
    myRec.AddNew
    myRec.Fields("OreNovembre") = xlsht.Cells(6, "I")
    myRec.Fields("OreDicembre") = xlsht.Cells(7, "I")
    myRec.Fields("OreGennaio") = xlsht.Cells(8, "I")
    myRec.Fields("OreFebbraio") = xlsht.Cells(9, "I")
    myRec.Fields("OreMarzo") = xlsht.Cells(10, "I")
    myRec.Fields("OreAprile") = xlsht.Cells(11, "I")
    myRec.Fields("OreMaggio") = xlsht.Cells(12, "I")
    myRec.Fields("OreGiugno") = xlsht.Cells(13, "I")
    myRec.Update
    
    
    End Sub

    Dove sto sbagliando?

    Quii invece sbagli e non di poco...

    dopo aver utilizzato degli oggetti si devono chiudere nello stesso ordine in cui sono stati aperti:
    Esempio:

    ...
    ..
    .
    ' Close obj
    xlWrkBk.Close False
    xl.Quit
    Set xlWrkBk = Nothing
    Set xl = Nothing
    Set xlsht = Nothing
    Set myRec = Nothing
    
    End Sub
    
  • Re: Leggere il valore di una cella excel da VBA MS Access

    28/04/2025 - Marco195 ha scritto:

    Dove sto sbagliando?

    In generale sbagli a fare i crossposting come ti hanno segnalato... 

    purtroppo io non l'ho visto e ti ho risposto comunque.  ;-(

  • Re: Leggere il valore di una cella excel da VBA MS Access

    28/04/2025 - oregon ha scritto:

    28/04/2025 - Sgrubak ha scritto:

    è vietato

    Oltre che essere un comportamento antipatico... anche se non tutti la pensano così

    hmmmm.... mannaggia !!! io non ci guardo mai a sto' fatto... che faccio cancello le risposte ???   :-(

  • Re: Leggere il valore di una cella excel da VBA MS Access

    Ma no... va bene lo stesso...

  • Re: Leggere il valore di una cella excel da VBA MS Access

    Prima di tutto grazie per le risposte.  Sei stato gentilissimo. Mi metto subito al lavoro.

    Vero ma mettiamola così: non accadrà pià perché, molto semplicemente, nell'altro forum non è mia intenzione mettere più piede. Ho cercato di cancellare l'account ma non vi è modo.

    [OT]
    Ci sono modi e modi per trattare chi commette un banale errore e non preme l'iconcina ed avere a che fare con cecchini a caccia di chi sbaglia, alla mia età, è cosa che non mi interessa più. Gestisco piattaforme con decine di migliaia di utenti dove si sbaglia, si posta erroneamente e si commettono errori ma non per questo si bloccano le conversazioni. I moderatori (moderare ha un significato ben preciso) dovrebbero saper fare meglio il loro lavoro.
    Tra l'altro, detto tra noi, il post che (orrore!) non avevo "chiuso" non aveva alcun bisogno di premi o coppe perché mi ero reso conto di uno sciocco refuso nel codice e mi ero auto-corretto. Ma credo di aver capito le motivazioni.
    Infine: questi forum esistono e sono una manna per chi lavora ma sono fantastici per chi come me usa questi software a livello amatoriale e lo fa per rilassarsi un po', scoprire nuove funzionalità e magari organizzare la propria discoteca o biblioteca. Essere consapevoli che non siamo in trincea sarebbe un buon inizio.
    [/ OT]

    Ancora grazie per i suggerimenti. 

  • Re: Leggere il valore di una cella excel da VBA MS Access

    28/04/2025 - oregon ha scritto:

    Ma no... va bene lo stesso...

    Grazie, scusa per la violazione del regolamento. Non accadrà più.

  • Re: Leggere il valore di una cella excel da VBA MS Access

    28/04/2025 - By65Franco ha scritto:

    myRec.Fields("OreGennaio") = xlsht.Cells(8, "I").Value

    Questa non funziona. 

    Ho controllato bene: 

    Su Access ho provato ad impostare il campo in due modi:
    1. Tipo dati: Data/ora > Formato data estesa
    2. Tipo dati: Data/ora > Formato data breve
    In entrambi i casi l'importazione adesso non restituisce nemmeno 1 o 0 ma il campo vuoto. 
    Su excel, mi posizioni sulla cella che contiene l'ora che mi serve (hh:mm), premo CTRL+1 e ho Categoria: Ora e Tipo hh:mm

    È tutto a posto ma mentre scrivevo questo post mi è venuto un dubbio e.. eureka! 

    Sembra non funzionasse perché il campo era frutto di un calcolo. 
    Se copio i valori puri in una colonna accanto l'importazione funziona perfettamente con questo codice:

    Private Sub LeggiDati()
    
    Dim xl As Excel.Application
    Dim xlWrkBk As Excel.Workbook
    Dim xlsht As Excel.Worksheet
    
    Dim myRec As DAO.Recordset
    
    Set xl = CreateObject("Excel.Application")
    Set xlWrkBk = GetObject("D:/MioFile.xlsx")
    Set xlsht = xlWrkBk.Worksheets(1)
    
    Set myRec = CurrentDb.OpenRecordset("000LeggiOrari")
    
    myRec.AddNew
    myRec.Fields("OreNovembre") = xlsht.Cells(6, "K")
    myRec.Fields("OreDicembre") = xlsht.Cells(7, "K")
    myRec.Fields("OreGennaio") = xlsht.Cells(8, "K")
    myRec.Fields("OreFebbraio") = xlsht.Cells(9, "K")
    myRec.Fields("OreMarzo") = xlsht.Cells(10, "K")
    myRec.Fields("OreAprile") = xlsht.Cells(11, "K")
    myRec.Fields("OreMaggio") = xlsht.Cells(12, "K")
    myRec.Fields("OreGiugno") = xlsht.Cells(13, "K")
    myRec.Update
    
    ' Close obj
    xlWrkBk.Close False
    xl.Quit
    Set xlWrkBk = Nothing
    Set xl = Nothing
    Set xlsht = Nothing
    Set myRec = Nothing
    
    End Sub

    La domanda a questo punto è, come si fa a copiare i dati di un campo calcolato data/ora in excel in una cella accanto in modo che la cella contenga solo il valore "puro"? 

  • Re: Leggere il valore di una cella excel da VBA MS Access

    28/04/2025 - Marco195 ha scritto:

    Ci sono modi e modi per trattare chi commette un banale errore

    Ciao, condivido i modi qualora non siano consoni e rispettosi.

    Allo stesso tempo posso capire i moderatori che hanno lo scopo di moderare facendo rispettare i modi, i regolamenti, etc... (lavoro spesso molto difficile)

    Può essere che tutti hanno un pò di ragione e un pò di torto.
    Spesso essere tolleranti è difficile.
    Spesso non si rispettano i regolamenti.
    Spesso il proprio comportamento appare lesivo e/o non rispettoso.
    Spesso per varie ragioni tra cui la fretta di dover risolvere un problema, per semplificare, etc... , porta a non rispettare i regolamenti.

    Se ci sono le regole un motivo c'è... 
    In questo caso fare crossposting, ma anche in generale, è soprattutto sintomo di poco rispetto per il lavoro degli altri. Almeno io la vedo in questo modo.

    Ma poi io per primo non vado a vedere se i regolamenti sono stati rispettati o meno e, se posso e se sono in grado, una risposta al quesito cerco di darla.
    Ammetto di essere un pò superficiale in questo, ma mi viene spontaneo mettere in ordine come prima cosa la necessità di chi ha chiesto aiuto e quindi per quanto possibile poter essere di aiuto... (un mio difetto, magari può essere chiamato "Altruismo")

    Detto questo, faccio il possibile per rispettare i regolamenti, il lavoro degli altri, dei moderatori e del forum che ci ospita. Ma spesso si può sbagliare ;-(

     Il quesito:

    Venendo alla tua richiesta vorrei in sintesi ricordarti quanto segue

    1. Il sintomo descritto riflette semplicemente l'incompatibilità tra il campo della tabella e la cella di excel che sono di fatto di due tipi diversi.
      1. Per esempio uno è di tipo testo e l'altro di tipo Data Ora:Minuti
        1. soluzione: uniformare i due tipidi dati... o impostare il campo della tabella e della cella di excel di tipo Stringa oppure di tipo Data nel formato Ora:Minuti
      2. Se il campo della tabella e di excel sono impostati come tipo Ore/Minuti:
        1. Field della Tabella = Cdate(Valore della Cella .Value)
      3. Se il campo della tabella e di tipo String e quello di excel formattato come Ore:Minuti (questo è il caso dove verrà riportato un valore numerico corrispondente all'orario)
        1. Field della Tabella = Format(Valoredella Cella .Value, "hh:nn")
      4. etc.. etc...

    ESEMPIO con la cella excel formattata di tipo Ore/Minuti ... nel caso in cui la field della tabella sia di tipo Ora:Minuti e nel caso in cui la field della tabella sia di tipo Testo :

        ' Read excel cells and table write
        Dim i As Long
        Dim cellValue As Variant
        For i = 2 To 13
            ' Retrieve cell value
            cellValue = xlsht.Cells(i, "I").Value
            ' Insert records
            With myRec
                .AddNew
                .Fields("OreGennaioTipoOreMinuti") = CDate(cellValue)
                .Fields("OreGennaioTipoString") = Format(cellValue, "hh:nn")
                .Update
            End With
        Next i
    

    .
    In sostanza devi verificare la compatibilità tra i due campi e adottare il sistema di formattazione adatto al caso specifico
    In ultimo ricordati sempre di chiudere e/o di liberare dalla memoria gli oggetti che sono stati utilizzati nella routine. (vedi come ti ho esposto nei post precedenti)
    Per esempio non chiudere gli oggetti di Excel potrebbe comportare la corruzione del file rendendolo inacessibile e/o perdendo i dati in esso contenuti.

  • Re: Leggere il valore di una cella excel da VBA MS Access

    28/04/2025 - Marco195 ha scritto:

    Su Access ho provato ad impostare il campo in due modi:
    1. Tipo dati: Data/ora > Formato data estesa
    2. Tipo dati: Data/ora > Formato data breve
    In entrambi i casi l'importazione adesso non restituisce nemmeno 1 o 0 ma il campo vuoto. 
    Su excel, mi posizioni sulla cella che contiene l'ora che mi serve (hh:mm), premo CTRL+1 e ho Categoria: Ora e Tipo hh:mm

    No !!! non è così.

    se prelevi il valore dalla cella e lo tratti come ti ho fatto vedere, non ci sono nè misteri nè dubbi... il valore frutto di un calcolo è comunque un valore e come tale viene trattato.

    In tabella le fields ore devono essere formattate in ore:minuti

    quindi se hai la field della tabella impostata come tipo Ora:Minuti
    e le celle di excel formattate come Ore:Minuti, 
    è sufficiente prelevare i valori dall'excel (anche se sono celle calcolate) e impostarli nelle Fields della tabella

            With myRec
                .AddNew
                .Fields("OreNovembre").Value = CDate(xlsht.Cells(6, "I").Value)
                .Fields("OreDicembre").Value = CDate(xlsht.Cells(7, "I").Value)
                .Fields("OreGennaio").Value = CDate(xlsht.Cells(8, "I").Value)
                .Fields("OreFebbraio").Value = CDate(xlsht.Cells(9, "I").Value)
                .Fields("OreMarzo").Value = CDate(xlsht.Cells(10, "I").Value)
                .Fields("OreAprile").Value = CDate(xlsht.Cells(11, "I").Value)
                .Fields("OreMaggio").Value = CDate(xlsht.Cells(12, "I").Value)
                .Fields("OreGiugno").Value = CDate(xlsht.Cells(13, "I").Value)
                .Update
            End With

    e non serve fare altro... molto semplice e logico. Basta rispettare le tecniche corrette e si ottiene un codice robusto e chiaro.
    Prova a provare ;-)

  • Re: Leggere il valore di una cella excel da VBA MS Access

    28/04/2025 - Marco195 ha scritto:

    • La domanda a questo punto è, come si fa a copiare i dati di un campo calcolato data/ora in excel in una cella accanto in modo che la cella contenga solo il valore "puro"? 

    Ma non si aggirano i problemi con degli escamotage... vanno semplicemente risolti come ti ho riportato sopra.

    E il codice va scritto tecnicamente bene e con una certa logica... altrimenti prima o poi avrai sempre dei risultati non voluti. ;-)

    Esempio:

    Excel: IlMioFile.xlsx

    dove la colonna "I" campo calcolato 
    con la formula '=OraStop - OraStart' con il risultato di quanti 
    ore e minuti intercorsi tra i due orari

    Tabella: TblLeggiOrari

    Risultato nella Tabella:

    Il codice:

    ' READ TIME (HH:MM) VALUES FROM EXCEL
    Private Sub MyExcelReadWriteValues()
        ' Set excel objetcs
        Dim xl As Excel.Application
        Dim xlWrkBk As Excel.Workbook
        Dim xlsht As Excel.Worksheet
        Set xl = CreateObject("Excel.Application")
        Set xlWrkBk = GetObject(CurrentProject.path & "\IlMioFile.xlsx")
        Set xlsht = xlWrkBk.Worksheets(1)
        
        ' Set dao recordset
        Dim myRec As DAO.Recordset
        Set myRec = CurrentDb.OpenRecordset("TblLeggiOrari", dbOpenDynaset, dbSeeChanges)
        
        ' Read excel cells and table write
        With myRec
            .AddNew
            .Fields("OreNovembre").Value = CDate(xlsht.Cells(6, "I").Value)
            .Fields("OreDicembre").Value = CDate(xlsht.Cells(7, "I").Value)
            .Fields("OreGennaio").Value = CDate(xlsht.Cells(8, "I").Value)
            .Fields("OreFebbraio").Value = CDate(xlsht.Cells(9, "I").Value)
            .Fields("OreMarzo").Value = CDate(xlsht.Cells(10, "I").Value)
            .Fields("OreAprile").Value = CDate(xlsht.Cells(11, "I").Value)
            .Fields("OreMaggio").Value = CDate(xlsht.Cells(12, "I").Value)
            .Fields("OreGiugno").Value = CDate(xlsht.Cells(13, "I").Value)
            .Update
        End With
        
        ' Close excel
        xlWrkBk.Close False
        xl.Quit
        Set xlWrkBk = Nothing
        Set xl = Nothing
        Set xlsht = Nothing
        ' Close recordset
        myRec.Close
        Set myRec = Nothing
    End Sub

    .
    Quindi direi niente eureka!  .... almeno per adesso  ;-)   

     28/04/2025 - Marco195 ha scritto:

    • È tutto a posto ma mentre scrivevo questo post mi è venuto un dubbio e.. eureka! 
  • Re: Leggere il valore di una cella excel da VBA MS Access

    Altro metodo e tecnica... (ma si può fare anche in altri modi)

    Se vuoi una soluzione più performante (che non apre excel con i suoi tempi etc...,)

    e con qualche controllo in più come Normalizzare e Validare i valori contenuti nelle celle di excel (nel caso in cui siano vuote o null restituiscono errore...)

    allora potresti scrivere il codice per esempio in questo modo:

    ' READ TIME (HH:MM) VALUES FROM EXCEL AND WRITE INTO TABLE MSACCESS
    Private Sub MyExcelReadWriteValuesOptimized()
        ' Set ADO objects
        Dim conn As Object, rst As Object
        Set conn = CreateObject("ADODB.Connection")
        Set rst = CreateObject("ADODB.Recordset")
        
        ' Set connection string and excel recordset open
        Dim cnnString As String, stringPathExcel As String: stringPathExcel = CurrentProject.path & "\IlMioFile.xlsx"
        cnnString = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source = " & stringPathExcel & "; Extended Properties='Excel 12.0 Xml;HDR=NO';"
        conn.Open cnnString: rst.Open "SELECT * FROM [Sheet1$I6:I13]", cnnString, adOpenKeyset, adLockReadOnly
    
        ' Create collection cells values
        Dim cellColl As New Collection
        ' Read and normalize values into collection
        Do While Not rst.EOF
            If Not IsNull(rst.Fields(0).Value) Then cellColl.Add Format(CDate(rst.Fields(0).Value), "hh:nn") Else cellColl.Add "00:00"
            ' Record next
            rst.MoveNext
        Loop
        ' Close ADO objects
        rst.Close: conn.Close: Set rst = Nothing: Set conn = Nothing
    
        ' Set sql string insert new record table
        Dim sqlString As String
        sqlString = "INSERT INTO TblLeggiOrari (OreNovembre, OreDicembre, OreGennaio, OreFebbraio, OreMarzo, OreAprile, OreMaggio, OreGiugno) " & _
                                        "VALUES (#" & cellColl(1) & "#, #" & cellColl(2) & "#, #" & cellColl(3) & "#, #" & cellColl(4) & "#, " & _
                                                "#" & cellColl(5) & "#, #" & cellColl(6) & "#, #" & cellColl(7) & "#, #" & cellColl(8) & "#)"
        ' Insert new record
        CurrentDb.Execute sqlString, dbFailOnError
    End Sub
    • Ottimizzazione tempi di accesso, apertura e lettura dei valori nelle celle del foglio excel
    • Normalizzazione e controllo dei dati da prelevare dalle celle del foglio excel (vedere celle vuote o null)
    • Ottimizzazione Insert new record nella tabella di MsAccess

    .
    Rispetto al metodo precedente vedrai che in merito alle performance non ci sono paragoni. Con questo metodo il processo è praticamente istantaneo.

    Per esempio nel mio PC il processo del primo metodo impiega dai 4 a 5 secondi
    mentre con questo metodo impiega meno di 1 secondo.

Devi accedere o registrarti per scrivere nel forum
16 risposte