在现代 Web 管理后台中,To Do List(待办事项)几乎是标配功能。用户可以快速添加任务、勾选完成、一键删除,操作流畅、反馈即时。
在 Access 中,利用连续子窗体的特性,完全可以实现类似的交互效果。本文将手把手带你从建表到创建窗体,再到编写事件代码,完整还原一个 Web 风格的 To Do List。
功能清单:
- 输入框 + 按钮添加待办
- 每行有复选框、任务文本、删除按钮
- 勾选后自动变灰斜体,排到列表底部
- 底部显示完成进度统计
- 支持一键清除已完成事项
技术方案概览
| 特征 | 说明 |
|---|---|
| 实现方式 | 手工创建窗体 + VBA 事件代码 |
| 数据存储 | Access 本地表 tblTodoList |
| UI 方案 | 主窗体 + 连续子窗体 |
| 兼容版本 | Access 2010 / 2013 / 2016 / 2019 / 365 |
之所以选择连续子窗体而不是 ListBox,是因为连续窗体的每一行都可以放置独立控件------复选框和删除按钮都可以直接操作当前行的记录,交互体验与 Web 版非常接近。
实现步骤
第一步:创建数据表
在 Access 中新建表 tblTodoList,字段结构如下:
| 字段 | 类型 | 说明 |
|---|---|---|
| ID | 自动编号 | 主键 |
| TaskText | 文本 (255) | 任务内容 |
| IsDone | 是/否 | 是否完成 |
| CreatedDate | 日期/时间 | 创建时间,默认 Now() |
表结构简单,只保留核心字段。如果后续需要优先级、分类、截止日期等,可以自行扩展。

第二步:创建子窗体 frmTodoSub
子窗体 frmTodoSub 是一个绑定到 tblTodoList 的连续窗体,用来展示待办列表的每一行。
创建步骤:
- 新建一个空白窗体,保存为
frmTodoSub - 设置窗体属性:
- 记录源 :
SELECT * FROM tblTodoList ORDER BY IsDone, ID DESC - 默认视图:连续窗体
- 滚动条:仅垂直
- 记录选定器:否
- 导航按钮:否
- 允许添加:否(通过主窗体按钮添加)
- 允许删除:否(通过按钮控制删除)
- 记录源 :
- 在主体节中依次添加以下控件:
| 控件 | 类型 | 说明 |
|---|---|---|
chkDone |
复选框 | 绑定 IsDone 字段,点击即切换完成状态 |
txtTaskText |
文本框 | 绑定 TaskText 字段,只读、无边框、透明背景 |
cmdDelete |
命令按钮 | 显示 "X",点击删除当前行记录 |
子窗体的查询按 IsDone, ID DESC 排序,未完成的任务始终排在前面,同组内新任务在上。

第三步:创建主窗体 frmTodoList
主窗体 frmTodoList 是一个普通的单一窗体,布局从上到下:
| 区域 | 控件 | 说明 |
|---|---|---|
| 标题 | lblTitle |
"To Do List",16pt 粗体 |
| 分隔线 | lnSep |
浅灰色水平线 |
| 输入行 | txtNewTodo + cmdAddTodo |
文本框 + 蓝色添加按钮 |
| 待办列表 | subTodos |
嵌入子窗体 frmTodoSub |
| 底部 | cmdClearDone + lblStats |
清除按钮 + 完成统计 |
创建步骤:
- 新建一个空白窗体,保存为
frmTodoList - 设置窗体属性:
- 标题:To Do List
- 默认视图:单一窗体
- 滚动条:无
- 记录选定器:否
- 导航按钮:否
- 自动居中:是
- 按上表从上到下依次添加控件
- 将子窗体控件
subTodos的源对象 设为frmTodoSub
主窗体的 Form_Load 事件设置条件格式------当 IsDone = True 时,任务文本变灰色斜体:
vb
With fSub!txtTaskText
.FormatConditions.Delete
With .FormatConditions.Add(acExpression, , "[IsDone]=True")
.ForeColor = RGB(160, 160, 160)
.FontItalic = True
End With
End With
这是 Access 条件格式的标准用法。它不支持删除线(strikethrough),但灰色 + 斜体已经能清晰区分完成和未完成的任务。

第四步:编写事件代码
打开主窗体 frmTodoList 的 VBA 代码模块,写入以下代码。按钮点击、窗体加载等事件通过 Private Sub 直接响应,逻辑清晰、维护方便。
vb
Private Sub cmdAddTodo_Click()
Dim sText As String
sText = Trim(Nz(Me.txtNewTodo, ""))
' 空文本不添加
If Len(sText) = 0 Then
Me.txtNewTodo.SetFocus
Exit Sub
End If
' 使用 Recordset.AddNew 添加记录, 避免 SQL 注入风险
Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset("tblTodoList", dbOpenDynaset)
rs.AddNew
rs!TaskText = sText
rs!IsDone = False
rs!CreatedDate = Now
rs.Update
rs.Close
Set rs = Nothing
' 清空输入框, 刷新列表
Me!txtNewTodo.value = ""
Me!txtNewTodo.SetFocus
Me!subTodos.Form.Requery
Todo_UpdateStats
End Sub
Private Sub cmdClearDone_Click()
Dim lCnt As Long
lCnt = Nz(DCount("*", "tblTodoList", "IsDone = True"), 0)
If lCnt = 0 Then
MsgBox "没有已完成的事项需要清除。", vbInformation
Exit Sub
End If
If MsgBox("确定清除 " & lCnt & " 条已完成事项?", _
vbQuestion + vbYesNo, "确认清除") = vbNo Then
Exit Sub
End If
CurrentDb.Execute "DELETE FROM tblTodoList" & _
" WHERE IsDone = True", dbFailOnError
Me!subTodos.Requery
Me.subTodos.SourceObject = Me.subTodos.SourceObject
Todo_UpdateStats
End Sub
Private Sub Form_Load()
On Error Resume Next
Dim fSub As Form
Set fSub = Me.Form
' 条件格式: 完成项 → 灰色斜体
With fSub!txtTaskText
.FormatConditions.Delete
With .FormatConditions.Add(acExpression, , "[IsDone]=True")
.ForeColor = RGB(160, 160, 160)
.FontItalic = True
End With
End With
On Error GoTo 0
Todo_UpdateStats
End Sub
' ---- 刷新底部统计标签 ----
Public Function Todo_UpdateStats() As Boolean
On Error Resume Next
Dim lTotal As Long, lDone As Long
lTotal = Nz(DCount("*", TABLE_NAME), 0)
lDone = Nz(DCount("*", TABLE_NAME, "IsDone = True"), 0)
Forms(FORM_NAME)!lblStats.Caption = lDone & " / " & lTotal & " completed"
On Error GoTo 0
Todo_UpdateStats = True
End Function

总结
本文介绍了如何在 Access 中实现一个功能完整的 Web 风格 To Do List。核心技术点包括:
- 通过连续子窗体实现每行独立控件(复选框 + 文本 + 删除按钮)
- 手工创建窗体布局,直观可控
- 事件代码写在窗体代码模块中,用
Private Sub直接响应按钮和窗体事件 - 条件格式实现完成项视觉反馈(灰色斜体)
- 使用
Recordset.AddNew添加记录,避免 SQL 注入风险
测试环境:Access 2016 / 2019 / 365,Windows 10 / 11