From d19ac690c6089dcdfe9d2895baab2e8cd7279399 Mon Sep 17 00:00:00 2001 From: Paul Hardy Date: Sat, 9 Oct 2021 18:49:17 +1100 Subject: [PATCH] Fix for Issue #783 - Conditional Formatting for Cells that "Begin With" a certain string - Third Attempt (#786) * Issue 783 - Third Attempt * Extension to fix all 4 text-specific operators Co-authored-by: Lars Hvam Co-authored-by: sandraros Co-authored-by: Abo --- src/demos/zdemo_excel27.prog.abap | 68 ++++++++++++++++++++++++++++- src/zcl_excel_style_cond.clas.abap | 12 +++++ src/zcl_excel_writer_2007.clas.abap | 67 +++++++++++++++++++++++++++- 3 files changed, 144 insertions(+), 3 deletions(-) diff --git a/src/demos/zdemo_excel27.prog.abap b/src/demos/zdemo_excel27.prog.abap index e003dbe..5f93546 100644 --- a/src/demos/zdemo_excel27.prog.abap +++ b/src/demos/zdemo_excel27.prog.abap @@ -17,9 +17,12 @@ DATA: lo_excel TYPE REF TO zcl_excel, lo_style_cond TYPE REF TO zcl_excel_style_cond, lo_style_1 TYPE REF TO zcl_excel_style, lo_style_2 TYPE REF TO zcl_excel_style, + lo_style TYPE REF TO zcl_excel_style, lv_style_1_guid TYPE zexcel_cell_style, lv_style_2_guid TYPE zexcel_cell_style, - ls_cellis TYPE zexcel_conditional_cellis. + lv_style_guid TYPE zexcel_cell_style, + ls_cellis TYPE zexcel_conditional_cellis, + ls_textfunction TYPE zcl_excel_style_cond=>ts_conditional_textfunction. DATA: lv_title TYPE zexcel_sheet_title. @@ -46,7 +49,7 @@ START-OF-SELECTION. " Get active sheet lo_worksheet = lo_excel->get_active_worksheet( ). - lv_title = 'Data Validation'. + lv_title = 'Conditional formatting'. lo_worksheet->set_title( lv_title ). " Set values for dropdown lo_worksheet->set_cell( ip_row = 2 ip_column = 'A' ip_value = c_fish ). @@ -97,5 +100,66 @@ START-OF-SELECTION. ip_stop_column = 'C' ip_stop_row = 2 ). + " Conditional formatting for all operators + DEFINE conditional_formatting_cellis. + + lo_style = lo_excel->add_new_style( ). + lo_style->font->color-rgb = zcl_excel_style_color=>c_white. + lo_style->number_format->format_code = '@\ "' && &7 && '"'. + lo_style->alignment->wraptext = abap_true. + lv_style_guid = lo_style->get_guid( ). + + lo_worksheet->set_cell( ip_row = &2 ip_column = &1 ip_formula = '$C$2' ip_style = lv_style_guid ). + + lo_style_cond = lo_worksheet->add_new_style_cond( ). + lo_style_cond->rule = &3. + ls_cellis-operator = &4. + ls_cellis-formula = &5. + ls_cellis-formula2 = &6. + ls_cellis-cell_style = lv_style_1_guid. + lo_style_cond->mode_cellis = ls_cellis. + lo_style_cond->priority = 1. + lo_style_cond->set_range( ip_start_column = &1 + ip_start_row = &2 + ip_stop_column = &1 + ip_stop_row = &2 ). + END-OF-DEFINITION. + + conditional_formatting_cellis 'C' 4 zcl_excel_style_cond=>c_rule_cellis zcl_excel_style_cond=>c_operator_equal '="Anchovy"' '' 'equal to Anchovy'. + conditional_formatting_cellis 'D' 4 zcl_excel_style_cond=>c_rule_cellis zcl_excel_style_cond=>c_operator_notequal '="Anchovy"' '' 'not equal to Anchovy'. + conditional_formatting_cellis 'E' 4 zcl_excel_style_cond=>c_rule_cellis zcl_excel_style_cond=>c_operator_between '="B"' '="CC"' 'between B and CC'. + conditional_formatting_cellis 'F' 4 zcl_excel_style_cond=>c_rule_cellis zcl_excel_style_cond=>c_operator_greaterthan '="Catfish"' '' 'greater than Catfish'. + conditional_formatting_cellis 'G' 4 zcl_excel_style_cond=>c_rule_cellis zcl_excel_style_cond=>c_operator_greaterthanorequal '="Catfish"' '' 'greater than or equal to Catfish'. + conditional_formatting_cellis 'H' 4 zcl_excel_style_cond=>c_rule_cellis zcl_excel_style_cond=>c_operator_lessthan '="Catfish"' '' 'less than Catfish'. + conditional_formatting_cellis 'I' 4 zcl_excel_style_cond=>c_rule_cellis zcl_excel_style_cond=>c_operator_lessthanorequal '="Catfish"' '' 'less than or equal to Catfish'. + + DEFINE conditional_formatting_textfun. + + lo_style = lo_excel->add_new_style( ). + lo_style->font->color-rgb = zcl_excel_style_color=>c_white. + lo_style->number_format->format_code = '@\ "' && &6 && '"'. + lo_style->alignment->wraptext = abap_true. + lv_style_guid = lo_style->get_guid( ). + + lo_worksheet->set_cell( ip_row = &2 ip_column = &1 ip_formula = '$C$2' ip_style = lv_style_guid ). + + lo_style_cond = lo_worksheet->add_new_style_cond( ). + lo_style_cond->rule = &3. + ls_textfunction-textfunction = &4. + ls_textfunction-text = &5. + ls_textfunction-cell_style = lv_style_1_guid. + lo_style_cond->mode_textfunction = ls_textfunction. + lo_style_cond->priority = 1. + lo_style_cond->set_range( ip_start_column = &1 + ip_start_row = &2 + ip_stop_column = &1 + ip_stop_row = &2 ). + END-OF-DEFINITION. + + conditional_formatting_textfun 'C' 6 zcl_excel_style_cond=>c_rule_textfunction zcl_excel_style_cond=>c_textfunction_beginswith 'A' 'begins with A'. + conditional_formatting_textfun 'D' 6 zcl_excel_style_cond=>c_rule_textfunction zcl_excel_style_cond=>c_textfunction_containstext 'h' 'contains text h'. + conditional_formatting_textfun 'E' 6 zcl_excel_style_cond=>c_rule_textfunction zcl_excel_style_cond=>c_textfunction_endswith 'p' 'ends with p'. + conditional_formatting_textfun 'F' 6 zcl_excel_style_cond=>c_rule_textfunction zcl_excel_style_cond=>c_textfunction_notcontains 'h' 'not contains h'. + *** Create output lcl_output=>output( lo_excel ). diff --git a/src/zcl_excel_style_cond.clas.abap b/src/zcl_excel_style_cond.clas.abap index 47c5e47..3506785 100644 --- a/src/zcl_excel_style_cond.clas.abap +++ b/src/zcl_excel_style_cond.clas.abap @@ -9,6 +9,12 @@ CLASS zcl_excel_style_cond DEFINITION *"* public components of class ZCL_EXCEL_STYLE_COND *"* do not include other source files here!!! TYPES tv_conditional_show_value TYPE c LENGTH 1. + TYPES tv_textfunction TYPE string. + TYPES: BEGIN OF ts_conditional_textfunction, + text TYPE string, + textfunction TYPE tv_textfunction, + cell_style TYPE zexcel_cell_style, + END OF ts_conditional_textfunction. CONSTANTS c_cfvo_type_formula TYPE zexcel_conditional_type VALUE 'formula'. "#EC NOTEXT CONSTANTS c_cfvo_type_max TYPE zexcel_conditional_type VALUE 'max'. "#EC NOTEXT CONSTANTS c_cfvo_type_min TYPE zexcel_conditional_type VALUE 'min'. "#EC NOTEXT @@ -44,6 +50,10 @@ CLASS zcl_excel_style_cond DEFINITION CONSTANTS c_operator_none TYPE zexcel_condition_operator VALUE ''. "#EC NOTEXT CONSTANTS c_operator_notcontains TYPE zexcel_condition_operator VALUE 'notContains'. "#EC NOTEXT CONSTANTS c_operator_notequal TYPE zexcel_condition_operator VALUE 'notEqual'. "#EC NOTEXT + CONSTANTS c_textfunction_beginswith TYPE tv_textfunction VALUE 'beginsWith'. "#EC NOTEXT + CONSTANTS c_textfunction_containstext TYPE tv_textfunction VALUE 'containsText'. "#EC NOTEXT + CONSTANTS c_textfunction_endswith TYPE tv_textfunction VALUE 'endsWith'. "#EC NOTEXT + CONSTANTS c_textfunction_notcontains TYPE tv_textfunction VALUE 'notContains'. "#EC NOTEXT CONSTANTS c_rule_cellis TYPE zexcel_condition_rule VALUE 'cellIs'. "#EC NOTEXT CONSTANTS c_rule_containstext TYPE zexcel_condition_rule VALUE 'containsText'. "#EC NOTEXT CONSTANTS c_rule_databar TYPE zexcel_condition_rule VALUE 'dataBar'. "#EC NOTEXT @@ -51,11 +61,13 @@ CLASS zcl_excel_style_cond DEFINITION CONSTANTS c_rule_iconset TYPE zexcel_condition_rule VALUE 'iconSet'. "#EC NOTEXT CONSTANTS c_rule_colorscale TYPE zexcel_condition_rule VALUE 'colorScale'. "#EC NOTEXT CONSTANTS c_rule_none TYPE zexcel_condition_rule VALUE 'none'. "#EC NOTEXT + CONSTANTS c_rule_textfunction TYPE zexcel_condition_rule VALUE ''. "#EC NOTEXT CONSTANTS c_rule_top10 TYPE zexcel_condition_rule VALUE 'top10'. "#EC NOTEXT CONSTANTS c_rule_above_average TYPE zexcel_condition_rule VALUE 'aboveAverage'. "#EC NOTEXT CONSTANTS c_showvalue_false TYPE tv_conditional_show_value VALUE 0. "#EC NOTEXT CONSTANTS c_showvalue_true TYPE tv_conditional_show_value VALUE 1. "#EC NOTEXT DATA mode_cellis TYPE zexcel_conditional_cellis . + DATA mode_textfunction TYPE ts_conditional_textfunction . DATA mode_colorscale TYPE zexcel_conditional_colorscale . DATA mode_databar TYPE zexcel_conditional_databar . DATA mode_expression TYPE zexcel_conditional_expression . diff --git a/src/zcl_excel_writer_2007.clas.abap b/src/zcl_excel_writer_2007.clas.abap index 18404e7..9d5c714 100644 --- a/src/zcl_excel_writer_2007.clas.abap +++ b/src/zcl_excel_writer_2007.clas.abap @@ -3758,6 +3758,8 @@ CLASS zcl_excel_writer_2007 IMPLEMENTATION. lc_xml_attr_dxfid TYPE string VALUE 'dxfId', lc_xml_attr_priority TYPE string VALUE 'priority', lc_xml_attr_operator TYPE string VALUE 'operator', + lc_xml_attr_text TYPE string VALUE 'text', + lc_xml_attr_notContainsText TYPE string VALUE 'notContainsText', lc_xml_attr_allowblank TYPE string VALUE 'allowBlank', lc_xml_attr_showinputmessage TYPE string VALUE 'showInputMessage', lc_xml_attr_showerrormessage TYPE string VALUE 'showErrorMessage', @@ -3819,6 +3821,10 @@ CLASS zcl_excel_writer_2007 IMPLEMENTATION. ls_colorscale TYPE zexcel_conditional_colorscale, ls_iconset TYPE zexcel_conditional_iconset, ls_cellis TYPE zexcel_conditional_cellis, + ls_textfunction TYPE zcl_excel_style_cond=>ts_conditional_textfunction, + lv_column_start TYPE zexcel_cell_column_alpha, + lv_row_start TYPE zexcel_cell_row, + lv_cell_coords TYPE zexcel_cell_coords, ls_expression TYPE zexcel_conditional_expression, ls_conditional_top10 TYPE zexcel_conditional_top10, ls_conditional_above_avg TYPE zexcel_conditional_above_avg, @@ -3845,7 +3851,9 @@ CLASS zcl_excel_writer_2007 IMPLEMENTATION. lo_autofilter TYPE REF TO zcl_excel_autofilter, lv_ref TYPE string, lt_condformating_ranges TYPE ty_condformating_ranges, - ls_condformating_range TYPE ty_condformating_range. + ls_condformating_range TYPE ty_condformating_range, + ld_first_half TYPE string, + ld_second_half TYPE string. FIELD-SYMBOLS: TYPE zexcel_s_cell_data, LIKE LINE OF lt_range_merge, @@ -4543,7 +4551,15 @@ CLASS zcl_excel_writer_2007 IMPLEMENTATION. " cfRule node lo_element_2 = lo_document->create_simple_element( name = lc_xml_node_cfrule parent = lo_document ). + IF lo_style_cond->rule = zcl_excel_style_cond=>c_rule_textfunction. + IF lo_style_cond->mode_textfunction-textfunction = zcl_excel_style_cond=>c_textfunction_notcontains. + lv_value = `notContainsText`. + ELSE. + lv_value = lo_style_cond->mode_textfunction-textfunction. + ENDIF. + ELSE. lv_value = lo_style_cond->rule. + ENDIF. lo_element_2->set_attribute_ns( name = lc_xml_attr_type value = lv_value ). lv_value = lo_style_cond->priority. @@ -4769,6 +4785,55 @@ CLASS zcl_excel_writer_2007 IMPLEMENTATION. lo_element_3->set_value( value = lv_value ). lo_element_2->append_child( new_child = lo_element_3 ). " 2nd formula node ENDIF. +*--------------------------------------------------------------------------------------* +* The below code creates an EXM structure in the following format: +* -- +* +* LEFT(G6,LEN("1"))="1" +* +* +*--------------------------------------------------------------------------------------* + WHEN zcl_excel_style_cond=>c_rule_textfunction. + ls_textfunction = lo_style_cond->mode_textfunction. + READ TABLE me->styles_cond_mapping INTO ls_style_cond_mapping WITH KEY guid = ls_cellis-cell_style. + lv_value = ls_style_cond_mapping-dxf. + CONDENSE lv_value. + lo_element_2->set_attribute_ns( name = lc_xml_attr_dxfid + value = lv_value ). + lv_value = ls_textfunction-textfunction. + lo_element_2->set_attribute_ns( name = lc_xml_attr_operator + value = lv_value ). + + " text + lv_value = ls_textfunction-text. + lo_element_2->set_attribute_ns( name = lc_xml_attr_text + value = lv_value ). + + " formula node + zcl_excel_common=>convert_range2column_a_row( + EXPORTING + i_range = lo_style_cond->get_dimension_range( ) + IMPORTING + e_column_start = lv_column_start + e_row_start = lv_row_start ). + lv_cell_coords = |{ lv_column_start }{ lv_row_start }|. + CASE ls_textfunction-textfunction. + WHEN zcl_excel_style_cond=>c_textfunction_beginswith. + lv_value = |LEFT({ lv_cell_coords },LEN("{ escape( val = ls_textfunction-text format = cl_abap_format=>e_html_text ) }"))=| + && |"{ escape( val = ls_textfunction-text format = cl_abap_format=>e_html_text ) }"|. + WHEN zcl_excel_style_cond=>c_textfunction_containstext. + lv_value = |NOT(ISERROR(SEARCH("{ escape( val = ls_textfunction-text format = cl_abap_format=>e_html_text ) }",{ lv_cell_coords })))|. + WHEN zcl_excel_style_cond=>c_textfunction_endswith. + lv_value = |RIGHT({ lv_cell_coords },LEN("{ escape( val = ls_textfunction-text format = cl_abap_format=>e_html_text ) }"))=| + && |"{ escape( val = ls_textfunction-text format = cl_abap_format=>e_html_text ) }"|. + WHEN zcl_excel_style_cond=>c_textfunction_notcontains. + lv_value = |ISERROR(SEARCH("{ escape( val = ls_textfunction-text format = cl_abap_format=>e_html_text ) }",{ lv_cell_coords }))|. + WHEN OTHERS. + ENDCASE. + lo_element_3 = lo_document->create_simple_element( name = lc_xml_node_formula + parent = lo_document ). + lo_element_3->set_value( value = lv_value ). + lo_element_2->append_child( new_child = lo_element_3 ). " formula node WHEN zcl_excel_style_cond=>c_rule_expression. ls_expression = lo_style_cond->mode_expression.