今天给大家分享:在窗体中用列表框实现多级筛选
在某些时候,由于数据量比较大,我们为了找到需要的数据,而查找的条件又不是太清楚的时候,就希望能够逐步缩小查询结果的范围,能在查询结果的基础上再次进行查询。实际上就是一个多条件查询,只是查询条件的提交是多次的,而不是把多个条件一次性提交。
在某些时候,由于数据量比较大,我们为了找到需要的数据,而查找的条件又不是太清楚的时候,就希望能够逐步缩小查询结果的范围,能在查询结果的基础上再次进行查询。这种查询方式实际上就是一个多条件查询,只是查询条件的提交是多次的,而不是把多个条件一次性提交。
一般来说在窗体中实现查询功能有两种方式:一种是先加载所有记录,然后通过窗体的筛选器对记录集数据进行筛选来实现查询功能;另一种方式是将窗体的记录源设为SQL语句,动态改变该SQL语句的WHERE条件子句来实现查询。
现在通过示例程序来对其进行说明,由于此功能是对数据的处理,所以需要基于一个有数据的表,这里我们用如图1、图2所示的“产品”表来做为例程表:
(图1)
(图2)
我们需要根据表中的“供应商”和“类别”来进行多层查询,首先基于该表用向导创建一个数据表视图的窗体(图3),将其命名为“子窗体”:
(图3)
然后再创建一个空白窗体,向窗体中添加控件,完成后的效果如图4所示:
(图4)
在窗体中添加控件属性如表格
控件类型 | 控件名称 | 其它属性 | 其它说明 | |
属性名 | 属性值 | |||
列表框 | lstProvider | 行来源类型 | 表/查询 | 显示供应商列表 |
行来源 | SELECT TOP 1 ‘(全部)’ FROM 产品 UNION SELECT DISTINCT 供应商 FROM 产品; | |||
默认值 | “(全部)” | |||
更新后 | [事件过程] | |||
标签 | lstProvider_Label | 标题 | 供应商 | 绑定标签 |
列表框 | lstSort | 行来源类型 | 表/查询 | 显示产品类别列表 |
行来源 | SELECT TOP 1 ‘(全部)’ FROM 产品 UNION SELECT DISTINCT 供应商 FROM 产品; | |||
默认值 | “(全部)” | |||
更新后 | [事件过程] | |||
标签 | lstSort_Label | 标题 | 产品类别 | 绑定标签 |
子窗体 | fsubDetail | 源对象 | 子窗体 |
说明:
这里列表框的行来源中的SQL语句是一个联合查询,其表示的含义是:SELECTTOP 1’(全部)’FROM 产品 (这一句就是用于把“(全部)”这一项添加到列表中)
SELECT DISTINCT 供应商 FROM 产品 (这一句是从产品表中取供应商字段的数据,DISTINCT关键字的用途是排除重复值)UNION关键字的作用是把两个结构相同的表中的数据合并(重复值被排除)
然后我们在此窗体的类模块中加入以下子过程(用筛选器):
Sub ApplyFilter()
Dim strWhere As String
If Me.lstProvider <> "(全部)" Then strWhere = "供应商='" & Me.lstProvider & "'"
If Me.lstSort <> "(全部)" Then strWhere = strWhere & " AND 类别='" & Me.lstSort & "'"
If strWhere <> "" Then
If strWhere Like " AND *" Then strWhere = Mid(strWhere, 6)
Me.fsubDetail.Form.Filter = strWhere
Me.fsubDetail.Form.FilterOn = True
Else
Me.fsubDetail.Form.Filter = ""
Me.fsubDetail.Form.FilterOn = False
End If
End Sub
前面这个是用筛选器实现的方法,如果要用重置记录源的方法,则子过程的代码如下:
Sub ApplyFilter()
Dim strWhere As String
If Me.lstProvider <> "(全部)" Then strWhere = "供应商='" & Me.lstProvider & "'"
If Me.lstSort <> "(全部)" Then strWhere = strWhere & " AND 类别='" & Me.lstSort & "'"
If strWhere <> "" Then
If strWhere Like " AND *" Then strWhere = Mid(strWhere, 6)
strWhere = " WHERE " & strWhere
End If
Me.fsubDetail.Form.RecordSource = "SELECT * FROM 产品" & strWhere
End Sub
从上面两个子过程的代码中我们可以看到其实两种方法实现起来非常相似,其中生成的条件字符串完全是一样的。那种两种方式有什么差别呢?使用筛选器方法数据只加载一次,在关闭窗体之前所有的筛选都是对保存在内存中的记录集进行操作,这样在网络环境中应用时减少了网络通信的频率;而使用重置数据源的方式一般每次只加载一部分数据。所以筛选器方式用在数据量不是太大但查询频繁的情况,重置数据源的方式则用在数据量大但查询不频繁的情况。
由于我们需要在2个列表框任意一个选中后对数据进行查询,所以我们需要在两个列表框的更新事件中对这个子过程进行调用:
Private Sub lstProvider_AfterUpdate()
Call ApplyFilter
End Sub
Private Sub lstSort_AfterUpdate()
Call ApplyFilter
End Sub
最终实现的效果如图5所示:
(图5)
大家快去试一下吧!