很多时候,我们想实现这样子的操作效果:
当向一个特定的Item输入数据之后,自动触发一系列的动作,例如GO_BLOCK,然后Loop这个Block,向这个Block维护一定的值(或者检查值)。这样子可以很大程度方便User操作(因为是自动操作的)。
但是,众所周知,如果在WHEN-VALIDATE-ITEM等触发器用GO_BLOCK等导航的内置函数,会报错:FRM-40737存在非法的受限过程。因为验证的触发器是不可以导航到别的记录的(大部分触发器都不可以)。
这里发现一个触发器可以达到这个效果:KEY-NEXT-ITEM。
这个触发器KEY-NEXT-ITEM是当用户向对应的Item输入数据,然后点Tab按键或者Enter按键(当然,画面没有Enter就直接调用的按钮)的时候,会触发这个触发器。而这个触发器是可以随意做一些我们想做的动作。例如跳到别的Item,别的Block等等。
但是,用这个触发器的程序猿会发现,如果用户录入数据的导航方式不是:向特定的Item输入值之后,用键盘Tab(或者Enter)导航到下一个Item;而是用鼠标直接点击,那是触发不了KEY-NEXT-ITEM事件,从而导致程序有隐含的bug!
怎么办?这里给出一个解决方案,虽然不是最好的,但是却是可以用的:对于这个Item,禁用鼠标导航的操作方式!
如何禁用?其原理:利用当用户点Tab按键的时候,触发器的顺序是:先触发KEY-NEXT-ITEM;再触发WHEN-VALIDATE-ITEM。当用户直接用鼠标导航的时候,只是触发WHEN-VALIDATE-ITEM。所以在WHEN-VALIDATE-ITEM下手即可,用RAISE FORM_TRIGGER_FAILURE;禁用。
实现步骤:
1 增加一个参数::PARAMETER.CURRENT_KEY_MODE。目的是为了区分用户的录入之后,导航的方式。
2 在WHEN-VALIDATE-ITEM触发器直接写下面的代码:
Begin
---当有变更,而且CURRENT_KEY_MODE(输入之后的导航类型)不是KEY-NEXT-ITEM的时候,必须用tab按键或者enter导航!
FND_MESSAGE.DEBUG('WHEN-VALIDATE-ITEM1');
IF :MDS_CONTROL.SCHEDULE_DATE IS NOT NULL AND NVL(:PARAMETER.CURRENT_KEY_MODE,'WHEN-VALIDATE-ITEM') <> 'KEY-NEXT-ITEM' THEN
FND_MESSAGE.SET_STRING('请注意:该栏位输入之后,请按Tab按键或者Enter按键导航!');
FND_MESSAGE.HINT;
RAISE FORM_TRIGGER_FAILURE;---禁止用户用鼠标点击导航!
END IF;
FND_MESSAGE.DEBUG('WHEN-VALIDATE-ITEM2');
End;
3 然后在KEY-NEXT-ITEM增加代码:
Declare
l_cur_record Number;
Begin
FND_MESSAGE.DEBUG('KEY-NEXT-ITEM1');
If :MDS_CONTROL.SCHEDULE_DATE Is Not Null Then
:PARAMETER.CURRENT_KEY_MODE := 'KEY-NEXT-ITEM';
Go_Block('XYG_MANUFACTURE_NEED');
l_cur_record := :SYSTEM.cursor_record;
First_Record;
Loop
If Nvl(:XYG_MANUFACTURE_NEED.CHK,'N')='Y' AND NVL(:XYG_MANUFACTURE_NEED.SCHEDULE_DATE,SYSDATE) <> :MDS_CONTROL.SCHEDULE_DATE
AND NVL(:XYG_MANUFACTURE_NEED.PROCESS_STATUS,'N') = 'Y' ---没审核的不可以预排
Then
:XYG_MANUFACTURE_NEED.SCHEDULE_DATE := :MDS_CONTROL.SCHEDULE_DATE;
---2011-10-19 samt add
:XYG_MANUFACTURE_NEED.SCHEDULE_USER_ID := FND_GLOBAL.USER_ID;
:XYG_MANUFACTURE_NEED.SCHEDULE_USER :=SUBSTRB( XYG_PUB_COMMON_PKG.GET_FND_FULL_NAME(FND_GLOBAL.USER_ID,SYSDATE,0),1,240) ;--FND_GLOBAL.USER_NAME;
End If;
Exit When :SYSTEM.LAST_RECORD='TRUE';
Next_Record;
End Loop;
--:MDS_CONTROL.SCHEDULE_DATE := NULL; ---清空
Go_record(l_cur_record);
:PARAMETER.CURRENT_KEY_MODE := 'WHEN-VALIDATE-ITEM';
End If;
FND_MESSAGE.DEBUG('KEY-NEXT-ITEM2');
End;
----2014.9.26更新:
有个问题:
在Key-commit的时候,再判断这个头的ITEM_COPY是否<>ITEM,如果是,则自动删除行的内容。
然后当用户点到行Block的时候,系统判断上面的(是否有自动做了DELETE记录的标识),如果是=Y,则自动刷新行的BLOCK即可。
这样子的话,就可以完全防呆了,反正有做了修改,DB数据库一定会删除记录。只不过对于用户来说刷新动作晚了一点而已。
您已经修改了这个值,系统已经在后台将行记录清空。请鼠标点到行块以确认数据。