PB7.0通用选字段查询窗口的设计
本文介绍一个在PB7.0下实现的通用查询窗口,可实现对任意表的查询,输出字段、排序字段、查询条件都可以随意指定。功能丰富,使用方便、灵活,可挂接到任何PB应用软件中,从而大大提高软件的开发效率。
本文是《PB7.0通用全字段查询技术》(计算机世界周报2000年第3期)的姊妹篇。两篇文章介绍的技术方案不同,做出查询窗口的风格、形式和用法也不同,可同时使用,丰富系统功能。
在PB7.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.建立任意一个数据库(例如,Adaptive Server Anywhere 6.0数据库test.db),配置ODBC、Profile,建立需要的若干个表。如:nhxx(农户信息表)、tjzl(生产信息表)等。可以使用任何已有的数据库和表。
二、窗口设计
通用查询是在窗口中实现的,技术核心都在窗口的控件当中。
首先,建立一个窗口对象w_serch。其中包含一个数据窗口控件dw_1,一个下拉列表ddlb_1,三个命令按钮cb_3、cb_4、cb_5,一个单行编辑框sle_2和一个标签tab_1。
标签tab_1的第一个标签页tabpage_1上放置一个列表框lb_1、一个单行编辑框sle_1和两个命令按钮cb_1、cb_2。
窗口和第一个标签页tabpage_1如下图所示。
为进行窗口各控件之间的数据传递,声明以下四个实例变量:
string s_tn //表名变量
string s_seq="A" //排序方式变量(默认升序)
string s_cn,s_ct,s_cp //字段名、字段类型、比较符变量
string t_c[50,3] //存放表中各“字段名”、“字段类型”和“字段标题”
窗口中下拉列表框ddlb_1的作用是选择不同的表。在它的item属性中设置两项:“农户信息"和“生产信息”,作为表名提示信息。当选择某一项时,通过代码将对应的表名送实例变量s_tn。通过修改和添加item项以及相应代码,即可选择不同的表,从而实现对任意表的查询。这里设置的“农户信息”、“生产信息”是两个例子。
当下拉列表框ddlb_1的选项改变时,产生selectionchanged事件,通过下面程序代码,将选定的表名送变量s_tn,该表的各个字段名、字段类型、字段标题送数组t_c,各字段标题添加到三个标签页上的列表框lb_1、lb_2、lb_3中。其中,数组t_c的第一个下标表示字段序号,第二个下标值1、2、3分别表示字段名、字段类型和字段标题。这里用到了系统表pbcatcol,它的字段pbc_tnam、pbc_cnam、pbc_jtfy和pbc_hdr值分别存储表名、字段名、字段类型和字段标题。
integer i //循环变量(数组下标)
CHOOSE CASE ddlb_1.text //根据表名提示信息,确定相应的表名
CASE "农户信息"
s_tn="nhxx"
CASE "生产信息"
s_tn="tjzl"
END CHOOSE
DECLARE tab_col CURSOR FOR //定义游标
SELECT "pbcatcol"."pbc_tnam", //表名
"pbcatcol"."pbc_cnam", //字段名
"pbcatcol"."pbc_jtfy", //字段类型
"pbcatcol"."pbc_hdr" //字段标题
FROM "pbcatcol"
WHERE "pbcatcol"."pbc_tnam" = :s_tn ;
OPEN tab_col; //打开游标
i=1
//字段名、类型、标题送数组
FETCH tab_col into :s_tn,:t_c[i,1],:t_c[i,2],:t_c[i,3];
DO While SQLCA.SQLCode=0
//设置列表信息(字段标题)
tab_1.tabpage_1.lb_1.AddItem(t_c[i,3])
tab_1.tabpage_2.lb_2.AddItem(t_c[i,3])
tab_1.tabpage_3.lb_3.AddItem(t_c[i,3])
i++
FETCH tab_col into :s_tn,:t_c[i,1],:t_c[i,2],:t_c[i,3];
Loop
CLOSE tab_col; //关闭游标
第一个标签页tabpage_1上列表框lb_1列出当前表各字段的标题,用于确定输出字段。为了能按windows资源管理器方式选择字段,应设置它的multiselect属性。
命令按钮cb_2的作用是将lb_1中选中的字段标题转换为字段名,形成字段表列放到单行编辑框sle_1中。其clicked代码如下:
int k //循环计数器
For k=1 to lb_1.totalitems() //列表项目数
If lb_1.state(k)=1 then //该项被选中
If sle_1.text="" then
//得到字段名
sle_1.text=t_c[k,1]
Else
//拼接列名
sle_1.text=sle_1.text+","+t_c[k,1]
End If
End If
Next
命令按钮cb_1的作用是清除单行编辑框sle_1的内容。clicked代码只有一行:
sle_1.text=""
第二个标签页tabpage_2如下图所示。其中有一个列表框lb_2,一个单行编辑框sle_3,一个命令按钮cb_6,两个单选按钮rb_1和rb_2。
列表框lb_2列出当前表的各字段标题。单击某一项时,产生selectionchanged事件,下面代码得到字段名,添加s_seq变量值(“A"或“D"),形成排序字符串放到单行编辑框sle_3。
integer k //循环计数器
For k=1 to lb_2.totalitems() //列表项目总数
If lb_2.state(k)=1 then //该项被选中
If sle_3.text="" then
//形成排序字符串
sle_3.text=t_c[k,1]+" "+s_seq
Else
//拼接排序字符串
sle_3.text=sle_3.text+","+t_c[k,1]+" "+s_seq
End If
End If
Next
单选按钮rb_1、rb_2用来设置排序方式变量s_seq的值,clicked代码分别为
s_seq="A" (升序)和
s_seq="D" (降序)
命令按钮cb_6的作用是清除单行编辑框sle_3的内容。clicked代码为
sle_3.text=""
第三个标签页tabpage_3如图3所示。它上面放有一个列表框lb_3,一个下拉列表框ddlb_2,两个单行编辑框sle_4和sle_5,两个单选按钮rb_3和rb_4,两个命令按钮cb_8和cb_9。
列表框lb_3列出当前表的各字段标题。单击某一项时,产生selectionchanged事件,通过下面代码将对应的字段名、字段类型分别送实例变量s_cn和s_ct。
int k //循环计数器
For k = 1 to lb_3.totalitems() //列表项目数
If lb_3.state(k)=1 then //该项被选中
s_cn=t_c[k,1] //取出字段名
s_ct=t_c[k,2] //取出字段类型
End If
Next
下拉列表框ddlb_2列出常用关系运算符(比较符)的描述文字,选择某一项后,产生selectionchanged事件,通过下面代码得到相应的关系运算符送实例变量s_cp。
CHOOSE CASE ddlb_2.text
CASE "等于"
s_cp=" = "
......
CASE "含有"
s_cp="in"
END CHOOSE
单行编辑框sle_5用来输入比较内容。
单击按钮cb_8(选中),通过以下代码形成条件表达式字符串送单行编辑框sle_4。
If s_ct="24" THEN
//形成条件表达式字符串(数值类)
sle_4.text=sle_4.text+s_cn+s_cp+sle_5.text
Else
//形成条件表达式字符串(字符类)
If s_cp="in" Then
sle_4.text=sle_4.text+"Pos("+s_cn+",'"+sle_5.text+"')>0"
Else
sle_4.text=sle_4.text+s_cn+s_cp+"'"+sle_5.text+"'"
End If
End If
在形成条件表达式字符串时,要根据字段类型是数值类还是字符类决定是否用引号定界符。字段类型24对应于binary、integer、numeric型,25对应于char、varchar、date型。如果比较符为“in”,表示“包含”关系,条件表达式字符串中要使用pos函数。
单选按钮rb_3、rb_4用来在sel_4中添加逻辑运算符,clicked代码分别为
sle_4.text=sle_4.text+" AND " (添加逻辑运算符)和
sle_4.text=sle_4.text+" OR " (添加逻辑运算符)
命令按钮cb_9的作用是清除单行编辑框sle_4的内容。clicked代码为
sle_4.text=""
窗口中“查询”按钮cb_3的作用是根据选定的表名和第一个标签页上单行编辑框sle_1的内容形成SQL句法,动态建立数据窗口对象,然后利用第二个标签页上单行编辑框sle_3和第三个标签页上单行编辑框sle_4的内容进行排序和过滤,达到查询的目的。代码如下:
string s_sql,s_err,s_syn,s_sty
s_sql="SELECT "+tab_1.tabpage_1.sle_1.text+" FROM "+s_tn
s_sty="Style(Type=Grid Horizontal_Spread = 80)"
s_syn=SQLCA.SyntaxFromSQL(s_sql,s_sty,s_err) //形成SQL句法
dw_1.Create(s_syn) //建立数据窗口对象
dw_1.SetTransObject(SQLCA)
dw_1.Retrieve() //输出结果
dw_1.SetFilter(tab_1.tabpage_3.sle_4.text)
dw_1.Filter( ) //进行过滤
dw_1.SetSort(tab_1.tabpage_2.sle_3.text) //进行排序
dw_1.Sort()
sle_2.text=string(dw_1.RowCount()) //显示记录数
窗口中"打印"按钮cb_5的clicked事件代码为dw_1.print()。
窗口中"退出"按钮cb_4的clicked事件代码为close(parent)。
三、使用
前面设计的查询窗口可作为一个通用模块挂接到任意一个PB应用软件当中,挂接时只要修改窗口中下拉列表框ddlb_1的item属性和selectionchanged代码,然后打开该窗口即可。
窗口打开后,通常要做的第一件事,是单击窗口中“表”右边的下拉列表,选择需要的表。表被选中后,相应的字段标题便显示在三个标签页的列表框中。接下来可选择输出字段、排序字段,指定条件进行查询。
1、选择输出字段
单击“字段选择”标签页,在列表框中选择需要的字段。选择方法与windows资源管理器选择文件的方法相同。即,按住Ctrl键,再单击,分别选择,按住Shift键再单击,或拖动,连续选择。单击“选中”按钮,选择生效。单击“清除”按钮,取消选择。
2、设置查询条件
单击“检索条件”标签页,在列表框单击某一字段,单击“比较符”下拉列表框,选择一个比较符(关系运算符),在“内容”下边的单行编辑框中输入要查询的部分或全部信息,单击“选中”按钮,部分条件表达式填入下面的单行编辑框。
如果继续指定条件,可单击单选按钮“并且”或“或者”,对应的逻辑运算符填入单行编辑框,然后再用前面的方法指定部分条件。
单击“清除”按钮,清除单行编辑框中的条件表达式,输出全部记录。
指定的查询条件在单行编辑框中,可左右滚动查看,也可直接修改。
3、设置排序字段
单击“排序设置”标签页,单击排序方式的“升序”或“降序”单选框,在列表框单击某一字段或多个字段,查询结果可按指定字段和方式排序。
单击“清除”按钮,清除排序字段,按自然顺序输出。
4、开始查询
单击窗口“查询”按钮,查询结果显示在数据窗口控件中。
5、打印
单击窗口“打印”按钮,可打印数据窗口控件中的查询结果。