子程序定義
以form開始,以endform結束,用perform語句調用,from語句可以在程序內部/外部,perform一定要寫在前面
perform.
from.
子程序模塊
endform.
perform writedata. "如果寫到子程序模塊后,這一行會提示 Statement is not accessible 問題:ABAP是編譯型語言還是解釋性語言 form writedata. write 'asdfasdf'. endform. "writedata
或者雙擊子程序名稱,創建子程序
1.在新文件中寫子程序,在調用文件中寫入包含語句
INCLUDE Z_YZW_STRUC_WRITEDATAF01.
2.如果是在原文件寫子程序就寫在perfrom語句下面
子程序參數
- 調用子程序時用於傳入/傳出的值.參數一般用data語句定義的局部變量相同.
- 調用子程序使用的參數是實參, 子程序中的參數叫形參
- perform利用using/changing定義參數,位置參數,順序要保持一致
FROM subr USING p1 TYPE type VALUE(p2) TYPE type ... CHANGING p3 TYPE type VALUE(p4) TYPE type
傳參
使用using和changing語句傳參, 3種方法
- Call by Value, 傳入參數即實參與傳出參數即形參有不同的物理內存, 使用using關鍵字傳遞參數時與value語句一起搭配使用
FROM sub USING ... VALUE(pi) [TYPE <T>| LIKE <F>].
VALUE子句形參占用自己的單獨內存, 調用子程序是,實參值復制到形參中,即使改變形參的值也不戶影響實參值
data: gv_val type c length 20 value 'I am value'. "引號內為實參 perform call_byvalue using gv_val. "執行子程序,帶參數gv_val form call_byvalue using value(p_val). "p_val是形參,是局部變量 write p_val. "打印形參,就是打印實參內容 endform.
- Call by reference, 具有相同的物理內存並且互相傳遞內存地址, 使用changing關鍵字傳參, 改變子程序參數值;調用時,子程序形參內存地址空間指向實參內存地址空間
FROM subr USING ... pi [TYPE <T> |LIKE <F>] ... FROM subr CHANGGING ...pi [TYPE <T> |LIKE <F>] ...
data: gv_val type c length 30 value '我是實參'. write / gv_val. "1打印局部變量 perform call_byvref changing gv_val. "3執行子程序,在子程序中修改了局部變量的值 這里比上面少了value關鍵字,如果不適用value關鍵字,using和changing語句都屬於cal by reference write / gv_val. "4打印被修改后的局部變量 form call_byvref changing p_val. "2子程序 p_val = 'value is changed'. endform.
總結:
- 在from語句中不適用value語句, using與changing
- 出於可讀性考慮,using代表傳遞數據,changging代表傳遞數據后變更值
- 因此使用using時最好加上value語句搭配使用,一眼看出是傳遞數據
- Call by Value and Result, 傳入傳出變量語句執行成功時返回變更后的值.具有不同的物理內存地址
FORM subr CHANGING .. VALUE(PI) [TYPE<T>| LIKE <F>].
using..value無法更改子程序實參值,changing...value在子程序結束時會更改實參值
data: gv_val1 type i value 2, gv_val2 type i value 3, gv_sum type i. perform sum_data using gv_val1 gv_val2 changing gv_sum." using ..changing,下面的子程序結束后,實參gv_sum被更改為p_sum的值 write: / 'result is:', gv_sum. form sum_data using value(p_val1) value(p_val2) changing value(p_sum). "using .. changeing value 只傳值,不能更改實參值 p_sum = p_val1 + p_val2. "三個形參,接收實參值 endform. 最后輸出5
定義參數類型
form的形參可以利用type和like語句定義所有的ABAP數據類型,不指定的話默認是Generic類型,集成實參的技術屬性
data gv_val type c. perform call_byvref changing gv_val. "這里傳遞實參類是c form call_byvref changing p_val type i. "指定形參數據類型為i, 兩種數據類型不能直接轉換 p_val = 'xxxx'. endform.
data gv_val type d. perform subr changing gv_val. *形參類型定義方法有3種 *1.直接不指定形參類型,使用默認Generic *perform subr changing pv_val. *2.使用相同數據類型 *perform subr changing pv_val type d. *3.使用相同類型的變量 *perform subr changing pv_val like gv_val.
參數與結構體
結構體與形參一樣可以使用所有的ABAP數據類型
當結構體作為參數時,可以使用type/like定義,還可以使用structrue語句定義結構體類型
FORM subr USING p_str STRUCTURE str ... FORM subr USING p_str TYPE str ... FORM subr USING p_str LIKE str ...
data: begin of gs_str, col1 value 'A', col2 value 'B', end of gs_str. perform write_data using gs_str. form write_data using ps_str structure gs_str. "形參使用結構體數據類型 write: ps_str-col1, ps_str-col2. endform.
參數與內表
子程序參數為內表時也可以使用關鍵字USING/CHANGING
FROM subr CHANGING ... <itab> [TYPE<t> | LIKE <f>]
types: begin of t_str, col1 type c, col2 type i, end of t_str. "定義結構體 types: t_itab type table of t_str."定義內表形式 data: gs_str type t_str,"根據結構體分別定義變量和內表,內表具有兩列 gt_itab type t_itab. gs_str-col1 = 'A'. gs_str-col2 = 1. append gs_str to gt_itab. gs_str-col1 = 'B'. gs_str-col2 = 2. append gs_str to gt_itab. perform test_itab using gt_itab. "gt_itab是實參,內表類型 form test_itab using pt_itab type t_itab."形參指定數據類型為內表 read table pt_itab with key col1 = 'A' into gs_str. "read table tabname with key condition into 變量,從表中讀取符合條件的數據保存到變量 if sy-subrc = 0 . write : gs_str-col1, gs_str-col2. endif. endform.
types: begin of t_str, col1 type c, col2 type i, end of t_str. "定義結構體 types: t_itab type table of t_str."定義內表形式 data: gs_str type t_str,"根據結構體分別定義變量和內表,內表具有兩列 gt_itab type t_itab. gs_str-col1 = 'A'. gs_str-col2 = 1. append gs_str to gt_itab. data: gv_name type char10. gv_name = 'COL1'. " gs_str-col1 = 'B'. gs_str-col2 = 2. append gs_str to gt_itab. perform test_itab using gt_itab. "gt_itab是實參,內表類型 form test_itab using pt_itab type any table."形參指定為任意表類型, 下面的read要用動態條件,即傳值進去,不然動態表找不到列名 read table pt_itab with key (gv_name) = 'A' into gs_str. "read table tabname with key condition into 變量,從表中讀取符合條件的數據保存到變量 if sy-subrc = 0 . write : gs_str-col1, gs_str-col2. endif. endform.
使用內表指定參數也有三種方法:
- 使用Generic type
FROM subr CHANGING pt_itab TYPE TABLE. FROM subr CHANGING pt_itab TYPE ANY TABLE. FROM subr CHANGING pt_itab TYPE INDEX TABLE. FROM subr CHANGING pt_itab TYPE STANDARD TABLE. FROM subr CHANGING pt_itab TYPE SORTED TABLE. FROM subr CHANGING pt_itab TYPE HASHED TABLE.
- 使用與實參相同的內表類型
FROM subr CHANGING pv_val TYPE i_tab.
- 使用與實參具有相同類型的內表
FROM subr CHANGING pv_val LIKE gt_itab.
TABLES語句
Rel3.0以前使用tables,可以替代USING與CHANGING語句
調用子程序
- 調用子程序的方法有Inetrnal/External,外部調用的子程序名后面要明確指定蓋子程序所屬程序名
- 通過perform可以調用ABAP程序內部子程序,也可以調用其他程序的子程序
調用語法
PERFORM sub. PERFORM subr(prog) [IF FOUND]. 括號內是外部程序名
- 調用內部子程序
data: gv_val1(10) type c value 'Enjoy', gv_val2(10) type c value 'ABAP', gv_val3(20) type c. perform concate_string using gv_val1 gv_val2 changing gv_val3. *form concate_string using value(p_val1) value(p_val2) changing value(p_val3). form concate_string using p_val1 p_val2 changing p_val3. concatenate p_val1 p_val2 into p_val3 separated by space. perform write_data using p_val3. "嵌套一個子程序,直接輸出不行? endform. form write_data using value(p_val). write: / p_val. endform.
- 調用外部子程序
data: gv_first(10) type c value 'External', gv_second(10) type c value 'call', gv_result(20) type c. perform concate_string(z_yzw_struc) if found using gv_first gv_second changing gv_result.
- 動態調用子程序,就是將程序名和子程序名當做實參傳進去
data: gv_first(10) type c value 'External', gv_second(10) type c value 'call', gv_result(20) type c. data: gv_pname(20) type c value 'Z_YZW_STRUC',"要用大寫,不然系統識別不到 gv_subname(20) type c value 'CONCATE_STRING'."要用大寫,不然系統識別不到 perform (gv_subname) in program (gv_pname) if found using gv_first gv_second changing gv_result.
利用list調用子程序
PERFORM idx OF subr1 subr2 .. subrn
根據順序索引調用列出的子程序,只能調用內部子程序,且不能指定參數
do 2 times. perform sy-index of subr1 subr2. enddo. form subr1. write / '1 subroutine is called'. endform. form subr2. write / '2 subroutine is called'. endform.
循環
do ~ while
- 可以指定循環次數的語句,不指定次數,進入死循環
- 循環次數保存在系統變量sy-index
do 3 times. ... enddo.
while ~ endwhile
- 當while語句的表達式結果為真,進入循環
- 循環次數保存在系統變量sy-index
while gv_flag = 'X'. ~~ endwhile.
loop ~ endloop
- 按順序依次循環內表,將讀取內表行數據保存到工作區或者表頭的循環語句.
- 循環次數保存在系統變量sy-index, sy-tabix表示內表的當前行數
loop at gt_itab to gs_wa.
~~~
endloop.
結束子程序
- endform, 正常結束
- exit, 直接跳出子程序
- check, 結果為假跳出子程序
parameters: p_val type char10. perform end_subr using p_val. form end_subr using value(p_val). case p_val. when 'EXIT'. "屏幕輸入后系統會轉換成大寫 write 'subroutine exit'. exit. when 'CHECK'. write 'value check'. when others. endcase. write 'subroutine is normally ended'. endform. "end_subr
判斷語句
if condition.
~~~
elseif codition.
~~~
else.
~~~
endif.
case variable
when value1.
~~~
when value2.
~~~
when OTHERS.
~~~
endcase.
臨時子程序
創建一個程序池,存儲子程序
GENERATE Subroutin POOL <itab> NAME <PROG>.
PERFORM ON COMMIT
- using perform on cmmit, 遇到commit work時調用子程序
select single * from scarr into gs_scarr where carrid ='AA'. "gs_scarr存儲1條數據 perform delete_data using gs_scarr. "子程序正常執行 perform insert_data on commit. "子程序定義時帶有選項on commit,遇到commit work才執行 if gv_flg = 'X'. commit work. "第二個子程序再這里開始執行 endif. form delete_data using value(ps_scarr) type scarr. delete scarr from ps_scarr. "從表scarr中刪除符合條件的條目 if sy-subrc = 0. gv_flg = 'X'. endif. endform. form insert_data. insert scarr from gs_scarr. endform.
- using perform on rollback, 遇到rollback work時調用子程序
局部Macro
減少代碼重復,定義如下,但是不能在其他程序中調用
DEFINE macro. ~~~ END-OF-DEFINITION.
data: gv_val1 type c value 'A', gv_val2 type c value 'B', gv_val3 type char3. define conn. concatenate &1 &2 into &3 separated by space. dis &3. "這里在調用一個define,作為實參傳遞過去 end-of-definition. define dis. write / &1. "打印傳進來的內容 end-of-definition. conn gv_val1 gv_val2 gv_val3.
全局MACRO
可以在其他程序中調用,全局MACRO維護在表TRMAC中,可以指定斷點時用BREAK語句