
本文于2023年6月17日首发于其他平台本人同名公众号,更多文章案例请搜索关注!
☆本期内容概要☆
用户窗体设置:单据查询
大家好,我是冷水泡茶,前段时间我们持续分享了好多期收费管理系统的设计过程,感兴趣的朋友可以翻看往期文章,今天我们继续。
今日目标:单据明细查询
我们录入了收费结算单,查询功能是必不可少的,我们先看一下效果,然后再一起来做吧。

我们要建立一个用户窗体,其上放置一些命令按钮、复合框、Listview等,用来展示数据。要建一个这样的窗体,还是比较费功夫的,好在我们前面有现成的(Excel VBA 凭证打印/SQL连接Eexcel文件/Listview控件/CommandButton命令按钮控件),直接复制过来就行了。方法是打开这个凭证打印文件(Excel财务记账模板(凭证打印).xlsm),进入代码编辑窗口,找到目标窗体Usf_VoucherList,直接把它拖到我们的收费系统里来,名字都不用改。

然后,我们就要修改代码。
主菜单usf_main增加命令按钮“明细查询”:
Private Sub CmdQuery_Click() tempValue = "收费单查询" Usf_VoucherList.Show unload meEnd Sub
这里增加了一个公共变量tempValue,临时值,在Usf_VoucherList窗体启动时调用它来显示窗体的Caption,Lbtitle的Caption。
在Settings表里,增加一个项目字段“Company”,公司名称,可以修改成不同的公司名称。

增加了一个自定义函数:Getinformation,用来取得Settings表中第2列项目对应的第3列的值。
Function GetInformation(fieldName As String) Dim lastRow As Integer Dim lastCol As Integer Dim ws As Worksheet Dim arr() Set ws = ThisWorkbook.Sheets("Settings") ws.Activate With ws lastRow = .UsedRange.Rows.Count lastCol = .UsedRange.Columns.Count arr = .Range(Cells(1, 1), Cells(lastRow, lastCol)).Value For i = 1 To lastRow If arr(i, 2) = fieldName Then GetInformation = arr(i, 3) Exit Function End If Next End WithEnd Function
代码解析:把Settings表的数据读入数组arr,然后循环数组2列,寻找与参数fieldName 相等的值所在的行,取对应第3列的值。
修改了自定义函数Pxy,原来是用工作表函数match来取值的,有时候打开了别的工作表,可能会报错。
'Function Pxy(arr(), field As String)' Pxy = Application.WorksheetFunction.Match(field, arr, 0)'End FunctionFunction Pxy(arr() As Variant, searchValue As Variant) As Long t = LBound(arr) t = 1 - t For i = LBound(arr) To UBound(arr) If arr(i) = searchValue Then Pxy = i + t Exit Function End If Next Pxy = -1 ' 如果未找到值,则返回 -1End Function
代码解析:前面三行是注释掉的原函数。现在改为循环数组来取得位置。函数中有个变量t,它的作用是避免数组下标不是从1开始而造成的函数值错误,我们是要取得字段的位置,而不是下标。
修改数据库结构,增加“月份”字段,放在“备注”字段前,写两行代码批量更新一下月份的值:
Sub updateMonth() dataFile = ThisWorkbook.Path & "\收费管理系统数据库.accdb" SQL = "update tb收费明细 set 月份=format(日期,'YYYYMM')" Call ExecuteSQL(dataFile, SQL)End Sub
同时,修改AddAndModify窗体保存按钮代码,补写月份值:

再把AddAndModify窗体启动时,Listview的字段宽度调整一下,隐藏月份。月份通过format函数自动补全,不用手输。
修改Usf_VoucherList启动代码,改动比较大,代码也较多,我放第二条吧。这里挑一些主要的解释一下。
本窗体使用两个ListView,上面是收费单记录列表,一个单号一条记录,下面是收费单明细,当点击上面收费单记录时,下面显示详细信息。
这里关键的是几条SQL查询语句:
sql1 = "select * from tb收费明细 where ID in " _ & "(select min(ID) from tb收费明细 group by 单号) order by 单号"sql2 = "select 日期,单号,sum(金额) as 金额 from tb收费明细 group by 日期,单号"SQL = "select a.日期,a.单号,a.客户,a.渠道,a.科室,a.医生,b.金额,a.月份 from (" _ & sql1 & ") as a left join (" & sql2 & ") as b " _ & "on a.日期 = b.日期 and a.单号 = b.单号" _ & " order by a.月份,a.单号"
代码解析:
1、sql1,每个单号选择ID最小的1条记录
2、sql2,把金额按日期、单号汇总
3、SQL,把sql1和sql2通过left join拼接起来,形成一个记录列表。
利用字典取得月份列表,赋值给CmbMonth的list。
然后就是把数据加载到LvVoucherList。
最后,添加下面ListView的表头字段。通过SQL查询一条tb明细表的记录,这里目的是取得表头字段,所以不需要查询所有记录。
其他一些按钮也有修改,就不详细说了,代码见第二条。
好,今天就这样吧。欢迎点赞、留言、分享,谢谢大家,我们下期再会。