演示结构体赋值与内表循环输出,读取系统表数据到结构体显示在alv


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.
posted @ 2026-07-09 11:37  虚拟过客之IT老男人  阅读(9)  评论(0)    收藏  举报