ABAP程序设计的一点建议
最近研究了一下ABAP程序设计方面的东西,就提高程序可读性方面的问题进行了深入的分析与研究。结果发现相当一批人在设计方面走入一个误区,网上一些二把刀子的程序员发布的一些程序模版简直是误人子弟。在此,基于本人十余年的经验,提出以下几点建议。
一、规范化程序中的命名规则。有些在变量与内表命名的时候简直是随心所欲,毫无规律可言。同一类的表名多了,干脆直接XXX_1、XXX_2、XXX_3地排列下去。我们的ABAP程序虽然不能使用微软的匈牙利命名法,但是这种毫无意义的命名法更是不可取的。
二、多定义一些程序,使用子程序将程序功能模块化。SAP的ABAP编辑器是很不错的一个编辑器,它左边有导航条,通过双击可以轻易定位到每个子程序名与变量。使用子程序模块化程序后,定位程序功能非常的方便。
三、不要轻易使用INCLUDE程序。ABAP开发的程序培训教材中,曾经提到过模块化程序的两种方式,INCLUDE程序与子程序FORM。系统程序因为代码量大,大量使用了INCLUDE程序。有些人看到这里,就有样学样,在自己的开发程序中大量使用INCLUDE程序。其实这是完全没必要的。一般的自开发程序,如果代码规范良好的话,不会超过3000行,放在一个主程序里足够了。有些人把程序分成变量定义、选择屏幕与事件、PAI、PBO、子程序等四五个INCLUDE程序,自以为很给力。而实际上呢,子程序部分占所有代码的80%以上,而这个INCLUDE程序里定义的子程序却有聊聊无几,结果跟踪调试程序麻烦的要死。又因为与变量在不同的INCLUDE程序里,结果新增变量时比较麻烦,转而大量使用局部变量,使用程序的可读性更加糟糕。
四、灵活地使用宏。MACRO这个东西从C语言提出来以后,可以说常盛不衰。当然如果不愿意使用宏,用子程序来代替也是可以的。一个比较典型的例子就是给ALV的FIELDCAT内表添加输出字段。曾经见过一个输出50列的ALV报表,这部分的代码就写了400多行。查找字段时要翻好多屏才能找到。如果使用宏的话,这部分代码五六十行就够了。
五、控制嵌套缩进的空格数。大家会发现ABAP代码一行限制在72个字符之内,当然我们也可以取消这个限制。这其实提示我们,在嵌套缩进的时候,两个空格就够了,不要太多的缩进。以前有个同事喜欢缩进四个空格,结果子程序一层,LOOPAT循环一层,里面随便出现一个IF ESLE的判断。写到中间,代码都在每一行的中间开始,一行里根本写不多少东西。
六、控制嵌套的层数。有人可能会大声反对,我的程序就是需要这么多判断,我的程序就是需要双层循环。我很想问一句,真的是必须要这样做吗?我看到过一些人的代码,是的,IF判断就嵌套了三四层,再加上子程序一层、循环一层,搞得代码逻辑相当复杂。我只想提醒一句,有时候我们用一个CHECK判断一下就行,没必要一定嵌套进去。
七、合理地使用INNERJOIN。内连接,大家都是会的。国内某大型集团曾提出一个硬性要求,SQL语句的表连接不能超过3个,多么傻的一个要求呀。不合理的连接,两个连在一块就会要人命;而合理的连接有四五个表在一起也是没问题的。曾经遇到过一个极品ABAP顾问,一个1500行的程序,光数据处理的全局内表就定义了28个,程序中几乎没有一个连接取数的。当然,过多的连接也是不行的。当年培训一个JAVA出身的程序员,出了一个题目,就是要求取销售订单及后续交货单、发货过账的一些数据。这哥们没写,还振振有词地说太简单了,在系统中建立三个视图VBAK-VBAP-VBUK、LIKP-LIPS、MKPF-MSEG,然后视图内连接就出来了。哥当时真的是无话可说了,夏虫不可语冰,他还真以为SAP的ERP系统是他自己开发的ACCESS数据库呢!
八、注意一下小技巧的使用。ABAP程序的一些语句在处理一些特定的问题时特别有用,不要有意无意地忽略了这些语句。比如LOOPAT循环中的AT事件。有人在将一组数分类汇总并插到内表中时,又是内表,又是排序,搞得相当复杂。比如,财务的某一科目段,要按科目汇总一次,按科目的前6位汇总一次,按科目的前4位汇总一次,按科目的前2位汇总一次。这样的汇总,如果灵活使用ATENDOF事件,一个循环就能搞定。再比如,财务的月度报表,求期末汇总时,有人就会判断一个月份,然后再从上年结转到当月等一系列字段加起来。累不累呀?ADDHSLVT THEN HSL01 UNTILL HSLXX GIVING XXX,这语句多好用呀。
九、注意清空中间内表。有人不喜欢清空中间内表,认为程序结束后会自动清空。要是用户在结果屏幕上待上半天呢?何况有些处理大数量的程序如果不及时清空,本身跑起来就会耗费大量的内存资源。曾经一个报表,就一个CLEAR语句,就解决了其性能问题。
十、多了解点业务。有时候业务顾问给的数据逻辑能解决问题,但绝对不是最优的。我们完全可以采用更好的数据逻辑来处理数据。新项目上可能不用这样想,但一些优化项目上这么做是必须的。
一般情况下,我开发ABAP程序的时候,变量及类型的命名采用以下命名规则。可能不是最优的,但能回避相当多的问题。如果自己没制定出成形的命名规则,不妨使用一下,肯定比胡乱命名要好的多。
1、选择屏幕
·P_XXXX:PARAMETERS 定义的单值输入框
·S_XXXX:SELECT-OPTIONS 定义的范围输入框
·RADX:PARAMETERS 定义的 RADIOBUTION 类型的单选按钮
·CB_XXX:PARAMETERS 定义的 CHECKBOX 类型的复选框
·XXXX:选择屏幕上定义的输出块
2、程序内常用的变量与类型命名规则:使变量名称尽可能的表明变量的类型
·CON_XXX: 程序常量
·TYP_XX:程序内定义的结构类型
·TYP_T_XX:程序内定义的内表类型的结构类型
·R_XXXX:程序内定义的RANGES变量
·G_XXXX:程序内定义的全局变量
·GW_XXX:程序内定义的工作区:全局变量 也可以用 WA_XXX
·GT_XXX:程序内定义的内表:全局变量
·CL_XXX:全局类的变量声明
· 全局的字段符声明,下划线前的两个字母根据字段符的类型确定
·MCR_XXXX:程序内定义的宏
·SUB_XXX:程序内定义的字程序
·LR_XXX: 子程序内定义的RANGE变量
·L_XXXX: 子程序内定义的局部变量
·LW_XXX: 子程序内定义的工作区:局部变量
·LT_XXX: 子程序内定义的内表:局部变量
·LC_XXXX:程序内定义的类 子程序内不建议定义类,如果定义使用此命名规则
·MCR_XXX 宏定义在一个程序中用的不是特别多,命名规则可以和全局宏的命名规则相同。
以上命名的一个大规则就是,全局变量用一个母或是G加相应的类别字母开头;局部变量以L加相应的类别字母开头。子程序的形式参数的命名规则尊守局部变量的命名规则。
* 以下命名规则不是必须的
·STATUSX:程序内定义的状态
·PF_STATUS:程序内定义的用户状态
3、内表与变量的命名规则:使变量名称尽可能的表明变量的意义
·内表与工作区命名规则
GT_EKKO:使用数据库表的表名,使内表名称表明主要保存的是哪个数据库表的数据
GT_SUM_EKKO:在数据库表的表名前加一个简写单词,表明内表的主要用途,而不是用1\2\3等数字代替
GT_RESULT:使用比较固定的单词,表明内表的主要使用目的,类似的常用内表名还有GT_EXCEL、GT_FIELD、GT_FIELDCAT
GT_EVENTS:特定的地方,使用相对固定的内表名称(此名称是用在ALV的事件处理上的)
GT_ITEMX: BAPI函数的内表则主要标明变量类别,意义则采用BAPI函数上的名称
·变量的命名规则:使变量名称尽可能的表明变量的意义
G_DMBTR: 使用字段表明字段的类型与意义
G_INDEX: 使用单词表明字段的意义,再如:G_ROW、G_COLWN、G_INDIC
CL_GRID: 使用类别名或特定的字段来用到特定的对象上(此字段是ALV输出时常用的一个字段)
G_MSG: 使用单词的简写来表明此字段的意义
G_HSLXX: 当内容相近的字段比较多时,可以使用中文首母或数字来表明字段的内容(期间金额)
常用的ABAP程序模版,使用以下模版就不错。
*@---------------------------------------------------------------------*
*@ Report ZTESTXUE68 常用的程序模版
*@ T-code
*@---------------------------------------------------------------------*
*@ Created by Xavery Hsueh(薛现军) on 2011-03-06
*@
*@ Lasted Edited date:
*@---------------------------------------------------------------------*
REPORT ztestxue68 NO STANDARD PAGE HEADING.
************************************************************************
** 声明数据库表 Declaration ofdatabase **
************************************************************************
TABLES:coep,
coss. "
************************************************************************
** 定义结构类型 Define the structure'stype **
************************************************************************
************************************************************************
** 定义变量与内表 Define the variants and Internaltables **
************************************************************************
************************************************************************
** 宏定义 Define themacro **
************************************************************************
DEFINE mcr_range.
clear &1.
&1-sign = 'I'.
&1-option = &2.
&1-low = &3.
&1-high = &4.
append &1.
END-OF-DEFINITION.
************************************************************************
** 选择屏幕 Customize theselection-screen **
************************************************************************
SELECTION-SCREEN BEGIN OF BLOCK xavery WITH FRAME TITLEtext_001.
PARAMETERS: p_erdat TYPE dats DEFAULTsy-datum. "统计日期
PARAMETERS: p_kokrs TYPE kokrsOBLIGATORY. "控制范围
SELECT-OPTIONS s_kstar FORcoep-kstar. "成本要素
SELECTION-SCREEN END OF BLOCK xavery.
************************************************************************
** 执行程序事件 Executing the program'sevents **
************************************************************************
INITIALIZATION.
PERFORM sub_init_cond.
START-OF-SELECTION.
PERFORM sub_query_vbak.
PERFORM sub_query_likp.
PERFORM sub_query_text.
PERFORM sub_prcess_data.
PERFORM sub_process_text.
END-OF-SELECTION.
输出结果内表的子程序调用
*@---------------------------------------------------------------------*
*@ Form SUB_INIT_COND
*@---------------------------------------------------------------------*
* 初始化选择条件
*----------------------------------------------------------------------*
FORM sub_init_cond .
text_001 = '选择屏幕'.
ENDFORM. " SUB_INIT_COND
使用以上程序模版,将类型、变量、宏、子程序等放到相应的注释下,再加上SAP的导航栏,操作起来是非常方便的,这比使用INCLUDE程序要方便的多。
常用的ABAPALV程序模版。ABAP程序开发中,ALV报表的输出占了一半以上,基于这一点的考虑,ALV报表我一般使用如下的模版。
*&---------------------------------------------------------------------*
*& Report ZTESTXUE56 采购订单发货跟踪表
*&
*&---------------------------------------------------------------------*
*& Created by Xavery Hsueh on 2014-02-13
*&
*&---------------------------------------------------------------------*
REPORT ztestxue56 NO STANDARD PAGE HEADING.
************************************************************************
** 声明数据库表 Declaration ofdatabase **
************************************************************************
TABLES:ekko,
ekpo,
ekbe,
lfa1. "
************************************************************************
** 定义结构类型 Define the structure'stype **
************************************************************************
TYPES:BEGIN OF typ_result,
ebeln TYPE ekpo-ebeln,
ebelp TYPE ekpo-ebelp,
lifnr TYPE ekko-lifnr,
name1 TYPE lfa1-name1,
matnr TYPE ekpo-matnr,
maktx TYPE makt-maktx,
matkl type mara-matkl,
menge TYPEekpo-menge, "采购订单数量
bdmng TYPEekpo-menge, "收货数量
inmng TYPEekpo-menge, "发票校验数量
box TYPE c,
END OF typ_result.
TYPES:BEGIN OF typ_lfa1,
lifnr TYPE lfa1-lifnr,
name1 TYPE lfa1-name1,
END OF typ_lfa1.
TYPES:BEGIN OF typ_ekbe,
ebeln TYPE ekbe-ebeln,
ebelp TYPE ekbe-ebelp,
vgabe TYPE ekbe-vgabe,
menge TYPE ekbe-menge,
bwart TYPE ekbe-bwart,
END OF typ_ekbe.
************************************************************************
** 定义变量与内表 Define the variants and Internaltables **
************************************************************************
DATA:gt_result TYPE TABLE OFtyp_result WITH HEADER LINE,
gt_makt TYPE TABLE OF makt WITH HEADER LINE,
gt_lfa1 TYPE TABLE OF typ_lfa1 WITH HEADER LINE,
gt_ekbe TYPE TABLE OF typ_ekbe WITH HEADER LINE,
gt_sum_ekbe TYPE TABLE OF typ_ekbe WITH HEADER LINE.
FIELD-SYMBOLS: TYPE typ_result.
TYPE-POOLS:slis.
DATA: cl_grid TYPE REF TO cl_gui_alv_grid,
g_repid LIKE sy-repid,
g_structure_name TYPE tabname,
g_command TYPE slis_formname,
g_title TYPE lvc_title,
g_setting TYPE lvc_s_glay,
wa_print TYPE slis_print_alv,
gt_list_top_of_page TYPE slis_t_listheader,
gt_events TYPE slis_t_event WITH HEADER LINE,
gt_sort TYPE slis_t_sortinfo_alv,
wa_sort TYPE slis_sortinfo_alv,
wa_layout TYPE slis_layout_alv,
gt_fieldcat TYPE slis_t_fieldcat_alv,
wa_fieldcat LIKE LINE OF gt_fieldcat,
g_field TYPE char30,
g_save TYPE c,
g_con_mark TYPE slis_fieldcat_alv-fieldname VALUE 'MARK',
g_length TYPE i,
g_pos TYPE i.
FIELD-SYMBOLS:.
************************************************************************
** 宏定义 Define themacro **
************************************************************************
DEFINE mcr_range.
clear &1.
&1-sign = 'I'.
&1-option = &2.
&1-low = &3.
&1-high = &4.
append &1.
END-OF-DEFINITION.
* 给FILEDCAT ALV内表赋值
DEFINE mcr_field.
clear wa_fieldcat.
clear g_field.
g_pos = g_pos + 1 .
wa_fieldcat-col_pos = g_pos.
wa_fieldcat-fieldname = &1.
wa_fieldcat-no_zero = 'X'.
wa_fieldcat-tabname = 'GT_RESULT'.
* wa_fieldcat-no_out ='X'. "field no display, choose from layout
wa_fieldcat-key =&2. "SUBTOTAL KEY
wa_fieldcat-seltext_l = &3.
* 计算输出字段的长度
concatenate 'GT_RESULT-' &1 intog_field.
assign (g_field) to .
describe field output-length g_length.
wa_fieldcat-outputlen = g_length.
append wa_fieldcat to gt_fieldcat.
END-OF-DEFINITION.
************************************************************************
** 选择屏幕 Customize theselection-screen **
************************************************************************
SELECTION-SCREEN BEGIN OF BLOCK xavery WITH FRAME TITLEtext-001.
PARAMETERS:p_bsart TYPE ekko-bsart OBLIGATORY DEFAULT 'NB'.
SELECT-OPTIONS: s_lifnr FOR lfa1-lifnr,
s_ekorg FOR ekko-ekorg,
s_bedat FOR ekko-bedat.
SELECTION-SCREEN END OF BLOCK xavery.
************************************************************************
** 执行程序事件 Executing the program'sevents **
************************************************************************
INITIALIZATION.
PERFORM sub_init_cond.
START-OF-SELECTION.
PERFORM sub_query_ekbe.
PERFORM sub_process_result.
PERFORM sub_query_text.
PERFORM sub_process_text.
END-OF-SELECTION.
PERFORM sub_create_fieldcat.
PERFORM sub_init_layout.
PERFORM sub_display_as_alv. "以ALV的方式输出结果表
*@---------------------------------------------------------------------*
*@ Form SUB_INIT_COND
*@---------------------------------------------------------------------*
* 初始化选择条件
*----------------------------------------------------------------------*
FORM sub_init_cond .
ENDFORM. " SUB_INIT_COND
*&---------------------------------------------------------------------*
*& Form SUB_QUERY_EKBE
*&---------------------------------------------------------------------*
* 查询采购订单相关的数据
*----------------------------------------------------------------------*
FORM sub_query_ekbe .
SELECT ekko~ebeln
ekpo~ebelp
ekpo~matnr
ekpo~menge
ekpo~matkl
ekpo~elikz
ekko~lifnr
FROM ekko INNER JOIN ekpo ON ekko~ebeln = ekpo~ebeln
INTO CORRESPONDING FIELDS OF TABLE gt_result
WHERE bsart EQ p_bsart AND
ekorg IN s_ekorg AND
lifnr IN s_lifnr AND
bedat IN s_bedat.
CHECK gt_result[] IS NOT INITIAL.
SELECT ebeln
ebelp
vgabe
menge
bwart
FROM ekbe
INTO TABLE gt_ekbe
FOR ALL ENTRIES IN gt_result
WHERE ebeln = gt_result-ebeln AND
ebelp = gt_result-ebelp.
SORT gt_ekbe BY ebeln ebelp vgabe.
LOOP AT gt_ekbe.
AT NEWvgabe.
CLEAR gt_sum_ekbe.
ENDAT.
gt_sum_ekbe-ebeln = gt_ekbe-ebeln.
gt_sum_ekbe-ebelp = gt_ekbe-ebelp.
gt_sum_ekbe-vgabe = gt_ekbe-vgabe.
IFgt_ekbe-bwart = '101' OR gt_ekbe-bwart = ''.
gt_sum_ekbe-menge = gt_sum_ekbe-menge + gt_ekbe-menge.
ELSEIFgt_ekbe-bwart = '102'.
gt_sum_ekbe-menge = gt_sum_ekbe-menge - gt_ekbe-menge.
ENDIF.
AT END OFvgabe.
APPEND gt_sum_ekbe.
ENDAT.
ENDLOOP.
* 释放中间内表
FREE:gt_ekbe.
ENDFORM. " SUB_QUERY_EKBE
*&---------------------------------------------------------------------*
*& Form SUB_QUERY_TEXT
*&---------------------------------------------------------------------*
* 查询文本描述信息
*----------------------------------------------------------------------*
FORM sub_query_text .
CHECK gt_result[] IS NOT INITIAL.
SELECT * FROM makt
INTO TABLE gt_makt
FOR ALL ENTRIES IN gt_result
WHERE matnr = gt_result-matnr AND
spras = sy-langu.
SELECT lifnr
name1
FROM lfa1
INTO TABLE gt_lfa1
FOR ALL ENTRIES IN gt_result
WHERE lifnr = gt_result-lifnr.
ENDFORM. " SUB_QUERY_TEXT
*&---------------------------------------------------------------------*
*& Form SUB_PROCESS_RESULT
*&---------------------------------------------------------------------*
* 将采购订单数据更新到结果内表
*----------------------------------------------------------------------*
FORM sub_process_result .
SORT gt_sum_ekbe BY ebeln ebelp vgabe.
LOOP AT gt_result ASSIGNING .
CLEARgt_sum_ekbe.
READ TABLEgt_sum_ekbe WITH KEY ebeln = -ebeln
ebelp = -ebelp
vgabe = 1
BINARY SEARCH.
IF sy-subrc= 0.
-bdmng = gt_sum_ekbe-menge.
ENDIF.
CLEARgt_sum_ekbe.
READ TABLEgt_sum_ekbe WITH KEY ebeln = -ebeln
ebelp = -ebelp
vgabe = 2
BINARY SEARCH.
IF sy-subrc= 0.
-inmng = gt_sum_ekbe-menge.
ENDIF.
ENDLOOP.
* 释放中间内表
FREE:gt_sum_ekbe.
ENDFORM. " SUB_PROCESS_RESULT
*&---------------------------------------------------------------------*
*& Form SUB_PROCESS_TEXT
*&---------------------------------------------------------------------*
* 将文本信息更新到结果内表
*----------------------------------------------------------------------*
FORM sub_process_text .
SORT gt_makt BY matnr.
SORT gt_lfa1 BY lifnr.
LOOP AT gt_result ASSIGNING .
CLEARgt_makt.
READ TABLEgt_makt WITH KEY matnr = -matnr
BINARY SEARCH.
IF sy-subrc= 0.
-maktx = gt_makt-maktx.
ENDIF.
CLEARgt_lfa1.
READ TABLEgt_lfa1 WITH KEY lifnr = -lifnr
BINARY SEARCH.
IF sy-subrc= 0.
-name1 = gt_lfa1-name1.
ENDIF.
ENDLOOP.
* 释放中间内表
FREE:gt_makt,
gt_lfa1.
ENDFORM. " SUB_PROCESS_TEXT
*&---------------------------------------------------------------------*
*& Form SUB_CREATE_FIELDCAT
*&---------------------------------------------------------------------*
* 给输出的结果内表指定字段
*----------------------------------------------------------------------*
FORM sub_create_fieldcat .
CLEAR gt_fieldcat[].
mcr_field 'EBELN' 'X' '采购订单号'.
mcr_field 'EBELP' 'X' '订单行项目'.
mcr_field 'LIFNR' '' '供应商账号' .
mcr_field 'NAME1' '' '供应商名称' .
mcr_field 'MATNR' '' '物料编号' .
mcr_field 'MATKL' '' '物料组'.
mcr_field 'MAKTX' '' '物料描述'.
mcr_field 'MENGE' '' '订单数量' .
mcr_field 'BDMNG' '' '收货数量' .
mcr_field 'INMNG' '' '发票校验数量' .
ENDFORM. " SUB_CREATE_FIELDCAT
*&---------------------------------------------------------------------*
*& Form SUB_INIT_LAYOUT
*&---------------------------------------------------------------------*
* 设置常用的输出布局参数
*----------------------------------------------------------------------*
FORM sub_init_layout .
wa_layout-zebra = 'X'.
wa_layout-window_titlebar ='采购发货跟踪表'.
wa_layout-colwidth_optimize = 'X'.
wa_layout-box_fieldname = 'BOX'.
wa_layout-header_text = '选择'.
ENDFORM. " SUB_INIT_LAYOUT
*&---------------------------------------------------------------------*
*& Form SUB_DISPLAY_AS_ALV
*&---------------------------------------------------------------------*
* 调用 ALV 的FUNCTION来输出结果
*----------------------------------------------------------------------*
FORM sub_display_as_alv .
g_repid = sy-repid.
g_setting-coll_top_p ='X'. "最小化 CALLBACK-TOP-OF-PAGE.
* ABAP List Viewer
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
EXPORTING
i_callback_program = g_repid
i_structure_name = 'TYP_RESULT'
i_grid_title = g_title
i_grid_settings = g_setting
i_callback_user_command ='SUB_USER_COMMAND'
i_callback_pf_status_set = 'SUB_SET_PF_STATUS'
i_save = g_save
is_layout = wa_layout
it_fieldcat = gt_fieldcat[]
TABLES
t_outtab = gt_result
EXCEPTIONS
program_error = 1
OTHERS = 2.
ENDFORM. " SUB_DISPLAY_AS_ALV
*@---------------------------------------------------------------------*
*@ FORMSUB_SET_PF_STATUS *
*@---------------------------------------------------------------------*
* 设置ALV菜单
* 通过SE41,拷贝程序SAPLSLVC_FULLSCREEN的状态STANDARD_FULLSCREEN过来
*@---------------------------------------------------------------------*
FORM sub_set_pf_status USING rt_extab TYPE slis_t_extab.
SET PF-STATUS 'STANDARD_FULLSCREEN'.
ENDFORM. "sub_set_pf_status
*@--------------------------------------------------------------------*
*@ Form sub_user_command
*@--------------------------------------------------------------------*
* -->R_UCOMM 事务功能码
* -->RS_SELFIELD ALV相关的数据
*---------------------------------------------------------------------*
FORM sub_user_command USINGr_ucomm LIKE sy-ucomm
rs_selfield TYPE slis_selfield.
DATA l_ebeln TYPE ekko-ebeln.
l_ebeln = rs_selfield-value+0(10).
CASE r_ucomm.
WHEN'&IC1'. "双击事件的功能码
PERFORM sub_ucomm_double_click USING l_ebeln.
WHEN'EDIT'. "刷新订单的特性值
* PERFORM sub_ucomm_update.
WHENOTHERS.
ENDCASE.
* 刷新ALV报表
rs_selfield-refresh = 'X'.
ENDFORM. "sub_user_command
*&---------------------------------------------------------------------*
*& Form SUB_UCOMM_DOUBLE_CLICK
*&---------------------------------------------------------------------*
* 实现ALV 的双击跳转功能
*----------------------------------------------------------------------*
FORM sub_ucomm_double_click USING l_ebeln TYPE ekko-ebeln.
CALL FUNCTION'ME_DISPLAY_PURCHASE_DOCUMENT'
EXPORTING
i_ebeln = l_ebeln
EXCEPTIONS
not_found = 1
no_authority = 2
invalid_call = 3
preview_not_possible = 4
OTHERS = 5.
IF sy-subrc <> 0.
MESSAGE IDsy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
ENDFORM. " SUB_UCOMM_DOUBLE_CLICK
本程序是一个项目上的实用程序,几经修订后变成了我常用的ALV程序的模版。
1、首先,ALV的变量是比较全的。一般情况下的ALV报表输出,不用再新增输出格式相关的变量。再是ALV报表的几个子程序也是固定的,使用ALV 输出,只要将这些子程序COPY过去,再做简单的修改就可以满足了。
2、本程序的命名规则也是很规范的。本程序曾经扩展到2000多行,业务延伸到了应付账款及账龄分析。在命名统一、子程序模块化的情况下,一点都不杂乱。移交给客户时非常的简单明了。不会因为逻辑的混乱而产生什么误解。
3、注意子程序的模块化。虽然只是五六百行的小程序,但取数与处理部分仍然分成了四个子程序。这在阅读程序的时候,只要双击一下START-OF-SELECTION,就可以找到相应的目录,非常简单位。扩展的时候也是先在事件下添加子程序调用,再双击子程序创建的。若一个子程序的代码超过三四百行,此程序的可读性就大大降低了。
4、程序的缩进与SQL的查询都很规范。缩进就不说了,一目了然。SQL的查询中,本程序使用了一定的内连接,简化了代码。在循环处理进又采用了BINARYSEARCH等小技巧,程序性能相当地出众。每个子程序的结束都将过期的内表释放掉,节约了内存。
ABAP程序设计的一点建议相关推荐
- 【职场】肺腑之言,给即将参加秋招的同学一点建议
文章来源于AI的那些事儿,作者黄鸿波 7月份到了,很多公司都陆陆续续的开启了秋招的进程,也有不少2021年毕业的同学也都在积极的准备着,并且也有很多同学都已经进入到了提前批的面试阶段.今天我就结合我自 ...
- 阳光学院计算机科学与技术需要英语四级,给各位想报阳光的朋友一点建议!来自学长的亲身经历!...
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 给各位想报阳光的朋友一点建议!来自学长的亲身经历! 首先,不要期望阳光学院的师资有多好.从师资上来说,阳光学院早期聘用的是福大的老师没错,但是阳光现在为了 ...
- Mysql数据库的瓶颈处理一点建议
Mysql数据库的瓶颈处理一点建议 我们在使用Mysql数据库是常见的两个瓶颈是CPU和I/O的瓶颈,CPU在饱和的时候一般发生在数据装入内存或从磁盘上读取数据时候.磁盘I/O瓶颈的出 ...
- #今日论文推荐# 陈天奇、王威廉等人推荐:ACL最佳论文奖得主给新入行研究者的一点建议
#今日论文推荐# 陈天奇.王威廉等人推荐:ACL最佳论文奖得主给新入行研究者的一点建议 本文将对两篇篇博客的中心思想进行了编译整理(以第一人称转述),内容如下: 前提:扩展你的相邻可能 想法往往出现在 ...
- 学校计算机基础做慢了扣分,中职学校《计算机应用基础》课程改革的一点建议...
中职学校<计算机应用基础>课程改革的一点建议 论文关键词:课程改革 任务驱动 模式化教学 过程性评价 教育技术 论文摘要:本文针对目前中职学校中学生的现状,以及计算机应用基拙教学中存在的问 ...
- 中职学校计算机应用基础学什么,浅谈中职学校《计算机应用基础》课程改革的一点建议...
<浅谈中职学校<计算机应用基础>课程改革的一点建议>由会员分享,可在线阅读,更多相关<浅谈中职学校<计算机应用基础>课程改革的一点建议(3页珍藏版)>请 ...
- 给B2C网站企业的一点建议
在周末时,我有了一次不太愉快的购物体验,自己经常使用的一款洗面奶用完了,但在周边超市购物时,并没有发现有该牌子的洗面奶销售,考虑到可以等待几天,故考虑从唯品会或者乐蜂上购买购买(个人看法:淘宝信不过, ...
- 给在北漂准备租房的菜鸟一点建议
最近这两天很烦,因为租房子的事情.事情现在还没算处理完,但是这次也被教育了,给在北漂准备租房的菜鸟一点建议(不喜勿喷) 我之前一直在上家公司的宿舍住,地点北京丰台郊区,那边没有地铁但是距离工作地点近. ...
- 上交大计算机复试机师难不难,一个去年考交大复试被刷的人给大家一点建议(更新)...
呵呵,很少来上网,不过看到现在的数学版真的是比去年差多了,有些话心里想说很久了,一直没机会说,因为很少有机会说,不过我蛮担心有些人学习方法不恰当,所以来谈谈过来人的建议. 我去年考交大信息安全学院通信 ...
最新文章
- Node中使用mysql模块遇到的问题
- 并发环境下,先操作数据库还是先操作缓存?
- Effective Java之覆盖equal时要遵守通用约定(八)
- 回归树与基于规则的模型(part2)--简单回归树
- 张腾:腾讯云融合通信应用场景及案例分享
- oracle dump enq hw,经典故障分析 - ASSM引发的索引争用与 enq HW -contentio
- 密码学在区块链中的应用 【八】
- TKDragView_TKCalendarView:页面curl的动画日历
- 64如何传入后台_如何保证API接口数据安全?
- android gridvie item,Android开发―解决自定义GridView高度第一个item高度异常问题
- xrld读取excel 中合并单元格内容
- 使用echars制作家谱图
- Android ViewBinding使用详解
- 查杀计算机病毒,计算机病毒查杀
- MySQL Server 5.7.13
- Perl中use strict
- HTML+CSS入到到精通
- JiangxiBank
- 如何理解 “Dense object detection“中的dense?
- Linux系统简介及简要shell命令介绍(2)