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.
class-data C_EXCEL_NUMFMT_OFFSET type INT1 value 164. "#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_BASELINE_DATE type D value '19000101'. "#EC NOTEXT
class-methods GET_FIELDCATALOG
importing
!IP_TABLE type STANDARD TABLE
returning
value(EP_FIELDCATALOG) type ZEXCEL_T_FIELDCATALOG .
class-methods CONVERT_COLUMN2ALPHA
importing
!IP_COLUMN type ZEXCEL_CELL_COLUMN
returning
value(EP_COLUMN) type ZEXCEL_CELL_COLUMN_ALPHA .
class-methods CONVERT_COLUMN2INT
importing
!IP_COLUMN type ZEXCEL_CELL_COLUMN_ALPHA
returning
value(EP_COLUMN) type ZEXCEL_CELL_COLUMN .
class-methods NUMBER_TO_EXCEL_STRING
importing
value(IP_VALUE) type NUMERIC
returning
value(EP_VALUE) type ZEXCEL_CELL_VALUE .
class-methods DATE_TO_EXCEL_STRING
importing
!IP_VALUE type D
returning
value(EP_VALUE) type ZEXCEL_CELL_VALUE .
class-methods TIME_TO_EXCEL_STRING
importing
!IP_VALUE type T
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 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 EXCEL_STRING_TO_DATE
importing
!IP_VALUE type ZEXCEL_CELL_VALUE
returning
value(EP_VALUE) type D .
class-methods EXCEL_STRING_TO_TIME
importing
!IP_VALUE type ZEXCEL_CELL_VALUE
returning
value(EP_VALUE) type T .*"* 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 .
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 zcl_Excel_Common_Test DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS zcl_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>zcl_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/>
*?<GENERATE_CLASS_FIXTURE/>
*?<GENERATE_INVOCATION>X
*?</GENERATE_INVOCATION>
*?<GENERATE_ASSERT_EQUAL>X
*?</GENERATE_ASSERT_EQUAL>
*?</TESTCLASS_OPTIONS>
*?</asx:values>
*?</asx:abap>
PRIVATE SECTION.
* ================
DATA:
f_cut TYPE REF TO zcl_excel_common. "class under test
METHODS: convert_columnrow2column_a_row FOR TESTING.
METHODS: date_conversions FOR TESTING.
METHODS: time_conversions FOR TESTING.
ENDCLASS. "zcl_Excel_Common_Test
*----------------------------------------------------------------------*
* CLASS zcl_Excel_Common_Test IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS zcl_excel_common_test IMPLEMENTATION.
* ===========================================
METHOD convert_columnrow2column_a_row.
* ======================================
DATA i_columnrow TYPE string VALUE 'AB344'.
DATA e_column TYPE zexcel_cell_column_alpha.
DATA e_row TYPE zexcel_cell_row.
zcl_excel_common=>convert_columnrow2column_a_row(
EXPORTING
i_columnrow = i_columnrow
IMPORTING
e_column = e_column
e_row = e_row
).
cl_aunit_assert=>assert_equals(
act = e_column
exp = 'AB'
msg = 'Testing value e_Column'
* level =
).
cl_aunit_assert=>assert_equals(
act = e_row
exp = 344
msg = 'Testing value e_Row'
* level =
).
i_columnrow = 'B3'.
zcl_excel_common=>convert_columnrow2column_a_row(
EXPORTING
i_columnrow = i_columnrow
IMPORTING
e_column = e_column
e_row = e_row
).
cl_aunit_assert=>assert_equals(
act = e_column
exp = 'B'
msg = 'Testing value e_Column'
* level =
).
cl_aunit_assert=>assert_equals(
act = e_row
exp = 3
msg = 'Testing value e_Row'
* level =
).
ENDMETHOD. "convert_Columnrow2column_A_Row
METHOD date_conversions.
DATA: lv_date TYPE d,
lv_cell TYPE zexcel_cell_value.
* test date conversions. Expected values generated using Excel 2010
lv_date = '20100101'.
lv_cell = zcl_excel_common=>date_to_excel_string( lv_date ).
cl_aunit_assert=>assert_equals(
act = lv_cell
exp = '40179'
msg = 'Wrong date conversion' ).
lv_date = zcl_excel_common=>excel_string_to_date( lv_cell ).
cl_aunit_assert=>assert_equals(
act = lv_date
exp = '20100101'
msg = 'Wrong date conversion' ).
lv_date = '20080229'.
lv_cell = zcl_excel_common=>date_to_excel_string( lv_date ).
cl_aunit_assert=>assert_equals(
act = lv_cell
exp = '39507'
msg = 'Wrong date conversion' ).
lv_date = zcl_excel_common=>excel_string_to_date( lv_cell ).
cl_aunit_assert=>assert_equals(
act = lv_date
exp = '20080229'
msg = 'Wrong date conversion' ).
lv_date = '19991231'.
lv_cell = zcl_excel_common=>date_to_excel_string( lv_date ).
cl_aunit_assert=>assert_equals(
act = lv_cell
exp = '36525'
msg = 'Wrong date conversion' ).
lv_date = zcl_excel_common=>excel_string_to_date( lv_cell ).
cl_aunit_assert=>assert_equals(
act = lv_date
exp = '19991231'
msg = 'Wrong date conversion' ).
ENDMETHOD. "date_conversions
METHOD time_conversions.
DATA: lv_time TYPE t,
lv_cell TYPE zexcel_cell_value,
lv_value TYPE f.
* test time conversions. Expected values generated using Excel 2010
lv_time = '000000'.
lv_value = zcl_excel_common=>time_to_excel_string( lv_time ).
cl_aunit_assert=>assert_equals_f(
act = lv_value
exp = 0
msg = 'Wrong time conversion' ).
lv_cell = lv_value.
lv_time = zcl_excel_common=>excel_string_to_time( lv_cell ).
cl_aunit_assert=>assert_equals(
act = lv_time
exp = '000000'
msg = 'Wrong time conversion' ).
lv_time = '090909'.
lv_value = zcl_excel_common=>time_to_excel_string( lv_time ).
cl_aunit_assert=>assert_equals_f(
act = lv_value
exp = '0.38135416666666666'
msg = 'Wrong time conversion' ).
lv_cell = lv_value.
lv_time = zcl_excel_common=>excel_string_to_time( lv_cell ).
cl_aunit_assert=>assert_equals(
act = lv_time
exp = '090909'
msg = 'Wrong time conversion' ).
lv_time = '120000'.
lv_value = zcl_excel_common=>time_to_excel_string( lv_time ).
cl_aunit_assert=>assert_equals_f(
act = lv_value
exp = '0.5'
msg = 'Wrong time conversion' ).
lv_cell = lv_value.
lv_time = zcl_excel_common=>excel_string_to_time( lv_cell ).
cl_aunit_assert=>assert_equals(
act = lv_time
exp = '120000'
msg = 'Wrong time conversion' ).
lv_time = '235959'.
lv_value = zcl_excel_common=>time_to_excel_string( lv_time ).
cl_aunit_assert=>assert_equals_f(
act = lv_value
exp = '0.99998842592592585'
msg = 'Wrong time conversion' ).
lv_cell = lv_value.
lv_time = zcl_excel_common=>excel_string_to_time( lv_cell ).
cl_aunit_assert=>assert_equals(
act = lv_time
exp = '235959'
msg = 'Wrong time conversion' ).
ENDMETHOD. "time_conversions
ENDCLASS. "zcl_Excel_Common_Testmethod CHAR2HEX.
IF o_conv IS NOT BOUND.
o_conv = cl_abap_conv_out_ce=>create( endian = 'L'
ignore_cerr = 'X'
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.
lv_column = ip_column.
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_char TYPE c,
lv_column(2) TYPE c.
* Calculate most significant letter
lv_char = ip_column+1(1).
IF lv_char IS NOT INITIAL. "To avoid the first 26 column that have only a char in first position
ep_column = cl_abap_conv_out_ce=>uccpi( lv_char ).
ep_column = ep_column MOD ( zcl_excel_common=>c_excel_col_module ).
lv_char = ip_column(1).
lv_uccpi = cl_abap_conv_out_ce=>uccpi( lv_char ).
lv_uccpi = ( lv_uccpi MOD ( zcl_excel_common=>c_excel_col_module ) ) * 26.
ep_column = ep_column + lv_uccpi.
ELSE.
lv_char = ip_column(1).
ep_column = cl_abap_conv_out_ce=>uccpi( lv_char ).
ep_column = ep_column - zcl_excel_common=>c_excel_col_module.
ENDIF.
endmethod.method CONVERT_COLUMNROW2COLUMN_A_ROW.
DATA: width TYPE i,
col_width TYPE i,
row_str TYPE string.
width = strlen( i_columnrow ).
col_width = 2.
e_column = i_columnrow.
WHILE e_column CA '0123456789'.
col_width = col_width - 1.
e_column = i_columnrow(col_width).
ENDWHILE.
width = width - col_width.
row_str = i_columnrow+col_width(width).
e_row = row_str.
endmethod.METHOD date_to_excel_string.
DATA: lv_date_diff TYPE i.
CHECK ip_value IS NOT INITIAL.
lv_date_diff = ip_value - c_excel_baseline_date + 2.
ep_value = zcl_excel_common=>number_to_excel_string( ip_value = lv_date_diff ).
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 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.
CATCH cx_sy_conversion_error.
CLEAR ep_value.
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.
CLEAR ep_value.
ENDTRY.
ENDMETHOD.method GET_FIELDCATALOG.
DATA: lr_data TYPE REF TO data,
lo_tabdescr TYPE REF TO cl_abap_structdescr,
ls_header TYPE x030l,
lt_dfies TYPE ddfields,
ls_dfies TYPE dfies,
ls_fieldcatalog TYPE zexcel_s_fieldcatalog.
CREATE DATA lr_data LIKE LINE OF ip_table.
lo_tabdescr ?= cl_abap_structdescr=>describe_by_data_ref( lr_data ).
ls_header = lo_tabdescr->get_ddic_header( ).
lt_dfies = lo_tabdescr->get_ddic_field_list( ).
LOOP AT lt_dfies INTO ls_dfies.
MOVE-CORRESPONDING ls_dfies TO ls_fieldcatalog.
APPEND ls_fieldcatalog TO ep_fieldcatalog.
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.
ENDIF.
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 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.