diff --git a/components/fpspreadsheet/examples/other/conditional_formatting/demo_conditional_formatting.pas b/components/fpspreadsheet/examples/other/conditional_formatting/demo_conditional_formatting.pas index c9f61297e..5af5458dc 100644 --- a/components/fpspreadsheet/examples/other/conditional_formatting/demo_conditional_formatting.pas +++ b/components/fpspreadsheet/examples/other/conditional_formatting/demo_conditional_formatting.pas @@ -16,7 +16,7 @@ begin try sh := wb.AddWorksheet('test'); - { ------ 1st conditional format ------------------------------------------ } + { ------ 1st conditional format : cfcEqual ------------------------------- } sh.WriteNumber(0, 0, 1.0); sh.WriteNumber(1, 0, 2.0); sh.WriteNumber(2, 0, 3.0); @@ -37,12 +37,11 @@ begin fmt.SetFont(wb.AddFont(font)); // Add format record to format list fmtIdx := wb.AddCellFormat(fmt); - // Use the format as conditional format of A1:A6 when cells are equal to 3. sh.WriteConditionalCellFormat(Range(0, 0, 5, 0), cfcEqual, 3.0, fmtIdx); - { ------- 2nd conditional format ----------------------------------------- } + { ------- 2nd conditional format : cfcBelowEqualAverage ------------------ } sh.WriteNumber(0, 2, 10.0); sh.WriteNumber(1, 2, 20.0); sh.WriteNumber(2, 2, 15.0); @@ -52,9 +51,25 @@ begin InitFormatRecord(fmt); fmt.SetBackgroundColor(scRed); fmtIdx := wb.AddCellFormat(fmt); - sh.WriteConditionalCellFormat(Range(0, 2, 4, 2), cfcBelowEqualAverage, fmtIdx); + { ------- 3rd and 4th conditional formats : beginWith, containsText ------ } + sh.WriteText(0, 4, 'abc'); + sh.WriteText(1, 4, 'def'); + sh.WriteText(2, 4, 'bac'); + sh.WriteText(3, 4, 'dbc'); + sh.WriteText(4, 4, 'acb'); + sh.WriteText(5, 4, 'aca'); + + InitFormatRecord(fmt); + fmt.SetBackgroundColor($DEF1F4); + fmtIdx := wb.AddCellFormat(fmt); + sh.WriteConditionalCellFormat(Range(0, 4, 5, 4), cfcBeginsWith, 'a', fmtIdx); + + fmt.SetBackgroundColor($D08330); + fmtIdx := wb.AddCellFormat(fmt); + sh.WriteConditionalCellFormat(Range(0, 4, 5, 4), cfcContainsText, 'bc', fmtIdx); + { ------ Save workbook to file-------------------------------------------- } wb.WriteToFile('test.xlsx', true); finally diff --git a/components/fpspreadsheet/source/common/fpsconditionalformat.pas b/components/fpspreadsheet/source/common/fpsconditionalformat.pas index 430b37cdc..31b25cf9e 100644 --- a/components/fpspreadsheet/source/common/fpsconditionalformat.pas +++ b/components/fpspreadsheet/source/common/fpsconditionalformat.pas @@ -19,9 +19,9 @@ type cfcGreaterThan, cfcLessThan, cfcGreaterEqual, cfcLessEqual, cfcBetween, cfcNotBetween, cfcAboveAverage, cfcBelowAverage, cfcAboveEqualAverage, cfcBelowEqualAverage, - cfcBeginsWidth, cfcEndsWith, cfcDuplicate, cfcUnique, - cfcContainsText, cfcNotContaisText, + cfcBeginsWith, cfcEndsWith, + cfcContainsText, cfcNotContainsText, cfcContainsErrors, cfcNotContainsErrors ); diff --git a/components/fpspreadsheet/source/common/xlsxooxml.pas b/components/fpspreadsheet/source/common/xlsxooxml.pas index c5f709d40..8d7d00851 100644 --- a/components/fpspreadsheet/source/common/xlsxooxml.pas +++ b/components/fpspreadsheet/source/common/xlsxooxml.pas @@ -145,8 +145,10 @@ type procedure WriteCols(AStream: TStream; AWorksheet: TsBasicWorksheet); procedure WriteComments(AWorksheet: TsBasicWorksheet); procedure WriteConditionalFormat(AStream: TStream; AFormat: TsConditionalFormat; var APriority: Integer); - procedure WriteConditionalFormatCellRule(AStream: TStream; ARule: TsCFCellRule; APriority: Integer); - procedure WriteConditionalFormatRule(AStream: TStream; ARule: TsCFRule; var APriority: Integer); + procedure WriteConditionalFormatCellRule(AStream: TStream; ARule: TsCFCellRule; + ARange: TsCellRange; APriority: Integer); + procedure WriteConditionalFormatRule(AStream: TStream; ARule: TsCFRule; + const ARange: TsCellRange; var APriority: Integer); procedure WriteConditionalFormats(AStream: TStream; AWorksheet: TsBasicWorksheet); procedure WriteDefinedNames(AStream: TStream); procedure WriteDifferentialFormat(AStream: TStream; AFormat: PsCellFormat); @@ -3332,29 +3334,38 @@ begin for i := 0 to AFormat.RulesCount-1 do begin rule := AFormat.Rules[i]; - WriteConditionalFormatRule(AStream, rule, APriority); + WriteConditionalFormatRule(AStream, rule, AFormat.CellRange, APriority); end; AppendToStream(AStream, ''); end; procedure TsSpreadOOXMLWriter.WriteConditionalFormatCellRule(AStream: TStream; - ARule: TsCFCellRule; APriority: Integer); + ARule: TsCFCellRule; ARange: TsCellRange; APriority: Integer); const OPERATOR_NAMES_1: array[cfcEqual..cfcLessEqual] of String = ('equal', 'notEqual', 'greaterThan', 'lessThan', 'greaterThanOrEqual', 'lessThanOrEqual'); OPERATOR_NAMES_2: array[cfcBetween..cfcNotBetween] of String = ('between', 'notBetween'); + OPERATOR_NAMES_Text: array[cfcBeginsWith..cfcNotContainsText] of String = + ('beginsWith', 'endsWith', 'containsText', 'notContainsText'); + FORMULA: array[cfcBeginsWith..cfcNotContainsText] of String = ( + 'LEFT(%0:s,LEN("%1:s"))="%1:s"', // cfcBeginsWith + 'RIGHT(%0:s,Len("%1:s"))="%1:s"', // cfcEndsWidth + 'NOT(ISERROR(SEARCH("%1:s",%0:s)))', // cfcContainsText + 'ISERROR(SEARCH("%1:s",%0:s))' // cfcNotContainsText + ); var i: Integer; - fmtID: Integer; - aveStr, stdDevStr, eqAveStr: String; + dxfID: Integer; + aveStr, stdDevStr, eqAveStr, opStr: String; + firstCellOfRange: String; begin - fmtID := -1; + dxfID := -1; for i := 0 to High(FDifferentialFormatIndexList) do if FDifferentialFormatIndexList[i] = ARule.FormatIndex then begin - fmtID := i; + dxfID := i; break; end; @@ -3364,7 +3375,7 @@ begin '' + '%s'+ '', [ - fmtID, APriority, OPERATOR_NAMES_1[ARule.Condition], ARule.Operand1 + dxfID, APriority, OPERATOR_NAMES_1[ARule.Condition], ARule.Operand1 ])); cfcBetween, cfcNotBetween: @@ -3373,7 +3384,7 @@ begin '%s'+ '%s'+ '', [ - fmtId, APriority, OPERATOR_NAMES_1[ARule.Condition], ARule.Operand1, ARule.Operand2 + dxfId, APriority, OPERATOR_NAMES_1[ARule.Condition], ARule.Operand1, ARule.Operand2 ])); cfcAboveAverage..cfcBelowEqualAverage: @@ -3392,7 +3403,24 @@ begin stdDevStr := Format(' stdDev="%d"', [ARule.Operand1]); AppendToStream(AStream, Format( '', - [fmtId, APriority, aveStr, stdDevStr, eqAveStr])); + [dxfId, APriority, aveStr, stdDevStr, eqAveStr])); + end; + + cfcBeginsWith..cfcNotContainsText: + begin + firstCellOfRange := GetCellString(ARange.Row1, ARange.Col1); + if ARule.Condition = cfcNotContainsText then opStr := ' operator="notContains"' else opStr := ''; + AppendToStream(AStream, Format( + ''+ + '' + FORMULA[ARule.Condition] + '' + + '', [ + firstCellOfRange, // must be 1st ... + ARule.Operand1, // ... and 2nd parameters (see FORMULA[]) + OPERATOR_NAMES_TEXT[ARule.Condition], + dxfId, + APriority, + opStr + ])); end; else FWorkbook.AddErrorMsg('ConditionalFormat operator not supported.'); @@ -3400,10 +3428,10 @@ begin end; procedure TsSpreadOOXMLWriter.WriteConditionalFormatRule(AStream: TStream; - ARule: TsCFRule; var APriority: Integer); + ARule: TsCFRule; const ARange: TsCellRange; var APriority: Integer); begin if ARule is TsCFCellRule then begin - WriteConditionalFormatCellRule(AStream, TsCFCellRule(ARule), APriority); + WriteConditionalFormatCellRule(AStream, TsCFCellRule(ARule), ARange, APriority); dec(APriority); end; end;