1 用VFP系统命令进行查询操作的不便之处
在Visual ForxPro数据管理系统中,设置了查询命令和查询向导,可以进行数据库表记录的选择、分组查询、多表查询及查询结果数据的输出等功能,能够产生独立的查询文件,通过调用该文件可得到所需要的数据。但这些分散的功能命令和文件不适用于数据库应用程序的查询操作,使用这种方式设计的数据库应用程序,用户必须熟知VFP系统命令、操作、数据类型的匹配方式及各种数据表之间的关系才能有效的查询到自己所需的信息,这给用户进行数据查询操作带来极大的不便。如果能把数据库表文件的选择、查询结果输出字段的选定、不定数量查询条件的输入、条件表达式中数据类型的匹配及查询结果的输出等操作容为一体,设计在一个查询程序中,则查询操作将变得非常方便灵活而且简单。
2 查询程序的设计
为了使查询程序具有良好的交互功能和方便操作,可使用如图1所示操作界面。在此查询程序中,查询操作只需要在窗口提供的数据库表中选择所要查询的数据表,在选择字段项的列表框中选定要显示的数据字段,在选择条件项中设置查询的数据条件,最后点击查询按钮,则查询结果数据将按图2所示的表格列出。其中,图1 中选定的字段将作为图2 中的表格标题,图2表格中的数据为图1选定的数据表中符合条件的数据记录。图1中输入的条件为:来款日期为1999年10月以后且来款单位含有“宝钢”的记录,并在图2的表中显示出来款日期、来款单位、来款数和室别。
2.1 控件设置
在图1所示查询窗体上设置Option控件、ListBox控件组、条件设置控件组。
Option控件用于选择当前所要查询的数据库表。
ListBox控件组分别用于源数据表的字段列表和被选择字段名列表。选择项ListBox控件作为查询数据表中的字段名,被选项ListBox控件作为查询结果显示的字段名,这将作为如图2 所示的查询结果表格标题。
条件设置控件组由ListBox、ComboBox及CommandButton按钮等组成,完成数据表字段选择、关系运算符选择和条件表达式输入等功能,多个条件无逻辑运算符时默认为“AND”操作,否则使用“OR”按钮插入“OR”操作符。TextBox作为条件表达式输入控件,其中的数据类型(字符、数值、日期型数据)都直接输入,不使用定界符,在程序内部进行数据类型转换处理,这样可避免了不同类型数据的定界符输入。
2.2 条件输入的制作方法
查询条件项的操作是输入查询的条件表达式。它应满足字段选择和关系操作运算符选择的灵活性和稳定性,即字段名称应是数据表中的字段名,否则进行查询操作时字段名称可能产生不匹配的问题,因此最好使用下拉列表框来控制。基于同样的理由,关系操作运算符也由下拉列表框来控制。
图1 查询窗口示意
图1所示的条件输入控制项由ComboBox、TextBox及CommanButton组成。其中两个ComboBox控件分别用作条件变量的字段名和关系运算符(>、<、=、Like、$等)的选择,TextBox控件用作条件表达式中的数值项的输入。每输入完一个查询条件后,单击“插入”按钮将此条件加入ListBox中,作为ListBox的一行显示,同时,条件输入控制项下移一行,等待下一个条件表达式的输入。为了使ListBox控件的选择、修改、插入和删除等操作更为灵活,使用临时数据表itemadd存放条件表达式,一个条件作为一个记录项,并与ListBox绑定。当条件输入完毕后,若单击窗体其他位置,条件输入控制项将隐藏。若要修改某个条件行时,鼠标点击ListBox的该行,条件输入控制组自动移到当前行显示,等待进行数据修改。该操作通过MOVE方法来实现,以下程序段是插入按钮和删除按钮的代码。
插入新条件:
select itemadd &&插入一个新条件
insert blank
this.parent.listxztj.setfocus &&设置焦点为ListBox
this.parent.listxztj.selected(curec)=.T. &&在插入记录之后选定ListBox中的该项
topToindex=curec-this.parent.listxztj.topindex
if topToindex<=4 &&4为列表区的行数,如果条件项数在4项内
clisthigh=thisform.clistop+topToindex*thisform.rowleng &&行高
this.parent.listxztj.setfocus
this.parent.comBtjzd.move(36,clisthigh)
this.parent.comnot.move(148,clisthigh)
this.parent.comupdn.move(367,clisthigh)
this.parent.combcondit.move(170,clisthigh)
this.parent.textexam.move(263,clisthigh)
*关闭输入方式
this.parent.comnot.visible=.F. &&隐藏输入条件项
this.parent.comupdn.visible=.F.
this.parent.combcondit.visible=.F.
this.parent.textexam.visible=.F.
else &&条件项数超过4项,使ListBox的滚动条上移一行
this.parent.listxztj.setfocus
this.parent.listxztj.selected(recc("itemadd"))=.T.
keyboard "{dnarrow}"
this.parent.comnot.visible=.F.
this.parent.comupdn.visible=.F.
this.parent.combcondit.visible=.F.
this.parent.textexam.visible=.F.
endif
this.parent.combtjzd.setfocus
删除按钮的代码如下:
curec=recno("itemadd") &&curec为在ListBox中选择的当前记录号
dele
pack
if recc("itemadd")=0 &&当itemadd库中无记录时
insert blank
this.parent.combtjzd.setfocus
this.parent.listxztj.listindex=recno("itemadd")
this.parent.listxztj.selected(recno("itemadd"))=.T.
return
endif
if curec>recc("itemadd")
go recc("itemadd")
else
go curec
endif
this.parent.listxztj.selected(recno("itemadd"))=.T.
topToindex=recno("itemadd")-this.parent.listxztj.topindex
if topToindex<=4 &&4为列表区的行数
clisthigh=thisform.clistop+topToindex*thisform.rowleng
this.parent.listxztj.setfocus
this.parent.comBtjzd.move(36,clisthigh)
this.parent.comnot.move(148,clisthigh)
this.parent.comupdn.move(367,clisthigh)
this.parent.combcondit.move(170,clisthigh)
this.parent.textexam.move(263,clisthigh)
endif
this.parent.listxztj.listindex=recno("itemadd")
this.parent.listxztj.refresh
this.parent.combtjzd.setfocus