用配置表给WEB DYNPRO做配置报表(限十个查询条件)

因为用户不用GUI客户端,不能用SQVI和query,有时候需要查询某些关联表的时候就有点麻烦。

所以就想着做一个可以配置的报表,把查询字段和结果字段已经关联条件全部配置起来,这样用户要是突发奇想要查点东西,只要简单配置下就可以了。

1,新建配置表:可根据用户配置对应的组件(用户,组件,组件描述,查询from表和关联关系配置)

2,组件配置表:根据组件,查询/结果条件,字段,字段类型,描述,表字段,查询的表,位置(可以根据S/R区分查询条件和结果字段,根据字段类型动态创建查询和结果结构和表,根据表字段,动态构建查询结果字段)

两个配置表可以动态分配程序到用户,动态构建查询和结果,动态展示

3,新建WEB DYNPRO程序:ZCRM_DYNAMIC_REPORT

组件里添加ALV和SELECTION的组件

4,组件控制器Component Controller中做动态ALV初始化(也可以在用户选择下拉报表的时候初始化)

复制代码
METHOD wddoinit .
  DATA lo_cmp_usage TYPE REF TO if_wd_component_usage.
  lo_cmp_usage =   wd_this->wd_cpuse_dynmaic_alv( ).
  IF lo_cmp_usage->has_active_component( ) IS INITIAL.
    lo_cmp_usage->create_component( ).
  ENDIF.
ENDMETHOD.

3,1 在MAIN视图中,我们新建一个node节点,做拉下用,下拉列表里展示当前登录用户可以选择的报表

参照上面的配置表1就可以了

2添加一个查询 ViewContainerUIElement (SELECT)

3添加一个结果展示的 ViewContainerUIElement (ALV)

4,init中初始化拉下程序列表(init_drop 根据用户取配置表报表)

复制代码
METHOD wddoinit .
  init_drop( ).
  init_select( ).
ENDMETHOD.
复制代码
METHOD init_drop .
  DATA: lt_value_set TYPE TABLE OF wdy_key_value,
        ls_value_set TYPE wdy_key_value.
  DATA:lr_node_info TYPE REF TO if_wd_context_node_info.

  lr_node_info = wd_context->get_node_info( ).
  lr_node_info = lr_node_info->get_child_node( `ZCRMT0209` ).

  SELECT component_name AS key text AS value INTO TABLE lt_value_set FROM zcrmt0209 WHERE uname = sy-uname.

  lr_node_info->set_attribute_value_set(
          name = `COMPONENT_NAME`
          value_set = lt_value_set ).
ENDMETHOD.
复制代码
METHOD init_select .
**初始化select option组件
  DATA:
    lr_componentcontroller TYPE REF TO ig_componentcontroller,
    l_ref_cmp_usage        TYPE REF TO if_wd_component_usage.
  DATA:
    display_btn_cancel  TYPE abap_bool,
    display_btn_check   TYPE abap_bool,
    display_btn_reset   TYPE abap_bool,
    display_btn_execute TYPE abap_bool.


* create the used component
  l_ref_cmp_usage = wd_this->wd_cpuse_selection( ).
  IF l_ref_cmp_usage->has_active_component( ) IS INITIAL.
    l_ref_cmp_usage->create_component( ).
  ENDIF.


* get a pointer to the interface controller of the select options
*component
  wd_this->m_wd_select_options = wd_this->wd_cpifc_selection( ).

* init the select screen
  wd_this->m_handler =
  wd_this->m_wd_select_options->init_selection_screen( ).

* adjust the global options
  wd_this->m_handler->set_global_options(
      i_display_btn_cancel  = display_btn_cancel
      i_display_btn_check   = display_btn_check
      i_display_btn_reset   = display_btn_reset
      i_display_btn_execute = display_btn_execute ).


ENDMETHOD.

5,根据下拉列表初始化选择条件和alv

复制代码
METHOD onactionselect_comp .
  DATA lo_nd_zcrmt0209 TYPE REF TO if_wd_context_node.
  DATA lo_el_zcrmt0209 TYPE REF TO if_wd_context_element.
  DATA ls_zcrmt0209 TYPE wd_this->element_zcrmt0209.

*   navigate from <CONTEXT> to <ZCRMT0209> via lead selection
  lo_nd_zcrmt0209 = wd_context->get_child_node( name = wd_this->wdctx_zcrmt0209 ).
*   get element via lead selection
  lo_el_zcrmt0209 = lo_nd_zcrmt0209->get_element( ).
*   get all declared attributes
  lo_el_zcrmt0209->get_static_attributes(
    IMPORTING
      static_attributes = ls_zcrmt0209 ).

  CHECK ls_zcrmt0209-component_name IS NOT INITIAL.
**初始化select和alv
  add_select( ls_zcrmt0209-component_name ).
  init_alv( ls_zcrmt0209-component_name ).

**控制查询清空按钮显示
  DATA lo_el_context TYPE REF TO if_wd_context_element.
  DATA ls_context TYPE wd_this->element_context.
  DATA lv_bt_vis TYPE wd_this->element_context-bt_vis.
*   get element via lead selection
  lo_el_context = wd_context->get_element( ).
*   @TODO fill attribute
  lv_bt_vis = 'X'.
*   set single attribute
  lo_el_context->set_attribute(
    name =  `BT_VIS`
    value = lv_bt_vis ).
ENDMETHOD.
复制代码
METHOD add_select .
  DATA:gt_zcrmt0209s TYPE TABLE OF zcrmt0209s,
       gw_zcrmt0209s LIKE LINE OF gt_zcrmt0209s.
  DATA:
    lt_range_table TYPE REF TO data,
    rt_range_table TYPE REF TO data,
    read_only      TYPE abap_bool,
    typename       TYPE string,
    id             TYPE string,
    desc           TYPE string.

  wd_this->m_handler->remove_all_sel_screen_items( ).
**根据选择的组件从配置表中带出查询条件并添加到select option中
  SELECT * INTO TABLE gt_zcrmt0209s FROM zcrmt0209s WHERE component_name = component_name AND zusage = 'S'.

  CHECK gt_zcrmt0209s[] IS NOT INITIAL.


  LOOP AT gt_zcrmt0209s INTO gw_zcrmt0209s.
    typename = gw_zcrmt0209s-field_type.
    id = gw_zcrmt0209s-field.
    desc = gw_zcrmt0209s-text.
* create a range table that consists of this new data element
    lt_range_table = wd_this->m_handler->create_range_table( i_typename = typename ).
* add a new field to the selection
    wd_this->m_handler->add_selection_field(
                            i_id = id
                            i_description = desc
                            it_result = lt_range_table
                            i_read_only = read_only ).
  ENDLOOP.
ENDMETHOD.

根据配置表初始化alv字段结构并绑定到alv

复制代码
METHOD init_alv .
  DATA:lt_child_node TYPE wdr_context_child_info_map,
       ls_child_node TYPE wdr_context_child_info.
  DATA:lv_name TYPE string.
  DATA:gt_zcrmt0209s TYPE TABLE OF zcrmt0209s,
       gw_zcrmt0209s LIKE LINE OF gt_zcrmt0209s.
  DATA: ls_comp     TYPE LINE OF cl_abap_structdescr=>component_table,
        lt_comp     TYPE cl_abap_structdescr=>component_table,
        ls_fieldcat TYPE LINE OF lvc_t_fcat,
        struct_type TYPE REF TO cl_abap_structdescr.


  lt_child_node = wd_context->get_node_info( )->get_child_nodes( ).
**取配置表的结果R字段,构建动态的节点,节点名就用报表名
  SELECT * INTO TABLE gt_zcrmt0209s FROM zcrmt0209s WHERE component_name = component_name AND zusage = 'R'.


  LOOP AT gt_zcrmt0209s INTO gw_zcrmt0209s.
    ls_comp-name = gw_zcrmt0209s-field.
    ls_comp-type ?= cl_abap_typedescr=>describe_by_name( gw_zcrmt0209s-field_type ).
    APPEND ls_comp TO lt_comp.
  ENDLOOP.

* Create structure defined in lt_comp
  struct_type = cl_abap_structdescr=>create( lt_comp ).
  lv_name = component_name.

  READ TABLE lt_child_node INTO ls_child_node WITH KEY name = lv_name.
  IF sy-subrc = 0.
  ELSE.
* Append dynamic node with name (  )
    wd_context->get_node_info( )->add_new_child_node(
                            name                = lv_name
                            is_mandatory        = abap_true
                            is_multiple         = abap_true
                            static_element_rtti = struct_type
                            is_static           = abap_false ).

  ENDIF.

**Step 4: Assign this context to ALV
  DATA lo_interfacecontroller TYPE REF TO iwci_salv_wd_table .
  lo_interfacecontroller =   wd_this->wd_cpifc_dynmaic_alv( ).

  lo_interfacecontroller->set_data(
*   only_if_new_descr =                 " wdy_boolean
  r_node_data = wd_context->get_child_node( lv_name )   " ref to if_wd_context_node
  ).
**以下是根据配置表控制alv显示的,暂时用默认也可以,先不用
*  DATA:gt_zcrmt0209s TYPE TABLE OF zcrmt0209s,
*       gw_zcrmt0209s LIKE LINE OF gt_zcrmt0209s.
*  DATA: lr_comp_alv    TYPE REF TO if_wd_component_usage,
*        lr_comp_if_alv TYPE REF TO iwci_salv_wd_table.
*  DATA: lr_column_settings TYPE REF TO if_salv_wd_column_settings,
*        lr_column          TYPE REF TO cl_salv_wd_column,
*        lr_column_header   TYPE REF TO cl_salv_wd_column_header.
*  DATA:gv_string TYPE string.
*
*  DATA: lt_column TYPE salv_wd_t_column_ref,
*        ls_column TYPE salv_wd_s_column_ref.
*
*****"定义特殊格式的类型
*  DATA: lr_input_field TYPE REF TO cl_salv_wd_uie_input_field,
*        lr_checkbox    TYPE REF TO cl_salv_wd_uie_checkbox,
*        lr_link        TYPE REF TO cl_salv_wd_uie_link_to_action,
*        lr_drop        TYPE REF TO cl_salv_wd_uie_dropdown_by_key.
*  DATA lr_column_id TYPE string.
*
*
*  CHECK gt_zcrmt0209s[] IS NOT INITIAL.
*
*
*
*
*  "创建组件/实例化组件
*  lr_comp_alv = wd_this->wd_cpuse_dynmaic_alv( ) .
*  IF lr_comp_alv->has_active_component( ) IS INITIAL.
*    lr_comp_alv->create_component( ).
*  ENDIF.
*
*
*  DATA lr_config TYPE REF TO cl_salv_wd_config_table.
*  DATA:lr_func_config TYPE REF TO cl_salv_wd_config_table.
*  "获取ALV对象的设置对象
*  lr_comp_if_alv = wd_this->wd_cpifc_dynmaic_alv( ).
*  lr_config      = lr_comp_if_alv->get_model( ).
*  lr_func_config      = lr_comp_if_alv->get_model( ).
*
*  lr_column_settings ?= lr_config .
*  lt_column = lr_column_settings->get_columns( )."获取ALV字段
*  "取配置表数据
*
**=========================================================
*
*  DATA: l_value  TYPE REF TO cl_salv_wd_config_table.
*
*  l_value = lr_comp_if_alv->get_model( ).
*  l_value->if_salv_wd_table_settings~set_fixed_table_layout( abap_false ).  "使列宽不可自动调节
*  l_value->if_salv_wd_table_settings~set_width( '100%'  ) .                "设置宽度
*  l_value->if_salv_wd_table_settings~set_visible_row_count( '15' ).        "显示的行数
*  l_value->if_salv_wd_table_settings~set_scrollable_col_count( '10' )."设置滚动条行数
*  l_value->if_salv_wd_table_settings~set_read_only( abap_false )."设置只读
*  l_value->if_salv_wd_table_settings~set_display_empty_rows( abap_false )."设置空表也显示alv行
*  l_value->if_salv_wd_table_settings~set_selection_mode( cl_wd_table=>e_selection_mode-multi_no_lead )."多选无lead
*  l_value->if_salv_wd_function_settings~set_enabled( abap_true ) ."功能
*  l_value->if_salv_wd_std_functions~set_edit_check_available( abap_false ) .
*  l_value->if_salv_wd_std_functions~set_edit_insert_row_allowed( abap_false ) .
*  l_value->if_salv_wd_std_functions~set_export_allowed( abap_true ) ."可excel导出
**  l_value->if_salv_wd_std_functions~set_view_list_allowed( abap_false ).
*  l_value->if_salv_wd_std_functions~set_pdf_allowed( abap_false ) ."可pdf导出
*  l_value->if_salv_wd_std_functions~set_edit_append_row_allowed( abap_false ) .
*  l_value->if_salv_wd_std_functions~set_edit_delete_row_allowed( abap_false ) .
*  l_value->if_salv_wd_std_functions~set_filter_filterline_allowed( abap_true ).
*  l_value->if_salv_wd_std_functions~set_filter_complex_allowed( abap_true )."多字段筛选
**  l_value->if_salv_wd_std_functions~set_dialog_settings_allowed( abap_true ).
*
*  DATA: lr_table_settings TYPE REF TO if_salv_wd_table_settings.
*  lr_table_settings ?= l_value.
*  lr_table_settings->set_data_check( '01' ).
*  lr_table_settings->set_read_only( abap_false ).
*
*  LOOP AT lt_column INTO ls_column.
*    lr_column_id = ls_column-id.
*    lr_column = ls_column-r_column.
*
*    lr_column->set_resizable( value = 'X' ).
*    lr_column->set_width( value = '100' ).
*
*    READ TABLE gt_zcrmt0209s INTO gw_zcrmt0209s WITH KEY field = ls_column-id.
*    IF sy-subrc = 0.
**      IF gw_zcrmt0209s-visiable = 'X'.
*      lr_column_header = ls_column-r_column->create_header( ).
**        ls_column-r_column->set_position( gw_ZCRMT0209S-posit ).
*      CASE gw_zcrmt0209s-field.
*        WHEN 'SEL'.
*          CREATE OBJECT lr_checkbox
*            EXPORTING
*              checked_fieldname = ls_column-id.
*          ls_column-r_column->set_cell_editor( lr_checkbox ).
*        WHEN 'ZZCON_TYPE'.
*          CREATE OBJECT lr_drop
*            EXPORTING
*              selected_key_fieldname = ls_column-id.
*
*          lr_drop->set_read_only_fieldname( value = ls_column-id ).
*
*          ls_column-r_column->set_cell_editor( lr_drop ).
*        WHEN 'CTYPE'.
*          CREATE OBJECT lr_drop
*            EXPORTING
*              selected_key_fieldname = ls_column-id.
**            lr_drop->set_read_only_fieldname( value = ls_column-id ).
*          ls_column-r_column->set_cell_editor( lr_drop ).
*        WHEN 'OBJECT_ID'.
*          CREATE OBJECT lr_link.
*          lr_link->set_text_fieldname( ls_column-id ).
*          ls_column-r_column->set_cell_editor( lr_link ).
*        WHEN 'E'.
*        WHEN 'F'.
*        WHEN OTHERS.
*      ENDCASE.
*      IF gw_zcrmt0209s-text CS 'CRM/'."otr text使用特定格式的
*        gv_string = gw_zcrmt0209s-text.
*        lr_column_header->set_text( zcl_otr=>get_text( gv_string ) ).
*      ELSE.
*        IF gw_zcrmt0209s-text IS NOT INITIAL.
*          gv_string = gw_zcrmt0209s-text.
*          lr_column_header->set_text( gv_string ).
*        ENDIF.
*      ENDIF.
**      ELSE.
**        ls_column-r_column->set_position( gw_zcrmt0209s-posit ).
**        lr_column = lr_column_settings->get_column( ls_column-id ).
**        lr_column->set_visible( if_wdl_core=>visibility_none ).
**      ENDIF.
*    ELSE.
**      ls_column-r_column->set_position( gw_zcrmt0209s-posit ).
*      lr_column = lr_column_settings->get_column( ls_column-id ).
*      lr_column->set_visible( if_wdl_core=>visibility_none ).
*    ENDIF.
*  ENDLOOP.

ENDMETHOD.

6,查询处理,动态构建内表并展示

复制代码
METHOD onactionsearch .
  DATA:gt_zcrmt0209s TYPE TABLE OF zcrmt0209s,
       gw_zcrmt0209s LIKE LINE OF gt_zcrmt0209s,
       gw_zcrmt0209  TYPE zcrmt0209.
  DATA lo_nd_zcrmt0209 TYPE REF TO if_wd_context_node.
  DATA lo_el_zcrmt0209 TYPE REF TO if_wd_context_element.
  DATA ls_zcrmt0209 TYPE wd_this->element_zcrmt0209.
  DATA: rt_object_id TYPE REF TO data,
        lt_where     TYPE rsds_where_tab,
        lt_from      TYPE rsds_where_tab,
        lt_sql       TYPE rsds_where_tab,
        lv_s         TYPE string,
        lv_n         TYPE n LENGTH 2,
        lv_line(70)  TYPE c.
  DATA: dy_table TYPE REF TO data,
        ifc      TYPE        lvc_t_fcat.
  FIELD-SYMBOLS:
    <fs01> TYPE table,
    <fs02> TYPE table,
    <fs03> TYPE table,
    <fs04> TYPE table,
    <fs05> TYPE table,
    <fs06> TYPE table,
    <fs07> TYPE table,
    <fs08> TYPE table,
    <fs09> TYPE table,
    <fs10> TYPE table.
  FIELD-SYMBOLS : <table> TYPE ANY TABLE.
  DATA:lr_node TYPE REF TO if_wd_context_node.

*   navigate from <CONTEXT> to <ZCRMT0209> via lead selection
  lo_nd_zcrmt0209 = wd_context->get_child_node( name = wd_this->wdctx_zcrmt0209 ).
*   get element via lead selection
  lo_el_zcrmt0209 = lo_nd_zcrmt0209->get_element( ).
*   get all declared attributes
  lo_el_zcrmt0209->get_static_attributes(
    IMPORTING
      static_attributes = ls_zcrmt0209 ).
  "根据配置表查询条件获得查询参数,限制10个条件
  SELECT * INTO TABLE gt_zcrmt0209s FROM zcrmt0209s WHERE component_name = ls_zcrmt0209-component_name AND zusage = 'S'.
  LOOP AT gt_zcrmt0209s INTO gw_zcrmt0209s.
    CLEAR:lv_line,lv_s.
    lv_n = sy-tabix.
    lv_s = gw_zcrmt0209s-field.
    rt_object_id = wd_this->m_handler->get_range_table_of_sel_field( i_id = lv_s ).
    CASE lv_n.
      WHEN '01'.
        ASSIGN rt_object_id->* TO <fs01>.
        IF <fs01>[] IS INITIAL.
          CONTINUE.
        ENDIF.
      WHEN '02'.
        ASSIGN rt_object_id->* TO <fs02>.
        IF <fs02>[] IS INITIAL.
          CONTINUE.
        ENDIF.
      WHEN '03'.
        ASSIGN rt_object_id->* TO <fs03>.
        IF <fs03>[] IS INITIAL.
          CONTINUE.
        ENDIF.
      WHEN '04'.
        ASSIGN rt_object_id->* TO <fs04>.
        IF <fs04>[] IS INITIAL.
          CONTINUE.
        ENDIF.
      WHEN '05'.
        ASSIGN rt_object_id->* TO <fs05>.
        IF <fs05>[] IS INITIAL.
          CONTINUE.
        ENDIF.
      WHEN '06'.
        ASSIGN rt_object_id->* TO <fs06>.
        IF <fs06>[] IS INITIAL.
          CONTINUE.
        ENDIF.
      WHEN '07'.
        ASSIGN rt_object_id->* TO <fs07>.
        IF <fs07>[] IS INITIAL.
          CONTINUE.
        ENDIF.
      WHEN '08'.
        ASSIGN rt_object_id->* TO <fs08>.
        IF <fs08>[] IS INITIAL.
          CONTINUE.
        ENDIF.
      WHEN '09'.
        ASSIGN rt_object_id->* TO <fs09>.
        IF <fs09>[] IS INITIAL.
          CONTINUE.
        ENDIF.
      WHEN '10'.
        ASSIGN rt_object_id->* TO <fs10>.
        IF <fs10>[] IS INITIAL.
          CONTINUE.
        ENDIF.
      WHEN OTHERS.
    ENDCASE.
    "动态查询条件,第二次拼接需要添加and
    CONCATENATE '<fs' lv_n '>' INTO lv_line.
    IF lt_where[] IS INITIAL.
      CONCATENATE gw_zcrmt0209s-name_on_db 'IN' lv_line INTO lv_line SEPARATED BY space.
    ELSE.
      CONCATENATE 'AND' gw_zcrmt0209s-name_on_db 'IN' lv_line INTO lv_line SEPARATED BY space.
    ENDIF.

    APPEND lv_line TO lt_where.

  ENDLOOP.

  CHECK lt_where[] IS NOT INITIAL.
  DATA:lv_name TYPE string.



  SELECT name_on_db INTO TABLE lt_sql FROM zcrmt0209s WHERE component_name = ls_zcrmt0209-component_name AND zusage = 'R'.


  "根据配置字段属性,构建动态内表
  SELECT dd03l~fieldname dd03l~inttype dd03l~leng AS intlen dd03l~decimals INTO CORRESPONDING FIELDS OF TABLE ifc FROM dd03l INNER JOIN zcrmt0209s
    ON zcrmt0209s~field = dd03l~fieldname AND zcrmt0209s~dbtabname = dd03l~tabname
    WHERE zcrmt0209s~component_name = ls_zcrmt0209-component_name AND zusage = 'R'.

  CALL METHOD cl_alv_table_create=>create_dynamic_table
    EXPORTING
      it_fieldcatalog = ifc
    IMPORTING
      ep_table        = dy_table.
  ASSIGN dy_table->* TO <table>.
**另一种动态构建内表的方法
*  DATA: ls_comp     TYPE LINE OF cl_abap_structdescr=>component_table,
*        lt_comp     TYPE cl_abap_structdescr=>component_table,
*        ls_fieldcat TYPE LINE OF lvc_t_fcat,
*        struct_type TYPE REF TO cl_abap_structdescr.
*  SELECT * INTO TABLE gt_zcrmt0209s FROM zcrmt0209s WHERE component_name = ls_zcrmt0209-component_name AND zusage = 'R'.
*  LOOP AT gt_zcrmt0209s INTO gw_zcrmt0209s.
*    ls_comp-name = gw_zcrmt0209s-field.
*    ls_comp-type ?= cl_abap_typedescr=>describe_by_name( gw_zcrmt0209s-field_type ).
*    APPEND ls_comp TO lt_comp.
*  ENDLOOP.
*
** Create structure defined in lt_comp
*  struct_type = cl_abap_structdescr=>create( lt_comp ).
*  DATA p_result     TYPE REF TO cl_abap_tabledescr.
*
*  p_result = cl_abap_tabledescr=>create(
*      p_line_type  = CAST #( struct_type )
*       p_table_kind = cl_abap_tabledescr=>tablekind_std ).
*  DATA: table TYPE REF TO data.
*  CREATE DATA table TYPE HANDLE p_result.
*  ASSIGN table->* TO <table>.


  "查询表连接处理
  SELECT SINGLE * INTO gw_zcrmt0209 FROM zcrmt0209 WHERE uname = sy-uname AND component_name = ls_zcrmt0209-component_name.

  CHECK gw_zcrmt0209-fromcond IS NOT INITIAL.
  SPLIT gw_zcrmt0209-fromcond AT '/' INTO TABLE lt_from.

  "动态查询
  SELECT (lt_sql)
    INTO CORRESPONDING FIELDS OF TABLE <table>
    FROM (lt_from)
    WHERE (lt_where).


  lv_name = ls_zcrmt0209-component_name.

  "绑定结果到node显示
  lr_node = wd_context->get_child_node( name = lv_name ).

  lr_node->bind_table( new_items = <table> set_initial_elements = abap_true ).



ENDMETHOD.

效果展示:

配置数据: