fpspreadsheet: Write some more conditional formatting conditions to ODS.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7507 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2020-07-01 10:40:36 +00:00
parent 1845d0fd8d
commit 54fc098d03
4 changed files with 85 additions and 27 deletions

View File

@ -38,7 +38,7 @@ begin
sh.WriteNumber(i, 8, 7.0); sh.WriteNumber(i, 8, 7.0);
sh.WriteNumber(i, 9, 8.0); sh.WriteNumber(i, 9, 8.0);
sh.WriteNumber(i, 10, 9.0); sh.WriteNumber(i, 10, 9.0);
sh.WriteNumber(i, 11, 10.0); //sh.WriteNumber(i, 11, 10.0);
sh.WriteText(i, 12, 'abc'); sh.WriteText(i, 12, 'abc');
sh.WriteText(i, 13, 'abc'); sh.WriteText(i, 13, 'abc');
sh.WriteBlank(i, 14); sh.WriteBlank(i, 14);
@ -60,7 +60,7 @@ begin
fmtIdx := wb.AddCellFormat(fmt); fmtIdx := wb.AddCellFormat(fmt);
// Write conditional format // Write conditional format
sh.WriteConditionalCellFormat(Range(row, 2, row, lastCol), cfcEqual, 5, fmtIdx); sh.WriteConditionalCellFormat(Range(row, 2, row, lastCol), cfcEqual, 5, fmtIdx);
(*
// conditional format #2: equal to text constant // conditional format #2: equal to text constant
inc(row); inc(row);
sh.WriteText(row, 0, 'equal to text "abc"'); sh.WriteText(row, 0, 'equal to text "abc"');
@ -123,7 +123,7 @@ begin
InitFormatRecord(fmt); InitFormatRecord(fmt);
fmt.SetBackground(fsThinStripeDiagUp, scRed, scYellow); fmt.SetBackground(fsThinStripeDiagUp, scRed, scYellow);
fmtIdx := wb.AddCellFormat(fmt); fmtIdx := wb.AddCellFormat(fmt);
sh.WriteConditionalCellFormat(Range(row, 2, row, lastCol), cfcAboveAverage, fmtIdx); sh.WriteConditionalCellFormat(Range(row, 2, row, 10), cfcAboveAverage, fmtIdx); // only 1..9 -> ave = 5
// conditional format #6: below average // conditional format #6: below average
inc(row); inc(row);
@ -132,7 +132,7 @@ begin
InitFormatRecord(fmt); InitFormatRecord(fmt);
fmt.SetBackground(fsGray25, scRed, scYellow); fmt.SetBackground(fsGray25, scRed, scYellow);
fmtIdx := wb.AddCellFormat(fmt); fmtIdx := wb.AddCellFormat(fmt);
sh.WriteConditionalCellFormat(Range(row, 2, row, lastCol), cfcBelowAverage, fmtIdx); sh.WriteConditionalCellFormat(Range(row, 2, row, 10), cfcBelowAverage, fmtIdx); // only 1..9 -> ave = 5
// conditional format #6: above or equal to average // conditional format #6: above or equal to average
inc(row); inc(row);
@ -141,7 +141,7 @@ begin
InitFormatRecord(fmt); InitFormatRecord(fmt);
fmt.SetBackground(fsThinStripeHor, scRed, scYellow); fmt.SetBackground(fsThinStripeHor, scRed, scYellow);
fmtIdx := wb.AddCellFormat(fmt); fmtIdx := wb.AddCellFormat(fmt);
sh.WriteConditionalCellFormat(Range(row, 2, row, lastCol), cfcAboveEqualAverage, fmtIdx); sh.WriteConditionalCellFormat(Range(row, 2, row, 10), cfcAboveEqualAverage, fmtIdx); // only 1..9 -> ave = 5
// conditional format #6: below or equal to average // conditional format #6: below or equal to average
inc(row); inc(row);
@ -150,7 +150,7 @@ begin
InitFormatRecord(fmt); InitFormatRecord(fmt);
fmt.SetBackground(fsThinStripeVert, scRed, scYellow); fmt.SetBackground(fsThinStripeVert, scRed, scYellow);
fmtIdx := wb.AddCellFormat(fmt); fmtIdx := wb.AddCellFormat(fmt);
sh.WriteConditionalCellFormat(Range(row, 2, row, lastCol), cfcBelowEqualAverage, fmtIdx); sh.WriteConditionalCellFormat(Range(row, 2, row, 10), cfcBelowEqualAverage, fmtIdx); // only 1..9 -> ave = 5
// conditional format #6: top 3 values // conditional format #6: top 3 values
inc(row); inc(row);
@ -183,7 +183,7 @@ begin
fmt.SetBackgroundColor($FFC0C0); fmt.SetBackgroundColor($FFC0C0);
fmtIdx := wb.AddCellFormat(fmt); fmtIdx := wb.AddCellFormat(fmt);
sh.WriteConditionalCellFormat(Range(row, 2, row, lastCol), cfcBottomPercent, 10, fmtIdx); sh.WriteConditionalCellFormat(Range(row, 2, row, lastCol), cfcBottomPercent, 10, fmtIdx);
(*
// conditional format #6: duplicates // conditional format #6: duplicates
inc(row); inc(row);
sh.WriteText(row, 0, 'duplicate values'); sh.WriteText(row, 0, 'duplicate values');
@ -199,7 +199,7 @@ begin
fmt.SetBackgroundColor($D0D0FF); fmt.SetBackgroundColor($D0D0FF);
fmtIdx := wb.AddCellFormat(fmt); fmtIdx := wb.AddCellFormat(fmt);
sh.WriteConditionalCellFormat(Range(row, 2, row, lastCol), cfcUnique, fmtIdx); sh.WriteConditionalCellFormat(Range(row, 2, row, lastCol), cfcUnique, fmtIdx);
*)
// conditional format #6: contains any text // conditional format #6: contains any text
inc(row); inc(row);
sh.WriteText(row, 0, 'contains any text'); sh.WriteText(row, 0, 'contains any text');
@ -247,7 +247,7 @@ begin
fmt.SetBackgroundColor(scRed); fmt.SetBackgroundColor(scRed);
fmtIdx := wb.AddCellFormat(fmt); fmtIdx := wb.AddCellFormat(fmt);
sh.WriteConditionalCellFormat(Range(row, 2, row, lastCol), cfcNotContainsText, 'ef', fmtIdx); sh.WriteConditionalCellFormat(Range(row, 2, row, lastCol), cfcNotContainsText, 'ef', fmtIdx);
(*
// conditional format #6: contains error // conditional format #6: contains error
inc(row); inc(row);
sh.WriteText(row, 0, 'contains error'); sh.WriteText(row, 0, 'contains error');

View File

@ -46,8 +46,8 @@ It provides graphical components like a grid and chart."/>
<RequiredPkgs Count="4"> <RequiredPkgs Count="4">
<Item1> <Item1>
<PackageName Value="laz_fpspreadsheet"/> <PackageName Value="laz_fpspreadsheet"/>
<MaxVersion Major="1" Minor="11"/> <MaxVersion Major="1" Minor="12"/>
<MinVersion Major="1" Minor="12" Valid="True"/> <MinVersion Major="1" Minor="13" Valid="True"/>
</Item1> </Item1>
<Item2> <Item2>
<PackageName Value="tachartlazaruspkg"/> <PackageName Value="tachartlazaruspkg"/>

View File

@ -383,9 +383,11 @@ const
COLWIDTH_EPS = 1e-3; COLWIDTH_EPS = 1e-3;
ROWHEIGHT_EPS = 1e-3; ROWHEIGHT_EPS = 1e-3;
CF_OPERATORS: array[TsCFCondition] of string = ( CF_STYLE_OP: array[TsCFCondition] of string = (
'=', '!=', '&gt;', '&lt;', '&gt;=', '&lt;=', 'cell-content()=%s', 'cell-content()!=%s', // cfcEqual, cfcNotEqual
'', '', // cfcBetween, cfcNotBetween, 'cell-content()&gt;%s', 'cell-content()&lt;%s', //cfcGreaterThan, cfcLessThan
'cell-content()&gt;=%s', 'cell-content&lt;=%s', // cfcGreaterEqual, cfdLessEqual
'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,
@ -393,6 +395,22 @@ const
'', '' // cfcContainsErrors, cfcNotContainsErrors '', '' // cfcContainsErrors, cfcNotContainsErrors
); );
CF_CALCEXT_OP: array[TsCFCondition] of string = (
'=%s', '!=%s', // cfcEqual, cfcNotEqual
'&gt;%s', '&lt;%s', //cfcGreaterThan, cfcLessThan
'&gt;=%s', '&lt;=%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,
'', '', // cfcDuplicate, cfcUnique,
'begins-with(%s)', 'ends-with(%s)', // cfcBeginsWith, cfcEndsWith,
'contains-text(%s)', 'not-contains-text(%s)', // cfcContainsText, cfcNotContainsText,
'', '' // cfcContainsErrors, cfcNotContainsErrors
);
type type
{ Table style items stored in TableStyleList of the reader } { Table style items stored in TableStyleList of the reader }
@ -5899,6 +5917,12 @@ 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]);
value1Str := VarToStr(cf_cellRule.Operand1);
if VarIsStr(cf_cellRule.Operand1) then value1Str := UTF8TextToXMLText(SafeQuoteStr(value1Str));
value2Str := VarToStr(cf_cellRule.Operand2);
if VarIsStr(cf_cellRule.Operand1) then value2Str := UTF8TextToXMLText(SafeQuoteStr(value2Str));
opStr := Format(CF_CALCEXT_OP[cf_cellRule.Condition], [value1Str, value2str]);
(*
case cf_cellRule.Condition of case cf_cellRule.Condition of
cfcEqual..cfcLessEqual: cfcEqual..cfcLessEqual:
begin begin
@ -5926,10 +5950,12 @@ begin
else else
Continue; Continue;
end; end;
AppendToStream(AStream, Format( *)
'<calcext:condition calcext:apply-style-name="%s" calcext:value="%s" calcext:base-cell-address="%s" />', if opStr <> '' then
[cf_stylename, opStr, firstCellStr] AppendToStream(AStream, Format(
)); '<calcext:condition calcext:apply-style-name="%s" calcext:value="%s" calcext:base-cell-address="%s" />',
[cf_stylename, opStr, firstCellStr]
));
end; end;
end; end;
@ -7365,12 +7391,18 @@ begin
cf_sheet := cf.Worksheet as TsWorksheet; cf_sheet := cf.Worksheet as TsWorksheet;
firstCellOfRange := cf_sheet.Name + '.' + GetCellString(cf.CellRange.Row1, cf.CellRange.Col1); firstCellOfRange := cf_sheet.Name + '.' + GetCellString(cf.CellRange.Row1, cf.CellRange.Col1);
// Every rule has a style:map node // Some rules have a style:map node
for k := 0 to cf.RulesCount-1 do begin for k := 0 to cf.RulesCount-1 do begin
if cf.Rules[k] is TsCFCellRule then if cf.Rules[k] is TsCFCellRule then
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 := VarToStr(cf_cellrule.Operand1);
if VarIsStr(cf_cellRule.Operand1) then operand1Str := UTF8TextToXMLText(SafeQuoteStr(operand1Str));
operand2Str := VarToStr(cf_cellrule.Operand2);
if VarIsStr(cf_cellRule.Operand2) then operand2Str := UTF8TextToXMLText(SafeQuoteStr(operand2Str));
cf_condition := Format(CF_STYLE_OP[cf_cellRule.Condition], [operand1Str, operand2Str]);
(*
case cf_cellRule.Condition of case cf_cellRule.Condition of
cfcEqual..cfcLessEqual: cfcEqual..cfcLessEqual:
begin begin
@ -7399,6 +7431,7 @@ begin
else else
cf_Condition := ''; cf_Condition := '';
end; end;
*)
if cf_Condition <> '' then if cf_Condition <> '' then
Result := Result + Result := Result +

View File

@ -640,8 +640,9 @@ type
imRow, imCol); imRow, imCol);
{@@ Inspector expanded nodes } {@@ Inspector expanded nodes }
TsInspectorExpandedNode = (ienFormatSettings, ienPageLayout, ienFonts, ienFormats, TsInspectorExpandedNode = (ienFormatSettings, ienConditionalFormats,
ienEmbeddedObj, ienImages, ienCryptoInfo); ienPageLayout, ienFonts, ienFormats, ienEmbeddedObj, ienImages,
ienCryptoInfo);
TsInspectorExpandedNodes = set of TsInspectorExpandedNode; TsInspectorExpandedNodes = set of TsInspectorExpandedNode;
{@@ TsSpreadsheetInspector displays all properties of a workbook, worksheet, {@@ TsSpreadsheetInspector displays all properties of a workbook, worksheet,
@ -691,8 +692,8 @@ type
{@@ Displays subproperties } {@@ Displays subproperties }
property ExpandedNodes: TsInspectorExpandedNodes property ExpandedNodes: TsInspectorExpandedNodes
read FExpanded write SetExpanded read FExpanded write SetExpanded
default [ienFormatSettings, ienPageLayout, ienFonts, ienFormats, default [ienFormatSettings, ienConditionalFormats, ienPageLayout,
ienEmbeddedObj, ienImages, ienCryptoInfo]; ienFonts, ienFormats, ienEmbeddedObj, ienImages, ienCryptoInfo];
{@@ inherited from TValueListEditor. Turns of the fixed column by default} {@@ inherited from TValueListEditor. Turns of the fixed column by default}
property FixedCols default 0; property FixedCols default 0;
{@@ inherited from TStringGrid, but not published in TValueListEditor. } {@@ inherited from TStringGrid, but not published in TValueListEditor. }
@ -708,7 +709,7 @@ uses
Types, Math, StrUtils, TypInfo, LCLType, LCLIntf, LCLProc, Types, Math, StrUtils, TypInfo, LCLType, LCLIntf, LCLProc,
Dialogs, Forms, Clipbrd, Dialogs, Forms, Clipbrd,
fpsStrings, fpsCrypto, fpsReaderWriter, fpsUtils, fpsNumFormat, fpsImages, fpsStrings, fpsCrypto, fpsReaderWriter, fpsUtils, fpsNumFormat, fpsImages,
fpsHTMLUtils, fpsCSV, fpsExprParser; fpsHTMLUtils, fpsCSV, fpsExprParser, fpsConditionalFormat;
var var
cfBiff8Format: Integer = 0; cfBiff8Format: Integer = 0;
@ -3529,8 +3530,8 @@ begin
inherited Create(AOwner); inherited Create(AOwner);
DisplayOptions := DisplayOptions - [doKeyColFixed]; DisplayOptions := DisplayOptions - [doKeyColFixed];
FixedCols := 0; FixedCols := 0;
FExpanded := [ienFormatSettings, ienPageLayout, ienFonts, ienFormats, FExpanded := [ienFormatSettings, ienConditionalFormats, ienPageLayout,
ienEmbeddedObj, ienImages, ienCryptoInfo]; ienFonts, ienFormats, ienEmbeddedObj, ienImages, ienCryptoInfo];
with (TitleCaptions as TStringList) do begin with (TitleCaptions as TStringList) do begin
OnChange := nil; // This fixes an issue with Laz 1.0 OnChange := nil; // This fixes an issue with Laz 1.0
Clear; Clear;
@ -3566,6 +3567,12 @@ begin
then Exclude(expNodes, ienFormatSettings) then Exclude(expNodes, ienFormatSettings)
else Include(expNodes, ienFormatSettings); else Include(expNodes, ienFormatSettings);
end else end else
if (pos('Conditional formats', s) > 0) or (pos('ConditionalFormats', s) > 0) then
begin
if (ienConditionalFormats in expNodes)
then Exclude(expNodes, ienConditionalFormats)
else Include(expNodes, ienConditionalFormats);
end else
if (pos('Page layout', s) > 0) or (pos('PageLayout', s) > 0) then if (pos('Page layout', s) > 0) or (pos('PageLayout', s) > 0) then
begin begin
if (ienPageLayout in expNodes) if (ienPageLayout in expNodes)
@ -4252,6 +4259,7 @@ var
embObj: TsEmbeddedObj; embObj: TsEmbeddedObj;
so: TsSheetOption; so: TsSheetOption;
sp: TsWorksheetProtection; sp: TsWorksheetProtection;
cf: TsConditionalFormat;
begin begin
if ASheet = nil then if ASheet = nil then
begin begin
@ -4270,6 +4278,7 @@ begin
AStrings.Add('Options='); AStrings.Add('Options=');
AStrings.Add('Protection='); AStrings.Add('Protection=');
AStrings.Add('TabColor='); AStrings.Add('TabColor=');
AStrings.Add('Conditional formats=');
end else end else
begin begin
AStrings.Add(Format('Name=%s', [ASheet.Name])); AStrings.Add(Format('Name=%s', [ASheet.Name]));
@ -4292,7 +4301,23 @@ begin
AStrings.Add(Format('Hyperlinks=%d items', [ASheet.Hyperlinks.Count])); AStrings.Add(Format('Hyperlinks=%d items', [ASheet.Hyperlinks.Count]));
AStrings.Add(Format('MergedCells=%d items', [ASheet.MergedCells.Count])); AStrings.Add(Format('MergedCells=%d items', [ASheet.MergedCells.Count]));
AStrings.Add(Format('TabColor=$%.8x (%s)', [ASheet.TabColor, GetColorName(ASheet.TabColor)])); AStrings.Add(Format('TabColor=$%.8x (%s)', [ASheet.TabColor, GetColorName(ASheet.TabColor)]));
(*
if ienConditionalFormats in FExpanded then
begin
AStrings.Add('(-) Conditional formats=');
AStrings.Add(Format(' Count=%d', [ASheet.ConditionalFormatCount]));
for i := 0 to ASheet.ConditionalFormatCount-1 do
begin
cf := ASheet.ReadConditionalFormat(i);
AStrings.Add(' Item #' + IntToStr(i) + ':');
with cf.CellRange do
AStrings.Add(Format(' CellRange=%s', [GetCellRangeString(Row1, Col1, Row2, Col2)]));
end;
end else
begin
AStrings.Add('(+) Conditional formats=(dblclick for more...)');
end;
*)
if ienPageLayout in FExpanded then if ienPageLayout in FExpanded then
begin begin
AStrings.Add('(-) Page layout='); AStrings.Add('(-) Page layout=');