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;