一个自己写的例子,实际的报表开发业务需求中,使用Function Module “LDB_PROCESS”来实现使用LDB时自定义选择屏幕,及对性能的提高。
通常的LDB用法,是在ABAP程序的属性里面设置LDB名,然后直接使用LDB的选择屏幕,通过Get事件进行业务逻辑的处理。但是也可以通过Function Module “LDB_PROCESS”来实现,SAP网站有一个例子如下:
http://help.sap.com/saphelp_nw70/helpdata/en/64/237f8cd43711d1950b0000e8
353423/content.htm
但是这里面对于自定义的选择屏幕参数和Get事件回调函数的逻辑都过于简单,以下给出一个自己写的例子,是实际的报表开发业务需求,只把最关键的部分给出来,其他的什么ALV显示或下载就略了。
1.选择屏幕
SELECT-OPTIONS:
S_BUKRS FOR BKPF-BUKRS ,
S_BELNR FOR BKPF-BELNR ,
S_HKONT FOR BSEG-HKONT ,
S_BUDAT FOR BKPF-BUDAT ,
S_BLART FOR BKPF-BLART ,
S_BSCHL FOR BSEG-BSCHL.
注意,其中S_BUDAT、S_HKONT、S_BSCHL都是在后面使用到的LDB 'BRM'里面没有被预先定义的。
2.定义回调函数
INITIALIZATION.
CALLBACK_WA-LDBNODE = 'BKPF'.
CALLBACK_WA-GET = 'X'.
CALLBACK_WA-CB_PROG = SY-REPID.
CALLBACK_WA-CB_FORM = 'CALLBACK_BKPF'.
APPEND CALLBACK_WA TO CALLBACK.
CLEAR CALLBACK_WA.
CALLBACK_WA-LDBNODE = 'BSEG'.
CALLBACK_WA-GET = 'X'.
CALLBACK_WA-GET_LATE = 'X'.
CALLBACK_WA-CB_PROG = SY-REPID.
CALLBACK_WA-CB_FORM = 'CALLBACK_BSEG'.
APPEND CALLBACK_WA TO CALLBACK.
内表CALLBACK要作为LDB_Process的一个输入参数,LDBNODE和CB_FORM分别对应了LDB中的表名和要在其中写业务逻辑的Form名。
3.填充选择屏幕的参数值
FORM FILL_SELECTION.
*Company Code
SELTAB_WA-KIND = 'S'.
SELTAB_WA-SELNAME = 'BR_BUKRS'.
LOOP AT S_BUKRS.
MOVE-CORRESPONDING S_BUKRS TO SELTAB_WA.
APPEND SELTAB_WA TO SELTAB.
ENDLOOP.
*Document number
SELTAB_WA-KIND = 'S'.
SELTAB_WA-SELNAME = 'BR_BELNR'.
LOOP AT S_BELNR.
MOVE-CORRESPONDING S_BELNR TO SELTAB_WA.
APPEND SELTAB_WA TO SELTAB.
ENDLOOP.
*Document type
SELTAB_WA-KIND = 'S'.
SELTAB_WA-SELNAME = 'BR_BLART'.
LOOP AT S_BLART.
MOVE-CORRESPONDING S_BLART TO SELTAB_WA.
APPEND SELTAB_WA TO SELTAB.
ENDLOOP.
ENDFORM.
SELNAME是LDB中预定义了的选择屏幕参数名,将对应的S_×××的参数值填充进去SELTAB,也要作为LDB_Process的一个输入参数。
4.调用Function Module
CALL FUNCTION 'LDB_PROCESS'
EXPORTING
LDBNAME = 'BRM'
VARIANT = ' '
EXPRESSIONS = TEXPR
FIELD_SELECTION = FSEL
TABLES
CALLBACK = CALLBACK
SELECTIONS = SELTAB
EXCEPTIONS
LDB_NOT_REENTRANT = 1
* ......
OTHERS = 13.
注意两个Tables的参数,就是第2、3步处理的两个内表。
5.回调函数中的业务逻辑
FORM CALLBACK_BKPF USING NAME TYPE LDBN-LDBNODE
WA TYPE BKPF
EVT TYPE C
CHECK TYPE C.
CASE EVT.
WHEN 'G'.
check WA-BUDAT IN S_BUDAT.
CLEAR rpt.
MOVE-CORRESPONDING WA TO rpt.
ENDCASE.
注意,check WA-BUDAT IN S_BUDAT,是对没有在LDB中定义的选择屏幕S_BUDAT的处理,判断抽取出的物料凭证的记账日期是否在输入的范围内,在的话会把数据放入一个rpt结构中。
FORM CALLBACK_BSEG USING NAME TYPE LDBN-LDBNODE
WA TYPE BSEG
EVT TYPE C
CHECK TYPE C.
CASE EVT.
WHEN 'G'.
check WA-BUKRS = rpt-BUKRS.
check WA-BELNR = rpt-BELNR.
check WA-GJAHR = rpt-GJAHR.
check WA-HKONT IN S_HKONT.
check WA-BSCHL IN S_BSCHL.
MOVE-CORRESPONDING WA TO rpt.
APPEND rpt.
ENDCASE.
ENDFORM.
对 S_HKONT和S_BSCHL的check与S_BUDAT类似,前面的三个check是关联BKPF和BSEG的条件,rpt-×××的值在 CALLBACK_BKPF中已经取得,这里就相当于SELECT ... FROM BSEG WHERE BUKRS = BKPF~BUKRS ...
最后所有满足条件的记录都APPEND到rpt中之后,就可以使用ALV显示,或下载到本地等等,此处略过。
这个程序的实 现的一个重大优点在于性能,众所周知读BKPF/BSEG是数据极大的表,一般都会建议在SQL中使用for all entries来优化性能,问题是,如果最初读BKPF的时候条件就设置很宽松,从这一个单表取数也很耗时间,这时不妨采用我这里介绍的LDB的方法,性 能明显更好,我自己已经有过体会了。