SAP-ABAP:深入浅出 SAP 经典可执行程序:从零开始掌握
在 SAP ABAP 开发的世界里,几乎每一位开发者的第一行代码都写在一个可执行程序里。它简单、直观、功能强大,是理解 SAP 开发模式的绝佳起点。本文将带你全面了解经典可执行程序的方方面面。
一、什么是可执行程序?
可执行程序(Executable Program)是 SAP ABAP 中最基础、最常用的程序类型之一。它的核心特征可以用一句话概括:可以不依赖任何事务代码,直接在 ABAP 编辑器(SE38)中点击运行按钮(F8)来执行。
在 ABAP 程序类型分类中,可执行程序的类型值为 1。与模块池(类型 M)、函数组(类型 F)、类池(类型 K)等其他程序类型不同,可执行程序拥有一个独立运行的入口,不需要通过事务代码或屏幕调用即可启动。
可执行程序与报表程序的关系
很多人会混淆"可执行程序"和"报表程序"这两个概念。严格来说:
- 可执行程序是程序类型层面的技术分类
- 报表程序是功能层面的描述,指用于输出数据列表的程序
实际上,所有的报表程序都是可执行程序,但可执行程序的应用范围远不止报表------它还可以用于数据导入、批量处理、后台作业等场景。因此,"可执行程序"这个名称更能准确反映其技术本质。
二、可执行程序的核心特点
2.1 独立运行,无需事务码
这是可执行程序最鲜明的特征。在 SE38 中输入程序名,按 F8 即可运行。当然,如果你希望将它挂到 SAP 菜单上或分配给某个权限角色,也可以随时为它创建事务码(通过 SE93),但这并非必须。
2.2 预定义事件块驱动
可执行程序的执行流程由一系列预定义的事件块控制。系统会按照固定的顺序自动调用这些事件块,开发者只需要在对应的事件块中编写业务逻辑即可。这种设计让代码结构清晰、易于维护。
2.3 自带选择屏幕
可执行程序天然支持选择屏幕(Selection Screen)。开发者可以使用 PARAMETERS、SELECT-OPTIONS 等语句定义用户输入界面,无需编写复杂的 Dynpro 屏幕代码。当用户运行程序时,系统会自动显示这个选择屏幕,供用户输入查询条件。
2.4 支持逻辑数据库
逻辑数据库(Logical Database)是 SAP 提供的一种标准化数据提取工具。可执行程序可以直接关联一个逻辑数据库,从而大幅简化数据读取逻辑------你不需要关心具体从哪些表中读取数据、如何处理表之间的关联关系,逻辑数据库会帮你完成。
2.5 可后台调度
可执行程序支持通过 SM36 事务码配置为后台作业(Background Job),可以定时、定期或在特定事件触发时自动运行。这一特性使其成为批量处理任务的理想载体。
三、创建一个可执行程序(手把手教程)
让我们从一个最经典的"Hello World"开始,逐步创建一个完整的可执行程序。
第 1 步:启动事务码 SE38
在 SAP GUI 的命令栏中输入 SE38,进入 ABAP 编辑器(也称为 ABAP 工作台)。
第 2 步:输入程序名称并创建
在"程序"字段中输入一个程序名。强烈建议以 Z 或 Y 开头------这是 SAP 预留的客户命名空间,可以确保你的程序不会与 SAP 标准程序或其他客户程序发生命名冲突。
例如:
Z_HELLO_WORLD
输入后,点击"创建"按钮。
第 3 步:选择程序类型
系统会弹出"ABAP:程序属性"窗口。在这里:
- 类型 :选择 "可执行程序"(Executable Program)
- 标题 :输入一个简短的描述,如
我的第一个ABAP程序
其他字段(如"应用程序组件"、"逻辑数据库"等)可以暂时留空。
点击"保存",系统会提示你选择开发类(Package)。如果是练习用途,可以选择本地对象($TMP)。
第 4 步:编写代码
在编辑器中输入以下两行代码:
abap
REPORT Z_HELLO_WORLD.
WRITE 'Hello, SAP World!'.
REPORT语句是每个可执行程序的必备语句,用于声明程序名称。WRITE语句用于在屏幕上输出内容。
第 5 步:激活并运行
- 点击激活 按钮(或按
Ctrl + F3),系统会检查语法是否正确。如果没有错误,程序会被激活(生成运行时对象)。 - 激活成功后,点击直接处理 按钮(或按
F8),即可运行程序。
你会看到屏幕上输出:
Hello, SAP World!
恭喜你,你的第一个 SAP 可执行程序已经成功运行!
四、可执行程序的事件块详解
可执行程序的执行流程是由一系列事件块驱动的。理解这些事件块的执行顺序,是编写高质量程序的基础。
4.1 完整的事件块及执行顺序
abap
REPORT Z_EVENT_DEMO.
" 1. LOAD-OF-PROGRAM - 程序加载时执行(最先)
LOAD-OF-PROGRAM.
WRITE: / '1. LOAD-OF-PROGRAM'.
" 2. INITIALIZATION - 选择屏幕显示之前执行
INITIALIZATION.
WRITE: / '2. INITIALIZATION'.
" 定义选择屏幕参数
PARAMETERS: p_date TYPE sy-datum DEFAULT sy-datum.
" 3. AT SELECTION-SCREEN - 用户点击执行按钮后,选择屏幕输入验证时执行
AT SELECTION-SCREEN.
IF p_date < sy-datum.
MESSAGE '日期不能早于今天' TYPE 'E'.
ENDIF.
" 4. START-OF-SELECTION - 数据选择开始前执行(最常用的事件)
START-OF-SELECTION.
WRITE: / '4. START-OF-SELECTION'.
WRITE: / '用户输入的日期是:', p_date.
" 5. END-OF-SELECTION - 数据选择结束后、列表输出前执行
END-OF-SELECTION.
WRITE: / '5. END-OF-SELECTION'.
4.2 各事件块的用途说明
| 事件块 | 触发时机 | 典型用途 |
|---|---|---|
LOAD-OF-PROGRAM |
程序被加载到内存时 | 初始化全局数据、加载缓存等(较少使用) |
INITIALIZATION |
选择屏幕显示之前 | 设置选择屏幕字段的默认值、动态修改选择屏幕属性 |
AT SELECTION-SCREEN |
用户输入选择条件后、点击执行时 | 校验用户输入、动态改变选择屏幕行为 |
START-OF-SELECTION |
数据选择开始前 | 核心业务逻辑:数据库查询、数据计算等(最常用) |
END-OF-SELECTION |
数据选择结束后、列表输出前 | 汇总统计、输出额外信息 |
💡 实践建议 :90% 以上的业务逻辑都可以写在
START-OF-SELECTION中。其他事件块只在有特殊需求时才使用。
4.3 选择屏幕相关的事件块
除了上述核心事件,可执行程序还支持更多与选择屏幕交互的事件:
AT SELECTION-SCREEN ON p_field:针对特定选择屏幕字段的校验AT SELECTION-SCREEN OUTPUT:选择屏幕显示时触发,可动态修改屏幕元素属性AT SELECTION-SCREEN ON HELP-REQUEST FOR p_field:用户按 F1 帮助时触发AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_field:用户按 F4 搜索帮助时触发
五、选择屏幕开发
选择屏幕是可执行程序与用户交互的主要界面。通过简单的 ABAP 语句,就能创建出功能强大的查询界面。
5.1 基本元素:PARAMETERS 与 SELECT-OPTIONS
PARAMETERS:定义单个值的输入字段
abap
PARAMETERS: p_ebeln TYPE ekko-ebeln OBLIGATORY, " 必输
p_bukrs TYPE bkpf-bukrs DEFAULT '1000', " 默认值
p_date TYPE sy-datum. " 日期
SELECT-OPTIONS:定义范围输入字段(相当于四个值的组合:低值、高值、选项、符号)
abap
SELECT-OPTIONS: s_ebeln FOR ekko-ebeln, " 采购订单范围
s_budat FOR bkpf-budat. " 过账日期范围
5.2 选择屏幕的布局控制
代码块 :使用 SELECTION-SCREEN BEGIN OF BLOCK 和 END OF BLOCK 将字段分组
abap
SELECTION-SCREEN BEGIN OF BLOCK block1 WITH FRAME TITLE text-001.
PARAMETERS: p_ebeln TYPE ekko-ebeln.
SELECT-OPTIONS: s_ebelp FOR ekpo-ebelp.
SELECTION-SCREEN END OF BLOCK block1.
注释行 :使用 SELECTION-SCREEN COMMENT 添加说明文字
abap
SELECTION-SCREEN COMMENT /1(30) text-002. " 在第1列输出30个字符长的说明
5.3 动态修改选择屏幕
通过 AT SELECTION-SCREEN OUTPUT 事件,可以动态修改选择屏幕字段的属性:
abap
AT SELECTION-SCREEN OUTPUT.
LOOP AT SCREEN.
IF screen-name = 'P_EBELN'.
screen-input = 0. " 将字段设为不可输入
MODIFY SCREEN.
ENDIF.
ENDLOOP.
六、逻辑数据库的使用
逻辑数据库(Logical Database)是一种将数据读取逻辑封装好的工具。使用逻辑数据库,开发者可以:
- 避免编写复杂的数据库连接逻辑(如多表关联、数据筛选)
- 自动获得选择屏幕(逻辑数据库自带的筛选条件)
- 利用系统内置的缓存和性能优化
6.1 如何指定逻辑数据库
在创建程序时,在程序属性窗口的"逻辑数据库"字段中选择一个逻辑数据库。例如:
F1S:财务凭证数据库PNP:HR 人员主数据数据库SDF:销售与分销数据库
6.2 逻辑数据库的事件块
使用逻辑数据库时,还需要额外了解几个事件块:
GET 表名:每次读取到一条数据时触发GET 表名 LATE:该表所有数据处理完后触发PUT 表名:将数据传递给报表程序
示例(使用财务凭证逻辑数据库 F1S):
abap
REPORT Z_F1S_DEMO.
GET bkpf. " 每读取一个财务凭证抬头时触发
WRITE: / bkpf-bukrs, bkpf-belnr, bkpf-gjahr.
GET bseg. " 每读取一个凭证行项目时触发
WRITE: / bseg-buzei, bseg-hkont, bseg-dmbtr.
七、后台调度:让程序自动运行
可执行程序的一大优势是可以配置为后台作业,实现无人值守的批量处理。
7.1 创建后台作业(SM36)
- 输入事务码
SM36 - 在"作业名称"字段输入一个有意义的名称
- 点击"步骤"按钮,在步骤列表中指定要运行的程序名
- 点击"开始条件"按钮,定义作业的执行时间(立即、定时、周期性)
- 保存后,作业即被调度
7.2 监控后台作业(SM37)
- 使用事务码
SM37查看所有后台作业的状态 - 常见状态:计划中(Scheduled)、已发布(Released)、就绪(Ready)、活跃(Active)、已完成(Finished)、已取消(Cancelled)
- 可以通过作业日志查看程序的输出结果
7.3 后台作业的最佳实践
- 在程序中使用
WRITE语句输出执行日志,这些内容会写入作业日志,方便排查问题 - 避免在后台作业中使用依赖用户交互的语句(如
POPUP弹窗) - 设置合适的开始时间,避免在系统高峰期运行
八、典型应用场景
8.1 数据报表
这是可执行程序最常见的用途。结合 ALV(ABAP List Viewer),可以快速开发出专业的数据报表。
abap
REPORT Z_PURCHASE_REPORT.
TABLES: ekko, ekpo.
DATA: gt_ekko TYPE TABLE OF ekko.
SELECT-OPTIONS: s_ebeln FOR ekko-ebeln.
START-OF-SELECTION.
SELECT * FROM ekko INTO TABLE gt_ekko
WHERE ebeln IN s_ebeln.
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
EXPORTING
i_structure_name = 'EKKO'
TABLES
t_outtab = gt_ekko.
8.2 数据批量导入
从本地文件(如 Excel、TXT)读取数据,然后更新到 SAP 数据库中。
abap
REPORT Z_DATA_UPLOAD.
PARAMETERS: p_file TYPE rlgrap-filename.
DATA: BEGIN OF it_data OCCURS 0,
field1 TYPE char10,
field2 TYPE char20,
END OF it_data.
START-OF-SELECTION.
CALL FUNCTION 'UPLOAD'
EXPORTING
filename = p_file
TABLES
data_tab = it_data.
LOOP AT it_data.
" 执行数据库更新操作
ENDLOOP.
8.3 数据一致性检查
定期运行程序,扫描业务数据中的异常情况,并输出报告。
8.4 批量状态变更
对满足条件的业务对象(如订单、凭证)进行批量状态修改或处理。
九、开发规范与最佳实践
9.1 命名规范
- 程序名以 Z 或 Y 开头
- 名称应具有业务含义:
Z_PURCHASE_ORDER_REPORT优于ZTEST123 - 使用下划线分隔单词
9.2 代码组织
- 将类型定义和全局数据放在程序开头(TOP 部分)
- 将复杂业务逻辑封装成 FORM 子程序 或 局部类(Local Class)
- 使用
INCLUDE语句将代码拆分到多个包含程序中,提升可维护性
abap
REPORT Z_MY_PROGRAM.
INCLUDE Z_MY_PROGRAM_TOP. " 数据定义
INCLUDE Z_MY_PROGRAM_F01. " FORM 子程序
INCLUDE Z_MY_PROGRAM_E01. " 事件块
9.3 性能优化
- 避免
SELECT *:只查询需要的字段 - 使用内表批量处理 :尽量用
SELECT ... INTO TABLE一次性读取数据,避免逐行APPEND - 善用索引 :在
WHERE条件中使用数据库表的索引字段 - 使用
FOR ALL ENTRIES:当需要根据另一个内表查询数据时使用
abap
" 不推荐:循环中逐条查询
LOOP AT it_main.
SELECT SINGLE * FROM ekpo WHERE ebeln = it_main-ebeln.
ENDLOOP.
" 推荐:批量查询
SELECT * FROM ekpo INTO TABLE it_ekpo
FOR ALL ENTRIES IN it_main
WHERE ebeln = it_main-ebeln.
9.4 异常处理
- 使用
MESSAGE语句向用户反馈错误信息 - 在后台作业中,将错误信息写入日志文件或自定义日志表
十、常用事务码速查
| 事务码 | 用途 |
|---|---|
| SE38 | ABAP 编辑器(创建、修改、运行可执行程序) |
| SA38 | 执行可执行程序(比 SE38 更轻量) |
| SE80 | 对象导航器(管理程序及其组件) |
| SE93 | 为程序创建事务代码 |
| SM36 | 定义后台作业 |
| SM37 | 监控后台作业 |
| SLIN | ABAP 扩展程序检查(代码质量检查) |
十一、总结
可执行程序是 SAP ABAP 开发的基石。掌握它,你就掌握了 SAP 开发的第一把钥匙。本文的核心要点:
| 维度 | 核心内容 |
|---|---|
| 定义 | 无需事务码、可在 SE38 中直接运行的程序(类型值 1) |
| 核心特征 | 事件块驱动、自带选择屏幕、支持逻辑数据库、可后台调度 |
| 创建步骤 | SE38 → 新建 → 选择"可执行程序" → 编写 REPORT + 业务逻辑 → 激活 → 运行 |
| 事件块顺序 | LOAD-OF-PROGRAM → INITIALIZATION → AT SELECTION-SCREEN → START-OF-SELECTION → END-OF-SELECTION |
| 选择屏幕 | PARAMETERS(单值)、SELECT-OPTIONS(范围) |
| 逻辑数据库 | 通过程序属性关联,使用 GET 事件接收数据 |
| 后台调度 | SM36 定义作业 + SM37 监控 |
| 最佳实践 | Z/Y 命名、避免 SELECT *、批量处理、代码分层 |
可执行程序看似简单,但它的设计思想------事件驱动、声明式选择屏幕、与逻辑数据库的集成------贯穿了 SAP 开发的方方面面。当你熟悉了可执行程序,再学习模块池、函数组、类池等其他程序类型时,会发现许多概念是一脉相承的。
现在,打开 SE38,写下你的第一行 REPORT 语句,开始你的 SAP 开发之旅吧!
本文基于 SAP 经典 ABAP 开发环境编写,适用于 ECC 6.0 及早期版本。现代 S/4HANA 开发范式(CDS、RAP、Application Jobs 等)不在本文讨论范围内,如有需要可参考相关专题文章。