Per risolvere errori VBA in Microsoft Access bisogna prima distinguere tra errori di compilazione, errori di runtime, errori logici e problemi legati a riferimenti, sicurezza o compatibilità 32/64 bit. La soluzione efficace non consiste nel nascondere il messaggio, ma nell’individuare la riga che fallisce, capire il contesto, verificare dipendenze e tipi di dati, quindi aggiungere una gestione degli errori che registri informazioni utili senza lasciare il database in uno stato incoerente.
Questa guida riguarda Access per Microsoft 365 e Access 2024 su Windows e vale in gran parte anche per Access 2021 e 2019. Access Runtime può eseguire codice VBA, ma non offre l’ambiente di sviluppo completo: per correggere e ricompilare il progetto serve normalmente la versione completa di Access. Per altre guide consulta la categoria Guide Access, la guida su come fare debug del codice VBA, quella su come usare VBA in Access e la guida su come eseguire query con VBA.
Tipi di errore VBA in Access
Il primo passaggio è classificare l’errore. Gli errori di compilazione impediscono al progetto VBA di essere compilato: esempi comuni sono Sub o Function non definita, Variabile non definita, Tipo definito dall’utente non definito, errori di sintassi, dichiarazioni API non compatibili o riferimenti a membri inesistenti. Gli errori di runtime si verificano invece durante l’esecuzione: il codice è sintatticamente valido, ma una determinata istruzione incontra una condizione che non può gestire, come un file mancante, un record bloccato, un valore Null, un oggetto non inizializzato o una query che fallisce.
Esistono poi errori logici: il codice termina senza messaggi, ma il risultato è sbagliato. Sono spesso i più insidiosi perché non generano un numero di errore. Un filtro può selezionare record non desiderati, un ciclo può saltare l’ultima riga, una data può essere interpretata con un formato inatteso o un calcolo può usare un tipo numerico non adeguato. Infine ci sono problemi ambientali: riferimenti mancanti, file spostati, driver ODBC, ActiveX, bitness 32/64, impostazioni di attendibilità o differenze tra PC.
Procedura di diagnosi passo passo
Quando compare un errore, evita di chiudere subito il messaggio. Annota numero e descrizione e scegli Debug quando disponibile. Access evidenzia la riga che ha generato l’eccezione. A quel punto osserva i valori delle variabili, verifica che gli oggetti siano impostati e controlla gli argomenti passati a funzioni o metodi. Se l’errore non è riproducibile, inserisci temporaneamente istruzioni Debug.Print nei punti critici.
- Lavora su una copia di test, non direttamente sul file produttivo multiutente.
- Apri l’editor VBA con ALT+F11.
- Dal menu Debug esegui Compila sul progetto.
- Correggi il primo errore evidenziato e ricompila fino a ottenere un progetto pulito.
- Controlla Strumenti > Riferimenti per eventuali voci MANCANTE o MISSING.
- Riproduci l’errore con un breakpoint prima della zona sospetta.
- Usa F8 per eseguire riga per riga e CTRL+G per la finestra Immediata.
- Controlla Err.Number, Err.Description e, se hai numerato le righe, Erl.
- Se il codice modifica dati, verifica transazioni, record lock e query di azione.
- Dopo la correzione, testa con dati realistici e con più utenti se l’applicazione è condivisa.
Correggere gli errori di compilazione
Compilare il progetto è una delle verifiche più importanti prima di distribuire un database. Il comando Debug > Compila rileva problemi che altrimenti emergerebbero soltanto quando l’utente attiva una determinata funzione. Se usi Option Explicit in ogni modulo, Access obbliga a dichiarare le variabili e riduce gli errori causati da refusi nei nomi. È utile attivare anche l’opzione dell’editor che richiede la dichiarazione delle variabili per i nuovi moduli.
Se scrivi accidentalmente un nome diverso da quello dichiarato, con Option Explicit la compilazione segnala subito il problema. Senza questa direttiva VBA può creare implicitamente una Variant e l’errore diventa logico anziché evidente. In database aziendali è una differenza importante: un errore bloccante durante lo sviluppo è preferibile a un calcolo sbagliato che passa inosservato in produzione.
Sub o Function non definita
Questo errore può significare che il nome è scritto male, che la procedura è Private in un modulo non accessibile, che un modulo ha lo stesso nome della funzione oppure che manca un riferimento a una libreria. Controlla prima la grafia. Se la funzione è personalizzata e deve essere richiamata da query o espressioni, dichiarala Public in un modulo standard e usa un nome che non confligga con oggetti del database.
Tipo definito dall’utente non definito
È frequente con dichiarazioni DAO.Database, DAO.Recordset, Outlook.Application o oggetti di librerie esterne. Per DAO nelle versioni moderne di Access la libreria del motore di database è normalmente disponibile, ma un riferimento danneggiato può bloccare la compilazione. Per automazione Office puoi scegliere early binding con riferimento esplicito oppure late binding con Object. Il late binding riduce alcuni problemi di versione ma rinuncia a IntelliSense e controllo dei tipi in compilazione.
Riferimenti mancanti e librerie
Un database che funziona sul PC dello sviluppatore e fallisce su un altro computer può avere un riferimento non disponibile. Nell’editor VBA apri Strumenti > Riferimenti. Se una libreria è contrassegnata come mancante, il progetto può produrre errori apparentemente scollegati, perfino su funzioni standard. Rimuovi il riferimento se non è necessario oppure installa la componente corretta e seleziona la versione disponibile.
La collection References permette anche un controllo diagnostico via codice; la documentazione Microsoft espone la proprietà IsBroken e consente di esaminare nome, percorso, GUID e versione. Non tentare di sostituire automaticamente una libreria in produzione senza sapere quale interfaccia stai cambiando. È meglio documentare le dipendenze del front-end e includerle nella procedura di distribuzione.
Gestire gli errori di runtime con On Error
La gestione strutturata degli errori in VBA usa On Error. Una procedura robusta ha un punto di uscita normale e un gestore che registra l’errore, ripristina lo stato dell’applicazione e decide se mostrare un messaggio all’utente. Evita On Error Resume Next esteso a intere procedure: può trasformare errori reali in dati incompleti o risultati silenziosamente errati.
Lo schema consigliato è: On Error GoTo GestioneErrore, codice operativo, etichetta Uscita con rilascio degli oggetti, quindi etichetta GestioneErrore che legge Err.Number e Err.Description, registra il problema e usa Resume Uscita. Se devi riprovare un’istruzione, fallo soltanto dopo avere corretto la condizione che ha causato l’errore; un Resume indiscriminato può creare cicli.
DAO Execute e dbFailOnError
Quando il codice esegue query di aggiornamento, eliminazione, accodamento o creazione tabella, non limitarti a chiamare Execute senza opzioni. La documentazione Microsoft di DAO raccomanda dbFailOnError per le query di azione: se un record interessato è bloccato e non può essere aggiornato, l’opzione genera un errore invece di lasciarti credere che l’operazione sia riuscita completamente.
Dopo l’esecuzione controlla anche RecordsAffected se il numero di righe modificate è importante. Se ti aspetti di aggiornare 500 ordini e il valore è zero, non è necessariamente un errore VBA ma è un segnale applicativo da gestire. Per query parametrizzate preferisci QueryDef con parametri espliciti invece di concatenare testo proveniente dall’utente.
Transazioni per operazioni composte
Supponi di dover aggiornare una tabella e poi inserire una riga di log. Se la prima operazione riesce e la seconda fallisce, puoi avere uno stato incoerente. Una transazione consente di confermare tutte le modifiche insieme oppure annullarle. Con DAO usa un Workspace, BeginTrans, le operazioni Execute con dbFailOnError, quindi CommitTrans; nel gestore dell’errore esegui Rollback se la transazione è attiva.
In ambiente multiutente le transazioni devono essere brevi. Una transazione lunga trattiene lock più a lungo e aumenta la probabilità di conflitti. Esegui prima i controlli che non modificano dati, poi apri la transazione soltanto per la parte necessaria. Questo migliora affidabilità e disponibilità dei record.
Debug pratico: breakpoint, F8 e finestra Immediata
L’editor VBA include strumenti sufficienti per diagnosticare la maggior parte dei problemi Access. Con F9 imposti o rimuovi un breakpoint. Con F8 esegui una riga alla volta. La finestra Immediata, richiamabile con CTRL+G, permette di interrogare variabili, eseguire istruzioni e vedere l’output di Debug.Print. Microsoft documenta la finestra Immediata come strumento per testare codice nuovo o problematico, leggere o modificare variabili durante una pausa e chiamare procedure.
La finestra Locals mostra le variabili locali della procedura corrente; Watch permette di seguire un’espressione specifica e può interrompere l’esecuzione quando una condizione diventa vera. Call Stack aiuta a capire da quale sequenza di procedure sei arrivato al punto di errore, particolarmente utile quando un evento di una maschera chiama funzioni che a loro volta richiamano altre routine.
Errori con Null e conversioni
Molti errori di runtime derivano da valori Null. Un campo Null non equivale a stringa vuota e non equivale a zero. Concatenare, convertire o assegnare un Null a una variabile tipizzata può causare problemi. In Access la funzione Nz è spesso utile, ma va usata con consapevolezza: trasformare indiscriminatamente Null in zero può cambiare il significato dei dati.
Per le conversioni usa funzioni coerenti con il tipo atteso e verifica prima il contenuto. CLng, CDbl, CDate e CCur generano errori se il valore non è convertibile. Se l’origine è una casella di testo o un file importato, controlla con IsNumeric, IsDate e con regole di validazione applicate il più vicino possibile alla sorgente. Per date e decimali considera le impostazioni locali di Windows quando trasformi stringhe in valori.
Errori negli eventi di maschere e report
Un’app Access è spesso guidata da eventi come BeforeUpdate, AfterUpdate, Current, Load, Open e Click. Un errore può sembrare casuale quando in realtà dipende dall’ordine degli eventi. Se modifichi un controllo dentro il suo stesso AfterUpdate puoi provocare ulteriore logica; se annulli un salvataggio in BeforeUpdate usa il parametro Cancel e comunica chiaramente all’utente cosa deve correggere.
Nei report alcuni eventi possono essere eseguiti durante formattazione e stampa. Non mettere logica di aggiornamento dati in eventi che possono essere richiamati più volte soltanto perché cambia l’impaginazione. Separa le regole di business dalla presentazione: una funzione che calcola o aggiorna dati dovrebbe poter essere testata indipendentemente dalla maschera o dal report che la richiama.
Compatibilità 32 bit e 64 bit
Access per Microsoft 365 e Access 2024 può essere installato a 32 o 64 bit. Il problema emerge soprattutto con dichiarazioni Windows API, controlli ActiveX e librerie esterne. Il formato ACCDB non diventa 32 o 64 bit, ma il codice che chiama componenti esterni deve essere compatibile con l’architettura del processo Access.
Per API nelle versioni moderne di VBA è spesso necessario PtrSafe e, per puntatori o handle, LongPtr. Non limitarti ad aggiungere PtrSafe a una dichiarazione vecchia: verifica la firma della funzione e quali parametri rappresentano puntatori. Se devi supportare entrambe le architetture usa compilazione condizionale con VBA7 e Win64 quando appropriato. Per controlli COM o ActiveX verifica che esista una versione compatibile con l’architettura di Office installata.
File, cartelle e percorsi
Non dare per scontato che tutti i PC abbiano la stessa lettera di unità o lo stesso percorso. In ambiente aziendale preferisci percorsi UNC quando appropriato, impostazioni configurabili e controlli espliciti prima di aprire o esportare un file. Una cartella sincronizzata, una share non disponibile o permessi NTFS insufficienti possono produrre errori diversi a seconda del punto in cui il codice fallisce.
Per applicazioni multiutente evita che il front-end condiviso venga eseguito direttamente dalla stessa cartella di rete. Microsoft raccomanda il modello split: back-end con le tabelle in posizione condivisa e copia locale del front-end per ogni utente. In questo modo riduci traffico di rete e rischio che un problema del front-end di un utente comprometta gli altri.
Sicurezza, attendibilità e codice bloccato
Se il codice non parte ma non trovi un errore VBA, controlla il Centro protezione e la barra dei messaggi. Access può disabilitare contenuto attivo in database non attendibili. La soluzione non è abilitare indiscriminatamente tutte le macro. Usa un percorso attendibile gestito, una firma digitale quando appropriato e distribuisci file da fonti controllate. Microsoft ricorda che VBA può eseguire operazioni potenti e va abilitato solo per database affidabili.
Se firmi il progetto VBA, una modifica al codice richiede una nuova firma. Per distribuzioni stabili valuta anche ACCDE: impedisce all’utente di modificare il codice sorgente VBA e la progettazione degli oggetti compilati, ma non sostituisce la sicurezza del back-end, i permessi di rete o la crittografia dei dati.
Access Runtime e gestione degli errori
Access Runtime è pensato per eseguire applicazioni su PC che non dispongono della versione completa. L’interfaccia di sviluppo è limitata e l’utente finale non dovrebbe dover fare debug. Per questo una soluzione distribuita con Runtime deve avere una gestione degli errori più accurata: messaggi comprensibili, log tecnico con procedura, numero errore, timestamp, utente e versione del front-end.
Una tabella LogErrori può contenere ID, DataOra, UtenteWindows, Procedura, NumeroErrore, Descrizione, VersioneApp e Contesto. Il gestore può inserire una riga evitando però che un eventuale errore nel logger generi una cascata infinita. In una routine di logging può avere senso un On Error Resume Next molto circoscritto; nelle procedure operative mantieni invece la gestione esplicita.
Query con parametri non riconosciuti
Se VBA apre una query che funziona dall’interfaccia ma produce un errore relativo ai parametri, spesso la query contiene riferimenti a controlli di maschere o nomi di campo non riconosciuti. DAO non risolve automaticamente ogni riferimento dell’interfaccia nello stesso modo. Crea un QueryDef, assegna esplicitamente i parametri e poi eseguilo. Per query SELECT apri un Recordset; per query di azione usa Execute con dbFailOnError.
Un errore frequente è costruire SQL concatenando testo senza gestire apostrofi, date o Null. Durante il debug stampa la stringa SQL completa nella finestra Immediata e incollala in una nuova query. Se il testo contiene un apostrofo, come in un cognome, va correttamente gestito; per logiche complesse i parametri sono più leggibili e sicuri.
Errori multiutente e record lock
In un database condiviso due utenti possono modificare lo stesso record. Con blocco ottimistico Access permette l’editing contemporaneo e avvisa il secondo utente al salvataggio se il record è cambiato. Non trattare ogni conflitto come un guasto: è una condizione prevista in concorrenza. Progetta maschere con RecordLocks adeguato e messaggi che aiutino l’utente a ricaricare il record.
Per operazioni batch non tenere Recordset editabili aperti più del necessario. Chiudi gli oggetti DAO. Se il back-end è su rete, controlla latenza, stabilità e permessi sulla cartella; Access deve poter gestire il file di lock associato. Problemi di connettività intermittente sono particolarmente rischiosi per database file-based.
Errori logici e test
Per scoprire un errore logico devi definire risultati attesi. Crea dati di test con casi normali, limiti, Null, stringhe vuote, date a fine mese, valori negativi e record duplicati. In fase di sviluppo puoi usare Debug.Assert per fermare il codice quando una condizione che consideri sempre vera diventa falsa. L’oggetto Debug supporta Print e Assert.
Non lasciare che il test manuale copra soltanto il percorso ideale. Gran parte dei bug reali emerge sui casi marginali o quando l’utente esegue azioni in un ordine diverso da quello previsto. Per procedure che modificano dati crea una copia del back-end con dataset realistico e ripeti lo stesso scenario dopo ogni correzione importante.
Checklist prima della distribuzione
- Compila l’intero progetto VBA senza errori.
- Verifica che non esistano riferimenti mancanti.
- Controlla Option Explicit nei moduli.
- Testa 32 e 64 bit se entrambe le architetture sono previste.
- Testa con un account Windows standard, non soltanto amministratore.
- Verifica percorsi di rete e permessi.
- Simula file mancanti e destinazioni non raggiungibili.
- Usa dbFailOnError nelle query di azione.
- Prova i flussi con più utenti se il database è condiviso.
- Testa Access Runtime su una macchina pulita se lo distribuisci.
- Registra numero e descrizione degli errori importanti.
- Assegna una versione al front-end per identificare la build installata.
Errori comuni e rimedi
Errore 91: variabile oggetto non impostata
Hai dichiarato un oggetto ma non lo hai assegnato con Set, oppure l’oggetto è diventato Nothing. Verifica la riga di inizializzazione e il ciclo di vita dell’oggetto. Se la funzione può restituire Nothing, controllalo esplicitamente prima di usare proprietà o metodi.
Uso non valido di Null
Stai assegnando Null a un tipo che non lo accetta o passando Null a una funzione. Controlla IsNull e usa Nz solo se la sostituzione con zero o stringa vuota ha senso nel dominio dei dati.
Errori di sintassi SQL
Stampa la stringa SQL nella finestra Immediata e provala come query. Controlla apostrofi nei testi, delimitatori delle date, parentesi, parole riservate e nomi di campo con spazi. Se possibile passa a QueryDef parametrizzati.
Codice che funziona in Access completo ma non in Runtime
Non dipendere da comandi di progettazione o dall’editor VBA. Gestisci errori e navigazione interamente nell’applicazione, crea una maschera iniziale, nascondi le dipendenze dagli strumenti di sviluppo e prova la build con Runtime reale.
FAQ
Conviene usare On Error Resume Next?
Solo in blocchi molto piccoli nei quali prevedi esplicitamente un errore e controlli subito Err.Number. Usarlo per intere procedure rende il debug difficile e può nascondere perdita o mancato aggiornamento di dati.
Come sapere la riga esatta dell’errore?
Durante lo sviluppo usa Debug e breakpoint. Per log in produzione puoi numerare le righe significative e leggere Erl nel gestore; Erl restituisce il numero dell’ultima etichetta numerica raggiunta.
Devo compilare prima di creare un ACCDE?
Sì. Correggi gli errori di compilazione e verifica i riferimenti prima di creare il file distribuito. Un progetto non compilabile non è una build pronta per gli utenti.
Access Runtime esegue VBA?
Sì, il Runtime può eseguire il codice dell’applicazione, ma non è l’ambiente adatto per modificarlo e fare debug. Progetta quindi log e messaggi di errore pensando all’utente finale.
Un errore VBA può dipendere da Windows?
Sì. API, driver, ActiveX, permessi file, percorsi, stampanti e architettura 32/64 bit sono dipendenze esterne al database. Se il problema compare su un solo PC confronta ambiente e componenti installati.
Come distinguere un bug da un record lock?
Riproduci il problema con un solo utente. Controlla il messaggio Access, la proprietà RecordLocks, la durata delle transazioni e quali record vengono modificati contemporaneamente. Un conflitto di scrittura può essere un comportamento normale in concorrenza.
Conclusione
Risolvere gli errori VBA in Microsoft Access richiede un metodo ripetibile: compila, controlla i riferimenti, riproduci l’errore, usa breakpoint e finestra Immediata, verifica tipi e Null, gestisci le eccezioni con On Error e proteggi le modifiche ai dati con dbFailOnError e transazioni quando servono. In ambiente multiutente aggiungi test di concorrenza e distribuisci un front-end locale per ciascun utente. Con Access Runtime il logging è essenziale perché l’utente non dispone degli stessi strumenti di sviluppo.
Per approfondire consulta la documentazione Microsoft sulla finestra Immediata VBA, sugli strumenti di debug e sul metodo DAO QueryDef.Execute. Mantieni sempre un backup prima di correggere codice che modifica dati o struttura del database.