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

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

相关文章:

  • ES6笔记总结
  • Vue的data配置项
  • springboot之HTML与图片生成
  • IP属地是通过卫星定位的吗?如何保护用户隐私
  • mysql-analyze table导致waiting for table flush
  • 【AI+智造】在阿里云Ubuntu 24.04上部署DeepSeek R1 14B的完整方案
  • Redis---缓存穿透,雪崩,击穿
  • GNN入门与实践——基于GraphSAGE在Cora数据集上的节点分类研究
  • 思维训练(算法+技巧)
  • 大白话TypeScript第八章TypeScript 项目的部署与监控
  • Kafka零拷贝
  • springcloud组件调用顺序
  • 游戏引擎学习第128天
  • 1-3压缩命令
  • 内存中的缓存区
  • 数据结构:二叉搜索树(排序树)
  • 介绍一款飞算JavaAI编程工具,集成到idea,图文并茂
  • AcWing 5933:爬楼梯 ← 递归 / 递推 / 高精度
  • Vue 安装 wangEditor 富文本编辑器
  • 【Redis】Mac系统一键安装redis
  • 青岛网站推广引流/网络推广运营是做什么
  • 嘉兴模板建站代理/品牌广告
  • 夫妻做网站/英文网站建设
  • 优秀的网站举例/国际新闻头条
  • wordpress主题博客主题/seo关键词优化公司
  • wordpress font google/seo的工作内容