Expert guide
Add AI Summaries to Microsoft Access Reports
A short, approved narrative at the top of the report, built from the report's own numbers
Call us at +1 (385) 386-3860
Short answer: build a small aggregate query from the same data the report uses, send its figures to an AI model from VBA with instructions to use only those numbers, store the draft in a tblReportSummaries table keyed by report and period, let a manager edit and approve it on a form, then bind a text box in the report header to the approved text. Do not call the AI from report events. Our Access reports and forms service builds this into existing reports.
Access reports are precise and dense: grouped totals, page after page of rows. Managers read the first page and the totals; they want to know what changed and what needs attention. An AI-drafted summary at the top of the report answers that, as long as it is built on the report's own numbers and a person signs it off.
Design: Generate, Store, Approve, Display
Generate
A button or scheduled routine builds the input from an aggregate query and calls the AI.
Store
The draft goes into tblReportSummaries with the report name, period and status.
Approve
A manager edits the text on a form and marks it Approved.
Display
The report header shows the approved summary for the period being printed.
Keeping generation out of the report itself matters. Report Format and Print events fire repeatedly, during preview, paging and printing. An API call there runs many times, costs money, and can produce a different summary on each page.
Step 1: The Summary Table
| Field | Type | Notes |
|---|---|---|
| SummaryID | AutoNumber | Primary key |
| ReportName | Short Text | e.g. rptMonthlySales |
| PeriodStart, PeriodEnd | Date/Time | The range the report covers |
| InputText | Long Text | Exactly what was sent, for audit |
| DraftText | Long Text | AI output |
| ApprovedText | Long Text | Edited, approved version shown on the report |
| Status | Short Text | Draft, Approved |
| ApprovedBy, ApprovedOn | Text, Date/Time | Sign-off |
Step 2: Build the Input From an Aggregate Query
qrySalesSummaryByRegion (saved query, parameters from a form):
SELECT [Region],
SUM(IIf([OrderDate] >= [Forms]![frmReportMenu]![txtStart]
AND [OrderDate] <= [Forms]![frmReportMenu]![txtEnd],
[LineTotal], 0)) AS ThisPeriod,
SUM(IIf([OrderDate] >= DateAdd("yyyy", -1, [Forms]![frmReportMenu]![txtStart])
AND [OrderDate] <= DateAdd("yyyy", -1, [Forms]![frmReportMenu]![txtEnd]),
[LineTotal], 0)) AS SamePeriodLastYear
FROM qryOrderLines
GROUP BY [Region];Use the same base query (qryOrderLines here) that the report uses, so the summary and the detail cannot disagree.
Step 3: Generate the Draft With VBA
Public Sub DraftSalesSummary(ByVal pStart As Date, ByVal pEnd As Date)
On Error GoTo Fail
Dim db As DAO.Database, rs As DAO.Recordset
Dim inputText As String, draft As String, diff As Double
Set db = CurrentDb
Set rs = db.QueryDefs("qrySalesSummaryByRegion").OpenRecordset()
' (parameters resolve from frmReportMenu, which must be open)
Do While Not rs.EOF
diff = Nz(rs!ThisPeriod, 0) - Nz(rs!SamePeriodLastYear, 0)
inputText = inputText & rs!Region & ": " & _
Format(rs!ThisPeriod, "$#,##0") & " vs " & _
Format(rs!SamePeriodLastYear, "$#,##0") & " last year (" & _
Format(diff, "+$#,##0;-$#,##0") & ")" & vbCrLf
rs.MoveNext
Loop
rs.Close
draft = AskAI("Write a 3–4 sentence summary of regional sales for a " & _
"management report. Use only these figures; do not calculate " & _
"new ones. Mention the largest increase and largest decrease. " & _
"Plain business English.", inputText)
db.Execute "INSERT INTO tblReportSummaries " & _
"(ReportName, PeriodStart, PeriodEnd, InputText, DraftText, Status) VALUES (" & _
"'rptMonthlySales', #" & Format(pStart, "yyyy-mm-dd") & "#, #" & _
Format(pEnd, "yyyy-mm-dd") & "#, '" & Replace(inputText, "'", "''") & "', '" & _
Replace(draft, "'", "''") & "', 'Draft')", dbFailOnError
DoCmd.OpenForm "frmApproveSummary", , , "ReportName='rptMonthlySales' AND " & _
"PeriodStart=#" & Format(pStart, "yyyy-mm-dd") & "#"
Exit Sub
Fail:
MsgBox "Could not draft summary: " & Err.Description, vbExclamation
End SubAskAI is the reusable function from connecting MS Access to the OpenAI API.
Step 4: Approve, Then Display
frmApproveSummary shows InputText (read-only), DraftText, and an editable ApprovedText pre-filled with the draft.
An Approve button sets Status, ApprovedBy and ApprovedOn.
In rptMonthlySales, add a text box in the Report Header with Control Source =DLookup("ApprovedText","tblReportSummaries","ReportName='rptMonthlySales' AND PeriodStart=#" & Format([Forms]![frmReportMenu]![txtStart],"yyyy-mm-dd") & "# AND Status='Approved'").
Set Can Grow = Yes so the box expands to fit.
Add a small line under it: AI-drafted, approved by [ApprovedBy] on [ApprovedOn].
Exporting and Emailing the Report
DoCmd.OutputTo acOutputReport, "rptMonthlySales", acFormatPDF, _
"C:\Reports\Monthly Sales " & Format(Date, "yyyy-mm") & ".pdf", FalseCombine with automated email for a fully hands-off monthly pack, except for the approval click; see exporting Access reports to PDF with VBA and sending email from Access with Outlook.
Reports That Benefit Most
| Report | What the summary highlights |
|---|---|
| Monthly sales by region or rep | Biggest movers versus last year and budget |
| Open work orders and backlog | Ageing, technicians with the most overdue jobs |
| Inventory status | Items below reorder level, slow movers |
| Accounts receivable ageing | Customers moving into 60+ days, total at risk |
| Quality / NCR log | Recurring defect types, suppliers with rising issues |
Guardrails
Aggregates only: never send detail rows or personal data for a summary.
Same source query for summary and report.
Human approval before printing or sending.
Store input, draft and approved text so you can show how a statement was produced.
The same approach in Excel is described in automating report commentary with AI. For ad hoc questions beyond the report, consider DatabaseAI.
FAQ
AI summaries in Access reports FAQ
Design, accuracy and approval