fpspreadsheet: Add, with r/w support, conditional date formats cfcLastYear, cfcThisYear, cfcNextYear.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7588 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz 2020-07-29 17:41:00 +00:00
parent aebb067738
commit 9d7457ccd4
5 changed files with 145 additions and 19 deletions

View File

@ -27,6 +27,7 @@ type
cfcYesterday, cfcToday, cfcTomorrow, cfcLast7Days,
cfcLastWeek, cfcThisWeek, cfcNextWeek,
cfcLastMonth, cfcThisMonth, cfcNextMonth,
cfcLastYear, cfcThisYear, cfcNextYear,
cfcExpression
);

View File

@ -409,6 +409,7 @@ const
'', '', '', '', // cfcYesterday .. cfcLast7Days
'', '', '', // cfcLastWeek .. cfcNextWeek
'', '', '', // cfcLastMonth .. cfcNextMonth
'', '', '', // cfcLastYear .. cfcNextYear
'is-true-formula(%s)' // cfcExpression
);
@ -428,8 +429,9 @@ const
'yesterday', 'today', 'tomorrow', 'last-7-days', // cfcYesterday .. cfcLast7Days
'last-week', 'this-week', 'next-week', // cfcLastWeek .. cfcNextWeek
'last-month', 'this-month', 'next-month', // cfcLastMonth .. cfcNextMonth
'last-year', 'this-year', 'next-year', // cfcLastYear .. cfcNextYear
'formula-is(%s)' // cfcExprssion
); // ???????????????????
);
CF_VALUE_KIND: array[TsCFValueKind] of string = (
'', // vkNone
@ -4185,7 +4187,7 @@ begin
exit;
// condition for comparison
for c in [cfcYesterday..cfcNextMonth] do
for c in [cfcYesterday..cfcNextYear] do
if CF_CALCEXT_OP[c] = s then
begin
condition := c;
@ -6561,7 +6563,7 @@ begin
value1Str := CFOperandToStr(cf_cellRule.Operand1, sheet);
value2Str := CFOperandToStr(cf_cellRule.Operand2, sheet);
opStr := Format(CF_CALCEXT_OP[cf_cellRule.Condition], [value1Str, value2str]);
isDateFmt := cf_cellRule.Condition in [cfcYesterday..cfcNextMonth];
isDateFmt := cf_cellRule.Condition in [cfcYesterday..cfcNextYear];
if opStr <> '' then
begin
if isDateFmt then

View File

@ -253,7 +253,10 @@ const
'@AND(MONTH(RC)=MONTH(EDATE(TODAY(),0-1)),YEAR(RC)=YEAR(EDATE(TODAY(),0-1)))', // cfcLastMonth
'@AND(MONTH(RC)=MONTH(TODAY()),YEAR(RC)=YEAR(TODAY()))', // cfcThisMonth
'@AND(MONTH(RC)=MONTH(EDATE(TODAY(),0+1)),YEAR(RC)=YEAR(EDATE(TODAY(),0+1)))', // cfcNextMonth
'@' // cfcExpression
'@YEAR(RC)=YEAR(TODAY())-1', // cfcLastYear
'@YEAR(RC)=YEAR(TODAY())', // cfcThisYear
'@YEAR(RC)=YEAR(TODAY())+1', // cfcNextYear
'@' // cfcExpression
);
// The leading '@' indicates that the formula will be used in <Value1> node
// Parameter 0 is Operand1, parameter 1 is Operand2 and parameter 2 is Range
@ -429,7 +432,7 @@ begin
end else
begin
expr := '@' + UTF8TextToXMLText(AExpr);
for c in [cfcContainsErrors..cfcNextMonth] do
for c in [cfcContainsErrors..cfcNextYear] do
if CF_CONDITIONS[c] = expr then
begin
ACondition := c;

View File

@ -442,6 +442,7 @@ const
'timePeriod', // cfcLast7Days
'timePeriod', 'timePeriod', 'timePeriod',// cfcLastWeek, cfcThisWeek, cfcNextWeek
'timePeriod', 'timePeriod', 'timePeriod',// cfcLastMonth, cfcThisMonth, cfcNextMonth
'expression', 'expression', 'expression',// cfcLastYear, cfcThisYear, cfcNextYear // implemented as expression
'expression' // cfcExpression
);
@ -456,9 +457,16 @@ const
'yesterday', 'today', 'tomorrow', 'last7Days', // cfcYesterday, cfcToday, cfcTomorrow, cfcLast7Days
'lastWeek', 'thisWeek', 'nextWeek', // cfcLastWeek, cfcThisWeek, cfcNextWeek
'lastMonth', 'thisMonth', 'nextMonth', // cfcLastMonth, cfcThisMonth, cfcNextMonth
'', '', '', // cfcLastYear, cfcThisYear, cfcNextYear
'' // cfcExpression
);
CF_YEAR_FORMULAS: array[cfcLastYear..cfcNextYear] of string = (
'YEAR(%0:s)=YEAR(TODAY())-1', // cfcLastYear
'YEAR(%0:s)=YEAR(TODAY())', // cfcThisYear
'YEAR(%0:s)=YEAR(TODAY())+1' // cfcNextYear
);
CF_ICON_SET: array[TsCFIconSet] of string = (
'3Arrows', '3ArrowsGray','3Flags', // is3Arrows, is3ArrowsGray, is3Flags
'3TrafficLights2', // REPLACEMENT FOR is3TrafficLights1 which requires x14
@ -1549,6 +1557,7 @@ begin
sheet := TsWorksheet(AWorksheet);
s := GetAttrValue(ANode, 'timePeriod');
for cond in [cfcYesterday..cfcNextMonth] do
if CF_OPERATOR_NAMES[cond] = s then
begin
@ -1562,9 +1571,12 @@ procedure TsSpreadOOXMLReader.ReadCFExpression(ANode: TDOMNode;
var
sheet: TsWorksheet;
nodeName: String;
s: String;
s, s1: String;
c: TsCFCondition;
firstCellInRange: String;
begin
sheet := TsWorksheet(AWorksheet);
firstCellInRange := GetCellString(ARange.Row1, ARange.Col1);
ANode := ANode.FirstChild;
while ANode <> nil do
@ -1573,6 +1585,16 @@ begin
if nodeName = 'formula' then
begin
s := GetNodeValue(ANode);
for c in [cfcLastYear..cfcNextYear] do
begin
s1 := Format(CF_YEAR_FORMULAS[c], [firstCellInRange]);
if s1 = s then begin
sheet.WriteConditionalCellFormat(ARange, c, AFormatIndex);
exit;
end;
end;
sheet.WriteConditionalCellFormat(ARange, cfcExpression, s, AFormatIndex);
exit;
end;
@ -4096,19 +4118,19 @@ procedure TsSpreadOOXMLWriter.WriteCFCellRule(AStream: TStream;
ARule: TsCFCellRule; ARange: TsCellRange; APriority: Integer);
const
FORMULA: array[cfcBeginsWith..cfcNextMonth] 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
'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
'ISERROR(%0:s)', // cfcContainsErrors
'NOT(ISERROR(%0:s))', // cfcNotContainsErrors
'FLOOR(%s,1)=TODAY()-1', // cfcYesterday
'FLOOR(%s,1)=TODAY()', // cfcToday
'FLOOR(%s,1)=TODAY()+1', // cfcTomorrow
'AND(TODAY()-FLOOR(%0:s,1)&lt;=6,FLOOR(%0:s,1)&lt;=TODAY())', // cfcLasst7Days
'AND(TODAY()-FLOOR(%0:s,1)&lt;=6,FLOOR(%0:s,1)&lt;=TODAY())', // cfcLast7Days
'AND(TODAY()-ROUNDDOWN(%0:s,0)&gt;=(WEEKDAY(TODAY())),TODAY()-ROUNDDOWN(%0:s,0)&lt;(WEEKDAY(TODAY())+7))', // cfcLastWeek
'AND(TODAY()-ROUNDDOWN(%0:s,0)&lt;=WEEKDAY(TODAY())-1,ROUNDDOWN(%0:s,0)-TODAY()&lt;=7-WEEKDAY(TODAY()))', // cfcThisWeek
'AND(ROUNDDOWN(%0:s,0)-TODAY()&gt;(7-WEEKDAY(TODAY())),ROUNDDOWN(C15,0)-TODAY()&lt;(15-WEEKDAY(TODAY())))', // cfcNextWeek
'AND(TODAY()-ROUNDDOWN(%0:s,0)&lt;=WEEKDAY(TODAY())-1,ROUNDDOWN(%0:s,0)-TODAY()&lt;=7-WEEKDAY(TODAY()))', // cfcThisWeek
'AND(ROUNDDOWN(%0:s,0)-TODAY()&gt;(7-WEEKDAY(TODAY())),ROUNDDOWN(C15,0)-TODAY()&lt;(15-WEEKDAY(TODAY())))', // cfcNextWeek
'AND(MONTH(%0:s)=MONTH(EDATE(TODAY(),0-1)),YEAR(%0:s)=YEAR(EDATE(TODAY(),0-1)))', // cfcLastMonth
'AND(MONTH(%0:s)=MONTH(TODAY()),YEAR(%0:s)=YEAR(TODAY()))', // cfcThisMonth
'AND(MONTH(%0:s)=MONTH(EDATE(TODAY(),0+1)),YEAR(%0:s)=YEAR(EDATE(TODAY(),0+1)))' // cfcNextMonth
@ -4169,19 +4191,28 @@ begin
end;
cfcDuplicate, cfcUnique:
;
cfcBeginsWith..cfcNextMonth:
cfcBeginsWith..cfcNotContainsErrors:
begin
firstCellOfRange := GetCellString(ARange.Row1, ARange.Col1);
formula1Str :=
'<formula>' +
Format(FORMULA[ARule.Condition], [firstcellOfRange, ARule.Operand1]) +
'</formula>';
if ARule.Condition >= cfcYesterday then
begin
param1Str := ' timePeriod="' + CF_OPERATOR_NAMES[ARule.Condition] + '"';
opStr := '';
end else
param1Str := ' text="' + VarToStr(ARule.Operand1) + '"';
param1Str := ' text="' + VarToStr(ARule.Operand1) + '"';
end;
cfcYesterday..cfcNextMonth:
begin
firstCellOfrange := GetCellString(ARange.Row1, ARange.Col1);
s := Format(FORMULA[ARule.Condition], [firstcellOfRange]);
formula1Str := '<formula>' + s + '</formula>';
param1Str := Format(' timePeriod="%s"', [CF_OPERATOR_NAMES[ARule.Condition]]);
opStr := '';
end;
cfcLastYear..cfcNextYear:
begin
firstCellOfRange := GetCellString(ARange.Row1, ARange.Col1);
s := Format(CF_YEAR_FORMULAS[ARule.Condition], [firstCellOfRange]);
formula1Str := '<formula>' + s + '</formula>';
end;
cfcExpression:
begin

View File

@ -84,6 +84,9 @@ type
procedure TestWriteRead_CF_CellFmt_XLSX_LastMonth;
procedure TestWriteRead_CF_CellFmt_XLSX_ThisMonth;
procedure TestWriteRead_CF_CellFmt_XLSX_NextMonth;
procedure TestWriteRead_CF_CellFmt_XLSX_LastYear;
procedure TestWriteRead_CF_CellFmt_XLSX_ThisYear;
procedure TestWriteRead_CF_CellFmt_XLSX_NextYear;
procedure TestWriteRead_CF_CellFmt_XLSX_Expression;
procedure TestWriteRead_CF_CellFmt_XLSX_Background;
procedure TestWriteRead_CF_CellFmt_XLSX_Border4;
@ -134,6 +137,9 @@ type
procedure TestWriteRead_CF_CellFmt_XML_LastMonth;
procedure TestWriteRead_CF_CellFmt_XML_ThisMonth;
procedure TestWriteRead_CF_CellFmt_XML_NextMonth;
procedure TestWriteRead_CF_CellFmt_XML_LastYear;
procedure TestWriteRead_CF_CellFmt_XML_ThisYear;
procedure TestWriteRead_CF_CellFmt_XML_NextYear;
procedure TestWriteRead_CF_CellFmt_XML_Expression;
procedure TestWriteRead_CF_CellFmt_XML_Background;
@ -178,6 +184,9 @@ type
procedure TestWriteRead_CF_CellFmt_ODS_LastMonth;
procedure TestWriteRead_CF_CellFmt_ODS_ThisMonth;
procedure TestWriteRead_CF_CellFmt_ODS_NextMonth;
procedure TestWriteRead_CF_CellFmt_ODS_LastYear;
procedure TestWriteRead_CF_CellFmt_ODS_ThisYear;
procedure TestWriteRead_CF_CellFmt_ODS_NextYear;
procedure TestWriteRead_CF_CellFmt_ODS_Expression;
procedure TestWriteRead_CF_CellFmt_ODS_Background;
procedure TestWriteRead_CF_CellFmt_ODS_Border4;
@ -810,6 +819,33 @@ begin
TestWriteRead_CF_CellFmt(sfOOXML, cfcNextMonth, fmt);
end;
procedure TSpreadWriteReadCFTests.TestWriteRead_CF_CellFmt_XLSX_LastYear;
var
fmt: TsCellFormat;
begin
InitFormatRecord(fmt);
fmt.SetBackgroundColor(scRed);
TestWriteRead_CF_CellFmt(sfOOXML, cfcLastYear, fmt);
end;
procedure TSpreadWriteReadCFTests.TestWriteRead_CF_CellFmt_XLSX_ThisYear;
var
fmt: TsCellFormat;
begin
InitFormatRecord(fmt);
fmt.SetBackgroundColor(scRed);
TestWriteRead_CF_CellFmt(sfOOXML, cfcThisYear, fmt);
end;
procedure TSpreadWriteReadCFTests.TestWriteRead_CF_CellFmt_XLSX_NextYear;
var
fmt: TsCellFormat;
begin
InitFormatRecord(fmt);
fmt.SetBackgroundColor(scRed);
TestWriteRead_CF_CellFmt(sfOOXML, cfcNextYear, fmt);
end;
procedure TSpreadWriteReadCFTests.TestWriteRead_CF_CellFmt_XLSX_Expression;
var
fmt: TsCellFormat;
@ -1119,6 +1155,32 @@ begin
TestWriteRead_CF_CellFmt(sfExcelXML, cfcNextMonth, fmt);
end;
procedure TSpreadWriteReadCFTests.TestWriteRead_CF_CellFmt_XML_LastYear;
var
fmt: TsCellFormat;
begin
InitFormatRecord(fmt);
fmt.SetBackgroundColor(scRed);
TestWriteRead_CF_CellFmt(sfExcelXML, cfcLastYear, fmt);
end;
procedure TSpreadWriteReadCFTests.TestWriteRead_CF_CellFmt_XML_ThisYear;
var
fmt: TsCellFormat;
begin
InitFormatRecord(fmt);
fmt.SetBackgroundColor(scRed);
TestWriteRead_CF_CellFmt(sfExcelXML, cfcThisYear, fmt);
end;
procedure TSpreadWriteReadCFTests.TestWriteRead_CF_CellFmt_XML_NextYear;
var
fmt: TsCellFormat;
begin
InitFormatRecord(fmt);
fmt.SetBackgroundColor(scRed);
TestWriteRead_CF_CellFmt(sfExcelXML, cfcNextYear, fmt);
end;
procedure TSpreadWriteReadCFTests.TestWriteRead_CF_CellFmt_XML_Expression;
var
fmt: TsCellFormat;
@ -1493,6 +1555,33 @@ begin
TestWriteRead_CF_CellFmt(sfOpenDocument, cfcNextMonth, fmt);
end;
procedure TSpreadWriteReadCFTests.TestWriteRead_CF_CellFmt_ODS_LastYear;
var
fmt: TsCellFormat;
begin
InitFormatRecord(fmt);
fmt.SetBackgroundColor(scRed);
TestWriteRead_CF_CellFmt(sfOpenDocument, cfcLastYear, fmt);
end;
procedure TSpreadWriteReadCFTests.TestWriteRead_CF_CellFmt_ODS_ThisYear;
var
fmt: TsCellFormat;
begin
InitFormatRecord(fmt);
fmt.SetBackgroundColor(scRed);
TestWriteRead_CF_CellFmt(sfOpenDocument, cfcThisYear, fmt);
end;
procedure TSpreadWriteReadCFTests.TestWriteRead_CF_CellFmt_ODS_NextYear;
var
fmt: TsCellFormat;
begin
InitFormatRecord(fmt);
fmt.SetBackgroundColor(scRed);
TestWriteRead_CF_CellFmt(sfOpenDocument, cfcNextYear, fmt);
end;
procedure TSpreadWriteReadCFTests.TestWriteRead_CF_CellFmt_ODS_Expression;
var
fmt: TsCellFormat;