在PowerBuilder7.0中,数据库中各表的内容通常用数据窗口对象显示输出。在输出过程中,我们可以通过程序设置过滤条件,达到对记录筛选查询的目的。但是如何让用户尽可能方便、灵活地指定过滤条件,使查询更加有效和迅速,是软件开发时必须要考虑的问题。经过不断探索和实践,我们找到了一种比较理想的方法,对任意数据窗口对象,只要在任意字段上输入一个值,然后,选择一个关系运算符,就可以得到一个与该字段的关系表达式,进一步,还可以产生一般的逻辑表达式作为过滤条件,进行过滤,达到查询的目的。这种生成查询条件的方法新颖、独特,实现的查询模块简单、实用,可挂接到任何PB应用软件中,从而大大提高软件的开发效率。下面介绍实现方法和具体步骤。
一、准备
1.首先建立一个应用程序对象serch,并对其open事件编写如下代码:
SQLCA.DBMS=ProfileString("PB.INI","Database","DBMS","")
SQLCA.DbParm=ProfileString("PB.INI","Database","DbParm","")
CONNECT USING SQLCA;
If sqlca.sqlcode <> 0 Then
MessageBox ("数据库连接失败", sqlca.sqlerrtext)
Halt //终止应用程序
End If
open(w_serch) //打开通用全字段查询窗口
2.在应用程序对象中定义以下两个全局变量:
string op_r //关系运算符变量
boolean cmx=False //复合查询标志变量
3.建立任意一个数据库(例如,Adaptive Server Anywhere 6.0数据库test.db),配置ODBC、Profile,建立需要的若干个表。如:nhxx(农户信息表)、tjzl(生产信息表)等。可以使用任何已有的数据库和表。
4.建立需要的数据窗口对象。例如:d_nhxx(农户信息、网格样式)、d_scxx(生产信息、自由表样式)等。可以使用任何已有的数据窗口对象。
5.建立一个弹出式菜单m_popup,其中只有一个菜单条选项m_r(操作符),具体菜单项定义如下表:
菜单项文本 Clicked事件代码 等于 op_r='=' 不等于 op_r='<>' 小于 op_r='<' 小于等于 op_r='<=' 大于 op_r='>' 大于等于 op_r='>=' 含有 op_r='in'
二、窗口设计
通用查询是在窗口中实现的,技术核心都在窗口的控件当中。
首先,建立一个如图1所示的窗口对象。
(图1)
其中包含一个数据窗口控件dw_1,四个图形按钮pb_1、pb_2、pb_3、pb_4,一个下拉列表ddlb_1,三个命令按钮cb_1、cb_2、cb_3,三个单行编辑框sle_1、sle_2、sle_3。
下拉列表框ddlb_1的作用是选择不同的表。在它的item属性中设置两项:"农户信息"和"生产信息",作为表名提示信息。当选择某一项时,通过代码设置与该表对应数据窗口对象。通过修改和添加item项以及相应代码,即可以在数据窗口控件动态挂接任意数据窗口对象,从而实行对任意表的查询。这里设置的"农户信息"、"生产信息"两项,只是例子。
当下拉列表框ddlb_1的选项改变时,产生selectionchanged事件,通过下面程序代码,确定与表对应的数据窗口对象,动态挂接到数据窗口控件dw_1上,显示其内容,以便下一步查询。
string t_n_s,t_n_d //表名提示信息,数据窗口对象名
t_n_s=ddlb_1.text //取出表名提示信息
CHOOSE CASE t_n_s //确定相应的数据窗口对象名
CASE "农户信息"
t_n_d="d_nhxx"
CASE "生产信息"
t_n_d="d_scxx"
END CHOOSE
parent.title="通用全字段查询窗口→"+t_n_s //重新设置窗口标题
parent.dw_1.dataobject=t_n_d //动态指定数据窗口对象
parent.dw_1.SetTransObject(SQLCA)
parent.dw_1.Retrieve()
sle_1.text=string(dw_1.RowCount()) //显示记录总数
sle_2.text=string(dw_1.GetRow()) //显示当前记录号
Parent.cb_1.TriggerEvent("clicked") //激活"擦除条件"的"clicked"事件
按钮cb_1(擦除条件)的作用是清除单行编辑框sle_3中的查询条件表达式,并使复合查询标志cmx置成"假"。复合查询标志cmx为"真"表示条件表达式中带有逻辑运算符(只使用AND),否则为简单的关系表达式。cb_1的clicked事件只有两行代码:
cmx=False //清复合查询标志
sle_3.text="" //清查询条件表达式
"开始查询"按钮cb_2的作用是从单行编辑框sle_3中取出查询条件表达式,并以此作为过滤条件,对数据窗口控件的内容进行过滤,实现查询。cb_2的clicked事件代码为:
dw_1.SetFilter(sle_3.text) //设置过滤条件
dw_1.Filter( ) //激活过滤
sle_1.text=string(dw_1.RowCount()) //显示记录总数
sle_2.text=string(dw_1.GetRow()) //显示当前记录号
为了在数据窗口控件中输入查询内容,同时又不破坏表中原来的数据,我们给数据窗口控件dw_1的itemchanged事件编写一行代码:
return 1 //拒绝数据
再给itemerror事件编写一行代码:
return 3 //拒绝数据并改变焦点
为显示当前记录号,在数据窗口控件dw_1的rowfocuschanged事件编写一行代码:
sle_2.text=string(dw_1.GetRow()) //显示当前记录号
接下来,最重要的一件事是对数据窗口控件dw_1的rbuttondown事件编码。当单击鼠标右键时,需要弹出一个关系描述符菜单,根据选择的菜单项,确定对应的关系运算符,并保存到全局变量op_r中。比如,选择"小于等于",得到关系运算符"<=",且赋给全局变量op_r。然后,取得当前列名、类型和当前控件的内容,组合成一个关系表达式。如果复合查询标志cmx的值为真,则用逻辑运算符"AND"组成逻辑表达式。关系表达式或逻辑表达式作为过滤条件字符串保存到sle_3.text中,显示在屏幕上并供"开始查询"按钮的clicked引用。
数据窗口控件dw_1的rbuttondown事件代码如下:
string FieldName,FieldType,FT,cts //列名,列类型,列类型的左四个字符,列信息
m_popup m_new //菜单变量声明
m_new=create m_popup //建立弹出菜单
m_new.m_r.PopMenu(parent.pointerX(),parent.pointerY()) //弹出关系符描述菜单
FieldName=GetColumnName() //取得当前列名
FieldType=Describe(FieldName+".ColType") //取得当前列类型
FT=left(FieldType,4) //列名左边四个字符
cts=GetText() //取得当前控件内容
If cmx Then sle_3.text=sle_3.text+" AND " //复合条件
If FT="numb" or FT="deci" or FT="long" or FT="real" THEN //形成过滤条件(数值型)
sle_3.text=sle_3.text+FieldName+op_r+cts
Else //形成过滤条件(C,d,t型)
If op_r="in" Then
sle_3.text=sle_3.text+"Pos("+FieldName+",'"+cts+"')>0"
Else
sle_3.text=sle_3.text+FieldName+op_r+"'"+cts+"'"
End If
End If
cmx=True //置复合条件标

