当前位置: 首页 > article >正文

ABAP语言的动态程序

通过几个例子,由浅入深讲解 ABAP 动态编程。ABAP 动态编程主要通过 RTTS (Runtime Type Services) 来实现,包括 RTTI 和 RTTC:

  • 运行时类型标识(RTTI) – 提供在运行时获取数据对象的类型定义的方法。
  • 运行时类型创建(RTTC) – 提供在运行时使用任何类型定义创建数据对象的方法。

动态程序的基本要素

第一个例子主要演示构建程序的最基本要素。
第一步:创建 structure descriptor 和 table descriptor,主要用于后面动态构建内表的结构:

data struct_descr type ref to cl_abap_datadescr.
data table_descr type ref to cl_abap_tabledescr.

struct_descr ?= cl_abap_structdescr=>describe_by_name( 'SFLIGHTS' ).
table_descr ?= cl_abap_tabledescr=>create( p_line_type = struct_descr ).

第二步:基于 table descriptor 创建泛型的 data reference object:

data table_dref type ref to data.
create data table_dref type handle table_descr.

第三步:使用 field symbol,将 table reference object 指向 field symbol。

field-symbols <table> type any table.
assign table_dref->* to <table>.

这样,就动态创建了一个内表 <table>。第一个完整的例子:

report  z_dynamic_table_01.

data gr_alv type ref to cl_salv_table.

data struct_descr type ref to cl_abap_datadescr.
data table_descr type ref to cl_abap_tabledescr.

struct_descr ?= cl_abap_structdescr=>describe_by_name( 'SFLIGHTS' ).
table_descr ?= cl_abap_tabledescr=>create( p_line_type = struct_descr ).

data table_dref type ref to data.
create data table_dref type handle table_descr.

field-symbols <table> type any table.
assign table_dref->* to <table>.

select * from sflights up to 10 rows into corresponding fields of table <table>.

try.
    call method cl_salv_table=>factory
      importing
        r_salv_table = gr_alv
      changing
        t_table      = <table>.
  catch cx_salv_msg .
endtry.

gr_alv->display( ).

动态程序的灵活性

如果只是从 SFLIGHTS 表获取数据,当然没必要使用动态程序,因为它让程序更加复杂。我们对上面的程序进行修改,支持在选择屏幕中输入任意表名,都能够在 ALV 中显示。

report  z_dynamic_table_02.


data gr_alv type ref to cl_salv_table.

data struct_descr type ref to cl_abap_datadescr.
data table_descr type ref to cl_abap_tabledescr.

parameters tab_name type dd02l-tabname.

start-of-selection.

  struct_descr ?= cl_abap_structdescr=>describe_by_name( tab_name ).
  table_descr ?= cl_abap_tabledescr=>create( p_line_type = struct_descr ).

  data table_dref type ref to data.
  create data table_dref type handle table_descr.

  field-symbols <table> type any table.
  assign table_dref->* to <table>.

  select * from (tab_name) up to 10 rows into corresponding fields of table <table>.

  try.
      call method cl_salv_table=>factory
        importing
          r_salv_table = gr_alv
        changing
          t_table      = <table>.
    catch cx_salv_msg .
  endtry.

  gr_alv->display( ).

构建动态程序所需的字段

第一个例子主要是演示动态程序的基本要素,一般情况下,我们不需要获取一个数据表的所有字段,这样就需要创建需要的字段。下面的示例演示了创建字段的方法。示例仍然从 sflights 中获取数据,然后在 ALV 中显示。只需要 CARRID, CONNID, CARRNAME 和 FLDATE 四个字段。

report  z_dynamic_table_03.

data gr_alv type ref to cl_salv_table.

data gs_component  type cl_abap_structdescr=>component.
data gt_component  type cl_abap_structdescr=>component_table.

data struct_descr  type ref to cl_abap_datadescr.
data table_descr   type ref to cl_abap_tabledescr.

data carrid type sflights-carrid.
data connid type sflights-connid.
data carrname type sflights-carrname.
data fldate type sflights-fldate.

try.
    gs_component-name = 'CARRID'.
    gs_component-type ?= cl_abap_datadescr=>describe_by_data( carrid ).
    append gs_component to gt_component.

    gs_component-name = 'CONNID'.
    gs_component-type ?= cl_abap_datadescr=>describe_by_data( connid ).
    append gs_component to gt_component.

    gs_component-name = 'CARRNAME'.
    gs_component-type ?= cl_abap_datadescr=>describe_by_data( carrname ).
    append gs_component to gt_component.

    gs_component-name = 'FLDATE'.
    gs_component-type ?= cl_abap_datadescr=>describe_by_data( fldate ).
    append gs_component to gt_component.

    struct_descr ?= cl_abap_structdescr=>create( p_components = gt_component ).
    table_descr ?= cl_abap_tabledescr=>create( p_line_type = struct_descr ).

    data table_dref type ref to data.
    create data table_dref type handle table_descr.

    field-symbols <table> type any table.
    assign table_dref->* to <table>.

    " Select data from database and fill dynamically created table
    select * from sflights up to 10 rows into corresponding fields of table <table>.

    try.
        call method cl_salv_table=>factory
          importing
            r_salv_table = gr_alv
          changing
            t_table      = <table>.
      catch cx_salv_msg .
    endtry.

    gr_alv->display( ).

  catch cx_root.
endtry.

动态程序实现行转列

最后给出一个稍微综合一点的示例,对于给定的数据:

实现行转列,并在 ALV 中显示:


完整代码:

report  z_dynamic_table_rtts.

type-pools: slis .

types:
  begin of gfirst_typ,
    vend(6) type c,
    month(5) type c,
    amt type i,
  end of gfirst_typ .

* RTTS declarations
data struct_descr type ref to cl_abap_datadescr.
data table_descr type ref to cl_abap_tabledescr.
data gs_component type cl_abap_structdescr=>component.
data gt_component type cl_abap_structdescr=>component_table.

* Dynamice table declarations
data table_dref type ref to data.
data line_dref type ref to data.

* Field symbol decalrations
field-symbols: <gfs_line>, <gfs_line1>.
field-symbols: <gfs_table> type standard table, <fld>.

data it_zdemo type standard table of gfirst_typ.
data wa_zdemo like line of it_zdemo.

* SALV declarionts.
data lo_cols type ref to cl_salv_columns.
data lo_salv_table type ref to cl_salv_table.
data lo_column type ref to cl_salv_column.
data col_name(30) type c.
data col_desc(20) type c.

start-of-selection.

* Populate the initial input table.
* Usually this input table contents will be popluated at run time,
* which raises the requirement of dynamic table.
* The talbe contens are filled here for illustration purpose.

  perform fill_table using:
        'V100' 'JAN' '100',
        'V100' 'FEB' '250',
        'V200' 'FEB' '200',
        'V300' 'FEB' '150',
        'V200' 'MAR' '250',
        'V300' 'MAR' '300',
        'V100' 'APR' '200',
        'V100' 'MAY' '100',
        'V200' 'MAY' '50',
        'V300' 'MAY' '125',
        'V400' 'MAY' '475'.

* Write the data
  write : / 'Initial internal table'.
  write : /(6) 'Vendor', (12) 'Month', (3) 'Amt'.
  loop at it_zdemo into wa_zdemo.
    write : / wa_zdemo-vend, wa_zdemo-month, wa_zdemo-amt.
    clear wa_zdemo.
  endloop.

* Create structure of dyanmic internal table.
  gs_component-name = 'VEND'.
  gs_component-type ?= cl_abap_datadescr=>describe_by_data( wa_zdemo-vend ).
  append gs_component to gt_component .

* Loop throught the internal table creating a column for every distinct month
  loop at it_zdemo into wa_zdemo.
* Search the component table if the month column already exists.
    read table gt_component into gs_component with key name = wa_zdemo-month.
    if sy-subrc ne 0.
* The name of the column would be the month
* and the data type would be the same as the amount filed of intenal tale
      gs_component-name = wa_zdemo-month.
      gs_component-type ?= cl_abap_datadescr=>describe_by_data( wa_zdemo-amt ).
      append gs_component to gt_component.
    endif.
    clear: gs_component, wa_zdemo.
  endloop.

  struct_descr ?= cl_abap_structdescr=>create( p_components = gt_component ).
  table_descr ?= cl_abap_tabledescr=>create( p_line_type = struct_descr ).

  create data table_dref type handle table_descr.
  create data line_dref type handle struct_descr.

  assign table_dref->* to <gfs_table>.
  assign line_dref->* to <gfs_line>.

* Fill vendor field
  loop at it_zdemo into wa_zdemo.
    read table <gfs_table> into <gfs_line> with key ('VEND') = wa_zdemo-vend.
    if sy-subrc ne 0.
      assign component 'VEND' of structure <gfs_line> to <fld>.
      <fld> = wa_zdemo-vend.
      append <fld> to <gfs_table>.
    endif.

    clear wa_zdemo.
  endloop.

* Aggregate data.
  loop at it_zdemo into wa_zdemo.
    read table <gfs_table> assigning <gfs_line> with key ('VEND') = wa_zdemo-vend.
    loop at gt_component into gs_component.
      if gs_component-name = wa_zdemo-month.
        if <fld> is assigned.
          unassign <fld>.
        endif.
        assign component gs_component-name of structure <gfs_line> to <fld>.
        <fld> = <fld> + wa_zdemo-amt.
      endif.
    endloop.

    clear wa_zdemo.
  endloop.

* ALV show
  try.
      cl_salv_table=>factory(
        importing
          r_salv_table = lo_salv_table
        changing
          t_table = <gfs_table>
      ).

    catch cx_salv_msg.
  endtry.

* Get columns object
  lo_cols = lo_salv_table->get_columns( ).

* Individual column names
  loop at gt_component into gs_component.
    try.
        col_name = gs_component-name.
        lo_column = lo_cols->get_column( col_name ).
        if col_name = 'VEND'.
          col_desc = 'Vendor'.
        else.
          concatenate col_name  '''13' into col_desc.
        endif.

        lo_column->set_medium_text( col_desc ).
        lo_column->set_output_length( 10 ).
      catch  cx_salv_not_found.
    endtry.
  endloop.

* Display table
  lo_salv_table->display( ).


*&---------------------------------------------------------------------*
*&      Form  fill_table
*&---------------------------------------------------------------------*
form fill_table using p_fld1 type gfirst_typ-vend
                      p_fld2 type gfirst_typ-month
                      p_fld3 type gfirst_typ-amt.

  clear wa_zdemo.
  wa_zdemo-vend = p_fld1.
  wa_zdemo-month = p_fld2.
  wa_zdemo-amt = p_fld3.

  append wa_zdemo to it_zdemo.

endform.                    "fill_table

http://www.kler.cn/a/565688.html

相关文章:

  • 快速列出MS Word中所有可用字体
  • PySpark中mapPartitionsWithIndex等map类算子生成器函数问题 - return\yield
  • SocketTool、串口调试助手、MQTT中间件基础
  • springBoot统一响应类型3.0版本
  • vue的双向绑定是怎么实现的
  • 【云原生之kubernetes实战】在k8s环境中高效部署Vikunja任务管理工具(含数据库配置)
  • 【Mybatis】如何简单使用mybatis-plus,以及MybatisGenerator自动生成或者实现SQL语句
  • 嵌入式迷雾:现状谜团待解,未来行情走向何方?
  • 微信小程序读取写入NFC文本,以及NFC直接启动小程序指定页面
  • 优博讯25届春招内推
  • 武汉大学生命科学学院与谱度众合(武汉)生命科技有限公司举行校企联培座谈会
  • MQTT应用环路验证
  • Godot4.3 显示像素风格图片模糊如何设置?
  • Debian安装C语言环境
  • 自主可控:国产CAE一体化平台如何筑基新能源车未来
  • leetcode 75.颜色分类(详解)数组分块c++
  • 【Spring】AOP
  • Ubuntu 下 nginx-1.24.0 源码分析 - ngx_conf_t
  • [深度学习] 大模型学习2-提示词工程指北
  • 【落羽的落羽 C++】C++入门基础·其之一