Qual è il numero che decide come migrare da Access?
Sopra il 60 per cento basta spostare i dati su SQL Server; fra il 30 e il 60 per cento si procede a gradini; sotto il 30 per cento il problema è il processo. In un'azienda di serramenti di 35 persone, al 27 per cento, la strada a gradini costava circa 24.900 euro in tre anni, contro 52.400 euro di non fare niente.

Il gestionale di un'azienda di serramenti su misura, 35 persone, vive in un file Access nato nel 2012. Lo ha scritto un geometra appassionato di informatica, che oggi lavora altrove e risponde al telefono quando ha tempo. Tre volte l'anno il file si corrompe, per mezza giornata nessuno emette un preventivo, e a ogni ripristino qualcuno perde le modifiche dell'ultima ora.
La domanda arriva in azienda con un preventivo da 30.000 euro per "rifare tutto". Il titolare chiede se serve davvero. La risposta onesta è che dipende da un numero che quasi nessuno ha misurato, e che in questo caso porta a una strada da circa 25.000 euro in tre anni, non da 52.000.
Questo articolo ti dice quando una migrazione da Access è necessaria e quando è solo una spesa, quanto costa ognuna delle strade, in quale ordine si fanno le cose e quali scelte (i tipi di dato prima di tutte) fanno la differenza fra un fine settimana tranquillo e tre mesi di problemi.
Troverai il conto di quanto costa tenere Access com'è, il numero che decide la strada, il confronto fra cinque opzioni con i costi in euro, il codice C# per fare l'inventario e per spostare i dati, la tabella di conversione dei tipi, il piano di passaggio in novanta giorni e gli errori che vedo più spesso.
Una premessa. Dal 1999 progetto software per aziende, quasi sempre in .NET, e ho incontrato decine di applicazioni Access che reggevano un'azienda intera. Alcune vanno tenute, altre vanno sostituite, quasi nessuna va buttata in blocco. Non ti devo vendere una riscrittura: te la consiglio solo quando i numeri la chiedono.
Il caso che uso in tutto l'articolo è un'azienda tipo, costruita con ordini di grandezza e medie di settore. Non è un cliente, è un metodo: lo rifai con i tuoi numeri in un pomeriggio.
Perché Access è ancora ovunque, e quando smette di reggere?
Access è ovunque perché fa una cosa che nessun altro strumento faceva così in fretta: in due settimane una persona sveglia, senza programmatori, costruisce un'applicazione con database, maschere, report e un po' di automazione. Costa quasi niente, sta già nella licenza di Office e risolve il problema di oggi.
Il guaio è che il problema di oggi diventa il processo di domani. Il file cresce, gli utenti passano da due a quattordici, qualcuno vuole aprirlo da casa, e quello che era un quaderno diventa il sistema nervoso dell'azienda.
I limiti che contano davvero sono sei.
- Due gigabyte per file. È un tetto tecnico del formato. Quando ci arrivi, il file smette di accettare dati. Si aggira dividendo in più file, e così si moltiplicano i problemi.
- Il database è un file condiviso. Ogni utente apre lo stesso file su una cartella di rete. Se la rete cade a metà di una scrittura, il file si danneggia. Non è sfortuna: è come funziona.
- Pochi utenti contemporanei. Il numero dichiarato è alto, quello che regge nella pratica è di 10-20 persone, e scende molto se qualcuno lavora in VPN o via Wi-Fi.
- Nessuna vera sicurezza sui dati. Dal formato 2007 Access non ha più la sicurezza a livello di utente. Chi apre il file vede tutto, e chi ha le maschere può leggere le tabelle.
- Nessuna versione web. Le maschere funzionano solo su Windows con Office. Niente tablet, niente browser, niente accesso del commercialista o dell'agente senza installare qualcosa.
- Una persona sola che lo capisce. Il codice VBA e le query sono scritti a mano da chi li ha fatti, senza test e senza documentazione. Quando quella persona se ne va, il sistema diventa una scatola chiusa.
C'è poi una questione di calendario. Secondo il calendario Microsoft, le versioni di Office vendute con licenza perpetua escono dal supporto una dopo l'altra: la 2016 e la 2019 sono scadute a ottobre 2025, la 2021 il 13 ottobre 2026, cioè pochi giorni fa. Access come prodotto non sparisce, perché resta in Microsoft 365, ma chi lo usa su una versione fuori supporto smette di ricevere correzioni di sicurezza.
Detto questo, un'avvertenza che ripeto spesso: Access non è "sbagliato". È uno strumento per pochi utenti e processi semplici, usato oltre il suo scopo. La domanda utile non è "Access è vecchio?", ma "che cosa mi costa, ogni anno, il fatto che sia Access?".
Com'è fatta l'azienda tipo e da quali numeri parte?
L'azienda tipo produce serramenti su misura per privati e imprese edili. Ha 35 persone, 14 delle quali lavorano ogni giorno sul gestionale: commerciale, ufficio tecnico, produzione, magazzino e amministrazione. Il gestionale è un'applicazione Access divisa in due file, come si fa quando si è fatto bene: uno con le maschere (il "front-end") su ogni computer, uno con le tabelle (il "back-end") su un server.
Ecco i numeri, quelli che rilevi in mezza giornata con un inventario e qualche domanda alle persone.
| Misura | Valore | Come si rileva |
|---|---|---|
| Utenti attivi | 14, di cui 3 in VPN | Elenco delle persone che aprono il file ogni giorno |
| Dimensione del file dati | 1,4 GB su 2 di limite | Proprietà del file, dopo una compattazione |
| Tabelle | 112 | Inventario (il codice è più sotto) |
| Maschere e report | 74 maschere, 58 report | Elenco degli oggetti del front-end |
| Codice VBA | circa 11.000 righe | Esportazione dei moduli |
| Fermi per file danneggiato | 3 l'anno, circa 4 ore ciascuno, 14 persone coinvolte | Memoria delle persone e registro delle chiamate al consulente |
| Lavoro fatto fuori da Access, in Excel | circa 6 ore alla settimana in totale, 3 persone | Chiedere "che cosa fai nel foglio dopo aver stampato?" |
| Consulente a chiamata | 6 ore al mese a 70 euro | Fatture dell'ultimo anno |
| Costo orario di una persona in azienda | 28 euro | Costo del lavoro diviso per le ore lavorate |
| Costo di una giornata di sviluppo | 480 euro | Tariffa di riferimento |
Due note sui numeri. La prima: la riga che quasi tutti dimenticano è quella del lavoro in Excel. Quando le persone dicono "il gestionale fa tutto", di solito vuol dire che fa tutto tranne la parte difficile, che si risolve a mano con un foglio di calcolo allegato a un'email.
La seconda: un file da 1,4 GB su 2 non è "lontano dal limite". Un archivio che cresce di 150 MB all'anno ci arriva in quattro anni, ma i problemi di prestazioni e di danneggiamento cominciano molto prima, già oltre il 70 per cento.
Quanto costa tenere Access com'è?

Tenere un sistema non è gratis: il costo c'è, ma sta in voci che nessuno mette in fattura. Per l'azienda tipo sono tre.
- I fermi. Tre volte l'anno, 14 persone ferme circa 4 ore: 3 per 14 per 4 per 28 euro fanno 4.704 euro. Non c'è dentro il ritardo sulle consegne né il cliente che cambia fornitore.
- Il lavoro fuori da Access. Sei ore alla settimana per 46 settimane sono 276 ore: a 28 euro fanno 7.728 euro. Sono le persone che copiano dati da una maschera a un foglio, ricalcolano un prezzo con le varianti e rimettono il risultato in un'altra maschera.
- Il consulente. Sei ore al mese a 70 euro fanno 420 euro, cioè 5.040 euro l'anno per tenere in piedi quello che c'è, senza aggiungere niente.
Il totale è 17.472 euro l'anno, circa 52.400 euro in tre anni. È il prezzo di non decidere, ed è la cifra con cui devi confrontare qualsiasi preventivo di migrazione. Un preventivo da 30.000 euro che elimina tutto il problema è conveniente. Uno da 30.000 euro che ne elimina un terzo, no.
Restano fuori, di proposito, le voci più pesanti e più difficili da stimare.
- Il rischio di perdere i dati: un backup che non è mai stato provato a ripristinare vale zero.
- Il rischio della persona sola: se il consulente smette, il costo non è 5.040 euro, è il blocco dell'azienda per settimane.
- L'impossibilità di fare quello che serve: portale clienti, app per i posatori in cantiere, integrazione con il fornitore dei profili. Con Access non si fa, e nessuno lo mette a bilancio perché non lo chiede più.
Se vuoi un solo esercizio da fare oggi, prendi un foglio, scrivi queste tre voci con i tuoi numeri e sommale. Tre telefonate e un'ora di lavoro.
Qual è il numero che decide che strada prendere?

Le persone si dividono in due partiti. Quelli che dicono "Access è il problema, buttiamolo". E quelli che dicono "funziona, perché cambiare". Hanno ragione e torto entrambi, perché mescolano due problemi diversi.
Il primo problema è il contenitore: il file condiviso, il limite dei 2 GB, la corruzione, l'assenza di backup serio, l'impossibilità di lavorare da fuori. Si risolve spostando i dati su un vero database, e costa poco.
Il secondo problema è il processo: il modo in cui l'azienda lavora, con regole che il programma non conosce e che le persone applicano a mano. Non si risolve spostando i dati. Si risolve scrivendo quelle regole nel software, e costa di più.
Il numero che decide è la quota del costo annuo che dipende dal contenitore. Nell'azienda tipo i fermi per file danneggiato valgono 4.704 euro su 17.472, cioè il 27 per cento. Il resto, il lavoro in Excel e il consulente, dipende dal processo e dalla persona sola.
La regola che uso:
- Sopra il 60 per cento: il problema è il contenitore. Sposta le tabelle su SQL Server o Azure SQL, lascia le maschere di Access, e hai risolto la maggior parte di quello che ti costa. Circa 3.840 euro.
- Fra il 30 e il 60 per cento: serve una strada a gradini. Prima i dati, poi i pezzi di processo che costano di più, uno alla volta.
- Sotto il 30 per cento: il contenitore è un dettaglio. Spostare i dati non cambia il conto. Il lavoro è ricostruire il processo, e ha senso valutare anche un sistema nuovo.
L'azienda tipo è al 27 per cento, quindi sul bordo fra "a gradini" e "ricostruire". La conclusione non è quella che si aspettavano né i fautori della riscrittura né quelli del "lasciamolo com'è": il contenitore va sistemato subito perché è poco costoso e toglie i fermi, ma da solo non basta. Il valore sta nel pezzo che oggi si fa in Excel.
Un controllo in più, che prende venti minuti. Elenca le dieci cose che le persone fanno con Access e segna per ciascuna una lettera: C se il problema è il file (lentezza, blocchi, accesso da fuori), P se il problema è la regola (calcolo, controllo, passaggio fra reparti), S se il problema è che solo una persona sa come funziona. Se hai più P e S che C, sai già dove spenderai.
Quali strade esistono, e quanto costano in tre anni?

Le strade sono cinque, più quella di non fare niente. I prezzi sono ordini di grandezza che ho sotto mano, da verificare con un preventivo. Il conto è sempre lo stesso: costo di passaggio, canoni per tre anni, e il costo di quello che resta come prima.
| Strada | Che cosa si fa | Costo di passaggio | Canoni e gestione in 3 anni | Costo che resta in 3 anni | Totale in 3 anni |
|---|---|---|---|---|---|
| A. Tenere com'è | Niente | 0 | consulente 15.120 | fermi 14.112 + Excel 23.184 | circa 52.400 |
| B. Solo i dati su SQL | Tabelle su Azure SQL, maschere Access collegate | 3.840 (8 giornate) | hosting 151 + consulente ridotto 5.040 | fermi 4.704 + Excel 23.184 | circa 36.900 |
| C. Pacchetto pronto | Gestionale di mercato, import dei dati | 5.760 (12 giornate) | licenze 19.152 | Excel 11.592 (le varianti restano a mano) | circa 36.500 |
| D. Power Apps e Dataverse | Applicazione low-code sui dati | 12.000 (25 giornate) | licenze 10.080 + consulente ridotto 5.040 | Excel 5.796 | circa 32.900 |
| E. Riscrittura completa | Applicazione web su misura, tutto insieme | 29.760 (62 giornate) | hosting 900 + manutenzione 8.640 | 0 | circa 39.300 |
| F. A gradini | Dati su SQL, poi un modulo web per il processo più costoso | 12.480 (26 giornate) | hosting 360 + consulente ridotto 5.040 | fermi 4.704 + Excel 2.318 | circa 24.900 |
Come leggere la tabella. La strada più economica in tre anni è la F, la più cara a parità di risultato è la E, e la A è quella che sembra gratis e costa di più di tutte.
Perché la F batte la E, che sulla carta risolve tutto? Per due ragioni. La prima: nella E paghi in anticipo 62 giornate di lavoro per riscrivere anche le 40 maschere che nessuno usa più di una volta al mese. La seconda: nella E non ottieni niente per sei-otto mesi, mentre nella F il primo risultato (niente più fermi) arriva dopo tre settimane.
Perché la F batte la C, il pacchetto? Perché il pacchetto elimina i fermi e il consulente, ma le varianti dei serramenti, che sono la ragione per cui l'azienda ha un gestionale proprio, restano a mano in Excel. Se la tua azienda fa cose in modo standard (contabilità, magazzino semplice, fatturazione), il pacchetto vince, ed è giusto che vinca.
E la D, Power Apps? Ha senso quando le persone sono già dentro Microsoft 365 e il processo è un modulo con un flusso. Si rompe quando le regole di calcolo diventano complesse, perché le formule low-code non si testano e non si leggono come il codice. In un'azienda con preventivi a varianti, io la userei per i moduli accessori, non per il cuore.
Tre avvertenze sui conti.
- Le licenze del pacchetto e di Power Apps cambiano spesso: i 38 e i 20 euro per utente al mese che ho usato sono ordini di grandezza, non un listino.
- Nella E non ho messo il costo di avviamento dei nuovi processi, né la formazione. Sono reali in tutte le strade e crescono con il cambiamento.
- I fermi della B e della F non sono zero ma uno all'anno: lasciare le maschere in Access su un computer vecchio e un portatile in VPN produce ancora qualche problema, molto meno grave perché i dati non sono più nel file.
Come si fa l'inventario di quello che c'è dentro Access?
Prima di scegliere una strada, e prima di chiedere un preventivo, serve un inventario. Un preventivo senza inventario è una scommessa: chi lo fa o si copre con un margine enorme, o sottovaluta e ti presenta il conto a metà lavoro.
L'inventario risponde a sei domande: quali tabelle ci sono e quanto pesano, quali hanno una chiave primaria, quali campi di tipo problematico contengono (allegati, campi a valori multipli, collegamenti ipertestuali), quali query sono in uso davvero, quanto codice VBA c'è e dove, e chi usa cosa.
Per le tabelle si può partire da un piccolo programma in C#. Legge il file con il provider OLE DB di Access e stampa nome, numero di righe e colonne di ogni tabella. Serve il motore di database di Access installato sulla macchina, nella stessa architettura (64 bit con 64 bit) del programma.
using System.Data;
using System.Data.OleDb;
var percorso = args[0];
var connessione = $"Provider=Microsoft.ACE.OLEDB.16.0;Data Source={percorso};Mode=Read";
using var db = new OleDbConnection(connessione);
db.Open();
var tabelle = db.GetSchema("Tables", new[] { null, null, null, "TABLE" });
foreach (DataRow riga in tabelle.Rows)
{
var nome = (string)riga["TABLE_NAME"];
if (nome.StartsWith("MSys", StringComparison.OrdinalIgnoreCase)) continue;
using var conta = new OleDbCommand($"SELECT COUNT(*) FROM [{nome}]", db);
var righe = Convert.ToInt64(conta.ExecuteScalar());
var colonne = db.GetSchema("Columns", new[] { null, null, nome, null });
var tipiDifficili = colonne.Rows.Cast<DataRow>()
.Count(c => (int)c["DATA_TYPE"] is 130 or 128 or 205);
Console.WriteLine($"{nome};{righe};{colonne.Rows.Count};{tipiDifficili}");
}L'output è un elenco separato da punto e virgola che apri in Excel. Ordinalo per numero di righe: le prime dieci tabelle sono quasi sempre il 95 per cento dei dati, e sono quelle su cui provare per prime la migrazione.
Il programma apre il file in sola lettura, quindi si può lanciare su una copia senza rischio. Lo ripeto perché è il primo passo di tutto: si lavora sempre su una copia, mai sul file in uso.
Per il codice VBA conta una sola cosa, all'inizio: la quantità e dove si concentra. Esporta i moduli (in Access c'è il comando di esportazione nell'editor del codice) e conta le righe per modulo. Nell'azienda tipo le 11.000 righe si dividono così:
| Tipo di codice | Righe | Che cosa fa | Dove va a finire |
|---|---|---|---|
| Apertura e chiusura maschere, messaggi | circa 3.200 | Navigazione, avvisi, valori di default | Resta in Access, o sparisce con le maschere nuove |
| Calcoli di prezzo e varianti | circa 2.600 | Il cuore: misure, sconti, maggiorazioni, listini per cliente | Diventa codice C# testato, e si riscrive per primo |
| Stampe e esportazioni (PDF, Excel, email) | circa 2.100 | Preventivi, ordini, etichette | Modelli nuovi, spesso più semplici |
| Controlli e regole di coerenza | circa 1.700 | "Non si può confermare l'ordine senza data di consegna" | Vincoli del database e codice C# |
| Codice morto | circa 1.400 | Funzioni mai chiamate, vecchie prove | Si elimina |
Il dato che conta è la seconda riga: 2.600 righe su 11.000 contengono il valore dell'azienda. Il 24 per cento del codice fa il 90 per cento del lavoro che interessa. Gli altri tre quarti si spostano, si semplificano o si buttano.
Come si spostano i dati su SQL Server senza perderli?
Questo è il passo che costa meno e rende di più, ed è quello che molti saltano per andare dritti alla riscrittura. Si chiama in gergo "upsizing": le tabelle escono dal file e vanno in un vero database, mentre le maschere restano quelle di prima, collegate al database nuovo.
Nella pratica il database di destinazione è Azure SQL o un SQL Server in azienda. Per i 1,4 GB dell'azienda tipo basta il livello Basic di Azure SQL, che costa circa 4,20 euro al mese e arriva a 2 GB. Quando i dati crescono si passa a un livello superiore senza cambiare il programma.
Il lavoro vero non è copiare le righe. È tradurre i tipi di dato, perché Access e SQL Server non parlano la stessa lingua. Ecco la tabella di conversione che uso.
| Tipo in Access | Tipo in SQL Server | La trappola |
|---|---|---|
| Testo breve | nvarchar(n), con la stessa lunghezza | Non lasciare nvarchar(max) ovunque: rallenta gli indici |
| Testo lungo (Memo) | nvarchar(max) | Nei Memo con cronologia (campi "Aggiungi solo") lo storico non si porta dietro |
| Numerico intero | smallint o int | Il "Numerico lungo" è un int, non un bigint |
| Numerico con virgola | decimal(p,s), mai float | Float sui prezzi dà centesimi che spariscono |
| Valuta | decimal(19,4) | Access arrotonda in un modo, SQL in un altro: confronta i totali |
| Data/ora | datetime2, o date se manca l'ora | Le date vuote di Access sono NULL, quelle sbagliate (30/12/1899) sono ore senza data |
| Sì/No | bit NOT NULL DEFAULT 0 | Un Sì/No con NULL fa comparire "#Eliminato" nelle maschere |
| Contatore (AutoNumber) | int IDENTITY | Dopo il caricamento va riallineato il contatore, altrimenti i nuovi record sbattono sui vecchi |
| Allegato | Tabella separata con varbinary(max), o meglio file su archivio | Non esiste un equivalente diretto: va deciso a mano |
| Campo a valori multipli | Tabella di collegamento | Si "vede" come un campo ma sono due tabelle: da riscrivere |
| Collegamento ipertestuale | nvarchar(2000) | Access salva il testo e l'indirizzo separati da un cancelletto |
Due regole ripagano il tempo speso a impararle.
La prima: ogni tabella deve avere una chiave primaria e una colonna di versione. Access, collegato a SQL Server, ha bisogno di una colonna rowversion per capire se un record è stato cambiato da qualcun altro. Senza, le modifiche in contemporanea danno errori strani, o peggio sovrascrivono.
CREATE TABLE dbo.Ordine
(
OrdineId int IDENTITY(1,1) NOT NULL CONSTRAINT PK_Ordine PRIMARY KEY,
ClienteId int NOT NULL,
DataOrdine date NOT NULL,
Confermato bit NOT NULL CONSTRAINT DF_Ordine_Confermato DEFAULT 0,
Totale decimal(19,4) NOT NULL,
Note nvarchar(max) NULL,
VersioneRiga rowversion NOT NULL
);La seconda: i totali si confrontano prima e dopo, tabella per tabella. Non basta contare le righe. Si sommano i campi numerici e si confrontano le due somme, altrimenti un arrotondamento diverso passa inosservato per sei mesi.
Per spostare i dati si può usare lo strumento di importazione di SQL Server, ma sulle tabelle grandi preferisco un caricamento controllato da programma, perché mi lascia scrivere il confronto nello stesso passaggio. Ecco il cuore, con SqlBulkCopy.
using System.Data;
using System.Data.OleDb;
using Microsoft.Data.SqlClient;
static async Task CopiaTabellaAsync(
string percorsoAccess, string connessioneSql, string tabella)
{
var origine = $"Provider=Microsoft.ACE.OLEDB.16.0;Data Source={percorsoAccess};Mode=Read";
await using var sql = new SqlConnection(connessioneSql);
await sql.OpenAsync();
using var access = new OleDbConnection(origine);
access.Open();
// le colonne si elencano, anche in un programma di passaggio
using var schema = access.GetSchema("Columns", new[] { null, null, tabella, null });
var elenco = string.Join(", ", schema.Rows.Cast<DataRow>()
.OrderBy(c => (long)c["ORDINAL_POSITION"])
.Select(c => $"[{c["COLUMN_NAME"]}]"));
using var comando = new OleDbCommand($"SELECT {elenco} FROM [{tabella}]", access);
using var lettore = comando.ExecuteReader();
using var copia = new SqlBulkCopy(sql)
{
DestinationTableName = $"dbo.{tabella}",
BatchSize = 5000,
BulkCopyTimeout = 600,
EnableStreaming = true
};
// le colonne si mappano per nome, così l'ordine dei campi non conta
for (var i = 0; i < lettore.FieldCount; i++)
copia.ColumnMappings.Add(lettore.GetName(i), lettore.GetName(i));
await copia.WriteToServerAsync(lettore);
}Dopo la copia, il confronto dei totali:
SELECT COUNT(*) AS Righe,
SUM(Totale) AS SommaTotale,
MIN(DataOrdine) AS PrimaData,
MAX(DataOrdine) AS UltimaData
FROM dbo.Ordine;La stessa interrogazione si lancia in Access sulla tabella originale. Se i quattro valori coincidono, passi alla tabella dopo. Se uno no, ti fermi e capisci perché: quasi sempre è una data a 1899, un NULL nei Sì/No o un arrotondamento.
Poi si collegano le tabelle a Access con un driver ODBC, e le maschere, che puntano ai nomi di prima, continuano a funzionare. Ci sono cinque cose da controllare sulle maschere: le query che usano funzioni di VBA dentro la clausola WHERE (diventano lentissime perché portano tutti i dati sul computer), le maschere con sottomaschere su tabelle grandi, i campi calcolati, i filtri sulle date e le tabelle temporanee create al volo.
Il risultato dopo il passo: il file con le maschere pesa pochi MB, le tabelle sono su un server con backup automatici e ripristino a un istante preciso, e i fermi per file danneggiato scendono quasi a zero. Per l'azienda tipo il passo costa 8 giornate: tre per l'inventario e la progettazione, due per la conversione, due per le maschere lente, una per il confronto e il passaggio.
Come si porta fuori da Access la logica che vale?

Una volta che i dati sono su SQL, la logica si può spostare a pezzi. Questa è la parte che di solito si fa male: si prende un'applicazione che funziona e la si ricostruisce tutta insieme, con un "lancio" fra otto mesi. Lo chiamo il progetto che non finisce, perché nel frattempo il vecchio sistema cambia e il nuovo deve inseguirlo.
La strada che funziona è un'altra, e si chiama in gergo strangler, "strangolatore": il nuovo pezzo cresce accanto al vecchio e lo sostituisce una funzione alla volta, finché il vecchio non serve più o si spegne da solo. Il vecchio sistema continua a lavorare per tutto il tempo.
Si procede con tre regole.
- Si sceglie il pezzo che costa di più, non quello più facile. Nell'azienda tipo è il preventivo con le varianti, perché è lì che finiscono le 276 ore l'anno di Excel. Le anagrafiche, che sono facili, possono restare in Access per altri tre anni.
- Il pezzo nuovo parla con lo stesso database. Per questo il primo gradino sono i dati su SQL: le maschere vecchie e il modulo nuovo leggono le stesse tabelle, quindi non c'è nessuna sincronizzazione da inventare.
- La regola di calcolo si scrive una volta, con i test. Prima di riscrivere le 2.600 righe dei prezzi, si raccolgono 150 preventivi reali, con il totale che l'azienda ha confermato al cliente, e si usano come prova: il codice nuovo deve restituire gli stessi totali al centesimo.
L'ultima regola è quella che cambia tutto. Un calcolo di prezzo in VBA sta dentro una maschera, non si può provare da solo e nessuno sa che cosa succede quando si cambia una riga. Se lo scrivi in C# come funzione pura, lo provi in un secondo contro i 150 casi.
public sealed record RigaPreventivo(
decimal LarghezzaMm, decimal AltezzaMm, string Profilo, string Vetro, int Quantita);
public sealed class CalcolatorePreventivo(IListino listino)
{
public decimal Calcola(RigaPreventivo riga, decimal scontoCliente)
{
var metriQuadri = riga.LarghezzaMm * riga.AltezzaMm / 1_000_000m;
// il listino fissa un minimo fatturabile: sotto 0,5 mq si paga 0,5 mq
var fatturabili = Math.Max(metriQuadri, 0.5m);
var prezzoBase = fatturabili * listino.PrezzoMetroQuadro(riga.Profilo);
var vetro = fatturabili * listino.PrezzoVetro(riga.Vetro);
var lordo = (prezzoBase + vetro) * riga.Quantita;
return Math.Round(lordo * (1 - scontoCliente), 2, MidpointRounding.AwayFromZero);
}
}Due dettagli che valgono tempo. L'uso di decimal e non di double: sui soldi la differenza si vede al centesimo. E l'arrotondamento esplicito: Access arrotonda il valore .5 al pari più vicino, C# di default fa lo stesso, e l'azienda aveva da sempre arrotondato per eccesso. Una differenza così si scopre solo con i casi di prova: in un archivio di 150 preventivi ne fa saltare una manciata, e senza quel confronto la trovi dal cliente.
Il modulo nuovo non deve essere un'opera d'arte. Per un'azienda di queste dimensioni basta un'applicazione web (ASP.NET Core con Blazor, o semplici pagine Razor) con accesso tramite il login aziendale, ospitata su Azure con scalatura a zero, a un costo di circa 10 euro al mese con il database incluso. Le maschere nuove si progettano con le persone che le useranno, guardando come lavorano, non copiando quelle vecchie.
Il costo del secondo gradino per l'azienda tipo è di 18 giornate, cioè 8.640 euro: 4 per la raccolta dei casi e il calcolo, 8 per le pagine, 3 per le stampe del preventivo, 3 per il passaggio con le persone. Sommato alle 8 del primo gradino, sono le 26 giornate della strada F, 12.480 euro.
Che cosa cambia per sicurezza, permessi e backup?
Qui il vantaggio rispetto ad Access è netto e non costa nulla di più. Con i dati su SQL cambiano quattro cose.
- Ruoli veri. L'amministrazione vede i costi, il commerciale no. Il permesso sta nel database e non nella maschera, quindi nessuno lo aggira aprendo la tabella.
- Backup automatici e ripristino a un istante. Azure SQL salva da solo e permette di tornare a un momento preciso degli ultimi giorni. Il "ripristino" di Access era la copia del file della sera prima, quando c'era.
- Traccia di chi ha fatto cosa. Con una colonna per l'autore e la data, oppure con le funzioni di storico del database, sai chi ha cambiato il prezzo di un ordine. In Access, di solito, non lo sai.
- Accesso da fuori senza aprire la rete. Chi lavora da casa non apre più una cartella condivisa via VPN: usa un'applicazione web con login, e il database non è raggiungibile da Internet.
C'è poi un punto che, nelle PMI, sposta le decisioni: il regolamento europeo sui dati personali. Un file Access con anagrafiche di clienti privati, copiato su una chiavetta o allegato a una email, è una violazione in attesa di accadere. Con i dati su un server con accessi tracciati, hai una risposta se un cliente chiede dove sono i suoi dati o se un controllo chiede come sono protetti.
Un'osservazione di costo, che la mia regola sul cloud impone: tutto questo si ottiene con il livello più economico di Azure SQL. Nella mia infrastruttura ho accorpato nove database piccoli in uno solo da 4,20 euro al mese, ognuno in uno schema separato. Se hai più applicazioni piccole, non servono tanti database: serve un database ben organizzato.
Come si fa il passaggio senza fermare l'azienda?
Il passaggio dei dati si fa in un fine settimana, ma la preparazione dura un mese. Il piano che propongo per il primo gradino, quello comune a quasi tutte le strade, è di novanta giorni al massimo.
- Giorni 1-10: inventario e copia di sicurezza. Il programma di inventario, l'elenco degli utenti, la copia del file su un disco che non sia quello del server. Si prova ad aprirla.
- Giorni 11-20: database di prova. Si creano le tabelle su SQL con i tipi corretti e si caricano i dati di una copia. Si confrontano i totali, tabella per tabella.
- Giorni 21-30: le maschere sulla copia. Si collegano le tabelle e si prova ogni maschera, con due persone dell'azienda che lavorano per un giorno come sempre. Si annotano le maschere lente e quelle rotte.
- Giorni 31-40: correzione delle maschere. Le query lente diventano viste del database, i filtri si riscrivono, i campi a valori multipli si trasformano in tabelle di collegamento.
- Giorni 41-45: prova generale. Si ripete tutto il passaggio da capo, con i tempi, su una copia fresca. Quello che è andato storto la prima volta non deve andare storto la seconda.
- Venerdì sera del giorno 46: il passaggio vero. Si blocca il vecchio file in sola lettura, si caricano i dati, si confrontano i totali, si collegano le tabelle e si aggiorna il front-end sui computer. Il lunedì mattina le persone aprono la stessa icona di sempre.
- Giorni 47-90: osservazione. Il vecchio file resta in sola lettura e non si cancella. Per tre mesi, se qualcosa non torna, si può confrontare con l'originale. Se tutto è tranquillo, si archivia.
Il piano di ritorno costa pochissimo: finché il vecchio file esiste e nessuno ci ha scritto dopo il venerdì sera, tornare indietro vuol dire riattivarlo. È la ragione per cui non si cancella mai subito il file vecchio, e per cui il passaggio si fa a fine settimana e non a metà mese, quando si chiudono le fatture.
Una nota sulle persone, che pesa più del codice. Prima del passaggio, chiedi alle quattro persone che usano di più il sistema di descriverti "la cosa che mi fa perdere più tempo". Metà delle volte non è quello che avevi in mente tu, ed è spesso la più facile da sistemare. Un risultato visibile nel primo mese vale più di una presentazione.
Quali errori evitare in una migrazione da Access?
Gli errori che vedo più spesso, e che costano di più, sono otto.
- Cominciare dalla riscrittura. Si parte da "facciamo un'applicazione nuova" senza sapere che cosa c'è dentro quella vecchia. Il preventivo è una stima alla cieca, e il conto arriva a metà lavoro.
- Lavorare sul file vero. Ogni prova, ogni conversione si fa su una copia. Un solo errore sull'originale e perdi anni di dati.
- Usare float per i soldi. I centesimi spariscono a gruppi, in silenzio. Si usa
decimalovunque. - Dimenticare la colonna di versione. Le maschere collegate a SQL danno errori di scrittura e salvataggi sovrapposti, e nessuno capisce perché.
- Tradurre ogni query una per una. Molte delle 41 query salvate non servono più. Se non sai chi le usa, non le traduci: aspetti che qualcuno le chieda.
- Spostare tutto insieme. Dati, maschere, report e regole in un solo "lancio". Se qualcosa va storto, non sai quale pezzo è stato.
- Non scrivere i casi di prova. Senza i 150 preventivi con il totale giusto, la regola di prezzo nuova è un atto di fede, e la scoprirai sbagliata dal cliente.
- Spegnere il vecchio troppo presto. Il file originale resta in sola lettura per almeno tre mesi. Costa uno spazio disco irrisorio e salva dalle sorprese di fine trimestre.
Una regola le riassume tutte: si cambia una cosa per volta e si può sempre tornare indietro. Un progetto di migrazione che non ha un passo indietro a ogni gradino non è un progetto, è una scommessa.
Quando conviene lasciare Access dov'è?
Succede spesso, ed è una buona notizia. Ci sono tre situazioni in cui spendere per migrare non conviene, e te le dico apertamente.
- Pochi utenti e dati piccoli. Un'applicazione per tre persone, con un file sotto i 200 MB, un backup giornaliero provato e un processo semplice. Qui il costo annuo è vicino a zero: sistemare il backup e basta.
- Un processo che sta per sparire. Se l'azienda ha deciso di passare a un pacchetto fra dodici mesi, non vale la pena investire sul vecchio. Un po' di cure (backup, compattazione, accessi) bastano per arrivarci.
- Il costo del problema è sotto il costo della soluzione in tre anni. Se i fermi valgono 300 euro l'anno e nessuno lavora in Excel dopo, una migrazione da 3.840 euro non si ripaga.
In ognuno di questi casi c'è un minimo che conviene fare comunque, e costa poche ore: una copia giornaliera su un disco diverso con una prova di ripristino ogni tre mesi, la divisione in front-end e back-end se non c'è già, la compattazione programmata e un elenco scritto di chi usa che cosa. Sono 8-10 ore di lavoro, e tolgono il rischio peggiore.
Se il problema non è Access ma il fatto che ogni cosa passa da una sola persona, la risposta non è software: è mettere per iscritto quello che c'è e far leggere il documento a una seconda persona. Si fa in un mese, e vale più di qualsiasi tecnologia.
Se sei arrivato fin qui, probabilmente hai in mente un preventivo di migrazione, o un file che fa paura. Prima di decidere, prendi i tuoi numeri: utenti, dimensione del file, fermi all'anno, ore di Excel alla settimana, ore del consulente. Mezza giornata, e sai se il tuo problema è il contenitore o il processo.
Se vuoi un secondo sguardo sul tuo caso, la strada è la consulenza software. E quando la soluzione giusta è un gestionale costruito attorno al tuo modo di lavorare, lo trovi spiegato nella pagina sul software su misura. Se il tuo problema è un'applicazione ancora più vecchia, ne parlo nella guida alla migrazione da VB6 a .NET e in quella sulla migrazione di Windows Forms. Sul tema dei costi del cloud, c'è come risparmiare con Azure.
Domande frequenti
Quando il file ha più di 10 utenti, supera il 70 per cento dei 2 GB di limite, si danneggia più di una volta l'anno, o quando una parte del lavoro si fa a mano in Excel perché il programma non la sa fare. Con pochi utenti, dati piccoli e un backup provato, in genere conviene lasciarlo dov'è.
Per un file di circa 1,4 GB con 112 tabelle e 14 utenti, spostare solo i dati su Azure SQL costa circa 8 giornate di lavoro, cioè 3.840 euro a 480 euro al giorno, più circa 4,20 euro al mese di database. Una riscrittura completa in .NET costa invece circa 62 giornate, 29.760 euro.
Sì, ed è il primo passo che consiglio. Le tabelle vanno su Azure SQL o SQL Server e le maschere di Access restano collegate. Si eliminano così i fermi per file danneggiato e il limite dei 2 GB, ma non il lavoro fatto a mano fuori dal programma.
Gli allegati, i campi a valori multipli, i campi Memo con cronologia, le date vuote che diventano 30/12/1899 e i campi Sì/No con valori nulli. Servono anche una chiave primaria e una colonna rowversion in ogni tabella, altrimenti le maschere collegate a SQL danno errori di scrittura.
Il passaggio dei dati si prepara in circa 45 giorni e si esegue in un fine settimana, con altri 45 giorni di osservazione. Un modulo web che sostituisce una parte del processo richiede in genere altri due mesi. Una riscrittura completa si misura in sei-otto mesi.
Access resta incluso in Microsoft 365. Le versioni con licenza perpetua 2016 e 2019 sono uscite dal supporto a ottobre 2025 e la 2021 il 13 ottobre 2026, quindi chi le usa non riceve più correzioni di sicurezza.
