Microsoft Access
Overview
This skill helps AI agents work with Microsoft Access databases — designing tables, writing queries, building forms and reports, automating with VBA, and planning migrations to modern platforms. Access is widely used in small businesses and departments for data management, and agents should know how to build, maintain, and eventually migrate these systems.
Instructions
Step 1: Database Design
Table: Customers
CustomerID AutoNumber (Primary Key)
FirstName Short Text (50)
LastName Short Text (50)
Email Short Text (100), Indexed (No Duplicates)
Phone Short Text (20)
Company Short Text (100)
CreatedDate Date/Time, Default: =Now()
IsActive Yes/No, Default: Yes
Table: Orders
OrderID AutoNumber (Primary Key)
CustomerID Long Integer (Foreign Key -> Customers)
OrderDate Date/Time, Default: =Date()
TotalAmount Currency
Status Short Text (20), Validation: In ("Pending","Shipped","Delivered","Cancelled")
Table: OrderItems
ItemID AutoNumber (Primary Key)
OrderID Long Integer (Foreign Key -> Orders)
ProductID Long Integer (Foreign Key -> Products)
Quantity Integer, Validation: >0
UnitPrice Currency
Table: Products
ProductID AutoNumber (Primary Key)
ProductName Short Text (100)
Category Short Text (50)
UnitPrice Currency
UnitsInStock Integer, Default: 0
ReorderLevel Integer, Default: 10
Relationships (enforce referential integrity, cascade update, no cascade delete):
Customers (1) --- (many) Orders
Orders (1) --- (many) OrderItems
Products (1) --- (many) OrderItems
Design rules: AutoNumber PKs, proper data types with length limits, validation rules at table level, default values, indexes on frequently queried fields.
Step 2: Queries
-- Join with aggregation: total sales per customer
SELECT c.CustomerID, c.FirstName & " " & c.LastName AS FullName,
Count(o.OrderID) AS OrderCount, Sum(o.TotalAmount) AS TotalSpent
FROM Customers c INNER JOIN Orders o ON c.CustomerID = o.CustomerID
GROUP BY c.CustomerID, c.FirstName & " " & c.LastName
HAVING Sum(o.TotalAmount) > 1000
ORDER BY TotalSpent DESC;
-- Crosstab: monthly sales by category
TRANSFORM Sum(oi.Quantity * oi.UnitPrice) AS Revenue
SELECT p.Category
FROM Products p INNER JOIN OrderItems oi ON p.ProductID = oi.ProductID
INNER JOIN Orders o ON oi.OrderID = o.OrderID
WHERE o.OrderDate Between #2026-01-01# And #2026-12-31#
GROUP BY p.Category
PIVOT Format(o.OrderDate, "yyyy-mm");
-- Inactive customers (no orders in 90 days)
SELECT c.CustomerID, c.FirstName, c.LastName, c.Email
FROM Customers c
WHERE c.CustomerID NOT IN (
SELECT DISTINCT o.CustomerID FROM Orders o WHERE o.OrderDate >= DateAdd("d", -90, Date())
) AND c.IsActive = True;
-- Action: mark overdue orders
UPDATE Orders SET Status = "Overdue"
WHERE Status = "Pending" AND OrderDate < DateAdd("d", -30, Date());
-- Parameter query
SELECT o.OrderID, c.LastName, o.OrderDate, o.TotalAmount
FROM Orders o INNER JOIN Customers c ON o.CustomerID = c.CustomerID
WHERE o.OrderDate Between [Enter Start Date:] And [Enter End Date:];
Step 3: Forms & VBA
' Search form with dynamic filtering
Private Sub btnSearch_Click()
Dim strFilter As String
If Not IsNull(Me.txtSearchName) Then
strFilter = "LastName Like '*" & Me.txtSearchName & "*'"
End If
If Not IsNull(Me.cboStatus) Then
If Len(strFilter) > 0 Then strFilter = strFilter & " AND "
strFilter = strFilter & "Status = '" & Me.cboStatus & "'"
End If
Me.subResults.Form.Filter = strFilter
Me.subResults.Form.FilterOn = (Len(strFilter) > 0)
End Sub
' Validation before save
Private Sub Form_BeforeUpdate(Cancel As Integer)
If IsNull(Me.txtEmail) Or Not Me.txtEmail Like "*@*.*" Then
MsgBox "Please enter a valid email address.", vbExclamation
Me.txtEmail.SetFocus
Cancel = True
End If
End Sub
Step 4: Reports & Export
' Export report to PDF
Private Sub btnExportPDF_Click()
DoCmd.OutputTo acOutputReport, "rptMonthlySales", acFormatPDF, _
"C:\Reports\SalesReport_" & Format(Date, "yyyy-mm-dd") & ".pdf"
End Sub
' Export query results to Excel
Public Sub ExportToExcel()
Dim xlApp As Object, xlWb As Object, rs As DAO.Recordset
Set xlApp = CreateObject("Excel.Application")
Set xlWb = xlApp.Workbooks.Add
Set rs = CurrentDb.OpenRecordset("qryMonthlySales")
Dim i As Integer
For i = 0 To rs.Fields.Count - 1
xlWb.Sheets(1).Cells(1, i + 1).Value = rs.Fields(i).Name
Next i
xlWb.Sheets(1).Range("A2").CopyFromRecordset rs
xlWb.Sheets(1).Columns.AutoFit
xlWb.SaveAs "C:\Reports\MonthlySales_" & Format(Date, "yyyy-mm") & ".xlsx"
xlWb.Close: xlApp.Quit
End Sub
Step 5: Automation
' Import CSV and deduplicate against existing data
Public Sub ImportCSV()
DoCmd.TransferText acImportDelim, , "ImportedData", "C:\Data\import.csv", True
CurrentDb.Execute "INSERT INTO Customers (FirstName, LastName, Email) " & _
"SELECT Trim(FirstName), Trim(LastName), LCase(Trim(Email)) " & _
"FROM ImportedData WHERE Email NOT IN (SELECT Email FROM Customers)"
CurrentDb.Execute "DROP TABLE ImportedData"
End Sub
' Link to SQL Server
Public Sub LinkSQLServerTables()
Dim tdf As DAO.TableDef, connStr As String
connStr = "ODBC;DRIVER={ODBC Driver 17 for SQL Server};SERVER=myserver.database.windows.net;DATABASE=MyDB;UID=admin;PWD=password;"
Set tdf = CurrentDb.CreateTableDef("dbo_Customers")
tdf.Connect = connStr
tdf.SourceTableName = "dbo.Customers"
CurrentDb.TableDefs.Append tdf
End Sub
Step 6: Migration Strategy
| Current |
Target |
Best For |
| Access tables |
SQL Server / Azure SQL |
Data > 2GB, multi-user |
| Access forms |
Power Apps |
Low-code, mobile access |
| Access reports |
Power BI |
Advanced analytics |
| Access + VBA |
Web app (Node/Python) |
Internet access, APIs |
| Everything |
Dataverse + Power Platform |
Full MS ecosystem |
Examples
Example 1: Build an order management database
User prompt: "Create an Access database for tracking customer orders with products, order items, and a search form to find orders by customer name or date range."
The agent will:
- Create four tables (Customers, Orders, OrderItems, Products) with AutoNumber primary keys, proper data types, and validation rules
- Set up relationships with referential integrity: Customers 1-to-many Orders, Orders 1-to-many OrderItems, Products 1-to-many OrderItems
- Build a search form with text box for customer name, combo box for status, and date range fields
- Add VBA
btnSearch_Click handler that constructs a dynamic filter string and applies it to a subform displaying matching orders
Example 2: Generate a monthly sales report and export to PDF
User prompt: "Create an Access report showing monthly sales totals grouped by product category, with subtotals per category and a grand total, then export it as a PDF."
The agent will:
- Write a crosstab query using
TRANSFORM Sum(Quantity * UnitPrice) pivoted by Format(OrderDate, "yyyy-mm") and grouped by product category
- Design a report with Group Header/Footer on Category (showing subtotals), Detail section for monthly figures, and Report Footer for grand total
- Add conditional formatting in the
GroupFooter_Format event to highlight categories with sales under $1,000 in red
- Implement a
btnExportPDF_Click handler using DoCmd.OutputTo to save the report as a dated PDF file
Guidelines
- Always compact and repair regularly — Access databases bloat over time
- Set the 2GB file size limit warning early — migrate before hitting it
- Split database: front-end (forms/queries) on user's machine, back-end (tables) on network share
- Back up .accdb files daily — no built-in replication or point-in-time recovery
- Use parameterized queries, not string concatenation — SQL injection applies to Access too
- Linked tables to SQL Server for multi-user scenarios (>5 concurrent users)
- Keep VBA in modules, not behind individual forms — easier to maintain and debug
- Error handling in every VBA procedure —
On Error GoTo ErrHandler
- Document table relationships, validation rules, and VBA in a design document
- Plan migration early — Access is a prototyping tool, not an enterprise platform
1---2name: ms-access3description: Build and manage Microsoft Access databases, queries, forms, reports, and VBA automation. Use when someone asks to "create Access database", "write Access queries", "build Access forms", "Access VBA macro", "migrate from Access", "Access report", "link Access to SQL Server", or "convert Access to web app". Covers table design, relationships, SQL queries, forms, reports, VBA automation, and migration strategies to modern platforms.4license: Apache-2.05---67# Microsoft Access89## Overview1011This skill helps AI agents work with Microsoft Access databases — designing tables, writing queries, building forms and reports, automating with VBA, and planning migrations to modern platforms. Access is widely used in small businesses and departments for data management, and agents should know how to build, maintain, and eventually migrate these systems.1213## Instructions1415### Step 1: Database Design1617```18Table: Customers19 CustomerID AutoNumber (Primary Key)20 FirstName Short Text (50)21 LastName Short Text (50)22 Email Short Text (100), Indexed (No Duplicates)23 Phone Short Text (20)24 Company Short Text (100)25 CreatedDate Date/Time, Default: =Now()26 IsActive Yes/No, Default: Yes2728Table: Orders29 OrderID AutoNumber (Primary Key)30 CustomerID Long Integer (Foreign Key -> Customers)31 OrderDate Date/Time, Default: =Date()32 TotalAmount Currency33 Status Short Text (20), Validation: In ("Pending","Shipped","Delivered","Cancelled")3435Table: OrderItems36 ItemID AutoNumber (Primary Key)37 OrderID Long Integer (Foreign Key -> Orders)38 ProductID Long Integer (Foreign Key -> Products)39 Quantity Integer, Validation: >040 UnitPrice Currency4142Table: Products43 ProductID AutoNumber (Primary Key)44 ProductName Short Text (100)45 Category Short Text (50)46 UnitPrice Currency47 UnitsInStock Integer, Default: 048 ReorderLevel Integer, Default: 104950Relationships (enforce referential integrity, cascade update, no cascade delete):51 Customers (1) --- (many) Orders52 Orders (1) --- (many) OrderItems53 Products (1) --- (many) OrderItems54```5556Design rules: AutoNumber PKs, proper data types with length limits, validation rules at table level, default values, indexes on frequently queried fields.5758### Step 2: Queries5960```sql61-- Join with aggregation: total sales per customer62SELECT c.CustomerID, c.FirstName & " " & c.LastName AS FullName,63 Count(o.OrderID) AS OrderCount, Sum(o.TotalAmount) AS TotalSpent64FROM Customers c INNER JOIN Orders o ON c.CustomerID = o.CustomerID65GROUP BY c.CustomerID, c.FirstName & " " & c.LastName66HAVING Sum(o.TotalAmount) > 100067ORDER BY TotalSpent DESC;6869-- Crosstab: monthly sales by category70TRANSFORM Sum(oi.Quantity * oi.UnitPrice) AS Revenue71SELECT p.Category72FROM Products p INNER JOIN OrderItems oi ON p.ProductID = oi.ProductID73INNER JOIN Orders o ON oi.OrderID = o.OrderID74WHERE o.OrderDate Between #2026-01-01# And #2026-12-31#75GROUP BY p.Category76PIVOT Format(o.OrderDate, "yyyy-mm");7778-- Inactive customers (no orders in 90 days)79SELECT c.CustomerID, c.FirstName, c.LastName, c.Email80FROM Customers c81WHERE c.CustomerID NOT IN (82 SELECT DISTINCT o.CustomerID FROM Orders o WHERE o.OrderDate >= DateAdd("d", -90, Date())83) AND c.IsActive = True;8485-- Action: mark overdue orders86UPDATE Orders SET Status = "Overdue"87WHERE Status = "Pending" AND OrderDate < DateAdd("d", -30, Date());8889-- Parameter query90SELECT o.OrderID, c.LastName, o.OrderDate, o.TotalAmount91FROM Orders o INNER JOIN Customers c ON o.CustomerID = c.CustomerID92WHERE o.OrderDate Between [Enter Start Date:] And [Enter End Date:];93```9495### Step 3: Forms & VBA9697```vba98' Search form with dynamic filtering99Private Sub btnSearch_Click()100 Dim strFilter As String101 If Not IsNull(Me.txtSearchName) Then102 strFilter = "LastName Like '*" & Me.txtSearchName & "*'"103 End If104 If Not IsNull(Me.cboStatus) Then105 If Len(strFilter) > 0 Then strFilter = strFilter & " AND "106 strFilter = strFilter & "Status = '" & Me.cboStatus & "'"107 End If108 Me.subResults.Form.Filter = strFilter109 Me.subResults.Form.FilterOn = (Len(strFilter) > 0)110End Sub111112' Validation before save113Private Sub Form_BeforeUpdate(Cancel As Integer)114 If IsNull(Me.txtEmail) Or Not Me.txtEmail Like "*@*.*" Then115 MsgBox "Please enter a valid email address.", vbExclamation116 Me.txtEmail.SetFocus117 Cancel = True118 End If119End Sub120```121122### Step 4: Reports & Export123124```vba125' Export report to PDF126Private Sub btnExportPDF_Click()127 DoCmd.OutputTo acOutputReport, "rptMonthlySales", acFormatPDF, _128 "C:\Reports\SalesReport_" & Format(Date, "yyyy-mm-dd") & ".pdf"129End Sub130131' Export query results to Excel132Public Sub ExportToExcel()133 Dim xlApp As Object, xlWb As Object, rs As DAO.Recordset134 Set xlApp = CreateObject("Excel.Application")135 Set xlWb = xlApp.Workbooks.Add136 Set rs = CurrentDb.OpenRecordset("qryMonthlySales")137 Dim i As Integer138 For i = 0 To rs.Fields.Count - 1139 xlWb.Sheets(1).Cells(1, i + 1).Value = rs.Fields(i).Name140 Next i141 xlWb.Sheets(1).Range("A2").CopyFromRecordset rs142 xlWb.Sheets(1).Columns.AutoFit143 xlWb.SaveAs "C:\Reports\MonthlySales_" & Format(Date, "yyyy-mm") & ".xlsx"144 xlWb.Close: xlApp.Quit145End Sub146```147148### Step 5: Automation149150```vba151' Import CSV and deduplicate against existing data152Public Sub ImportCSV()153 DoCmd.TransferText acImportDelim, , "ImportedData", "C:\Data\import.csv", True154 CurrentDb.Execute "INSERT INTO Customers (FirstName, LastName, Email) " & _155 "SELECT Trim(FirstName), Trim(LastName), LCase(Trim(Email)) " & _156 "FROM ImportedData WHERE Email NOT IN (SELECT Email FROM Customers)"157 CurrentDb.Execute "DROP TABLE ImportedData"158End Sub159160' Link to SQL Server161Public Sub LinkSQLServerTables()162 Dim tdf As DAO.TableDef, connStr As String163 connStr = "ODBC;DRIVER={ODBC Driver 17 for SQL Server};SERVER=myserver.database.windows.net;DATABASE=MyDB;UID=admin;PWD=password;"164 Set tdf = CurrentDb.CreateTableDef("dbo_Customers")165 tdf.Connect = connStr166 tdf.SourceTableName = "dbo.Customers"167 CurrentDb.TableDefs.Append tdf168End Sub169```170171### Step 6: Migration Strategy172173| Current | Target | Best For |174|---------|--------|----------|175| Access tables | SQL Server / Azure SQL | Data > 2GB, multi-user |176| Access forms | Power Apps | Low-code, mobile access |177| Access reports | Power BI | Advanced analytics |178| Access + VBA | Web app (Node/Python) | Internet access, APIs |179| Everything | Dataverse + Power Platform | Full MS ecosystem |180181## Examples182183### Example 1: Build an order management database184**User prompt:** "Create an Access database for tracking customer orders with products, order items, and a search form to find orders by customer name or date range."185186The agent will:1871. Create four tables (Customers, Orders, OrderItems, Products) with AutoNumber primary keys, proper data types, and validation rules1882. Set up relationships with referential integrity: Customers 1-to-many Orders, Orders 1-to-many OrderItems, Products 1-to-many OrderItems1893. Build a search form with text box for customer name, combo box for status, and date range fields1904. Add VBA `btnSearch_Click` handler that constructs a dynamic filter string and applies it to a subform displaying matching orders191192### Example 2: Generate a monthly sales report and export to PDF193**User prompt:** "Create an Access report showing monthly sales totals grouped by product category, with subtotals per category and a grand total, then export it as a PDF."194195The agent will:1961. Write a crosstab query using `TRANSFORM Sum(Quantity * UnitPrice)` pivoted by `Format(OrderDate, "yyyy-mm")` and grouped by product category1972. Design a report with Group Header/Footer on Category (showing subtotals), Detail section for monthly figures, and Report Footer for grand total1983. Add conditional formatting in the `GroupFooter_Format` event to highlight categories with sales under $1,000 in red1994. Implement a `btnExportPDF_Click` handler using `DoCmd.OutputTo` to save the report as a dated PDF file200201## Guidelines202203- Always compact and repair regularly — Access databases bloat over time204- Set the 2GB file size limit warning early — migrate before hitting it205- Split database: front-end (forms/queries) on user's machine, back-end (tables) on network share206- Back up .accdb files daily — no built-in replication or point-in-time recovery207- Use parameterized queries, not string concatenation — SQL injection applies to Access too208- Linked tables to SQL Server for multi-user scenarios (>5 concurrent users)209- Keep VBA in modules, not behind individual forms — easier to maintain and debug210- Error handling in every VBA procedure — `On Error GoTo ErrHandler`211- Document table relationships, validation rules, and VBA in a design document212- Plan migration early — Access is a prototyping tool, not an enterprise platform