• 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语句

  • 相关阅读:
    POJ3259 Wormholes
    leetCode-Plus One
    leetCode-Pascal's Triangle
    leetCode-Longest Continuous Increasing Subsequence
    leetCode-Missing Number
    leetCode-Maximum Product of Three Numbers
    leetCode-Image Smoother
    leetCode-Contains Duplicate
    机器学习实战笔记-使用Apriori算法进行关联分析
    leetCode-Degree of an Array
  • 原文地址:https://www.cnblogs.com/jenvid/p/8303805.html
Copyright © 2020-2023  润新知