The Complete Guide to Migrating Access Databases to Modern Formats

January 19, 2026 · 18 min read

Your Access database has been running your business for years. Maybe decades. It tracks inventory, manages customer records, runs payroll reports, or logs service calls. And then you upgraded to Windows 11 — or moved to a new machine with 64-bit Office — and suddenly it doesn't work anymore.

This is the guide you need. We'll cover everything: the difference between .mdb and .accdb, what actually breaks during migration, how to preserve your VBA code, what to do about ActiveX controls, how Jet SQL differs from ACE SQL, and how to verify that nothing was lost after the move.

Other tools — including some that claim to migrate Access databases — only move your data. Your VBA code, your forms, your ActiveX controls, your Jet SQL procedures: most tools silently drop all of it. This guide explains what a real migration covers.

Table of Contents

  1. Understanding the Formats: .mdb vs .accdb
  2. Why Migration Can't Wait
  3. Pre-Migration Inventory
  4. The Migration Process, Step by Step
  5. Preserving VBA Code
  6. Jet SQL vs ACE SQL: What Changes
  7. ActiveX Controls: The Hidden Migration Challenge
  8. Linked Tables and External Data Sources
  9. Data Integrity Verification
  10. When to Consider SQL Server Instead
  11. Migration Checklist

Understanding the Formats: .mdb vs .accdb

Both .mdb and .accdb are Microsoft Access database formats, but they use completely different underlying database engines.

Feature .mdb (Legacy) .accdb (Modern)
Database engine Jet 4.0 ACE (Access Connectivity Engine)
Introduced Access 97 Access 2007
Max database size 2GB total 2GB per database file (same as .mdb)
Max table size 2GB 2GB (same, but more flexible)
Encryption Weak (RC4-based) Strong (AES-256)
Multi-value fields Not supported Supported
Attachment fields Not supported Supported
64-bit Windows 11 Broken (Jet not available) Fully supported
Office 365 compatibility Limited / broken Full
Jet OLEDB provider Required (deprecated) Not needed (uses ACE OLEDB)

The core issue is the database engine. Jet 4.0 is a 32-bit engine that Microsoft stopped developing after Access 2003. It was never ported to 64-bit. Windows 11 64-bit doesn't include the 32-bit Jet provider by default, and even when installed, Jet has known security vulnerabilities that Microsoft will not patch.

ACE (Access Connectivity Engine) is Jet's replacement. It's 64-bit native, actively maintained, and included with all modern Office installations.

Why Migration Can't Wait

Windows 11 64-bit removed Jet OLEDB 4.0

The Jet OLEDB 4.0 provider is not present on clean Windows 11 64-bit installations. This means any application that tries to open an .mdb file using the standard OLEDB connection string will fail. This affects not just Access itself — it affects Excel workbooks that query Access, .NET applications using OleDbConnection, and any VBA code that uses DAO or ADO to connect to .mdb files.

Unpatched security vulnerabilities

Jet 4.0 has several publicly documented security vulnerabilities (CVE-2018-8423, CVE-2019-1024, and others). Microsoft has explicitly stated these will not be patched because Jet is end-of-life. If your .mdb database is accessible from a network or web application, running Jet 4.0 is a security risk.

No password reset for .mdb encryption

The RC4-based encryption in .mdb is easily broken by free tools. If you're encrypting sensitive data in an .mdb database and believe it's protected — it isn't. AES-256 encryption in .accdb is legitimate.

Your IT team is already blocked

Most enterprise IT departments have already removed or blocked the Jet OLEDB 4.0 redistributable as part of security hardening. If your business has users on managed Windows 11 machines, they likely can't open .mdb files even if they want to.

Not sure what's breaking in your database?

LegacyLeaps scans your .mdb file and produces a report of every VBA issue, broken reference, and compatibility problem — before you convert anything.

Run Free Scan

Pre-Migration Inventory

Before you touch anything, document everything. A migration without a pre-migration inventory is how databases get partially migrated and then used in production half-working for months.

Tables

Queries

Forms and Reports

VBA Code

Linked Tables and External Connections

Tip: Run this query in your .mdb to get a quick table inventory: SELECT Name, Type FROM MSysObjects WHERE Type IN (1, 4, 5, 6) ORDER BY Type, Name — this lists tables (1), queries (5), forms (2), and reports (3).

The Migration Process, Step by Step

Step 1: Create a complete backup

Copy the .mdb file to a separate drive or cloud storage. Do not proceed without a verified backup. This sounds obvious but is the most commonly skipped step — and the source of most irreversible migrations.

Step 2: Compact and Repair the source

Before converting, compact and repair the .mdb in its original version of Access (or the nearest available). This catches any pre-existing corruption. A database with corruption before migration will have worse corruption after it. Tools > Database Utilities > Compact and Repair Database.

Step 3: Open in Access 2016+ and Save As .accdb

Open the compacted .mdb in Access 2016, 2019, 2021, or 365. Go to File > Save As > Access Database (.accdb). Give the new file a distinct name — don't overwrite the .mdb.

Access will convert the data, queries, forms, reports, macros, and VBA modules. It will not automatically fix compatibility issues — it will just copy them into the new container. The compatibility work happens in the steps below.

Step 4: Fix VBA code

This is where most migrations fail if done manually. See the VBA section below for complete details. At minimum: add PtrSafe to all Declare statements, replace Long with LongPtr for pointers, and resolve broken references.

Step 5: Repair or replace ActiveX controls

Open every form and check for errors. ActiveX controls that reference 32-bit-only libraries will not load on 64-bit Office. See the ActiveX section for replacement strategies.

Step 6: Update linked tables

Open the Linked Table Manager (External Data > Linked Table Manager) and refresh all connections. Update any paths that pointed to the old .mdb files.

Step 7: Test all queries

Run every query in the database. Pay attention to queries that use: IN with subqueries, TRANSFORM/PIVOT, TOP with ties, and date arithmetic using # delimiters. Some Jet SQL behaviors changed slightly in ACE.

Step 8: Validate data integrity

See the Data Integrity Verification section. Don't skip this. Record counts must match exactly.

Preserving VBA Code

This is the section that distinguishes a real migration from a "data dump." Most migration tools — including SysTools — extract your tables and queries but silently ignore your VBA code modules. Your forms lose their event handlers. Your reports lose their custom formatting logic. Your automation stops working.

What transfers automatically

When you use Access's Save As to convert from .mdb to .accdb, the following transfers without intervention:

What requires manual fixing

Win32 API Declare statements

64-bit Office VBA requires the PtrSafe keyword on every Declare statement. Without it, any Declare in your code will cause a compile error in 64-bit Access.

' Before (fails on 64-bit Office)
Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
  (ByVal lpClassName As String, ByVal lpWindowName As String) As Long

' After (works on 32-bit and 64-bit Office)
Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" _
  (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr

Parameters that represent window handles, memory addresses, or pointers should use LongPtr instead of Long. LongPtr is 32-bit on 32-bit Office and 64-bit on 64-bit Office, so it's the right type for any pointer or handle value.

DAO vs ADO connection strings

If your VBA code opens connections to other databases using ADO, the connection string must be updated to reference ACE OLEDB instead of Jet OLEDB:

' Old (Jet — fails on 64-bit Windows 11)
conn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & dbPath

' New (ACE — works on current systems)
conn.ConnectionString = "Provider=Microsoft.ACE.OLEDB.16.0;Data Source=" & dbPath

Broken library references

Tools > References in the VBA editor. Anything marked MISSING needs to be removed and re-added (if still needed) or removed entirely (if the library is obsolete). Common culprits:

Too much VBA to fix manually?

LegacyLeaps scans your entire .mdb database, identifies every VBA compatibility issue, and applies all fixes automatically during migration. No code editing required.

See Done-For-You Migration

Jet SQL vs ACE SQL: What Changes

Most Jet SQL works identically in ACE. But there are edge cases that can silently return different results or throw errors after migration.

Date literals

Jet SQL uses # delimiters for date literals: WHERE OrderDate = #01/15/2020#. ACE SQL accepts the same syntax, but regional date format interpretation can vary. If your database was created in a UK locale and is now running in a US locale (or vice versa), date queries may return wrong results.

Best practice: Use ISO 8601 format in date literals: #2020-01-15#. This is unambiguous in both Jet and ACE.

Outer join syntax

Jet SQL supported an older outer join syntax using *= and =* from the early SQL days. This does not work in ACE. Replace with standard ANSI LEFT JOIN, RIGHT JOIN, and FULL OUTER JOIN.

' Old Jet syntax (broken in ACE)
SELECT * FROM Customers, Orders WHERE Customers.ID *= Orders.CustomerID

' Standard ANSI (works in ACE)
SELECT * FROM Customers LEFT JOIN Orders ON Customers.ID = Orders.CustomerID

DISTINCTROW keyword

Jet SQL's DISTINCTROW keyword (which removes duplicates based on entire rows from the source table) has different behavior in ACE in edge cases. Review any queries using DISTINCTROW carefully.

TOP with ties

In Jet, SELECT TOP 10 would return up to 10 records but might return more if there were ties on the ordering column. ACE behavior is similar but there are known edge cases. Verify TOP queries return expected record counts.

IIf() and Nz() function behavior

These Access-specific functions work in both Jet and ACE, but IIf() always evaluates both branches in Jet (even the one not selected), which can cause errors. ACE behavior is similar. Avoid IIf() with side-effect expressions.

Pass-through queries

Pass-through queries use the syntax of the back-end database, not Jet/ACE. If your .mdb had pass-through queries to SQL Server, they will continue to work after migration to .accdb — assuming the ODBC connection string is valid.

ActiveX Controls: The Hidden Migration Challenge

This is the issue most migration guides — and most migration tools — skip entirely. ActiveX controls are COM components embedded in Access forms and reports. They add functionality like calendars, progress bars, rich text editors, and custom grid controls.

The problem: many ActiveX controls are 32-bit only. A 32-bit ActiveX control cannot load in 64-bit Access. The form opens, but the control is a grey box with an error, and any code referencing it throws a runtime error.

Identifying your ActiveX controls

Open each form in Design View. Any control with a small icon in the corner is likely an ActiveX control. Check the Properties sheet — the Control Source property will be blank and the control class will show something like Forms.{GUID}.0 or a descriptive name like MSComctlLib.ProgressBar.

Common legacy controls and their replacements

Legacy ActiveX Control 64-bit Status Replacement
Microsoft Calendar Control (mscal.ocx) 32-bit only — broken Use a text box with Date Picker or free Date Picker from Microsoft
MSComctlLib (ListView, TreeView, ProgressBar) 32-bit only — broken MSCOMCTL.OCX has a 64-bit version — re-register it, or use VBA-drawn alternatives
Microsoft Masked Edit Control 32-bit only — broken Use native Access input masks on text boxes
Microsoft Rich Textbox Control 32-bit only — broken Use a bound text box with Memo/Long Text field type
Microsoft WebBrowser Control 64-bit version exists May work after re-registration — test carefully
Tabstrip Control (MSComctlLib) 32-bit only — broken Use native Access Tab Control

The re-registration approach

For controls that have 64-bit versions available, you can try re-registering the .ocx file. Open Command Prompt as Administrator and run: regsvr32 "C:\Windows\SysWOW64\MSCOMCTL.OCX". This may restore some controls but will not help for controls with no 64-bit version at all.

When manual replacement is impractical

If your database has dozens of forms with ActiveX controls, manual replacement becomes a large project. Each control replacement requires testing the form, rewriting any VBA that referenced the old control's properties and methods, and verifying the replacement behaves identically.

This is exactly the kind of migration complexity that LegacyLeaps's done-for-you service handles — we document every ActiveX control, identify the replacement strategy, and implement it as part of the migration.

Linked Tables and External Data Sources

Linked tables are one of the most common sources of post-migration headaches. The table data doesn't live inside the .mdb — it lives elsewhere, and the .mdb just contains a connection string and schema definition.

Tables linked to other .mdb files

After your main database converts to .accdb, any linked .mdb files also need to be converted (or the links updated to use the Jet OLEDB provider with the redistributable). The simplest approach: convert all linked .mdb databases first, then update the links in the main database to point to the new .accdb files.

Use the Linked Table Manager (External Data > Linked Table Manager) to view and update all links at once. You can also update links programmatically:

' VBA to update all linked table connection strings
Dim db As DAO.Database
Dim tdf As DAO.TableDef
Set db = CurrentDb()
For Each tdf In db.TableDefs
  If Left(tdf.Connect, 10) = ";DATABASE=" Then
    ' Update the path to the new .accdb location
    tdf.Connect = ";DATABASE=C:\NewPath\Database.accdb"
    tdf.RefreshLink
  End If
Next tdf

Tables linked to ODBC data sources

ODBC-linked tables (SQL Server, MySQL, Oracle) generally survive migration without changes — the ODBC connection string doesn't care whether the front-end is .mdb or .accdb. However, verify that the ODBC driver is still registered on the new machine and that connection strings are still valid.

Tables linked to SharePoint lists

SharePoint-linked tables are stored differently in .accdb vs .mdb. After migration, you may need to unlink and re-link SharePoint tables. Access's External Data > SharePoint List wizard handles this.

Linked Excel spreadsheets

Links to .xls spreadsheets use the Jet OLEDB provider — same as .mdb files. On 64-bit Windows 11, these links will fail too. Convert linked Excel files to .xlsx first, then update the links to use the ACE OLEDB provider with the Excel connection string format.

Data Integrity Verification

The most important step — and the one most commonly skipped. Do not declare a migration complete until you've verified that every record, every relationship, and every computation produces the same result in the new database.

Record count verification

Run this in both the old and new database. Counts must match exactly:

-- Run in both .mdb and .accdb and compare output
SELECT 'Customers' AS TableName, COUNT(*) AS RecordCount FROM Customers
UNION ALL
SELECT 'Orders', COUNT(*) FROM Orders
UNION ALL
SELECT 'Products', COUNT(*) FROM Products
-- (add all tables)
ORDER BY TableName

Relationship integrity check

Open the Relationships window (Database Tools > Relationships) in both databases and compare. Referential integrity settings, cascade delete/update settings, and join types must all match.

Query output comparison

Run every query in both the old and new database on the same date/time and compare outputs. For large result sets, export to CSV and diff the files. Pay special attention to aggregate queries, date-range queries, and queries with complex joins.

Warning: Jet SQL and ACE SQL can produce subtly different results for queries involving NULL handling, outer joins, and certain aggregate functions. Don't assume a query that ran successfully means the output is correct — verify the actual data.

Form and report functionality

Open every form in Normal view (not Design view). Click every button, fill every input, trigger every event. Check that all subforms load, all calculated fields display correctly, and all record navigation works. Run every report and visually verify the output against a known-good printout from the old version.

VBA procedure testing

Run every VBA procedure that's accessible via button click, form event, or standalone module. Check the Immediate Window (Ctrl+G in VBA editor) for runtime errors during execution.

Compact and Repair the new .accdb

After migration and validation, run Compact and Repair on the new .accdb (Database Tools > Compact and Repair Database). This rebuilds indexes, reclaims space, and catches any internal inconsistencies introduced by the migration.

When to Consider SQL Server Instead of .accdb

Converting to .accdb is the right move for most small business Access databases. But if your database has grown beyond what Access was designed for, migration to SQL Server (with Access as a front-end, or a full application rewrite) may be the better long-term investment.

Signs you've outgrown Access

The access front-end / SQL Server back-end option

This is the lowest-risk migration path: keep your Access forms, reports, and VBA code exactly as-is, but move the data tables to SQL Server. The Access database becomes a thin client connected to SQL Server via ODBC linked tables.

This preserves all your Access-specific UI work while gaining SQL Server's reliability, scalability, and backup capabilities. It's the approach recommended for databases with more than 5 concurrent users or files over 500MB.

When to do a full migration to SQL Server

A full migration (rewriting the Access front-end as a web application or thick client against SQL Server) makes sense when the Access UI itself is the bottleneck — outdated forms, poor performance, or a need to add web or mobile access. This is a larger project and typically requires developer engagement.

For most businesses, the right answer is .accdb first, SQL Server later if needed. Converting to .accdb solves the immediate compatibility problem. If you grow into SQL Server territory, you migrate from a stable .accdb rather than a broken .mdb.

Migration Checklist

Use this checklist before calling a migration complete.

Pre-Migration

During Migration

Post-Migration Verification

Coming Soon

AccessLeap — Turn Your Access Database Into a Web App

AI-powered code generation from .accdb files. Your data never leaves your machine.


Learn More & Get Notified

Ready to migrate your Access database?

LegacyLeaps handles the full migration: VBA fixes, ActiveX replacement, Jet SQL updates, linked table refresh, and data integrity verification. 100% money-back guarantee — if LegacyLeaps doesn't preserve your VBA code, forms, and data, we'll refund every penny.

Get a Free Consultation

Related Resources

Get tips like this in your inbox

Practical fixes for legacy Excel and Access problems. No spam.

← Back to all posts