子程序定义

以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  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  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 ,
gv_val2 type i value ,
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 = .
append gs_str to gt_itab. gs_str-col1 = 'B'.
gs_str-col2 = .
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 = .
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 = .
append gs_str to gt_itab. data: gv_name type char10.
gv_name
= 'COL1'. " gs_str-col1 = 'B'.
gs_str-col2 = .
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 = .
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() type c value 'Enjoy',
gv_val2() type c value 'ABAP',
gv_val3() 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() type c value 'External',
gv_second() type c value 'call',
gv_result() type c.
perform concate_string(z_yzw_struc) if found
using gv_first gv_second
changing gv_result.
  • 动态调用子程序,就是将程序名和子程序名当做实参传进去
data:
gv_first() type c value 'External',
gv_second() type c value 'call',
gv_result() type c.
data:
gv_pname() type c value 'Z_YZW_STRUC',"要用大写,不然系统识别不到
gv_subname() 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  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  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 = .
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 & & into & separated by space.
dis &. "这里在调用一个define,作为实参传递过去
end-of-definition. define dis.
write / &. "打印传进来的内容
end-of-definition. conn gv_val1 gv_val2 gv_val3.

全局MACRO

可以在其他程序中调用,全局MACRO维护在表TRMAC中,可以指定断点时用BREAK语句

ABAP基础4:模块化的更多相关文章

  1. 【ABAP系列】SAP ABAP基础-abap数据类型的解析整理

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP基础-abap数 ...

  2. 【ABAP系列】SAP ABAP基础-录制BDC的MODE定义解析

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP基础-录制BDC ...

  3. 【ABAP系列】SAP ABAP基础-数据更新至数据库操作解析

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP基础-数据更新至 ...

  4. 【ABAP系列】SAP ABAP基础-程序优化及响应速度之LOOP

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP基础-程序优化及 ...

  5. 【ABAP系列】SAP ABAP基础-SQL的嵌套使用

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP基础-SQL的嵌 ...

  6. ABAP基础1:概念

    包(Package)也称作开发类,是为了将程序等对象根据功能划分,进行区分和管理而导入的概念 每一个开发对象,如程序.类,都要隶属一个包,包一般隶属于某一个模块 每个包拥有一个CTS号,CTS号用于系 ...

  7. ABAP基础一:ALV基础之ALV的整体结构

    很久没摸ECC了,最近看到很多新人在捯饬ALV...中国就喜欢量产垃圾...培训,上岗...没有行业道德... 闲话不多说,开始正事: ALV很常见,在SAP非WEB的项目,没有不用的,它包含了报表和 ...

  8. Node基础-CommonJS模块化规范

    1.在本地项目中基于NPM/YARN安装第三方模块 第一步:在本地项目中创建一个"package.json"的文件 作用:把当前项目所有依赖的第三方模块信息(包含:模块名称以及版本 ...

  9. ABAP基础语法

    1.数据类型及属性 类型 说明 C N 0到9之间字符组成的数字字符串 D 日期格式必须为 YYYYMMDD T 格式为 24-hour的 HHMMSS I -2.147.483.648 to +2. ...

随机推荐

  1. CSS常用遮罩层

    为什么80%的码农都做不了架构师?>>>   CSS常用遮罩层 应用场景: 上传了一张图片,鼠标移入到图片上的时候显示遮罩层,并且提示点击删除. 通过改变遮罩层的透明度来实现显示隐藏 ...

  2. BeanDefinition源码解析

    我们知道BeanDefintion定义了Bean在IoC容器内的基本数据结构.在学习IoC之前先了解BeanDefition对我们理解IoC容器是有帮助的. 首先BeanDefinition是一个接口 ...

  3. iOS开发·runtime原理与实践: 消息转发篇(Message Forwarding) (消息机制,方法未实现+API不兼容奔溃,模拟多继承)...

    本文Demo传送门: MessageForwardingDemo 摘要:编程,只了解原理不行,必须实战才能知道应用场景.本系列尝试阐述runtime相关理论的同时介绍一些实战场景,而本文则是本系列的消 ...

  4. Spring MVC的Controller接受请求方式以及编写请求处理方法

    Controller接受请求参数的常见方法: 1.通过Bean接受请求参数: 创建POJO实体类 创建pojo包,并在该包中创建实体类UserForm,代码: package pojo; public ...

  5. 题目分享D 二代目

    题意:给定一个T条边的无向图,求S到E恰好经过N条边的最短路径 T≤100 N≤1000000 分析:(据说好像假期学长讲过) 首先很容易想到的是dp[i][j][k]表示从i到j经过k条边的最短路径 ...

  6. 编译原理-第四章 语法分析-4.7 规范的LR分析

    规范的LR分析 一.规范LR(l)项 二.规范LR(l)项集族 1.构建项目集 2.例 三.规范LR(1)语法分析表 1.构造 2.例1 3.例2 四.LALR语法分析表 1.重要性 2.特点 3.构 ...

  7. Python监控文件夹 && 发送邮件

    直接上代码: # python3 # -*- coding: utf-8 -*- # 2017/06/16 by luohan from email.mime.text import MIMEText ...

  8. Java——Spring整合Mybatis(IDEA版)

    本文适用于初学者: 该文主要教大家如何整合spring和mybatis,整合完成效果,可以从数据库中查询出学生信息: 完整的工程目录如下: 整合思路: 需要spring来管理数据源信息. 需要spri ...

  9. A. Hilbert's Hotel(数学)

    传送门 \(看了一下网上都没什么题解,自己写一篇吧,对你有帮助的话留个言吧~\) \(\color{Orange}{----------------------分割------------------ ...

  10. T - zxa and leaf HDU - 5682 二分+dfs

    T - zxa and leaf HDU - 5682 题目大意是:给你一颗树,这棵树有些节点已经设置了它的美丽值,然后剩下一些节点需要我们设置美丽值. 一条边的丑陋程度等于被定义为由这个边缘连接的两 ...