ABAP子程序
ABAP子程序,相当于封装的一个方法,执行一段逻辑处理。
子程序内部定义变量只能子程序内部使用,全局变量可以直接使用。
语法:form <子程序名>
[using]
[changing]
[value ( 变量 )]
[changing value (变量)].
程序处理逻辑.
endform.
关键词:using、changing都是传递地址给子程序,using一般不允许子程序修改值,changing允许子程序修改值,如果子程序内修改using传递的参数值这个只是定义上的,程序并没有限定,会报出警告,不影响运行。
关键词:value只传递值,发现没啥用;
关键词:changing value 返回修改值;
注意:changing value 不能和changing同时存在,一般不使用,changing因为传递的地址,直接修改就会修改地址值,一般就使用changing就可以了。
调用子程序:
语法:perform <子程序名>
[using]
[changing]
[value ( 变量 )].
示例:
DATA: num1 type I value 49,
num2 type I value 58.
DATA: sum type I.
测试1:
"子程序调用
PERFORM multi USING num1 num2.
"子过程定义
form multi USING num1 num2.
"局部变量
Data : mul type I.
"using传入参数,也可重新赋值,但程序会警告
num1 = 10.
mul = num1 * num2."可使用全局变量
WRITE :/ num1,'*',num2,'=',mul.
ENDFORM.
测试2:
"子程序调用
PERFORM add01 using num1 num2 CHANGING sum.
WRITE :/ '主程序:', num1 ,num2, sum.
"子过程定义,使用using,changing传地址,一般using是不允许子程序改值。changing,允许子程序改值
form add01 CHANGING num1 num2 sum.
WRITE :/ num1 ,num2, sum.
"子程序赋值,主程序也跟着修改
num1 = 10.
num2 = 20.
sum = num1 + num2.
WRITE :/ num1 ,num2, sum.
ENDFORM.
测试3:
"子程序调用
PERFORM add02 using num1 sum num2.
WRITE :/ '主程序:', num1 ,num2, sum.
"子过程定义,value()只传值。
form add02 CHANGING num1 sum value(num2).
WRITE :/'前',num1, num2, sum.
num2 = 40."这个赋值只在局部有效
sum = num1 + num2.
WRITE :/ '后',num1,num2,sum.
ENDFORM.
测试时发现:使用value(),子程序赋值,仍然会影响主程序值。调用传参顺序和定义子程序时顺序要一致,不然会出现错位现象,不是按照参数名传参赋值,而是根据位置。
测试4:
"子程序调用
PERFORM add03 using num1 num2 CHANGING sum.
WRITE :/ '主程序:', num1 ,num2, sum.
"子过程定义,返回changing value().
FORM add03 USING num1 num2 CHANGING VALUE(s).
WRITE :/ num1,num2,sum.
num1 = 20.
num2 = 30.
s = num1 + num2.
WRITE :/ num1, num2, s.
ENDFORM.
测试时发现:使用changing value(),子程序赋值,仍然会影响主程序值。
ABAP宏定义
定义一段通用代码,使用&数字,表明传入参数,执行一段逻辑。这段代码可以在主程序中反复调用。
定义宏:
语法:define <程序名>
程序逻辑.
end-of-definition.
调用宏定义代码段:
语法:<程序名> <参数1> [<参数2> ………]
示例:
"宏定义
DATA: sum type I.
DATA: num1 type I value 10,
num2 type I value 20.
"定义宏,两个数求和,并输出
DEFINE addNum.
sum = &1 + &2.
WRITE :/ &1,'+', &2 ,'=',sum.
end-OF-DEFINITION.
"调用宏定义代码
addNum num1 num2.
ABAP公共代码块
定义一段公共使用的代码,编译时直接嵌入到调用位置,主程序可以使用公共代码中定义的所有变量、子程序等。
定义公共代码块,选中包名,右键选择create,找include选择就行了。
如果包下有一个includes活页夹,直接选中includes右键create就行了。
在主程序调用,直接将z_test_include中的代码嵌入到主程序调用位置。
示例:
"调用includeProgram
INCLUDE z_test_include.
ABAP程序结构
1报表程序结构
Report <name>:宣告程序名称和报表格式;
语法:report <程序名>
[NO STANDARD PAGE HEADING]
[message-id <messageid>]
[line-count <数字>]
[line-size <数字>]
Message-id:指定使用的message
Line-count:指定报表显示列数
Line-siez:显示每页报表宽度
Include语句:宣告使用的公共代码块;
语法:Include <代码块>:包含其他公共代码块
Tables语句:声明程序中使用到的数据库表;
语法:Tables:<数据库表名>[,<数据库表名>].
Types,Data语句:定义变量类型和变量;
Selection screen、option、parameter定义屏幕显示内容;
语法:见屏幕显示;
Initialization语句:执行一些变量初始化;
语法:Initiallization.
At selection-screen语句:选择屏幕运行时触发,主要对查询条件和权限进行校验。
语法:at selection-screen.
[on <parameters名>]:parameters输入时,按enter触发;
[on end of <select-option名>]:select-option,multi-option页面数据填写后,按确认触发;
[on value–request for <parameters名>]:f4帮助,点击输入框小方块,弹出备选值;
[on help-request for <parameters名>]:f1帮助,按f1执行;
[on radiobutton group <按钮组名>]:监听选择按钮组按钮触发事件,按enter键触发;
[on block <模块名>]:监听block触发事件;
[output]:屏幕每次输出时触发
Start-of-selection语句:开始执行程序主逻辑,比如读取数据,处理数据等,类似于java的main()方法;
语法:start-of-selection.
程序主逻辑.
End-of-selection语句:程序执行结束,调用的子程序可以定义在这模块后;
语法:end-of-selection.
子程序form.
Include代码块.
示例:
"宣告程序名,和报表参数
REPORT Z_TEST_REPORT
NO STANDARD PAGE HEADING
MESSAGE-ID ym
LINE-COUNT 20
LINE-SIZE 20.
"include语句
"可以包含公共代码块
"tables语句,宣告使用的数据库表
TABLES:spfli.
"定义数据类型,数据变量
TYPES:BEGIN OF str_spfli,
carrid LIKE spfli-carrid,
connid LIKE spfli-connid,
cityfrom LIKE spfli-cityfrom,
END OF str_spfli.
DATA:t_spfli TYPE TABLE OF str_spfli.
DATA:wa_spfli LIKE LINE OF t_spfli.
DATA:t_spfli_all LIKE TABLE OF spfli.
"定义屏幕元素
"parameters
PARAMETERS: p_carrid LIKE spfli-carrid.
"select option
SELECT-OPTIONS s_connid FOR spfli-connid NO-EXTENSION.
"selection-screen
SELECTION-SCREEN BEGIN OF BLOCK RADIO WITH FRAME TITLE text1 .
PARAMETER p1 RADIOBUTTON GROUP GR1.
PARAMETER p2 RADIOBUTTON GROUP GR1.
PARAMETER p3 RADIOBUTTON GROUP GR1.
SELECTION-SCREEN END OF BLOCK RADIO.
"初始化
INITIALIZATION.
text1 = '选择参数'.
"选择屏幕运行时触发,检查参数
"当parameters输入后,enter触发
AT SELECTION-SCREEN ON p_carrid.
MESSAGE s000 WITH p_carrid.
"select-option的multi-option界面输入后确认时触发
AT SELECTION-SCREEN ON END OF s_connid.
MESSAGE s000 WITH s_connid.
"按f4触发,或者点击输入框最后的小方框
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_carrid.
MESSAGE s000 WITH p_carrid 'f4帮助'.
"按f1触发
AT SELECTION-SCREEN ON HELP-REQUEST FOR p_carrid.
MESSAGE s000 WITH p_carrid 'f1帮助'.
"屏幕按钮组变化监听
*AT SELECTION-SCREEN ON RADIOBUTTON GROUP gr1.
* IF p1 = 'X'.
* MESSAGE s000 with 'p1'.
* ELSEIF p2 = 'X'.
* MESSAGE s000 WITH 'p2'.
* ELSE.
* MESSAGE s000 WITH 'p3'.
* ENDIF.
"屏幕模块监听
AT SELECTION-SCREEN ON BLOCK RADIO.
IF p1 = 'X'.
MESSAGE s000 with 'p1'.
ELSEIF p2 = 'X'.
MESSAGE s000 WITH 'p2'.
ELSE.
MESSAGE s000 WITH 'p3'.
ENDIF.
"屏幕输出时触发,可以检查输入值,检查权限
AT SELECTION-SCREEN OUTPUT.
MESSAGE s000 WITH 'output screen'.
"程序主逻辑开始
START-OF-SELECTION.
WRITE:/ 'hello world'.
MESSAGE s000 WITH '程序主逻辑'.
"处理GUI-Status自定义的命令
AT USER-COMMAND.
"报表中按f2触发,或者双击
AT LINE-SELECTION.
"定义报表表头
TOP-OF-PAGE.
"打印完最后一页触发
END-OF-PAGE.
"报表程序结束,后面定义一下form或者include代码块
END-OF-SELECTION.
2module pool程序结构
Modul pool programs,模块池程序。主要使用screen作为主要操作对象,所有操作围绕屏幕PBO模块,PAI模块操作。
选择项目,项目活页夹上右键->create->Screen,
输入屏幕编号,例如100。
PBO Modules:屏幕输出前执行module模块池方法;
PAI Modules:用户和屏幕输入交互调用module方法;
Screens:我们创建的屏幕;
GUI Status:自定义的工具栏;
GUI Title:显示的标题;
可以看到我们创建的屏幕,点击0100,在右边设计界面可以添加我们的module逻辑代码。
点击Layout可以进入一个图形化界面,我们可以通过拖动组件方式设计我们的页面。
逻辑代码:
PROCESS BEFORE OUTPUT.模块下的module会在屏幕输出之前执行,一般设置屏幕标题,功能字段逻辑在这里。
PROCESS AFTER INPUT.模块下module会响应用户在屏幕上的操作。比如用户点击功能按钮等。
示例:
TABLES: sflight.
DATA : OK_CODE like sy-ucomm.
DATA : t_carrid like sflight-carrid.
DATA : t_connid LIKE sflight-connid.
DATA : t_price LIKE sflight-price.
*DATA : testTab like sflight OCCURS 10 WITH HEADER LINE,
* testLine like sflight.
"调用屏幕显示
CALL SCREEN 100.
"屏幕输出前,设置工具栏和标题
MODULE STATUS_0100 OUTPUT.
"设置GUI STATUS工具栏
SET PF-STATUS 'STS_100'.
"设置标题
SET TITLEBAR 'TEST'.
ENDMODULE.
"用户退出
MODULE USER_EXIT_0100 INPUT.
ok_code = sy-ucomm.
CLEAR sy-ucomm.
if ok_code = 'BACK' or ok_code = 'CANCEL' or ok_code = 'EXIT'.
LEAVE PROGRAM.
ENDIF.
ENDMODULE.
"用户点击执行
MODULE USER_COMMAND_0100 INPUT.
ok_code = sy-ucomm.
CLEAR sy-ucomm.
case ok_code .
when 'EXC'.
select SINGLE connid price into (t_connid,t_price)
from sflight where carrid = t_carrid.
if sy-subrc <> 0.
t_connid = '00'.
t_price = '0.000'.
ENDIF.
endcase.
ENDMODULE.