You open a workbook or Access database that has worked for years, and suddenly VBA throws "Can't find project or library" on a line that was perfectly fine yesterday. You check Tools > References in the VBA Editor and see the dreaded MISSING: Microsoft DAO 3.6 Object Library. This guide explains exactly why it happens and how to fix it — in both Excel and Access — without breaking your existing code.
DAO stands for Data Access Objects. It is a programming interface that lets VBA code interact with Jet and ACE databases — the engines behind Microsoft Access .mdb and .accdb files. The "3.6" version shipped with Office 2000 through Office 2010 and lived in a file called dao360.dll, typically located at:
C:\Program Files\Common Files\Microsoft Shared\DAO\dao360.dll
When your VBA project references this library, you can write strongly-typed code like:
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = CurrentDb() ' Access
Set db = DBEngine.OpenDatabase("C:\Data\inventory.mdb") ' Excel
Set rs = db.OpenRecordset("SELECT * FROM Products")
Do Until rs.EOF
Debug.Print rs!ProductName
rs.MoveNext
Loop
rs.Close
db.Close
Every DAO. prefix in that code depends on the reference being intact. The moment the library goes missing, every one of those lines becomes a compile error.
There are four common triggers:
dao360.dll is not installed by Microsoft 365. The replacement is the Microsoft Office Access Database Engine Object Library, but your VBA project still points to the old file.dao360.dll change. Even if the file physically exists, the COM registration may not match the bitness Office expects.Depending on your code and Office version, the missing DAO reference produces one of these errors:
Compile error: Can't find project or library — the most common. VBA highlights the first line that uses a DAO type.Compile error: User-defined type not defined — appears when you Dim a variable as DAO.Database or DAO.Recordset and the reference is missing.Run-time error 3021: No current record or Run-time error 3061: Too few parameters — these can surface if a different DAO-like library partially resolves the types but behaves differently at runtime.Error in loading DLL — rare, but happens when the DLL file exists but is the wrong bitness (32-bit DLL on 64-bit Office).This procedure works in both Excel and Access. The only difference is which library name you will check — covered in the next section.
Press Alt + F11 to open the Visual Basic Editor.
Go to Tools > References from the menu bar. This opens the list of all registered type libraries on your system.
Scroll to the top of the list. Broken references are moved to the top and prefixed with MISSING:. You will see something like:
☑ MISSING: Microsoft DAO 3.6 Object Library
Uncheck this entry. Do not just leave it checked — a checked MISSING reference will cause compile errors every time.
Scroll through the Available References list and check the correct library for your Office version:
| Office Version | Library to Check |
|---|---|
| Office 365 / Office 2021 / 2019 | Microsoft Office 16.0 Access Database Engine Object Library |
| Office 2016 | Microsoft Office 16.0 Access Database Engine Object Library |
| Office 2013 | Microsoft Office 15.0 Access Database Engine Object Library |
| Office 2010 | Microsoft Office 14.0 Access Database Engine Object Library |
| Office 2007 | Microsoft Office 12.0 Access Database Engine Object Library |
| Office 2003 and earlier | Microsoft DAO 3.6 Object Library (dao360.dll) |
If you do not see any of these libraries, it means the Access Database Engine is not installed. You can download the Microsoft Access Database Engine Redistributable from Microsoft for free — make sure you get the version (32-bit or 64-bit) that matches your Office installation, not your Windows installation.
After checking the new library, go to Debug > Compile in the VBA Editor. If it compiles without errors, you are done. Save the file and test your macros.
When VBA loads a project, it reads a list of GUIDs (globally unique identifiers) stored inside the file. Each GUID maps to a specific type library. If VBA cannot find a registered library matching that GUID and version on the current machine, it marks the reference as MISSING: and moves it to the top of the References list.
Key things to know about MISSING references:
DAO.Database and DAO.Recordset declarations will throw "User-defined type not defined."The fix procedure is the same, but there are important differences in context.
Access has a built-in reference to DAO by default. Every new Access database automatically includes the Access Database Engine Object Library. If you are seeing a MISSING DAO reference in Access, it usually means one of these:
.mdb file was created in Access 2003 or earlier and references the old dao360.dll specifically. Converting the file to .accdb format usually auto-fixes this.In Access, you can also use CurrentDb and Recordset without the DAO. prefix because Access implicitly resolves these types. But if you have both DAO and ADO referenced, the unqualified Recordset type becomes ambiguous — see the DAO vs. ADO section below.
Excel does not include a DAO reference by default. If your Excel VBA code uses DAO, someone added that reference manually. This makes Excel workbooks more fragile when moving between machines because:
If you distribute Excel workbooks that rely on DAO, consider switching to late binding to avoid reference issues entirely:
' Early binding (requires DAO reference — breaks if missing)
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = DBEngine.OpenDatabase("C:\Data\sales.accdb")
' Late binding (no reference needed — always works)
Dim db As Object
Dim rs As Object
Set db = CreateObject("DAO.DBEngine.120").OpenDatabase("C:\Data\sales.accdb")
Late binding trades IntelliSense and compile-time checking for portability. For distributed workbooks, it is usually the right call.
LegacyLeaps detects and fixes broken references automatically — across hundreds of files at once. Upload your workbook or database and get a full compatibility report in seconds.
Try the Free ScanThese three terms cause constant confusion. Here is the breakdown:
| Technology | Full Name | Best For | Library Name in References |
|---|---|---|---|
| DAO | Data Access Objects | Access/Jet/ACE databases (.mdb, .accdb) | Microsoft DAO 3.6 Object Library or Microsoft Office xx.0 Access Database Engine Object Library |
| ADO | ActiveX Data Objects | SQL Server, Oracle, any OLE DB/ODBC source | Microsoft ActiveX Data Objects x.x Library |
| ADODB | ADO namespace prefix | Same as ADO — ADODB is just the VBA prefix | Same as ADO |
DAO talks directly to the Jet/ACE database engine. It is faster for local Access databases and supports Access-specific features like table-level security and linked tables.
ADO is a higher-level, provider-based model. You connect through a connection string and can talk to virtually any database. In VBA code, ADO types are prefixed with ADODB. — for example, ADODB.Connection and ADODB.Recordset.
Common conflict: If your Access VBA project references both DAO and ADO, and your code says Dim rs As Recordset without a prefix, VBA does not know which Recordset you mean. Whichever library is higher in the References priority list wins. This is why best practice is to always qualify: DAO.Recordset or ADODB.Recordset.
Here are the most common patterns that fail when the DAO reference goes missing, along with the exact error each produces:
' This line throws "User-defined type not defined"
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim td As DAO.TableDef
Dim qd As DAO.QueryDef
Dim fld As DAO.Field
Why: Without the DAO reference, VBA has no idea what DAO.Database means. It is not a built-in type.
' In Access, this compiles IF DAO is the default — but breaks if
' DAO is missing and only ADO is referenced
Dim rs As Recordset
Set rs = CurrentDb.OpenRecordset("Customers")
Why: If only ADO is referenced, Recordset resolves to ADODB.Recordset, which does not have an OpenRecordset method. You get "Method or data member not found" at compile time, or a confusing runtime error.
' Throws "Can't find project or library" on DBEngine
Dim db As DAO.Database
Set db = DBEngine.OpenDatabase("\\server\share\data.mdb")
Why: DBEngine is part of the DAO library. Without the reference, VBA does not recognize it as an object.
' dbOpenDynaset is a DAO constant — undefined without the reference
Set rs = db.OpenRecordset("Products", dbOpenDynaset)
Why: dbOpenDynaset, dbOpenSnapshot, dbOpenTable, and similar constants are defined in the DAO type library. Without the reference, they are undefined. Replace with their numeric values as a temporary workaround: dbOpenDynaset = 2, dbOpenSnapshot = 4, dbOpenTable = 1.
Once you have fixed the reference, take these steps to prevent it from breaking again:
DAO.Recordset instead of Recordset. This prevents ambiguity if ADO is ever added to the project.| Scenario | Action |
|---|---|
See MISSING: Microsoft DAO 3.6 in References |
Uncheck it, check Microsoft Office 16.0 Access Database Engine Object Library |
| No DAO library appears in the list at all | Install the Access Database Engine Redistributable (match bitness to Office) |
Code uses Recordset without prefix and behaves oddly |
Add DAO. prefix: Dim rs As DAO.Recordset |
| Distributing a workbook to users without Access | Switch to late binding or use ADO with a connection string |
Both DAO and ADO referenced, ambiguous Recordset |
Use priority order (Tools > References, use arrow buttons) or qualify all types |
Download LegacyLeaps and scan your workbooks and databases for free. Broken references, missing libraries, VBA compatibility issues — all detected automatically. Use promo code FIRSTFILE for a free file conversion.
Download Free ScannerPractical fixes for legacy Excel and Access problems. No spam.
Related Articles