You've already forked lazarus-ccr
fpspreadsheet: Support expression conditional cell formatting by XLSX, Excel-XML and ODS writers.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7541 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -265,6 +265,15 @@ begin
|
||||
fmtIdx := wb.AddCellFormat(fmt);
|
||||
sh.WriteConditionalCellFormat(Range(row, 2, row, lastCol), cfcNotContainsErrors, fmtIdx);
|
||||
|
||||
// conditional format: expression
|
||||
inc(row);
|
||||
sh.WriteText(row, 0, 'expression: ISNUMBER($E$5)');
|
||||
sh.WriteText(row, 1, 'background blue');
|
||||
InitFormatRecord(fmt);
|
||||
fmt.SetBackgroundColor(scBlue);
|
||||
fmtIdx := wb.AddCellFormat(fmt);
|
||||
sh.WriteConditionalCellFormat(Range(row, 2, row, 2), cfcExpression, '=ISNUMBER($E$5)', fmtIdx);
|
||||
|
||||
// Two rules in the same conditional format
|
||||
inc(row);
|
||||
sh.WriteText(row, 0, 'Two rules: #1: equal to 5, #2: equal to 3');
|
||||
|
@ -23,7 +23,8 @@ type
|
||||
cfcDuplicate, cfcUnique,
|
||||
cfcBeginsWith, cfcEndsWith,
|
||||
cfcContainsText, cfcNotContainsText,
|
||||
cfcContainsErrors, cfcNotContainsErrors
|
||||
cfcContainsErrors, cfcNotContainsErrors,
|
||||
cfcExpression
|
||||
);
|
||||
|
||||
TsCFCellRule = class(TsCFRule)
|
||||
|
@ -388,26 +388,28 @@ const
|
||||
'cell-content()>%s', 'cell-content()<%s', //cfcGreaterThan, cfcLessThan
|
||||
'cell-content()>=%s', 'cell-content<=%s', // cfcGreaterEqual, cfdLessEqual
|
||||
'cell-is-between(%s,%s)', 'cell-is-not-between(%s,%s)', // cfcBetween, cfcNotBetween,
|
||||
'', '', '', '', // cfcAboveAverage, cfcBelowAverage, cfcAboveEqualAverage, cfcBelowEqualAverage
|
||||
'', '', '', '', // cfcTop, cfcBottom, cfcTopPercent, cfcBottomPercent,
|
||||
'', '', // cfcDuplicate, cfcUnique,
|
||||
'', '', '', '', // cfcBeginsWith, cfcEndsWith, cfcContainsText, cfcNotContainsText,
|
||||
'', '' // cfcContainsErrors, cfcNotContainsErrors
|
||||
'', '', '', '', // cfcAboveAverage, cfcBelowAverage, cfcAboveEqualAverage, cfcBelowEqualAverage
|
||||
'', '', '', '', // cfcTop, cfcBottom, cfcTopPercent, cfcBottomPercent,
|
||||
'', '', // cfcDuplicate, cfcUnique,
|
||||
'', '', '', '', // cfcBeginsWith, cfcEndsWith, cfcContainsText, cfcNotContainsText,
|
||||
'', '', // cfcContainsErrors, cfcNotContainsErrors
|
||||
'is-true-formula(%s)' // cfcExpression
|
||||
);
|
||||
|
||||
CF_CALCEXT_OP: array[TsCFCondition] of string = (
|
||||
'=%s', '!=%s', // cfcEqual, cfcNotEqual
|
||||
'>%s', '<%s', //cfcGreaterThan, cfcLessThan
|
||||
'>=%s', '<=%s', // cfcGreaterEqual, cfdLessEqual
|
||||
'between(%s,%s)', 'not-between(%s,%s)', // cfcBetween, cfcNotBetween,
|
||||
'above-average', 'below-average', // cfcAboveAverage, cfcBelowAverage,
|
||||
'=%s', '!=%s', // cfcEqual, cfcNotEqual
|
||||
'>%s', '<%s', //cfcGreaterThan, cfcLessThan
|
||||
'>=%s', '<=%s', // cfcGreaterEqual, cfdLessEqual
|
||||
'between(%s,%s)', 'not-between(%s,%s)', // cfcBetween, cfcNotBetween,
|
||||
'above-average', 'below-average', // cfcAboveAverage, cfcBelowAverage,
|
||||
'above-equal-average', 'below-equal-average', // cfcAboveEqualAverage, cfcBelowEqualAverage
|
||||
'top-elements(%s)', 'bottom-elements(%s)', // cfcTop, cfcBottom,
|
||||
'top-percent(%s)', 'bottom-percent(%s)', // cfcTopPercent, cfcBottomPercent,
|
||||
'duplicate', 'unique', // cfcDuplicate, cfcUnique,
|
||||
'begins-with(%s)', 'ends-with(%s)', // cfcBeginsWith, cfcEndsWith,
|
||||
'contains-text(%s)', 'not-contains-text(%s)', // cfcContainsText, cfcNotContainsText,
|
||||
'is-error', 'is-no-error' // cfcContainsErrors, cfcNotContainsErrors
|
||||
'is-error', 'is-no-error', // cfcContainsErrors, cfcNotContainsErrors
|
||||
'formula-is(%s)' // cfcExprssion
|
||||
);
|
||||
|
||||
CF_VALUE_KIND: array[TsCFValueKind] of string = (
|
||||
@ -7398,8 +7400,18 @@ begin
|
||||
begin
|
||||
cf_cellRule := TsCFCellRule(cf.Rules[k]);
|
||||
cf_styleName := Format('conditional_%d', [cf_cellRule.FormatIndex]);
|
||||
operand1Str := CFOperandToStr(cf_cellrule.Operand1, cf_sheet);
|
||||
operand2Str := CFOperandToStr(cf_cellrule.Operand2, cf_sheet);
|
||||
if cf_cellRule.Condition = cfcExpression then
|
||||
begin
|
||||
operand1Str := VarToStr(cf_cellRule.Operand1);
|
||||
if (operand1Str <> '') and (operand1Str[1] <> '=') then
|
||||
operand1Str := '=' + operand1Str;
|
||||
operand1Str := CFOperandToStr(operand1Str, cf_sheet);
|
||||
operand2Str := '';
|
||||
end else
|
||||
begin
|
||||
operand1Str := CFOperandToStr(cf_cellrule.Operand1, cf_sheet);
|
||||
operand2Str := CFOperandToStr(cf_cellrule.Operand2, cf_sheet);
|
||||
end;
|
||||
cf_condition := Format(CF_STYLE_OP[cf_cellRule.Condition], [operand1Str, operand2Str]);
|
||||
|
||||
if cf_Condition <> '' then begin
|
||||
|
@ -229,7 +229,8 @@ const
|
||||
'@NOT(ISERROR(SEARCH(%0:s,RC)))', // cfcContainsText
|
||||
'@ISERROR(SEARCH(%0:s,RC))', // cfcNotContainsText,
|
||||
'@ISERROR(RC)', // cfcContainsErrors
|
||||
'@NOT(ISERROR(RC))' // cfcNotContainsErrors
|
||||
'@NOT(ISERROR(RC))', // cfcNotContainsErrors
|
||||
'@' // cfcExpression
|
||||
);
|
||||
// The leading '@' indicates that the formula will be used in <Value1> node
|
||||
|
||||
@ -2134,14 +2135,26 @@ begin
|
||||
Continue;
|
||||
end;
|
||||
|
||||
value1Str := CFOperandToStr(cfRule.Operand1, sheet);
|
||||
value2Str := CFOperandToStr(cfRule.Operand2, sheet);
|
||||
if cfRule.Condition = cfcExpression then
|
||||
begin
|
||||
s := cfRule.Operand1;
|
||||
if (s <> '') and (s[1] <> '=') then s := '=' + s;
|
||||
value1Str := CFOperandToStr(s, sheet);
|
||||
value2Str := '';
|
||||
end else
|
||||
begin
|
||||
value1Str := CFOperandToStr(cfRule.Operand1, sheet);
|
||||
value2Str := CFOperandToStr(cfRule.Operand2, sheet);
|
||||
end;
|
||||
|
||||
s := CF_CONDITIONS[cfRule.Condition];
|
||||
if s[1] = '@' then
|
||||
begin
|
||||
Delete(s, 1,1);
|
||||
s := Format(s, [value1Str, value2Str, rangeStr]);
|
||||
if s = '' then
|
||||
s := value1Str
|
||||
else
|
||||
s := Format(s, [value1Str, value2Str, rangeStr]);
|
||||
value1Str := s;
|
||||
s := '';
|
||||
end;
|
||||
@ -2152,9 +2165,11 @@ begin
|
||||
if s <> '' then
|
||||
AppendToStream(AStream, LF + INDENT4 +
|
||||
'<Qualifier>' + s + '</Qualifier>');
|
||||
|
||||
if value1Str <> '' then
|
||||
AppendToStream(AStream, LF + INDENT4 +
|
||||
'<Value1>' + value1Str + '</Value1>');
|
||||
|
||||
if (cfRule.Condition in [cfcBetween, cfcNotBetween]) and (value2Str <> '') then
|
||||
AppendToStream(AStream, LF + INDENT4 +
|
||||
'<Value2>' + value2Str + '</Value2>');
|
||||
|
@ -430,7 +430,8 @@ const
|
||||
'duplicateValues', 'uniqueValues', // cfcDuplicate, cfcUnique,
|
||||
'beginsWith', 'endsWith', // cfcBeginsWith, cfcEndsWith,
|
||||
'containsText', 'notContainsText', // cfcContainsText, cfcNotContainsText,
|
||||
'containsErrors', 'notContainsErrors' // cfcContainsErrors, cfcNotContainsErrors
|
||||
'containsErrors', 'notContainsErrors', // cfcContainsErrors, cfcNotContainsErrors
|
||||
'expression' // cfcExpression
|
||||
);
|
||||
|
||||
CF_OPERATOR_NAMES: array[TsCFCondition] of string = (
|
||||
@ -440,7 +441,8 @@ const
|
||||
'', '', '', '', // cfcTop, cfcBottom, cfcTopPercent, cfcBottomPercent,
|
||||
'', '', // cfcDuplicate, cfcUnique,
|
||||
'', '', '', 'notContains', //cfcBeginsWith, cfcEndsWith, cfcContainsText, cfcNotContainsText,
|
||||
'', '' // cfcContainsErrors, cfcNotContainsErrors
|
||||
'', '', // cfcContainsErrors, cfcNotContainsErrors
|
||||
'' // cfcExpression
|
||||
);
|
||||
|
||||
function StrToFillStyle(s: String): TsFillStyle;
|
||||
@ -4115,6 +4117,12 @@ begin
|
||||
'</formula>';
|
||||
param1Str := ' text="' + VarToStr(ARule.Operand1) + '"';
|
||||
end;
|
||||
cfcExpression:
|
||||
begin
|
||||
s := ARule.Operand1;
|
||||
if (s <> '') and (s[1] = '=') then Delete(s, 1, 1);
|
||||
formula1Str := '<formula>' + s + '</formula>';
|
||||
end;
|
||||
else
|
||||
FWorkbook.AddErrorMsg('ConditionalFormat operator not supported.');
|
||||
end;
|
||||
|
Reference in New Issue
Block a user