因为用户不用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.
效果展示:
配置数据:


