模块化编程概念
模块化编程
基础概念
代码语言:javascript复制把程序中部分源代码储存到一个模块里
封装成一个特定的功能,可以认为是程序的一部分
公用的,多个程序都可以调用
(类似py中的函数)
优点
代码语言:javascript复制提高程序透明度
提高代码重用
简化程序维护
方便程序调试
样例
代码语言:javascript复制获取每月最后一天(函数)
获取当前时间(函数)
模块化编程内容
代码语言:javascript复制函数
子例程
宏
类
参数
代码语言:javascript复制用于在程序和模块之间交换数据
定义模块化单元的时候就确定了可以使用哪些参数
参数分类
代码语言:javascript复制输入参数——是用来传递数据给模块化单元
导出参数——把模块化单元中的数据返回给调用程序
变更参数——是把数据传递给模块化单元并返回更改后的数据 (传入内表,内表变动,传出变动内表)
函数的概念
函数
代码语言:javascript复制Function:
Function模块是具有全局可见性的特殊程序。
Function模块只能在Function Group中定义并使用。
函数组
代码语言:javascript复制Function Group
Function Group中可以包含一个以上的函数,是对某一类对象的操作。
Function Group专门用作Function的主程序
函数操作
定义函数组
代码语言:javascript复制操作
代码语言:javascript复制SE37-->转到-->函数组-->创建组
注意创建的名称必须以 Z开头
定义函数
代码语言:javascript复制前置动作->提前建立好函数组 -->上一步
T-code se37
函数界面介绍及demo
属性
代码语言:javascript复制 内容介绍
代码语言:javascript复制1.一般函数模块
一般的函数模块,只能用于当前系统
2.远程模块
可用于其他系统,SAP系统,或者非SAP系统,调用时候要指定目的地,目的地在SM59配置
3.更新函数
用于数据库数据更新
导入
代码语言:javascript复制参数名称: 以I_开头 参数名称
类型化: TYPE就行
关联类型: 就是你这个字段原表的参考数据类型
缺省值:提示
可选:是否为必须录入
导出
代码语言:javascript复制参数名称:以E_开头加输出参数名称,可以是字段,或者结构均可以
类型化: TYPE就行
关联类型: 数据类型或者结构/表
代码语言:javascript复制即变更参数 同导入一样,
表
代码语言:javascript复制参数名称:你输出表的名称
类型化: 有type ,like 两个 参考 内表/表
关联类型: 具体哪个内表/表
例外
代码语言:javascript复制即 抛出异常
例外:异常名称
短文本:异常描述
源代码
代码语言:javascript复制即你操作的所有内容代码
案例:
FUNCTION Z_DEMO_FUNC2.
*"----------------------------------------------------------------------
*"*"本地接口:
*" IMPORTING
*" REFERENCE(I_CONNID) TYPE S_CONN_ID OPTIONAL
*" EXPORTING
*" REFERENCE(E_SPFLI) TYPE SPFLI
*" TABLES
*" T_SPFLI STRUCTURE SPFLI
*" EXCEPTIONS
*" SALE_NOT_EXIST
*"----------------------------------------------------------------------
*输出参数
select SINGLE * from SPFLI into E_SPFLI where CONNID = I_CONNID .
*异常判断
if sy-subrc <> 0 .
RAISE sale_not_exist .
ENDIF .
*输出到表
select * from SPFLI into table t_SPFLI where CONNID = I_CONNID .
ENDFUNCTION.
demo演示
函数的调用
概念
代码语言:javascript复制调用
使用 CALL FUNCTION 语句调用
Function的名称采用单引号内包含大写字母的形式
在EXPORTING块中,系统会将值传递给Function的导入参数
在IMPORTING块中,可使用导出参数访问调用结果
异常
在处理Function时出现应用程序错误(例如,值不适于计算),
函数模块就会提出相应的异常。
出现异常会取消对Function的处理,系统会返回到调用程序。
可在Exception中为可能的异常明确设置返回代码(sy-subrc),
同时指定 OTHERS,则会为所有未明确列出的异常分配一个共享的返回码。
自动生成函数
代码部分
代码语言:javascript复制*&---------------------------------------------------------------------*
*& Report YFUNC_DEMO1
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT YFUNC_DEMO1.
data : lv_CONNID type S_CONN_ID .
data : ls_SPFLI type SPFLI .
data : lt_SPFLI TYPE TABLE OF SPFLI .
lv_CONNID = '0017' .
CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
EXPORTING
INPUT = lv_CONNID
IMPORTING
OUTPUT = lv_CONNID .
CALL FUNCTION 'Z_DEMO_FUNC2'
*入参
EXPORTING
I_CONNID = lv_CONNID
*出参
IMPORTING
E_SPFLI = ls_SPFLI
*表
TABLES
T_SPFLI = lt_SPFLI
*异常捕获
EXCEPTIONS
SALE_NOT_EXIST = 1
OTHERS = 2
.
IF SY-SUBRC = 0.
WRITE : ls_SPFLI-CONNID , ls_SPFLI-CITYFROM .
ELSEIF SY-SUBRC = 1 .
WRITE : '销售凭证不存在' .
ENDIF.
结果
子例程
子例程的概念
代码语言:javascript复制子例程概述:
子例程是源代码里具有一定独立功能的模块单元。
类型:
内部子例程:内部子例程的源代码与调用程序位于同一个ABAP程序 中
外部子例程:外部子例程的源代码位于另外的ABAP程序中,而不是位于调用程序内部。
注意:
子例程中应避免使用主程序的变量,应使用参数
在子例程中定义的变量,只在子例程中有效
子例程的定义方式
子例程定义方式
代码语言:javascript复制子例程的定义方式:
以FORM开头、以 ENDFORM 结尾的ABAP代码块。
语法:
FORM <subroutine> [<pass>].
<statement block>
ENDFORM.
其中:
<subroutine> 用于定义子例程名,
<pass> 参数<pass>选项也可以没有
子例程可以访问其所在主程序中声明的所有数据对象。
一般都将同一程序中定义的所有内部子例程都集中定义在程序的末尾。
子例程的定义不能互相嵌套。
形参和实参
代码语言:javascript复制形参和实参:
形参(formal parameters):
子例程定义期间用FORM语句定义的参数
实参(actual parameters):
子例程调用期间用PERFORM语句指定的参数
参数传递方式
代码语言:javascript复制参数传递:
将主程序变量传递给子例程形式参数
传递类型:
值传:
子例程中参数变量的值的改变,不影响外部程序实际变量的值
引用传:
若子例程中的参数变量的值发生了改变,那么,外部程序的实际变量的值也发生改变
值传并返回结果:
传递参数的方式同值传递相同,但在子例程执行过程中,变量值不改变,而结束执行后,把变量的最终值返回
局部和全局变量
代码语言:javascript复制局部和全局变量:
全局变量:
在主程序中定义的变量
这些变量在整个主程序和调用的每个子例程中均可见(可进行处理)
局部变量:
在子例程中定义的变量称作局部变量,
这些变量只存在于相关的子例程中(与形式参数相同),只能在子例程中使用。
注意:
当全局变量和局部变量同名时,在子例程中局部变量起作用,而全局变量的值不改变。
在子例程中对全局变量的值进行修改以后,其修改的值仅存在于子例程中
子例程demo
无参数
代码语言:javascript复制*调用子例程
PERFORM FOR_DEMO1 .
*无参数
FORM FOR_DEMO1 .
WRITE : '测试无参数子例程' .
ENDFORM .
值传
代码语言:javascript复制A:值传
子例程中参数变量的值的改变,不影响外部程序实际变量的值
DATA : A TYPE I VALUE 1 ,
B TYPE I VALUE 2,
C TYPE I .
PERFORM FRM_PLUS USING A B C.
WRITE C.
FORM FRM_PLUS USING VALUE(P_A) VALUE(P_b) value(P_C).
P_C = P_A P_B P_C.
WRITE P_C.
ENDFORM.
引用传
代码语言:javascript复制B:引用传(以下用的最多)
若子例程中的参数变量的值发生了改变,那么,传递程序的实际变量的值也发生改变
DATA : A TYPE I VALUE 1 ,
B TYPE I VALUE 2,
C TYPE I .
PERFORM FRM_PLUS USING A B C.
WRITE C.
FORM FRM_PLUS USING P_A P_b P_C.
P_C = P_A P_B P_C.
WRITE P_C.
ENDFORM.
值传并返回结果
代码语言:javascript复制C:值传并返回结果
传递参数的方式同值传递相同,但在子例程执行过程中,变量值不改变,而结束执行后,把变量的最终值返回。
DATA : A TYPE I VALUE 1 ,
B TYPE I VALUE 2,
C TYPE I .
PERFORM FRM_PLUS USING A B C.
WRITE C.
FORM FRM_PLUS USING VALUE(P_A) VALUE(P_b) CHANGING P_C.
P_C = P_A P_B P_C.
WRITE P_C.
endform.
外部调用子例程
通过调用指定程序调用子例程
语法
代码语言:javascript复制不同的ABAP程序中的子例程是可以共用的(不建议)
PERFORM form IN PROGRAM prog
代码
代码语言:javascript复制DATA:num2 TYPE i VALUE 10.
PERFORM add_value CHANGING num2 IN PROGRAM XXXX.
WRITE:num2."调用子例程加10.
通过Tcode调用程序
解释
代码语言:javascript复制通过CALL来实现对某TCode中相对应的子例程的调用
CALL TRANSACTION TCode
代码
代码语言:javascript复制CALL TRANSACTION 'ICON' AND SKIP FIRST SCREEN.
使用submit 的方法调用另一个程序
代码语言:javascript复制使用SUBMIT方法调用另一个程序
在ABAP中可以直接调用具体程序来实现该程序的所有功能,
并提供程序执行中所需要输入的字段及参数
语法:
SUBMIT <程序名>.
...USING SELECTION-SCREEN <SCR>. "调用子屏幕
...VIA SELECTION-SCREEN. "显示所调用程序的初始屏幕
...AND RETURN. "调用指定程序执行后可返回上一屏幕
宏
宏定义
代码语言:javascript复制宏(Macros)是一段独立的代码,能实现数据的运算与输出,
功能与子例程类似,主要应用于同一程序中某些重复的运算,以简化代码
语法:
DEFINE INCREMENT. "INCREMENT为宏的名称。
......
END-OF-DEFINITION.
与子例程不同的是,宏通过&N(N为索引)接收传入的参数,不需要定义接收参数的类型及格式。
宏参数最多可以包含九个(&1,&2,...,&9)
宏只能被本程序中定义于宏后面的语名所调用,宏一般定义于程序最开始
演示代码
代码语言:javascript复制DEFINE increment. "定义宏
add 1 to &1.
write: / &1.
write: / &2.
END-OF-DEFINITION.
DATA:number TYPE i VALUE 1,
str(10) TYPE c VALUE 'HELLO SAP'.
increment number str. "调用宏