*"* 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*"* use this source file for your ABAP unit test classesABAPmethod 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 CALCULATE_CELL_DISTANCE.
DATA: lv_reference_row TYPE i,
lv_reference_col_alpha TYPE zexcel_cell_column_alpha,
lv_reference_col TYPE i,
lv_current_row TYPE i,
lv_current_col_alpha TYPE zexcel_cell_column_alpha,
lv_current_col TYPE i.
*--------------------------------------------------------------------*
* Split reference cell into numerical row/column representation
*--------------------------------------------------------------------*
convert_columnrow2column_a_row( EXPORTING
i_columnrow = iv_reference_cell
IMPORTING
e_column = lv_reference_col_alpha
e_row = lv_reference_row ).
lv_reference_col = convert_column2int( lv_reference_col_alpha ).
*--------------------------------------------------------------------*
* Split current cell into numerical row/column representation
*--------------------------------------------------------------------*
convert_columnrow2column_a_row( EXPORTING
i_columnrow = iv_current_cell
IMPORTING
e_column = lv_current_col_alpha
e_row = lv_current_row ).
lv_current_col = convert_column2int( lv_current_col_alpha ).
*--------------------------------------------------------------------*
* Calculate row and column difference
* Positive: Current cell below reference cell
* or Current cell right of reference cell
* Negative: Current cell above reference cell
* or Current cell left of reference cell
*--------------------------------------------------------------------*
ev_row_difference = lv_current_row - lv_reference_row.
ev_col_difference = lv_current_col - lv_reference_col.
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: 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
*--------------------------------------------------------------------*
* Check whether column is in allowed range for EXCEL to handle ( 1-16384 )
*--------------------------------------------------------------------*
IF lv_column > 16384
OR lv_column < 1.
RAISE EXCEPTION TYPE zcx_excel
EXPORTING
error = 'Index out of bounds'.
ENDIF.
*--------------------------------------------------------------------*
* Build alpha representation of 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.
*--------------------------------------------------------------------*
* 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.
MESSAGE e800(zabap2xlsx) INTO lv_errormessage.
RAISE EXCEPTION TYPE zcx_excel
EXPORTING
syst_at_raise = syst.
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.
MESSAGE e800(zabap2xlsx) INTO lv_errormessage.
RAISE EXCEPTION TYPE zcx_excel
EXPORTING
syst_at_raise = syst.
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.
MESSAGE e800(zabap2xlsx) INTO lv_errormessage.
RAISE EXCEPTION TYPE zcx_excel
EXPORTING
syst_at_raise = syst.
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.
MESSAGE e800(zabap2xlsx) INTO lv_errormessage.
RAISE EXCEPTION TYPE zcx_excel
EXPORTING
syst_at_raise = syst.
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.
MESSAGE e800(zabap2xlsx) INTO lv_errormessage.
RAISE EXCEPTION TYPE zcx_excel
EXPORTING
syst_at_raise = syst.
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
*--------------------------------------------------------------------*
* Stefan Schmöcker, 2013-08-11
* Allow input to be CLIKE instead of STRING
*--------------------------------------------------------------------*
DATA: pane_cell_row_a TYPE string,
lv_columnrow type string.
lv_columnrow = i_columnrow. " Get rid of trailing blanks
FIND REGEX '^(\D+)(\d+)$' IN lv_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 DETERMINE_RESULTING_FORMULA.
DATA: lv_row_difference TYPE i,
lv_col_difference TYPE i.
*--------------------------------------------------------------------*
* Calculate distance of reference and current cell
*--------------------------------------------------------------------*
calculate_cell_distance( EXPORTING
iv_reference_cell = iv_reference_cell
iv_current_cell = iv_current_cell
IMPORTING
ev_row_difference = lv_row_difference
ev_col_difference = lv_col_difference ).
*--------------------------------------------------------------------*
* and shift formula by using the row- and columndistance
*--------------------------------------------------------------------*
ev_resulting_formula = shift_formula( iv_reference_formula = iv_reference_formula
iv_shift_rows = lv_row_difference
iv_shift_cols = lv_col_difference ).
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 SHIFT_FORMULA.
CONSTANTS: lcv_operators TYPE string VALUE '+-/*^%=<>&, !',
lcv_letters TYPE string VALUE 'ABCDEFGHIJKLMNOPQRSTUVWXYZ$',
lcv_digits TYPE string VALUE '0123456789',
lcv_cell_reference_error TYPE string VALUE '#REF!'.
DATA: lv_tcnt TYPE i, " Counter variable
lv_tlen TYPE i, " Temp variable length
lv_cnt TYPE i, " Counter variable
lv_cnt2 TYPE i, " Counter variable
lv_offset1 TYPE i, " Character offset
lv_numchars TYPE i, " Number of characters counter
lv_tchar(1) TYPE c, " Temp character
lv_tchar2(1) TYPE c, " Temp character
lv_cur_form(132) TYPE c, " Formula for current cell
lv_ref_cell_addr TYPE string, " Reference cell address
lv_tcol1 TYPE string, " Temp column letter
lv_tcol2 TYPE string, " Temp column letter
lv_tcoln TYPE i, " Temp column number
lv_trow1 TYPE string, " Temp row number
lv_trow2 TYPE string, " Temp row number
lv_flen TYPE i, " Length of reference formula
lv_tlen2 TYPE i, " Temp variable length
lv_substr1 TYPE string, " Substring variable
lv_abscol TYPE string, " Absolute column symbol
lv_absrow TYPE string, " Absolute row symbol
lv_errormessage TYPE string.
FIELD-SYMBOLS: <find_my_include> TYPE ANY.
*--------------------------------------------------------------------*
* When copying a cell in EXCEL to another cell any inherent formulas
* are copied as well. Cell-references in the formula are being adjusted
* by the distance of the new cell to the original one
*--------------------------------------------------------------------*
* §1 Parse reference formula character by character
* §2 Identify Cell-references
* §3 Shift cell-reference
* §4 Build resulting formula
*--------------------------------------------------------------------*
*--------------------------------------------------------------------*
* No distance --> Reference = resulting cell/formula
*--------------------------------------------------------------------*
IF iv_shift_cols = 0
AND iv_shift_rows = 0.
ev_resulting_formula = iv_reference_formula.
EXIT. " done
ENDIF.
lv_flen = STRLEN( iv_reference_formula ).
lv_numchars = 1.
*--------------------------------------------------------------------*
* §1 Parse reference formula character by character
*--------------------------------------------------------------------*
DO lv_flen TIMES.
CLEAR: lv_tchar,
lv_substr1,
lv_ref_cell_addr.
lv_cnt2 = lv_cnt + 1.
IF lv_cnt2 > lv_flen.
EXIT. " Done
ENDIF.
*--------------------------------------------------------------------*
* Here we have the current character in the formula
*--------------------------------------------------------------------*
lv_tchar = iv_reference_formula+lv_cnt(1).
*--------------------------------------------------------------------*
* Operators or opening parenthesis will separate possible cellreferences
*--------------------------------------------------------------------*
IF ( lv_tchar CA lcv_operators
OR lv_tchar CA '(' )
AND lv_cnt2 = 1.
lv_substr1 = iv_reference_formula+lv_offset1(1).
CONCATENATE lv_cur_form lv_substr1 INTO lv_cur_form.
lv_cnt = lv_cnt + 1.
lv_offset1 = lv_cnt.
lv_numchars = 1.
CONTINUE. " --> next character in formula can be analyzed
ENDIF.
*--------------------------------------------------------------------*
* Quoted literal text holds no cell reference --> advance to end of text
*--------------------------------------------------------------------*
IF lv_tchar EQ '"'.
lv_cnt = lv_cnt + 1.
lv_numchars = lv_numchars + 1.
lv_tchar = iv_reference_formula+lv_cnt(1).
WHILE lv_tchar NE '"'.
lv_cnt = lv_cnt + 1.
lv_numchars = lv_numchars + 1.
lv_tchar = iv_reference_formula+lv_cnt(1).
ENDWHILE.
lv_cnt2 = lv_cnt + 1.
lv_substr1 = iv_reference_formula+lv_offset1(lv_numchars).
CONCATENATE lv_cur_form lv_substr1 INTO lv_cur_form.
lv_cnt = lv_cnt + 1.
IF lv_cnt = lv_flen.
EXIT.
ENDIF.
lv_offset1 = lv_cnt.
lv_numchars = 1.
lv_tchar = iv_reference_formula+lv_cnt(1).
lv_cnt2 = lv_cnt + 1.
CONTINUE. " --> next character in formula can be analyzed
ENDIF.
*--------------------------------------------------------------------*
* Operators or parenthesis or last character in formula will separate possible cellreferences
*--------------------------------------------------------------------*
IF lv_tchar CA lcv_operators
OR lv_tchar CA '():'
OR lv_cnt2 = lv_flen.
IF lv_cnt > 0.
lv_substr1 = iv_reference_formula+lv_offset1(lv_numchars).
*--------------------------------------------------------------------*
* Check for text concatenation and functions
*--------------------------------------------------------------------*
IF ( lv_tchar CA lcv_operators AND lv_tchar EQ lv_substr1 ) OR lv_tchar EQ '('.
CONCATENATE lv_cur_form lv_substr1 INTO lv_cur_form.
lv_cnt = lv_cnt + 1.
lv_offset1 = lv_cnt.
lv_cnt2 = lv_cnt + 1.
lv_numchars = 1.
CONTINUE. " --> next character in formula can be analyzed
ENDIF.
lv_tlen = lv_cnt2 - lv_offset1.
*--------------------------------------------------------------------*
* Exclude mathematical operators and closing parentheses
*--------------------------------------------------------------------*
IF lv_tchar CA lcv_operators
OR lv_tchar CA ':)'.
IF lv_cnt2 = lv_flen
AND lv_numchars = 1.
CONCATENATE lv_cur_form lv_substr1 INTO lv_cur_form.
lv_cnt = lv_cnt + 1.
lv_offset1 = lv_cnt.
lv_cnt2 = lv_cnt + 1.
lv_numchars = 1.
CONTINUE. " --> next character in formula can be analyzed
ELSE.
lv_tlen = lv_tlen - 1.
ENDIF.
ENDIF.
*--------------------------------------------------------------------*
* Capture reference cell address
*--------------------------------------------------------------------*
TRY.
MOVE: iv_reference_formula+lv_offset1(lv_tlen) TO lv_ref_cell_addr. "Ref cell address
CATCH cx_root.
lv_errormessage = 'Internal error in Class ZCL_EXCEL_COMMON Method SHIFT_FORMULA Spot 1 '. " Change to messageclass if possible
RAISE EXCEPTION TYPE zcx_excel
EXPORTING
error = lv_errormessage.
ENDTRY.
*--------------------------------------------------------------------*
* Split cell address into characters and numbers
*--------------------------------------------------------------------*
CLEAR: lv_tlen,
lv_tcnt,
lv_tcol1,
lv_trow1.
lv_tlen = STRLEN( lv_ref_cell_addr ).
IF lv_tlen <> 0.
CLEAR: lv_tcnt.
DO lv_tlen TIMES.
CLEAR: lv_tchar2.
lv_tchar2 = lv_ref_cell_addr+lv_tcnt(1).
IF lv_tchar2 CA lcv_letters.
CONCATENATE lv_tcol1 lv_tchar2 INTO lv_tcol1.
ELSEIF lv_tchar2 CA lcv_digits.
CONCATENATE lv_trow1 lv_tchar2 INTO lv_trow1.
ENDIF.
lv_tcnt = lv_tcnt + 1.
ENDDO.
ENDIF.
*--------------------------------------------------------------------*
* Check for invalid cell address
*--------------------------------------------------------------------*
IF lv_tcol1 IS INITIAL OR lv_trow1 IS INITIAL.
CONCATENATE lv_cur_form lv_substr1 INTO lv_cur_form.
lv_cnt = lv_cnt + 1.
lv_offset1 = lv_cnt.
lv_cnt2 = lv_cnt + 1.
lv_numchars = 1.
CONTINUE.
ENDIF.
*--------------------------------------------------------------------*
* Check for range names
*--------------------------------------------------------------------*
CLEAR: lv_tlen.
lv_tlen = STRLEN( lv_tcol1 ).
IF lv_tlen GT 3.
CONCATENATE lv_cur_form lv_substr1 INTO lv_cur_form.
lv_cnt = lv_cnt + 1.
lv_offset1 = lv_cnt.
lv_cnt2 = lv_cnt + 1.
lv_numchars = 1.
CONTINUE.
ENDIF.
*--------------------------------------------------------------------*
* Check for valid row
*--------------------------------------------------------------------*
IF lv_trow1 GT 1048576.
CONCATENATE lv_cur_form lv_substr1 INTO lv_cur_form.
lv_cnt = lv_cnt + 1.
lv_offset1 = lv_cnt.
lv_cnt2 = lv_cnt + 1.
lv_numchars = 1.
CONTINUE.
ENDIF.
*--------------------------------------------------------------------*
* Check for absolute column or row reference
*--------------------------------------------------------------------*
CLEAR: lv_tcol2,
lv_trow2,
lv_abscol,
lv_absrow.
lv_tlen2 = STRLEN( lv_tcol1 ) - 1.
IF lv_tcol1 IS NOT INITIAL.
lv_abscol = lv_tcol1(1).
ENDIF.
IF lv_tlen2 GE 0.
lv_absrow = lv_tcol1+lv_tlen2(1).
ENDIF.
IF lv_abscol EQ '$' AND lv_absrow EQ '$'.
lv_tlen2 = lv_tlen2 - 1.
IF lv_tlen2 > 0.
lv_tcol1 = lv_tcol1+1(lv_tlen2).
ENDIF.
lv_tlen2 = lv_tlen2 + 1.
ELSEIF lv_abscol EQ '$'.
lv_tcol1 = lv_tcol1+1(lv_tlen2).
ELSEIF lv_absrow EQ '$'.
lv_tcol1 = lv_tcol1(lv_tlen2).
ENDIF.
*--------------------------------------------------------------------*
* Check for valid column
*--------------------------------------------------------------------*
TRY.
lv_tcoln = zcl_excel_common=>convert_column2int( lv_tcol1 ) + iv_shift_cols.
CATCH zcx_excel.
CONCATENATE lv_cur_form lv_substr1 INTO lv_cur_form.
lv_cnt = lv_cnt + 1.
lv_offset1 = lv_cnt.
lv_cnt2 = lv_cnt + 1.
lv_numchars = 1.
CONTINUE.
ENDTRY.
*--------------------------------------------------------------------*
* Check whether there is a referencing problem
*--------------------------------------------------------------------*
lv_trow2 = lv_trow1 + iv_shift_rows.
IF ( lv_tcoln < 1 AND lv_abscol <> '$' ) " Maybe we should add here max-column and max row-tests as well.
OR ( lv_trow2 < 1 AND lv_absrow <> '$' ). " Check how EXCEL behaves in this case
*--------------------------------------------------------------------*
* Referencing problem encountered --> set error
*--------------------------------------------------------------------*
CONCATENATE lv_cur_form lcv_cell_reference_error INTO lv_cur_form.
ELSE.
*--------------------------------------------------------------------*
* No referencing problems --> adjust row and column
*--------------------------------------------------------------------*
*--------------------------------------------------------------------*
* Adjust column
*--------------------------------------------------------------------*
IF lv_abscol EQ '$'.
CONCATENATE lv_cur_form lv_abscol lv_tcol1 INTO lv_cur_form.
ELSEIF iv_shift_cols EQ 0.
CONCATENATE lv_cur_form lv_tcol1 INTO lv_cur_form.
ELSE.
TRY.
lv_tcol2 = zcl_excel_common=>convert_column2alpha( lv_tcoln ).
CONCATENATE lv_cur_form lv_tcol2 INTO lv_cur_form.
CATCH zcx_excel.
CONCATENATE lv_cur_form lv_substr1 INTO lv_cur_form.
lv_cnt = lv_cnt + 1.
lv_offset1 = lv_cnt.
lv_cnt2 = lv_cnt + 1.
lv_numchars = 1.
CONTINUE.
ENDTRY.
ENDIF.
*--------------------------------------------------------------------*
* Adjust row
*--------------------------------------------------------------------*
IF lv_absrow EQ '$'.
CONCATENATE lv_cur_form lv_absrow lv_trow1 INTO lv_cur_form.
ELSEIF iv_shift_rows = 0.
CONCATENATE lv_cur_form lv_trow1 INTO lv_cur_form.
* elseif lv_trow2 < 1.
* CONCATENATE lv_cur_form lc_cell_reference_error INTO lv_cur_form.
ELSE.
CONCATENATE lv_cur_form lv_trow2 INTO lv_cur_form.
ENDIF.
ENDIF.
lv_numchars = 0.
IF lv_tchar CA lcv_operators
OR lv_tchar CA ':)'.
CONCATENATE lv_cur_form lv_tchar INTO lv_cur_form.
ENDIF.
lv_offset1 = lv_cnt2.
ENDIF.
ENDIF.
lv_numchars = lv_numchars + 1.
lv_cnt = lv_cnt + 1.
lv_cnt2 = lv_cnt + 1.
ENDDO.
*--------------------------------------------------------------------*
* Return resulting formula
*--------------------------------------------------------------------*
IF lv_cur_form IS NOT INITIAL.
MOVE lv_cur_form TO ev_resulting_formula.
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 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.