Fix #723 Calculated Columns - Replace PR 734 (#843)

* Fix #723 Calculated Columns - Replace PR 734

Co-authored-by: sandraros <sandraros@gmail.com>
Co-authored-by: Abo <andrea@borgia.bo.it>
Co-authored-by: Lars Hvam <larshp@hotmail.com>
This commit is contained in:
sandraros 2021-10-15 17:22:00 +02:00 committed by GitHub
parent de39aa842a
commit 904a014609
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 883 additions and 1 deletions

View File

@ -0,0 +1,232 @@
*&---------------------------------------------------------------------*
*& Report zdemo_excel47
*&---------------------------------------------------------------------*
*&
*& - BIND_TABLE and Calculated Columns
*&
*&---------------------------------------------------------------------*
REPORT zdemo_excel47.
DATA: lo_excel TYPE REF TO zcl_excel,
lo_worksheet TYPE REF TO zcl_excel_worksheet,
lo_hyperlink TYPE REF TO zcl_excel_hyperlink,
lo_column TYPE REF TO zcl_excel_column.
CONSTANTS: gc_save_file_name TYPE string VALUE '47_ColumnFormulas.xlsx'.
INCLUDE zdemo_excel_outputopt_incl.
CLASS lcl_app DEFINITION.
PUBLIC SECTION.
METHODS main
RAISING
zcx_excel.
ENDCLASS.
CLASS lcl_app IMPLEMENTATION.
METHOD main.
TYPES: BEGIN OF ty_tblsheet1_line,
carrid TYPE sflight-carrid,
connid TYPE sflight-connid,
fldate TYPE sflight-fldate,
price TYPE sflight-price,
formula TYPE string,
formula_2 TYPE string,
column_formula TYPE string,
column_formula_2 TYPE sflight-price,
column_formula_3 TYPE sflight-price,
column_formula_4 TYPE sflight-price,
column_formula_5 TYPE string,
column_formula_6 TYPE string,
column_formula_7 TYPE string,
END OF ty_tblsheet1_line,
BEGIN OF ty_tblsheet2_line,
carrid TYPE scarr-carrid,
carrname TYPE scarr-carrname,
END OF ty_tblsheet2_line.
DATA: lv_f1 TYPE string,
ls_tblsheet1 TYPE ty_tblsheet1_line,
lt_tblsheet1 TYPE STANDARD TABLE OF ty_tblsheet1_line,
ls_tblsheet2 TYPE ty_tblsheet2_line,
lt_tblsheet2 TYPE STANDARD TABLE OF ty_tblsheet2_line,
lt_field_catalog TYPE zexcel_t_fieldcatalog,
ls_catalog TYPE zexcel_s_fieldcatalog,
ls_table_settings TYPE zexcel_s_table_settings,
lo_range TYPE REF TO zcl_excel_range.
FIELD-SYMBOLS: <ls_field_catalog> TYPE zexcel_s_fieldcatalog.
*** Initialization
CREATE OBJECT lo_excel.
" Sheet1
lv_f1 = 'TblSheet1[[#This Row],[Airfare]]+100'. " [@Airfare]+100
ls_tblsheet1-carrid = `AA`. ls_tblsheet1-connid = '0017'. ls_tblsheet1-fldate = '20180116'. ls_tblsheet1-price = '422.94'. ls_tblsheet1-formula = lv_f1. ls_tblsheet1-formula_2 = lv_f1.
APPEND ls_tblsheet1 TO lt_tblsheet1.
ls_tblsheet1-carrid = `AZ`. ls_tblsheet1-connid = '0555'. ls_tblsheet1-fldate = '20180116'. ls_tblsheet1-price = '185.00'. ls_tblsheet1-formula = lv_f1.
APPEND ls_tblsheet1 TO lt_tblsheet1.
ls_tblsheet1-carrid = `LH`. ls_tblsheet1-connid = '0400'. ls_tblsheet1-fldate = '20180119'. ls_tblsheet1-price = '666.00'. ls_tblsheet1-formula = lv_f1. ls_tblsheet1-formula_2 = lv_f1.
APPEND ls_tblsheet1 TO lt_tblsheet1.
ls_tblsheet1-carrid = `AA`. ls_tblsheet1-connid = '0941'. ls_tblsheet1-fldate = '20180117'. ls_tblsheet1-price = '879.82'. ls_tblsheet1-formula = lv_f1.
APPEND ls_tblsheet1 TO lt_tblsheet1.
" Sheet2
ls_tblsheet2-carrid = `AA`. ls_tblsheet2-carrname = 'America Airlines'.
APPEND ls_tblsheet2 TO lt_tblsheet2.
ls_tblsheet2-carrid = `AZ`. ls_tblsheet2-carrname = 'Alitalia'.
APPEND ls_tblsheet2 TO lt_tblsheet2.
ls_tblsheet2-carrid = `LH`. ls_tblsheet2-carrname = 'Lufthansa'.
APPEND ls_tblsheet2 TO lt_tblsheet2.
*** Sheet1
lo_worksheet = lo_excel->get_active_worksheet( ).
lt_field_catalog = zcl_excel_common=>get_fieldcatalog( ip_table = lt_tblsheet1 ).
LOOP AT lt_field_catalog ASSIGNING <ls_field_catalog>.
CASE <ls_field_catalog>-fieldname.
WHEN 'CARRID'.
<ls_field_catalog>-scrtext_l = 'Company ID'.
WHEN 'AIRFARE'.
<ls_field_catalog>-scrtext_l = 'Airfare'.
WHEN 'PRICE'.
<ls_field_catalog>-totals_function = zcl_excel_table=>totals_function_average.
WHEN 'FORMULA'.
" Each cell may have a distinct formula, none formula is applied to future new rows
<ls_field_catalog>-scrtext_l = 'Formula and aggregate function'.
<ls_field_catalog>-formula = abap_true.
<ls_field_catalog>-totals_function = zcl_excel_table=>totals_function_sum.
WHEN 'FORMULA_2'.
" each cell may have a distinct formula, a formula is applied to future new rows
<ls_field_catalog>-scrtext_l = 'Formula except 1 cell & aggregate fu.'.
<ls_field_catalog>-formula = abap_true.
<ls_field_catalog>-column_formula = lv_f1. " to apply to future rows
<ls_field_catalog>-totals_function = zcl_excel_table=>totals_function_min.
WHEN 'COLUMN_FORMULA'.
" The column formula applies to all rows and to future new rows. Internally, the formula is NOT shared because a column name is used.
<ls_field_catalog>-scrtext_l = 'Column formula and aggregate function'.
<ls_field_catalog>-column_formula = 'TblSheet1[[#This Row],[Airfare]]+222'. " [@Airfare]+222
<ls_field_catalog>-totals_function = zcl_excel_table=>totals_function_min.
WHEN 'COLUMN_FORMULA_2'.
" The column formula applies to all rows and to future new rows. Internally, the formula is shared.
<ls_field_catalog>-scrtext_l = 'C2. Column formula'.
<ls_field_catalog>-column_formula = 'D2+100'.
WHEN 'COLUMN_FORMULA_3'.
" The column formula applies to all rows and to future new rows. Internally, the formula is shared.
<ls_field_catalog>-scrtext_l = 'C3. Column formula & aggregate function'.
<ls_field_catalog>-column_formula = 'D2+100'.
<ls_field_catalog>-totals_function = zcl_excel_table=>totals_function_max.
WHEN 'COLUMN_FORMULA_4'.
" The column formula applies to all rows and to future new rows. Internally, the formula is shared.
<ls_field_catalog>-scrtext_l = 'C4. Column formula array fu./named range'.
<ls_field_catalog>-column_formula = 'A1&";"&_xlfn.IFS(TRUE,NamedRange)'. " =A1&";"&@IFS(TRUE,NamedRange)
WHEN 'COLUMN_FORMULA_5'.
" The column formula applies to all rows and to future new rows. Internally, the formula is NOT shared because it refers to a different sheet.
<ls_field_catalog>-scrtext_l = 'C5. Column formula refers to other sheet'.
<ls_field_catalog>-column_formula = 'OtherSheet!A2'.
WHEN 'COLUMN_FORMULA_6'.
" The column formula applies to all rows and to future new rows. Internally, the formula is NOT shared.
" The formula seen in Excel: =FILTER(TblSheet2[Company Name],TblSheet2[Airline ID]=[@Airline],"")
<ls_field_catalog>-scrtext_l = 'C6. Column formula array fu./other sheet'.
<ls_field_catalog>-column_formula = '_xlfn.FILTER(TblSheet2[Company Name],TblSheet2[Company ID]=TblSheet1[[#This Row],[Company ID]],"")'.
WHEN 'COLUMN_FORMULA_7'.
" The column formula applies to all rows and to future new rows. Internally, the formula is NOT shared.
" The formula seen in Excel: =FILTER(Tbl2_Sheet1[Company Name],Tbl2_Sheet1[Airline ID]=[@Airline],"")
<ls_field_catalog>-scrtext_l = 'C7. Column formula array fu./same sheet'.
<ls_field_catalog>-column_formula = '_xlfn.FILTER(Tbl2_Sheet1[Company Name],Tbl2_Sheet1[Company ID]=TblSheet1[[#This Row],[Company ID]],"")'.
ENDCASE.
ENDLOOP.
ls_table_settings-table_style = zcl_excel_table=>builtinstyle_medium2.
ls_table_settings-table_name = 'TblSheet1'.
ls_table_settings-top_left_column = 'A'.
ls_table_settings-top_left_row = 1.
ls_table_settings-show_row_stripes = abap_true.
lo_worksheet->bind_table(
ip_table = lt_tblsheet1
it_field_catalog = lt_field_catalog
is_table_settings = ls_table_settings
iv_default_descr = 'L' ).
" Named range for formula 4
lo_range = lo_excel->add_new_range( ).
lo_range->name = 'NamedRange'.
lo_range->set_value( ip_sheet_name = lo_worksheet->get_title( )
ip_start_column = 'B'
ip_start_row = 1
ip_stop_column = 'B'
ip_stop_row = 1 ).
" Second table in same sheet
lt_field_catalog = zcl_excel_common=>get_fieldcatalog( ip_table = lt_tblsheet2 ).
LOOP AT lt_field_catalog ASSIGNING <ls_field_catalog>.
CASE <ls_field_catalog>-fieldname.
WHEN 'CARRID'.
<ls_field_catalog>-scrtext_l = 'Company ID'.
WHEN 'CARRNAME'.
<ls_field_catalog>-scrtext_l = 'Company Name'.
ENDCASE.
ENDLOOP.
CLEAR ls_table_settings.
ls_table_settings-table_style = zcl_excel_table=>builtinstyle_medium2.
ls_table_settings-table_name = 'Tbl2_Sheet1'.
ls_table_settings-top_left_column = 'O'.
ls_table_settings-top_left_row = 1.
ls_table_settings-show_row_stripes = abap_true.
lo_worksheet->bind_table(
ip_table = lt_tblsheet2
it_field_catalog = lt_field_catalog
is_table_settings = ls_table_settings
iv_default_descr = 'L' ).
*** Sheet2
lo_worksheet = lo_excel->add_new_worksheet( 'Sheet2' ).
CLEAR ls_table_settings.
ls_table_settings-table_style = zcl_excel_table=>builtinstyle_medium2.
ls_table_settings-table_name = 'TblSheet2'.
ls_table_settings-top_left_column = 'A'.
ls_table_settings-top_left_row = 1.
ls_table_settings-show_row_stripes = abap_true.
lo_worksheet->bind_table(
ip_table = lt_tblsheet2
it_field_catalog = lt_field_catalog
is_table_settings = ls_table_settings
iv_default_descr = 'L' ).
*** OtherSheet
lo_worksheet = lo_excel->add_new_worksheet( 'OtherSheet' ).
lo_worksheet->set_cell( ip_column = 1 ip_row = 1 ip_value = 'Title' ).
lo_worksheet->set_cell( ip_column = 1 ip_row = 2 ip_value = 'A2' ).
lo_worksheet->set_cell( ip_column = 1 ip_row = 3 ip_value = 'A3' ).
lo_worksheet->set_cell( ip_column = 1 ip_row = 4 ip_value = 'A4' ).
lo_worksheet->set_cell( ip_column = 1 ip_row = 5 ip_value = 'A5' ).
*** Active sheet = Sheet1
lo_excel->set_active_sheet_index_by_name( 'Sheet1' ).
*** Create output
lcl_output=>output( lo_excel ).
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
DATA: go_app TYPE REF TO lcl_app,
go_error TYPE REF TO zcx_excel.
TRY.
CREATE OBJECT go_app.
go_app->main( ).
CATCH zcx_excel INTO go_error.
MESSAGE go_error TYPE 'I' DISPLAY LIKE 'E'.
ENDTRY.

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_PROG" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<PROGDIR>
<NAME>ZDEMO_EXCEL47</NAME>
<DBAPL>S</DBAPL>
<DBNA>D$</DBNA>
<SUBC>1</SUBC>
<RLOAD>E</RLOAD>
<FIXPT>X</FIXPT>
<LDBNAME>D$S</LDBNAME>
<UCCHECK>X</UCCHECK>
</PROGDIR>
<TPOOL>
<item>
<ID>R</ID>
<ENTRY>abap2xlsx Demo: Table Calculated Columns (from Excel 365 or 2019)</ENTRY>
<LENGTH>65</LENGTH>
</item>
</TPOOL>
</asx:values>
</asx:abap>
</abapGit>

View File

@ -1076,6 +1076,7 @@ CLASS ZCL_EXCEL_COMMON IMPLEMENTATION.
lv_ref_formula TYPE string, lv_ref_formula TYPE string,
lv_compare_1 TYPE string, lv_compare_1 TYPE string,
lv_compare_2 TYPE string, lv_compare_2 TYPE string,
lv_level TYPE i, " Level of groups [..[..]..] or {..}
lv_errormessage TYPE string. lv_errormessage TYPE string.
@ -1165,6 +1166,30 @@ CLASS ZCL_EXCEL_COMMON IMPLEMENTATION.
ENDIF. ENDIF.
*--------------------------------------------------------------------*
* Groups - Ignore values inside blocks [..[..]..] and {..}
* R1C1-Style Cell Reference: R[1]C[1]
* Cell References: 'C:\[Source.xlsx]Sheet1'!$A$1
* Array constants: {1,3.5,TRUE,"Hello"}
* "Intra table reference": Flights[[#This Row],[Air fare]]
*--------------------------------------------------------------------*
IF lv_tchar CA '[]{}' OR lv_level > 0.
IF lv_tchar CA '[{'.
lv_level = lv_level + 1.
ELSEIF lv_tchar CA ']}'.
lv_level = lv_level - 1.
ENDIF.
IF lv_cnt2 = lv_flen.
lv_substr1 = iv_reference_formula+lv_offset1(lv_numchars).
CONCATENATE lv_cur_form lv_substr1 INTO lv_cur_form.
EXIT.
ENDIF.
lv_numchars = lv_numchars + 1.
lv_cnt = lv_cnt + 1.
lv_cnt2 = lv_cnt + 1.
CONTINUE.
ENDIF.
*--------------------------------------------------------------------* *--------------------------------------------------------------------*
* Operators or parenthesis or last character in formula will separate possible cellreferences * Operators or parenthesis or last character in formula will separate possible cellreferences
*--------------------------------------------------------------------* *--------------------------------------------------------------------*

View File

@ -1197,6 +1197,20 @@ CLASS lcl_excel_common_test IMPLEMENTATION.
iv_shift_rows = 1 iv_shift_rows = 1
iv_expected = |'A1'!$A$1| ). iv_expected = |'A1'!$A$1| ).
" Reference to another column in the same row of a Table, with a space in the column name
macro_shift_formula(
iv_reference_formula = 'Tbl[[#This Row],[Air fare]]'
iv_shift_cols = 1
iv_shift_rows = 1
iv_expected = 'Tbl[[#This Row],[Air fare]]' ).
" Reference to another column in the same row of a Table, inside more complex expression
macro_shift_formula(
iv_reference_formula = 'Tbl[[#This Row],[Air]]+A1'
iv_shift_cols = 1
iv_shift_rows = 1
iv_expected = 'Tbl[[#This Row],[Air]]+B2' ).
ENDMETHOD. ENDMETHOD.
METHOD is_cell_in_range. METHOD is_cell_in_range.

View File

@ -31,6 +31,20 @@ CLASS zcl_excel_worksheet DEFINITION
END OF mty_s_outline_row . END OF mty_s_outline_row .
TYPES: TYPES:
mty_ts_outlines_row TYPE SORTED TABLE OF mty_s_outline_row WITH UNIQUE KEY row_from row_to . mty_ts_outlines_row TYPE SORTED TABLE OF mty_s_outline_row WITH UNIQUE KEY row_from row_to .
TYPES:
BEGIN OF mty_s_column_formula,
id TYPE i,
column TYPE zexcel_cell_column,
formula TYPE string,
table_top_left_row TYPE zexcel_cell_row,
table_bottom_right_row TYPE zexcel_cell_row,
table_left_column_int TYPE zexcel_cell_column,
table_right_column_int TYPE zexcel_cell_column,
END OF mty_s_column_formula .
TYPES:
mty_th_column_formula
TYPE HASHED TABLE OF mty_s_column_formula
WITH UNIQUE KEY id .
TYPES ty_doc_url TYPE c LENGTH 255. TYPES ty_doc_url TYPE c LENGTH 255.
CONSTANTS c_break_column TYPE zexcel_break VALUE 2. "#EC NOTEXT CONSTANTS c_break_column TYPE zexcel_break VALUE 2. "#EC NOTEXT
@ -44,6 +58,13 @@ CLASS zcl_excel_worksheet DEFINITION
DATA show_rowcolheaders TYPE zexcel_show_gridlines READ-ONLY VALUE abap_true. "#EC NOTEXT DATA show_rowcolheaders TYPE zexcel_show_gridlines READ-ONLY VALUE abap_true. "#EC NOTEXT
DATA styles TYPE zexcel_t_sheet_style . DATA styles TYPE zexcel_t_sheet_style .
DATA tabcolor TYPE zexcel_s_tabcolor READ-ONLY . DATA tabcolor TYPE zexcel_s_tabcolor READ-ONLY .
DATA column_formulas TYPE mty_th_column_formula READ-ONLY .
CLASS-DATA: BEGIN OF c_messages READ-ONLY,
formula_id_only_is_possible TYPE string,
column_formula_id_not_found TYPE string,
formula_not_in_this_table TYPE string,
formula_in_other_column TYPE string,
END OF c_messages.
METHODS add_comment METHODS add_comment
IMPORTING IMPORTING
@ -231,6 +252,7 @@ CLASS zcl_excel_worksheet DEFINITION
VALUE(ep_guid) TYPE zexcel_cell_style VALUE(ep_guid) TYPE zexcel_cell_style
RAISING RAISING
zcx_excel . zcx_excel .
CLASS-METHODS class_constructor.
METHODS constructor METHODS constructor
IMPORTING IMPORTING
!ip_excel TYPE REF TO zcl_excel !ip_excel TYPE REF TO zcl_excel
@ -412,6 +434,7 @@ CLASS zcl_excel_worksheet DEFINITION
!ip_hyperlink TYPE REF TO zcl_excel_hyperlink OPTIONAL !ip_hyperlink TYPE REF TO zcl_excel_hyperlink OPTIONAL
!ip_data_type TYPE zexcel_cell_data_type OPTIONAL !ip_data_type TYPE zexcel_cell_data_type OPTIONAL
!ip_abap_type TYPE abap_typekind OPTIONAL !ip_abap_type TYPE abap_typekind OPTIONAL
!ip_column_formula_id TYPE mty_s_column_formula-id OPTIONAL
RAISING RAISING
zcx_excel . zcx_excel .
METHODS set_cell_formula METHODS set_cell_formula
@ -632,6 +655,16 @@ CLASS zcl_excel_worksheet DEFINITION
VALUE(ep_width) TYPE float VALUE(ep_width) TYPE float
RAISING RAISING
zcx_excel . zcx_excel .
CLASS-METHODS check_cell_column_formula
IMPORTING
it_column_formulas TYPE mty_th_column_formula
ip_column_formula_id TYPE mty_s_column_formula-id
ip_formula TYPE zexcel_cell_formula
ip_value TYPE simple
ip_row TYPE zexcel_cell_row
ip_column TYPE zexcel_cell_column
RAISING
zcx_excel.
METHODS generate_title METHODS generate_title
RETURNING RETURNING
VALUE(ep_title) TYPE zexcel_sheet_title . VALUE(ep_title) TYPE zexcel_sheet_title .
@ -814,6 +847,8 @@ CLASS zcl_excel_worksheet IMPLEMENTATION.
lo_iterator TYPE REF TO cl_object_collection_iterator, lo_iterator TYPE REF TO cl_object_collection_iterator,
lo_style_cond TYPE REF TO zcl_excel_style_cond, lo_style_cond TYPE REF TO zcl_excel_style_cond,
lo_curtable TYPE REF TO zcl_excel_table. lo_curtable TYPE REF TO zcl_excel_table.
DATA: ls_column_formula TYPE mty_s_column_formula,
lv_mincol TYPE i.
FIELD-SYMBOLS: FIELD-SYMBOLS:
<ls_field_catalog> TYPE zexcel_s_fieldcatalog, <ls_field_catalog> TYPE zexcel_s_fieldcatalog,
@ -969,6 +1004,17 @@ CLASS zcl_excel_worksheet IMPLEMENTATION.
ip_value = lv_value ). ip_value = lv_value ).
ENDIF. ENDIF.
IF <ls_field_catalog>-column_formula IS NOT INITIAL.
ls_column_formula-id = lines( column_formulas ) + 1.
ls_column_formula-column = lv_column_int.
ls_column_formula-formula = <ls_field_catalog>-column_formula.
ls_column_formula-table_top_left_row = lo_table->settings-top_left_row.
ls_column_formula-table_bottom_right_row = lo_table->settings-bottom_right_row.
ls_column_formula-table_left_column_int = lv_mincol.
ls_column_formula-table_right_column_int = lv_maxcol.
INSERT ls_column_formula INTO TABLE column_formulas.
ENDIF.
ADD 1 TO lv_row_int. ADD 1 TO lv_row_int.
LOOP AT ip_table ASSIGNING <fs_table_line>. LOOP AT ip_table ASSIGNING <fs_table_line>.
@ -998,6 +1044,31 @@ CLASS zcl_excel_worksheet IMPLEMENTATION.
ip_row = lv_row_int ip_row = lv_row_int
ip_formula = <fs_fldval> ). ip_formula = <fs_fldval> ).
ENDIF. ENDIF.
ELSEIF <ls_field_catalog>-column_formula IS NOT INITIAL.
" Column formulas
IF <ls_field_catalog>-style IS NOT INITIAL.
IF <ls_field_catalog>-abap_type IS NOT INITIAL.
me->set_cell( ip_column = lv_column_alpha
ip_row = lv_row_int
ip_column_formula_id = ls_column_formula-id
ip_abap_type = <ls_field_catalog>-abap_type
ip_style = <ls_field_catalog>-style ).
ELSE.
me->set_cell( ip_column = lv_column_alpha
ip_row = lv_row_int
ip_column_formula_id = ls_column_formula-id
ip_style = <ls_field_catalog>-style ).
ENDIF.
ELSEIF <ls_field_catalog>-abap_type IS NOT INITIAL.
me->set_cell( ip_column = lv_column_alpha
ip_row = lv_row_int
ip_column_formula_id = ls_column_formula-id
ip_abap_type = <ls_field_catalog>-abap_type ).
ELSE.
me->set_cell( ip_column = lv_column_alpha
ip_row = lv_row_int
ip_column_formula_id = ls_column_formula-id ).
ENDIF.
ELSE. ELSE.
IF <ls_field_catalog>-style IS NOT INITIAL. IF <ls_field_catalog>-style IS NOT INITIAL.
IF <ls_field_catalog>-abap_type IS NOT INITIAL. IF <ls_field_catalog>-abap_type IS NOT INITIAL.
@ -1704,6 +1775,40 @@ CLASS zcl_excel_worksheet IMPLEMENTATION.
ENDMETHOD. "CHANGE_CELL_STYLE ENDMETHOD. "CHANGE_CELL_STYLE
METHOD check_cell_column_formula.
FIELD-SYMBOLS <fs_column_formula> TYPE zcl_excel_worksheet=>mty_s_column_formula.
IF ip_value IS NOT INITIAL OR ip_formula IS NOT INITIAL.
zcx_excel=>raise_text( c_messages-formula_id_only_is_possible ).
ENDIF.
READ TABLE it_column_formulas WITH TABLE KEY id = ip_column_formula_id ASSIGNING <fs_column_formula>.
IF sy-subrc <> 0.
zcx_excel=>raise_text( c_messages-column_formula_id_not_found ).
ENDIF.
IF ip_row < <fs_column_formula>-table_top_left_row + 1
OR ip_row > <fs_column_formula>-table_bottom_right_row + 1
OR ip_column < <fs_column_formula>-table_left_column_int
OR ip_column > <fs_column_formula>-table_right_column_int.
zcx_excel=>raise_text( c_messages-formula_not_in_this_table ).
ENDIF.
IF ip_column <> <fs_column_formula>-column.
zcx_excel=>raise_text( c_messages-formula_in_other_column ).
ENDIF.
ENDMETHOD.
METHOD class_constructor.
c_messages-formula_id_only_is_possible = |{ 'If Formula ID is used, value and formula must be empty'(008) }|.
c_messages-column_formula_id_not_found = |{ 'The Column Formula does not exist'(009) }|.
c_messages-formula_not_in_this_table = |{ 'The cell uses a Column Formula which should be part of the same table'(010) }|.
c_messages-formula_in_other_column = |{ 'The cell uses a Column Formula which is in a different column'(011) }|.
ENDMETHOD.
METHOD constructor. METHOD constructor.
DATA: lv_title TYPE zexcel_sheet_title. DATA: lv_title TYPE zexcel_sheet_title.
@ -2884,15 +2989,27 @@ CLASS zcl_excel_worksheet IMPLEMENTATION.
<fs_time> TYPE t, <fs_time> TYPE t,
<fs_value> TYPE simple, <fs_value> TYPE simple,
<fs_typekind_int8> TYPE abap_typekind. <fs_typekind_int8> TYPE abap_typekind.
FIELD-SYMBOLS: <fs_column_formula> TYPE mty_s_column_formula.
IF ip_value IS NOT SUPPLIED AND ip_formula IS NOT SUPPLIED. IF ip_value IS NOT SUPPLIED
AND ip_formula IS NOT SUPPLIED
AND ip_column_formula_id = 0.
zcx_excel=>raise_text( 'Please provide the value or formula' ). zcx_excel=>raise_text( 'Please provide the value or formula' ).
ENDIF. ENDIF.
* Begin of change issue #152 - don't touch exisiting style if only value is passed * Begin of change issue #152 - don't touch exisiting style if only value is passed
* lv_style_guid = ip_style. * lv_style_guid = ip_style.
lv_column = zcl_excel_common=>convert_column2int( ip_column ). lv_column = zcl_excel_common=>convert_column2int( ip_column ).
IF ip_column_formula_id <> 0.
check_cell_column_formula(
it_column_formulas = column_formulas
ip_column_formula_id = ip_column_formula_id
ip_formula = ip_formula
ip_value = ip_value
ip_row = ip_row
ip_column = lv_column ).
ENDIF.
READ TABLE sheet_content ASSIGNING <fs_sheet_content> WITH TABLE KEY cell_row = ip_row " Changed to access via table key , Stefan Schmöcker, 2013-08-03 READ TABLE sheet_content ASSIGNING <fs_sheet_content> WITH TABLE KEY cell_row = ip_row " Changed to access via table key , Stefan Schmöcker, 2013-08-03
cell_column = lv_column. cell_column = lv_column.
IF sy-subrc = 0. IF sy-subrc = 0.
@ -3035,6 +3152,7 @@ CLASS zcl_excel_worksheet IMPLEMENTATION.
* End of change issue #152 - don't touch exisiting style if only value is passed * End of change issue #152 - don't touch exisiting style if only value is passed
<fs_sheet_content>-cell_value = lv_value. <fs_sheet_content>-cell_value = lv_value.
<fs_sheet_content>-cell_formula = ip_formula. <fs_sheet_content>-cell_formula = ip_formula.
<fs_sheet_content>-column_formula_id = ip_column_formula_id.
<fs_sheet_content>-cell_style = lv_style_guid. <fs_sheet_content>-cell_style = lv_style_guid.
<fs_sheet_content>-data_type = lv_data_type. <fs_sheet_content>-data_type = lv_data_type.
ELSE. ELSE.
@ -3042,6 +3160,7 @@ CLASS zcl_excel_worksheet IMPLEMENTATION.
ls_sheet_content-cell_column = lv_column. ls_sheet_content-cell_column = lv_column.
ls_sheet_content-cell_value = lv_value. ls_sheet_content-cell_value = lv_value.
ls_sheet_content-cell_formula = ip_formula. ls_sheet_content-cell_formula = ip_formula.
ls_sheet_content-column_formula_id = ip_column_formula_id.
ls_sheet_content-cell_style = lv_style_guid. ls_sheet_content-cell_style = lv_style_guid.
ls_sheet_content-data_type = lv_data_type. ls_sheet_content-data_type = lv_data_type.
lv_row_alpha = ip_row. lv_row_alpha = ip_row.

View File

@ -1,3 +1,6 @@
CLASS ltc_check_cell_column_formula DEFINITION DEFERRED.
CLASS zcl_excel_worksheet DEFINITION LOCAL FRIENDS
ltc_check_cell_column_formula.
CLASS lcl_excel_worksheet_test DEFINITION FOR TESTING CLASS lcl_excel_worksheet_test DEFINITION FOR TESTING
RISK LEVEL HARMLESS RISK LEVEL HARMLESS
@ -39,6 +42,40 @@ CLASS lcl_excel_worksheet_test DEFINITION FOR TESTING
ENDCLASS. "lcl_Excel_Worksheet_Test ENDCLASS. "lcl_Excel_Worksheet_Test
CLASS ltc_check_cell_column_formula DEFINITION FOR TESTING
RISK LEVEL HARMLESS
DURATION SHORT.
PRIVATE SECTION.
METHODS: success FOR TESTING RAISING cx_static_check.
METHODS: fails_both_formula_id_value FOR TESTING RAISING cx_static_check.
METHODS: fails_both_formula_id_formula FOR TESTING RAISING cx_static_check.
METHODS: formula_id_not_found FOR TESTING RAISING cx_static_check.
METHODS: outside_table_fails__above FOR TESTING RAISING cx_static_check.
METHODS: outside_table_fails__below FOR TESTING RAISING cx_static_check.
METHODS: outside_table_fails__left FOR TESTING RAISING cx_static_check.
METHODS: outside_table_fails__right FOR TESTING RAISING cx_static_check.
METHODS: must_be_in_same_column FOR TESTING RAISING cx_static_check.
METHODS: setup.
METHODS: should_fail
IMPORTING
ip_formula_id TYPE zexcel_s_cell_data-column_formula_id
ip_formula TYPE zexcel_s_cell_data-cell_formula OPTIONAL
ip_value TYPE zexcel_s_cell_data-cell_value OPTIONAL
ip_row TYPE zexcel_s_cell_data-cell_row
ip_column TYPE zexcel_s_cell_data-cell_column
ip_exp TYPE string
RAISING
zcx_excel.
DATA: mt_column_formulas TYPE zcl_excel_worksheet=>mty_th_column_formula,
c_messages LIKE zcl_excel_worksheet=>c_messages.
ENDCLASS.
CLASS LCL_EXCEL_WORKSHEET_TEST IMPLEMENTATION. CLASS LCL_EXCEL_WORKSHEET_TEST IMPLEMENTATION.
* ============================================== * ==============================================
@ -422,3 +459,100 @@ CLASS LCL_EXCEL_WORKSHEET_TEST IMPLEMENTATION.
ENDMETHOD. ENDMETHOD.
ENDCLASS. "lcl_Excel_Worksheet_Test ENDCLASS. "lcl_Excel_Worksheet_Test
CLASS ltc_check_cell_column_formula IMPLEMENTATION.
METHOD setup.
DATA: ls_column_formula TYPE zcl_excel_worksheet=>mty_s_column_formula.
c_messages = zcl_excel_worksheet=>c_messages.
" Column Formula in table A1:B4 (for unknown reason, bottom_right_row is last actual row minus 1)
CLEAR ls_column_formula.
ls_column_formula-id = 1.
ls_column_formula-column = 1.
ls_column_formula-table_top_left_row = 1.
ls_column_formula-table_bottom_right_row = 3.
ls_column_formula-table_left_column_int = 1.
ls_column_formula-table_right_column_int = 2.
INSERT ls_column_formula INTO TABLE mt_column_formulas.
" Column Formula in table D1:E4 (for unknown reason, bottom_right_row is last actual row minus 1)
CLEAR ls_column_formula.
ls_column_formula-id = 2.
ls_column_formula-column = 4.
ls_column_formula-table_top_left_row = 1.
ls_column_formula-table_bottom_right_row = 3.
ls_column_formula-table_left_column_int = 4.
ls_column_formula-table_right_column_int = 5.
INSERT ls_column_formula INTO TABLE mt_column_formulas.
ENDMETHOD.
METHOD success.
zcl_excel_worksheet=>check_cell_column_formula(
it_column_formulas = mt_column_formulas
ip_column_formula_id = 1
ip_formula = ''
ip_value = ''
ip_row = 2
ip_column = 1 ).
ENDMETHOD.
METHOD fails_both_formula_id_value.
should_fail( ip_formula_id = 1 ip_formula = '' ip_value = '3.14' ip_row = 2 ip_column = 1 ip_exp = c_messages-formula_id_only_is_possible ).
ENDMETHOD.
METHOD fails_both_formula_id_formula.
should_fail( ip_formula_id = 1 ip_formula = 'A2' ip_value = '' ip_row = 2 ip_column = 1 ip_exp = c_messages-formula_id_only_is_possible ).
ENDMETHOD.
METHOD formula_id_not_found.
should_fail( ip_formula_id = 3 ip_row = 1 ip_column = 1 ip_exp = c_messages-column_formula_id_not_found ).
ENDMETHOD.
METHOD outside_table_fails__above.
should_fail( ip_formula_id = 2 ip_row = 1 ip_column = 1 ip_exp = c_messages-formula_not_in_this_table ).
ENDMETHOD.
METHOD outside_table_fails__below.
should_fail( ip_formula_id = 2 ip_row = 5 ip_column = 1 ip_exp = c_messages-formula_not_in_this_table ).
ENDMETHOD.
METHOD outside_table_fails__left.
should_fail( ip_formula_id = 2 ip_row = 2 ip_column = 0 ip_exp = c_messages-formula_not_in_this_table ).
ENDMETHOD.
METHOD outside_table_fails__right.
should_fail( ip_formula_id = 2 ip_row = 2 ip_column = 3 ip_exp = c_messages-formula_not_in_this_table ).
ENDMETHOD.
METHOD must_be_in_same_column.
should_fail( ip_formula_id = 1 ip_row = 2 ip_column = 2 ip_exp = c_messages-formula_in_other_column ).
ENDMETHOD.
METHOD should_fail.
DATA: lo_exception TYPE REF TO zcx_excel.
TRY.
zcl_excel_worksheet=>check_cell_column_formula(
EXPORTING
it_column_formulas = mt_column_formulas
ip_column_formula_id = ip_formula_id
ip_formula = ip_formula
ip_value = ip_value
ip_row = ip_row
ip_column = ip_column ).
cl_abap_unit_assert=>fail( msg = |Should have failed with error "{ ip_exp }"| ).
CATCH zcx_excel INTO lo_exception.
cl_abap_unit_assert=>assert_equals( act = lo_exception->get_text( ) exp = ip_exp msg = ip_exp ).
ENDTRY.
ENDMETHOD.
ENDCLASS.

View File

@ -13,6 +13,13 @@ CLASS zcl_excel_writer_2007 DEFINITION
*"* protected components of class ZCL_EXCEL_WRITER_2007 *"* protected components of class ZCL_EXCEL_WRITER_2007
*"* do not include other source files here!!! *"* do not include other source files here!!!
TYPES: BEGIN OF mty_column_formula_used,
id TYPE zexcel_s_cell_data-column_formula_id,
si TYPE string,
"! type: shared, etc.
t TYPE string,
END OF mty_column_formula_used,
mty_column_formulas_used TYPE HASHED TABLE OF mty_column_formula_used WITH UNIQUE KEY id.
CONSTANTS c_content_types TYPE string VALUE '[Content_Types].xml'. "#EC NOTEXT CONSTANTS c_content_types TYPE string VALUE '[Content_Types].xml'. "#EC NOTEXT
CONSTANTS c_docprops_app TYPE string VALUE 'docProps/app.xml'. "#EC NOTEXT CONSTANTS c_docprops_app TYPE string VALUE 'docProps/app.xml'. "#EC NOTEXT
CONSTANTS c_docprops_core TYPE string VALUE 'docProps/core.xml'. "#EC NOTEXT CONSTANTS c_docprops_core TYPE string VALUE 'docProps/core.xml'. "#EC NOTEXT
@ -197,6 +204,25 @@ CLASS zcl_excel_writer_2007 DEFINITION
io_document TYPE REF TO if_ixml_document io_document TYPE REF TO if_ixml_document
RETURNING RETURNING
VALUE(ep_content) TYPE xstring. VALUE(ep_content) TYPE xstring.
METHODS create_xl_sheet_column_formula
IMPORTING
io_document TYPE REF TO if_ixml_document
it_column_formulas TYPE zcl_excel_worksheet=>mty_th_column_formula
is_sheet_content TYPE zexcel_s_cell_data
EXPORTING
eo_element TYPE REF TO if_ixml_element
CHANGING
ct_column_formulas_used TYPE mty_column_formulas_used
cv_si TYPE i
RAISING
zcx_excel.
METHODS is_formula_shareable
IMPORTING
ip_formula TYPE string
RETURNING
VALUE(ep_shareable) TYPE abap_bool
RAISING
zcx_excel.
PRIVATE SECTION. PRIVATE SECTION.
*"* private components of class ZCL_EXCEL_WRITER_2007 *"* private components of class ZCL_EXCEL_WRITER_2007
@ -5386,6 +5412,83 @@ CLASS zcl_excel_writer_2007 IMPLEMENTATION.
ENDMETHOD. ENDMETHOD.
METHOD create_xl_sheet_column_formula.
TYPES: ls_column_formula_used TYPE mty_column_formula_used,
lv_column_alpha TYPE zexcel_cell_column_alpha,
lv_top_cell_coords TYPE zexcel_cell_coords,
lv_bottom_cell_coords TYPE zexcel_cell_coords,
lv_cell_coords TYPE zexcel_cell_coords,
lv_ref_value TYPE string,
lv_test_shared TYPE string,
lv_si TYPE i,
lv_1st_line_shared_formula TYPE abap_bool.
DATA: lv_value TYPE string,
ls_column_formula_used TYPE mty_column_formula_used,
lv_column_alpha TYPE zexcel_cell_column_alpha,
lv_top_cell_coords TYPE zexcel_cell_coords,
lv_bottom_cell_coords TYPE zexcel_cell_coords,
lv_cell_coords TYPE zexcel_cell_coords,
lv_ref_value TYPE string,
lv_1st_line_shared_formula TYPE abap_bool.
FIELD-SYMBOLS: <ls_column_formula> TYPE zcl_excel_worksheet=>mty_s_column_formula,
<ls_column_formula_used> TYPE mty_column_formula_used.
READ TABLE it_column_formulas WITH TABLE KEY id = is_sheet_content-column_formula_id ASSIGNING <ls_column_formula>.
ASSERT sy-subrc = 0.
lv_value = <ls_column_formula>-formula.
lv_1st_line_shared_formula = abap_false.
eo_element = io_document->create_simple_element( name = 'f'
parent = io_document ).
READ TABLE ct_column_formulas_used WITH TABLE KEY id = is_sheet_content-column_formula_id ASSIGNING <ls_column_formula_used>.
IF sy-subrc <> 0.
CLEAR ls_column_formula_used.
ls_column_formula_used-id = is_sheet_content-column_formula_id.
IF is_formula_shareable( ip_formula = lv_value ) = abap_true.
ls_column_formula_used-t = 'shared'.
ls_column_formula_used-si = cv_si.
CONDENSE ls_column_formula_used-si.
cv_si = cv_si + 1.
lv_1st_line_shared_formula = abap_true.
ENDIF.
INSERT ls_column_formula_used INTO TABLE ct_column_formulas_used ASSIGNING <ls_column_formula_used>.
ENDIF.
IF lv_1st_line_shared_formula = abap_true OR <ls_column_formula_used>-t <> 'shared'.
lv_column_alpha = zcl_excel_common=>convert_column2alpha( ip_column = is_sheet_content-cell_column ).
lv_top_cell_coords = |{ lv_column_alpha }{ <ls_column_formula>-table_top_left_row + 1 }|.
lv_bottom_cell_coords = |{ lv_column_alpha }{ <ls_column_formula>-table_bottom_right_row + 1 }|.
lv_cell_coords = |{ lv_column_alpha }{ is_sheet_content-cell_row }|.
IF lv_top_cell_coords = lv_cell_coords.
lv_ref_value = |{ lv_top_cell_coords }:{ lv_bottom_cell_coords }|.
ELSE.
lv_ref_value = |{ lv_cell_coords }:{ lv_bottom_cell_coords }|.
lv_value = zcl_excel_common=>shift_formula(
iv_reference_formula = lv_value
iv_shift_cols = 0
iv_shift_rows = is_sheet_content-cell_row - <ls_column_formula>-table_top_left_row - 1 ).
ENDIF.
ENDIF.
IF <ls_column_formula_used>-t = 'shared'.
eo_element->set_attribute( name = 't'
value = <ls_column_formula_used>-t ).
eo_element->set_attribute( name = 'si'
value = <ls_column_formula_used>-si ).
IF lv_1st_line_shared_formula = abap_true.
eo_element->set_attribute( name = 'ref'
value = lv_ref_value ).
eo_element->set_value( value = lv_value ).
ENDIF.
ELSE.
eo_element->set_value( value = lv_value ).
ENDIF.
ENDMETHOD.
METHOD create_xl_sheet_pagebreaks. METHOD create_xl_sheet_pagebreaks.
DATA: lo_pagebreaks TYPE REF TO zcl_excel_worksheet_pagebreaks, DATA: lo_pagebreaks TYPE REF TO zcl_excel_worksheet_pagebreaks,
lt_pagebreaks TYPE zcl_excel_worksheet_pagebreaks=>tt_pagebreak_at, lt_pagebreaks TYPE zcl_excel_worksheet_pagebreaks=>tt_pagebreak_at,
@ -5760,6 +5863,8 @@ CLASS zcl_excel_writer_2007 IMPLEMENTATION.
lv_value TYPE string, lv_value TYPE string,
lv_style_guid TYPE zexcel_cell_style. lv_style_guid TYPE zexcel_cell_style.
DATA: lt_column_formulas_used TYPE mty_column_formulas_used,
lv_si TYPE i.
FIELD-SYMBOLS: <ls_sheet_content> TYPE zexcel_s_cell_data, FIELD-SYMBOLS: <ls_sheet_content> TYPE zexcel_s_cell_data,
<ls_row_outline> LIKE LINE OF lts_row_outlines. <ls_row_outline> LIKE LINE OF lts_row_outlines.
@ -6016,6 +6121,18 @@ CLASS zcl_excel_writer_2007 IMPLEMENTATION.
CONDENSE lv_value. CONDENSE lv_value.
lo_element_4->set_value( value = lv_value ). lo_element_4->set_value( value = lv_value ).
lo_element_3->append_child( new_child = lo_element_4 ). " fomula node lo_element_3->append_child( new_child = lo_element_4 ). " fomula node
ELSEIF <ls_sheet_content>-column_formula_id <> 0.
create_xl_sheet_column_formula(
EXPORTING
io_document = io_document
it_column_formulas = io_worksheet->column_formulas
is_sheet_content = <ls_sheet_content>
IMPORTING
eo_element = lo_element_4
CHANGING
ct_column_formulas_used = lt_column_formulas_used
cv_si = lv_si ).
lo_element_3->append_child( new_child = lo_element_4 ).
ELSEIF <ls_sheet_content>-cell_value IS NOT INITIAL "cell can have just style or formula ELSEIF <ls_sheet_content>-cell_value IS NOT INITIAL "cell can have just style or formula
AND <ls_sheet_content>-cell_value <> lc_dummy_cell_content. AND <ls_sheet_content>-cell_value <> lc_dummy_cell_content.
IF <ls_sheet_content>-data_type IS NOT INITIAL. IF <ls_sheet_content>-data_type IS NOT INITIAL.
@ -7137,6 +7254,7 @@ CLASS zcl_excel_writer_2007 IMPLEMENTATION.
lo_element_root TYPE REF TO if_ixml_element, lo_element_root TYPE REF TO if_ixml_element,
lo_element TYPE REF TO if_ixml_element, lo_element TYPE REF TO if_ixml_element,
lo_element2 TYPE REF TO if_ixml_element, lo_element2 TYPE REF TO if_ixml_element,
lo_element3 TYPE REF TO if_ixml_element,
lv_table_name TYPE string, lv_table_name TYPE string,
lv_id TYPE i, lv_id TYPE i,
lv_match TYPE i, lv_match TYPE i,
@ -7249,6 +7367,15 @@ CLASS zcl_excel_writer_2007 IMPLEMENTATION.
value = ls_fieldcat-totals_function ). value = ls_fieldcat-totals_function ).
ENDIF. ENDIF.
IF ls_fieldcat-column_formula IS NOT INITIAL.
lv_value = ls_fieldcat-column_formula.
CONDENSE lv_value.
lo_element3 = lo_document->create_simple_element_ns( name = 'calculatedColumnFormula'
parent = lo_element2 ).
lo_element3->set_value( lv_value ).
lo_element2->append_child( new_child = lo_element3 ).
ENDIF.
lo_element->append_child( new_child = lo_element2 ). lo_element->append_child( new_child = lo_element2 ).
ENDLOOP. ENDLOOP.
@ -7635,6 +7762,21 @@ CLASS zcl_excel_writer_2007 IMPLEMENTATION.
ENDMETHOD. ENDMETHOD.
METHOD is_formula_shareable.
DATA: lv_test_shared TYPE string.
ep_shareable = abap_false.
IF ip_formula NA '!'.
lv_test_shared = zcl_excel_common=>shift_formula(
iv_reference_formula = ip_formula
iv_shift_cols = 1
iv_shift_rows = 1 ).
IF lv_test_shared <> ip_formula.
ep_shareable = abap_true.
ENDIF.
ENDIF.
ENDMETHOD.
METHOD set_vml_shape_footer. METHOD set_vml_shape_footer.
CONSTANTS: lc_shape TYPE string VALUE '<v:shape id="{ID}" o:spid="_x0000_s1025" type="#_x0000_t75" style=''position:absolute;margin-left:0;margin-top:0;width:{WIDTH}pt;height:{HEIGHT}pt; z-index:1''>', CONSTANTS: lc_shape TYPE string VALUE '<v:shape id="{ID}" o:spid="_x0000_s1025" type="#_x0000_t75" style=''position:absolute;margin-left:0;margin-top:0;width:{WIDTH}pt;height:{HEIGHT}pt; z-index:1''>',

View File

@ -0,0 +1,170 @@
*"* use this source file for your ABAP unit test classes
CLASS ltc_column_formula DEFINITION DEFERRED.
CLASS ltc_is_formula_shareable DEFINITION DEFERRED.
CLASS zcl_excel_writer_2007 DEFINITION LOCAL FRIENDS
ltc_column_formula
ltc_is_formula_shareable.
CLASS ltc_column_formula DEFINITION FOR TESTING
RISK LEVEL HARMLESS
DURATION SHORT.
PRIVATE SECTION.
METHODS one_column_formula FOR TESTING RAISING cx_static_check.
METHODS two_column_formulas FOR TESTING RAISING cx_static_check.
METHODS setup.
METHODS set_cell
IMPORTING
is_cell_data TYPE zexcel_s_cell_data
RAISING
zcx_excel.
METHODS get_xml
RETURNING
VALUE(rv_xml) TYPE string.
DATA lo_document TYPE REF TO if_ixml_document.
DATA lo_excel TYPE REF TO zcl_excel_writer_2007.
DATA lo_ixml TYPE REF TO if_ixml.
DATA lo_root TYPE REF TO if_ixml_element.
DATA lt_column_formulas TYPE zcl_excel_worksheet=>mty_th_column_formula.
DATA lt_column_formulas_used TYPE zcl_excel_writer_2007=>mty_column_formulas_used.
DATA lv_si TYPE i.
ENDCLASS.
CLASS ltc_is_formula_shareable DEFINITION FOR TESTING
RISK LEVEL HARMLESS
DURATION SHORT.
PRIVATE SECTION.
METHODS is_formula_shareable FOR TESTING RAISING cx_static_check.
ENDCLASS.
CLASS ltc_column_formula IMPLEMENTATION.
METHOD one_column_formula.
DATA ls_cell_data TYPE zexcel_s_cell_data.
DATA lv_xml TYPE string.
ls_cell_data-cell_row = 2.
ls_cell_data-cell_column = 1.
ls_cell_data-column_formula_id = 1.
set_cell( ls_cell_data ).
lv_xml = get_xml( ).
cl_abap_unit_assert=>assert_equals( act = lv_xml exp = '<c r="R2C1"><f ref="A2:A4" si="0" t="shared">A2</f></c>' ).
ENDMETHOD.
METHOD two_column_formulas.
DATA ls_cell_data TYPE zexcel_s_cell_data.
DATA lv_xml TYPE string.
ls_cell_data-cell_row = 2.
ls_cell_data-cell_column = 1.
ls_cell_data-column_formula_id = 1.
set_cell( ls_cell_data ).
ls_cell_data-cell_row = 3.
ls_cell_data-cell_column = 1.
ls_cell_data-column_formula_id = 1.
set_cell( ls_cell_data ).
lv_xml = get_xml( ).
cl_abap_unit_assert=>assert_equals( act = lv_xml exp = '<c r="R2C1"><f ref="A2:A4" si="0" t="shared">A2</f></c>'
&& '<c r="R3C1"><f si="0" t="shared"/></c>' ).
ENDMETHOD.
METHOD set_cell.
DATA lo_cell TYPE REF TO if_ixml_element.
DATA lo_formula TYPE REF TO if_ixml_element.
lo_cell = lo_document->create_element( 'c' ).
lo_cell->set_attribute( name = 'r' value = |R{ is_cell_data-cell_row }C{ is_cell_data-cell_column }| ).
lo_root->append_child( lo_cell ).
lo_excel->create_xl_sheet_column_formula(
EXPORTING
io_document = lo_document
it_column_formulas = lt_column_formulas
is_sheet_content = is_cell_data
IMPORTING
eo_element = lo_formula
CHANGING
ct_column_formulas_used = lt_column_formulas_used
cv_si = lv_si ).
lo_cell->append_child( lo_formula ).
ENDMETHOD.
METHOD get_xml.
DATA lo_stream_factory TYPE REF TO if_ixml_stream_factory.
DATA lo_ostream TYPE REF TO if_ixml_ostream.
DATA lo_renderer TYPE REF TO if_ixml_renderer.
lo_stream_factory = lo_ixml->create_stream_factory( ).
lo_ostream = lo_stream_factory->create_ostream_cstring( string = rv_xml ).
lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ).
lo_renderer->render( ).
CALL TRANSFORMATION id SOURCE XML rv_xml RESULT XML rv_xml OPTIONS xml_header = 'no'.
IF strlen( rv_xml ) >= 2.
rv_xml = substring( val = rv_xml off = 1 ). " Remove Byte Order Mark (one character in Unicode systems)
ENDIF.
FIND REGEX '^<dummy>(.*)</dummy>$' IN rv_xml SUBMATCHES rv_xml.
ENDMETHOD.
METHOD setup.
DATA ls_column_formula TYPE zcl_excel_worksheet=>mty_s_column_formula.
lo_ixml = cl_ixml=>create( ).
lo_document = lo_ixml->create_document( ).
lo_root = lo_document->create_element( 'dummy' ).
lo_document->append_child( lo_root ).
CREATE OBJECT lo_excel.
ls_column_formula-id = 1.
ls_column_formula-formula = 'A2'.
ls_column_formula-table_top_left_row = 1.
ls_column_formula-table_bottom_right_row = 3.
INSERT ls_column_formula INTO TABLE lt_column_formulas.
ENDMETHOD.
ENDCLASS.
CLASS ltc_is_formula_shareable IMPLEMENTATION.
METHOD is_formula_shareable.
DATA lo_excel TYPE REF TO zcl_excel_writer_2007.
CREATE OBJECT lo_excel.
cl_abap_unit_assert=>assert_equals( act = lo_excel->is_formula_shareable( 'TblFlights[[#This Row],[Airfare]]+222' ) exp = abap_false ). " [@Airfare]+222
cl_abap_unit_assert=>assert_equals( act = lo_excel->is_formula_shareable( 'OtherSheet!A2' ) exp = abap_false ).
cl_abap_unit_assert=>assert_equals( act = lo_excel->is_formula_shareable( 'D2+100' ) exp = abap_true ).
cl_abap_unit_assert=>assert_equals( act = lo_excel->is_formula_shareable( 'A1&";"&_xlfn.IFS(TRUE,NamedRange)' ) exp = abap_true ).
ENDMETHOD.
ENDCLASS.

View File

@ -10,6 +10,7 @@
<CLSCCINCL>X</CLSCCINCL> <CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT> <FIXPT>X</FIXPT>
<UNICODE>X</UNICODE> <UNICODE>X</UNICODE>
<WITH_UNIT_TESTS>X</WITH_UNIT_TESTS>
</VSEOCLASS> </VSEOCLASS>
<DESCRIPTIONS> <DESCRIPTIONS>
<SEOCOMPOTX> <SEOCOMPOTX>

View File

@ -7,6 +7,7 @@
<DDLANGUAGE>E</DDLANGUAGE> <DDLANGUAGE>E</DDLANGUAGE>
<TABCLASS>INTTAB</TABCLASS> <TABCLASS>INTTAB</TABCLASS>
<DDTEXT>Cell data</DDTEXT> <DDTEXT>Cell data</DDTEXT>
<MASTERLANG>E</MASTERLANG>
<EXCLASS>1</EXCLASS> <EXCLASS>1</EXCLASS>
</DD02V> </DD02V>
<DD03P_TABLE> <DD03P_TABLE>
@ -52,6 +53,16 @@
<ADMINFIELD>0</ADMINFIELD> <ADMINFIELD>0</ADMINFIELD>
<COMPTYPE>E</COMPTYPE> <COMPTYPE>E</COMPTYPE>
</DD03P> </DD03P>
<DD03P>
<FIELDNAME>COLUMN_FORMULA_ID</FIELDNAME>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>X</INTTYPE>
<INTLEN>000004</INTLEN>
<DATATYPE>INT4</DATATYPE>
<LENG>000010</LENG>
<MASK> INT4</MASK>
<DDTEXT>Column Formula ID</DDTEXT>
</DD03P>
</DD03P_TABLE> </DD03P_TABLE>
</asx:values> </asx:values>
</asx:abap> </asx:abap>

View File

@ -7,6 +7,7 @@
<DDLANGUAGE>E</DDLANGUAGE> <DDLANGUAGE>E</DDLANGUAGE>
<TABCLASS>INTTAB</TABCLASS> <TABCLASS>INTTAB</TABCLASS>
<DDTEXT>Fieldcatalog for Table Binding</DDTEXT> <DDTEXT>Fieldcatalog for Table Binding</DDTEXT>
<MASTERLANG>E</MASTERLANG>
<EXCLASS>1</EXCLASS> <EXCLASS>1</EXCLASS>
</DD02V> </DD02V>
<DD03P_TABLE> <DD03P_TABLE>
@ -101,6 +102,15 @@
<LENG>000001</LENG> <LENG>000001</LENG>
<MASK> CHAR</MASK> <MASK> CHAR</MASK>
</DD03P> </DD03P>
<DD03P>
<FIELDNAME>COLUMN_FORMULA</FIELDNAME>
<ADMINFIELD>0</ADMINFIELD>
<INTTYPE>g</INTTYPE>
<INTLEN>000008</INTLEN>
<DATATYPE>STRG</DATATYPE>
<MASK> STRG</MASK>
<DDTEXT>Column Formula</DDTEXT>
</DD03P>
</DD03P_TABLE> </DD03P_TABLE>
</asx:values> </asx:values>
</asx:abap> </asx:abap>