实现查询窗口式定制查询
实现这种定制查询的主要原理是:创建一个窗口(注:是使用FORM. BUILDER中的OBJECT NAVIGATOR的Windows节点创建的窗口),窗口上包含用户查询数据块时很可能使用的字段,点击查找按钮后,先将用户输入的值复制到查询数据块上再执行查询。
举例说明:原来的文档还是以EMP数据块为基础,这里的例子换成了自己的表单HELPKLY表单的一个表格式的数据块BILL_LINES,这个块被称为目标数据块。
步骤一:从Oracle提供的APPSTAND这个表单中将QUERY_FIND这个Object Group拷贝到自己的表单上(注:操作方法是将APPSTAND这个表单的Object Groups节点下的一个名为QUERY_FIND的对象拖动到自己表单的Object Groups节点下,然后放开鼠标,在弹出的对话框中一定要选择copy按钮,而不能选择Subclass按钮,因为你不是引用它,而是拷贝过来定制它, 主要操作见截图),成功后你会发现QUERY_FIND这个Object Group包含了一个窗口、一个数据块和一块画布,这是你做查询窗口的基础。操作完成后将复制过来的QUERY_FIND这个Object Group删除掉,不用担心,会保留提供的那一个窗口、一个数据块和一块画布,而且当你需要更多的查询窗口时你可以用通用的方法从APPSTAND中再次 复制就是了。
步骤二:重命名复制过来的窗口、数据块和画布
命名规则一般是目标数据块加上相关的后缀,比如用的例子的目标数据块名叫BILL_LINES,那么相应的数据块、画布和窗口分别命名为 BILL_LINES_QF、BILL_LINES_QF_CANVAS和BILL_LINES_QF_WINDOW,注意还要将刚才重命名的数据块的 Query Allowed属性设置为No(罗勇补注:原文是将queryable属性设置为No)。
步骤三:编辑取消按钮(NEW button)的触发器代码
编辑刚才重命名的数据块BILL_LINES_QF的名称为NEW按钮的WHEN-BUTTON-PRESSED触发器代码使之将目标数据块的名称作为参 数传递,修改后该触发器的代码为:app_find.new('BILL_LINES');。设置这个是为了让用户可以取消查询,并且导航到目标数据块的 新行上。主要的应用情景就是刚打开表单就弹出这个查询窗口,用户可能此时并不想查询查数,而是想导航到目标数据块上,此时就可以点击这个按钮。注: 为了适应习惯,应该将该按钮本来的label属性的值(label属性值就是按钮上的文本)修改为中文的,对于这个NEW按钮其作用其实相当于取消查 询,所以将其label属性设置为取消(&C) 更加通俗易懂,注意这时设置了一个快捷键Alt加上c键就相当于点击了取消按钮,注意学习这种设置按钮快捷键的方法。
步骤四:编辑查找按钮的触发器代码
编辑刚才重命名的数据块BILL_LINES_QF的名称为FIND按钮的WHEN-BUTTON-PRESSED触发器代码为
:parameter.G_query_find := 'TRUE';
app_find.find('BILL_LINES');
:parameter.G_query_find := 'FALSE';
这些代码的主要作用是关闭查询窗口,并导航到目标数据块执行查询。
如果你需要对查询窗口做更多的验证,比如某些项目必须输入,某些值必须在某个区间内,输入的条件会导致查询花费很长时间,没有输入任何查询条件等等提出警 告,你可以在该触发器代码app_find.find('BILL_LINES');这行前面撰写相应代码。注:可惜的是用户输入一个或者多个百分 号也会认为是输入了条件,因为form. builder好像不支持正则表达式进行验证项目。
步骤五:设置查询数据块Previous Navigation Data Block属性
设置查询数据块BILL_LINES_QF的Previous Navigation Data Block属性为目标数据块BILL_LINES。这样做是为了让用户可以离开查询窗口而不执行查询,个人觉得这个功能通过点击取消按钮也可以嘛。当然目 标数据块的Previous Navigation Data Block属性和Next Navigation Data Block属性都不要设置为查询数据块。
步骤六:编辑KEY-NXTBLK触发器
设置查询数据块BILL_LINES_QF的KEY-NXTBLK触发器的代码为:
:parameter.G_query_find := 'TRUE';
app_find.find('BILL_LINES');
:parameter.G_query_find := 'FALSE';
这样做的目的主要是当用户使用“下一块”对应的快捷键(目前EBS对应的是Shift+Pagedown)时相当于点击了查找按钮。个人觉得这个功能没什么用处吧,可能很多用户都不会使用这个快捷键。
步骤七:修改查询窗口的标题
将查询窗口BILL_LINES_QF_WINDOW的Title属性设置好,比如为查询单据。
步骤八:创建必要的项目
在查询窗口上创建用户很可能用到的查询项目(字段),一般采用从目标数据块复制项目到查询数据块,设置查询数据块BILL_LINES_QF中项目的属性请遵循以下规则:
1、 设置Required属性为No;
2、 设置Initial Value属性为空;
3、 如果你是从目标数据块拷贝过来的,请将所有项目的Database Item属性设置为No,并移除项目的所有触发器(特别是那些验证触发器)。如果有某些特殊理由要保留某些触发器,请确认你修改了相关的引用,特别是数据 块名称要改成现在的查询数据块名BILL_LINES_QF。
4、 典型情况下,查询窗口中可能使用LOV,那么LOV显示的是所有合法的记录,而不是目前合法的记录,对于日期字段请提供日历给用户选择日期并撰写该日历字段的KEY-LISTVAL触发器(注:这个代码一般是calendar.show;)。
5、 如果查询窗口中有个显示字段,这个显示字段有个ID字段跟其关联,那么查询窗口中这个ID字段也要创建赋值,因为使用ID字段会提高查询效率。
6、 目标数据块中的复选框型和单选按钮组型字段,在查询窗口中请换成弹出窗口,如果弹出窗口的值为空值null,那么这个项目在查询时不会施加任何约束条件。
步骤九:美化查询窗口
设置查询窗口使其更加美化,主要是调节窗口大小,字段的放置等。
步骤十:创建一个PRE-QUERY触发器
对目标数据块BILL_LINES创建一个PRE-QUERY触发器(该触发器的Execution Hierarchy属性设置为Before)用来拷贝查询查询窗口上的条件到目标数据块上。
使用COPY函数来复制字符串字段的值,使用:=符号来复制其他类型字段的值,但是使用:=符号来复制值的字段用户不能使用通配符。比如代码如下:
IF :parameter.G_query_find = 'TRUE' THEN
COPY(:BILL_LINES_QF.ELVBOX_NAME,'BILL_LINES.ELVBOX_NAME');
:parameter.G_query_find := 'FALSE';
END IF;
还有一种常用的查询条件是查询某个范围内的日期、数字和字符,这种情况下Oracle为你专门的定制了APP_FIND.QUERY_RANGE这个过 程。这个过程一般使用三个参数,第一个参数是查询块的字段,为查询范围的最小值,第二个参数也为查询块的字段,为查询范围的最大值,第三个参数是目标数据 块的字段名,是要使用这个查询范围的那个字段。示例代码:
IF :parameter.G_query_find = 'TRUE' THEN
COPY(:BILL_LINES_QF.ELVBOX_NAME,'BILL_LINES.ELVBOX_NAME');
APP_FIND.QUERY_RANGE(:BILL_LINES_QF.LINE_QTY_FROM,:BILL_LINES_QF.LINE_QTY_TO,'BILL_LINES.LINE_QTY');
:parameter.G_query_find := 'FALSE';
END IF;
注意:
目标数据块BILL_LINES的查询项目的Query Length属性要足够长来容纳将要复制过来的查询条件,如果不能容纳就会出错,建议最小设置为255。 如果你的目标数据块中含有单选按钮型项目、列表型项目或者复选框型项目,如果查询窗口中这些字段的值不为空值,也应该将其复制到目标数据块相应的字段。
步骤十一:创建QUERY_FIND触发器
为目标数据块创建一个QUERY_FIND触发器(该触发器的Execution Hierarchy属性设置为Override),代码如下:
app_find.query_find('MAIN_WIN', 'BILL_LINES_QF_WINDOW', 'BILL_LINES_QF');
补注:其中MAIN_WIN为表单的主要窗口,BILL_LINES_QF_WINDOW为创建的查询窗口,BILL_LINES_QF为创建的查询数据块。