ABAP基礎4:模塊化


子程序定義

以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.

總結:

  1. 在from語句中不適用value語句, using與changing
  2. 出於可讀性考慮,using代表傳遞數據,changging代表傳遞數據后變更值
  3. 因此使用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語句

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM