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