ABAP学习笔记之——第四章:模块化程序

news2025/3/1 13:49:28

一、子程序:

语法:

参数:

参数(Parameter)是指调用子程序时用于传入、传出的值。子程序中的参数与一般用 DATA语句定义的局部变量相同。调用子程序时使用的参数叫实参(Actual Parameter),在子程序中使用的参数叫虚参(Formal Parameter)。PERFORM 利用 USING、CHAING 定义参数,且使用时要与子程序的顺序一致。参数可以使用 ABAP 的所有对象,即基本数据类型、Field Smbol、内表等。

传递参数的三种方法:

Call by value:

传入参数即实参(Actual Parameter)与传出参数即虚参(Formal Parameter)有不同的物理内存。

VALUE 语句中虚参(FormalParameter)占用自己的单独内存。调用子程序时,实参(ActualParameter)值复制到虚参中,即使改变虚参的值也不会影响实参值。

例:

*call by value   using参数用法
DATA: gv_val TYPE c LENGTH 20 VALUE 'call by value test'.
PERFORM call_byvalue USING gv_val.
FORM call_byvalue USING VALUE(p_val).
  WRITE p_val.
ENDFORM.

Call by reference:

共有相同的物理内存并且互相传递地址。

子程序的虚参没有自己的内存空间。只是在调用子程序期间占用实参的地址。即在调用Subroutine 的程序的内存地址(相同名字的变量)中进行工作。

例:

*call by reference  changing参数用法
DATA : gv_val TYPE c LENGTH 30 VALUE 'call by reference test'.
WRITE / gv_val.
PERFORM call_byvref CHANGING gv_val.
WRITE / gv_val.
FORM call_byvref CHANGING p_val.
  p_val = 'value is changed'.
ENDFORM.

Call by Value and Result:

传入传出变量语句执行成功时返回变更后的值。拥有不同的物理地址。

USING 语句与VALUE 语句一起搭配使用,则无法修改子程序中的实参值(Call by value),但是 CHANGING 语句与 VALUE 语句一起配套使用时,当正常结束子程序时会修改实参值练习做一个定义整数类型的3 个变量后,在FORM语句内执行加法的程序。

例:

*call by value and result   changing 和 using 混合使用
PARAMETER :val1 TYPE i,
      val2 TYPE i.
DATA gv_sum  TYPE i.
PERFORM sum_data USING val1 val2
      CHANGING gv_sum.
WRITE : / 'resukt is :',gv_sum.
FORM sum_data USING VALUE(p_val1) VALUE(p_val2)
      CHANGING VALUE(p_sum).
  p_sum = p_val1 + p_val2.
ENDFORM.

参数类型:

FORM语句内的虚参(Formal Parameter)可以利用TYPE 与 LIKE 语定义所有ABAP 数据类型。若不明确指定类型,则被定义成 Generic 类型,会继承实参(Actual Parameter)的技术属性。

若传递了d类型的参数,则虚参的定义方法有下列 3 种形式:

  1. 使用 Generic TypeFORM subr CHANGING p_val
  2. 使用与实参(Actual Parameter)相同的数据类型FORM subr CHANGING p val TYPE d.
  3. 使用与实参(Actual Parameter)有相同类型的变量FORM subr CHANGING p valLIKE gv_VAL.

参数与结构体:

虚参可以使用所有 ABAP 数据类型,结构体也不例外。当结构体作为参数使用时,不仅能使用 TYPELIKE 语句定义,还可以使用 STRUCTURE语句定义结构体类型。

例:

*参数与结构体
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:

当程序参数为内表是也可以使用using和changing

*参数与内表
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 = 2.
APPEND gs_str TO gt_itab.

gs_str-col1 = 'b'.
gs_str-col2 = 3.
APPEND gs_str TO gt_itab.

PERFORM test_itab USING gt_itab.
FORM test_itab USING pt_itab TYPE t_itab.
  READ TABLE pt_itab WITH KEY col1 = 'b' INTO gs_str.
  IF sy-subrc = 0.
    WRITE: gs_str-col1,gs_str-col2.
  ENDIF.
ENDFORM.
*-------------内表---------------
PERFORM test_itab TABLES gt_itab.
PERFORM write_data TABLES gt_itab.

FORM test_itab TABLES pt_itab TYPE t_itab.
  DATA ls_str TYPE t_str.

  ls_str-col1 = 'a'.
  ls_str-col2 = 1.
  APPEND ls_str TO pt_itab.

  ls_str-col1 = 'b'.
  ls_str-col2 = 2.
  APPEND ls_str TO pt_itab.

ENDFORM.

FORM write_data TABLES pt_itab LIKE gt_itab.
  DATA ls_str TYPE t_str.
  LOOP AT pt_itab INTO ls_str.
    WRITE : / ls_str-col1,ls_str-col2.
  ENDLOOP.
ENDFORM.

Tables:

在 Rel 3.0 版本以前使用过TABLES 语,可以替代USING 与 CHANGING 语。以前开发的程序中使用了 TABLES 语句,因此出于互换性问题现在也经常使用此语句。

调用子程序:

程序内部调用子程序

例:

*调用程序内部的子程序
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).
  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.

程序外部调用子程序

例:

*调用程序外部子程序
*外部程序z_subrouite_1与上面调用程序内部子程序的例子一样(别忘了先激活)
DATA: gv_first(10)  TYPE c VALUE 'external',
      gv_second(10) TYPE c VALUE 'call',
      gv_result(20) TYPE c.

PERFORM concate_string(z_subrouite_1) 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_subrouite_1',
      gv_subname(20) TYPE c VALUE 'concate_string'.

TRANSLATE gv_pname TO UPPER CASE.
TRANSLATE gv_subname TO UPPER CASE.  "记得转大写

PERFORM (gv_subname) IN PROGRAM (gv_pname) IF FOUND
USING gv_first gv_second
      CHANGING gv_result.

利用list调用子程序:

*利用list调用子程序
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.

Abap循环语句:

DO~ENDDO 循环语句

是可以指定循环次数的语句,若不指定次数,则会无限执行循环,当前循环次数保存在系统变量 SY-INDEX 中。

WHILE~ENDWHILE

循环语句当WHILE 语句的表达式结果为真时反复持续循环。当前循环次数保存在系统变量 SY-INDEX 中。

LOOP~ENDLOOP 

循环语句按顺序依次循环内表,将读取内表行数据保存到工作区或者表头的循环语句。当前循环次数保存在系统变量 SYINDEX 中。SY-TABX 表示内表的当前行数。

结束子程序:

子程序遇到 END FORM语句就正常结束。此外,还可以利用 EXIT、CHECK 语句强制在执行过程中结束此子程序。遇到 EXIT 语句会直接跳出子程序,遇到 CHECK 语句时,判其值结果为假时不执行后续操作会跳出子程序。

例:

*结束子程序
PARAMETERS: p_val TYPE char10.
PERFORM end_subr USING p_val.

TRANSLATE p_val TO LOWER CASE.

FORM end_subr USING VALUE(p_val).
  CASE p_val.
    WHEN 'exit'.
      WRITE 'subroutine exit'.
      EXIT.
    WHEN 'check'.
      WRITE 'value check'.
      CHECK p_val NE 'check'.
    WHEN OTHERS.
  ENDCASE.
  WRITE 'subroutine is normally ended'.
ENDFORM.

Abap条件语句:

IF~ENDIF 分歧语句

比较条件语句中的逻辑值,当值为真时执行里面语句并跳出此语句块

IF 条件语句.
    ...
    ELSEIF 条件语句.
    ...
    ELSE.
    ...
ENDIF.

CASE~ENDCASE 分歧语句

一个变量有多个值时,根据每个值执行不同操作时使用的语句。

临时子程序:

可以定义在主内存中执行的动态子程序

上面语句有在执行中程序的主内存里创建子程序池的功能。将子程序池的代码插入到内表<itab>中,创建 8 位类型为 C 的子程序名prog 。即当需要使用动态的子程序时利用子程序池(程序),动态定义内表时经常使用此语句。例如,假设做一本根据用户指定的期间查询该期间销售额的程序。此时用户每次指定的日期是不一样的,因此无法事先预测内表的字段个数。这时用 GENERATE 语句就可以根据日期数动态地定义内表,此外还有很多动态定义内表的方法,在此不一一列举。子程序池只存在于程序执行过程中,在一个程序中可以创建36个子程序池。发生错误时 SY-SUBRC 返回8。

例:

*临时子程序
DATA:gt_code(72) OCCURS 10,
     gv_prog(8),
     gv_msg(120).
APPEND 'PROGRAM SUBPOOL.' TO gt_code.
APPEND 'FORM dynamic_subr.' TO gt_code.
APPEND 'WRITE / ''dynamic subroutine is called''.' TO gt_code.  "这里需要注意单引号的拼接
APPEND 'ENDFORM.' TO gt_code.    "拼接子程序代码
WRITE sy-subrc.
GENERATE SUBROUTINE POOL gt_code NAME gv_prog
MESSAGE gv_msg.
WRITE / sy-subrc.
IF sy-subrc <> 0. "注:sy-subrc  0:成功  4:源代码错误(注意查看字符串拼接是否正确)  8:发生错误
  WRITE: / 'subroutine pool is failed.'.
ELSE.
  WRITE: / 'subroutine pool name:',gv_prog.
  SKIP 1.
  PERFORM dynamic_subr IN PROGRAM (gv_prog).
ENDIF.

Perform on commit:

Using PERFORM ON COMMIT:遇到 COMMIT WORK 时调用子程序。

Using PERFORM ON ROLLBACK: 遇到 ROLLBACK WORK 时调用子程序

例:

*perform on commit   用法
DATA:gs_scarr LIKE scarr,
     gv_flg   TYPE c.

SELECT SINGLE * INTO gs_scarr FROM scarr
  WHERE carrid = 'AA'.

PERFORM delete_data USING gs_scarr.
PERFORM insert_data ON COMMIT.

IF gv_flg = 'X'.
  COMMIT WORK.
ENDIF.

FORM delete_data USING VALUE(ps_scarr) TYPE scarr.
  DELETE scarr FROM ps_scarr.
  IF sy-subrc = 0.
    gv_flg = 'X'.
  ENDIF.
ENDFORM.

FORM insert_data.
  INSERT scarr FROM gs_scarr.
ENDFORM.

Macro:

局部:

在程序中重复使用的语句,最好定义成 Macro 后使用。当在程序中使用时,先以DEFINE~END-OF-DEFINITION 形式定义后用 Macro 名字和参数调用即可。如果 PERFORM语句只是逻辑中包含的重复利用模块,Macro 功能只是为了减少代码重复。

 例:

*局部 MACRO
DATA:gv_val1 TYPE c VALUE 'A',
     gv_val2 TYPE c VALUE 'B',
     gv_val3 TYPE char3.
DEFINE con.
  CONCATENATE &1 &2 INTO &3 SEPARATED BY space.
  dis &3.
END-OF-DEFINITION.
DEFINE dis.
  WRITE &1.
END-OF-DEFINITION.
con gv_val1 gv_val2 gv_val3.

全局:

全局 Macro 在数据库表 TRMAC 中进行维护。经常使用的全局 Macro 中包含指定断点时用的 BREAK 语句。从[图 4-3]中显示的数据库表 TRMAC 的数据中可以看出,在程序中输入 BREAK 会调用此Macro,从而可以实现设定断点的功能。

Function:

函数(Function Module) 是储存在中央库 (R/3 Repository)中的特殊全局子程序。在一个程序中多次使用相同功能的语句会增加代码量,另外有修改需求时要修改多处,因此效率低。此时使用函数将代码模块化就可以实现代码重复利用,从而减少代码量。

传入参数

 往函数里传入值的参数,是可选项。

传出参数

从函数往 ABAP 程序里传递值的参数,也是可选项。传入/传出参数可以往函数里传值并且改变其值再传出。

表(Tables)

可以往函数传入/传出内表。

例外处理

提供错误信息。

函数属性:

子程序和函数的区别:

函数包含在称为函数组的一个池中。

函数提供例外处理功能,因此当发生错误时调用设定例外处理的程序

函数与调用的程序无关可以单独在 Stand-alone 模式下进行测试。

函数组:

函数组 (Function Group)可以看成是集合多个函数的集装箱。函数组不能直接运行,调用函数时,系统负载所有函数组到正在执行的程序内部会话中。这是指在一个函数组内的函数可以互相共享所有数据,还可以共享创建的屏幕,子程序等。

函数组名字最多可以指定成 26 个字母。通过函数编辑器创建函数和函数组,则系统会自动生成主程序及共享程序(Include Program)。

RFC:

        为了充当源系统和 R/3 系统的数据接口,要把 R/3 的函数定义为 RFC 函数。导入 SAPERP 之前,很多企业一般都是分别用各个不同的语言如 C、JAVA、power build 等语言来构筑财务、人事、生产等系统的。当导入 SAP 后,这种源系统一般会被废弃,但也存在与其并行执行的系统。此时,难免会遇到将源系统的数据传递到 SAP 或者 SAP 数据要在源系统上进行查询的情况,这种工作就需要通过 SAP RFC 来完成。而有时只用 RFC 无法实现 SAP 与多种语言开发的源系统的连接。

        为了解决此类问题,通常会创建 METHODS 来充当交换设备SAP 系统担当者利用 RFC 函数来传出数据,然后 WEBMETHODS 接收此数据后传递到源系统。同样,也可以从源系统接收数据后传递到 SAP 系统。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/38824.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

nginx(六十八)http_proxy模块 nginx与上游的ssl握手

一 nginx作为客户端与上游的SSL/TLS握手 理解上&#xff1a; nginx作为客户端,此时类似浏览器的角色,发请求建立连接 nginx作为server端与下游进行SSL/TLS握手 ① nginx与后端选择什么样的协议 1&#xff09;如果nginx与上游是局域网内,一般通过http建立请求,不需要进行…

使用flv.js + websokect播放rtsp格式视频流

1.问题背景 在最近的项目中&#xff0c;涉及到海康接入的视频播放的问题&#xff0c;海康这边获取到的视频流是rtsp格式&#xff0c;web端目前没有直接可以播放的组件&#xff0c;于是最开始是后端处理了视频流&#xff0c;返回hls格式的m3u8地址&#xff0c;这样用videojs插件…

进程【JavaEE初阶】

目录 一、操作系统 二、进程 2.1 进程的概念 2.2 进程的管理 2.3 PCB 2.3.1 PCB里面的一些属性 2.3.2 进程的调度 2.3.3 进程的虚拟地址空间 2.3.4 进程间通信 一、操作系统 CPU、存储器、输入设备、输出设备&#xff0c;这些实物看得着摸得到的&#xff0c;都属于 …

web前端-javascript-switch条件分支语句(语法,执行流程,补充)

文章目录条件分支语句(switch 语句)1. 语法&#xff1b;2. 执行流程&#xff1a;2.1. 在执行时会依次将 case 后的条件表达式的值和 switch 后的条件表达式的值进行全等比较2.2. 如果比较结果为 true&#xff0c;则从当前 case 处开始执行代码2.3. 如果比较结果为 false&#x…

【知识网络分析】研究机构合作网络(co-investigator institution)

研究机构合作网络(co-investigator institution) 1 网络数据集读取2 网络最大子群数据获取与精简3 中心点指定网络半径子群获取4 节点中心度相关指标计算1 网络数据集读取 使用GC.networkCoInvestigatorInstitution()方法快速生成研究结构合作网络数据集,其中GC代表着读入p…

解析华为OSPF协议

文章目录 前言一、pandas是 目录 文章目录 OSPF基础 一、报文类型 二、LSA类型 三.LSA在各区域中传播的支持情况 四.邻居状态机 邻居关系 邻接关系 &#xff18;种状态机&#xff1a; OSPF报文认证 OSPF缺省路由 2.读入数据 总结 什么&#xff1f;二、使用步骤 1.引入库2.读入数…

卷积神经网络CNN各层基本知识

卷积神经网络 卷积神经网络(CNN)由输入层、卷积层、激活函数、池化层以及全连接层构成。 INPUT&#xff08;输入层&#xff09;-CONV&#xff08;卷积层&#xff09;-RELU&#xff08;激活函数&#xff09;-POOL&#xff08;池化层&#xff09;-FC&#xff08;全连接层&#…

[VNCTF2022]easyj4va

看源码 输入 /file?url 1报错 用伪协议可以读取到内容 /file?urlfile:///etc/passwd 然后就是查看java字节码文件的目录 file?urlfile:///usr/local/tomcat/webapps/ROOT/WEB-INF 这里官方给了另外一个协议netdoc&#xff0c;跟file用法是一样的&#xff0c;但是这个netd…

JDK动态代理与Cglib动态代理使用详解

JDK动态代理与Cglib动态代理使用详解一、JDK动态代理准备使用二、Cglib动态代理准备使用Enhancer.create(Class type, Callback callback)Enhancer.create((Class superclass, Class[] interfaces, Callback callback))Enhancer.create(Class superclass, Class[] interfaces, …

【学习笔记35】JavaScript计算两个指定日期的时间差

一、要求 计算两个指定日期的时间差&#xff08;2023年元旦到来的时间&#xff09; 二、分析 先获取到两个时间距离1970&#xff08;格林尼时间&#xff09;~~~毫秒数计算两个毫秒数的差值 ----> 得到了总毫秒数计算总毫秒数内, 有多少个完整的天 parseInt(总毫秒数 / 一天的…

会话跟踪技术-session和cookie

会话&#xff08;Session&#xff09;跟踪是Web程序中常用的技术&#xff0c;用来跟踪用户的整个会话。常用的会话跟踪技术是Cookie与Session。 Cookie通过在客户端记录信息确定用户身份&#xff0c;Session通过在服务器端记录信息确定用户身份。 Cookie对象与HttpSession对象简…

nginx(六十七)http_ssl模块 client与nginx的ssl握手

一 HTTPS握手机制 关注点&#xff1a; SSL/TLS握手的细节与nginx配置指令的关系核心&#xff1a; 讲解客户端(下游)与作为server端的nginx之间的握手最佳实践&#xff1a; 建议在http块中通过include ssl.conf把共工部分抽离处理ssl/tls报错原因&#xff1a;可能是客户端或服…

Flutter高仿微信-第56篇-搜索好友

Flutter高仿微信系列共59篇&#xff0c;从Flutter客户端、Kotlin客户端、Web服务器、数据库表结构、Xmpp即时通讯服务器、视频通话服务器、腾讯云服务器全面讲解。 详情请查看 效果图&#xff1a; 实现代码&#xff1a; /*** Author : wangning* Email : maoning20080809163.co…

Java---Stream流详解

目录​​​​​​​ 一、Stream流详解 二、Stream流的获取 &#xff08;1&#xff09;单列集合 &#xff08;2&#xff09;双列集合 &#xff08;3&#xff09;数组 &#xff08;4&#xff09;一些零散数据 三、Stream流中常用的API方法 &#xff08;1&#xff09;中间…

含可再生能源的热电联供型微网经济运行优化_粒子群PSO算法_matlab程序

含可再生能源的热电联供型微网经济运行优化matlab程序 参考文献&#xff1a;含可再生能源的热电联供型微网经济运行优化 热电联供系统具有节能! 环保! 经济等特点" 有着良好的发展前景和应用价值# 文中针对由 风电机组! 光伏电池! 燃料电池! 余热锅炉! 燃气锅炉! 蓄电池以…

含电热联合系统的微电网运行优化附Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

SpringBoot+Vue项目投稿和稿件处理系统

文末获取源码 开发语言&#xff1a;Java 使用框架&#xff1a;spring boot 前端技术&#xff1a;JavaScript、Vue.js 、css3 开发工具&#xff1a;IDEA/MyEclipse/Eclipse、Visual Studio Code 数据库&#xff1a;MySQL 5.7/8.0 数据库管理工具&#xff1a;phpstudy/Navicat JD…

MYSQL中的锁

全局锁 就是对整个数据库进行加锁&#xff0c;加锁之后整个数据库就处于只读状态&#xff0c;后续的DML写语句&#xff0c;DDL语句&#xff0c;以及对更新事务的提交操作都会被阻塞&#xff0c;典型地使用场景就是做整个数据库的逻辑备份&#xff0c;对所有的表进行锁定&#x…

非凡社群管理之如何高效的进行社群管理

一、初始成员的严格筛选 我们建立社群初期&#xff0c;就要严格筛选初始会员&#xff0c;争取让我们找到的第一批种子用户&#xff0c;就是有着共同的连接点。而不是找到一群人之后&#xff0c;再去培养大家的同好。这样不仅吃力不讨好&#xff0c;往往效果也不太高&#xf…

Kafka系列之:实现Kafka Connect集群访问认证

Kafka系列之:实现Kafka Connect集群访问认证 一、Kafka Connect访问控制二、Kafka Connect技术知识三、详细介绍Kafka connect访问认证实现过程四、启动Kafka Connect集群五、测试Kafka Connect集群访问认证一、Kafka Connect访问控制 实现的效果如下所示: 错误的用户名和密…