Access开发:用子窗体实现右侧抽屉编辑面板

1.png

Hi,大家好!

做过 Web 后台的朋友,应该见过这样的编辑界面:点击一条记录,右侧展开一个面板,左侧原来的页面还在,只是变灰了。改完以后点确认,面板收起来,继续留在原来的位置。

这类界面一般叫“抽屉”。

Access 也能做。下面以姓名、部门和备注的编辑界面为例,做一个右侧展开的抽屉面板。

先看效果

初始界面只放一行示例信息和一个“编辑”按钮。

demo-list.png

Access 抽屉窗体的初始界面

点“编辑”,右侧出现编辑区,左侧背景变灰,编辑按钮暂时禁用。

demo-drawer.png

Access 右侧抽屉展开,显示姓名、部门和备注

“确认”和“取消”有一点区别:确认会把输入内容带回主窗体;取消、右上角关闭和 Esc 都只是关闭面板,下次打开时重新带入主界面的文字。

实现思路

我这里用主窗体显示示例文字,再把另一个窗体嵌入右侧的子窗体控件。平时隐藏这个控件,点“编辑”时显示,点“取消”时隐藏。

移动、显示和隐藏的是子窗体控件,不是另外打开一个弹出窗体。

01
第一步:手工创建编辑窗体

打开 Access 数据库,点击“创建 → 窗体设计”,按 F4 打开属性表,选中整个窗体,先设置这些属性:

属性设置值
记录源留空
默认视图单一窗体
记录选择器否
导航按钮否
分隔线否
滚动条纵向
按键预览(KeyPreview)是
宽度约 9.5 厘米

在设计区域空白处右键,选择“窗体页眉/页脚”,把这两个节显示出来。注意选的是“窗体页眉/页脚”,不是“页面页眉/页脚”。

页眉高度设为约 1.2 厘米,详细节约 6 厘米,页脚约 1.4 厘米,三个节的背景都设为白色。

接着手工放控件。命令按钮向导如果弹出来,点“取消”,后面统一写事件代码。

放置位置控件类型及名称标题或用途
窗体页眉左侧标签 lblTitle编辑信息
窗体页眉右侧按钮 cmdClose关闭
详细节第一行文本框 txtNickname输入姓名
详细节第二行文本框 txtDepartment输入部门
详细节第三行文本框 txtRemark输入备注
详细节下方标签 lblMessage显示校验提示
窗体页脚按钮 cmdCancel取消
窗体页脚按钮 cmdConfirm确认

这里的名称填在属性表“其他”选项卡的“名称”里,不能只改按钮上显示的文字。比如“确认”是按钮的标题,cmdConfirm 才是代码用的名称。

三个文本框左边的附属标签,标题分别改成“姓名”“部门”“备注”,标签名称不用改。三个文本框的“控件来源”都留空,不要填字段名,也不要填表达式。

排版可以直接照前面的效果图:输入框左边距约 2.2 厘米,宽约 6.5 厘米,三行的上边距分别为 0.6、2.0、3.3 厘米。备注框高度约 1.6 厘米,其余两个约 0.7 厘米。

备注框的“Enter 键行为”设为“字段中新行”,“滚动条”设为“纵向”。lblMessage 放在备注框下方,宽度留够,字体颜色设为红色,标题先写“提示”,运行时会清空。

“取消”和“确认”并排放在页脚右侧,不要放进详细节。这样窗口变矮时,中间的输入区可以滚动。

保存窗体,命名为 sfrmDrawerEditor,然后关闭设计视图。

02
第二步:手工创建主窗体

再次点击“创建 → 窗体设计”,新建第二个窗体。记录源同样留空,默认视图设为“单一窗体”,记录选择器、导航按钮、分隔线都设为“否”。

主窗体的滚动条设为“两者均无”,按键预览设为“是”。这次不需要页眉和页脚,所有控件都放在详细节,详细节背景设为白色。

把窗体宽度设为约 25.4 厘米,详细节高度设为约 14.8 厘米。先放这些控件:

控件类型名称标题
标签lblHeading用户信息
标签lblNameTitle姓名
标签lblDeptTitle部门
标签lblNameValue张三
标签lblDeptValue开发部
标签lblRemarkValue备注
命令按钮cmdEdit编辑
标签lblStatus就绪

lblHeading 放在左上角,字号调大一些。“姓名”和“部门”放在标题下面,lblNameValue、lblDeptValue 分别放在对应文字下方,“编辑”按钮放在右边。

lblRemarkValue 放在这行信息下方,宽约 7.5 厘米、高约 1.6 厘米;lblStatus 放在左下方。这两个标签也要保留,后面的代码会用到。

接着,在功能区的控件组中关闭“使用控件向导”,选择“子窗体/子报表”,在详细节右侧画一个子窗体控件。选中它的外框,按下面设置属性:

属性设置值
名称subDrawer
来源对象Form.sfrmDrawerEditor
链接主字段留空
链接子字段留空
左边距约 15.9 厘米
上边距0 厘米
宽度约 9.5 厘米
高度约 14.8 厘米
边框样式透明
可见否

子窗体控件自带的附属标签可以删除。选中 subDrawer,在“排列”选项卡里执行“置于顶层”,让它展开后能盖在主窗体原来的内容上。如果控件处于布局中,先执行“删除布局”。

这里容易混淆:subDrawer 是主窗体上的控件名,sfrmDrawerEditor 是被装进去的窗体名。两个名字都要对上。

保存主窗体,命名为 frmDrawerDemo。

03
第三步:给主窗体添加代码

主窗体保持在设计视图,点击“设计 → 查看代码”,进入它自己的窗体模块。

下面是主窗体模块的完整代码。新建窗体如果已经有 Option Compare Database,直接用下面内容替换默认代码,不要重复保留两份选项语句。这些代码不要放进标准模块。

Option Compare Database
Option Explicit

Private Const PANEL_WIDTH As Long = 5400

Private Sub Form_Load()
    Me!lblNameValue.Caption = "张三"
    Me!lblDeptValue.Caption = "开发部"
    Me!lblRemarkValue.Caption = ""
    Me!lblStatus.Caption = "就绪"
    Me!subDrawer.Visible = False
    Me.Section(acDetail).BackColor = RGB(255, 255, 255)
    LayoutDrawer
End Sub

Private Sub Form_Resize()
    LayoutDrawer
End Sub

Private Sub LayoutDrawer()
    Dim viewWidth As Long
    Dim viewHeight As Long
    Dim panelWidth As Long

    viewWidth = Me.InsideWidth
    viewHeight = Me.InsideHeight
    If viewWidth < 720 Or viewHeight < 720 Then
        Exit Sub
    End If

    panelWidth = PANEL_WIDTH
    If panelWidth > viewWidth Then
        panelWidth = viewWidth
    End If

    Me!subDrawer.Move viewWidth - panelWidth, 0, _
        panelWidth, viewHeight
End Sub

Private Sub cmdEdit_Click()
    Dim editor As Form

    If Me!subDrawer.Visible Then
        Exit Sub
    End If

    Set editor = Me!subDrawer.Form
    editor!txtNickname = Me!lblNameValue.Caption
    editor!txtDepartment = Me!lblDeptValue.Caption
    editor!txtRemark = Me!lblRemarkValue.Caption
    editor!lblMessage.Caption = ""

    LayoutDrawer
    Me!subDrawer.Visible = True
    Me!subDrawer.SetFocus
    editor!txtNickname.SetFocus
    Me!cmdEdit.Enabled = False
    Me.Section(acDetail).BackColor = RGB(184, 187, 192)
End Sub

Public Sub CloseDrawer()
    If Not Me!subDrawer.Visible Then
        Exit Sub
    End If

    Me!cmdEdit.Enabled = True
    Me!cmdEdit.SetFocus
    Me!subDrawer.Visible = False
    Me.Section(acDetail).BackColor = RGB(255, 255, 255)
End Sub

Private Sub Detail_Click()
    CloseDrawer
End Sub

Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
    If KeyCode = vbKeyEscape Then
        KeyCode = 0
        CloseDrawer
    End If
End Sub

回到设计视图,还要把事件接上。只粘贴过程代码,不代表属性表中的事件已经设置好了。

选中对象“事件”选项卡中的属性设置值
整个主窗体加载时(On Load)[事件过程]
整个主窗体调整大小时(On Resize)[事件过程]
整个主窗体键按下时(On Key Down)[事件过程]
cmdEdit 按钮单击时(On Click)[事件过程]
详细节单击时(On Click)[事件过程]

选详细节时,点击“详细”节标题条,再看属性表,不要把它设置成整个窗体的“单击时”。这里对应的过程名是 Detail_Click。

这段代码里,5400 的单位是 twips(缇),约为 9.5 厘米。抽屉左边距用“窗体内部可见宽度减去抽屉宽度”计算,因此调整窗口大小后仍然贴着右边。

还有一个顺序要留意:展开时,先把焦点交给子窗体,再禁用“编辑”;收起时,先启用“编辑”并把焦点交回去,再隐藏子窗体。否则容易遇到“不能禁用或隐藏具有焦点的控件”这类错误。

保存并关闭主窗体的设计视图。

04
第四步:给编辑窗体添加代码

右键 sfrmDrawerEditor,打开设计视图,点击“查看代码”,将下面完整代码放进它的窗体模块。同样不要重复保留默认的 Option 语句。

Option Compare Database
Option Explicit

Private Sub cmdConfirm_Click()
    Dim nickname As String

    nickname = Trim$(Nz(Me!txtNickname.Value, ""))
    If Len(nickname) = 0 Then
        Me!lblMessage.Caption = "请填写姓名。"
        Me!txtNickname.SetFocus
        Exit Sub
    End If

    Me.Parent!lblNameValue.Caption = nickname
    Me.Parent!lblDeptValue.Caption = Nz(Me!txtDepartment.Value, "")
    Me.Parent!lblRemarkValue.Caption = Nz(Me!txtRemark.Value, "")
    Me.Parent!lblStatus.Caption = "已确认"
    Me.Parent.CloseDrawer
End Sub

Private Sub cmdCancel_Click()
    Me.Parent.CloseDrawer
End Sub

Private Sub cmdClose_Click()
    Me.Parent.CloseDrawer
End Sub

Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
    If KeyCode = vbKeyEscape Then
        KeyCode = 0
        Me.Parent.CloseDrawer
    End If
End Sub

回到编辑窗体的设计视图,设置下面的事件:

选中对象“事件”选项卡中的属性设置值
cmdConfirm 按钮单击时(On Click)[事件过程]
cmdCancel 按钮单击时(On Click)[事件过程]
cmdClose 按钮单击时(On Click)[事件过程]
整个编辑窗体键按下时(On Key Down)[事件过程]

Me.Parent 指的是装着这个编辑窗体的主窗体,所以可以直接调用主窗体里的公开过程 CloseDrawer。这也是前面把它写成 Public Sub 的原因。

“确认”会更新主窗体标签,“取消”和“关闭”只收起面板。再次点“编辑”时,主窗体会重新给三个输入框赋值,未确认的输入就不会保留下来。

保存编辑窗体。它需要嵌在主窗体里运行,不要单独打开它测试按钮,否则 Me.Parent 找不到对应的主窗体。

05
第五步:编译并测试

按 Alt + F11 打开 VBA 编辑器,点击“调试 → 编译”。如果提示找不到成员或控件,先回设计视图检查控件的“名称”,尤其是 subDrawer,不要只检查窗体名。

关闭 VBA 编辑器,从导航窗格打开 frmDrawerDemo,按下面顺序试一遍:

  1. 初始显示“张三”“开发部”,右侧编辑区隐藏。

  2. 点“编辑”,右侧出现三个输入框,带入当前文字,主窗体背景变灰,“编辑”按钮不可再点。

  3. 把姓名改成“李四”,点“取消”。主窗体仍然显示“张三”;再次点“编辑”,输入框里也应恢复“张三”。

  4. 清空姓名,点“确认”。抽屉不关闭,下方出现“请填写姓名。”。

  5. 填入姓名、部门和备注,点“确认”。抽屉收起,主窗体文字更新,下方显示“已确认”。

  6. 再展开,分别试右上角“关闭”、Esc,以及主窗体左侧灰色空白区域,应该都能收起。灰色区域要点详细节空白处,不是标签文字。

  7. 关闭主窗体再打开,加载事件会重新显示初始示例文字。

最后拖动 Access 窗口边缘,确认抽屉仍然贴右。示例的输入框按约 9.5 厘米宽的面板排版,窗口过窄时还需要另外调整内部控件,不能只靠移动外框解决。

这里的灰色只是详细节背景色,不是透明遮罩;也没有添加滑动动画。如果接到现有业务窗体,后台还有其他按钮、输入框或快捷键,要一起限制操作,不能只改背景色。

到这里,右侧抽屉就做好了:展开时带入当前文字,确认后更新主界面,取消则保留原来的内容。示例中的确认按钮更新的是标签;用于实际业务时,在确认事件中接入自己的保存逻辑。

demo-narrow.png


技术培训

  • Access VBA 从入门到精通(线上/线下均可)

  • Access + SQL Server 企业级开发实战

  • Access 系统性能优化与架构设计

  • AI + Access 融合开发专题培训

定制开发

  • 企业 ERP / CRM / 进销存 / WMS / MES 等系统开发

  • 旧 Access 系统升级、性能优化与架构重构

  • AI 能力集成到现有 Access 业务系统

技术支持

  • 代码审查与重构建议

  • 疑难问题远程诊断

  • 一对一技术辅导