REPORT z_struct_loop_demo.
* 1. 定义结构体类型:包含姓名、地址、年龄
TYPES: BEGIN OF ty_person,
name TYPE string, " 姓名
addr TYPE string, " 地址
age TYPE i, " 年龄
END OF ty_person.
* 2. 基于结构体类型定义内表和工作区
DATA: gt_people TYPE TABLE OF ty_person, " 内表
gs_person TYPE ty_person. " 工作区(结构体变量)
* 3. 给结构体赋值并添加到内表(模拟多条数据)
START-OF-SELECTION.
" 第一条记录
gs_person-name = '张三'.
gs_person-addr = '北京市朝阳区'.
gs_person-age = 28.
APPEND gs_person TO gt_people.
CLEAR gs_person. " 清空工作区,准备下一条
" 第二条记录
gs_person-name = '李四'.
gs_person-addr = '上海市浦东新区'.
gs_person-age = 34.
APPEND gs_person TO gt_people.
CLEAR gs_person.
" 第三条记录
gs_person-name = '王五'.
gs_person-addr = '广州市天河区'.
gs_person-age = 22.
APPEND gs_person TO gt_people.
CLEAR gs_person.
" 也可以使用 VALUE #( ) 语法直接内表赋值(更简洁,SAP 740+ 支持)
" gt_people = VALUE #(
" ( name = '赵六' addr = '深圳市南山区' age = 30 )
" ( name = '孙七' addr = '成都市高新区' age = 26 )
" ).
" 注:上面这种写法更现代,但如果系统版本较低,建议使用上面的 APPEND 方式。
* 4. 循环输出内表中的所有记录
LOOP AT gt_people INTO gs_person.
WRITE: / '姓名:', gs_person-name,
' 地址:', gs_person-addr,
' 年龄:', gs_person-age.
ENDLOOP.
* 5. 输出总条数
SKIP 1.
WRITE: '共计输出 ', LINES( gt_people ), ' 条记录。'.
* 3. 定义从系统表读取数据所需的变量
DATA: lt_usr21 TYPE TABLE OF usr21, " USR21 系统表内表
ls_usr21 TYPE usr21. " USR21 系统表工作区
* 4. 从系统表 USR21 中读取数据(取前10条作为示例)
START-OF-SELECTION.
" 从 USR21 表读取数据,该表存储了用户名与地址编号的分配关系[reference:0]
SELECT *
FROM usr21
INTO TABLE lt_usr21
UP TO 100 ROWS. " 限制条数,避免数据过多
IF sy-subrc <> 0.
WRITE: '未从 USR21 表中读取到数据。'.
EXIT.
ENDIF.
* 5. 将系统表数据映射到自定义结构体并存入内表
LOOP AT lt_usr21 INTO ls_usr21.
CLEAR gs_person.
" 字段映射:将 USR21 的字段赋值给 ty_person 结构体
gs_person-name = ls_usr21-bname. " BNAME = 用户名[reference:1]
" 地址信息:USR21 存储的是地址编号(ADDRNUMBER)[reference:2],此处直接转为字符串演示
" 如需获取完整地址文本,可进一步关联 ADRC 表或调用函数 ADDR_GET[reference:3]
gs_person-addr = ls_usr21-ADDRNUMBER. " ADDRNUMBER = 地址编号
" USR21 表没有年龄字段,此处用系统字段 sy-tabix(循环索引)模拟年龄数据
gs_person-age = sy-tabix + 20. " 生成模拟年龄
APPEND gs_person TO gt_people.
ENDLOOP.
* 6. 循环输出内表中的所有记录
LOOP AT gt_people INTO gs_person.
WRITE: / '姓名:', gs_person-name,
' 地址编号:', gs_person-addr,
' 年龄:', gs_person-age.
ENDLOOP.
* 7. 输出总条数
SKIP 1.
WRITE: '共计从 USR21 读取并输出 ', LINES( gt_people ), ' 条记录。'.
TRY.
" 调用工厂方法,将内表 gt_people 传入
cl_salv_table=>factory(
IMPORTING
r_salv_table = DATA(lo_salv_table) " 内联声明 SALV 对象
CHANGING
t_table = gt_people " 传入要显示的内表
).
" (可选) 显示标准工具栏
lo_salv_table->get_functions( )->set_all( ).
" (可选) 设置ALV标题和条纹显示
DATA(lo_display_settings) = lo_salv_table->get_display_settings( ).
lo_display_settings->set_list_header( '人员信息列表' ). " 设置标题
lo_display_settings->set_striped_pattern( abap_true ). " 设置条纹显示
"自定义宽度
DATA(lo_columns) = lo_salv_table->get_columns( ).
TRY.
lo_columns->get_column( 'NAME' )->set_short_text( '姓名' ).
lo_columns->get_column( 'ADDR' )->set_short_text( '地址' ).
lo_columns->get_column( 'AGE' )->set_short_text( '年龄' ).
lo_columns->get_column( 'NAME' )->set_output_length( 20 ).
lo_columns->get_column( 'ADDR' )->set_output_length( 50 ).
lo_columns->get_column( 'AGE' )->set_output_length( 10 ).
CATCH cx_salv_not_found.
ENDTRY.
"自适应宽度
TRY.
" 姓名列
DATA(lo_column) = lo_columns->get_column( 'NAME' ).
lo_column->set_short_text( '姓名' ).
lo_column->set_optimized( abap_true ). " ← 自适应宽度
" 地址列
lo_column = lo_columns->get_column( 'ADDR' ).
lo_column->set_short_text( '地址' ).
lo_column->set_optimized( abap_true ).
" 年龄列
lo_column = lo_columns->get_column( 'AGE' ).
lo_column->set_short_text( '年龄' ).
lo_column->set_optimized( abap_true ).
CATCH cx_salv_not_found.
MESSAGE '字段名不存在,请检查' TYPE 'E'.
ENDTRY.
" 显示 ALV
lo_salv_table->display( ).
CATCH cx_salv_msg INTO DATA(lo_exception).
" 异常处理
MESSAGE lo_exception->get_text( ) TYPE 'E'.
ENDTRY.