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程序设计的一点建议的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: BAPI FOR MD61,MD62,M
- 下一篇: 更新自定义表时的通用锁对象