diff --git a/components/fpspreadsheet/source/common/fpsopendocument.pas b/components/fpspreadsheet/source/common/fpsopendocument.pas
index fbc17ded7..e3e9c72fd 100644
--- a/components/fpspreadsheet/source/common/fpsopendocument.pas
+++ b/components/fpspreadsheet/source/common/fpsopendocument.pas
@@ -220,7 +220,7 @@ type
function WriteBorderStyleXMLAsString(const AFormat: TsCellFormat): String;
function WriteCellProtectionStyleXMLAsString(const AFormat: TsCellFormat): String;
function WriteCommentXMLAsString(AComment: String): String;
- function WriteConditionalStyleXMLAsString(AFormatIndex: Integer): String;
+ function WriteConditionalStyleXMLAsString(ACFIndex: Integer): String;
function WriteDefaultFontXMLAsString: String;
function WriteDefaultGraphicStyleXMLAsString: String; overload;
function WriteDocumentProtectionXMLAsString: String;
@@ -383,6 +383,16 @@ const
COLWIDTH_EPS = 1e-3;
ROWHEIGHT_EPS = 1e-3;
+ CF_OPERATORS: array[TsCFCondition] of string = (
+ '=', '!=', '>', '<', '>=', '<=',
+ '', '', // cfcBetween, cfcNotBetween,
+ '', '', '', '', // cfcAboveAverage, cfcBelowAverage, cfcAboveEqualAverage, cfcBelowEqualAverage
+ '', '', '', '', // cfcTop, cfcBottom, cfcTopPercent, cfcBottomPercent,
+ '', '', // cfcDuplicate, cfcUnique,
+ '', '', '', '', // cfcBeginsWith, cfcEndsWith, cfcContainsText, cfcNotContainsText,
+ '', '' // cfcContainsErrors, cfcNotContainsErrors
+ );
+
type
{ Table style items stored in TableStyleList of the reader }
@@ -4818,11 +4828,15 @@ function TsSpreadOpenDocWriter.GetStyleName(ACell: PCell): String;
var
fmt: TsCellFormat;
ncf: Integer;
+ cf: Integer;
begin
ncf := Length(ACell^.ConditionalFormatIndex);
if ncf > 0 then
- Result := Format('ce%d_%d', [ACell^.FormatIndex, ACell^.ConditionalFormatIndex[ncf-1]])
- else
+ begin
+ cf := ACell^.ConditionalFormatIndex[ncf-1];
+ // Support only last conditional format of cell (having highest priority)
+ Result := 'ce' + IntToStr((cf+1)*1000 + ACell^.FormatIndex);
+ end else
begin
fmt := (FWorkbook as TsWorkbook).GetCellFormat(ACell^.FormatIndex);
if fmt.UsedFormattingFields <> [] then
@@ -5468,6 +5482,7 @@ begin
'');
end;
+{ Writes the style node in "content.xml" }
procedure TsSpreadOpenDocWriter.WriteCellStyle(AStream: TStream;
AFormatIndex, AConditionalFormatIndex: integer);
var
@@ -5488,11 +5503,12 @@ begin
// The style name will be 'ce' plus format index in the workbook's CellFormats
// list.
- styleName := 'ce' + IntToStr(AFormatIndex);
- // In case of a conditional format the index in the worksheet's
- // ConditionalFormatList will be added after an underscore character.
+ // In case of a conditional format the style name is a combination of
+ // conditional format index and normal format index.
if isConditionalFormat then
- styleName := styleName + '_' + IntToStr(AConditionalFormatIndex);
+ styleName := 'ce' + IntToStr(1000 * (AConditionalFormatIndex+1) + AFormatIndex)
+ else
+ styleName := 'ce' + IntToStr(AFormatIndex);
fmt := book.GetCellFormat(AFormatIndex);
@@ -5575,7 +5591,7 @@ var
cf_range: TsCellRange;
cf_rule: TsCFCellRule;
ncf: Integer;
- i, j, k, p: Integer;
+ i, j: Integer;
cell: PCell;
r, c: Cardinal;
L: TStrings;
@@ -5609,7 +5625,7 @@ begin
if Assigned(cell) and
(cell^.ConditionalFormatIndex[High(cell^.ConditionalFormatIndex)] = i)
then begin
- s := Format('ce%d_%d', [cell^.FormatIndex, i]);
+ s := 'ce' + IntToStr((i+1) * 1000 + cell^.FormatIndex);
if L.IndexOf(s) = -1 then
L.Add(s);
end;
@@ -5619,11 +5635,10 @@ begin
// Now write the combined styles to the stream. The styles can be identified
// from the style name in the string list.
for i := 0 to L.Count-1 do begin
- s := L[i];
- p := pos('_', L[i]);
- fmtIndex := StrToInt(Copy(L[i], 3, p-3));
- cfIndex := StrToInt(Copy(L[i], p+1, MaxInt));
- WriteCellStyle(AStream, fmtIndex, cfIndex);
+ s := Copy(L[i], 3, MaxInt); // remove 'ce'
+ j := StrToInt(s);
+ DivMod(j, 1000, cfIndex, fmtIndex);
+ WriteCellStyle(AStream, fmtIndex, cfIndex-1);
end;
finally
L.Free;
@@ -5847,76 +5862,82 @@ var
cf_range: TsCellRange;
cf_styleName: String;
cf_cellRule: TsCFCellRule;
- i, j: Integer;
+ i, j, k: Integer;
sheet: TsWorksheet;
rangeStr: String;
firstCellStr: string;
value1Str, value2Str: String;
+ opStr: String;
s: String;
begin
book := TsWorkbook(FWorkbook);
sheet := TsWorksheet(ASheet);
ncf := book.GetNumConditionalFormats;
+
+ AppendToStream(AStream,
+ '');
+
for i := 0 to ncf-1 do begin
cf := book.GetConditionalFormat(i);
if cf.Worksheet <> ASheet then
continue;
- cf_styleName := 'cf' + IntToStr(i);
cf_range := cf.CellRange;
firstCellStr := sheet.Name + '.' + GetCellString(cf_range.Row1, cf_range.Col1);
rangeStr := firstCellStr + ':' + sheet.Name + '.' + GetCellString(cf_range.Row2, cf_range.Col2);
- if cf.Rules[cf.RulesCount-1] is TsCFCellRule then
+
+ AppendToStream(AStream, Format(
+ '', [
+ rangeStr
+ ]));
+
+ for k := 0 to cf.RulesCount-1 do
begin
- cf_cellRule := TsCFCellRule(cf.Rules[cf.RulesCount-1]);
- case cf_cellRule.Condition of
- cfcEqual:
- if VarIsStr(cf_cellRule.Operand1) then
- value1Str := '=' + UTF8TextToXMLText(SafeQuoteStr(cf_cellrule.Operand1))
- else
- value1Str := '=' + VarToStr(cf_cellRule.Operand1);
- else
- Continue;
- end;
- s := Format(
- '' +
- '' +
- '' +
- '' +
- '', [
- rangeStr, cf_stylename, value1Str, firstCellStr
- ]);
- AppendToStream(AStream, s);
- end;
- (*
-
-
-
- for j := 0 to cf.RulesCount-1 do
- begin
- range := cf.CellRange;
- firstCellStr := sheet.Name + '.' + GetCellString(range.Row1, range.Col1);
- rangeStr := firstCellStr + ':' + sheet.Name + '.' + GetCellString(range.Row2, range.Col2);
- if cf.Rules[j] is TsCFCellRule then
+ value1Str := '';
+ value2Str := '';
+ opStr := '';
+ if cf.Rules[k] is TsCFCellRule then
begin
- cellRule := TsCFCellRule(cf.Rules[j]);
- cf_styleName := Format('cf%d_%d', [sheet.Index, cellRule.FormatIndex]);
- case cellRule.Condition of
- cfcEqual: value1Str := '=' + VarToStr(cellRule.Operand1);
- else Continue;
+ cf_cellRule := TsCFCellRule(cf.Rules[k]);
+ cf_styleName := Format('conditional_%d', [cf_CellRule.FormatIndex]);
+ case cf_cellRule.Condition of
+ cfcEqual..cfcLessEqual:
+ begin
+ opStr := CF_OPERATORS[cf_cellRule.Condition];
+ if VarIsStr(cf_cellRule.Operand1) then
+ value1Str := UTF8TextToXMLText(SafeQuoteStr(cf_cellrule.Operand1))
+ else
+ value1Str := VarToStr(cf_cellRule.Operand1);
+ opStr := CF_OPERATORS[cf_cellRule.Condition] + value1Str;
+ end;
+ cfcBetween, cfcNotBetween:
+ begin
+ if VarIsStr(cf_cellRule.Operand1) then
+ value1Str := UTF8TextToXMLText(SafeQuoteStr(cf_cellrule.Operand1))
+ else
+ value1Str := VarToStr(cf_cellRule.Operand1);
+ if VarIsStr(cf_cellRule.Operand2) then
+ value2Str := UTF8TextToXMLText(SafeQuoteStr(cf_cellrule.Operand2))
+ else
+ value2Str := VarToStr(cf_cellRule.Operand2);
+ opStr := Format('between(%s,%s)', [value1Str, value2Str]);
+ if cf_cellRule.Condition = cfcNotBetween then
+ opStr := 'not-' + opStr;
+ end;
+ else
+ Continue;
end;
- s := Format(
- '' +
- '' +
- '' +
- '' +
- '', [
- rangeStr, cf_stylename, value1Str, firstCellStr
- ]);
- AppendToStream(AStream, s);
+ AppendToStream(AStream, Format(
+ '',
+ [cf_stylename, opStr, firstCellStr]
+ ));
end;
end;
- *)
+
+ AppendToStream(AStream,
+ '');
end;
+ AppendToStream(AStream,
+ '' );
end;
{ Writes the conditional format part of a style to "styles.xml". }
@@ -5954,7 +5975,9 @@ var
nCF: Integer;
CF: TsConditionalFormat;
fmt: TsCellFormat;
- cf_rule: TsCFCellRule;
+ fmtIndex: Integer;
+ cf_rule: TsCFRule;
+ stylename: String;
begin
book := TsWorkbook(FWorkbook);
nCF := book.GetNumConditionalFormats;
@@ -5962,6 +5985,20 @@ begin
for i := 0 to nCF-1 do
begin
CF := book.GetConditionalFormat(i);
+ for j := 0 to CF.RulesCount-1 do
+ begin
+ cf_Rule := CF.Rules[j];
+ if cf_Rule is TsCFCellRule then
+ begin
+ fmtIndex := TsCFCellRule(cf_Rule).FormatIndex;
+ fmt := book.GetCellFormat(TsCFCellRule(cf_Rule).FormatIndex);
+ stylename := Format('conditional_%d', [fmtIndex]);
+ WriteConditionalStyle(AStream, stylename, fmt);
+ end;
+ end;
+ end;
+ (*
+
// for the moment: write only the style of the highest-priority rule
if CF.Rules[CF.RulesCount-1] is TsCFCellRule then
begin
@@ -5970,6 +6007,7 @@ begin
WriteConditionalStyle(AStream, Format('cf%d', [i]), fmt); // "cf" + index of CF in book's list
end;
end;
+ *)
(*
for i := 0 to book.GetWorksheetCount-1 do
begin
@@ -7063,10 +7101,16 @@ var
r1,c1,r2,c2: Cardinal;
fmt: TsCellFormat;
sheet: TsWorksheet;
+ lStyle: String;
begin
Unused(ARow, ACol);
sheet := FWorksheet as TsWorksheet;
+ // Style
+ lStyle := GetStyleName(ACell);
+ if lStyle <> '' then
+ lStyle := Format(' table:style-name="%s"', [lStyle]);
+
// Hyperlink
if sheet.HasHyperlink(ACell) then
FWorkbook.AddErrorMsg(rsODSHyperlinksOfTextCellsOnly, [GetCellString(ARow, ACol)]);
@@ -7087,8 +7131,8 @@ begin
fmt := (FWorkbook as TsWorkbook).GetCellFormat(ACell^.FormatIndex);
if (fmt.UsedFormattingFields <> []) then
AppendToStream(AStream, Format(
- '', [ACell^.FormatIndex, spannedStr]),
- comment,
+ '', [lStyle, spannedStr]),
+ comment,
'')
else
if comment <> '' then
@@ -7116,6 +7160,8 @@ begin
Unused(ARow, ACol);
valType := 'boolean';
+
+ // Style
lStyle := GetStyleName(ACell);
if lStyle <> '' then
lStyle := Format(' table:style-name="%s"', [lStyle]);
@@ -7300,49 +7346,68 @@ begin
end;
end;
-function TsSpreadOpenDocWriter.WriteConditionalStyleXMLAsString(AFormatIndex: Integer): string;
+function TsSpreadOpenDocWriter.WriteConditionalStyleXMLAsString(ACFIndex: Integer): string;
var
book: TsWorkbook;
- isConditional: Boolean;
- i, j, k: Integer;
+ k: Integer;
cf: TsConditionalFormat;
cf_CellRule: TsCFCellRule;
cf_StyleName: String;
cf_Condition: String;
cf_Sheet: TsWorksheet;
firstCellOfRange: String;
- operand1Str: String;
+ operand1Str, operand2Str: String;
begin
Result := '';
book := TsWorkbook(FWorkbook);
- cf := book.GetConditionalFormat(AFormatIndex);
- cf_styleName := 'cf' + IntToStr(AFormatIndex);
+ cf := book.GetConditionalFormat(ACFIndex);
cf_sheet := cf.Worksheet as TsWorksheet;
firstCellOfRange := cf_sheet.Name + '.' + GetCellString(cf.CellRange.Row1, cf.CellRange.Col1);
- if cf.Rules[cf.RulesCount-1] is TsCFCellRule then
- begin
- // for the moment: we only use the highest-priority rule
- cf_cellRule := TsCFCellRule(cf.Rules[cf.RulesCount-1]);
- case cf_cellRule.Condition of
- cfcEqual:
- begin
- operand1Str := VarToStr(cf_cellrule.Operand1);
- if VarIsStr(cf_cellRule.Operand1) then
- operand1Str := UTF8TextToXMLText(SafeQuoteStr(cf_cellrule.Operand1));
- cf_Condition := Format('cell-content()=%s', [operand1Str]);
- end;
- else
- cf_Condition := '';
- end;
+ // Every rule has a style:map node
+ for k := 0 to cf.RulesCount-1 do begin
+ if cf.Rules[k] is TsCFCellRule then
+ begin
+ cf_cellRule := TsCFCellRule(cf.Rules[k]);
+ cf_styleName := Format('conditional_%d', [cf_cellRule.FormatIndex]);
+ case cf_cellRule.Condition of
+ cfcEqual..cfcLessEqual:
+ begin
+ operand1Str := VarToStr(cf_cellrule.Operand1);
+ if VarIsStr(cf_cellRule.Operand1) then
+ operand1Str := UTF8TextToXMLText(SafeQuoteStr(operand1Str));
+ cf_Condition := Format('cell-content()%s%s', [
+ CF_OPERATORS[cf_cellRule.Condition],
+ operand1Str
+ ]);
+ end;
+ cfcBetween, cfcNotBetween:
+ begin
+ 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));
+ case cf_cellRule.Condition of
+ cfcBetween: cf_Condition := 'cell-content-is-between(%s,%s)';
+ cfcNotBetween: cf_Condition := 'cell-content-is-not-between(%s,%s)';
+ end;
+ cf_Condition := Format(cf_Condition, [operand1Str, operand2Str]);
+ end;
+ else
+ cf_Condition := '';
+ end;
- if cf_Condition <> '' then
- Result := Format('', [
- cf_Condition,
- cf_StyleName,
- firstCellOfRange
- ]);
+ if cf_Condition <> '' then
+ Result := Result +
+ Format('', [
+ cf_Condition,
+ cf_StyleName,
+ firstCellOfRange
+ ]);
+ end;
end;
(*
// Determine whether the format is a conditional format.
@@ -7467,11 +7532,10 @@ begin
sheet := FWorksheet as TsWorksheet;
- fmt := (FWorkbook as TsWorkbook).GetPointerToCellFormat(ACell^.FormatIndex);
- if fmt^.UsedFormattingFields <> [] then
- lStyle := ' table:style-name="ce' + IntToStr(ACell^.FormatIndex) + '" '
- else
- lStyle := '';
+ // Style
+ lStyle := GetStyleName(ACell);
+ if lStyle <> '' then
+ lStyle := Format(' table:style-name="%s"', [lStyle]);
// Comment
comment := WriteCommentXMLAsString(sheet.ReadComment(ACell));
@@ -8269,11 +8333,9 @@ begin
sheet := FWorksheet as TsWorksheet;
// Style
- fmt := (FWorkbook as TsWorkbook).GetCellFormat(ACell^.FormatIndex);
- if fmt.UsedFormattingFields <> [] then
- lStyle := ' table:style-name="ce' + IntToStr(ACell^.FormatIndex) + '" '
- else
- lStyle := '';
+ lStyle := GetStyleName(ACell);
+ if lStyle <> '' then
+ lStyle := Format(' table:style-name="%s"', [lStyle]);
// Comment
comment := WriteCommentXMLAsString(sheet.ReadComment(ACell));
@@ -8459,11 +8521,9 @@ begin
sheet := FWorksheet as TsWorksheet;
// Style
- fmt := (FWorkbook as TsWorkbook).GetCellFormat(ACell^.FormatIndex);
- if fmt.UsedFormattingFields <> [] then
- lStyle := ' table:style-name="ce' + IntToStr(ACell^.FormatIndex) + '"'
- else
- lStyle := '';
+ lStyle := GetStyleName(ACell);
+ if lStyle <> '' then
+ lStyle := Format(' table:style-name="%s"', [lStyle]);
// Comment
comment := WriteCommentXMLAsString(sheet.ReadComment(ACell));
@@ -8615,6 +8675,7 @@ begin
Unused(ARow, ACol);
valType := 'float';
+
lStyle := GetStyleName(ACell);
if lStyle <> '' then
lStyle := Format(' table:style-name="%s"', [lStyle]);
@@ -8714,12 +8775,13 @@ begin
end else
spannedStr := '';
+ // Style
+ lStyle := GetStyleName(ACell);
+ if lStyle <> '' then
+ lStyle := Format(' table:style-name="%s"', [lStyle]);
+
fmt := (FWorkbook as TsWorkbook).GetCellFormat(ACell^.FormatIndex);
numFmtParams := (FWorkbook as TsWorkbook).GetNumberFormat(fmt.NumberFormatIndex);
- if fmt.UsedFormattingFields <> [] then
- lStyle := Format(' table:style-name="ce%d"', [ACell^.FormatIndex])
- else
- lStyle := '';
// Comment
comment := WriteCommentXMLAsString(sheet.ReadComment(ACell));