• Form_Form Builder的基本语法(概念)


    2014-05-21 Created By BaoXinjian

    1. Trigger 


    (1). Override模式:默认模式不再触发高级别事件 

    (2). Before模式:触发完本级别事件后再触发高级别事件 

    (3). After模式:触发高级别事件后再触发本级别事件

     

    2. 常用form trigger


    (1). Form Level 

            i. per-form: form版本信息 

                         设定第一个windows 

                         切换org 

                         对Global和Parameter参数赋值 

            ii. when-new-form-instance: 定义弹性域 

                         定义folder 

    (2). Block Level 

            i. post-query 

            ii. when-new-record-form


    3. Form 对基于View的block进行数据操作


        on-lock 

        on-insert 

        on-update 

        on-delete

     

    4. Form Trigger的优先级


    (1).先从Item -> Record -> Block -> Form

    (2).如果另外设置Execution Hierarch属性(override,before,after),则按照设置后的顺序执行。

         如果是override的话,则执行完这个级别的触发器,就不往上执行了,

         before就是执行完这个级别的触发器后,如果上一个级别也有这个触发器的话,继续去执行,

         after就是先去执行上一个级别的触发器,然后再回来执行。

     

    5. 打开Form时的Tigger执行的顺序


    • (1)PRE-FORM

    • (2)PRE-BLOCK(BLOCK级)

    • (3)WHEN-NEW-FORM-INSTANCE

    • (4)WHEN-NEW-BLOCK-INSTANCE

    • (5)WHEN-NEW-RECORD-INSTANCE

    • (6)WHEN-NEW-ITEM-INSTANCE

     

    6. 触发Tigger的Execution Hierarchy


    (1).当一个事件发生的时候,Forms Engine可一并触发由低到高3个级别(Item、Block、Form)的同名事件,如何触发,由定义低级别的事件时所设置的执行层次决定。

    (2).Execution Hierarchy:

         Override模式,默认模式,不再触发高级别事件

         Before模式,触发完本级别的事件后,再触发高级别事件

         After模式,先触发高级别事件,再回来触发本级别事件

         当然了,如果某一层次我们没定义事件代码,Forms Engine就跳过该级别,直接进入下一级别。此外,Block中任何Item发生的事件,都可能引发该Block级事件,所以在Block级写本属于Item级的事件,要特别性能问题;Form级事件更有类似问题。

        例子. WHEN-VALIDATE-ITEM例子

        假设:

            1、 Item XXX的WHEN-VALIDATE-ITEM的代码是“代码1”,模式是“After”;

            2、 Item XXX所在BlockWHEN-VALIDATE-ITEM的代码是“代码2”,模式是“Override”;

            3、 Form级WHEN-VALIDATE-ITEM的代码是“代码3”。

        事件:发生Item XXX的WHEN-VALIDATE-ITEM

        那么:实际先执行“代码2”,然后执行“代码1”。

     

    7. Form Builder的四种commit方式


    (1).commit 

          对form和数据库进行提交. 

          如果form上面的数据变动和代码中的数据变动有冲突,最后以界面上的为准。 

    (2).commit_form 

          针对form上面的数据变动进行commit,对于代码中的类似update,insert语句也进行提交;会触发on-update,如果form上面的数据变动和代码中的数据变动有冲突,最后以界面上的为准。 

    (3).do_key('commit_form') 

          会首先寻找form下的triggers中的KEY-COMMIT这个trigger,并执行KEY-COMMIT中所写的代码。 

          如果没有KEY-COMMIT这个trigger,则会针对form和代码一起提交。 

          如果form上面的数据变动和代码中的数据变动有冲突,最后以界面上的为准。 

    (4).forms_ddl('commit'); 

          只针对代码中的update,insert,delete语句进行提交,form上面的数据变动不提交.

     

    8. Form 中遍历行


    go_block('block_name'); 

    first_record; 

    LOOP 

          message(:block_name.item); 

          if :system.last_record  = 'TRUE' then 

              exit; 

          end if; 

          next_record; 

    END LOOP;

     

    9. Compile Form


        frmcmp_batch module=xxapinvoice.fmb userid=apps/apps output_file=$CUX_TOP/forms/ZHS/xxapinvoice.fmx

     

    10. Form 的查询三种方式


    (1). 使用:parameter.G_query_find参数;

            if (name_in('PO_HEADERS.PO_HEADER_ID') is not null) then

               :parameter.g_query_find := 'TRUE'; 

               app_find.find('CUX_PO_HEADERS_ADD_MESSAGE'); 

               go_block('CUX_PO_HEADERS_ADD_MESSAGE'); 

               :parameter.G_query_find := 'FALSE'; 

            else

               FND_MESSAGE.DEBUG('请先保存订单头'); 

            end if;

            在CUX_PO_HEADERS_ADD_MESSAGE的PRE-BLOCK中处理 

            COPY(name_in('PO_HEADERS.PO_HEADER_ID'),'CUX_PO_HEADERS_ADD_MESSAGE.PO_HEADER_ID');

    (2). 使用Default_where属性处理 

            declare 

              lv_default varchar2(2000); 

            begin 

              lv_default:='.....'; 

              go_block('CUX_PO_HEADERS_ADD_MESSAGE'); 

              set_block_property('CUX_PO_HEADERS_ADD_MESSAGE',DEFAULT_WHERE,lv_default); 

              execute_query; 

            end;

    (3). 用app_find.query_range()来处理: 

            begin 

               .... 

               app_find.query_range(:find_date_from, 

                                    :find_date_to, 

                                    'CUX_PO_HEADERS_ADD_MESSAGE.REATE_DATE'); 

               :parameter.q_query_find:='false'; 

            end;

    (4). LOV查询,选择LOV值后自动查询Block,如选择Invoice Num后自动查询: 

            a. 创建一个Paramter参数<invoice_id>

            b. 创建LOV, 并将返回的值付给:Parameter.Invoice_id 

                SELECT invoice_id, invoice_number, description FROM bxj_invoices_all 

            c. 添加Block层级的Trigger<query_find> 

                app_find.query_find('q_invoices'); 

            d. 添加Block层级Trigger<pre_query> 

                IF :parameter.g_query_find = 'true' THEN 

                    :invoice_header.invoice_id = :paramter.invoice_id 

                    :paramter.g_query_find = 'true' 

                END IF;

     

    11. Form 建立表时常用栏位


    (1). 1个表关键字ID,通常与表名一致,并用Sequence为每条记录获得一个唯一值。

    (2). 1个组织ID,根据不同的开发选用不同层次的组织ID,这里的销售订单跑在OU层,所以基表命名为_ALL表,并创建一个过滤组织的View作为“基表”。

    要考虑这个表是否区分OU和库存组织

    (3). 5个Who字段,记录由谁在何时创建,并由谁在何时修改,登录ID是多少。

    EBS中提供了一个函数FND_STANDARD.SET_WHO,大家只要在FORM的BLOCK级触发器PRE-INSERT/PRE-UPDATE中进行调用即可

    (4). 4个请求字段,处理的请求ID、请求日期、并发程序ID及其应用ID,如果有的话。

    (5). 16个描述性弹性域字段,1个上下文字段,15个弹性域字段。

     

    12. Form 查看历史记录


    (1). 设定Block层存在5个Who字段,creation_date, created_by, last_updated_date, last_updated_id, login_id

    (2). 在该Block层when-new-block-instance中

           app_special.enable('ABOUT', property_on);

     

    13. 日历控件


    (1).增加Trigger:key-listval  -> calendar.show   

    (2).修改property: LOV为enable_list_lamp

    (3).修改property:Validate from List为No 


    14. 描述性弹性域控件


    (1).增加Trigger:when-new-form-instance        

          fnd_descr_flex.define(block => 'BLOCKNAME',

                                         field => 'DESC_FLEX',

                                         appl_short_name => 'SCF',

                                         desc_flex_name => 'CUX_FLEXFIELD_DEMO');

    (2).增加Trigger: block-level

          fnd_flex.event('PRE-INSERT');

          fnd_flex.event('PRE-UPDATE');

          fnd_flex.event('PRE-QUERY');

          fnd_flex.event('POST-QUERY');

          fnd_flex.event('WHEN-VALIDATE-RECORD');

    (3).增加Trigger:

         fnd_flex.event('WHEN-NEW-ITEM-INSTANCE');

         fnd_flex.event('WHEN-VALIDATE-ITEM');

    (4).修改Property: LOV为enable_list_lamp

     
    15. 关键值弹性域控件


    (1).when-new-form-instance特殊定义        

         fnd_key_flex.define(BLOCK => 'BLOCKNAME',

                                     field => 'ACCOUNT_CODE',

                                     description => 'ACCOUNT_DESCRIPTION',

                                     appl_short_name => 'SQLGL',

                                     code => 'GL#',

                                     id => 'CODE_COMBINATION_ID',

                                     required => 'N',

                                     usedbflds => 'N',

                                     validate => 'FULL',

                                     vrule => \nSUMMARY_FLAG\nI\nAPPL=SQLGL???

                                     num => 101);

     

     16. Form调用Form的四种方式


    (1). Open_Form

    (2). Call_from

    (3). New_Form

    (4). FND_FUNCTION

     

     17. Form中5个Who字段赋值方式


    (1). 如果表中存在Who字段,通过fnd_standard.set_who来自动设置WHO字段

    (2). 如表中无WHO字段,须禁用HELP–>ABOUT_THIS_RECORD. 方法如下:

          在BLOCK级的WHEN–NEW–BLOCK–INSTANCE(”Override”) 中写如下代码:

          app_standard.event(’WHEN–NEW–BLOCK–INSTANCE’);

          app_special.enable(’ABOUT’, PROPERTY_OFF);

     

     18. Form打开后切换Organization


    (1). 首先在parameter中加上CHART_OF_ACCOUNTS_ID、ORG_NAME、ORG_CODE、ORG_ID四个参数

    (2). 在form level的trigger中的pre-form中加入FND_ORG.CHOOSE_ORG

    (3). 在form level的trigger中的when-new-form-instance中加上APP_WINDOW.SET_TITLE('ADJ_RECEIVE',:PARAMETER.ORG_CODE);其中ADJ_RECEIVE是WINDOW的名字,用于设置WINDOW的TITLE。

     

     18. Form完成检查步骤


    1. 常规属性的设置,如模块、数据块、画布、窗口,常规触发器的修改。

    2. 是否有添加create_by,creation_date等字段信息,即在PRE_INSERT,PRE_UPDATE添加fnd_standard.set_who,select fnd_profile.value('org_id') into :hek_fnd_user.org_id from dual.

    3. 一些特殊属性:如删除记录行为(级联)、防止无主记录操作(否)、DML数据目标名称(如果基于视图建form,要指定一个表)、时间(格式掩码:yyyymmdd)、lov时间不需要验证、tab顺序的设置,项的仅查询。

     

     20. 开发人员需注意点


    1. 例外处理

    有很多人喜欢在处理exception时,置为'null',应该说这是一个很不好的习惯。

    如果没有定义特定的exception,最起码应该把数据库的错误信息完整的报出来。

    2. 并发程式Output和Log部分

    (1). 输出到请求的输出:FND_FILE.PUT_LINE(FND_FILE.OUTPUT, 'XXXXXXX');

    (2). 输出到请求的日志:FND_FILE.PUT_LINE(FND_FILE.LOG, 'XXXXXX');

    一般情况是把报表的内容输出到Output,把报表中间的Debug逻辑输出到Log中

    3. 开发环境的初始化

    我们经常会遇到在pl/sql中运行某个视图,不能显示出数据,但是在界面上确有数据,这主要是因为视图是OU屏蔽的

    fnd_global.APPS_INITIALIZE(uesr_id, resp_id, resp_appl_id);

    4.  FND_MESSAGE消息的使用

    (1). FORM中直接使用FND_MESSAGE.DEBUG('xxxxx');来显示错误或提示信息,实际上这是非常不正确的做法。

    (2). 一般情况下在FORM中显示出错信息使用以下代码:

    FND_MESSAGE.SET_NAME( APPL_SHORT_NAME,MESSAGE_NAME) ;

    FND_MESSAGE.ERROR ;

    (3). 在PACKAGE中显示出错信息一般使用以下代码:

    FND_MESSAGE.SET_NAME( APPL_SHORT_NAME,MESSAGE_NAME) ;

    APP_EXCEPTION.RAISE_EXCEPTION ;

    5. Trigger的写法

    在FORM开发中不管是FORM级还是BLOCK级或者ITEM级的TRIGGER,不要把代码直接写到TRIGGER中,要使用PROGRAM UNIT来创建相应的TRIGGER,

    6. 在EBS如果要使用弹性域或预警等,则必须在EBS注册TABLE及COLUMN

    此注册功能是通过调用AD_DD函数包来实现的:

    AD_DD.REGISTER_TABLE        注册TABLE

    AD_DD.REGISTER_COLUMN     注册COLUMN

    AD_DD.DELETE_TABLE           取消注册TABLE

    AD_DD.DELETE_COLUMN        取消注册COLUMN

     

    Thanks and Regards

  • 相关阅读:
    Kubernetes
    桥接模式
    原型模式
    工厂模式
    生成器模式
    Java-Sentinel限流中间件
    python模拟发送、消费kafka消息
    使用idea搭建springBoot项目
    linux 虚拟机不能启动不了系统,虚拟机更改linux初始启动5,出现无法启动现象
    vwware workstation虚机网络配置NAT
  • 原文地址:https://www.cnblogs.com/eastsea/p/3762417.html
Copyright © 2020-2023  润新知