class ZCL_EXCEL_COMMON definition public final create public . *"* public components of class ZCL_EXCEL_COMMON *"* do not include other source files here!!! public section. constants C_EXCEL_BASELINE_DATE type D value '19000101'. "#EC NOTEXT class-data C_EXCEL_NUMFMT_OFFSET type INT1 value 164. "#EC NOTEXT . constants C_EXCEL_SHEET_MAX_COL type INT4 value 16384. "#EC NOTEXT constants C_EXCEL_SHEET_MIN_COL type INT4 value 1. "#EC NOTEXT class-data C_SPRAS_EN type SPRAS value 'E'. "#EC NOTEXT . class-data O_CONV type ref to CL_ABAP_CONV_OUT_CE . constants C_EXCEL_1900_LEAP_YEAR type D value '19000228'. "#EC NOTEXT class-methods DESCRIBE_STRUCTURE importing !IO_STRUCT type ref to CL_ABAP_STRUCTDESCR returning value(RT_DFIES) type DDFIELDS . class-methods DESCRIBE_TABLE . class-methods CONVERT_COLUMN2ALPHA importing !IP_COLUMN type SIMPLE returning value(EP_COLUMN) type ZEXCEL_CELL_COLUMN_ALPHA raising ZCX_EXCEL . class-methods CONVERT_COLUMN2INT importing !IP_COLUMN type SIMPLE returning value(EP_COLUMN) type ZEXCEL_CELL_COLUMN raising ZCX_EXCEL . class-methods CONVERT_COLUMNROW2COLUMN_A_ROW importing !I_COLUMNROW type STRING exporting !E_COLUMN type ZEXCEL_CELL_COLUMN_ALPHA !E_ROW type ZEXCEL_CELL_ROW . class-methods CONVERT_RANGE2COLUMN_A_ROW importing !I_RANGE type STRING exporting !E_COLUMN_START type ZEXCEL_CELL_COLUMN_ALPHA !E_COLUMN_END type ZEXCEL_CELL_COLUMN_ALPHA !E_ROW_START type ZEXCEL_CELL_ROW !E_ROW_END type ZEXCEL_CELL_ROW !E_SHEET type ZEXCEL_SHEET_TITLE . class-methods DATE_TO_EXCEL_STRING importing !IP_VALUE type D returning value(EP_VALUE) type ZEXCEL_CELL_VALUE . class-methods ENCRYPT_PASSWORD importing !I_PWD type ZEXCEL_AES_PASSWORD returning value(R_ENCRYPTED_PWD) type ZEXCEL_AES_PASSWORD . class-methods ESCAPE_STRING importing !IP_VALUE type STRING returning value(EP_ESCAPED_VALUE) type STRING . class-methods EXCEL_STRING_TO_DATE importing !IP_VALUE type ZEXCEL_CELL_VALUE returning value(EP_VALUE) type D raising ZCX_EXCEL . class-methods EXCEL_STRING_TO_TIME importing !IP_VALUE type ZEXCEL_CELL_VALUE returning value(EP_VALUE) type T raising ZCX_EXCEL . class-methods GET_FIELDCATALOG importing !IP_TABLE type STANDARD TABLE returning value(EP_FIELDCATALOG) type ZEXCEL_T_FIELDCATALOG . class-methods NUMBER_TO_EXCEL_STRING importing value(IP_VALUE) type NUMERIC returning value(EP_VALUE) type ZEXCEL_CELL_VALUE . class-methods RECURSIVE_CLASS_TO_STRUCT importing !I_SOURCE type ANY changing !E_TARGET type DATA !E_TARGETX type DATA . class-methods RECURSIVE_STRUCT_TO_CLASS importing !I_SOURCE type DATA !I_SOURCEX type DATA changing !E_TARGET type ANY . class-methods TIME_TO_EXCEL_STRING importing !IP_VALUE type T returning value(EP_VALUE) type ZEXCEL_CELL_VALUE . interface IF_AUNIT_CONSTANTS load . type-pools ABAP . class-methods ASSERT_EQUALS importing !EXP type ANY !ACT type ANY !MSG type CSEQUENCE optional !LEVEL type AUNIT_LEVEL default IF_AUNIT_CONSTANTS=>CRITICAL !TOL type F optional !QUIT type AUNIT_FLOWCTRL default IF_AUNIT_CONSTANTS=>METHOD !IGNORE_HASH_SEQUENCE type ABAP_BOOL default ABAP_FALSE returning value(ASSERTION_FAILED) type ABAP_BOOL . class-methods FAIL importing !MSG type CSEQUENCE optional !LEVEL type AUNIT_LEVEL default IF_AUNIT_CONSTANTS=>CRITICAL !QUIT type AUNIT_FLOWCTRL default IF_AUNIT_CONSTANTS=>METHOD !DETAIL type CSEQUENCE optional . class-methods ASSERT_DIFFERS importing !EXP type SIMPLE !ACT type SIMPLE !MSG type CSEQUENCE optional !LEVEL type AUNIT_LEVEL default IF_AUNIT_CONSTANTS=>CRITICAL !TOL type F optional !QUIT type AUNIT_FLOWCTRL default IF_AUNIT_CONSTANTS=>METHOD returning value(ASSERTION_FAILED) type ABAP_BOOL . *"* protected components of class ZCL_EXCEL_COMMON *"* do not include other source files here!!! protected section. *"* private components of class ZCL_EXCEL_COMMON *"* do not include other source files here!!! private section. class-data C_EXCEL_COL_MODULE type INT2 value 64. "#EC NOTEXT . type-pools ABAP . class-methods STRUCTURE_CASE importing !IS_COMPONENT type ABAP_COMPONENTDESCR changing !XT_COMPONENTS type ABAP_COMPONENT_TAB . class-methods STRUCTURE_RECURSIVE importing !IS_COMPONENT type ABAP_COMPONENTDESCR returning value(RT_COMPONENTS) type ABAP_COMPONENT_TAB . class-methods CHAR2HEX importing !I_CHAR type CHAR1 returning value(R_HEX) type ZEXCEL_PWD_HASH . class-methods SHL01 importing !I_PWD_HASH type ZEXCEL_PWD_HASH returning value(R_PWD_HASH) type ZEXCEL_PWD_HASH . class-methods SHR14 importing !I_PWD_HASH type ZEXCEL_PWD_HASH returning value(R_PWD_HASH) type ZEXCEL_PWD_HASH . *"* 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. 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 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 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. DATA: lv_uccpi TYPE i, lv_factor TYPE i, lv_offset TYPE i, lv_char TYPE c, lv_column TYPE zexcel_cell_column_alpha, lv_column_c TYPE char10, mod TYPE i. * If a number gets passed, just convert it to an integer, * Otherwise try to interpret it as if ZEXCEL_CELL_COLUMN_ALPHA was passed * if both fails raise exception lv_column_c = ip_column. TRANSLATE lv_column TO UPPER CASE. CONDENSE lv_column_c NO-GAPS. IF lv_column_c EQ ''. RAISE EXCEPTION TYPE zcx_excel EXPORTING error = 'Unable to interpret column'. ENDIF. * First try - convert to number TRY. IF lv_column_c CO '1234567890 '. " Fix #164 ep_column = lv_column_c. " Fix #164 EXIT. ENDIF. CATCH cx_sy_conversion_no_number. " Too bad - try the character-approach ENDTRY. * Upper case lv_column = lv_column_c. ** Get string lenght and align to right * lv_offset = 3 - STRLEN( lv_column ). * * SHIFT lv_column RIGHT BY lv_offset PLACES. * ** Calculate column position * DO 3 TIMES. * lv_offset = sy-index - 1. * lv_char = lv_column+lv_offset(1). * if lv_char IS INITIAL. * CONTINUE. * ENDIF. * lv_uccpi = cl_abap_conv_out_ce=>uccpi( lv_char ). * lv_factor = 26 ** ( 3 - sy-index ). * ep_column = ep_column + ( lv_uccpi MOD zcl_excel_common=>c_excel_col_module ) * lv_factor. * ENDDO. * Raise error if unexpected character turns up mod = cl_abap_conv_out_ce=>uccpi( lv_column+0(1) ) MOD zcl_excel_common=>c_excel_col_module. IF mod < 1 OR mod > 26. RAISE EXCEPTION TYPE zcx_excel EXPORTING error = 'Unable to interpret column'. ENDIF. ep_column = mod. CHECK lv_column+1(1) IS NOT INITIAL. " No need to continue if string ended mod = cl_abap_conv_out_ce=>uccpi( lv_column+1(1) ) MOD zcl_excel_common=>c_excel_col_module. IF mod < 1 OR mod > 26. RAISE EXCEPTION TYPE zcx_excel EXPORTING error = 'Unable to interpret column'. ENDIF. ep_column = 26 * ep_column + mod. CHECK lv_column+2(1) IS NOT INITIAL. " No need to continue if string ended mod = cl_abap_conv_out_ce=>uccpi( lv_column+2(1) ) MOD zcl_excel_common=>c_excel_col_module. IF mod < 1 OR mod > 26. RAISE EXCEPTION TYPE zcx_excel EXPORTING error = 'Unable to interpret column'. ENDIF. ep_column = 26 * ep_column + mod. IF ep_column GT 16384 OR ep_column LT 1. RAISE EXCEPTION TYPE zcx_excel EXPORTING error = 'Index out of bounds'. ENDIF. endmethod. method CONVERT_COLUMNROW2COLUMN_A_ROW. DATA: width TYPE i, col_width TYPE i, row_str TYPE string, col_str TYPE string. width = strlen( i_columnrow ). col_width = width. col_str = i_columnrow. WHILE col_str CA '0123456789'. col_width = col_width - 1. col_str = i_columnrow(col_width). ENDWHILE. e_column = col_str. width = width - col_width. row_str = i_columnrow+col_width(width). e_row = row_str. endmethod. method CONVERT_RANGE2COLUMN_A_ROW. DATA: sheet TYPE string, range TYPE string, columnrow_start TYPE string, columnrow_end TYPE string. IF i_range IS INITIAL OR NOT i_range CS ':'. RETURN. ENDIF. IF i_range CS '!'. SPLIT i_range AT '!' INTO sheet range. e_sheet = sheet. ELSE. range = i_range. ENDIF. REPLACE ALL OCCURRENCES OF '$' IN range WITH ''. SPLIT range AT ':' INTO columnrow_start columnrow_end. convert_columnrow2column_a_row( EXPORTING i_columnrow = columnrow_start IMPORTING e_column = e_column_start e_row = e_row_start ). convert_columnrow2column_a_row( EXPORTING i_columnrow = columnrow_end IMPORTING e_column = e_column_end e_row = e_row_end ). 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 lo_struct->is_ddic_type( ) = abap_true. rt_dfies = lo_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-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. DATA lv_value TYPE string. lv_value = ip_value. REPLACE ALL OCCURRENCES OF `'` IN lv_value WITH `''`. IF lv_value CP '* *'. 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. * it causes a short dump running DEMO_EXCEL3 * rein vert to old implementation * * DATA: lr_data TYPE REF TO data, * lo_structdescr TYPE REF TO cl_abap_structdescr, * lt_dfies TYPE ddfields, * ls_dfies TYPE dfies, * ls_fieldcatalog TYPE zexcel_s_fieldcatalog. * * CREATE DATA lr_data LIKE LINE OF ip_table. * * lo_structdescr ?= cl_abap_structdescr=>describe_by_data( lr_data ). * * lt_dfies = describe_structure( io_struct = lo_structdescr ). * * LOOP AT lt_dfies INTO ls_dfies. * CLEAR ls_fieldcatalog. * MOVE-CORRESPONDING ls_dfies TO ls_fieldcatalog. * APPEND ls_fieldcatalog TO ep_fieldcatalog. * ENDLOOP. DATA: lr_data TYPE REF TO data, lo_structdescr TYPE REF TO cl_abap_structdescr, lo_elemdescr TYPE REF TO cl_abap_elemdescr, lt_dfies TYPE ddfields, ls_dfies TYPE dfies, lv_sytabix TYPE sytabix, ls_fieldcatalog TYPE zexcel_s_fieldcatalog, lt_components TYPE abap_component_tab, ls_component LIKE LINE OF lt_components. CREATE DATA lr_data LIKE LINE OF ip_table. lo_structdescr ?= cl_abap_structdescr=>describe_by_data_ref( lr_data ). "for DDIC structure get the info directly IF lo_structdescr->is_ddic_type( ) = abap_true. lt_dfies = lo_structdescr->get_ddic_field_list( ). LOOP AT lt_dfies INTO ls_dfies. CLEAR ls_fieldcatalog. MOVE-CORRESPONDING ls_dfies TO ls_fieldcatalog. APPEND ls_fieldcatalog TO ep_fieldcatalog. ENDLOOP. ELSE. "if structure is not DDIC check components lt_components = lo_structdescr->get_components( ). LOOP AT lt_components INTO ls_component. lv_sytabix = sy-tabix. CLEAR ls_fieldcatalog. lo_elemdescr ?= ls_component-type. "component is DDIC IF lo_elemdescr->is_ddic_type( ) = abap_true. ls_dfies = lo_elemdescr->get_ddic_field( ). MOVE-CORRESPONDING ls_dfies TO ls_fieldcatalog. ls_fieldcatalog-fieldname = ls_component-name. ELSE. "component is not DDIC -> return minimum information required ls_fieldcatalog-fieldname = ls_component-name. ls_fieldcatalog-dynpfld = abap_true. ls_fieldcatalog-scrtext_m = ls_component-name. ENDIF. ls_fieldcatalog-position = lv_sytabix. APPEND ls_fieldcatalog TO ep_fieldcatalog. ENDLOOP. ENDIF. 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. " 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. 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. " 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 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 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.