您的位置:首页 > 其它

自动行号功能实现不同方法研究

2014-01-06 17:28 399 查看



方法一、

只需要将“序号”定义成公式,并将公式设置为:get_block_property('block_name',current_record)就可以实现了,或者把这行语句放到“When-Create-Record”触发器中。

缺点:增改删时,行号不能自动刷新。


方法二、

在block的三个触发器中添加相应的代码:

Key-Crerec:
DECLARE
LINE NUMBER;
BEGIN
LINE := :SYSTEM.CURSOR_RECORD;
LOOP
IF :SYSTEM.LAST_RECORD = 'TRUE' THEN
EXIT;
ELSE
NEXT_RECORD;
:blk.ID := :SYSTEM.CURSOR_RECORD + 1;
END IF;
END LOOP;
GO_RECORD(LINE);
CREATE_RECORD;
:blk.ID := :SYSTEM.CURSOR_RECORD;
END;
Key - Delrec:
DECLARE
LINE NUMBER;
BEGIN
DELETE_RECORD;
LINE := :SYSTEM.CURSOR_RECORD;
LOOP
:blk.ID := :SYSTEM.CURSOR_RECORD;
IF :SYSTEM.LAST_RECORD = 'TRUE' THEN
EXIT;
ELSE
NEXT_RECORD;
END IF;
END LOOP;
GO_RECORD(LINE);
END;
When - Create - Record:
:blk.ID := :SYSTEM.TRIGGER_RECORD;


缺点:对于记录数很少的table适用,当table中的记录很多时,由于使用了循环操作,所以会影响效率。

 

为了防止按F11时也生成序号,影响查询,可以在生成前加入以下条件:

IF (:SYSTEM.MODE != ‘ENTER-QUERY’) THEN 


方法三

Step1创建3个参数和一个非数据库字段

Parametername                                                 type       InitialValue

P_BOLCKNAME_MAX_LINE_NUMBER    number

P_BOLCKNAME_VALIDATE_FLAG            char

P_BOLCKNAME_RESET_LINE_NUMBER  char        N

在使用line_number功能的Block中添加一个非数据库Item

Columnname                          type       InitialValue

VAL_REC_FIRED_FLAG      char       N

 

Step2在block-leveltrigger中添加以下代码

(1) pre_query

 BOLCKNAME.line_num('PRE-QUERY');

(2) post_query

 BOLCKNAME.line_num('POST-QUERY');

(3) when_create_record

 IF :PARAMETER. P_BOLCKNAME_RESET_LINE_NUMBER = 'Y' THEN

     copy('1',:PARAMETER.P_BOLCKNAME_MAX_LINE_NUMBER);

     :PARAMETER.P_BOLCKNAME_RESET_LINE_NUMBER:= 'N';

END IF;

BOLCKNAME.line_num('INIT');

(4) when-validate-record

BOLCKNAME.line_num('WHEN-VALIDATE-RECORD');

(5) when-new-record-instance

BOLCKNAME.line_num('WHEN-NEW-RECORD-INSTANCE');

(6) on-clear-details(子块需添加,主块不需该trigger)

  IF :system.cursor_block = 'BOLCKNAME' andnvl(:system.coordination_operation,'X') in('CREATE_RECORD','NEXT_RECORD') 

THEN

        copy('Y',P_BOLCKNAME_RESET_LINE_NUMBER);

   END IF;

(7) pre_insert

 BOLCKNAME.catalog_group_line_unique; --行号唯一性的检查

(8) pre_update

 BOLCKNAME.catalog_group_line_unique; --行号唯一性的检查

       

在VAL_REC_FIRED_FLAG的Item leveltrigger中添加以下代码

(1) WHEN-VALIDATE-ITEM

BOLCKNAME.catalog_group_line_unique; --行号唯一性的检查

BOLCKNAME.line_num('WHEN-VALIDATE-ITEM');

 

Step3在ProgrameUnit中添加名为BOLCKNAME的PACKAGE

在PACKAGE BLOCKNAME BODY中添加

  PROCEDURE line_num(event VARCHAR2) IS

                           x_max_line_num  NUMBER:= 0;

                           x_lines_curr_maxNUMBER;       

BEGIN

               IF(event = 'WHEN-VALIDATE-ITEM') THEN

                        --code略 

    END IF ;

END ;           

 

   PROCEDURE catalog_group_header_uniqueis

     l_rec_num number;

  BEGIN

        selectcount(1) into l_rec_num

      --code略 

  END;

具体代码参看附件:blockname_body.txt

 

Step4在数据库中创建下面的PACKAGE

红蓝两部分代码功能类似,区别在于蓝色代码多了一个line_type传入参数,可根据条件灵活调用。

create or replace package bodyTVSN_CONTROL_F_PKG is

PROCEDUREcheck_catalog_unique(p_catalog_header_idINNUMBER,

                                P_catalog_LINE_ID  INNUMBER,

                                P_catalog_LINE_NUM INNUMBER,

                                p_validate_flag    OUTVARCHAR2) IS

              p_record_numbernumber := 0;        

BEGIN                               

END;

PROCEDUREget_catalog_max_num (P_catalog_header_idINNUMBER,

                                P_MAX_NUM          OUTNUMBER) IS

BEGIN

END;

PROCEDUREcheck_catalog_group_unique(p_catalog_group_header_idINNUMBER,

                                      p_catalog_line_type      INNUMBER,

                                      P_catalog_group_LINE_ID  INNUMBER,

                                      P_catalog_group_LINE_NUM INNUMBER,

                                      p_validate_flag          OUTVARCHAR2) IS

     p_record_number number :=0;                                      

BEGIN

END; 

PROCEDUREget_catalog_group_max_num(P_catalog_group_header_idINNUMBER,

                                     p_line_type              INNUMBER,

                                     P_MAX_NUM           OUTNUMBER) IS

BEGIN

END;                                 

endTVSN_CONTROL_F_PKg;

注:此种方法有个缺陷,即可能产生断号的Line_Number,如现有行号为4,5,6的记录删除了行号为5的记录,那么新增一条记录的行号就为7,行号5就永远不可能被用到了。

 

顺带介绍两个和行记录有关的API:

(1)   APP_RECORD.DELETE_ROW

procedureAPP_RECORD.DELETE_ROW(

check_delete BOOLEAN default FALSE, --是否检查Block的delete_allowed属性

product_name varchar2 default NULL,

message_name varchar2 default NULL);

functionAPP_RECORD.DELETE_ROW(

check_delete BOOLEAN default FALSE,

product_name varchar2 default NULL,

message_name varchar2 default NULL)

return BOOLEAN;

此API可应用删除记录时需提示时,确认后执行删除,取消则不删除,可以通过重写Block的KEY-DELREC Trigger添加APP_RECORD.DELETE_ROW;实现该功能。也可以利用下面的代码实现更复杂的删除逻辑。

IF APP_RECORD.DELETE_ROW THEN

  Code1;

ELSE

  Code2;

END IF;

 

(2)   APP_RECORD. FOR_ALL_RECORDS

此API补充了本章开头介绍的Line_Number功能的断号缺陷,将两者结合起来应该是一种比较完善的解决方案,实现步骤如下:

Step 1创建itemhandler procedures

PACKAGE BODY lines IS

line_number_seq number := 0;

PROCEDURE delete_row IS

BEGIN

line_number_seq := 0;

APP_RECORD.FOR_ALL_RECORDS(’reseq_line_number’);

END delete_row;

END lines;

 

Step 2创建用户定义triggerRESEQ_LINE_NUMBER

lines.line_number_seq := lines.line_number_seq + 1;

:lines.line_number := lines.line_number_seq;

 

Step 3在KEY–DELETETrigger调用item
handler procedures

lines.line_number(’KEY–DELETE’); --删除记录时调用delete_row代码重置行号

 

注意:当块中包含的记录数非常多时,那么重置行号将非常缓慢。如果块查询出的记录集只是所有记录的一部分,而行号又是主键字段,那么重置行号有可能导致主键重复的错误。如果在查询玩数据或保存提交后需要重置行号,那么可能需要修改record的状态将其标记为未修改。


方法四

在某些情况下,在新增、删除记录后,要求为 BLOCK中显示的
RECORD进行排序并

且编号。完成这一动作可通过以下函数来完成:

l APP_RECORD.FOR_ALL_RECORDS

例子如下:

块 LINES中有
ITEM: LINE_NUMBER。要求当记录被删除时, LINE_NUMBER要重

新编号。

步骤 1  创建
ITEM的 HANDLER

PACKAGE BODY lines IS

line_number_seq number := 0;

PROCEDURE delete_row IS

BEGIN

line_number_seq := 0;

APP_RECORD.FOR_ALL_RECORDS(’reseq_line_number’);

END delete_row;

END lines;


步骤 2  创建自定义的TRIGGER:RESEQ_LINE_NUMBER

汉得信息技术有限公司 ORACLE应用开发培训手册

Lesson 9 FORM中对象的编程 37

Company  Confidential -For internal use only

lines.lin e_number_seq :=lines.line_number_seq + 1;

:lines.line_number :=lines.line_number_seq;

步骤 3  调用
ITEM的 HANDLER

Trigger: KEY– DELETE:

lines.line_number(’KEY–DELETE’);


方法五

这个行号的特点是:

新增行时自动生成默认行号:已有的最大行号+1
用户可以修改行号为合法的数字:大于0;保证唯一
如果用户修改了行号,新增生成的行号必须在用户修改行号的基础上+1

实现这样的行号相对比较麻烦,下面描述如何来实现上图中所示的行号功能:

在记录块的PRE-QUERY中查询出数据库中已有的最大行号,并将其记录到参数中作为最大的行号,如果单据的头是新建的,那这个参数默认的最大值则为1
在行记录的WHEN-CREATE-RECORD中将最大行号的参数值+1赋给行号字段
行号数据项的WHEN-VALIDATE-ITEM中检查行号是否<0;同时检查行号在数据库中是否存在(对于同时录入多行相同的行号在这个触发器中无需处理)
在WHEN-NEW-RECORD-INSTANCE中检查如果块的状态是NEW,从数据库中获取最大的行号,并设置行号
在WHEN-VALIDATE-RECORD中判断当前的行号是否大于参数中的最大行号,如果是则覆盖参数的最大行号

procedure line_num ( event varchar2) is
l_line_num_count number;
begin
if ( event = 'WHEN-VALIDATE-ITEM') then

if :lines.line_number <= 0 then
fnd_message.set_name('XHU','XHU_ALL_ENTER_VALUE_GT_ZERO');
fnd_message.error;
raise form_trigger_failure;
end if;
-- check the unique line number from DB
if xhu_orders_sv.po_line_num_exists(name_in('headers.header_id'),name_in('lines.line_number')) then
fnd_message.set_name('XUH','XHU_ENTER_UNIQUE_LINE_NUM');
fnd_message.error;
raise form_trigger_failure;
end if;

elsif (event = 'WHEN-CREATE-RECORD') then
:lines.line_number := :parameter.max_line_num + 1;
elsif (event = 'PRE-QUERY') then
-- get the maximums line number from the DB
:parameter.max_line_num := xhu_orders_sv.get_max_line_num(name_in('headers.header_id'));
elsif (event = 'WHEN-VALIDATE-RECORD') then
if :lines.line_number > :parameter.max_line_num then
:parameter.max_line_num := :lines.line_number ;
end if;
elsif (event = 'WHEN-NEW-RECORD-INSTANCE')then
if upper(get_block_property('lines',status)) = upper('NEW') and :System.Mode <> 'ENTER-QUERY' then
:parameter.max_line_num := xhu_orders_sv.get_max_line_num(name_in('headers.header_id'));
line_num('WHEN-CREATE-RECORD');
SET_RECORD_PROPERTY(get_block_property('lines',current_record), 'lines', STATUS, NEW_STATUS );
end if;
else
APP_EXCEPTION.INVALID_ARGUMENT('LINE_NUMBER', 'EVENT', EVENT);
end if;

exception
when others THEN
raise;
end line_num;

--headers:单据的头数据块
--lines:行号所属的数据块
--xhu_orders_sv.get_max_line_num:根据头ID取得数据库中单据的最大行号
--XHU_ENTER_UNIQUE_LINE_NUM:消息字典:请输入唯一行号
--XHU_ALL_ENTER_VALUE_GT_ZERO:消息字典:请输入大于0的值


各触发器的HANDLER:

procedure when_create_record is
begin
lines.line_num('WHEN-CREATE-RECORD');
end when_create_record;

procedure when_new_record_instance is
begin
lines.line_num('WHEN-NEW-RECORD-INSTANCE');
end when_new_record_instance;

procedure when_validate_record is
begin
lines.line_num('WHEN-VALIDATE-RECORD');
end when_validate_record;

procedure pre_query is
begin
lines.line_num('PRE-QUERY');
end pre_query;
添加一个MAX_LINE_NUM(NUMBER)的参数来保存当前最大行号的值
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  EBS FORM 自动行号