*"* local class implementation for public class *"* use this source file for the implementation part of *"* local helper classes *"* use this source file for any type declarations (class *"* definitions, interfaces or data types) you need for method *"* implementation or private method's signature *"* use this source file for any macro definitions you need *"* in the implementation part of the class CLASS lcl_excel_common_test DEFINITION DEFERRED. CLASS zcl_excel_common DEFINITION LOCAL FRIENDS lcl_excel_common_test. *----------------------------------------------------------------------* * CLASS lcl_Excel_Common_Test DEFINITION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS lcl_excel_common_test DEFINITION FOR TESTING "#AU Risk_Level Harmless . "#AU Duration Short *?<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0"> *?<asx:values> *?<TESTCLASS_OPTIONS> *?<TEST_CLASS>lcl_Excel_Common_Test *?</TEST_CLASS> *?<TEST_MEMBER>f_Cut *?</TEST_MEMBER> *?<OBJECT_UNDER_TEST>ZCL_EXCEL_COMMON *?</OBJECT_UNDER_TEST> *?<OBJECT_IS_LOCAL/> *?<GENERATE_FIXTURE>X *?</GENERATE_FIXTURE> *?<GENERATE_CLASS_FIXTURE>X *?</GENERATE_CLASS_FIXTURE> *?<GENERATE_INVOCATION>X *?</GENERATE_INVOCATION> *?<GENERATE_ASSERT_EQUAL>X *?</GENERATE_ASSERT_EQUAL> *?</TESTCLASS_OPTIONS> *?</asx:values> *?</asx:abap> PRIVATE SECTION. * ================ DATA: lx_excel TYPE REF TO zcx_excel, f_cut TYPE REF TO zcl_excel_common. "class under test CLASS-METHODS: class_setup. CLASS-METHODS: class_teardown. METHODS: setup. METHODS: teardown. * METHODS: char2hex FOR TESTING. METHODS: convert_column2alpha FOR TESTING. METHODS: convert_column2int FOR TESTING. METHODS: date_to_excel_string FOR TESTING. METHODS: encrypt_password FOR TESTING. METHODS: excel_string_to_date FOR TESTING. METHODS: excel_string_to_time FOR TESTING. * METHODS: number_to_excel_string FOR TESTING. METHODS: time_to_excel_string FOR TESTING. METHODS: split_file FOR TESTING. METHODS: convert_range2column_a_row FOR TESTING. METHODS: describe_structure FOR TESTING. ENDCLASS. "lcl_Excel_Common_Test *----------------------------------------------------------------------* * CLASS lcl_Excel_Common_Test IMPLEMENTATION *----------------------------------------------------------------------* * *----------------------------------------------------------------------* CLASS lcl_excel_common_test IMPLEMENTATION. * =========================================== METHOD class_setup. * =================== ENDMETHOD. "class_Setup METHOD class_teardown. * ====================== ENDMETHOD. "class_Teardown METHOD setup. * ============= CREATE OBJECT f_cut. ENDMETHOD. "setup METHOD teardown. * ================ ENDMETHOD. "teardown METHOD convert_column2alpha. * ============================ DATA ep_column TYPE zexcel_cell_column_alpha. * Test 1. Simple test TRY. ep_column = zcl_excel_common=>convert_column2alpha( 1 ). zcl_excel_common=>assert_equals( act = ep_column exp = 'A' msg = 'Wrong column conversion' level = if_aunit_constants=>critical ). CATCH zcx_excel INTO lx_excel. zcl_excel_common=>fail( msg = 'unexpected exception' level = if_aunit_constants=>critical " Error Severity ). ENDTRY. * Test 2. Max column for OXML #16,384 = XFD TRY. ep_column = zcl_excel_common=>convert_column2alpha( 16384 ). zcl_excel_common=>assert_equals( act = ep_column exp = 'XFD' msg = 'Wrong column conversion' level = if_aunit_constants=>critical ). CATCH zcx_excel INTO lx_excel. zcl_excel_common=>fail( msg = 'unexpected exception' level = if_aunit_constants=>critical " Error Severity ). ENDTRY. * Test 3. Index 0 is out of bounds TRY. ep_column = zcl_excel_common=>convert_column2alpha( 0 ). zcl_excel_common=>assert_equals( act = ep_column exp = 'A' ). CATCH zcx_excel INTO lx_excel. zcl_excel_common=>assert_equals( act = lx_excel->error exp = 'Index out of bounds' msg = 'Colum index 0 is out of bounds, min column index is 1' level = if_aunit_constants=>fatal ). ENDTRY. * Test 4. Exception should be thrown index out of bounds TRY. ep_column = zcl_excel_common=>convert_column2alpha( 16385 ). zcl_excel_common=>assert_differs( act = ep_column exp = 'XFE' msg = 'Colum index 16385 is out of bounds, max column index is 16384' level = if_aunit_constants=>fatal ). CATCH zcx_excel INTO lx_excel. zcl_excel_common=>assert_equals( act = lx_excel->error exp = 'Index out of bounds' msg = 'Wrong exception is thrown' level = if_aunit_constants=>tolerable ). ENDTRY. ENDMETHOD. "convert_Column2alpha METHOD convert_column2int. * ========================== DATA ep_column TYPE zexcel_cell_column. * Test 1. Basic test TRY. ep_column = zcl_excel_common=>convert_column2int( 'A' ). zcl_excel_common=>assert_equals( act = ep_column exp = 1 msg = 'Wrong column conversion' level = if_aunit_constants=>critical ). CATCH zcx_excel INTO lx_excel. zcl_excel_common=>fail( msg = 'unexpected exception' level = if_aunit_constants=>critical " Error Severity ). ENDTRY. * Test 2. Max column TRY. ep_column = zcl_excel_common=>convert_column2int( 'XFD' ). zcl_excel_common=>assert_equals( act = ep_column exp = 16384 msg = 'Wrong column conversion' level = if_aunit_constants=>critical ). CATCH zcx_excel INTO lx_excel. zcl_excel_common=>fail( msg = 'unexpected exception' level = if_aunit_constants=>critical " Error Severity ). ENDTRY. * Test 3. Out of bounds TRY. ep_column = zcl_excel_common=>convert_column2int( '' ). zcl_excel_common=>assert_differs( act = ep_column exp = '0' msg = 'Wrong column conversion' level = if_aunit_constants=>critical ). CATCH zcx_excel INTO lx_excel. zcl_excel_common=>assert_equals( act = lx_excel->error exp = 'Unable to interpret input as column' msg = 'Colum name should be a valid string' level = if_aunit_constants=>fatal ). ENDTRY. * Test 4. Out of bounds TRY. ep_column = zcl_excel_common=>convert_column2int( 'XFE' ). zcl_excel_common=>assert_differs( act = ep_column exp = 16385 msg = 'Wrong column conversion' level = if_aunit_constants=>critical ). CATCH zcx_excel INTO lx_excel. zcl_excel_common=>assert_equals( act = lx_excel->error exp = 'Index out of bounds' msg = 'Colum XFE is out of range' level = if_aunit_constants=>fatal ). ENDTRY. ENDMETHOD. "convert_Column2int METHOD date_to_excel_string. * ============================ DATA ep_value TYPE zexcel_cell_value. * Test 1. Basic conversion TRY. ep_value = zcl_excel_common=>date_to_excel_string( '19000101' ). zcl_excel_common=>assert_equals( act = ep_value exp = 1 msg = 'Wrong date conversion' level = if_aunit_constants=>critical ). CATCH zcx_excel INTO lx_excel. zcl_excel_common=>fail( msg = 'unexpected exception' level = if_aunit_constants=>critical " Error Severity ). ENDTRY. * Check around the "Excel Leap Year" 1900 TRY. ep_value = zcl_excel_common=>date_to_excel_string( '19000228' ). zcl_excel_common=>assert_equals( act = ep_value exp = 59 msg = 'Wrong date conversion' level = if_aunit_constants=>critical ). CATCH zcx_excel INTO lx_excel. zcl_excel_common=>fail( msg = 'unexpected exception' level = if_aunit_constants=>critical " Error Severity ). ENDTRY. TRY. ep_value = zcl_excel_common=>date_to_excel_string( '19000301' ). zcl_excel_common=>assert_equals( act = ep_value exp = 61 msg = 'Wrong date conversion' level = if_aunit_constants=>critical ). CATCH zcx_excel INTO lx_excel. zcl_excel_common=>fail( msg = 'unexpected exception' level = if_aunit_constants=>critical " Error Severity ). ENDTRY. * Test 2. Basic conversion TRY. ep_value = zcl_excel_common=>date_to_excel_string( '99991212' ). zcl_excel_common=>assert_equals( act = ep_value exp = 2958446 msg = 'Wrong date conversion' level = if_aunit_constants=>critical ). CATCH zcx_excel INTO lx_excel. zcl_excel_common=>fail( msg = 'unexpected exception' level = if_aunit_constants=>critical " Error Severity ). ENDTRY. * Test 3. Initial date TRY. DATA: lv_date TYPE d. ep_value = zcl_excel_common=>date_to_excel_string( lv_date ). zcl_excel_common=>assert_equals( act = ep_value exp = '' msg = 'Wrong date conversion' level = if_aunit_constants=>critical ). CATCH zcx_excel INTO lx_excel. zcl_excel_common=>fail( msg = 'unexpected exception' level = if_aunit_constants=>critical " Error Severity ). ENDTRY. * Test 2. Basic conversion TRY. DATA exp_value TYPE zexcel_cell_value VALUE 0. ep_value = zcl_excel_common=>date_to_excel_string( '18991231' ). zcl_excel_common=>assert_differs( act = ep_value exp = exp_value msg = 'Wrong date conversion' level = if_aunit_constants=>critical ). CATCH zcx_excel INTO lx_excel. zcl_excel_common=>assert_equals( act = lx_excel->error exp = 'Index out of bounds' msg = 'Dates prior of 1900 are not available in excel' level = if_aunit_constants=>critical ). ENDTRY. ENDMETHOD. "date_To_Excel_String METHOD encrypt_password. * ======================== DATA lv_encrypted_pwd TYPE zexcel_aes_password. TRY. lv_encrypted_pwd = zcl_excel_common=>encrypt_password( 'test' ). zcl_excel_common=>assert_equals( act = lv_encrypted_pwd exp = 'CBEB' msg = 'Wrong password encryption' level = if_aunit_constants=>critical ). CATCH zcx_excel INTO lx_excel. zcl_excel_common=>fail( msg = 'unexpected exception' level = if_aunit_constants=>critical " Error Severity ). ENDTRY. ENDMETHOD. "encrypt_Password METHOD excel_string_to_date. * ============================ DATA ep_value TYPE d. * Test 1. Simple test -> ABAP Manage also date prior of 1900 TRY. ep_value = zcl_excel_common=>excel_string_to_date( '0' ). zcl_excel_common=>assert_equals( act = ep_value exp = '18991231' msg = 'Wrong date conversion' level = if_aunit_constants=>tolerable ). CATCH zcx_excel INTO lx_excel. zcl_excel_common=>fail( msg = 'unexpected exception' level = if_aunit_constants=>critical " Error Severity ). ENDTRY. * Check around the "Excel Leap Year" 1900 TRY. ep_value = zcl_excel_common=>excel_string_to_date( '59' ). zcl_excel_common=>assert_equals( act = ep_value exp = '19000228' msg = 'Wrong date conversion' level = if_aunit_constants=>critical ). CATCH zcx_excel INTO lx_excel. zcl_excel_common=>fail( msg = 'unexpected exception' level = if_aunit_constants=>critical " Error Severity ). ENDTRY. TRY. ep_value = zcl_excel_common=>excel_string_to_date( '61' ). zcl_excel_common=>assert_equals( act = ep_value exp = '19000301' msg = 'Wrong date conversion' level = if_aunit_constants=>critical ). CATCH zcx_excel INTO lx_excel. zcl_excel_common=>fail( msg = 'unexpected exception' level = if_aunit_constants=>critical " Error Severity ). ENDTRY. * Test 2. Simple test TRY. ep_value = zcl_excel_common=>excel_string_to_date( '1' ). zcl_excel_common=>assert_equals( act = ep_value exp = '19000101' msg = 'Wrong date conversion' level = if_aunit_constants=>critical ). CATCH zcx_excel INTO lx_excel. zcl_excel_common=>fail( msg = 'unexpected exception' level = if_aunit_constants=>critical " Error Severity ). ENDTRY. * Test 3. Index 0 is out of bounds TRY. ep_value = zcl_excel_common=>excel_string_to_date( '2958446' ). zcl_excel_common=>assert_equals( act = ep_value exp = '99991212' msg = 'Wrong date conversion' level = if_aunit_constants=>critical ). CATCH zcx_excel INTO lx_excel. zcl_excel_common=>fail( msg = 'unexpected exception' level = if_aunit_constants=>critical " Error Severity ). ENDTRY. * Test 4. Exception should be thrown index out of bounds TRY. ep_value = zcl_excel_common=>excel_string_to_date( '2958447' ). zcl_excel_common=>assert_differs( act = ep_value exp = '99991212' msg = 'Wrong date conversion' level = if_aunit_constants=>fatal ). zcl_excel_common=>assert_differs( act = ep_value exp = '00000000' msg = 'Wrong date conversion' level = if_aunit_constants=>fatal ). CATCH zcx_excel INTO lx_excel. zcl_excel_common=>assert_equals( act = lx_excel->error exp = 'Index out of bounds' msg = 'Wrong exception is thrown' level = if_aunit_constants=>tolerable ). ENDTRY. ENDMETHOD. "excel_String_To_Date METHOD excel_string_to_time. * ============================ DATA ep_value TYPE t. * Test 1. Simple test TRY. ep_value = zcl_excel_common=>excel_string_to_time( '0' ). zcl_excel_common=>assert_equals( act = ep_value exp = '000000' msg = 'Wrong date conversion' level = if_aunit_constants=>tolerable ). CATCH zcx_excel INTO lx_excel. zcl_excel_common=>fail( msg = 'unexpected exception' level = if_aunit_constants=>critical " Error Severity ). ENDTRY. * Test 2. Simple test TRY. ep_value = zcl_excel_common=>excel_string_to_time( '1' ). zcl_excel_common=>assert_equals( act = ep_value exp = '000000' msg = 'Wrong date conversion' level = if_aunit_constants=>critical ). CATCH zcx_excel INTO lx_excel. zcl_excel_common=>fail( msg = 'unexpected exception' level = if_aunit_constants=>critical " Error Severity ). ENDTRY. * Test 3. Simple test TRY. ep_value = zcl_excel_common=>excel_string_to_time( '0.99999' ). zcl_excel_common=>assert_equals( act = ep_value exp = '235959' msg = 'Wrong date conversion' level = if_aunit_constants=>critical ). CATCH zcx_excel INTO lx_excel. zcl_excel_common=>fail( msg = 'unexpected exception' level = if_aunit_constants=>critical " Error Severity ). ENDTRY. * Test 4. Also string greater than 1 should be managed TRY. ep_value = zcl_excel_common=>excel_string_to_time( '4.1' ). zcl_excel_common=>assert_equals( act = ep_value exp = '022400' msg = 'Wrong date conversion' level = if_aunit_constants=>critical ). CATCH zcx_excel INTO lx_excel. zcl_excel_common=>fail( msg = 'unexpected exception' level = if_aunit_constants=>critical " Error Severity ). ENDTRY. * Test 4. string is not a number TRY. ep_value = zcl_excel_common=>excel_string_to_time( 'NaN' ). zcl_excel_common=>assert_differs( act = ep_value exp = '000000' msg = 'Wrong date conversion' level = if_aunit_constants=>critical ). CATCH zcx_excel INTO lx_excel. zcl_excel_common=>assert_equals( act = lx_excel->error exp = 'Unable to interpret time' msg = 'Time should be a valid string' level = if_aunit_constants=>fatal ). ENDTRY. ENDMETHOD. "excel_String_To_Time METHOD time_to_excel_string. * ============================ DATA ep_value TYPE zexcel_cell_value. * Test 1. Basic conversion TRY. ep_value = zcl_excel_common=>time_to_excel_string( '000001' ). " A test directly in Excel returns the value 0.0000115740740740741000 zcl_excel_common=>assert_equals( act = ep_value exp = '0.0000115740740741' msg = 'Wrong date conversion' level = if_aunit_constants=>critical ). CATCH zcx_excel INTO lx_excel. zcl_excel_common=>fail( msg = 'unexpected exception' level = if_aunit_constants=>critical " Error Severity ). ENDTRY. * Test 2. Basic conversion TRY. ep_value = zcl_excel_common=>time_to_excel_string( '235959' ). " A test directly in Excel returns the value 0.9999884259259260000000 zcl_excel_common=>assert_equals( act = ep_value exp = '0.9999884259259260' msg = 'Wrong date conversion' level = if_aunit_constants=>critical ). CATCH zcx_excel INTO lx_excel. zcl_excel_common=>fail( msg = 'unexpected exception' level = if_aunit_constants=>critical " Error Severity ). ENDTRY. * Test 3. Initial date TRY. ep_value = zcl_excel_common=>time_to_excel_string( '000000' ). zcl_excel_common=>assert_equals( act = ep_value exp = '0' msg = 'Wrong date conversion' level = if_aunit_constants=>critical ). CATCH zcx_excel INTO lx_excel. zcl_excel_common=>fail( msg = 'unexpected exception' level = if_aunit_constants=>critical " Error Severity ). ENDTRY. * Test 2. Basic conversion TRY. ep_value = zcl_excel_common=>time_to_excel_string( '022400' ). zcl_excel_common=>assert_equals( act = ep_value exp = '0.1000000000000000' msg = 'Wrong date conversion' level = if_aunit_constants=>critical ). CATCH zcx_excel INTO lx_excel. zcl_excel_common=>fail( msg = 'unexpected exception' level = if_aunit_constants=>critical " Error Severity ). ENDTRY. ENDMETHOD. "time_To_Excel_String METHOD split_file. * ============================ DATA: ep_file TYPE text255, ep_extension TYPE char10, ep_dotextension TYPE char10. * Test 1. Basic conversion zcl_excel_common=>split_file( EXPORTING ip_file = 'filename.xml' IMPORTING ep_file = ep_file ep_extension = ep_extension ep_dotextension = ep_dotextension ). zcl_excel_common=>assert_equals( act = ep_file exp = 'filename' msg = 'Split filename failed' level = if_aunit_constants=>critical ). zcl_excel_common=>assert_equals( act = ep_extension exp = 'xml' msg = 'Split extension failed' level = if_aunit_constants=>critical ). zcl_excel_common=>assert_equals( act = ep_dotextension exp = '.xml' msg = 'Split extension failed' level = if_aunit_constants=>critical ). * Test 2. no extension zcl_excel_common=>split_file( EXPORTING ip_file = 'filename' IMPORTING ep_file = ep_file ep_extension = ep_extension ep_dotextension = ep_dotextension ). zcl_excel_common=>assert_equals( act = ep_file exp = 'filename' msg = 'Split filename failed' level = if_aunit_constants=>critical ). zcl_excel_common=>assert_equals( act = ep_extension exp = '' msg = 'Split extension failed' level = if_aunit_constants=>critical ). zcl_excel_common=>assert_equals( act = ep_dotextension exp = '' msg = 'Split extension failed' level = if_aunit_constants=>critical ). ENDMETHOD. "split_file METHOD convert_range2column_a_row. DATA: lv_range TYPE string. DATA: lv_column_start TYPE zexcel_cell_column_alpha, lv_column_end TYPE zexcel_cell_column_alpha, lv_row_start TYPE zexcel_cell_row, lv_row_end TYPE zexcel_cell_row, lv_sheet TYPE string. * a) input empty --> nothing to do zcl_excel_common=>convert_range2column_a_row( EXPORTING i_range = lv_range IMPORTING e_column_start = lv_column_start " Cell Column Start e_column_end = lv_column_end " Cell Column End e_row_start = lv_row_start " Cell Row e_row_end = lv_row_end " Cell Row e_sheet = lv_sheet " Title ). zcl_excel_common=>assert_equals( act = lv_column_start exp = '' msg = 'Conversion of range failed' level = if_aunit_constants=>critical ). zcl_excel_common=>assert_equals( act = lv_column_end exp = '' msg = 'Conversion of range failed' level = if_aunit_constants=>critical ). zcl_excel_common=>assert_equals( act = lv_row_start exp = '' msg = 'Conversion of range failed' level = if_aunit_constants=>critical ). zcl_excel_common=>assert_equals( act = lv_row_end exp = '' msg = 'Conversion of range failed' level = if_aunit_constants=>critical ). zcl_excel_common=>assert_equals( act = lv_sheet exp = '' msg = 'Conversion of range failed' level = if_aunit_constants=>critical ). * b) sheetname existing - starts with ' example 'Sheet 1'!$B$6:$D$13 lv_range = `'Sheet 1'!$B$6:$D$13`. zcl_excel_common=>convert_range2column_a_row( EXPORTING i_range = lv_range IMPORTING e_column_start = lv_column_start " Cell Column Start e_column_end = lv_column_end " Cell Column End e_row_start = lv_row_start " Cell Row e_row_end = lv_row_end " Cell Row e_sheet = lv_sheet " Title ). zcl_excel_common=>assert_equals( act = lv_column_start exp = 'B' msg = 'Conversion of range failed' level = if_aunit_constants=>critical ). zcl_excel_common=>assert_equals( act = lv_column_end exp = 'D' msg = 'Conversion of range failed' level = if_aunit_constants=>critical ). zcl_excel_common=>assert_equals( act = lv_row_start exp = '6' msg = 'Conversion of range failed' level = if_aunit_constants=>critical ). zcl_excel_common=>assert_equals( act = lv_row_end exp = '13' msg = 'Conversion of range failed' level = if_aunit_constants=>critical ). zcl_excel_common=>assert_equals( act = lv_sheet exp = 'Sheet 1' msg = 'Conversion of range failed' level = if_aunit_constants=>critical ). * c) sheetname existing - does not start with ' example Sheet1!$B$6:$D$13 lv_range = `Sheet1!B6:$D$13`. zcl_excel_common=>convert_range2column_a_row( EXPORTING i_range = lv_range IMPORTING e_column_start = lv_column_start " Cell Column Start e_column_end = lv_column_end " Cell Column End e_row_start = lv_row_start " Cell Row e_row_end = lv_row_end " Cell Row e_sheet = lv_sheet " Title ). zcl_excel_common=>assert_equals( act = lv_column_start exp = 'B' msg = 'Conversion of range failed' level = if_aunit_constants=>critical ). zcl_excel_common=>assert_equals( act = lv_column_end exp = 'D' msg = 'Conversion of range failed' level = if_aunit_constants=>critical ). zcl_excel_common=>assert_equals( act = lv_row_start exp = '6' msg = 'Conversion of range failed' level = if_aunit_constants=>critical ). zcl_excel_common=>assert_equals( act = lv_row_end exp = '13' msg = 'Conversion of range failed' level = if_aunit_constants=>critical ). zcl_excel_common=>assert_equals( act = lv_sheet exp = 'Sheet1' msg = 'Conversion of range failed' level = if_aunit_constants=>critical ). * d) no sheetname - just area example $B$6:$D$13 lv_range = `$B$6:D13`. zcl_excel_common=>convert_range2column_a_row( EXPORTING i_range = lv_range IMPORTING e_column_start = lv_column_start " Cell Column Start e_column_end = lv_column_end " Cell Column End e_row_start = lv_row_start " Cell Row e_row_end = lv_row_end " Cell Row e_sheet = lv_sheet " Title ). zcl_excel_common=>assert_equals( act = lv_column_start exp = 'B' msg = 'Conversion of range failed' level = if_aunit_constants=>critical ). zcl_excel_common=>assert_equals( act = lv_column_end exp = 'D' msg = 'Conversion of range failed' level = if_aunit_constants=>critical ). zcl_excel_common=>assert_equals( act = lv_row_start exp = '6' msg = 'Conversion of range failed' level = if_aunit_constants=>critical ). zcl_excel_common=>assert_equals( act = lv_row_end exp = '13' msg = 'Conversion of range failed' level = if_aunit_constants=>critical ). zcl_excel_common=>assert_equals( act = lv_sheet exp = '' msg = 'Conversion of range failed' level = if_aunit_constants=>critical ). ENDMETHOD. METHOD describe_structure. DATA: ls_test TYPE scarr. DATA: lo_structdescr TYPE REF TO cl_abap_structdescr. DATA: lt_structure TYPE ddfields. FIELD-SYMBOLS: <line> LIKE LINE OF lt_structure. " Test with DDIC Type lo_structdescr ?= cl_abap_structdescr=>describe_by_data( p_data = ls_test ). lt_structure = zcl_excel_common=>describe_structure( io_struct = lo_structdescr ). READ TABLE lt_structure ASSIGNING <line> INDEX 1. zcl_excel_common=>assert_equals( act = <line>-fieldname exp = 'MANDT' msg = 'Describe structure failed' level = if_aunit_constants=>critical ). " Test with local defined structure having DDIC and non DDIC elements TYPES: BEGIN OF t_test, carrid TYPE s_carr_id, carrname TYPE s_carrname, carrdesc TYPE string, END OF t_test. DATA: ls_ttest type t_test. lo_structdescr ?= cl_abap_structdescr=>describe_by_data( p_data = ls_ttest ). lt_structure = zcl_excel_common=>describe_structure( io_struct = lo_structdescr ). READ TABLE lt_structure ASSIGNING <line> INDEX 1. zcl_excel_common=>assert_equals( act = <line>-fieldname exp = 'CARRID' msg = 'Describe structure failed' level = if_aunit_constants=>critical ). ENDMETHOD. ENDCLASS. "lcl_Excel_Common_Test ABAP method ASSERT_DIFFERS. DATA: ls_seoclass TYPE seoclass. " Let see >=7.02 SELECT SINGLE * INTO ls_seoclass FROM seoclass WHERE clsname = 'CL_ABAP_UNIT_ASSERT'. IF sy-subrc = 0. CALL METHOD (ls_seoclass-clsname)=>assert_differs EXPORTING exp = exp act = act msg = msg level = level tol = tol quit = quit RECEIVING assertion_failed = assertion_failed. ELSE. " Let see >=7.00 or even lower SELECT SINGLE * INTO ls_seoclass FROM seoclass WHERE clsname = 'CL_AUNIT_ASSERT'. IF sy-subrc = 0. CALL METHOD (ls_seoclass-clsname)=>assert_differs EXPORTING exp = exp act = act msg = msg level = level tol = tol quit = quit RECEIVING assertion_failed = assertion_failed. ELSE. * We do nothing for now not supported ENDIF. ENDIF. endmethod. method ASSERT_EQUALS. DATA: ls_seoclass TYPE seoclass. " Let see >=7.02 SELECT SINGLE * INTO ls_seoclass FROM seoclass WHERE clsname = 'CL_ABAP_UNIT_ASSERT'. IF sy-subrc = 0. CALL METHOD (ls_seoclass-clsname)=>assert_equals EXPORTING exp = exp act = act msg = msg level = level tol = tol quit = quit ignore_hash_sequence = ignore_hash_sequence RECEIVING assertion_failed = assertion_failed. ELSE. " Let see >=7.00 or even lower SELECT SINGLE * INTO ls_seoclass FROM seoclass WHERE clsname = 'CL_AUNIT_ASSERT'. IF sy-subrc = 0. CALL METHOD (ls_seoclass-clsname)=>assert_equals EXPORTING exp = exp act = act msg = msg level = level tol = tol quit = quit ignore_hash_sequence = ignore_hash_sequence RECEIVING assertion_failed = assertion_failed. ELSE. * We do nothing for now not supported ENDIF. ENDIF. endmethod. method CHAR2HEX. IF o_conv IS NOT BOUND. o_conv = cl_abap_conv_out_ce=>create( endian = 'L' ignore_cerr = abap_true replacement = '#' ). ENDIF. CALL METHOD o_conv->reset( ). CALL METHOD o_conv->write( data = i_char ). r_hex+1 = o_conv->get_buffer( ). " x'65' must be x'0065' endmethod. method CONVERT_COLUMN2ALPHA. DATA: lo_conv TYPE REF TO cl_abap_conv_in_ce, lv_uccpi TYPE i, lv_text TYPE sychar02, lv_module TYPE int4, lv_column TYPE zexcel_cell_column. * Propagate zcx_excel if error occurs " issue #155 - less restrictive typing for ip_column lv_column = convert_column2int( ip_column ). " issue #155 - less restrictive typing for ip_column IF lv_column GT 16384 OR lv_column LT 1. RAISE EXCEPTION TYPE zcx_excel EXPORTING error = 'Index out of bounds'. ENDIF. WHILE lv_column GT 0. lv_module = ( lv_column - 1 ) MOD 26. lv_uccpi = 65 + lv_module. lv_column = ( lv_column - lv_module ) / 26. lv_text = cl_abap_conv_in_ce=>uccpi( lv_uccpi ). CONCATENATE lv_text ep_column INTO ep_column. ENDWHILE. endmethod. METHOD convert_column2int. *--------------------------------------------------------------------* * issue #230 - Pimp my Code * - Stefan Schmöcker, (done) 2012-12-29 * - ... * changes: renaming variables to naming conventions * removing unused variables * removing commented out code that is inactive for more then half a year * message made to support multilinguality * adding comments to explain what we are trying to achieve *--------------------------------------------------------------------* * issue#246 - error converting lower case column names * - Stefan Schmöcker, 2012-12-29 * changes: translating the correct variable to upper dase * adding missing exception if input is a number * that is out of bounds * adding missing exception if input contains * illegal characters like german umlauts *--------------------------------------------------------------------* DATA: lv_column TYPE zexcel_cell_column_alpha, lv_column_c TYPE char10, lv_column_s TYPE string, lv_errormessage TYPE string, " Can't pass '...'(abc) to exception-class lv_modulo TYPE i. *--------------------------------------------------------------------* * This module tries to identify which column a user wants to access * Numbers as input are just passed back, anything else will be converted * using EXCEL nomenclatura A = 1, AA = 27, ..., XFD = 16384 *--------------------------------------------------------------------* *--------------------------------------------------------------------* * Normalize input ( upper case , no gaps ) *--------------------------------------------------------------------* lv_column_c = ip_column. * TRANSLATE lv_column TO UPPER CASE. " Fix #246 TRANSLATE lv_column_c TO UPPER CASE. " Fix #246 CONDENSE lv_column_c NO-GAPS. IF lv_column_c EQ ''. lv_errormessage = 'Unable to interpret input as column'(003). RAISE EXCEPTION TYPE zcx_excel EXPORTING error = lv_errormessage. ENDIF. *--------------------------------------------------------------------* * If a number gets passed, just convert it to an integer and return * the converted value *--------------------------------------------------------------------* TRY. IF lv_column_c CO '1234567890 '. " Fix #164 ep_column = lv_column_c. " Fix #164 *--------------------------------------------------------------------* * Maximum column for EXCEL: XFD = 16384 " if anyone has a reference for this information - please add here instead of this comment *--------------------------------------------------------------------* IF ep_column > 16384 OR ep_column < 1. lv_errormessage = 'Index out of bounds'(004). RAISE EXCEPTION TYPE zcx_excel EXPORTING error = lv_errormessage. ENDIF. EXIT. ENDIF. CATCH cx_sy_conversion_no_number. "#EC NO_HANDLER " Try the character-approach if approach via number has failed ENDTRY. *--------------------------------------------------------------------* * Raise error if unexpected characters turns up *--------------------------------------------------------------------* lv_column_s = lv_column_c. IF lv_column_s CN sy-abcde. lv_errormessage = 'Unable to interpret input as column'(003). RAISE EXCEPTION TYPE zcx_excel EXPORTING error = lv_errormessage. ENDIF. *--------------------------------------------------------------------* * Interpret input as number to base 26 with A=1, ... Z=26 * Raise error if unexpected character turns up *--------------------------------------------------------------------* * 1st character *--------------------------------------------------------------------* lv_column = lv_column_c. lv_modulo = cl_abap_conv_out_ce=>uccpi( lv_column+0(1) ) MOD zcl_excel_common=>c_excel_col_module. IF lv_modulo < 1 OR lv_modulo > 26. lv_errormessage = 'Unable to interpret input as column'(003). RAISE EXCEPTION TYPE zcx_excel EXPORTING error = lv_errormessage. ENDIF. ep_column = lv_modulo. " Leftmost digit *--------------------------------------------------------------------* * 2nd character if present *--------------------------------------------------------------------* CHECK lv_column+1(1) IS NOT INITIAL. " No need to continue if string ended lv_modulo = cl_abap_conv_out_ce=>uccpi( lv_column+1(1) ) MOD zcl_excel_common=>c_excel_col_module. IF lv_modulo < 1 OR lv_modulo > 26. lv_errormessage = 'Unable to interpret input as column'(003). RAISE EXCEPTION TYPE zcx_excel EXPORTING error = lv_errormessage. ENDIF. ep_column = 26 * ep_column + lv_modulo. " if second digit is present first digit is for 26^1 *--------------------------------------------------------------------* * 3rd character if present *--------------------------------------------------------------------* CHECK lv_column+2(1) IS NOT INITIAL. " No need to continue if string ended lv_modulo = cl_abap_conv_out_ce=>uccpi( lv_column+2(1) ) MOD zcl_excel_common=>c_excel_col_module. IF lv_modulo < 1 OR lv_modulo > 26. lv_errormessage = 'Unable to interpret input as column'(003). RAISE EXCEPTION TYPE zcx_excel EXPORTING error = lv_errormessage. ENDIF. ep_column = 26 * ep_column + lv_modulo. " if third digit is present first digit is for 26^2 and second digit for 26^1 *--------------------------------------------------------------------* * Maximum column for EXCEL: XFD = 16384 " if anyone has a reference for this information - please add here instead of this comment *--------------------------------------------------------------------* IF ep_column > 16384 OR ep_column < 1. lv_errormessage = 'Index out of bounds'(004). RAISE EXCEPTION TYPE zcx_excel EXPORTING error = lv_errormessage. ENDIF. ENDMETHOD. METHOD convert_columnrow2column_a_row. "issue #256 - replacing char processing with regex DATA: pane_cell_row_a TYPE string. FIND REGEX '^(\D+)(\d+)$' IN i_columnrow SUBMATCHES e_column pane_cell_row_a. e_row = pane_cell_row_a. ENDMETHOD. METHOD convert_range2column_a_row. *--------------------------------------------------------------------* * issue #230 - Pimp my Code * - Stefan Schmöcker, (done) 2012-12-07 * - ... * changes: renaming variables to naming conventions * aligning code * added exceptionclass * added errorhandling for invalid range * adding comments to explain what we are trying to achieve *--------------------------------------------------------------------* * issue#241 - error when sheetname contains "!" * - sheetname should be returned unescaped * - Stefan Schmöcker, 2012-12-07 * changes: changed coding to support sheetnames with "!" * unescaping sheetname *--------------------------------------------------------------------* * issue#155 - lessening restrictions of input parameters * - Stefan Schmöcker, 2012-12-07 * changes: i_range changed to clike * e_sheet changed to clike *--------------------------------------------------------------------* DATA: lv_sheet TYPE string, lv_range TYPE string, lv_columnrow_start TYPE string, lv_columnrow_end TYPE string, lv_errormessage TYPE string. " Can't pass '...'(abc) to exception-class *--------------------------------------------------------------------* * Split input range into sheetname and Area * 4 cases - a) input empty --> nothing to do * - b) sheetname existing - starts with ' example 'Sheet 1'!$B$6:$D$13 * - c) sheetname existing - does not start with ' example Sheet1!$B$6:$D$13 * - d) no sheetname - just area example $B$6:$D$13 *--------------------------------------------------------------------* * Initialize output parameters CLEAR: e_column_start, e_column_end, e_row_start, e_row_end, e_sheet. IF i_range IS INITIAL. " a) input empty --> nothing to do EXIT. ELSEIF i_range(1) = `'`. " b) sheetname existing - starts with ' FIND REGEX '\![^\!]*$' IN i_range MATCH OFFSET sy-fdpos. " Find last ! IF sy-subrc = 0. lv_sheet = i_range(sy-fdpos). ADD 1 TO sy-fdpos. lv_range = i_range. SHIFT lv_range LEFT BY sy-fdpos PLACES. ELSE. lv_errormessage = 'Invalid range'(001). RAISE EXCEPTION TYPE zcx_excel EXPORTING error = lv_errormessage. ENDIF. ELSEIF i_range CS '!'. " c) sheetname existing - does not start with ' SPLIT i_range AT '!' INTO lv_sheet lv_range. ELSE. " d) no sheetname - just area lv_range = i_range. ENDIF. REPLACE ALL OCCURRENCES OF '$' IN lv_range WITH ''. SPLIT lv_range AT ':' INTO lv_columnrow_start lv_columnrow_end. convert_columnrow2column_a_row( EXPORTING i_columnrow = lv_columnrow_start IMPORTING e_column = e_column_start e_row = e_row_start ). convert_columnrow2column_a_row( EXPORTING i_columnrow = lv_columnrow_end IMPORTING e_column = e_column_end e_row = e_row_end ). e_sheet = unescape_string( lv_sheet ). " Return in unescaped form ENDMETHOD. method DATE_TO_EXCEL_STRING. DATA: lv_date_diff TYPE i. CHECK ip_value IS NOT INITIAL. " Needed hack caused by the problem that: " Excel 2000 incorrectly assumes that the year 1900 is a leap year " http://support.microsoft.com/kb/214326/en-us IF ip_value > c_excel_1900_leap_year. lv_date_diff = ip_value - c_excel_baseline_date + 2. ELSE. lv_date_diff = ip_value - c_excel_baseline_date + 1. ENDIF. ep_value = zcl_excel_common=>number_to_excel_string( ip_value = lv_date_diff ). endmethod. method DESCRIBE_STRUCTURE. DATA: lt_components TYPE abap_component_tab, lt_comps TYPE abap_component_tab, lo_struct TYPE REF TO cl_abap_structdescr, ls_component TYPE abap_componentdescr, lo_elemdescr TYPE REF TO cl_abap_elemdescr, ls_dfies TYPE dfies, l_position TYPE tabfdpos. "for DDIC structure get the info directly IF io_struct->is_ddic_type( ) = abap_true. rt_dfies = io_struct->get_ddic_field_list( ). ELSE. lt_components = io_struct->get_components( ). LOOP AT lt_components INTO ls_component. structure_case( EXPORTING is_component = ls_component CHANGING xt_components = lt_comps ) . ENDLOOP. LOOP AT lt_comps INTO ls_component. CLEAR ls_dfies. IF ls_component-type->kind = cl_abap_typedescr=>kind_elem. "E Elementary Type ADD 1 TO l_position. lo_elemdescr ?= ls_component-type. IF lo_elemdescr->is_ddic_type( ) = abap_true. ls_dfies = lo_elemdescr->get_ddic_field( ). ls_dfies-fieldname = ls_component-name. ls_dfies-position = l_position. ELSE. ls_dfies-fieldname = ls_component-name. ls_dfies-position = l_position. ls_dfies-inttype = lo_elemdescr->type_kind. ls_dfies-leng = lo_elemdescr->length. ls_dfies-outputlen = lo_elemdescr->length. ls_dfies-decimals = lo_elemdescr->decimals. ls_dfies-fieldtext = ls_component-name. ls_dfies-reptext = ls_component-name. ls_dfies-scrtext_s = ls_component-name. ls_dfies-scrtext_m = ls_component-name. ls_dfies-scrtext_l = ls_component-name. ls_dfies-dynpfld = abap_true. ENDIF. INSERT ls_dfies INTO TABLE rt_dfies. ENDIF. ENDLOOP. ENDIF. endmethod. method DESCRIBE_TABLE. endmethod. method ENCRYPT_PASSWORD. DATA lv_curr_offset TYPE i. DATA lv_curr_char TYPE c LENGTH 1. DATA lv_curr_hex TYPE zexcel_pwd_hash. DATA lv_pwd_len TYPE zexcel_pwd_hash. DATA lv_pwd_hash TYPE zexcel_pwd_hash. CONSTANTS: lv_0x7fff TYPE zexcel_pwd_hash VALUE '7FFF', lv_0x0001 TYPE zexcel_pwd_hash VALUE '0001', lv_0xce4b TYPE zexcel_pwd_hash VALUE 'CE4B'. DATA lv_pwd TYPE zexcel_aes_password. lv_pwd = i_pwd(15). lv_pwd_len = STRLEN( lv_pwd ). lv_curr_offset = lv_pwd_len - 1. WHILE lv_curr_offset GE 0. lv_curr_char = lv_pwd+lv_curr_offset(1). lv_curr_hex = char2hex( lv_curr_char ). lv_pwd_hash = ( shr14( lv_pwd_hash ) BIT-AND lv_0x0001 ) BIT-OR ( shl01( lv_pwd_hash ) BIT-AND lv_0x7fff ). lv_pwd_hash = lv_pwd_hash BIT-XOR lv_curr_hex. SUBTRACT 1 FROM lv_curr_offset. ENDWHILE. lv_pwd_hash = ( shr14( lv_pwd_hash ) BIT-AND lv_0x0001 ) BIT-OR ( shl01( lv_pwd_hash ) BIT-AND lv_0x7fff ). lv_pwd_hash = lv_pwd_hash BIT-XOR lv_0xce4b. lv_pwd_hash = lv_pwd_hash BIT-XOR lv_pwd_len. WRITE lv_pwd_hash TO r_encrypted_pwd. endmethod. METHOD escape_string. *--------------------------------------------------------------------* * issue #230 - Pimp my Code * - Stefan Schmöcker, (done) 2012-12-08 * - ... * changes: aligning code * adding comments to explain what we are trying to achieve *--------------------------------------------------------------------* * issue#242 - Support escaping for white-spaces * - Escaping also necessary when ' encountered in input * - Stefan Schmöcker, 2012-12-08 * changes: switched check if escaping is necessary to regular expression * and moved the "REPLACE" *--------------------------------------------------------------------* * issue#155 - lessening restrictions of input parameters * - Stefan Schmöcker, 2012-12-08 * changes: ip_value changed to clike *--------------------------------------------------------------------* DATA: lv_value TYPE string. *--------------------------------------------------------------------* * There exist various situations when a space will be used to separate * different parts of a string. When we have a string consisting spaces * that will cause errors unless we "escape" the string by putting ' at * the beginning and at the end of the string. *--------------------------------------------------------------------* *--------------------------------------------------------------------* * When allowing clike-input parameters we might encounter trailing * "real" blanks . These are automatically eliminated when moving * the input parameter to a string. * Now any remaining spaces ( white-spaces or normal spaces ) should * trigger the escaping as well as any ' *--------------------------------------------------------------------* lv_value = ip_value. FIND REGEX `\s|'` IN lv_value. " \s finds regular and white spaces IF sy-subrc = 0. REPLACE ALL OCCURRENCES OF `'` IN lv_value WITH `''`. CONCATENATE `'` lv_value `'` INTO lv_value . ENDIF. ep_escaped_value = lv_value. ENDMETHOD. method EXCEL_STRING_TO_DATE. DATA: lv_date_int TYPE i. TRY. lv_date_int = ip_value. ep_value = lv_date_int + c_excel_baseline_date - 2. " Needed hack caused by the problem that: " Excel 2000 incorrectly assumes that the year 1900 is a leap year " http://support.microsoft.com/kb/214326/en-us IF ep_value < c_excel_1900_leap_year. ep_value = ep_value + 1. ENDIF. CATCH cx_sy_conversion_error. RAISE EXCEPTION TYPE zcx_excel EXPORTING error = 'Index out of bounds'. ENDTRY. endmethod. method EXCEL_STRING_TO_TIME. DATA: lv_seconds_in_day TYPE i, lv_day_fraction TYPE f, lc_seconds_in_day TYPE i VALUE 86400. TRY. lv_day_fraction = ip_value. lv_seconds_in_day = lv_day_fraction * lc_seconds_in_day. ep_value = lv_seconds_in_day. CATCH cx_sy_conversion_error. RAISE EXCEPTION TYPE zcx_excel EXPORTING error = 'Unable to interpret time'. ENDTRY. endmethod. method FAIL. DATA: ls_seoclass TYPE seoclass. " Let see >=7.02 SELECT SINGLE * INTO ls_seoclass FROM seoclass WHERE clsname = 'CL_ABAP_UNIT_ASSERT'. IF sy-subrc = 0. CALL METHOD (ls_seoclass-clsname)=>fail EXPORTING msg = msg level = level quit = quit detail = detail. ELSE. " Let see >=7.00 or even lower SELECT SINGLE * INTO ls_seoclass FROM seoclass WHERE clsname = 'CL_AUNIT_ASSERT'. IF sy-subrc = 0. CALL METHOD (ls_seoclass-clsname)=>fail EXPORTING msg = msg level = level quit = quit detail = detail. ELSE. * We do nothing for now not supported ENDIF. ENDIF. endmethod. METHOD get_fieldcatalog. DATA: lr_dref_tab TYPE REF TO data, lo_salv_table TYPE REF TO cl_salv_table, lo_salv_columns_table TYPE REF TO cl_salv_columns_table, lt_salv_t_column_ref TYPE salv_t_column_ref, ls_salv_t_column_ref LIKE LINE OF lt_salv_t_column_ref, lo_salv_column_table TYPE REF TO cl_salv_column_table. FIELD-SYMBOLS: <tab> TYPE STANDARD TABLE. FIELD-SYMBOLS: <fcat> LIKE LINE OF ep_fieldcatalog. * Get copy of IP_TABLE-structure <-- must be changeable to create salv CREATE DATA lr_dref_tab LIKE ip_table. ASSIGN lr_dref_tab->* TO <tab>. * Create salv --> implicitly create fieldcat TRY. cl_salv_table=>factory( IMPORTING r_salv_table = lo_salv_table CHANGING t_table = <tab> ). lo_salv_columns_table = lo_salv_table->get_columns( ). lt_salv_t_column_ref = lo_salv_columns_table->get( ). CATCH cx_root. * maybe some errorhandling here - just haven't made up my mind yet ENDTRY. * Loop through columns and set relevant fields ( fieldname, texts ) LOOP AT lt_salv_t_column_ref INTO ls_salv_t_column_ref. lo_salv_column_table ?= ls_salv_t_column_ref-r_column. APPEND INITIAL LINE TO ep_fieldcatalog ASSIGNING <fcat>. <fcat>-position = sy-tabix. <fcat>-fieldname = ls_salv_t_column_ref-columnname. <fcat>-scrtext_s = ls_salv_t_column_ref-r_column->get_short_text( ). <fcat>-scrtext_m = ls_salv_t_column_ref-r_column->get_medium_text( ). <fcat>-scrtext_l = ls_salv_t_column_ref-r_column->get_long_text( ). <fcat>-dynpfld = 'X'. " What in the world would we exclude here? IF <fcat>-position = 1. " except for the MANDT-field of most tables ( 1st column that is ) IF lo_salv_column_table->get_ddic_datatype( ) = 'CLNT'. CLEAR <fcat>-dynpfld. ENDIF. ENDIF. * For fields that don't a description ( i.e. defined by "field type i," ) * just use the fieldname as description - that is better than nothing IF <fcat>-scrtext_s IS INITIAL AND <fcat>-scrtext_m IS INITIAL AND <fcat>-scrtext_l IS INITIAL. CONCATENATE 'Col:' <fcat>-fieldname INTO <fcat>-scrtext_l SEPARATED BY space. <fcat>-scrtext_m = <fcat>-scrtext_l. <fcat>-scrtext_s = <fcat>-scrtext_l. ENDIF. ENDLOOP. ENDMETHOD. method NUMBER_TO_EXCEL_STRING. DATA: lv_value_c TYPE c LENGTH 100. WRITE ip_value TO lv_value_c EXPONENT 0 NO-GROUPING NO-SIGN. REPLACE ALL OCCURRENCES OF ',' IN lv_value_c WITH '.'. ep_value = lv_value_c. CONDENSE ep_value. IF ip_value < 0. CONCATENATE '-' ep_value INTO ep_value. ELSEIF ip_value EQ 0. ep_value = '0'. ENDIF. endmethod. method RECURSIVE_CLASS_TO_STRUCT. " # issue 139 * is working for me - but after looking through this coding I guess * I'll rewrite this to a version w/o recursion * This is private an no one using it so far except me, so no need to hurry DATA: descr TYPE REF TO cl_abap_structdescr, wa_component LIKE LINE OF descr->components, attribute_name TYPE fieldname, flag_class TYPE flag, o_border TYPE REF TO zcl_excel_style_border. FIELD-SYMBOLS: <field> TYPE any, <fieldx> TYPE any, <class> TYPE REF TO object, <attribute> TYPE any. descr ?= cl_abap_structdescr=>describe_by_data( e_target ). LOOP AT descr->components INTO wa_component. * Assign structure and X-structure ASSIGN COMPONENT wa_component-name OF STRUCTURE e_target TO <field>. ASSIGN COMPONENT wa_component-name OF STRUCTURE e_targetx TO <fieldx>. * At least one field in the structure should be marked - otherwise continue with next field CLEAR flag_class. * maybe source is just a structure - try assign component... ASSIGN COMPONENT wa_component-name OF STRUCTURE i_source TO <attribute>. IF sy-subrc <> 0. * not - then it is an attribute of the class - use different assign then CONCATENATE 'i_source->' wa_component-name INTO attribute_name. ASSIGN (attribute_name) TO <attribute>. IF sy-subrc <> 0. EXIT. ENDIF. " Should not happen if structure is built properly - otherwise just exit to create no dumps flag_class = abap_true. ENDIF. CASE wa_component-type_kind. WHEN cl_abap_structdescr=>typekind_struct1 OR cl_abap_structdescr=>typekind_struct2. " Structure --> use recursio * IF flag_class = abap_true. ** Only borders will be passed as unbound references. But since we want to set a value we have to create an instance * ENDIF. zcl_excel_common=>recursive_class_to_struct( EXPORTING i_source = <attribute> CHANGING e_target = <field> e_targetx = <fieldx> ). WHEN OTHERS. <field> = <attribute>. <fieldx> = abap_true. ENDCASE. ENDLOOP. endmethod. METHOD recursive_struct_to_class. " # issue 139 * is working for me - but after looking through this coding I guess * I'll rewrite this to a version w/o recursion * This is private an no one using it so far except me, so no need to hurry DATA: descr TYPE REF TO cl_abap_structdescr, wa_component LIKE LINE OF descr->components, attribute_name TYPE fieldname, flag_class TYPE flag, o_border TYPE REF TO zcl_excel_style_border. FIELD-SYMBOLS: <field> TYPE any, <fieldx> TYPE any, <class> TYPE REF TO object, <attribute> TYPE any, <attribute_s> TYPE ANY TABLE. descr ?= cl_abap_structdescr=>describe_by_data( i_source ). LOOP AT descr->components INTO wa_component. * Assign structure and X-structure ASSIGN COMPONENT wa_component-name OF STRUCTURE i_source TO <field>. ASSIGN COMPONENT wa_component-name OF STRUCTURE i_sourcex TO <fieldx>. * At least one field in the structure should be marked - otherwise continue with next field CHECK <fieldx> CA abap_true. CLEAR flag_class. * maybe target is just a structure - try assign component... ASSIGN COMPONENT wa_component-name OF STRUCTURE e_target TO <attribute>. IF sy-subrc <> 0. * not - then it is an attribute of the class - use different assign then CONCATENATE 'E_TARGET->' wa_component-name INTO attribute_name. ASSIGN (attribute_name) TO <attribute>. IF sy-subrc <> 0.EXIT.ENDIF. " Should not happen if structure is built properly - otherwise just exit to create no dumps flag_class = abap_true. ENDIF. CASE wa_component-type_kind. WHEN cl_abap_structdescr=>typekind_struct1 OR cl_abap_structdescr=>typekind_struct2. " Structure --> use recursion IF flag_class = abap_true AND <attribute> IS INITIAL. * Only borders will be passed as unbound references. But since we want to set a value we have to create an instance CREATE OBJECT o_border. <attribute> = o_border. ENDIF. zcl_excel_common=>recursive_struct_to_class( EXPORTING i_source = <field> i_sourcex = <fieldx> CHANGING e_target = <attribute> ). * WHEN cl_abap_structdescr=>typekind_struct2. " String * CHECK <fieldx> = abap_true. " Marked for change * <attribute_s> = <field>. WHEN OTHERS. CHECK <fieldx> = abap_true. " Marked for change <attribute> = <field>. ENDCASE. ENDLOOP. ENDMETHOD. method SHL01. DATA: lv_bit TYPE i, lv_curr_pos TYPE i VALUE 2, lv_prev_pos TYPE i VALUE 1. DO 15 TIMES. GET BIT lv_curr_pos OF i_pwd_hash INTO lv_bit. SET BIT lv_prev_pos OF r_pwd_hash TO lv_bit. ADD 1 TO lv_curr_pos. ADD 1 TO lv_prev_pos. ENDDO. SET BIT 16 OF r_pwd_hash TO 0. endmethod. method SHR14. DATA: lv_bit TYPE i, lv_curr_pos TYPE i, lv_next_pos TYPE i. r_pwd_hash = i_pwd_hash. DO 14 TIMES. lv_curr_pos = 15. lv_next_pos = 16. DO 15 TIMES. GET BIT lv_curr_pos OF r_pwd_hash INTO lv_bit. SET BIT lv_next_pos OF r_pwd_hash TO lv_bit. SUBTRACT 1 FROM lv_curr_pos. SUBTRACT 1 FROM lv_next_pos. ENDDO. SET BIT 1 OF r_pwd_hash TO 0. ENDDO. endmethod. method SPLIT_FILE. DATA: lt_hlp TYPE TABLE OF text255, ls_hlp TYPE text255. DATA: lf_ext(10) TYPE c, lf_dot_ext(10) TYPE c. DATA: lf_str TYPE text255, lf_anz TYPE i, lf_len TYPE i. ** --------------------------------------------------------------------- CLEAR: lt_hlp, ep_file, ep_extension, ep_dotextension. ** Split the whole file at '.' SPLIT ip_file AT '.' INTO TABLE lt_hlp. ** get the extenstion from the last line of table DESCRIBE TABLE lt_hlp LINES lf_anz. IF lf_anz <= 1. ep_file = ip_file. EXIT. ENDIF. READ TABLE lt_hlp INTO ls_hlp INDEX lf_anz. ep_extension = ls_hlp. lf_ext = ls_hlp. IF NOT lf_ext IS INITIAL. CONCATENATE '.' lf_ext INTO lf_dot_ext. ENDIF. ep_dotextension = lf_dot_ext. ** get only the filename lf_len = strlen( ip_file ) - strlen( lf_dot_ext ). IF lf_len > 0. ep_file = ip_file(lf_len). ENDIF. endmethod. method STRUCTURE_CASE. DATA: lt_comp_str TYPE abap_component_tab. CASE is_component-type->kind. WHEN cl_abap_typedescr=>kind_elem. "E Elementary Type INSERT is_component INTO TABLE xt_components. WHEN cl_abap_typedescr=>kind_table. "T Table INSERT is_component INTO TABLE xt_components. WHEN cl_abap_typedescr=>kind_struct. "S Structure lt_comp_str = structure_recursive( is_component = is_component ). INSERT LINES OF lt_comp_str INTO TABLE xt_components. WHEN OTHERS. "cl_abap_typedescr=>kind_ref or cl_abap_typedescr=>kind_class or cl_abap_typedescr=>kind_intf. * We skip it. for now. ENDCASE. endmethod. method STRUCTURE_RECURSIVE. DATA: lo_struct TYPE REF TO cl_abap_structdescr, lt_components TYPE abap_component_tab, ls_components TYPE abap_componentdescr. REFRESH rt_components. lo_struct ?= is_component-type. lt_components = lo_struct->get_components( ). LOOP AT lt_components INTO ls_components. structure_case( EXPORTING is_component = ls_components CHANGING xt_components = rt_components ) . ENDLOOP. endmethod. method TIME_TO_EXCEL_STRING. DATA: lv_seconds_in_day TYPE i, lv_day_fraction TYPE f, lc_time_baseline TYPE t VALUE '000000', lc_seconds_in_day TYPE i VALUE 86400. lv_seconds_in_day = ip_value - lc_time_baseline. lv_day_fraction = lv_seconds_in_day / lc_seconds_in_day. ep_value = zcl_excel_common=>number_to_excel_string( ip_value = lv_day_fraction ). endmethod. METHOD unescape_string. CONSTANTS lcv_regex TYPE string VALUE `^'[^']` & `|` & " Beginning single ' OR `[^']'$` & `|` & " Trailing single ' OR `[^']'[^']`. " Single ' somewhere in between DATA: lv_errormessage TYPE string. " Can't pass '...'(abc) to exception-class *--------------------------------------------------------------------* * This method is used to extract the "real" string from an escaped string. * An escaped string can be identified by a beginning ' which must be * accompanied by a trailing ' * All '' in between beginning and trailing ' are treated as single ' *--------------------------------------------------------------------* *--------------------------------------------------------------------* * When allowing clike-input parameters we might encounter trailing * "real" blanks . These are automatically eliminated when moving * the input parameter to a string. *--------------------------------------------------------------------* ev_unescaped_string = iv_escaped. " Pass through if not escaped CHECK ev_unescaped_string IS NOT INITIAL. " Nothing to do if empty CHECK ev_unescaped_string(1) = `'`. " Nothing to do if not escaped *--------------------------------------------------------------------* * Remove leading and trailing ' *--------------------------------------------------------------------* REPLACE REGEX `^'(.*)'$` IN ev_unescaped_string WITH '$1'. IF sy-subrc <> 0. lv_errormessage = 'Input not properly escaped - &'(002). RAISE EXCEPTION TYPE zcx_excel EXPORTING error = lv_errormessage. ENDIF. *--------------------------------------------------------------------* * Any remaining single ' should not be here *--------------------------------------------------------------------* FIND REGEX lcv_regex IN ev_unescaped_string. IF sy-subrc = 0. lv_errormessage = 'Input not properly escaped - &'(002). RAISE EXCEPTION TYPE zcx_excel EXPORTING error = lv_errormessage. ENDIF. *--------------------------------------------------------------------* * Replace '' with ' *--------------------------------------------------------------------* REPLACE ALL OCCURRENCES OF `''` IN ev_unescaped_string WITH `'`. ENDMETHOD.