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_color type n length 2 . types: ty_xml(1024) type x . types: ty_xml_t type standard table of ty_xml with non-unique default key . types: ty_delimiter type c length 1 . constants: begin of e_color, none type ty_color value '00', standard type ty_color value '01', end of e_color . type-pools ABAP . class-methods FACTORY_USING_SQL importing !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 !IM_AUTHOR type STRING optional !IM_SHEET_NAME type STRING optional !IM_FREEZE_HEADER type ABAP_BOOL default ABAP_TRUE !IM_HEADER_COLOR type TY_COLOR default E_COLOR-STANDARD !IM_HEADER_HEIGHT type I default 5 !IM_STRING_CELL_WIDTH type I default 80 !IM_POINTS_FACTOR type I default 8 exporting value(EX_TABLE_INTROSPECTOR) type ref to ZCL_BC_TABLE_INTROSPECTOR raising ZCX_BC_TABLE_INTROSPECTOR . class-methods FACTORY_USING_TABLE importing !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 !IM_AUTHOR type STRING optional !IM_SHEET_NAME type STRING optional !IM_FREEZE_HEADER type ABAP_BOOL default ABAP_TRUE !IM_HEADER_COLOR type TY_COLOR default E_COLOR-STANDARD !IM_HEADER_HEIGHT type I default 5 !IM_STRING_CELL_WIDTH type I default 80 !IM_POINTS_FACTOR type I default 8 exporting value(EX_TABLE_INTROSPECTOR) type ref to ZCL_BC_TABLE_INTROSPECTOR raising ZCX_BC_TABLE_INTROSPECTOR . methods GET_ALV_RENDITION exporting value(EX_ALV_TABLE) type ref to CL_SALV_TABLE raising ZCX_BC_TABLE_INTROSPECTOR . methods GET_SOLI_RENDITION exporting value(EX_SOLI_TABLE) type SOLI_TAB raising ZCX_BC_TABLE_INTROSPECTOR . methods GET_SOLIX_RENDITION exporting value(EX_SOLIX_TABLE) type SOLIX_TAB raising ZCX_BC_TABLE_INTROSPECTOR . methods GET_XML_SOLIX_RENDITION exporting value(EX_XML_SOLIX_TABLE) type SOLIX_TAB raising ZCX_BC_TABLE_INTROSPECTOR . methods GET_FILE_RENDITION exporting value(EX_FILE_TABLE) type STRING_TABLE raising ZCX_BC_TABLE_INTROSPECTOR . methods GET_XML_RENDITION exporting value(EX_XML_TABLE) type TY_XML_T 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 . data XML_DOCUMENT_REF type ref to IF_IXML_DOCUMENT . 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 !IM_XML_DOCUMENT_REF type ref to IF_IXML_DOCUMENT . class-methods GET_INTERNAL_TABLE_METADATA importing !IM_TABLE type ANY TABLE !IM_COLUMNS type CSEQUENCE optional exporting value(EX_STRUCT_DESCR) type ref to CL_ABAP_STRUCTDESCR value(EX_XML_STRUCT_DESCR) type ref to CL_ABAP_STRUCTDESCR raising ZCX_BC_TABLE_INTROSPECTOR . class-methods GET_TABLE_METADATA importing !IM_DBTAB type CSEQUENCE !IM_COLUMNS type CSEQUENCE exporting value(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 !IM_COLUMNS type CSEQUENCE !IM_COMPONENTS type CL_ABAP_STRUCTDESCR=>COMPONENT_TABLE exporting value(EX_COMPONENTS) type CL_ABAP_STRUCTDESCR=>COMPONENT_TABLE raising ZCX_BC_TABLE_INTROSPECTOR . class-methods POPULATE_HEADER importing !IM_USE_COLUMN_ALIGNMENT type ABAP_BOOL !IM_POINT_HEADER_TO_DDIC type ABAP_BOOL !IM_STRUCT_DESCR type ref to CL_ABAP_STRUCTDESCR exporting value(EX_STRUCT_REF) type ref to DATA raising ZCX_BC_TABLE_INTROSPECTOR . class-methods EXECUTE_SQL importing !IM_DBTAB type CSEQUENCE !IM_WHERE_CLAUSE type CSEQUENCE !IM_MAX_ROWS type I !IM_STRUCT_DESCR type ref to CL_ABAP_STRUCTDESCR exporting value(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 value(EX_TABLE_REF) type ref to DATA raising ZCX_BC_TABLE_INTROSPECTOR . class-methods BUILD_FORMATTED_COMPONENTS importing !IM_USE_COLUMN_ALIGNMENT type ABAP_BOOL !IM_ENCLOSE_STRINGS type ABAP_BOOL !IM_STRUCT_DESCR type ref to CL_ABAP_STRUCTDESCR exporting value(EX_FORMATTED_STRUCT_DESCR) type ref to CL_ABAP_STRUCTDESCR value(EX_FORMATTED_TABLE_DESCR) type ref to CL_ABAP_STRUCTDESCR raising ZCX_BC_TABLE_INTROSPECTOR . class-methods POPULATE_FORMATTED_HEADER importing !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 exporting value(EX_FORMATTED_STRUCT_REF) type ref to DATA raising ZCX_BC_TABLE_INTROSPECTOR . class-methods POPULATE_FORMATTED_TABLE importing !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 exporting value(EX_FORMATTED_TABLE_REF) type ref to DATA raising ZCX_BC_TABLE_INTROSPECTOR . class-methods NORMALIZE_LINE_FORMAT importing !IM_USE_COLUMN_ALIGNMENT type ABAP_BOOL !IM_DATA type ANY exporting value(EX_TABLE) type STRING_TABLE raising ZCX_BC_TABLE_INTROSPECTOR . class-methods POPULATE_XML_TABLE importing !IM_TABLE type ANY TABLE !IM_XML_STRUCT_DESCR type ref to CL_ABAP_STRUCTDESCR exporting value(EX_XML_TABLE_REF) type ref to DATA raising ZCX_BC_TABLE_INTROSPECTOR . class-methods GET_DDIC_NAME importing !IM_COMPONENT type CL_ABAP_STRUCTDESCR=>COMPONENT !IM_POINT_HEADER_TO_DDIC type ABAP_BOOL exporting value(EX_NAME) type STRING raising ZCX_BC_TABLE_INTROSPECTOR . class-methods POPULATE_XML_DOCUMENT importing !IM_USE_HEADER_RECORD type ABAP_BOOL optional !IM_POINT_HEADER_TO_DDIC type ABAP_BOOL optional !IM_FORMAT_TIME type ABAP_BOOL optional !IM_FORMAT_DATE type ABAP_BOOL optional !IM_AUTHOR type STRING optional !IM_SHEET_NAME type STRING optional !IM_FREEZE_HEADER type ABAP_BOOL optional !IM_HEADER_COLOR type TY_COLOR optional !IM_HEADER_HEIGHT type I optional !IM_STRING_CELL_WIDTH type I optional !IM_POINTS_FACTOR type I optional !IM_XML_TABLE_REF type ref to DATA exporting value(EX_XML_DOCUMENT_REF) type ref to IF_IXML_DOCUMENT 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_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. *-- 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. "build_formatted_components * ---------------------------------------------------------------------------------------+ * | 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 * | [--->] IM_XML_DOCUMENT_REF TYPE REF TO IF_IXML_DOCUMENT * +-------------------------------------------------------------------------------------- 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. xml_document_ref = im_xml_document_ref. endmethod. "constructor * ---------------------------------------------------------------------------------------+ * | 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. "execute_sql * ---------------------------------------------------------------------------------------+ * | 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) * | [--->] IM_AUTHOR TYPE STRING(optional) * | [--->] IM_SHEET_NAME TYPE STRING(optional) * | [--->] IM_FREEZE_HEADER TYPE ABAP_BOOL (default =ABAP_TRUE) * | [--->] IM_HEADER_COLOR TYPE TY_COLOR (default =E_COLOR-STANDARD) * | [--->] IM_HEADER_HEIGHT TYPE I (default =5) * | [--->] IM_STRING_CELL_WIDTH TYPE I (default =80) * | [--->] IM_POINTS_FACTOR TYPE I (default =8) * | [<---] 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_xml_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_xml_document_ref type ref to if_ixml_document. *-- 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 ). *-- populate xml table structure - no long text considered lo_xml_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 ). *-- populate xml document call method populate_xml_document( exporting im_use_header_record = im_use_header_record im_point_header_to_ddic = im_point_header_to_ddic im_format_time = im_format_time im_format_date = im_format_date im_author = im_author im_sheet_name = im_sheet_name im_freeze_header = im_freeze_header im_header_color = im_header_color im_header_height = im_header_height im_string_cell_width = im_string_cell_width im_points_factor = im_points_factor im_xml_table_ref = lo_xml_table_ref importing ex_xml_document_ref = lo_xml_document_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 im_xml_document_ref = lo_xml_document_ref. endmethod. "factory_using_sql * ---------------------------------------------------------------------------------------+ * | 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) * | [--->] IM_AUTHOR TYPE STRING(optional) * | [--->] IM_SHEET_NAME TYPE STRING(optional) * | [--->] IM_FREEZE_HEADER TYPE ABAP_BOOL (default =ABAP_TRUE) * | [--->] IM_HEADER_COLOR TYPE TY_COLOR (default =E_COLOR-STANDARD) * | [--->] IM_HEADER_HEIGHT TYPE I (default =5) * | [--->] IM_STRING_CELL_WIDTH TYPE I (default =80) * | [--->] IM_POINTS_FACTOR TYPE I (default =8) * | [<---] 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_xml_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_xml_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_xml_document_ref type ref to if_ixml_document. *-- 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 ex_xml_struct_descr = lo_xml_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 ). *-- populate xml table structure call method populate_xml_table( exporting im_table = im_table im_xml_struct_descr = lo_xml_struct_descr importing ex_xml_table_ref = lo_xml_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 ). *-- populate xml document call method populate_xml_document( exporting im_use_header_record = im_use_header_record im_point_header_to_ddic = im_point_header_to_ddic im_format_time = im_format_time im_format_date = im_format_date im_author = im_author im_sheet_name = im_sheet_name im_freeze_header = im_freeze_header im_header_color = im_header_color im_header_height = im_header_height im_string_cell_width = im_string_cell_width im_points_factor = im_points_factor im_xml_table_ref = lo_xml_table_ref importing ex_xml_document_ref = lo_xml_document_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 im_xml_document_ref = lo_xml_document_ref. endmethod. "factory_using_table * ---------------------------------------------------------------------------------------+ * | Instance Public Method ZCL_BC_TABLE_INTROSPECTOR->GET_ALV_RENDITION * +-------------------------------------------------------------------------------------------------+ * | [<---] EX_ALV_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_alv_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. "get_alv_rendition * ---------------------------------------------------------------------------------------+ * | Static Private Method ZCL_BC_TABLE_INTROSPECTOR=>GET_DDIC_NAME * +-------------------------------------------------------------------------------------------------+ * | [--->] IM_COMPONENT TYPE CL_ABAP_STRUCTDESCR=>COMPONENT * | [--->] IM_POINT_HEADER_TO_DDIC TYPE ABAP_BOOL * | [<---] EX_NAME TYPE STRING * | [!CX!] ZCX_BC_TABLE_INTROSPECTOR * +-------------------------------------------------------------------------------------- method get_ddic_name. *-- object references data: lo_elemdescr type ref to cl_abap_elemdescr, lo_root_exc type ref to cx_root. *-- structure defintion data: ls_dfies type dfies. *-- local variables data: lv_normalized_name type c length 255, lv_error_msg type string. try. lo_elemdescr ?= im_component-type. *-- retrieve ddic description where relevant if im_point_header_to_ddic eq abap_false. lv_normalized_name = im_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. endif. *-- if not ddic element (or ddic description empty), set field label to pretty printed name of element if lv_normalized_name is initial. lv_normalized_name = im_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. ex_name = lv_normalized_name. 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. endmethod. "get_ddic_name * ---------------------------------------------------------------------------------------+ * | Instance Public Method ZCL_BC_TABLE_INTROSPECTOR->GET_FILE_RENDITION * +-------------------------------------------------------------------------------------------------+ * | [<---] EX_FILE_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_file_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_file_table. endif. append lines of lt_body_table to lt_file_table. ex_file_table[] = lt_file_table[]. endmethod. "get_file_rendition * ---------------------------------------------------------------------------------------+ * | 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 * | [<---] EX_XML_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_elem_objectdescr type ref to cl_abap_objectdescr, lo_xml_struct_descr type ref to cl_abap_structdescr, lo_root_exc type ref to cx_root. *-- internal table defintion data: lt_original_components type cl_abap_structdescr=>component_table, lt_components_filtered type cl_abap_structdescr=>component_table, lt_components type cl_abap_structdescr=>component_table, lt_xml_components type cl_abap_structdescr=>component_table. *-- structure defintion data: ls_component_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_original_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_original_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. *-- standard component set includes elements only lo_elem_objectdescr ?= cl_abap_typedescr=>describe_by_name( 'cl_abap_elemdescr' ). loop at lt_components_filtered into ls_component_filtered. if lo_elem_objectdescr->applies_to( ls_component_filtered-type ) eq 'X'. append ls_component_filtered to lt_components. endif. endloop. *-- xml component set includes elements and tables lt_xml_components[] = lt_components_filtered[]. try. lo_struct_descr = cl_abap_structdescr=>create( lt_components ). lo_xml_struct_descr = cl_abap_structdescr=>create( lt_xml_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. ex_struct_descr = lo_struct_descr. ex_xml_struct_descr = lo_xml_struct_descr. endmethod. "get_internal_table_metadata * ---------------------------------------------------------------------------------------+ * | Instance Public Method ZCL_BC_TABLE_INTROSPECTOR->GET_SOLIX_RENDITION * +-------------------------------------------------------------------------------------------------+ * | [<---] EX_SOLIX_TABLE 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_file_table type string_table. *-- structure defintion data: ls_file_table like line of lt_file_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_file_table = lt_file_table. loop at lt_file_table into ls_file_table. concatenate lv_string ls_file_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_table[] = lt_solix[]. endmethod. "get_solix_rendition * ---------------------------------------------------------------------------------------+ * | Instance Public Method ZCL_BC_TABLE_INTROSPECTOR->GET_SOLI_RENDITION * +-------------------------------------------------------------------------------------------------+ * | [<---] EX_SOLI_TABLE 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_file_table type string_table. *-- structure defintion data: ls_file_table like line of lt_file_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_file_table = lt_file_table. loop at lt_file_table into ls_file_table. concatenate lv_string ls_file_table cl_abap_char_utilities=>cr_lf into lv_string respecting blanks. endloop. try. cl_bcs_convert=>string_to_soli( exporting iv_string = lv_string receiving et_soli = 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. ex_soli_table[] = lt_soli[]. endmethod. "get_soli_rendition * ---------------------------------------------------------------------------------------+ * | 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_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. *-- 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. "get_table_metadata * ---------------------------------------------------------------------------------------+ * | Instance Public Method ZCL_BC_TABLE_INTROSPECTOR->GET_XML_RENDITION * +-------------------------------------------------------------------------------------------------+ * | [<---] EX_XML_TABLE TYPE TY_XML_T * | [!CX!] ZCX_BC_TABLE_INTROSPECTOR * +-------------------------------------------------------------------------------------- method get_xml_rendition. *-- object references data: lo_ixml_factory type ref to if_ixml, lo_stream_factory type ref to if_ixml_stream_factory, lo_ostream type ref to if_ixml_ostream, lo_renderer type ref to if_ixml_renderer. *-- local variables data: lv_error_msg type string. *-- constants data: lc_ampersand type string value '&'. if xml_document_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. *-- get reference to iXML factory object lo_ixml_factory = cl_ixml=>create( ). *-- get stream factory lo_stream_factory = lo_ixml_factory->create_stream_factory( ). *-- create table-based output stream lo_ostream = lo_stream_factory->create_ostream_itable( ex_xml_table ). *-- create renderer and set options lo_renderer = lo_ixml_factory->create_renderer( ostream = lo_ostream document = xml_document_ref ). call method lo_renderer->set_no_escaping exporting no_escaping = lc_ampersand. call method lo_renderer->set_normalizing( ). *-- render document lo_renderer->render( ). endmethod. "get_xml_rendition * ---------------------------------------------------------------------------------------+ * | Instance Public Method ZCL_BC_TABLE_INTROSPECTOR->GET_XML_SOLIX_RENDITION * +-------------------------------------------------------------------------------------------------+ * | [<---] EX_XML_SOLIX_TABLE TYPE SOLIX_TAB * | [!CX!] ZCX_BC_TABLE_INTROSPECTOR * +-------------------------------------------------------------------------------------- method get_xml_solix_rendition. *-- object references data: lo_ixml_factory type ref to if_ixml, lo_stream_factory type ref to if_ixml_stream_factory, lo_ostream type ref to if_ixml_ostream, lo_renderer type ref to if_ixml_renderer, lo_root_exc type ref to cx_bcs. *-- internal table defintion data: lt_solix type solix_tab. *-- local variables data: lv_xml_xstring type xstring, lv_string type string, lv_error_msg type string. *-- constants data: lc_ampersand type string value '&'. if xml_document_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. *-- get reference to iXML factory object lo_ixml_factory = cl_ixml=>create( ). *-- get stream factory lo_stream_factory = lo_ixml_factory->create_stream_factory( ). *-- create xstring-based output stream lo_ostream = lo_stream_factory->create_ostream_xstring( lv_xml_xstring ). *-- create renderer and set options lo_renderer = lo_ixml_factory->create_renderer( ostream = lo_ostream document = xml_document_ref ). call method lo_renderer->set_no_escaping exporting no_escaping = lc_ampersand. call method lo_renderer->set_normalizing( ). *-- render document lo_renderer->render( ). *-- convert to solix tab try. cl_bcs_convert=>xstring_to_solix( exporting iv_xstring = lv_xml_xstring receiving 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_xml_solix_table[] = lt_solix[]. endmethod. "get_solix_rendition * ---------------------------------------------------------------------------------------+ * | 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_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 . 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. "normalize_line_format * ---------------------------------------------------------------------------------------+ * | 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. "populate_formatted_header * ---------------------------------------------------------------------------------------+ * | 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_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. "populate_formatted_table * ---------------------------------------------------------------------------------------+ * | 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_ddic_name type string, 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. call method get_ddic_name exporting im_component = ls_component im_point_header_to_ddic = im_point_header_to_ddic importing ex_name = lv_ddic_name. = lv_ddic_name. endloop. endmethod. "populate_header * ---------------------------------------------------------------------------------------+ * | 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. "populate_table * ---------------------------------------------------------------------------------------+ * | Static Private Method ZCL_BC_TABLE_INTROSPECTOR=>POPULATE_XML_DOCUMENT * +-------------------------------------------------------------------------------------------------+ * | [--->] IM_USE_HEADER_RECORD TYPE ABAP_BOOL(optional) * | [--->] IM_POINT_HEADER_TO_DDIC TYPE ABAP_BOOL(optional) * | [--->] IM_FORMAT_TIME TYPE ABAP_BOOL(optional) * | [--->] IM_FORMAT_DATE TYPE ABAP_BOOL(optional) * | [--->] IM_AUTHOR TYPE STRING(optional) * | [--->] IM_SHEET_NAME TYPE STRING(optional) * | [--->] IM_FREEZE_HEADER TYPE ABAP_BOOL(optional) * | [--->] IM_HEADER_COLOR TYPE TY_COLOR(optional) * | [--->] IM_HEADER_HEIGHT TYPE I(optional) * | [--->] IM_STRING_CELL_WIDTH TYPE I(optional) * | [--->] IM_POINTS_FACTOR TYPE I(optional) * | [--->] IM_XML_TABLE_REF TYPE REF TO DATA * | [<---] EX_XML_DOCUMENT_REF TYPE REF TO IF_IXML_DOCUMENT * | [!CX!] ZCX_BC_TABLE_INTROSPECTOR * +-------------------------------------------------------------------------------------- method populate_xml_document. *-- type pools type-pools: ixml. *-- object references data: lo_ixml_factory type ref to if_ixml, lo_excel_pi type ref to if_ixml_pi_parsed, lo_document type ref to if_ixml_document, lo_element_root type ref to if_ixml_element, lo_element_worksheet type ref to if_ixml_element, lo_element_properties type ref to if_ixml_element, lo_element_options type ref to if_ixml_element, lo_element_selected type ref to if_ixml_element, lo_element_freezepanes type ref to if_ixml_element, lo_element_frozennosplit type ref to if_ixml_element, lo_element_splithorizontal type ref to if_ixml_element, lo_element_toprowbottompane type ref to if_ixml_element, lo_element_activepane type ref to if_ixml_element, lo_ns_attribute type ref to if_ixml_attribute, lo_styles type ref to if_ixml_element, lo_style type ref to if_ixml_element, lo_format type ref to if_ixml_element, lo_table type ref to if_ixml_element, lo_column type ref to if_ixml_element, lo_row type ref to if_ixml_element, lo_cell type ref to if_ixml_element, lo_data type ref to if_ixml_element, lo_struct_descr type ref to cl_abap_structdescr, lo_table_descr type ref to cl_abap_tabledescr, lo_elemdescr type ref to cl_abap_elemdescr, lo_root_exc type ref to cx_root. *-- internal table defintion data: lt_components type cl_abap_structdescr=>component_table. *-- structure defintion data: ls_component type abap_componentdescr. *-- local variables data: lv_field_type type string, lv_field_value type string, lv_time_internal type syuzeit, lv_time_external type string, lv_date_internal type sydatum, lv_date_external type string, lv_color type string, lv_header_height type string, lv_author type string, lv_typekind type abap_typekind, lv_style_id type string, lv_format_code type string, lv_error_msg type string, lv_sheet_name type string, lv_column_width type string, lv_output_length type i, lv_ddic_length type i, lv_actual_length type i, lv_ddic_name type string. *-- constants constants: lc_max_column_width type i value 500. *-- field symbols field-symbols: type standard table, type any, type any. if im_xml_table_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. *-- get reference to iXML factory object lo_ixml_factory = cl_ixml=>create( ). *-- create DOM-based XML document lo_document = lo_ixml_factory->create_document( ). *-- create processing instruction lo_excel_pi = lo_document->create_pi_parsed( name = 'mso-application' ). lo_excel_pi->set_attribute( name = 'progid' value = 'Excel.Sheet' ). lo_document->append_child( lo_excel_pi ). *-- create workbook root element lo_element_root = lo_document->create_simple_element( name = 'Workbook' parent = lo_document ). lo_element_root->set_attribute( name = 'xmlns' value = 'urn:schemas-microsoft-com:office:spreadsheet' ). lo_ns_attribute = lo_document->create_namespace_decl( name = 'ss' prefix = 'xmlns' uri = 'urn:schemas-microsoft-com:office:spreadsheet' ). lo_element_root->set_attribute_node( lo_ns_attribute ). lo_ns_attribute = lo_document->create_namespace_decl( name = 'x' prefix = 'xmlns' uri = 'urn:schemas-microsoft-com:office:excel' ). lo_element_root->set_attribute_node( lo_ns_attribute ). *-- create document properties element lo_element_properties = lo_document->create_simple_element( name = 'DocumentProperties' parent = lo_element_root ). lo_element_properties->set_attribute( name = 'xmlns' value = 'urn:schemas-microsoft-com:office:office' ). lv_author = im_author. if lv_author is initial. lv_author = sy-uname. endif. lo_document->create_simple_element( name = 'Author' value = lv_author parent = lo_element_properties ). *-- create styles element lo_styles = lo_document->create_simple_element( name = 'Styles' parent = lo_element_root ). *-- header style if im_use_header_record eq abap_true. lo_style = lo_document->create_simple_element( name = 'Style' parent = lo_styles ). lo_style->set_attribute_ns( name = 'ID' prefix = 'ss' value = 'Header' ). lo_format = lo_document->create_simple_element( name = 'Font' parent = lo_style ). lo_format->set_attribute_ns( name = 'Bold' prefix = 'ss' value = '1' ). case im_header_color. when zcl_bc_table_introspector=>e_color-standard. lv_color = '#C5D9F1'. when zcl_bc_table_introspector=>e_color-none. lv_color = ''. when others. lv_color = ''. endcase. if lv_color is not initial. lo_format = lo_document->create_simple_element( name = 'Interior' parent = lo_style ). lo_format->set_attribute_ns( name = 'Color' prefix = 'ss' value = lv_color ). lo_format->set_attribute_ns( name = 'Pattern' prefix = 'ss' value = 'Solid' ). endif. lo_format = lo_document->create_simple_element( name = 'Alignment' parent = lo_style ). lo_format->set_attribute_ns( name = 'Vertical' prefix = 'ss' value = 'Bottom' ). lo_format->set_attribute_ns( name = 'WrapText' prefix = 'ss' value = '1' ). endif. *-- body style lo_style = lo_document->create_simple_element( name = 'Style' parent = lo_styles ). lo_style->set_attribute_ns( name = 'ID' prefix = 'ss' value = 'Body' ). lo_format = lo_document->create_simple_element( name = 'Alignment' parent = lo_style ). lo_format->set_attribute_ns( name = 'Vertical' prefix = 'ss' value = 'Bottom' ). lo_format->set_attribute_ns( name = 'WrapText' prefix = 'ss' value = '1' ). *-- begin table analysis assign im_xml_table_ref->* to . try. lo_table_descr ?= cl_abap_tabledescr=>describe_by_data_ref( im_xml_table_ref ). 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( ). *-- create style ids for each column, setting the appropriate format loop at lt_components into ls_component. *-- create style id based on component type lv_style_id = ls_component-name. try. lo_elemdescr ?= 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. *-- create new style element lo_style = lo_document->create_simple_element( name = 'Style' parent = lo_styles ). *-- set style attributes ss:ID lo_style->set_attribute_ns( name = 'ID' prefix = 'ss' value = lv_style_id ). *-- create new number format element lo_format = lo_document->create_simple_element( name = 'NumberFormat' parent = lo_style ). lv_format_code = '@'. *-- set number format attribute ss:format lo_format->set_attribute_ns( name = 'Format' prefix = 'ss' value = lv_format_code ). endloop. *-- create worksheet element lo_element_worksheet = lo_document->create_simple_element( name = 'Worksheet' parent = lo_element_root ). lv_sheet_name = im_sheet_name. if lv_sheet_name is initial. lv_sheet_name = 'Sheet1'. endif. lo_element_worksheet->set_attribute_ns( name = 'Name' prefix = 'ss' value = lv_sheet_name ). lo_table = lo_document->create_simple_element( name = 'Table' parent = lo_element_worksheet ). lo_table->set_attribute_ns( name = 'FullColumns' prefix = 'x' value = '1' ). lo_table->set_attribute_ns( name = 'FullRows' prefix = 'x' value = '1' ). *-- loop thru components to build set of column elements loop at lt_components into ls_component. lo_column = lo_document->create_simple_element( name = 'Column' parent = lo_table ). lv_style_id = ls_component-name. *-- set style id to name of field lo_column->set_attribute_ns( name = 'StyleID' prefix = 'ss' value = lv_style_id ). call method get_ddic_name exporting im_component = ls_component im_point_header_to_ddic = im_point_header_to_ddic importing ex_name = lv_ddic_name. try. lo_elemdescr ?= 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. *-- get output length if lo_elemdescr->output_length = 0. lv_output_length = im_string_cell_width. else. lv_output_length = lo_elemdescr->output_length. endif. *-- get ddic length lv_ddic_length = strlen( lv_ddic_name ). *-- get actual length if im_use_header_record eq abap_true and lv_ddic_length gt lv_output_length. lv_actual_length = lv_ddic_length. else. lv_actual_length = lv_output_length. endif. lv_column_width = lv_actual_length * im_points_factor. if lv_column_width gt lc_max_column_width. lv_column_width = lc_max_column_width. endif. condense lv_column_width no-gaps. lo_column->set_attribute_ns( name = 'Width' prefix = 'ss' value = lv_column_width ). endloop. *-- create header record if im_use_header_record = abap_true. lo_row = lo_document->create_simple_element( name = 'Row' parent = lo_table ). *-- set header record height if im_header_height is not initial. lv_header_height = im_header_height * im_points_factor. condense lv_header_height. lo_row->set_attribute_ns( name = 'Height' prefix = 'ss' value = lv_header_height ). else. lo_row->set_attribute_ns( name = 'AutoFitHeight' prefix = 'ss' value = '1' ). endif. *-- iterate thru components to build header loop at lt_components into ls_component. *-- create header cell element lo_cell = lo_document->create_simple_element( name = 'Cell' parent = lo_row ). *-- set style lo_cell->set_attribute_ns( name = 'StyleID' prefix = 'ss' value = 'Header' ). *-- get ddic name call method get_ddic_name exporting im_component = ls_component im_point_header_to_ddic = im_point_header_to_ddic importing ex_name = lv_ddic_name. *-- set header cell value lo_data = lo_document->create_simple_element( name = 'Data' value = lv_ddic_name parent = lo_cell ). lo_data->set_attribute_ns( name = 'Type' prefix = 'ss' value = 'String' ). endloop. endif. *-- iterate thru table records loop at assigning . lo_row = lo_document->create_simple_element( name = 'Row' parent = lo_table ). *-- autofit height lo_row->set_attribute_ns( name = 'AutoFitHeight' prefix = 'ss' value = '1' ). lt_components = lo_struct_descr->get_components( ). *-- for each record, iterate thru components and build cell elements loop at lt_components into ls_component. lo_cell = lo_document->create_simple_element( name = 'Cell' parent = lo_row ). lo_cell->set_attribute_ns( name = 'StyleID' prefix = 'ss' value = 'Body' ). assign component ls_component-name of structure to . lv_typekind = cl_abap_elemdescr=>get_data_type_kind( ). case lv_typekind. when cl_abap_typedescr=>typekind_time. lv_field_type = 'String'. lv_field_value = . if im_format_time eq abap_true. lv_time_internal = lv_field_value. try. call method cl_abap_timefm=>conv_time_int_to_ext exporting time_int = lv_time_internal importing time_ext = lv_time_external. lv_field_value = lv_time_external. catch cx_parameter_invalid_range. clear lv_field_value. endtry. endif. when cl_abap_typedescr=>typekind_date. lv_field_type = 'String'. lv_field_value = . if im_format_date eq abap_true. lv_date_internal = lv_field_value. try. call method cl_abap_datfm=>conv_date_int_to_ext exporting im_datint = lv_date_internal importing ex_datext = lv_date_external. lv_field_value = lv_date_external. catch cx_abap_datfm_format_unknown. clear lv_field_value. endtry. endif. when cl_abap_typedescr=>typekind_string or cl_abap_typedescr=>typekind_char. lv_field_type = 'String'. lv_field_value = . when cl_abap_typedescr=>typekind_num or cl_abap_typedescr=>typekind_packed or cl_abap_typedescr=>typekind_int or cl_abap_typedescr=>typekind_float. lv_field_type = 'Number'. lv_field_value = . call function 'CLOI_PUT_SIGN_IN_FRONT' changing value = lv_field_value. when others. lv_field_type = 'String'. lv_field_value = . endcase. shift lv_field_value right deleting trailing space. shift lv_field_value left deleting leading space. *-- set field data lo_data = lo_document->create_simple_element( name = 'Data' value = lv_field_value parent = lo_cell ). *-- set field type lo_data->set_attribute_ns( name = 'Type' prefix = 'ss' value = lv_field_type ). endloop. endloop. *-- create worksheet option element if im_use_header_record eq abap_true and im_freeze_header eq abap_true. lo_element_options = lo_document->create_simple_element( name = 'WorksheetOptions' parent = lo_element_worksheet ). lo_element_options->set_attribute( name = 'xmlns' value = 'urn:schemas-microsoft-com:office:excel' ). lo_element_selected = lo_document->create_simple_element( name = 'Selected' parent = lo_element_options ). lo_element_freezepanes = lo_document->create_simple_element( name = 'FreezePanes' parent = lo_element_options ). lo_element_frozennosplit = lo_document->create_simple_element( name = 'FrozenNoSplit' parent = lo_element_options ). lo_element_splithorizontal = lo_document->create_simple_element( name = 'SplitHorizontal' value = '1' parent = lo_element_options ). lo_element_toprowbottompane = lo_document->create_simple_element( name = 'TopRowBottomPane' value = '1' parent = lo_element_options ). lo_element_activepane = lo_document->create_simple_element( name = 'ActivePane' value = '2' parent = lo_element_options ). endif. ex_xml_document_ref = lo_document. endmethod. "POPULATE_RENDERED_XML_TABLE * ---------------------------------------------------------------------------------------+ * | Static Private Method ZCL_BC_TABLE_INTROSPECTOR=>POPULATE_XML_TABLE * +-------------------------------------------------------------------------------------------------+ * | [--->] IM_TABLE TYPE ANY TABLE * | [--->] IM_XML_STRUCT_DESCR TYPE REF TO CL_ABAP_STRUCTDESCR * | [<---] EX_XML_TABLE_REF TYPE REF TO DATA * | [!CX!] ZCX_BC_TABLE_INTROSPECTOR * +-------------------------------------------------------------------------------------- method populate_xml_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_struct_descr type ref to cl_abap_structdescr, lo_table_descr type ref to cl_abap_tabledescr, lo_elem_objectdescr type ref to cl_abap_objectdescr, lo_table_objectdescr type ref to cl_abap_objectdescr, lo_root_exc type ref to cx_root. *-- internal table defintion data: lt_components type cl_abap_structdescr=>component_table, lt_xml_components type cl_abap_structdescr=>component_table, lt_tlines type tline_t, lt_text type string_table. *-- structure defintion data: ls_component_temp like line of lt_components, ls_component like line of lt_components, ls_tline type tline. *-- local variables data: lv_text type string, lv_num_lines type i, lv_index type i, lv_error_msg type string. *-- constants data: lc_xml_newline type string value ' '. *-- field symbols field-symbols: type standard table, type any, type standard table, type any, type standard table, like line of lt_components, type any, type any. *-- prepare source table structure 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 structure (where long text modelled as string) lt_components = im_xml_struct_descr->get_components( ). lo_elem_objectdescr ?= cl_abap_typedescr=>describe_by_name( 'cl_abap_elemdescr' ). lo_table_objectdescr ?= cl_abap_typedescr=>describe_by_name( 'cl_abap_tabledescr' ). loop at lt_components into ls_component. if lo_elem_objectdescr->applies_to( ls_component-type ) eq 'X'. append ls_component to lt_xml_components. elseif lo_table_objectdescr->applies_to( ls_component-type ) eq 'X'. ls_component_temp-type = cl_abap_elemdescr=>get_string( ). ls_component_temp-name = ls_component-name. append ls_component_temp to lt_xml_components. endif. endloop. try. lo_struct_descr = cl_abap_structdescr=>create( lt_xml_components ). lo_table_descr = cl_abap_tabledescr=>create( lo_struct_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. 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 lo_struct_descr. assign lo_dst_struct_ref->* to . *-- copy data between tables loop at into . clear: . loop at lt_components assigning . if lo_elem_objectdescr->applies_to( -type ) eq 'X'. *-- if type kind is element, do direct copy assign component -name of structure to . assign component -name of structure to . = . elseif lo_table_objectdescr->applies_to( -type ) eq 'X'. *-- if type kind is table, map long text to string and then copy assign component -name of structure to . assign component -name of structure to . lt_tlines[] = . check lt_tlines[] is not initial. clear lv_text. lv_num_lines = lines( lt_tlines ). lv_index = 1. while lv_index lt lv_num_lines. read table lt_tlines index lv_index into ls_tline. concatenate lv_text ls_tline-tdline lc_xml_newline into lv_text. add 1 to lv_index. endwhile. read table lt_tlines index lv_index into ls_tline. concatenate lv_text ls_tline-tdline into lv_text. = lv_text. endif. endloop. append to . endloop. ex_xml_table_ref = lo_dst_table_ref. endmethod. "populate_xml_table * ---------------------------------------------------------------------------------------+ * | 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_table_objectdescr type ref to cl_abap_objectdescr, lo_structdescr type ref to cl_abap_structdescr, lo_tabledescr 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, lt_inner_components type cl_abap_structdescr=>component_table, lt_components_temp type cl_abap_structdescr=>component_table, lt_tline type tline_t. *-- 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' ). lo_table_objectdescr ?= cl_abap_typedescr=>describe_by_name( 'cl_abap_tabledescr' ). *-- adjust component collection based on selected columns (* or space defaults to all columns) clear: ls_component_temp. if ls_component-as_include ne 'X' and im_columns ns '*' and im_columns is not initial. move ls_component to ls_component_temp. concatenate '(\W|^)' ls_component_temp-name '(\W|$)' into ls_component_temp-name. find regex ls_component_temp-name in im_columns ignoring case. check sy-subrc eq 0. endif. *-- 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. 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. elseif lo_table_objectdescr->applies_to( ls_component-type ) eq 'X'. try. *-- cast to cl_abap_tabledescr, discard if table is not long text (tline = tdformat, tdline) lo_tabledescr ?= 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. if lo_tabledescr->applies_to_data( lt_tline ) eq 'X'. append ls_component to lt_components_filtered. endif. endif. endloop. *-- return new flat filtered component structure ex_components[] = lt_components_filtered[]. endmethod. "recursive_filter_columns ENDCLASS.