class ZCL_BC_TABLE_INTROSPECTOR definition public final create private . public section. *"* public components of class ZCL_BC_TABLE_INTROSPECTOR *"* do not include other source files here!!! types: ty_delimiter type c length 1 . type-pools ABAP . class-methods FACTORY_USING_SQL importing value(IM_DBTAB) type CSEQUENCE value(IM_COLUMNS) type CSEQUENCE optional value(IM_WHERE_CLAUSE) type CSEQUENCE optional value(IM_MAX_ROWS) type I optional value(IM_DELIMITER) type TY_DELIMITER default ',' value(IM_USE_HEADER_RECORD) type ABAP_BOOL default ABAP_TRUE value(IM_USE_COLUMN_ALIGNMENT) type ABAP_BOOL default ABAP_TRUE value(IM_POINT_HEADER_TO_DDIC) type ABAP_BOOL default ABAP_TRUE value(IM_ENCLOSE_STRINGS) type ABAP_BOOL default ABAP_FALSE value(IM_FORMAT_TIME) type ABAP_BOOL default ABAP_TRUE value(IM_FORMAT_DATE) type ABAP_BOOL default ABAP_TRUE exporting !EX_TABLE_INTROSPECTOR type ref to ZCL_BC_TABLE_INTROSPECTOR raising ZCX_BC_TABLE_INTROSPECTOR . class-methods FACTORY_USING_TABLE importing value(IM_TABLE) type ANY TABLE value(IM_COLUMNS) type CSEQUENCE optional value(IM_DELIMITER) type TY_DELIMITER default ',' value(IM_USE_HEADER_RECORD) type ABAP_BOOL default ABAP_TRUE value(IM_USE_COLUMN_ALIGNMENT) type ABAP_BOOL default ABAP_TRUE value(IM_POINT_HEADER_TO_DDIC) type ABAP_BOOL default ABAP_TRUE value(IM_ENCLOSE_STRINGS) type ABAP_BOOL default ABAP_FALSE value(IM_FORMAT_TIME) type ABAP_BOOL default ABAP_TRUE value(IM_FORMAT_DATE) type ABAP_BOOL default ABAP_TRUE exporting !EX_TABLE_INTROSPECTOR type ref to ZCL_BC_TABLE_INTROSPECTOR raising ZCX_BC_TABLE_INTROSPECTOR . methods GET_ALV_RENDITION exporting !EX_SALV_TABLE type ref to CL_SALV_TABLE raising ZCX_BC_TABLE_INTROSPECTOR . methods GET_SOLI_RENDITION importing !IM_TRUNCATE_LINES type ABAP_BOOL default ABAP_TRUE exporting !EX_SOLI type SOLI_TAB raising ZCX_BC_TABLE_INTROSPECTOR . methods GET_SOLIX_RENDITION exporting !EX_SOLIX type SOLIX_TAB raising ZCX_BC_TABLE_INTROSPECTOR . methods GET_FILE_RENDITION exporting !EX_OUTPUT_TABLE type STRING_TABLE raising ZCX_BC_TABLE_INTROSPECTOR . protected section. *"* protected components of class ZCL_BC_TABLE_INTROSPECTOR *"* do not include other source files here!!! private section. *"* private components of class ZCL_BC_TABLE_INTROSPECTOR *"* do not include other source files here!!! type-pools ABAP . data USE_HEADER_RECORD type ABAP_BOOL . data USE_COLUMN_ALIGNMENT type ABAP_BOOL . data HEADER_DATA_REF type ref to DATA . data TABLE_DATA_REF type ref to DATA . data RAW_TABLE_DATA_REF type ref to DATA . methods CONSTRUCTOR importing !IM_USE_HEADER_RECORD type ABAP_BOOL !IM_USE_COLUMN_ALIGNMENT type ABAP_BOOL !IM_HEADER_DATA_REF type ref to DATA !IM_TABLE_DATA_REF type ref to DATA !IM_RAW_TABLE_DATA_REF type ref to DATA . class-methods GET_INTERNAL_TABLE_METADATA importing value(IM_TABLE) type ANY TABLE value(IM_COLUMNS) type CSEQUENCE optional exporting !EX_STRUCT_DESCR type ref to CL_ABAP_STRUCTDESCR raising ZCX_BC_TABLE_INTROSPECTOR . class-methods GET_TABLE_METADATA importing value(IM_DBTAB) type CSEQUENCE value(IM_COLUMNS) type CSEQUENCE exporting !EX_STRUCT_DESCR type ref to CL_ABAP_STRUCTDESCR raising ZCX_BC_TABLE_INTROSPECTOR . class CL_ABAP_STRUCTDESCR definition load . class-methods RECURSIVE_FILTER_COLUMNS importing value(IM_COLUMNS) type CSEQUENCE value(IM_COMPONENTS) type CL_ABAP_STRUCTDESCR=>COMPONENT_TABLE exporting !EX_COMPONENTS type CL_ABAP_STRUCTDESCR=>COMPONENT_TABLE raising ZCX_BC_TABLE_INTROSPECTOR . class-methods POPULATE_HEADER importing value(IM_USE_COLUMN_ALIGNMENT) type ABAP_BOOL value(IM_POINT_HEADER_TO_DDIC) type ABAP_BOOL value(IM_STRUCT_DESCR) type ref to CL_ABAP_STRUCTDESCR exporting !EX_STRUCT_REF type ref to DATA raising ZCX_BC_TABLE_INTROSPECTOR . class-methods EXECUTE_SQL importing value(IM_DBTAB) type CSEQUENCE value(IM_WHERE_CLAUSE) type CSEQUENCE value(IM_MAX_ROWS) type I value(IM_STRUCT_DESCR) type ref to CL_ABAP_STRUCTDESCR exporting !EX_TABLE_REF type ref to DATA raising ZCX_BC_TABLE_INTROSPECTOR . class-methods POPULATE_TABLE importing !IM_TABLE type ANY TABLE !IM_STRUCT_DESCR type ref to CL_ABAP_STRUCTDESCR exporting !EX_TABLE_REF type ref to DATA raising ZCX_BC_TABLE_INTROSPECTOR . class-methods BUILD_FORMATTED_COMPONENTS importing value(IM_USE_COLUMN_ALIGNMENT) type ABAP_BOOL value(IM_ENCLOSE_STRINGS) type ABAP_BOOL value(IM_STRUCT_DESCR) type ref to CL_ABAP_STRUCTDESCR exporting !EX_FORMATTED_STRUCT_DESCR type ref to CL_ABAP_STRUCTDESCR !EX_FORMATTED_TABLE_DESCR type ref to CL_ABAP_STRUCTDESCR raising ZCX_BC_TABLE_INTROSPECTOR . class-methods POPULATE_FORMATTED_HEADER importing value(IM_DELIMITER) type TY_DELIMITER optional value(IM_ENCLOSE_STRINGS) type ABAP_BOOL value(IM_FORMATTED_STRUCT_DESCR) type ref to CL_ABAP_STRUCTDESCR value(IM_STRUCT_REF) type ref to DATA exporting !EX_FORMATTED_STRUCT_REF type ref to DATA raising ZCX_BC_TABLE_INTROSPECTOR . class-methods POPULATE_FORMATTED_TABLE importing value(IM_DELIMITER) type TY_DELIMITER optional value(IM_ENCLOSE_STRINGS) type ABAP_BOOL value(IM_FORMAT_TIME) type ABAP_BOOL optional value(IM_FORMAT_DATE) type ABAP_BOOL optional value(IM_FORMATTED_TABLE_DESCR) type ref to CL_ABAP_STRUCTDESCR value(IM_TABLE_REF) type ref to DATA exporting !EX_FORMATTED_TABLE_REF type ref to DATA raising ZCX_BC_TABLE_INTROSPECTOR . class-methods NORMALIZE_LINE_FORMAT importing value(IM_USE_COLUMN_ALIGNMENT) type ABAP_BOOL value(IM_DATA) type ANY exporting !EX_TABLE type STRING_TABLE raising ZCX_BC_TABLE_INTROSPECTOR . ENDCLASS. CLASS ZCL_BC_TABLE_INTROSPECTOR IMPLEMENTATION. * ---------------------------------------------------------------------------------------+ * | Static Private Method ZCL_BC_TABLE_INTROSPECTOR=>BUILD_FORMATTED_COMPONENTS * +-------------------------------------------------------------------------------------------------+ * | [--->] IM_USE_COLUMN_ALIGNMENT TYPE ABAP_BOOL * | [--->] IM_ENCLOSE_STRINGS TYPE ABAP_BOOL * | [--->] IM_STRUCT_DESCR TYPE REF TO CL_ABAP_STRUCTDESCR * | [<---] EX_FORMATTED_STRUCT_DESCR TYPE REF TO CL_ABAP_STRUCTDESCR * | [<---] EX_FORMATTED_TABLE_DESCR TYPE REF TO CL_ABAP_STRUCTDESCR * | [!CX!] ZCX_BC_TABLE_INTROSPECTOR * +-------------------------------------------------------------------------------------- method BUILD_FORMATTED_COMPONENTS. *-- object references data: lo_elem_objectdescr type ref to cl_abap_objectdescr, lo_struct_objectdescr type ref to cl_abap_objectdescr, lo_elemdescr type ref to cl_abap_elemdescr, lo_header_struct_descr type ref to cl_abap_structdescr, lo_table_struct_descr type ref to cl_abap_structdescr, lo_root_exc type ref to cx_root. *-- internal table defintion data: lt_components type cl_abap_structdescr=>component_table, lt_hdr_components_interleaved type cl_abap_structdescr=>component_table, lt_rec_components_interleaved type cl_abap_structdescr=>component_table, lt_inner_components type cl_abap_structdescr=>component_table, lt_hdr_components_temp type cl_abap_structdescr=>component_table, lt_rec_components_temp type cl_abap_structdescr=>component_table. *-- structure defintion data: ls_component type abap_componentdescr, ls_component_temp type abap_componentdescr. *-- local variables data: lv_output_length type i, lv_delimiter_name type char5, lv_counter type n length 4, lv_error_msg type string. lt_components = im_struct_descr->get_components( ). *-- loop thru all components and convert to flat, character-based, delimited collection suitable for output in flat file loop at lt_components into ls_component. try. *-- create new character-based component based on length of ddic description (for header) clear: ls_component_temp. lo_elemdescr ?= ls_component-type. if im_use_column_alignment eq abap_true. *-- account for string elements which have no defined length if lo_elemdescr->output_length eq 0. ls_component_temp-type = cl_abap_elemdescr=>get_c( p_length = 255 ). else. lv_output_length = lo_elemdescr->output_length. if im_enclose_strings eq abap_true and ( lo_elemdescr->type_kind eq cl_abap_typedescr=>typekind_char or lo_elemdescr->type_kind eq cl_abap_typedescr=>typekind_string ). add 2 to lv_output_length. endif. ls_component_temp-type = cl_abap_elemdescr=>get_c( p_length = lv_output_length ). endif. else. ls_component_temp-type = cl_abap_elemdescr=>get_c( p_length = 40 ). endif. ls_component_temp-name = ls_component-name. append ls_component_temp to lt_hdr_components_interleaved. *-- cast to cl_abap_elemdescr, retrieve output length, and create new character-based component based on this length (for record) clear: ls_component_temp. lo_elemdescr ?= ls_component-type. if lo_elemdescr->output_length eq 0. ls_component_temp-type = cl_abap_elemdescr=>get_c( p_length = 255 ). else. lv_output_length = lo_elemdescr->output_length. if im_enclose_strings eq abap_true and ( lo_elemdescr->type_kind eq cl_abap_typedescr=>typekind_char or lo_elemdescr->type_kind eq cl_abap_typedescr=>typekind_string ). add 2 to lv_output_length. endif. ls_component_temp-type = cl_abap_elemdescr=>get_c( p_length = lv_output_length ). endif. ls_component_temp-name = ls_component-name. append ls_component_temp to lt_rec_components_interleaved. *-- create dynamically named delimiter component clear: ls_component_temp. add 1 to lv_counter. concatenate 'd' lv_counter into lv_delimiter_name. ls_component_temp-type = cl_abap_elemdescr=>get_c( p_length = 1 ). ls_component_temp-name = lv_delimiter_name. append ls_component_temp to lt_hdr_components_interleaved. append ls_component_temp to lt_rec_components_interleaved. catch cx_sy_move_cast_error into lo_root_exc. lv_error_msg = lo_root_exc->get_text( ). raise exception type zcx_bc_table_introspector exporting error_text = lv_error_msg. endtry. endloop. try. lo_header_struct_descr = cl_abap_structdescr=>create( lt_hdr_components_interleaved ). lo_table_struct_descr = cl_abap_structdescr=>create( lt_rec_components_interleaved ). catch cx_sy_struct_creation cx_sy_table_creation into lo_root_exc. lv_error_msg = lo_root_exc->get_text( ). raise exception type zcx_bc_table_introspector exporting error_text = lv_error_msg. endtry. *-- return new delimited component structure ex_formatted_struct_descr = lo_header_struct_descr. ex_formatted_table_descr = lo_table_struct_descr. endmethod. * ---------------------------------------------------------------------------------------+ * | Instance Private Method ZCL_BC_TABLE_INTROSPECTOR->CONSTRUCTOR * +-------------------------------------------------------------------------------------------------+ * | [--->] IM_USE_HEADER_RECORD TYPE ABAP_BOOL * | [--->] IM_USE_COLUMN_ALIGNMENT TYPE ABAP_BOOL * | [--->] IM_HEADER_DATA_REF TYPE REF TO DATA * | [--->] IM_TABLE_DATA_REF TYPE REF TO DATA * | [--->] IM_RAW_TABLE_DATA_REF TYPE REF TO DATA * +-------------------------------------------------------------------------------------- method constructor. use_header_record = im_use_header_record. use_column_alignment = im_use_column_alignment. header_data_ref = im_header_data_ref. table_data_ref = im_table_data_ref. raw_table_data_ref = im_raw_table_data_ref. endmethod. * ---------------------------------------------------------------------------------------+ * | Static Private Method ZCL_BC_TABLE_INTROSPECTOR=>EXECUTE_SQL * +-------------------------------------------------------------------------------------------------+ * | [--->] IM_DBTAB TYPE CSEQUENCE * | [--->] IM_WHERE_CLAUSE TYPE CSEQUENCE * | [--->] IM_MAX_ROWS TYPE I * | [--->] IM_STRUCT_DESCR TYPE REF TO CL_ABAP_STRUCTDESCR * | [<---] EX_TABLE_REF TYPE REF TO DATA * | [!CX!] ZCX_BC_TABLE_INTROSPECTOR * +-------------------------------------------------------------------------------------- method execute_sql. *-- object references data: lo_table_descr type ref to cl_abap_tabledescr, lo_root_exc type ref to cx_root. *-- local variables data: lv_structdata_ref type ref to data, lv_error_msg type string, lv_error_msg_temp type string. *-- field symbols field-symbols: type standard table, type any. try. lo_table_descr = cl_abap_tabledescr=>create( im_struct_descr ). create data ex_table_ref type handle lo_table_descr. assign ex_table_ref->* to . create data lv_structdata_ref type handle im_struct_descr. assign lv_structdata_ref->* to . catch cx_sy_create_data_error into lo_root_exc. lv_error_msg = lo_root_exc->get_text( ). raise exception type zcx_bc_table_introspector exporting error_text = lv_error_msg. endtry. if im_max_rows lt 0. lv_error_msg = 'With "UP TO n ROWS", specify only positive values'. raise exception type zcx_bc_table_introspector exporting error_text = lv_error_msg. endif. try. select * from (im_dbtab) into corresponding fields of table up to im_max_rows rows where (im_where_clause). catch cx_sy_sql_error into lo_root_exc. clear: lv_error_msg_temp. lv_error_msg = 'Error in SQL execution'. lv_error_msg_temp = lo_root_exc->get_text( ). if lv_error_msg_temp is not initial. concatenate lv_error_msg ': ' lv_error_msg_temp into lv_error_msg respecting blanks. endif. raise exception type zcx_bc_table_introspector exporting error_text = lv_error_msg. endtry. endmethod. * ---------------------------------------------------------------------------------------+ * | Static Public Method ZCL_BC_TABLE_INTROSPECTOR=>FACTORY_USING_SQL * +-------------------------------------------------------------------------------------------------+ * | [--->] IM_DBTAB TYPE CSEQUENCE * | [--->] IM_COLUMNS TYPE CSEQUENCE(optional) * | [--->] IM_WHERE_CLAUSE TYPE CSEQUENCE(optional) * | [--->] IM_MAX_ROWS TYPE I(optional) * | [--->] IM_DELIMITER TYPE TY_DELIMITER (default =',') * | [--->] IM_USE_HEADER_RECORD TYPE ABAP_BOOL (default =ABAP_TRUE) * | [--->] IM_USE_COLUMN_ALIGNMENT TYPE ABAP_BOOL (default =ABAP_TRUE) * | [--->] IM_POINT_HEADER_TO_DDIC TYPE ABAP_BOOL (default =ABAP_TRUE) * | [--->] IM_ENCLOSE_STRINGS TYPE ABAP_BOOL (default =ABAP_FALSE) * | [--->] IM_FORMAT_TIME TYPE ABAP_BOOL (default =ABAP_TRUE) * | [--->] IM_FORMAT_DATE TYPE ABAP_BOOL (default =ABAP_TRUE) * | [<---] EX_TABLE_INTROSPECTOR TYPE REF TO ZCL_BC_TABLE_INTROSPECTOR * | [!CX!] ZCX_BC_TABLE_INTROSPECTOR * +-------------------------------------------------------------------------------------- method factory_using_sql. *-- object references data: lo_struct_descr type ref to cl_abap_structdescr, lo_formatted_struct_descr type ref to cl_abap_structdescr, lo_formatted_table_descr type ref to cl_abap_structdescr, lo_table_ref type ref to data, lo_formatted_table_ref type ref to data, lo_struct_ref type ref to data, lo_formatted_struct_ref type ref to data. *-- local variables data: lv_folder type string, lv_file type string, lv_use_header type abap_bool, lv_use_column_alignment type abap_bool, lv_use_tstamp type abap_bool, lv_use_server type abap_bool. *-- get flattened components according to columns call method get_table_metadata( exporting im_dbtab = im_dbtab im_columns = im_columns importing ex_struct_descr = lo_struct_descr ). *-- populate header structure call method populate_header( exporting im_use_column_alignment = im_use_column_alignment im_point_header_to_ddic = im_point_header_to_ddic im_struct_descr = lo_struct_descr importing ex_struct_ref = lo_struct_ref ). *-- execute SQL query and populate table structure call method execute_sql( exporting im_dbtab = im_dbtab im_where_clause = im_where_clause im_max_rows = im_max_rows im_struct_descr = lo_struct_descr importing ex_table_ref = lo_table_ref ). *-- create new header and table structures with delimiters inserted call method build_formatted_components( exporting im_use_column_alignment = im_use_column_alignment im_enclose_strings = im_enclose_strings im_struct_descr = lo_struct_descr importing ex_formatted_struct_descr = lo_formatted_struct_descr ex_formatted_table_descr = lo_formatted_table_descr ). *-- populate formatted header call method populate_formatted_header( exporting im_delimiter = im_delimiter im_enclose_strings = im_enclose_strings im_formatted_struct_descr = lo_formatted_struct_descr im_struct_ref = lo_struct_ref importing ex_formatted_struct_ref = lo_formatted_struct_ref ). *-- populate formatted table call method populate_formatted_table( exporting im_delimiter = im_delimiter im_enclose_strings = im_enclose_strings im_format_time = im_format_time im_format_date = im_format_date im_formatted_table_descr = lo_formatted_table_descr im_table_ref = lo_table_ref importing ex_formatted_table_ref = lo_formatted_table_ref ). *-- finally we instantiate the class create object ex_table_introspector exporting im_use_header_record = im_use_header_record im_use_column_alignment = im_use_column_alignment im_header_data_ref = lo_formatted_struct_ref im_table_data_ref = lo_formatted_table_ref im_raw_table_data_ref = lo_table_ref. endmethod. * ---------------------------------------------------------------------------------------+ * | Static Public Method ZCL_BC_TABLE_INTROSPECTOR=>FACTORY_USING_TABLE * +-------------------------------------------------------------------------------------------------+ * | [--->] IM_TABLE TYPE ANY TABLE * | [--->] IM_COLUMNS TYPE CSEQUENCE(optional) * | [--->] IM_DELIMITER TYPE TY_DELIMITER (default =',') * | [--->] IM_USE_HEADER_RECORD TYPE ABAP_BOOL (default =ABAP_TRUE) * | [--->] IM_USE_COLUMN_ALIGNMENT TYPE ABAP_BOOL (default =ABAP_TRUE) * | [--->] IM_POINT_HEADER_TO_DDIC TYPE ABAP_BOOL (default =ABAP_TRUE) * | [--->] IM_ENCLOSE_STRINGS TYPE ABAP_BOOL (default =ABAP_FALSE) * | [--->] IM_FORMAT_TIME TYPE ABAP_BOOL (default =ABAP_TRUE) * | [--->] IM_FORMAT_DATE TYPE ABAP_BOOL (default =ABAP_TRUE) * | [<---] EX_TABLE_INTROSPECTOR TYPE REF TO ZCL_BC_TABLE_INTROSPECTOR * | [!CX!] ZCX_BC_TABLE_INTROSPECTOR * +-------------------------------------------------------------------------------------- method factory_using_table. *-- object references data: lo_struct_descr type ref to cl_abap_structdescr, lo_formatted_struct_descr type ref to cl_abap_structdescr, lo_formatted_table_descr type ref to cl_abap_structdescr, lo_table_ref type ref to data, lo_formatted_table_ref type ref to data, lo_struct_ref type ref to data, lo_formatted_struct_ref type ref to data, lo_root_exc type ref to cx_root. *-- local variables data: lv_folder type string, lv_file type string, lv_use_header type abap_bool, lv_use_column_alignment type abap_bool, lv_use_tstamp type abap_bool, lv_use_server type abap_bool, lv_error_msg type string. *-- get flattened components according to columns call method get_internal_table_metadata( exporting im_table = im_table im_columns = im_columns importing ex_struct_descr = lo_struct_descr ). *-- populate header structure call method populate_header( exporting im_use_column_alignment = im_use_column_alignment im_point_header_to_ddic = im_point_header_to_ddic im_struct_descr = lo_struct_descr importing ex_struct_ref = lo_struct_ref ). *-- populate table structure call method populate_table( exporting im_table = im_table im_struct_descr = lo_struct_descr importing ex_table_ref = lo_table_ref ). *-- create new header and table structures with delimiters interleaved call method build_formatted_components( exporting im_use_column_alignment = im_use_column_alignment im_enclose_strings = im_enclose_strings im_struct_descr = lo_struct_descr importing ex_formatted_struct_descr = lo_formatted_struct_descr ex_formatted_table_descr = lo_formatted_table_descr ). *-- populate formatted header call method populate_formatted_header( exporting im_delimiter = im_delimiter im_enclose_strings = im_enclose_strings im_formatted_struct_descr = lo_formatted_struct_descr im_struct_ref = lo_struct_ref importing ex_formatted_struct_ref = lo_formatted_struct_ref ). *-- populate formatted table call method populate_formatted_table( exporting im_delimiter = im_delimiter im_enclose_strings = im_enclose_strings im_format_time = im_format_time im_format_date = im_format_date im_formatted_table_descr = lo_formatted_table_descr im_table_ref = lo_table_ref importing ex_formatted_table_ref = lo_formatted_table_ref ). *-- finally we instantiate the class create object ex_table_introspector exporting im_use_header_record = im_use_header_record im_use_column_alignment = im_use_column_alignment im_header_data_ref = lo_formatted_struct_ref im_table_data_ref = lo_formatted_table_ref im_raw_table_data_ref = lo_table_ref. endmethod. * ---------------------------------------------------------------------------------------+ * | Instance Public Method ZCL_BC_TABLE_INTROSPECTOR->GET_ALV_RENDITION * +-------------------------------------------------------------------------------------------------+ * | [<---] EX_SALV_TABLE TYPE REF TO CL_SALV_TABLE * | [!CX!] ZCX_BC_TABLE_INTROSPECTOR * +-------------------------------------------------------------------------------------- method get_alv_rendition. *-- object references data: lo_root_exc type ref to cx_root. *-- local variables data: lv_error_msg type string. *-- field symbols field-symbols: type standard table. if raw_table_data_ref is not bound. lv_error_msg = 'No table data found - make sure you have instantiated the class first.'. raise exception type zcx_bc_table_introspector exporting error_text = lv_error_msg. endif. try. assign raw_table_data_ref->* to . cl_salv_table=>factory( importing r_salv_table = ex_salv_table changing t_table = ). catch cx_salv_msg into lo_root_exc. lv_error_msg = lo_root_exc->get_text( ). raise exception type zcx_bc_table_introspector exporting error_text = lv_error_msg. endtry. endmethod. * ---------------------------------------------------------------------------------------+ * | Instance Public Method ZCL_BC_TABLE_INTROSPECTOR->GET_FILE_RENDITION * +-------------------------------------------------------------------------------------------------+ * | [<---] EX_OUTPUT_TABLE TYPE STRING_TABLE * | [!CX!] ZCX_BC_TABLE_INTROSPECTOR * +-------------------------------------------------------------------------------------- method get_file_rendition. *-- internal table defintion data: lt_header_table type string_table, lt_body_table type string_table, lt_output_table type string_table. *-- local variables data: lv_error_msg type string. *-- field symbols field-symbols: type any, type standard table. if table_data_ref is not bound. lv_error_msg = 'No table data found - make sure you have instantiated the class first.'. raise exception type zcx_bc_table_introspector exporting error_text = lv_error_msg. endif. assign header_data_ref->* to . assign table_data_ref->* to . *-- normalize header and body call method normalize_line_format exporting im_use_column_alignment = use_column_alignment im_data = importing ex_table = lt_header_table. call method normalize_line_format exporting im_use_column_alignment = use_column_alignment im_data = importing ex_table = lt_body_table. if use_header_record eq abap_true. append lines of lt_header_table to lt_output_table. endif. append lines of lt_body_table to lt_output_table. ex_output_table[] = lt_output_table[]. endmethod. * ---------------------------------------------------------------------------------------+ * | Static Private Method ZCL_BC_TABLE_INTROSPECTOR=>GET_INTERNAL_TABLE_METADATA * +-------------------------------------------------------------------------------------------------+ * | [--->] IM_TABLE TYPE ANY TABLE * | [--->] IM_COLUMNS TYPE CSEQUENCE(optional) * | [<---] EX_STRUCT_DESCR TYPE REF TO CL_ABAP_STRUCTDESCR * | [!CX!] ZCX_BC_TABLE_INTROSPECTOR * +-------------------------------------------------------------------------------------- method get_internal_table_metadata. *-- object references data: lo_struct_descr type ref to cl_abap_structdescr, lo_table_descr type ref to cl_abap_tabledescr, lo_root_exc type ref to cx_root. *-- internal table defintion data: lt_components type cl_abap_structdescr=>component_table, lt_components_filtered type cl_abap_structdescr=>component_table. *-- structure defintion data: ls_components_filtered like line of lt_components_filtered. *-- local variables data: lv_error_msg type string. try. lo_table_descr ?= cl_abap_tabledescr=>describe_by_data( im_table ). lo_struct_descr ?= lo_table_descr->get_table_line_type( ). catch cx_sy_move_cast_error into lo_root_exc. lv_error_msg = lo_root_exc->get_text( ). raise exception type zcx_bc_table_introspector exporting error_text = lv_error_msg. endtry. lt_components = lo_struct_descr->get_components( ). *-- recursive call - as side effect, components are flattened call method recursive_filter_columns( exporting im_columns = im_columns im_components = lt_components importing ex_components = lt_components_filtered ). if lt_components_filtered[] is initial. lv_error_msg = 'No columns found according to search criteria'. raise exception type zcx_bc_table_introspector exporting error_text = lv_error_msg. endif. try. lo_struct_descr = cl_abap_structdescr=>create( lt_components_filtered ). catch cx_sy_struct_creation cx_sy_table_creation into lo_root_exc. lv_error_msg = lo_root_exc->get_text( ). raise exception type zcx_bc_table_introspector exporting error_text = lv_error_msg. endtry. ex_struct_descr = lo_struct_descr. endmethod. * ---------------------------------------------------------------------------------------+ * | Instance Public Method ZCL_BC_TABLE_INTROSPECTOR->GET_SOLIX_RENDITION * +-------------------------------------------------------------------------------------------------+ * | [<---] EX_SOLIX TYPE SOLIX_TAB * | [!CX!] ZCX_BC_TABLE_INTROSPECTOR * +-------------------------------------------------------------------------------------- method get_solix_rendition. *-- object references data: lo_root_exc type ref to cx_bcs. *-- internal table defintion data: lt_solix type solix_tab, lt_output_table type string_table. *-- structure defintion data: ls_output_table like line of lt_output_table. *-- local variables data: lv_string type string, lv_error_msg type string. if table_data_ref is not bound. lv_error_msg = 'No table data found - make sure you have instantiated the class first.'. raise exception type zcx_bc_table_introspector exporting error_text = lv_error_msg. endif. call method me->get_file_rendition importing ex_output_table = lt_output_table. loop at lt_output_table into ls_output_table. concatenate lv_string ls_output_table cl_abap_char_utilities=>cr_lf into lv_string respecting blanks. endloop. try. cl_bcs_convert=>string_to_solix( exporting iv_string = lv_string importing et_solix = lt_solix ). catch cx_bcs into lo_root_exc. lv_error_msg = lo_root_exc->get_text( ). raise exception type zcx_bc_table_introspector exporting error_text = lv_error_msg. endtry. ex_solix[] = lt_solix[]. endmethod. * ---------------------------------------------------------------------------------------+ * | Instance Public Method ZCL_BC_TABLE_INTROSPECTOR->GET_SOLI_RENDITION * +-------------------------------------------------------------------------------------------------+ * | [--->] IM_TRUNCATE_LINES TYPE ABAP_BOOL (default =ABAP_TRUE) * | [<---] EX_SOLI TYPE SOLI_TAB * | [!CX!] ZCX_BC_TABLE_INTROSPECTOR * +-------------------------------------------------------------------------------------- method get_soli_rendition. *-- object references data: lo_root_exc type ref to cx_bcs. *-- internal table defintion data: lt_soli type soli_tab, lt_soli_temp type soli_tab, lt_output_table type string_table. *-- structure defintion data: ls_soli type soli, ls_output_table like line of lt_output_table. *-- local variables data: lv_string type string, lv_max_len type i, lv_str_len type i, lv_error_msg type string. if table_data_ref is not bound. lv_error_msg = 'No table data found - make sure you have instantiated the class first.'. raise exception type zcx_bc_table_introspector exporting error_text = lv_error_msg. endif. call method me->get_file_rendition importing ex_output_table = lt_output_table. describe field ls_soli-line length lv_max_len in character mode. loop at lt_output_table into ls_output_table. if im_truncate_lines eq abap_true. lv_str_len = strlen( ls_output_table ). if lv_str_len gt lv_max_len. lv_str_len = lv_max_len. endif. ls_soli-line = ls_output_table(lv_str_len). append ls_soli to lt_soli. else. try. cl_bcs_convert=>string_to_soli( exporting iv_string = ls_output_table receiving et_soli = lt_soli_temp ). append lines of lt_soli_temp to lt_soli. catch cx_bcs into lo_root_exc. lv_error_msg = lo_root_exc->get_text( ). raise exception type zcx_bc_table_introspector exporting error_text = lv_error_msg. endtry. endif. endloop. ex_soli[] = lt_soli[]. endmethod. * ---------------------------------------------------------------------------------------+ * | Static Private Method ZCL_BC_TABLE_INTROSPECTOR=>GET_TABLE_METADATA * +-------------------------------------------------------------------------------------------------+ * | [--->] IM_DBTAB TYPE CSEQUENCE * | [--->] IM_COLUMNS TYPE CSEQUENCE * | [<---] EX_STRUCT_DESCR TYPE REF TO CL_ABAP_STRUCTDESCR * | [!CX!] ZCX_BC_TABLE_INTROSPECTOR * +-------------------------------------------------------------------------------------- method get_table_metadata. *-- object references data: lo_type_descr type ref to cl_abap_typedescr, lo_elemdescr type ref to cl_abap_elemdescr, lo_struct_descr type ref to cl_abap_structdescr, lo_root_exc type ref to cx_root. *-- internal table defintion data: lt_components type cl_abap_structdescr=>component_table, lt_components_filtered type cl_abap_structdescr=>component_table. *-- structure defintion data: ls_components_filtered like line of lt_components_filtered, ls_dfies type dfies. *-- local variables data: lv_error_msg type string. cl_abap_typedescr=>describe_by_name( exporting p_name = im_dbtab receiving p_descr_ref = lo_type_descr exceptions type_not_found = 4 ). if sy-subrc = 4. if im_dbtab is initial. lv_error_msg = 'No table specified'. else. concatenate 'Table ' im_dbtab ' not found' into lv_error_msg respecting blanks. condense lv_error_msg. endif. raise exception type zcx_bc_table_introspector exporting error_text = lv_error_msg. endif. try. lo_struct_descr ?= lo_type_descr. catch cx_sy_move_cast_error into lo_root_exc. lv_error_msg = lo_root_exc->get_text( ). raise exception type zcx_bc_table_introspector exporting error_text = lv_error_msg. endtry. lt_components = lo_struct_descr->get_components( ). *-- recursive call - as side effect, components are flattened call method recursive_filter_columns( exporting im_columns = im_columns im_components = lt_components importing ex_components = lt_components_filtered ). if lt_components_filtered[] is initial. lv_error_msg = 'No columns found according to search criteria'. raise exception type zcx_bc_table_introspector exporting error_text = lv_error_msg. endif. try. lo_struct_descr = cl_abap_structdescr=>create( lt_components_filtered ). catch cx_sy_struct_creation cx_sy_table_creation into lo_root_exc. lv_error_msg = lo_root_exc->get_text( ). raise exception type zcx_bc_table_introspector exporting error_text = lv_error_msg. endtry. ex_struct_descr = lo_struct_descr. endmethod. * ---------------------------------------------------------------------------------------+ * | Static Private Method ZCL_BC_TABLE_INTROSPECTOR=>NORMALIZE_LINE_FORMAT * +-------------------------------------------------------------------------------------------------+ * | [--->] IM_USE_COLUMN_ALIGNMENT TYPE ABAP_BOOL * | [--->] IM_DATA TYPE ANY * | [<---] EX_TABLE TYPE STRING_TABLE * | [!CX!] ZCX_BC_TABLE_INTROSPECTOR * +-------------------------------------------------------------------------------------- method normalize_line_format. *-- object references data: lo_struct_ref type ref to data, lo_table_ref type ref to data, lo_struct_objectdescr type ref to cl_abap_objectdescr, lo_table_objectdescr type ref to cl_abap_objectdescr, lo_type_descr type ref to cl_abap_typedescr. *-- local variables data: lv_len type i, lv_mod_result type i, lv_counter type i, lv_line type string. *-- field symbols field-symbols: type any, type standard table, type any, type any. cl_abap_typedescr=>describe_by_data( exporting p_data = im_data receiving p_descr_ref = lo_type_descr ). lo_struct_objectdescr ?= cl_abap_typedescr=>describe_by_name( 'cl_abap_structdescr' ). lo_table_objectdescr ?= cl_abap_typedescr=>describe_by_name( 'cl_abap_tabledescr' ). if lo_struct_objectdescr->applies_to( lo_type_descr ) eq 'X'. *-- process structure create data lo_struct_ref like im_data. assign lo_struct_ref->* to . = im_data. lv_counter = 0. lv_line = ''. if im_use_column_alignment eq abap_false. *-- build up line with condensed fields do. add 1 to lv_counter. assign component lv_counter of structure to . if sy-subrc is not initial. exit. endif. shift right deleting trailing space. shift left deleting leading space. *-- add field to line lv_len = strlen( ). if lv_len ge 1. concatenate lv_line (lv_len) into lv_line respecting blanks. endif. enddo. else. lv_len = strlen( ). lv_line = (lv_len). endif. append lv_line to ex_table. elseif lo_table_objectdescr->applies_to( lo_type_descr ) eq 'X'. *-- process table create data lo_table_ref like im_data. assign lo_table_ref->* to . = im_data. loop at assigning . " cast to address fields symbol. w/out using offset/length lv_counter = 0. lv_line = ''. if im_use_column_alignment eq abap_false. *-- build up line with condensed fields do. add 1 to lv_counter. assign component lv_counter of structure to . if sy-subrc is not initial. exit. endif. shift right deleting trailing space. shift left deleting leading space. lv_len = strlen( ). if lv_len ge 1. concatenate lv_line (lv_len) into lv_line respecting blanks. endif. enddo. else. lv_len = strlen( ). lv_line = (lv_len). endif. append lv_line to ex_table. endloop. endif. endmethod. * ---------------------------------------------------------------------------------------+ * | Static Private Method ZCL_BC_TABLE_INTROSPECTOR=>POPULATE_FORMATTED_HEADER * +-------------------------------------------------------------------------------------------------+ * | [--->] IM_DELIMITER TYPE TY_DELIMITER(optional) * | [--->] IM_ENCLOSE_STRINGS TYPE ABAP_BOOL * | [--->] IM_FORMATTED_STRUCT_DESCR TYPE REF TO CL_ABAP_STRUCTDESCR * | [--->] IM_STRUCT_REF TYPE REF TO DATA * | [<---] EX_FORMATTED_STRUCT_REF TYPE REF TO DATA * | [!CX!] ZCX_BC_TABLE_INTROSPECTOR * +-------------------------------------------------------------------------------------- method populate_formatted_header. *-- object references data: lo_elemdescr type ref to cl_abap_elemdescr, lo_root_exc type ref to cx_root. *-- local variables data: lv_counter type i value 0, lv_mod_result type i, lv_string_length type i, lv_output_length type i, lv_repetitions type string, lv_regex type string, lv_error_msg type string. *-- field symbols field-symbols: type any, type any, type any. try. create data ex_formatted_struct_ref type handle im_formatted_struct_descr. assign ex_formatted_struct_ref->* to . " point to results for later export catch cx_sy_create_data_error into lo_root_exc. lv_error_msg = lo_root_exc->get_text( ). raise exception type zcx_bc_table_introspector exporting error_text = lv_error_msg. endtry. *-- move data to , and inject delimiters assign im_struct_ref->* to . move-corresponding to . *-- iterate thru each component of interleaved structure lv_counter = 0. do. add 1 to lv_counter. assign component lv_counter of structure to . if sy-subrc is not initial. exit. endif. lv_mod_result = lv_counter mod 2. *-- populate field if lv_mod_result ne 0. shift right deleting trailing space. shift left deleting leading space. *-- header fields are always treated as a string if im_enclose_strings eq abap_true. *-- build regular expression to correctly insert quotes lo_elemdescr ?= cl_abap_elemdescr=>describe_by_data( ). lv_output_length = lo_elemdescr->output_length - 2. lv_string_length = strlen( ). if lv_output_length lt lv_string_length. lv_repetitions = lv_output_length. else. lv_repetitions = lv_string_length. endif. condense lv_repetitions. concatenate '(^.{' lv_repetitions '})(.*$)' into lv_regex. *-- interpolate quotes in field replace regex lv_regex in with '"$1"'. endif. else. *-- populate delimiter = im_delimiter. endif. enddo. endmethod. * ---------------------------------------------------------------------------------------+ * | Static Private Method ZCL_BC_TABLE_INTROSPECTOR=>POPULATE_FORMATTED_TABLE * +-------------------------------------------------------------------------------------------------+ * | [--->] IM_DELIMITER TYPE TY_DELIMITER(optional) * | [--->] IM_ENCLOSE_STRINGS TYPE ABAP_BOOL * | [--->] IM_FORMAT_TIME TYPE ABAP_BOOL(optional) * | [--->] IM_FORMAT_DATE TYPE ABAP_BOOL(optional) * | [--->] IM_FORMATTED_TABLE_DESCR TYPE REF TO CL_ABAP_STRUCTDESCR * | [--->] IM_TABLE_REF TYPE REF TO DATA * | [<---] EX_FORMATTED_TABLE_REF TYPE REF TO DATA * | [!CX!] ZCX_BC_TABLE_INTROSPECTOR * +-------------------------------------------------------------------------------------- method populate_formatted_table. *-- object references data: lo_struct_descr type ref to cl_abap_structdescr, lo_table_descr type ref to cl_abap_tabledescr, lo_structdescr_interleaved type ref to cl_abap_structdescr, lo_tabledescr_interleaved type ref to cl_abap_tabledescr, lo_table_line_ref type ref to data, lo_table_interleaved_ref type ref to data, lo_root_exc type ref to cx_root. *-- local variables data: lv_error_msg type string, lv_counter type i value 0, lv_typekind type abap_typekind, lv_mod_result type i, lv_date_internal type sydatum, lv_date_external type string, lv_time_internal type syuzeit, lv_time_external type string. *-- field symbols field-symbols: type standard table, type standard table, type any, type any, like line of cl_abap_structdescr=>components, type any, type any. *-- create new (empty) table based on previously built interleaved components try. lo_tabledescr_interleaved = cl_abap_tabledescr=>create( im_formatted_table_descr ). catch cx_sy_struct_creation cx_sy_table_creation into lo_root_exc. lv_error_msg = lo_root_exc->get_text( ). raise exception type zcx_bc_table_introspector exporting error_text = lv_error_msg. endtry. try. create data ex_formatted_table_ref type handle lo_tabledescr_interleaved. assign ex_formatted_table_ref->* to . " point to results for later export catch cx_sy_create_data_error into lo_root_exc. lv_error_msg = lo_root_exc->get_text( ). raise exception type zcx_bc_table_introspector exporting error_text = lv_error_msg. endtry. try. *-- create table work area assign im_table_ref->* to . create data lo_table_line_ref like line of . assign lo_table_line_ref->* to . *-- create interleaved table work area create data lo_table_interleaved_ref like line of . assign lo_table_interleaved_ref->* to . catch cx_sy_create_data_error into lo_root_exc. lv_error_msg = lo_root_exc->get_text( ). raise exception type zcx_bc_table_introspector exporting error_text = lv_error_msg. endtry. *-- move data to , and inject delimiters loop at into . *-- iterate thru each component of interleaved structure lv_counter = 0. loop at im_formatted_table_descr->components assigning . add 1 to lv_counter. assign component -name of structure to . lv_mod_result = lv_counter mod 2. *-- populate field if lv_mod_result ne 0. *-- lookup original field to get type kind assign component -name of structure to . lv_typekind = cl_abap_elemdescr=>get_data_type_kind( ). = . *-- apply formatting to field check is not initial. case lv_typekind. when cl_abap_typedescr=>typekind_time. if im_format_time eq abap_true. lv_time_internal = . try. call method cl_abap_timefm=>conv_time_int_to_ext exporting time_int = lv_time_internal importing time_ext = lv_time_external. = lv_time_external. catch cx_parameter_invalid_range. clear . endtry. endif. when cl_abap_typedescr=>typekind_date. if im_format_date eq abap_true. lv_date_internal = . try. call method cl_abap_datfm=>conv_date_int_to_ext exporting im_datint = lv_date_internal importing ex_datext = lv_date_external. = lv_date_external. catch cx_abap_datfm_format_unknown. clear . endtry. endif. when cl_abap_typedescr=>typekind_string or cl_abap_typedescr=>typekind_char. if im_enclose_strings eq abap_true. replace all occurrences of '"' in with ''''. concatenate '"' '"' into . else. *-- remove delimiter when not escaped with quotes replace all occurrences of im_delimiter in with ` `. endif. when cl_abap_typedescr=>typekind_num or cl_abap_typedescr=>typekind_packed or cl_abap_typedescr=>typekind_int or cl_abap_typedescr=>typekind_float. call function 'CLOI_PUT_SIGN_IN_FRONT' changing value = . endcase. shift right deleting trailing space. shift left deleting leading space. else. *-- populate delimiter = im_delimiter. endif. endloop. append to . endloop. endmethod. * ---------------------------------------------------------------------------------------+ * | Static Private Method ZCL_BC_TABLE_INTROSPECTOR=>POPULATE_HEADER * +-------------------------------------------------------------------------------------------------+ * | [--->] IM_USE_COLUMN_ALIGNMENT TYPE ABAP_BOOL * | [--->] IM_POINT_HEADER_TO_DDIC TYPE ABAP_BOOL * | [--->] IM_STRUCT_DESCR TYPE REF TO CL_ABAP_STRUCTDESCR * | [<---] EX_STRUCT_REF TYPE REF TO DATA * | [!CX!] ZCX_BC_TABLE_INTROSPECTOR * +-------------------------------------------------------------------------------------- method populate_header. *-- object references data: lo_elemdescr type ref to cl_abap_elemdescr, lo_struct_descr type ref to cl_abap_structdescr, lo_root_exc type ref to cx_root. *-- internal table defintion data: lt_components type cl_abap_structdescr=>component_table, lt_hdr_components type cl_abap_structdescr=>component_table. *-- structure defintion data: ls_component type abap_componentdescr, ls_hdr_component type abap_componentdescr, ls_component_temp type abap_componentdescr, ls_dfies type dfies. *-- local variables data: lv_normalized_name type c length 255, lv_error_msg type string. *-- field symbols field-symbols: type any, type any. *-- call get_components to populate components from structure lt_components = im_struct_descr->get_components( ). loop at lt_components into ls_component. *-- create new structure based on structure passed thru try. clear: ls_component_temp. lo_elemdescr ?= ls_component-type. if im_use_column_alignment eq abap_true. *-- account for string elements which have no defined length if lo_elemdescr->output_length eq 0. ls_component_temp-type = cl_abap_elemdescr=>get_c( p_length = 255 ). else. ls_component_temp-type = cl_abap_elemdescr=>get_c( p_length = lo_elemdescr->output_length ). endif. else. ls_component_temp-type = cl_abap_elemdescr=>get_c( p_length = 40 ). endif. ls_component_temp-name = ls_component-name. append ls_component_temp to lt_hdr_components. catch cx_sy_move_cast_error into lo_root_exc. lv_error_msg = lo_root_exc->get_text( ). raise exception type zcx_bc_table_introspector exporting error_text = lv_error_msg. endtry. endloop. *-- get structure description from newly created component table try. lo_struct_descr = cl_abap_structdescr=>create( lt_hdr_components ). catch cx_sy_struct_creation into lo_root_exc. lv_error_msg = lo_root_exc->get_text( ). raise exception type zcx_bc_table_introspector exporting error_text = lv_error_msg. endtry. *-- now populate each field from previous ddic lookup try. create data ex_struct_ref type handle lo_struct_descr. assign ex_struct_ref->* to . catch cx_sy_create_data_error into lo_root_exc. lv_error_msg = lo_root_exc->get_text( ). raise exception type zcx_bc_table_introspector exporting error_text = lv_error_msg. endtry. loop at lt_hdr_components into ls_hdr_component. assign component ls_hdr_component-name of structure to . *-- lookup original component and read element description read table lt_components with key name = ls_hdr_component-name into ls_component. lo_elemdescr ?= ls_component-type. *-- retrieve ddic description where relevant if im_point_header_to_ddic eq abap_false. lv_normalized_name = ls_hdr_component-name. translate lv_normalized_name to lower case. else. *-- if ddic element, retrieve field label if lo_elemdescr->is_ddic_type( ) eq abap_true. ls_dfies = lo_elemdescr->get_ddic_field( ). lv_normalized_name = ls_dfies-scrtext_l. else. *-- if not ddic element, set field label to pretty printed name of element lv_normalized_name = ls_hdr_component-name. replace all occurrences of '_' in lv_normalized_name with ` `. translate lv_normalized_name to lower case. translate lv_normalized_name+0(1) to upper case. endif. endif. = lv_normalized_name. endloop. endmethod. * ---------------------------------------------------------------------------------------+ * | Static Private Method ZCL_BC_TABLE_INTROSPECTOR=>POPULATE_TABLE * +-------------------------------------------------------------------------------------------------+ * | [--->] IM_TABLE TYPE ANY TABLE * | [--->] IM_STRUCT_DESCR TYPE REF TO CL_ABAP_STRUCTDESCR * | [<---] EX_TABLE_REF TYPE REF TO DATA * | [!CX!] ZCX_BC_TABLE_INTROSPECTOR * +-------------------------------------------------------------------------------------- method populate_table. *-- object references data: lo_src_table_descr type ref to cl_abap_tabledescr, lo_src_table_ref type ref to data, lo_src_struct_descr type ref to cl_abap_structdescr, lo_src_struct_ref type ref to data, lo_dst_table_ref type ref to data, lo_dst_struct_ref type ref to data, lo_table_descr type ref to cl_abap_tabledescr, lo_root_exc type ref to cx_root. *-- local variables data: lv_error_msg type string. *-- field symbols field-symbols: type standard table, type any, type standard table, type any. *-- prepare source table structures try. lo_src_table_descr ?= cl_abap_tabledescr=>describe_by_data( im_table ). lo_src_struct_descr ?= lo_src_table_descr->get_table_line_type( ). catch cx_sy_move_cast_error into lo_root_exc. lv_error_msg = lo_root_exc->get_text( ). raise exception type zcx_bc_table_introspector exporting error_text = lv_error_msg. endtry. create data lo_src_table_ref type handle lo_src_table_descr. assign lo_src_table_ref->* to . create data lo_src_struct_ref type handle lo_src_struct_descr. assign lo_src_struct_ref->* to . = im_table. *-- prepare destination table structures (descriptions passed represent destination) lo_table_descr = cl_abap_tabledescr=>create( im_struct_descr ). create data lo_dst_table_ref type handle lo_table_descr. assign lo_dst_table_ref->* to . create data lo_dst_struct_ref type handle im_struct_descr. assign lo_dst_struct_ref->* to . *-- copy data between tables loop at into . move-corresponding to . append to . endloop. ex_table_ref = lo_dst_table_ref. endmethod. * ---------------------------------------------------------------------------------------+ * | Static Private Method ZCL_BC_TABLE_INTROSPECTOR=>RECURSIVE_FILTER_COLUMNS * +-------------------------------------------------------------------------------------------------+ * | [--->] IM_COLUMNS TYPE CSEQUENCE * | [--->] IM_COMPONENTS TYPE CL_ABAP_STRUCTDESCR=>COMPONENT_TABLE * | [<---] EX_COMPONENTS TYPE CL_ABAP_STRUCTDESCR=>COMPONENT_TABLE * | [!CX!] ZCX_BC_TABLE_INTROSPECTOR * +-------------------------------------------------------------------------------------- method recursive_filter_columns. *-- object references data: lo_elem_objectdescr type ref to cl_abap_objectdescr, lo_struct_objectdescr type ref to cl_abap_objectdescr, lo_structdescr type ref to cl_abap_structdescr, lo_root_exc type ref to cx_root. *-- internal table defintion data: lt_components type cl_abap_structdescr=>component_table, lt_components_filtered type cl_abap_structdescr=>component_table, lt_inner_components type cl_abap_structdescr=>component_table, lt_components_temp type cl_abap_structdescr=>component_table. *-- structure defintion data: ls_component type abap_componentdescr, ls_component_temp type abap_componentdescr. *-- local variables data: lv_error_msg type string. lt_components[] = im_components[]. *-- loop thru all components and convert to flat, filtered collection loop at lt_components into ls_component. *-- set up descriptors to test what subclass of cl_abap_typedescr is being processed (ABAP lacks instance of operator) lo_elem_objectdescr ?= cl_abap_typedescr=>describe_by_name( 'cl_abap_elemdescr' ). lo_struct_objectdescr ?= cl_abap_typedescr=>describe_by_name( 'cl_abap_structdescr' ). *-- iterate thru each component: if component is an element, process directly; if component is a structure, process recursively if lo_elem_objectdescr->applies_to( ls_component-type ) eq 'X'. *-- skip MANDT column here if ls_component-name eq 'MANDT'. continue. endif. *-- adjust component collection based on selected columns (* or space defaults to all columns) clear: ls_component_temp. if im_columns ns '*' and im_columns is not initial. move ls_component to ls_component_temp. concatenate '\b' ls_component_temp-name '\b' into ls_component_temp-name. find regex ls_component_temp-name in im_columns ignoring case. if sy-subrc <> 0. "remove all occurrences replace all occurrences of regex ls_component_temp-name in im_columns with ''. continue. endif. endif. append ls_component to lt_components_filtered. elseif lo_struct_objectdescr->applies_to( ls_component-type ) eq 'X'. try. *-- cast to cl_abap_structdescr, get each component related to the structure, and process lo_structdescr ?= ls_component-type. catch cx_sy_move_cast_error into lo_root_exc. lv_error_msg = lo_root_exc->get_text( ). raise exception type zcx_bc_table_introspector exporting error_text = lv_error_msg. endtry. lt_inner_components = lo_structdescr->get_components( ). *-- recursive call call method recursive_filter_columns( exporting im_columns = im_columns im_components = lt_inner_components importing ex_components = lt_components_temp ). append lines of lt_components_temp to lt_components_filtered. endif. endloop. *-- return new flat filtered component structure ex_components[] = lt_components_filtered[]. endmethod. ENDCLASS.