Mark的技术博客

SAP顾问 | 咨询专家 | IT与AI技术探索者

吴让宇(Mark)

吴让宇(Mark)

SAP顾问 | 咨询专家 | IT与AI技术探索者

吴让宇(Mark)的个人技术博客,专注于SAP系统实施、行业方案咨询、IT技术与AI技术的研究与分享。

SAP Fiori ABAP CDS OData Dify Docker AI LLM

最新文章

ABAP 屏幕导航

🎯 概述

为了理解SAP ABAP,您需要掌握基本屏幕操作知识,包括登录、ABAP编辑器使用、注销等操作。本章重点介绍屏幕导航和标准工具栏功能。

🔐 登录屏幕

登录流程

  1. 🖥️ 启动SAP登录界面
  2. 🆔 输入用户ID(由系统管理员提供)
  3. 🔑 输入密码
  4. ⏎ 按Enter键登录

登录界面元素

  • 👤 用户ID输入框
  • 🔒 密码输入框
  • 🚪 登录按钮
  • ⚙️ 系统选项选择

提示:确保使用有效的用户ID和密码,注意密码大小写敏感。

🛠️ SAP屏幕结构

工具栏组件



graph TB
    A[菜单栏] --> B[标准工具栏]
    B --> C[标题栏]
    C --> D[应用程序工具栏]
    D --> E[命令字段]

📋 菜单栏

  • 位置:对话框窗口的顶行
  • 功能:提供各种菜单选项
  • 特点:包含系统、编辑、视图、导航等菜单

⚙️ 标准工具栏

  • 功能:提供常用操作功能
  • 📑 页首/页尾
  • 📄 上一页/下一页
  • 💾 保存功能

🏷️ 标题栏

  • 显示内容:当前所在应用程序/业务流程的名称
  • 作用:帮助用户定位当前操作位置

🎯 应用程序工具栏

  • 特点:提供特定于应用程序的菜单选项
  • 动态性:根据当前程序不同而变化

💻 命令字段

  • 功能:直接启动应用程序,无需浏览菜单
  • 使用方法:在命令字段中输入事务代码
  • 优势:快速访问常用事务

📝 ABAP编辑器

启动方式

在命令字段中输入 SE38 直接启动ABAP编辑器。

ABAP编辑器界面

  • 📝 代码编辑区域
  • 🎯 程序属性设置
  • 🔧 工具栏功能
  • 📊 状态信息显示

⌨️ 标准键和图标

退出键(Exit Keys)



graph LR
    A[返回] --> B[退出程序]
    A --> C[返回上一级]
    A --> D[注销系统]

🔙 返回功能

  • 作用:返回到最后访问的屏幕
  • 快捷键:通常为 F3 或 Ctrl+F3
  • 图标:返回箭头

❌ 退出程序

  • 作用:完全退出当前程序
  • 快捷键:通常为 F15 或 Ctrl+F15
  • 图标:关闭按钮

报表操作选项

🔍 检查报表

  • 功能:检查语法错误
  • 图标:对勾或检查标志
  • 快捷键:Ctrl+F7

✅ 激活报表

  • 功能:编译并激活程序
  • 图标:勾选或激活标志
  • 快捷键:Ctrl+F8

▶️ 处理报表

  • 功能:运行程序
  • 图标:播放按钮
  • 快捷键:F8

🚪 注销操作

注销的重要性

  • 🔒 安全性:完成工作后退出系统
  • 💪 资源释放:释放服务器资源
  • 👥 良好习惯:避免会话占用

注销方式

  1. 🖱️ 点击工具栏的”退出”按钮
  2. ⌨️ 使用快捷键(通常为 F15)
  3. 📱 通过菜单选择”系统”→”退出”

注销界面

  • 🔍 确认提示
  • 💾 保存更改选项
  • ⚡ 快速退出选项

📚 实践操作

常用事务码速查

事务码 功能描述 快捷方式
SE38 ABAP编辑器 直接输入
SE16 数据浏览器 数据查询
SE11 数据字典 表查看
SM30 视图维护 数据维护
SE80 对象浏览器 导航浏览

导航技巧

  1. 🚀 使用命令字段快速访问
  2. ⌨️ 记住常用快捷键
  3. 🖱️ 熟悉工具栏图标
  4. 🧭 使用F3返回导航
  5. 💾 保存和激活良好习惯

ABAP 对象事件

📖 简介

事件(Event)是ABAP面向对象编程中的重要概念,它允许一个类(触发器)在特定条件发生时通知其他类(监听器),而无需知道具体的通知细节。

🔄 事件的基本概念

  • 松耦合:触发器不知道具体的事件处理程序
  • 动态绑定:在运行时动态绑定事件和处理程序
  • 多对多关系:一个事件可以触发多个处理程序
  • 单一职责:将不同功能分离到不同的类中

💡 核心原理 - 事件是在类中定义的一组结果,用于触发其他类中的事件处理程序。当事件被触发时,我们可以调用任何数量的事件处理程序方法。

🔄 事件 vs 方法调用

传统方法调用

1
调用程序 → 调用特定方法 → 固定的处理流程

事件调用

1
触发器 → 触发事件 → 动态调用所有注册的处理程序

📊 对比分析

特性 方法调用 事件调用
绑定方式 编译时绑定 运行时绑定
调用关系 直接调用,固定目标 间接调用,动态目标
耦合度 高耦合 低耦合
灵活性 固定实现 可扩展实现
适用场景 明确的业务流程 松散的功能集成

🏗️ 事件语法

定义事件

1
EVENTS: <event_name> [EXPORTING <parameters>].

事件处理程序声明

1
METHODS: <handler_name> FOR EVENT <event_name> OF <class_name>.

触发事件

1
RAISE EVENT <event_name> [EXPORTING <parameters>].

绑定事件处理程序

1
SET HANDLER <handler_name> FOR <instance_name>.

📝 事件示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
REPORT zevent1.

CLASS cl_main DEFINITION.
PUBLIC SECTION.
DATA: num1 TYPE i.
METHODS: pro IMPORTING num2 TYPE i.
EVENTS: cutoff.
ENDCLASS.

CLASS cl_eventhandler DEFINITION.
PUBLIC SECTION.
METHODS: handling_cutoff FOR EVENT cutoff OF cl_main.
ENDCLASS.

START-OF-SELECTION.
DATA: main1 TYPE REF TO cl_main.
DATA: eventhandler1 TYPE REF TO cl_eventhandler.
CREATE OBJECT main1.
CREATE OBJECT eventhandler1.
SET HANDLER eventhandler1->handling_cutoff FOR main1.
main1->pro( 4 ).

CLASS cl_main IMPLEMENTATION.
METHOD pro.
num1 = num2.
IF num2 >= 2.
RAISE EVENT cutoff.
ENDIF.
ENDMETHOD.
ENDCLASS.

CLASS cl_eventhandler IMPLEMENTATION.
METHOD handling_cutoff.
WRITE: 'Handling the CutOff'.
WRITE: / 'Event has been processed'.
ENDMETHOD.
ENDCLASS.

📝 输出结果

1
2
Handling the CutOff
Event has been processed

🔍 代码解析



graph TB
    A[cl_main.pro] -->|触发| B[cutoff事件]
    B -->|处理| C[cl_eventhandler.handling_cutoff]
    B -->|条件| D[num2 >= 2]

  1. 对象创建:创建了主类和事件处理类的实例
  2. 事件绑定:使用 SET HANDLER 将处理程序与主类实例绑定
  3. 方法调用:调用主类的 pro 方法,传入值 4
  4. 条件判断:当值 >= 2 时,触发 cutoff 事件
  5. 事件处理:执行绑定的处理程序方法

🔧 事件特性

1. 参数传递

类似于类的方法,事件可以有参数接口,但它只有输出参数。

1
2
3
4
5
EVENTS: data_changed
EXPORTING
changed_data TYPE any
old_value TYPE any
new_value TYPE any.

2. 动态绑定

事件通过使用 SET HANDLER 语句在程序中动态链接到其处理程序方法。

1
2
SET HANDLER handler1->method1 FOR instance1.
SET HANDLER handler2->method2 FOR instance1.

3. 多监听支持

一个事件可以绑定多个处理程序:

1
2
3
4
5
DATA: handler1 TYPE REF TO cl_handler1,
handler2 TYPE REF TO cl_handler2.

SET HANDLER handler1->process FOR main_instance.
SET HANDLER handler2->process FOR main_instance.

🎯 使用场景

1. UI事件处理

1
2
3
4
5
6
7
8
9
10
CLASS cl_controller DEFINITION.
PUBLIC SECTION.
EVENTS: button_clicked EXPORTING button_id TYPE string.
METHODS: handle_button_click.
ENDCLASS.

CLASS cl_ui DEFINITION.
PUBLIC SECTION.
METHODS: update_display FOR EVENT button_clicked OF cl_controller.
ENDCLASS.

2. 数据变更通知

1
2
3
4
5
6
7
8
9
10
11
12
13
14
CLASS cl_data_store DEFINITION.
PUBLIC SECTION.
EVENTS: data_changed
EXPORTING
field_name TYPE string
old_value TYPE any
new_value TYPE any.
METHODS: set_value IMPORTING value TYPE any.
ENDCLASS.

CLASS cl_audit_log DEFINITION.
PUBLIC SECTION.
METHODS: log_change FOR EVENT data_changed OF cl_data_store.
ENDCLASS.

3. 工作流处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
CLASS cl_workflow DEFINITION.
PUBLIC SECTION.
EVENTS: task_completed
EXPORTING
task_id TYPE string
result TYPE any.
METHODS: execute_task IMPORTING task_id TYPE string.
ENDCLASS.

CLASS cl_notification DEFINITION.
PUBLIC SECTION.
METHODS: send_notification FOR EVENT task_completed OF cl_workflow.
ENDCLASS.

CLASS cl_audit DEFINITION.
PUBLIC SECTION.
METHODS: audit_task FOR EVENT task_completed OF cl_workflow.
ENDCLASS.

🚀 事件模式的优势

1. 解耦合

触发器类不需要知道处理程序类的存在和处理逻辑。

2. 可扩展性

可以轻松添加新的处理程序,而无需修改触发器代码。

3. 异步处理

事件处理可以支持异步执行,提高系统性能。

4. 松散集成

不同模块之间可以通过事件进行松散集成。

⚠️ 注意事项

1. 事件管理

当触发事件时,应该在所有处理类中执行适当的事件处理程序方法。

2. 性能考虑

多个事件处理程序会影响性能,特别是在高频场景下。

3. 错误处理

需要考虑事件处理过程中的异常处理。

ABAP 对象

🎯 对象的概念

对象是一种特殊类型的变量,具有不同的==特征==和==行为==。对象的特性或属性用于描述对象的==状态==,行为或方法表示对象执行的==动作==。

对象是类的==实例==。它表示真实世界的实体,例如人或编程实体,如变量和常量。

对象的三个主要特点

特点 说明
==状态== 由一组属性及其值描述
==唯一身份== 每个对象有独一无二的标识
==行为== 在一段时间内属性中发生的变化
ℹ️状态 vs 行为
  • 对象的状态可以被描述为一组属性及其值。例如,银行帐户具有一组属性:帐号、名称、帐户类型、余额。
  • 对象的行为是指在一段时间内在其属性中发生的更改。

🔍 对象的唯一性

每个对象具有==唯一的标识==,可以用于将其与其他对象区分开。两个对象可以表现出相同的行为,并且它们可以具有或不具有相同的状态,但它们从不具有相同的身份

两个人可能具有相同的姓名、年龄和性别,但他们不相同。类似地,对象的身份在其整个生命周期永远不会改变。

^object-uniqueness

📋 对象交互

对象可以通过==发送消息==来相互交互。对象包含用于操作数据的==数据==和==代码==。对象也可以在类的帮助下用作用户定义的数据类型。

对象也称为==类型类的变量==。定义类后,可以创建属于该类的任意数量的对象。每个对象都与创建它的类型类的数据相关联。



graph TD
    A[类 Class] -->|实例化| B[对象1]
    A -->|实例化| C[对象2]
    A -->|实例化| D[对象N]
    B -->|发送消息| C
    C -->|发送消息| D
    D -->|发送消息| B

🏗️ 创建对象

对象创建通常包括以下步骤:

1. 创建引用变量

引用类创建引用变量,其语法是:

1
DATA: <object_name> TYPE REF TO <class_name>.

2. 创建对象实例

从引用变量创建对象,其语法是:

1
CREATE OBJECT: <object_name>.
💡两步创建流程
  1. 先声明 TYPE REF TO — 创建引用变量(指针)
  2. CREATE OBJECT — 在内存中分配实际对象
    两步缺一不可,引用变量只是指向对象的”遥控器”。


graph LR
    A["DATA lo_obj TYPE REF TO zcl_class"] --> B["引用变量(指针)"]
    B -->|"CREATE OBJECT lo_obj"| C["实际对象(内存)"]
    C -->|"lo_obj->method()"| D["访问对象成员"]

💡 示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
REPORT zdemo_object.
CLASS Class1 DEFINITION.
PUBLIC SECTION.
DATA: text1(45) VALUE 'ABAP Objects.'.
METHODS: Display1.
ENDCLASS.

CLASS Class1 IMPLEMENTATION.
METHOD Display1.
WRITE:/ 'This is the Display method.'.
ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
DATA: Class1 TYPE REF TO Class1.
CREATE OBJECT: Class1.
WRITE:/ Class1->text1.
CALL METHOD: Class1->Display1.

输出结果

1
2
ABAP Objects.
This is the Display method.
💥代码解析
  • CLASS Class1 DEFINITION — 定义类的结构(属性和方法声明)
  • CLASS Class1 IMPLEMENTATION — 实现类的方法逻辑
  • TYPE REF TO Class1 — 创建指向 Class1 的引用变量
  • CREATE OBJECT: Class1 — 实例化对象
  • Class1->text1 — 使用 -> 运算符访问对象成员
  • CALL METHOD: — 调用对象方法

⚠️ 注意事项

  • 对象是==类的实例==,每个对象有==唯一标识==
  • 对象通过==消息==进行交互
  • 可以创建==多个对象实例==
  • 使用 -> 运算符访问对象的属性和方法
  • 引用变量为空时访问成员会导致 CX_SY_REF_IS_INIT 异常

ABAP 异常处理

🚨 异常概述

异常是在程序执行期间出现的问题。当异常发生时:

  • 程序的正常流程中断
  • 程序应用程序异常终止(不推荐)
  • 需要处理这些异常以维持程序稳定性

异常的作用

异常提供了一种将控制从程序的一个部分转移到另一个部分的方法,确保程序在出现错误时能够优雅地处理问题。

🔧 ABAP异常处理关键字

ABAP异常处理建立在四个关键字基础上:

关键字 作用 说明
RAISE 提出异常 表示发生了一些异常情况
TRY 定义尝试块 包含要处理其异常的应用程序编码
CATCH 捕获异常 处理程序捕获异常的位置
CLEANUP 清理操作 恢复一致状态或释放外部资源

TRY-CATCH语法结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
TRY.
Try Block <Code that raises an exception>

CATCH
Catch Block <exception handler M>
. . .
. . .
. . .
CATCH
Catch Block <exception handler R>

CLEANUP.
Cleanup block <to restore consistent state>
ENDTRY.

🎯 引发异常

可以在方法中的任何点、函数模块、子例程等提出异常。有两种方式可以引发异常:

1. ABAP运行时系统引发的异常

由系统自动检测错误情况:

1
2
3
4
5
DATA: y TYPE i VALUE 1.
DATA: z TYPE i VALUE 0.
DATA: result TYPE p LENGTH 8 DECIMALS 2.

result = y / z. " 将导致类型CX_SY_ZERODIVIDE的运行时错误

2. 程序员提出的异常

程序员主动创建并引发异常:

1
2
3
DATA: exep TYPE REF TO CX_DEMO_ERROR.

RAISE EXCEPTION exep. " 使用已存在的异常对象引发异常

🕸️ 捕捉异常

处理程序示例

1
2
3
4
5
6
7
8
9
10
11
12
13
DATA: result TYPE P LENGTH 8 DECIMALS 2,
exref TYPE REF TO CX_ROOT,
msgtxt TYPE STRING.

PARAMETERS: Num1 TYPE I, Num2 TYPE I.

TRY.
result = Num1 / Num2.
CATCH CX_SY_ZERODIVIDE INTO exref.
msgtxt = exref->GET_TEXT( ).
CATCH CX_SY_CONVERSION_NO_NUMBER INTO exref.
msgtxt = exref->GET_TEXT( ).
ENDTRY.

异常类型说明

异常类 描述 处理场景
CX_SY_ZERODIVIDE 除零异常 数学运算中除数为零
CX_SY_CONVERSION_NO_NUMBER 数字转换错误 无法将字符串转换为数字

🔍 异常的属性和方法

五个重要属性和方法

编号 属性/方法 说明
1 Textid 用于定义异常的不同文本,影响get_text的结果
2 Previous 存储原始异常,允许构建异常链
3 get_text 根据系统语言将异常文本作为字符串返回
4 get_longtext 返回异常文本的长变体
5 get_source_position 给出引发异常的程序名和行号

💡 完整示例

综合异常处理示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
PARAMETERS Num_1 TYPE i.
DATA res_1 TYPE p DECIMALS 2.
DATA orf_1 TYPE REF TO cx_root.
DATA txt_1 TYPE string.

START-OF-SELECTION.
WRITE: / 'Square Root and Division with:', Num_1.
WRITE: /.
TRY.
IF abs( Num_1 ) > 150.
RAISE EXCEPTION TYPE cx_demo_abs_too_large.
ENDIF.

TRY.
res_1 = sqrt( Num_1 ).
WRITE: / 'Result of square root:', res_1.

res_1 = 1 / Num_1.
WRITE: / 'Result of division:', res_1.
CATCH cx_sy_zerodivide INTO orf_1.
txt_1 = orf_1->get_text( ).
CLEANUP.
CLEAR res_1.
ENDTRY.

CATCH cx_sy_arithmetic_error INTO orf_1.
txt_1 = orf_1->get_text( ).
CATCH cx_root INTO orf_1.
txt_1 = orf_1->get_text( ).
ENDTRY.

IF NOT txt_1 IS INITIAL.
WRITE / txt_1.
ENDIF.

WRITE: / 'Final Result is:', res_1.

输出示例(输入160)

1
2
3
Square Root and Division with: 160
The absolute value of number is too high
Final Result is: 0.00

📝 异常处理最佳实践

1. 异常分类

  • 系统异常:由ABAP运行时系统自动触发
  • 自定义异常:程序员根据业务逻辑主动抛出

2. 异常处理层次



graph TD
    A[TRY块] --> B[具体异常处理]
    A --> C[通用异常处理]
    A --> D[CLEANUP块]

3. 错误恢复策略

  • 在CLEANUP块中恢复一致状态
  • 释放外部资源(文件句柄、数据库连接等)
  • 记录错误日志供后续分析

ABAP开发规范

ℹ️概述
本文档提供了ABAP开发的命名规范和最佳实践,确保代码的一致性和可维护性。

🏷️ 命名规则

基本命名约定

遵循统一的命名规范可以提高代码的可读性和维护性。以下是各类ABAP元素的命名规则:

变量命名规则

变量类型 前缀 示例 说明
常量 CNS_ CNS_MAX_RETRY_COUNT 所有常量以 “CNS_” 开头
全局变量 GV_ GV_USER_NAME 所有全局变量以 “GV_” 开头
局部变量 LV_ LV_LOCAL_DATA 所有局部变量以 “LV_” 开头
字段符号 <FS_ 所有字段符号以 “<FS_” 开头,”>”结尾

数据结构命名规则

数据类型 前缀 示例 说明
全局内表 GT_ GT_MATERIAL_LIST 所有全局内表以 “GT_” 开头
局部内表 LT_ LT_TEMP_RESULT 所有局部内表以 “LT_” 开头
全局工作区 GS_ GS_WORK_AREA 所有全局工作区以 “GS_” 开头
局部工作区 LS_ LS_LINE_DATA 所有局部工作区以 “LS_” 开头

对象和类型命名规则

对象类型 前缀 示例 说明
全局范围 GR_ GR_GLOBAL_SCOPE 所有全局范围以 “GR_” 开头
局部范围 LR_ LR_LOCAL_SCOPE 所有局部范围以 “LR_” 开头
全局类 GC_ GC_APPLICATION_CLASS 所有全局类以 “GC_” 开头
局部类 LC_ LC_HELPER_CLASS 所有局部类以 “LC_” 开头
类型 TY_ TY_MATERIAL_STRUCTURE 所有类型以 “TY_” 开头

其他元素命名规则

元素类型 前缀 示例 说明
MCR_ MCR_DEBUG_OUTPUT 所有宏以 “MCR_” 开头
子例程 FRM_ FRM_CALCULATE_TOTAL 所有子例程以 “FRM_” 开头

🔧 子例程参数命名规则

子例程参数前缀规范

参数类型 前缀 示例 说明
USING参数(输入参数) I_ I_INPUT_DATA 所有子例程USING参数以”I”开头
CHANGING参数(修改参数) C_ C_OUTPUT_VALUE 所有子例程CHANGING参数以”C”开头
TABLE参数(表参数) T_ T_TABLE_DATA 所有子例程TABLE参数以”T”开头

子例程命名示例

1
2
3
4
5
6
FORM FRM_CALCULATE_SUM
USING I_INPUT_VALUE TYPE I
CHANGING C_RESULT_VALUE TYPE I
TABLES T_TABLE_DATA TYPE STANDARD TABLE OF TY_DATA.
" 子例程实现
ENDFORM.

💡 编码最佳实践

1. 代码结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
REPORT Z_MY_PROGRAM.

" 包含声明
INCLUDE Z_COMMON_DEFINITIONS.

" 常量定义
CONSTANTS: CNS_MAX_RETRIES TYPE I VALUE 3,
CNS_TIMEOUT TYPE I VALUE 30.

" 类型定义
TYPES: TY_MATERIAL TYPE MARA-MATNR,
TY_QUANTITY TYPE P DECIMALS 3.

" 全局变量
DATA: GV_USER_NAME TYPE SY-UNAME,
GV_ERROR_FLAG TYPE ABAP_BOOL,
GT_MATERIAL_LIST TYPE STANDARD TABLE OF TY_MATERIAL,
GS_WORK_AREA TYPE TY_MATERIAL.

" 程序开始
START-OF-SELECTION.
PERFORM FRM_PROCESS_DATA.

2. 代码格式化

  • 使用4个空格缩进
  • 每行代码不超过79个字符
  • 关键字和操作符之间使用空格
  • 逗号后使用空格

3. 注释规范

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
" 模块注释
*&---------------------------------------------------------------------*
*& Form FRM_PROCESS_DATA
*&---------------------------------------------------------------------*
* 文本
*----------------------------------------------------------------------*
FORM FRM_PROCESS_DATA.
" 局部变量定义
DATA: LV_COUNTER TYPE I VALUE 0,
LV_RESULT TYPE P DECIMALS 2.

" 处理逻辑
DO CNS_MAX_RETRIES TIMES.
LV_COUNTER = SY-INDEX.

" 业务逻辑
PERFORM FRM_VALIDATE_DATA USING I_INPUT_DATA
CHANGING C_VALID_FLAG.

" 错误处理
IF C_VALID_FLAG = ABAP_FALSE.
MESSAGE ID 'ZMSG' TYPE 'E' NUMBER '001'
WITH '数据验证失败'.
EXIT.
ENDIF.
ENDDO.
ENDFORM.

📊 命名规范速查表

元素类型 命名前缀 示例
常量 CNS_ CNS_MAX_COUNT
全局变量 GV_ GV_SYSTEM_DATE
局部变量 LV_ LV_TEMP_VALUE
全局内表 GT_ GT_ORDER_HEADER
局部内表 LT_ LT_TEMP_LINES
全局工作区 GS_ GS_ORDER_DATA
局部工作区 LS_ LS_LINE_ITEM
全局范围 GR_ GR_GLOBAL_SCOPE
局部范围 LR_ LR_LOCAL_SCOPE
全局类 GC_ GC_APPLICATION_CLASS
局部类 LC_ LC_HELPER_CLASS
类型 TY_ TY_ORDER_TYPE
MCR_ MCR_DEBUG_LOG
字段符号 <FS_
子例程 FRM_ FRM_CALCULATE_TOTAL
USING参数 I_ I_INPUT_DATA
CHANGING参数 C_ C_OUTPUT_VALUE
TABLE参数 T_ T_ITEM_TABLE

🔄 命名规范流程图



graph TD
    A[开发开始] --> B[确定变量类型]
    B --> C{选择合适的前缀}
    C --> D[按照命名规范命名]
    D --> E[代码审查]
    E --> F{是否符合规范?}
    F -->|是| G[代码提交]
    F -->|否| H[重新命名]
    H --> E
    
    D --> I[添加注释说明]
    I --> E

⚠️ 重要提醒

  1. 一致性原则:在整个项目中保持命名规范的一致性
  2. 可读性优先:命名应清晰表达变量的用途
  3. 避免缩写过度:适当使用缩写,但不要过度
  4. 团队规范:与团队成员达成一致,遵守共同的标准
  5. 文档更新:新的命名规则应及时更新到团队文档中

ABAP 屏幕

📖 简介

屏幕编程(Dialog Programming)处理多个对象的开发,所有这些对象被分层链接到主程序,并且它们按顺序执行。对话程序开发利用ABAP工作台中的工具,这些是在标准SAP应用程序开发中使用的相同工具。

🔄 屏幕编程的基本概念

  • 分层结构:多个对象按顺序链接到主程序
  • 交互式:用户与界面进行实时交互
  • 模块化:程序逻辑模块化组织
  • 事件驱动:基于用户操作触发相应处理

💡 核心特点 - 对话程序应该由对象浏览器(事务:SE80)开发,以便所有对象都被链接到主程序,而不必显式地指向每个对象。高级导航技术增强了从一个对象移动到另一个对象的过程。

🏗️ 对话程序主要组件

组件 描述 作用
屏幕 用户界面的定义 显示数据和接收用户输入
模块池 程序的模块化语法 处理屏幕逻辑和数据操作
子程序 可重用的代码块 执行特定功能
菜单 用户界面导航选项 提供操作选择
交易 程序的访问入口 启动屏幕程序

🎯 组件关系



graph TB
    A[屏幕] --> B[模块池]
    B --> C[子程序]
    D[菜单] --> A
    E[交易] --> A
    A -->|调用| F[程序逻辑]
    F -->|处理| G[数据操作]

🛠️ 工具集

对话框程序开发使用的工具包括:

  • SE80 - 对象浏览器:开发和管理所有对象
  • SE51 - 屏幕画笔:设计屏幕布局
  • PBO - 屏幕输出前的事件处理
  • PAI - 屏幕输入后的事件处理

📝 创建新对话框程序

步骤详解

步骤1 - 创建程序

在事务SE80中:

  1. 从下拉列表中选择”程序”
  2. 为自定义SAP程序输入Z名称,如”ZSCREENEX”
  3. 按Enter键确认

步骤2 - 设置包含文件

  1. 选择”使用TOP INCL”
  2. 点击”Yes”按钮

步骤3 - 输入包含名称

  1. 输入热门包含名称,如”ZSCRTOP”
  2. 点击绿色刻度线(保存)

步骤4 - 保存程序

  1. 在属性屏幕中输入标题
  2. 点击保存按钮

🔧 屏幕开发流程

1. 添加屏幕到程序

步骤:

  1. 右键单击程序名称
  2. 选择选项 Create → Screen
  3. 输入屏幕号码(如”0211”)
  4. 点击绿色刻度线(保存)
  5. 在下一个屏幕中:
    • 输入简短标题
    • 设置为正常屏幕类型
    • 点击顶部应用程序工具栏上的保存按钮

2. 屏幕布局设计

步骤:

  1. 点击应用程序工具栏中的布局按钮
  2. 出现Screen Painter窗口
  3. 添加文本字段并输入文本,如”Hello World”
  4. 保存并激活屏幕

📊 屏幕组成部分



graph LR
    A[屏幕属性] --> B[屏幕布局]
    B --> C[字段定义]
    C --> D[流逻辑]
    
    E[PBO事件] -->|初始化| F[屏幕显示前]
    G[PAI事件] -->|处理| H[用户输入后]
    I[事件处理] --> J[模块调用]

🚀 创建事务

步骤详解

步骤1 - 创建事务代码

  1. 右键单击程序名称
  2. 选择选项 创建→事务
  3. 输入事务代码(如”ZTRANEX”)

步骤2 - 配置事务

  1. 输入事务文本
  2. 设置程序和屏幕(如ZSCREENEX & 0211)
  3. 在”GUI支持”部分勾选”SAPGUI for Windows”复选框
  4. 保存并激活

📋 事务配置参数

参数 说明 示值
程序 屏幕程序名称 ZSCREENEX
屏幕 屏幕编号 0211
GUI支持 用户界面类型 SAPGUI for Windows
文本 事务描述 示例屏幕程序

🎯 屏幕类型和属性

常用屏幕类型

屏幕类型 用途 特点
Normal Screen 标准屏幕 常规数据输入
Subscreen 子屏幕 嵌入到其他屏幕中
Modal Dialog Box 模态对话框 阻塞其他操作
Popup 弹出窗口 临时显示信息

关键属性设置

1
2
PROCESS BEFORE OUTPUT.  " PBO - 屏幕显示前
PROCESS AFTER INPUT. " PAI - 屏幕输入后

💡 屏幕编程最佳实践

1. 模块化设计



graph TB
    A[主程序] --> B[模块池]
    B --> C[PBO模块]
    B --> D[PAI模块]
    C --> E[数据初始化]
    D --> F[输入验证]
    F --> G[数据保存]

2. 错误处理

1
2
3
4
5
6
MODULE validate_input.
IF input_field IS INITIAL.
MESSAGE '请输入必填字段' TYPE 'E'.
SET SCREEN 0.
ENDIF.
ENDMODULE.

3. 数据传递

1
2
3
4
5
6
7
8
9
10
11
12
MODULE data_to_screen OUTPUT.
screen-matnr = wa_matnr.
screen-maktx = wa_maktx.
ENDMODULE.

MODULE user_command_0200 INPUT.
ok_code = sy-ucomm.
CASE ok_code.
WHEN 'SAVE'.
PERFORM save_data.
ENDCASE.
ENDMODULE.

ABAP 报表

📖 简介

报表(Report)是以组织结构呈现数据的重要工具。许多数据库管理系统包括一个报表写入器,使您能够设计和生成报表。SAP应用程序支持报表创建,其中经典报表是最基础和常用的形式。

🔄 报表的基本概念

  • 数据展示:将数据库中的数据以结构化方式展示
  • 事件驱动:通过不同的事件控制报表的执行流程
  • 格式化输出:控制数据的显示格式和布局
  • 交互式:支持用户输入和选择

💡 核心特点 - 使用循环内的WRITE语句中的输出数据创建经典报表。它们不包含任何子报表。SAP还提供了一些标准报表,例如用于在客户端之间复制表的RSCLTCOP和用于显示实例参数的RSPARAM。

📊 报表事件

经典报表事件概述

编号 事件 & 说明
1 INITIALIZATION
在显示选择画面之前触发。
2 AT SELECTION-SCREEN
在选择屏幕上处理用户输入后触发。此事件在执行程序之前验证用户输入。在处理用户输入之后,选择屏幕保持在活动模式。
3 START-OF-SELECTION
仅在选择屏幕的处理结束后触发;即当用户点击选择屏幕上的执行图标时。
4 END-OF-SELECTION
在执行START-OF-SELECTION事件中的最后一条语句之后触发。
5 TOP-OF-PAGE
由第一条WRITE语句触发以在新页面上显示数据。
6 END-OF-PAGE
触发以在报表的页面末尾显示文本。请注意,此事件是创建报告时的最后一个事件,应与REPORT语句的LINE-COUNT子句结合使用。

🎯 事件执行顺序



graph TB
    A[程序启动] --> B[INITIALIZATION]
    B --> C[显示选择屏幕]
    C --> D[用户输入]
    D --> E[AT SELECTION-SCREEN]
    E --> F{验证通过?}
    F -->|是| G[START-OF-SELECTION]
    F -->|否| C
    G --> H[数据查询和处理]
    H --> I[END-OF-SELECTION]
    I --> J[程序结束]
    
    K[分页处理] --> L[TOP-OF-PAGE]
    L --> M[数据输出]
    M --> N[END-OF-PAGE]
    M --> O[继续下一页]

📝 经典报表示例

让我们创建一个经典报表来显示标准数据库MARA(包含一般材料数据)中的信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
REPORT zreport2 LINE-SIZE 75  LINE-COUNT 30(3)  NO STANDARD PAGE HEADING.
TABLES: mara.
TYPES:
BEGIN OF itab,
matnr TYPE mara-matnr,
mbrsh TYPE mara-mbrsh,
meins TYPE mara-meins,
mtart TYPE mara-mtart,
END OF itab.
DATA: wa_ma TYPE itab,
it_ma TYPE STANDARD TABLE OF itab.
SELECT-OPTIONS: mats FOR mara-matnr OBLIGATORY.

INITIALIZATION.
mats-low = '1'.
mats-high = '500'.
APPEND mats.

AT SELECTION-SCREEN.
IF mats-low = ' '.
MESSAGE i000(zkmessage).
ELSEIF mats-high = ' '.
MESSAGE i001(zkmessage).
ENDIF.

TOP-OF-PAGE.
WRITE:/ 'CLASSICAL REPORT CONTAINING GENERAL MATERIAL DATA FROM THE TABLE MARA' COLOR 7.
ULINE.
WRITE:/ 'MATERIAL' COLOR 1,
24 'INDUSTRY' COLOR 2,
38 'UNITS' COLOR 3,
53 'MATERIAL TYPE' COLOR 4.
ULINE.

END-OF-PAGE.

START-OF-SELECTION.
SELECT
matnr
mbrsh
meins
mtart
FROM mara
INTO TABLE it_ma
WHERE matnr IN mats.
LOOP AT it_ma INTO wa_ma.
WRITE:/ wa_ma-matnr,
25 wa_ma-mbrsh,
40 wa_ma-meins,
55 wa_ma-mtart.
ENDLOOP.

END-OF-SELECTION.
ULINE.
WRITE:/ 'CLASSICAL REPORT HAS BEEN CREATED' COLOR 7.
ULINE.
SKIP.

🔍 代码解析

1. 报表基本设置

1
REPORT zreport2 LINE-SIZE 75  LINE-COUNT 30(3)  NO STANDARD PAGE HEADING.
  • LINE-SIZE 75:设置每行75个字符
  • LINE-COUNT 30(3):每页30行,标题页保留3行
  • NO STANDARD PAGE HEADING:不显示标准页头

2. 数据结构定义

1
2
3
4
5
6
7
TYPES:
BEGIN OF itab,
matnr TYPE mara-matnr,
mbrsh TYPE mara-mbrsh,
meins TYPE mara-meins,
mtart TYPE mara-mtart,
END OF itab.

定义了内表的数据结构,对应MARA表的字段。

3. 初始化事件

1
2
3
4
INITIALIZATION.
mats-low = '1'.
mats-high = '500'.
APPEND mats.

在程序启动前设置选择屏幕的默认值。

4. 选择屏幕验证

1
2
3
4
5
6
AT SELECTION-SCREEN.
IF mats-low = ' '.
MESSAGE i000(zkmessage).
ELSEIF mats-high = ' '.
MESSAGE i001(zkmessage).
ENDIF.

验证用户输入,如果输入不完整则显示错误消息。

5. 页面头部

1
2
3
4
5
6
7
8
TOP-OF-PAGE.
WRITE:/ 'CLASSICAL REPORT CONTAINING GENERAL MATERIAL DATA FROM THE TABLE MARA' COLOR 7.
ULINE.
WRITE:/ 'MATERIAL' COLOR 1,
24 'INDUSTRY' COLOR 2,
38 'UNITS' COLOR 3,
53 'MATERIAL TYPE' COLOR 4.
ULINE.

设置报表的标题和表头。

6. 数据查询和输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
START-OF-SELECTION.
SELECT
matnr
mbrsh
meins
mtart
FROM mara
INTO TABLE it_ma
WHERE matnr IN mats.
LOOP AT it_ma INTO wa_ma.
WRITE:/ wa_ma-matnr,
25 wa_ma-mbrsh,
40 wa_ma-meins,
55 wa_ma-mtart.
ENDLOOP.

执行数据库查询并输出结果。

🎯 报表组件详解

1. SELECT-OPTIONS 语句

1
SELECT-OPTIONS: mats FOR mara-matnr OBLIGATORY.
  • 允许用户输入一个范围值
  • OBLIGATORY表示该字段必须输入
  • 会生成一个范围表供WHERE条件使用

2. 格式化输出

1
2
3
4
WRITE:/ wa_ma-matnr,
25 wa_ma-mbrsh,
40 wa_ma-meins,
55 wa_ma-mtart.
  • :/ 表示新行开始
  • 数字指定了列的位置
  • COLOR 设置文本颜色

3. 格式化控制



graph LR
    A[格式化] --> B[位置控制]
    A --> C[颜色设置]
    A --> D[分隔线]
    A --> E[跳行]
    
    B --> F[固定列位]
    B --> G[对齐方式]
    
    C --> H[数字颜色]
    C --> I[文本颜色]
    
    D --> J[ULINE]
    
    E --> K[SKIP]

🚀 报表开发最佳实践

1. 代码结构组织

1
2
3
4
✓ 清晰的事件划分
✓ 合理的数据结构
✓ 适当的错误处理
✓ 用户友好的提示

2. 性能优化

  • 使用高效的SELECT语句
  • 减少数据传输量
  • 合理使用缓存

3. 用户体验

  • 提供清晰的选择界面
  • 设置合理的默认值
  • 提供错误反馈

ABAP 循环

ℹ️概述
可能有一种情况,当你需要执行一段代码几次。一般来说,语句是按顺序执行的:函数中的第一个语句首先执行,然后是第二个语句,依此类推。编程语言提供允许更复杂的执行路径的各种控制结构,循环语句允许我们多次执行一个语句或一组语句。

📐 循环执行流程



graph TD
    A[开始循环] --> B{条件判断}
    B -->|条件为真| C[执行循环体]
    B -->|条件为假| D[结束循环]
    C --> E[继续下一次循环]
    E --> B


🔁 ABAP循环类型

ABAP编程语言提供以下类型的循环来处理循环需求:

编号 循环类型 说明
1 While循环 当给定条件为真时,重复一个语句或一组语句。它在执行循环体之前测试条件。
2 Do循环 DO语句对于将特定任务重复特定次数很有用。
3 嵌套循环 你可以在任何另一个WHILE或DO循环中使用一个或多个循环。

🎯 循环控制语句

循环控制语句从其正常序列改变执行。ABAP包括允许循环提前结束的控制语句。

编号 控制语句 说明
1 CONTINUE语句 导致循环跳过其身体的剩余部分,并开始下一个循环传递。
2 CHECK语句 如果条件为假,则在CHECK之后的剩余语句被忽略,并且系统开始下一循环通过。
3 Exit语句 完全终止循环,并将执行转移到循环后立即执行的语句。

控制语句对比

语句 作用 特点
CONTINUE 跳过当前循环剩余部分 进入下一次循环
CHECK 跳过循环剩余部分(条件为假时) 类似于CONTINUE,但有条件
EXIT 立即退出循环 结束整个循环

💡 循环使用场景

1. 遍历数据

1
2
3
4
5
6
7
8
9
" 遍历内表
DATA: lt_table TYPE TABLE OF mara,
wa_table TYPE mara.

SELECT * FROM mara INTO TABLE lt_table.

LOOP AT lt_table INTO wa_table.
WRITE: / wa_table-matnr, wa_table-maktx.
ENDLOOP.

2. 重复执行任务

1
2
3
4
" 重复执行5次
DO 5 TIMES.
WRITE: / 'Processing iteration', sy-index.
ENDDO.

3. 条件循环

1
2
3
4
5
6
7
" 条件循环
DATA: lv_count TYPE I VALUE 1.

WHILE lv_count <= 10.
WRITE: / 'Count:', lv_count.
lv_count = lv_count + 1.
ENDWHILE.

⚠️ 注意事项

1. 避免无限循环

1
2
3
4
5
6
7
8
9
10
11
12
13
" ❌ 危险:可能造成无限循环
DATA: lv_count TYPE I VALUE 1.
WHILE lv_count > 0.
WRITE: / 'This loop will never end!'.
" 缺少修改循环条件的代码
ENDWHILE.

" ✅ 正确:确保循环能结束
DATA: lv_count TYPE I VALUE 1.
WHILE lv_count <= 10.
WRITE: / 'Iteration:', lv_count.
lv_count = lv_count + 1.
ENDWHILE.

2. 循环性能

  • 避免在循环中进行不必要的计算
  • 尽量使用内表索引操作
  • 注意循环次数对性能的影响

3. 内存使用

  • 大数据量时注意内存占用
  • 考虑分批处理大量数据
  • 及时释放不再需要的数据

📊 循环选择指南



graph LR
    A[选择循环类型] --> B{需要控制次数?}
    B -->|是| C[使用DO循环]
    B -->|否| D{基于条件循环?}
    D -->|是| E[使用WHILE循环]
    D -->|否| F[使用LOOP循环]
    
    C --> G[DO n TIMES]
    C --> H[DO ... VARYING]
    
    E --> I[WHILE condition]
    E --> J[WHILE ... condition]
    
    F --> K[LOOP AT table]
    F --> L[LOOP AT ... INTO]


💡 最佳实践

1. 循环设计原则

  • 明确循环的终止条件
  • 确保循环能够正常结束
  • 避免过深的嵌套

2. 代码可读性

  • 使用有意义的循环变量名
  • 添加必要的注释说明
  • 保持循环结构简洁

3. 性能优化

  • 减少循环体内的复杂操作
  • 考虑使用索引访问
  • 避免在循环中创建临时对象

4. 错误处理

  • 添加适当的错误处理机制
  • 考虑循环异常情况
  • 确保资源正确释放

ABAP 数据类型

ℹ️概述
当在ABAP中编程时,我们需要使用各种变量来存储各种信息。变量只是保留值的存储位置。基于变量的数据类型,操作系统分配内存并决定在保留内存中可以存储的内容。

📊 基本数据类型

ABAP为程序员提供了丰富的固定长度和可变长度数据类型。

数据类型关键词

类型 关键词 描述
字节字段 X 存储二进制数据
文本域 C 存储字符数据
数字文本字段 N 存储数字字符
日期字段 D 存储日期信息
时间字段 T 存储时间信息
整数 I 存储整数值
浮点数 F 存储浮点数
打包数量 P 存储十进制数
文本字符串 STRING 可变长度文本
字节字符串 XSTRING 可变长度二进制数据

数据类型分类

ABAP数据类型可以分为以下几类:

  • byte: 字节类型
  • numeric: 数字类型
  • character-like: 字符类型

内存占用和范围

类型 典型长度 典型范围 说明
X 1字节 00到FF 任何字节值
C 1个字符 1~65535 文本字符
N 1个字符 1~65535 数字文本
D 8个字符 固定8字符 日期格式
T 6个字符 固定6字符 时间格式
I 4字节 -2147483648至2147483647 32位整数
F 8字节 ±2.225E-308至±1.798E+308 64位浮点数
P 8字节 [-10^(2len-1)+1]到[+10^(2len-1)] 打包十进制数
STRING 可变 任意长度 动态字符串
XSTRING 可变 任意字节值 动态二进制数据
💥代码示例
1
2
3
4
5
6
7
8
9
10
11
12
REPORT YR_SEP_12.
DATA text_line TYPE C LENGTH 40.
text_line = 'A Chapter on Data Types'.
Write text_line.

DATA text_string TYPE STRING.
text_string = 'A Program in ABAP'.
Write / text_string.

DATA d_date TYPE D.
d_date = SY-DATUM.
Write / d_date.

输出结果

1
2
3
A Chapter on Data Types
A Program in ABAP
12092015
📌字符串类型说明
  • 类型STRING数据对象通常应用于固定长度不重要的字符内容
  • DATE类型用于存储日期信息,并且可以存储八位数字
  • N类型只能存储数字字符,不能存储其他字符

🔧 复杂和参考类型

复杂类型分类

复杂类型分为结构类型表类型

结构类型

在结构类型中,基本类型和结构(即嵌入在结构中的结构)被分组在一起。你可以只考虑基本类型的分组,但必须意识到结构的嵌套可用性。

💡数据访问
当基本类型被分组在一起时,数据项可以作为分组数据项被访问或者可以访问各个基本类型数据项(结构字段)。

表类型(内部表)

表类型在其他编程语言中更好地称为数组。数组可以是简单数组或结构数组。在ABAP中,数组被称为内部表,并且与其他编程语言相比,它们可以以许多方式被声明和操作。

内部表参数

S.No. 参数 & 描述
1 行类型

内部表的行可以是基本类型、复杂类型或引用类型
2

将字段或一组字段指定为标识表行的内部表的键。键包含基本类型的字段
3 访问方法

描述ABAP程序如何访问单个表条目

引用类型

引用类型用于引用类、接口和运行时数据项的实例。ABAP OOP运行时类型服务(RTTS)允许在运行时声明数据项。

⚠️引用类型用途
  • 用于面向对象编程中的对象引用
  • 用于动态创建和操作数据
  • 支持运行时类型检查

📊 ABAP数据类型关系图



graph TD
    A[ABAP数据类型] --> B[基本数据类型]
    A --> C[复杂类型]
    A --> D[引用类型]
    
    B --> B1[字节类型<br/>X, XSTRING]
    B --> B2[字符类型<br/>C, N, STRING]
    B --> B3[数值类型<br/>I, F, P]
    B --> B4[日期时间<br/>D, T]
    
    C --> C1[结构类型]
    C --> C2[表类型/内部表]
    
    D --> D1[对象引用]
    D --> D2[接口引用]
    D --> D3[运行时类型]

💡 最佳实践

  1. 数据类型选择

    • 对于固定长度的文本使用TYPE C
    • 对于动态文本使用TYPE STRING
    • 对于数字计算使用TYPE I或TYPE F
    • 对于货币金额使用TYPE P
  2. 内存管理

    • 合理设置字段长度,避免浪费内存
    • 注意数据类型的范围限制
    • 对于大数字考虑使用F类型
  3. 性能考虑

    • 避免频繁转换数据类型
    • 合理使用STRING的动态特性
    • 注意P类型的小数位限制

ABAP 格式化数据

ℹ️概述
ABAP提供各种类型的格式化选项以格式化程序的输出。例如,您可以创建包含不同颜色或格式样式的各种项目的列表。WRITE语句是用于在屏幕上显示数据的格式化语句。

📝 WRITE语句语法

WRITE语句的语法是:

1
WRITE <format> <f> <options>.

参数说明

  • <format> - 输出格式规范,可以是指示从新行开始的输出的显示的正斜杠(/)
  • <f> - 数据变量或编号文本
  • <options> - 格式化选项

格式规范示例

格式规范 说明
/ 从新行开始
04(6) 从第4列开始,列长度为6
20 显示在第20列

🔘 基本格式化选项

对齐方式

编号 选项 说明
1 LEFT-JUSTIFIED 指定输出为左对齐
2 CENTERED 表示输出居中
3 RIGHT-JUSTIFIED 指定输出为右对齐

位置控制

编号 选项 说明
4 UNDER 输出直接在字段下启动
5 NO-GAP 指定字段之后的空白被拒绝

编辑掩码

编号 选项 说明
6 USING EDIT MASK 表示格式模板的规范
7 NO-ZERO 如果字段只包含零,则它们将被空格替换

🔢 数字格式化选项

编号 选项 说明
1 NO-SIGN 指定屏幕上不显示前导符号
2 EXPONENT 指定在类型F(浮点字段)中,指数在中定义
3 ROUND 类型P字段先乘以10**(-r),然后四舍五入为整数值
4 CURRENCY 表示格式化是根据货币值存储在TCURX数据库表中
5 UNIT 指定小数位数根据单位,如类型P的T006数据库表中指定
6 DECIMALS 指定数字的数目必须显示在小数点后面

📅 日期格式化选项

格式化选项 示例
DD/MM/YY 13/01/15
MM/DD/YY 01/13/15
DD/MM/YYYY 13/01/2015
MM/DD/YYYY 01/13/2015
DDMMYY 130115
MMDDYY 011315
YYMMDD 150113
📌日期格式说明
  • DD - 代表两个数字中的日期
  • MM - 代表两个数字中的月份
  • YY - 代表两个数字中的年份
  • YYYY - 代表一年中的四个数字

📝 示例代码

基本格式化示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
REPORT ZTest123_01.
DATA:
n(9) TYPE C VALUE 'Tutorials',
m(5) TYPE C VALUE 'Point'.

-- 基本输出
WRITE: n, m.

-- 换行和对齐
WRITE: / n, / m UNDER n.

-- 无间隙连接
WRITE: / n NO-GAP, m.

-- 时间格式化
DATA time TYPE T VALUE '112538'.
WRITE: / time, -- 输出: 112538
/(8) time USING EDIT MASK '__:__:__'. -- 输出: 11:25:38

输出

1
2
3
4
5
6
Tutorials Point
Tutorials
Point
TutorialsPoint
112538
11:25:38

数字格式化示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
REPORT ZTest123_01.
DATA:
amount TYPE P DECIMALS 2 VALUE 1234.56,
number TYPE I VALUE -12345,
float TYPE F VALUE 1234.5678.

-- 基本数字输出
WRITE: / 'Basic amount:', amount.
WRITE: / 'Basic number:', number.

-- 格式化选项
WRITE: / 'NO-SIGN:', number NO-SIGN.
WRITE: / 'CURRENCY:', amount CURRENCY 'EUR'.
WRITE: / 'DECIMALS:', amount DECIMALS 4.
WRITE: / 'ROUND:', amount ROUND 2.

-- 浮点数格式化
WRITE: / 'EXPONENT:', float EXPONENT 2.

输出

1
2
3
4
5
6
7
Basic amount: 1,234.56
Basic number: -12345
NO-SIGN: 12345
CURRENCY: €1,234.56
DECIMALS: 1,234.5600
ROUND: 1,235.00
EXPONENT: 1.23457E+03

日期格式化示例

1
2
3
4
5
6
7
8
9
10
11
REPORT ZTest123_01.
DATA: date TYPE D VALUE '20240315'.

-- 不同日期格式
WRITE: / 'Date format 1:', date DD/MM/YYYY.
WRITE: / 'Date format 2:', date MM/DD/YYYY.
WRITE: / 'Date format 3:', date YYMMDD.
WRITE: / 'Date format 4:', date DDMMYY.

-- 使用编辑掩码
WRITE: / 'Custom format:', date USING EDIT MASK 'Day: DD Month: YYYY'.

输出

1
2
3
4
5
Date format 1: 15/03/2024
Date format 2: 03/15/2024
Date format 3: 240315
Date format 4: 150324
Custom format: Day: 15 Month: 2024

🎨 高级格式化技巧

1. 颜色和样式

1
2
3
4
5
6
7
8
9
10
11
12
REPORT ZTest123_01.
DATA: text TYPE C VALUE 'Colored Text'.

-- 设置颜色
FORMAT COLOR COL_POSITIVE.
WRITE: / 'Positive Text', text.

FORMAT COLOR COL_NEGATIVE.
WRITE: / 'Negative Text', text.

FORMAT COLOR COL_HEADING.
WRITE: / 'Heading Text', text.

2. 热点功能

1
2
3
4
5
6
7
8
9
10
11
12
13
REPORT ZTest123_01.
DATA:
lv_field(10) VALUE 'Click Me',
lv_value TYPE I VALUE 100.

-- 创建热点
WRITE: / lv_field HOTSPOT ON.
WRITE: / 'Value:', lv_value.

AT LINE-SELECTION.
IF sy-lspos = 1. -- 点击第一列
WRITE: / 'You clicked on:', lv_field.
ENDIF.

3. 列对齐和布局

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
REPORT ZTest123_01.
DATA:
col1 TYPE C VALUE 'Name',
col2 TYPE C VALUE 'Age',
col3 TYPE C VALUE 'City',
val1 TYPE C VALUE 'John',
val2 TYPE I VALUE 30,
val3 TYPE C VALUE 'New York'.

-- 表格形式输出
WRITE: / col1 UNDER col1,
col2 UNDER col2,
col3 UNDER col3.

ULINE.

WRITE: / val1 LEFT-JUSTIFIED,
val2 RIGHT-JUSTIFIED,
val3 CENTERED.

输出

1
2
3
Name    Age   City
------------------
John 30 New York

⚙️ 常用格式化组合

1. 货币格式化

1
2
3
4
5
6
7
8
9
10
REPORT ZTest123_01.
DATA:
amount TYPE P DECIMALS 2 VALUE 12345.67,
currency TYPE C VALUE 'USD'.

-- 不同货币格式
WRITE: / 'Basic:', amount.
WRITE: / 'Currency:', amount CURRENCY currency.
WRITE: / 'With Unit:', amount UNIT 'PC'.
WRITE: / 'Round:', amount ROUND -2.

2. 时间格式化

1
2
3
4
5
6
7
REPORT ZTest123_01.
DATA: time TYPE T VALUE '143025'.

-- 不同时间格式
WRITE: / 'Basic:', time.
WRITE: / 'With mask:', time USING EDIT MASK '__:__:__'.
WRITE: / 'Short:', time USING EDIT MASK '__:__'.

3. 列宽控制

1
2
3
4
5
6
7
8
9
REPORT ZTest123_01.
DATA:
long_text TYPE C VALUE 'This is a long text that needs to be formatted',
short_text TYPE C VALUE 'Short'.

-- 控制列宽
WRITE: / long_text.
WRITE: /(20) long_text. -- 限制宽度为20
WRITE: / short_text NO-GAP.

🎯 实际应用场景

1. 报表输出格式化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
" 生成格式化的销售报表
REPORT ZSalesReport.
DATA:
lt_sales TYPE TABLE OF zsals,
wa_sales TYPE zsals.

SELECT * FROM zsals INTO TABLE lt_sales
WHERE bukrs = '1000'
UP TO 100 ROWS.

" 报表标题
WRITE: / 'SALES REPORT'.
ULINE.
WRITE: / 'Company' HOTSPOT ON,
'Material' HOTSPOT ON,
'Quantity' RIGHT-JUSTIFIED,
'Amount' RIGHT-JUSTIFIED.

ULINE.

LOOP AT lt_sales INTO wa_sales.
WRITE: / wa_sales-bukrs UNDER 'Company',
wa_sales-matnr UNDER 'Material',
wa_sales-menge RIGHT-JUSTIFIED,
wa_sales-netwr RIGHT-JUSTIFIED CURRENCY 'EUR'.
ENDLOOP.

2. ALV报表基础

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
" ALV显示前的数据准备
DATA: lt_fieldcat TYPE TABLE OF lvc_s_fcat.

" 定义字段目录
APPEND VALUE #(
fieldname = 'MATNR'
coltext = 'Material Number'
outputlen = 18
hotspot = 'X'
) TO lt_fieldcat.

APPEND VALUE #(
fieldname = 'MAKTX'
coltext = 'Description'
outputlen = 40
hotspot = 'X'
) TO lt_fieldcat.

APPEND VALUE #(
fieldname = 'NETWR'
coltext = 'Net Value'
outputlen = 15
currency = 'EUR'
hotspot = 'X'
) TO lt_fieldcat.

3. Web界面格式化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
" 生成HTML格式的输出
REPORT ZWebOutput.
DATA: html TYPE STRING.

" 构建HTML内容
html = '<table border="1">' &&
'<tr><th>Name</th><th>Age</th></tr>' &&
'<tr><td>John</td><td>30</td></tr>' &&
'</table>'.

" 写入HTML
CALL FUNCTION 'HTML '
EXPORTING
html = html.

⚠️ 注意事项

1. 性能考虑

1
2
3
4
5
6
7
8
9
10
11
" ❌ 性能差:频繁的格式化
DO 1000 TIMES.
WRITE: / 'Line:', sy-index USING EDIT_MASK '0000'.
ENDDO.

" ✅ 性能好:预格式化
DATA: lv_text TYPE C VALUE 100.
DO 1000 TIMES.
lv_text = |Line: { sy-index ALIGN = 'LEFT' }|.
WRITE: / lv_text.
ENDDO.

2. 内存使用

1
2
3
4
5
" ❌ 内存浪费:大字符串
DATA: lv_large TYPE C VALUE 100000.

" ✅ 内存优化:按需分配
DATA: lv_optimized(80) TYPE C.

3. 显示控制

1
2
3
4
5
6
" 控制显示区域
WRITE: / 'Header' COLOR COL_HEADING.
ULINE.

WRITE: / 'Content' UNDER 'Header'.
ULINE.

💡 格式化最佳实践

1. 一致性原则

  • 保持整个应用程序的格式化风格一致
  • 使用标准的颜色和样式
  • 统一的日期和数字格式

2. 可读性优化

  • 合理的列宽和对齐
  • 适当的间距和分隔
  • 清晰的标题和说明

3. 性能优化

  • 避免在循环中进行复杂格式化
  • 使用预定义的格式模板
  • 减少不必要的格式化选项

4. 用户体验

  • 考虑不同用户的显示偏好
  • 提供格式化选项的配置
  • 确保格式化后的数据易于理解

💡 最佳实践

1. 格式化设计原则

  • 根据数据类型选择合适的格式化选项
  • 保持输出的可读性和一致性
  • 考虑不同用户的显示需求

2. 代码质量

  • 使用有意义的格式化选项
  • 添加必要的注释说明
  • 保持代码的简洁和清晰

3. 维护考虑

  • 将格式化逻辑集中管理
  • 使用参数化格式化选项
  • 避免硬编码格式化值

4. 测试验证

  • 测试各种格式化选项
  • 验证显示效果
  • 检查性能影响
0%