fpspreadsheet: Add writing of conditional formats to ODS (only cfcEqual condition, so far).

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7504 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2020-06-30 10:46:07 +00:00
parent b80085c78d
commit aff774ebc9
2 changed files with 457 additions and 155 deletions

View File

@ -2,7 +2,8 @@ program demo_conditional_formatting;
uses
sysUtils,
fpsTypes, fpsUtils, fpspreadsheet, xlsxooxml, fpsconditionalformat;
fpsTypes, fpsUtils, fpspreadsheet, fpsConditionalFormat,
xlsxooxml, fpsOpenDocument;
var
wb: TsWorkbook;
@ -59,7 +60,7 @@ begin
fmtIdx := wb.AddCellFormat(fmt);
// Write conditional format
sh.WriteConditionalCellFormat(Range(row, 2, row, lastCol), cfcEqual, 5, fmtIdx);
(*
// conditional format #2: equal to text constant
inc(row);
sh.WriteText(row, 0, 'equal to text "abc"');
@ -262,96 +263,19 @@ begin
fmt.SetBackgroundColor(scRed);
fmtIdx := wb.AddCellFormat(fmt);
sh.WriteConditionalCellFormat(Range(row, 2, row, lastCol), cfcNotContainsErrors, fmtIdx);
*)
(*
sh.Wri
'
{ ------ 1st conditional format : cfcEqual ------------------------------- }
sh.WriteNumber(0, 0, 1.0);
sh.WriteNumber(1, 0, 2.0);
sh.WriteNumber(2, 0, 3.0);
sh.WriteNumber(3, 0, 4.0);
sh.WriteNumber(4, 0, 5.0);
// Prepare the format record
InitFormatRecord(fmt);
// ... set the background color
fmt.SetBackgroundColor(scYellow);
// ... set the borders
fmt.SetBorders([cbNorth, cbEast, cbWest], scBlack, lsThin);
fmt.SetBorders([cbSouth], scRed, lsThick);
// ... set the font (bold) ---- NOT SUPPORTED AT THE MOMENT FOR WRITING TO XLSX...
font := wb.CloneFont(0);
font.Style := [fssBold, fssItalic];
font.Color := scRed;
fmt.SetFont(wb.AddFont(font));
// Add format record to format list
fmtIdx := wb.AddCellFormat(fmt);
// Use the format as conditional format of A1:A6 when cells are equal to 3.
sh.WriteConditionalCellFormat(Range(0, 0, 5, 0), cfcEqual, 3.0, fmtIdx);
{ ------- 2nd conditional format : cfcBelowEqualAverage ------------------ }
sh.WriteNumber(0, 2, 10.0);
sh.WriteNumber(1, 2, 20.0);
sh.WriteNumber(2, 2, 15.0);
sh.WriteNumber(3, 2, 11.0);
sh.WriteNumber(4, 2, 19.0);
InitFormatRecord(fmt);
fmt.SetBackgroundColor(scRed);
fmtIdx := wb.AddCellFormat(fmt);
sh.WriteConditionalCellFormat(Range(0, 2, 4, 2), cfcBelowEqualAverage, fmtIdx);
{ ------- 3rd and 4th conditional formats : beginWith, containsText ------ }
sh.WriteText(0, 4, 'abc');
sh.WriteText(1, 4, 'def');
sh.WriteText(2, 4, 'bac');
sh.WriteText(3, 4, 'dbc');
sh.WriteText(4, 4, 'acb');
sh.WriteText(5, 4, 'aca');
InitFormatRecord(fmt);
fmt.SetBackgroundColor($DEF1F4);
fmtIdx := wb.AddCellFormat(fmt);
sh.WriteConditionalCellFormat(Range(0, 4, 5, 4), cfcBeginsWith, 'a', fmtIdx);
fmt.SetBackgroundColor($D08330);
fmtIdx := wb.AddCellFormat(fmt);
sh.WriteConditionalCellFormat(Range(0, 4, 5, 4), cfcContainsText, 'bc', fmtIdx);
{ ------ 5th conditional format: containsErrors -------------------------- }
sh.WriteFormula(0, 6, '=1.0/0.0');
sh.WriteFormula(1, 6, '=1.0/1.0');
sh.WriteFormula(2, 6, '=1.0/2.0');
InitFormatRecord(fmt);
fmt.SetBackgroundColor(scGreen);
fmtIdx := wb.AddCellFormat(fmt);
sh.WriteConditionalCellFormat(Range(0, 6, 5, 6), cfcNotContainsErrors, fmtIdx);
// Condition for ContainsErrors after NoContainsErrors to get higher priority
fmt.SetBackgroundColor(scRed);
fmtIdx := wb.AddCellFormat(fmt);
sh.WriteConditionalCellFormat(Range(0, 0, 100, 100), cfcContainsErrors, fmtIdx);
{ ------ 6th conditional format: unique/duplicate values ----------------- }
sh.WriteNumber(0, 1, 1.0);
sh.WriteNumber(1, 1, 99.0);
InitFormatRecord(fmt);
fmt.SetBackgroundColor(scSilver);
sh.WriteConditionalCellFormat(Range(0, 0, 1, 1), cfcUnique, wb.AddCellFormat(fmt));
fmt.SetBackgroundColor(scGreen);
sh.WriteConditionalCellFormat(Range(0, 0, 1, 1), cfcDuplicate, wb.AddCellFormat(fmt));
*)
WriteLn('row = ', row);
WriteLn('wb.GetNumcellFormats = ', wb.GetNumCellFormats);
WriteLn('wb.GetNumConditionalFormats = ', wb.GetNumConditionalFormats);
{ ------ Save workbook to file-------------------------------------------- }
wb.WriteToFile('test.xlsx', true);
wb.WriteToFile('test.ods', true);
finally
wb.Free;
end;
ReadLn;
end.

View File

@ -193,9 +193,13 @@ type
procedure WriteAutomaticStyles(AStream: TStream);
procedure WriteCellRow(AStream: TStream; ASheet: TsBasicWorksheet;
ARowIndex, ALastColIndex: Integer);
procedure WriteCellStyle(AStream: TStream; AFormatIndex, AConditionalFormatIndex: integer);
procedure WriteCellStyles(AStream: TStream);
procedure WriteColStyles(AStream: TStream);
procedure WriteColumns(AStream: TStream; ASheet: TsBasicWorksheet);
procedure WriteConditionalFormats(AStream: TStream; ASheet: TsBasicWorksheet);
procedure WriteConditionalStyle(AStream: TStream; AStyleName: String; const AFormat: TsCellFormat);
procedure WriteConditionalStyles(AStream: TStream);
procedure WriteEmptyRow(AStream: TStream; ASheet: TsBasicWorksheet;
ARowIndex, AFirstColIndex, ALastColIndex, ALastRowIndex: Integer;
out ARowsRepeated: Integer);
@ -216,6 +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 WriteDefaultFontXMLAsString: String;
function WriteDefaultGraphicStyleXMLAsString: String; overload;
function WriteDocumentProtectionXMLAsString: String;
@ -246,6 +251,7 @@ type
out AHeader, AFooter: String);
procedure GetHeaderFooterImagePosStr(APagelayout: TsPageLayout;
out AHeader, AFooter: String);
function GetStyleName(ACell: PCell): String;
{
procedure GetRowStyleAndHeight(ASheet: TsBasicWorksheet; ARowIndex: Integer;
out AStyleName: String; out AHeight: Single);
@ -308,7 +314,7 @@ uses
fpsPatches,
{$ENDIF}
fpsStrings, fpsStreams, fpsCrypto, fpsClasses, fpspreadsheet,
fpsExprParser, fpsImages;
fpsExprParser, fpsImages, fpsConditionalFormat;
const
{ OpenDocument general XML constants }
@ -4808,6 +4814,24 @@ begin
AFooter := GetPosStr(ftrTags);
end;
function TsSpreadOpenDocWriter.GetStyleName(ACell: PCell): String;
var
fmt: TsCellFormat;
ncf: Integer;
begin
ncf := Length(ACell^.ConditionalFormatIndex);
if ncf > 0 then
Result := Format('ce%d_%d', [ACell^.FormatIndex, ACell^.ConditionalFormatIndex[ncf-1]])
else
begin
fmt := (FWorkbook as TsWorkbook).GetCellFormat(ACell^.FormatIndex);
if fmt.UsedFormattingFields <> [] then
Result := 'ce' + IntToStr(ACell^.FormatIndex)
else
Result := '';
end;
end;
procedure TsSpreadOpenDocWriter.InternalWriteToStream(AStream: TStream);
var
FZip: TZipper;
@ -5244,6 +5268,7 @@ begin
'</office:document-settings>');
end;
{ Writes the file "styles.xml" }
procedure TsSpreadOpenDocWriter.WriteStyles;
begin
AppendToStream(FSStyles,
@ -5272,6 +5297,9 @@ begin
'<style:style style:name="Default" style:family="table-cell">',
WriteDefaultFontXMLAsString,
'</style:style>');
WriteConditionalStyles(FSStyles);
if (FWorkbook as TsWorkbook).HasEmbeddedSheetImages then
AppendToStream(FSStyles,
'<style:default-style style:family="graphic">',
@ -5429,6 +5457,9 @@ begin
else
WriteRowsAndCells(AStream, FWorksheet);
// Conditional formats
WriteConditionalFormats(AStream, FWorksheet);
// named expressions, i.e. print range, repeated cols/rows
WriteNamedExpressions(AStream, FWorksheet);
@ -5437,78 +5468,165 @@ begin
'</table:table>');
end;
procedure TsSpreadOpenDocWriter.WriteCellStyle(AStream: TStream;
AFormatIndex, AConditionalFormatIndex: integer);
var
book: TsWorkbook;
fmt: TsCellFormat;
nfs: String;
nfParams: TsNumFormatParams;
nfidx: Integer;
s: String;
p: Integer;
j: Integer;
stylename: String;
cf: TsConditionalFormat;
isConditionalFormat: Boolean;
begin
book := TsWorkbook(FWorkbook);
isConditionalFormat := AConditionalFormatIndex > -1;
// 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.
if isConditionalFormat then
styleName := styleName + '_' + IntToStr(AConditionalFormatIndex);
fmt := book.GetCellFormat(AFormatIndex);
nfs := '';
nfidx := fmt.NumberFormatIndex;
if nfidx <> -1 then
begin
nfParams := book.GetNumberFormat(nfidx);
if nfParams <> nil then
begin
nfs := nfParams.NumFormatStr;
for j:=0 to NumFormatList.Count-1 do
begin
s := NumFormatList[j];
p := pos(':', s);
if SameText(Copy(s, p+1, Length(s)), nfs) then
begin
nfs := Format('style:data-style-name="%s"', [copy(s, 1, p-1)]);
break;
end;
p := 0;
end;
if p = 0 then // not found
nfs := '';
end;
end;
// Start and name
AppendToStream(AStream,
'<style:style style:name="' + styleName + '" style:family="table-cell" ' +
'style:parent-style-name="Default" '+ nfs + '>');
// style:text-properties
// - font
s := WriteFontStyleXMLAsString(fmt);
if s <> '' then
AppendToStream(AStream,
'<style:text-properties '+ s + '/>');
// - border, background, wordwrap, text rotation, vertical alignment
s := WriteBorderStyleXMLAsString(fmt) +
WriteBackgroundColorStyleXMLAsString(fmt) +
WriteWordwrapStyleXMLAsString(fmt) +
WriteTextRotationStyleXMLAsString(fmt) +
WriteVertAlignmentStyleXMLAsString(fmt);
if not isConditionalFormat then
s := s + WriteCellProtectionStyleXMLAsString(fmt);
if s <> '' then
AppendToStream(AStream,
'<style:table-cell-properties ' + s + '/>');
// style:paragraph-properties
// - hor alignment, bidi
s := WriteHorAlignmentStyleXMLAsString(fmt) +
WriteBiDiModeStyleXMLAsString(fmt);
if s <> '' then
AppendToStream(AStream,
'<style:paragraph-properties ' + s + '/>');
if isConditionalFormat then
begin
s := WriteConditionalStyleXMLAsString(AConditionalFormatIndex);
if s <> '' then
AppendToStream(AStream, s);
end;
// End
AppendToStream(AStream,
'</style:style>');
end;
{ Writes the cell styles ("ce0", "ce1", ...). Directly maps to the CellFormats
list of the workbook. "ce0" is the default format }
procedure TsSpreadOpenDocWriter.WriteCellStyles(AStream: TStream);
var
i, j, p: Integer;
book: TsWorkbook;
cf: TsConditionalFormat;
cf_sheet: TsWorksheet;
cf_range: TsCellRange;
cf_rule: TsCFCellRule;
ncf: Integer;
i, j, k, p: Integer;
cell: PCell;
r, c: Cardinal;
L: TStrings;
s: String;
nfidx: Integer;
nfs: String;
fmt: TsCellFormat;
nfParams: TsNumFormatParams;
fmtIndex, cfIndex: Integer;
begin
for i := 0 to (FWorkbook as TsWorkbook).GetNumCellFormats - 1 do
begin
fmt := TsWorkbook(FWorkbook).GetCellFormat(i);
nfs := '';
nfidx := fmt.NumberFormatIndex;
if nfidx <> -1 then
book := TsWorkbook(FWorkbook);
// Write fixed formats only
for i := 0 to book.GetNumCellFormats - 1 do
WriteCellStyle(AStream, i, -1);
// Conditional formats contain the fixed formats plus the condition params
// To avoid duplicate style entries in the file we first collect all style
// names in a list
ncf := book.GetNumConditionalFormats;
if ncf = 0 then
exit;
L := TStringList.Create;
try
for i := 0 to ncf - 1 do
begin
nfParams := TsWorkbook(FWorkbook).GetNumberFormat(nfidx);
if nfParams <> nil then
begin
nfs := nfParams.NumFormatStr;
for j:=0 to NumFormatList.Count-1 do
cf := book.GetConditionalFormat(i);
cf_sheet := TsWorksheet(cf.Worksheet);
cf_range := cf.Cellrange;
for r := cf_range.Row1 to cf_range.Row2 do
for c := cf_range.Col1 to cf_range.Col2 do
begin
s := NumFormatList[j];
p := pos(':', s);
if SameText(Copy(s, p+1, Length(s)), nfs) then
begin
nfs := Format('style:data-style-name="%s"', [copy(s, 1, p-1)]);
break;
cell := cf_sheet.FindCell(r, c);
if Assigned(cell) and
(cell^.ConditionalFormatIndex[High(cell^.ConditionalFormatIndex)] = i)
then begin
s := Format('ce%d_%d', [cell^.FormatIndex, i]);
if L.IndexOf(s) = -1 then
L.Add(s);
end;
p := 0;
end;
if p = 0 then // not found
nfs := '';
end;
end;
// Start and name
AppendToStream(AStream,
'<style:style style:name="ce' + IntToStr(i) + '" style:family="table-cell" ' +
'style:parent-style-name="Default" '+ nfs + '>');
// style:text-properties
// - font
s := WriteFontStyleXMLAsString(fmt);
if s <> '' then
AppendToStream(AStream,
'<style:text-properties '+ s + '/>');
// - border, background, wordwrap, text rotation, vertical alignment
s := WriteBorderStyleXMLAsString(fmt) +
WriteBackgroundColorStyleXMLAsString(fmt) +
WriteWordwrapStyleXMLAsString(fmt) +
WriteTextRotationStyleXMLAsString(fmt) +
WriteVertAlignmentStyleXMLAsString(fmt) +
WriteCellProtectionStyleXMLAsString(fmt);
if s <> '' then
AppendToStream(AStream,
'<style:table-cell-properties ' + s + '/>');
// style:paragraph-properties
// - hor alignment, bidi
s := WriteHorAlignmentStyleXMLAsString(fmt) +
WriteBiDiModeStyleXMLAsString(fmt);
if s <> '' then
AppendToStream(AStream,
'<style:paragraph-properties ' + s + '/>');
// End
AppendToStream(AStream,
'</style:style>');
// 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);
end;
finally
L.Free;
end;
end;
@ -5708,6 +5826,171 @@ begin
Result := Result + '</office:annotation>';
end;
{@@ ----------------------------------------------------------------------------
Writes the "calcext:conditional-formats" node after the table block
in "contents.xml". This is the third part needed for conditional formatting.
The other part are implemented in
#1 WriteConditionalStyles/WriteConditionalStyle
#2 WriteCellStyle
-------------------------------------------------------------------------------}
procedure TsSpreadOpenDocWriter.WriteConditionalFormats(AStream: TStream;
ASheet: TsBasicWorksheet);
{<calcext:conditional-formats>
<calcext:conditional-format calcext:target-range-address="Tabelle1.B4:Tabelle1.J4">
<calcext:condition calcext:apply-style-name="cf" calcext:value="=5" calcext:base-cell-address="Tabelle1.B4" />
</calcext:conditional-format>
</calcext:conditional-formats> }
var
book: TsWorkbook;
ncf: Integer;
cf: TsConditionalFormat;
cf_range: TsCellRange;
cf_styleName: String;
cf_cellRule: TsCFCellRule;
i, j: Integer;
sheet: TsWorksheet;
rangeStr: String;
firstCellStr: string;
value1Str, value2Str: String;
s: String;
begin
book := TsWorkbook(FWorkbook);
sheet := TsWorksheet(ASheet);
ncf := book.GetNumConditionalFormats;
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
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(
'<calcext:conditional-formats>' +
'<calcext:conditional-format calcext:target-range-address="%s">' +
'<calcext:condition calcext:apply-style-name="%s" calcext:value="%s" calcext:base-cell-address="%s" />' +
'</calcext:conditional-format>' +
'</calcext:conditional-formats>', [
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
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;
end;
s := Format(
'<calcext:conditional-formats>' +
'<calcext:conditional-format calcext:target-range-address="%s">' +
'<calcext:condition calcext:apply-style-name="%s" calcext:value="%s" calcext:base-cell-address="%s" />' +
'</calcext:conditional-format>' +
'</calcext:conditional-formats>', [
rangeStr, cf_stylename, value1Str, firstCellStr
]);
AppendToStream(AStream, s);
end;
end;
*)
end;
end;
{ Writes the conditional format part of a style to "styles.xml". }
procedure TsSpreadopenDocWriter.WriteConditionalStyle(AStream: TStream;
AStyleName: String; const AFormat: TsCellFormat);
begin
AppendToStream(AStream, Format(
'<style:style style:name="%s" style:family="table-cell" style:parent-style-name="Default">',
[AStyleName]));
AppendToStream(AStream, Format(
'<style:table-cell-properties %s%s />', [
WriteBackgroundColorStyleXMLAsString(AFormat),
WriteBorderStyleXMLAsString(AFormat)
// To do: add the remaining style elements
]));
AppendToStream(AStream,
'</style:style>');
end;
{@@ ----------------------------------------------------------------------------
Writes the styles used by conditional formatting to "styles.xml".
In total there are three parts which must be implemented
for condtional formatting:
#1 Definition of the styles (here, and in WriteConditionalStyle) (can be
omitted if one of the already existing styles is used)
#2 Definition of the cell styles (in WriteCellStyles), style:map nodes)
#3 Definition of the cell ranges in WriteConditionalFormats
(calcext:conditional-formattings node)
-------------------------------------------------------------------------------}
procedure TsSpreadOpenDocWriter.WriteConditionalStyles(AStream: TStream);
var
book: TsWorkbook;
sheet: TsWorksheet;
i, j, k: Integer;
nCF: Integer;
CF: TsConditionalFormat;
fmt: TsCellFormat;
cf_rule: TsCFCellRule;
begin
book := TsWorkbook(FWorkbook);
nCF := book.GetNumConditionalFormats;
for i := 0 to nCF-1 do
begin
CF := book.GetConditionalFormat(i);
// for the moment: write only the style of the highest-priority rule
if CF.Rules[CF.RulesCount-1] is TsCFCellRule then
begin
cf_rule := TsCFCellRule(CF.Rules[CF.RulesCount-1]);
fmt := book.GetCellFormat(cf_rule.FormatIndex);
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
sheet := book.GetWorksheetByIndex(i);
for j := 0 to sheet.ConditionalFormatCount-1 do
begin
CF := sheet.ReadConditionalFormat(j);
for k := 0 to CF.RulesCount-1 do
begin
rule := CF.Rules[k];
if rule is TsCFCellRule then
begin
fmt := book.GetCellFormat(TsCFCelLRule(rule).FormatIndex);
WriteConditionalStyle(AStream, Format('cf%d_%d', [i, j]), fmt); // cf"sheet"_"fmtindex"
end;
end;
end;
end;
*)
end;
{@@ ----------------------------------------------------------------------------
Writes the declaration of the font faces used in the workbook.
Is used in styles.xml and content.xml.
@ -6833,12 +7116,9 @@ begin
Unused(ARow, ACol);
valType := 'boolean';
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((FWorksheet as TsWorksheet).ReadComment(ACell));
@ -7020,6 +7300,101 @@ begin
end;
end;
function TsSpreadOpenDocWriter.WriteConditionalStyleXMLAsString(AFormatIndex: Integer): string;
var
book: TsWorkbook;
isConditional: Boolean;
i, j, k: Integer;
cf: TsConditionalFormat;
cf_CellRule: TsCFCellRule;
cf_StyleName: String;
cf_Condition: String;
cf_Sheet: TsWorksheet;
firstCellOfRange: String;
operand1Str: String;
begin
Result := '';
book := TsWorkbook(FWorkbook);
cf := book.GetConditionalFormat(AFormatIndex);
cf_styleName := 'cf' + IntToStr(AFormatIndex);
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;
if cf_Condition <> '' then
Result := Format('<style:map style:condition="%s" style:apply-style-name="%s" style:base-cell-address="%s" />', [
cf_Condition,
cf_StyleName,
firstCellOfRange
]);
end;
(*
// Determine whether the format is a conditional format.
isConditional := false;
for i := 0 to book.GetWorksheetCount-1 do
begin
sheet := book.GetWorksheetByIndex(i);
for j := 0 to sheet.ConditionalFormatCount-1 do
begin
cf := sheet.ReadConditionalFormat(j);
for k := 0 to cf.RulesCount-1 do
if cf.Rules[k] is TsCFCellRule then
if TsCFCellRule(cf.Rules[k]).FormatIndex = AFormatIndex then
begin
isConditional := true;
cf_CellRule := TsCFCellRule(cf.Rules[k]);
cf_StyleName := Format('cf%d_%d', [i, cf_CellRule.FormatIndex]);
firstCellOfRange := GetCellString(cf.CellRange.Row1, cf.CellRange.Col1);
firstCellOfRange := sheet.Name + '.' + firstCellOfRange;
break;
end;
if isConditional then break;
end;
if isConditional then break;
end;
if not isConditional then
exit;
// <style:map style:condition="cell-content()=5" style:apply-style-name="cf" style:base-cell-address="Tabelle1.B4" />
// or ="cell-content()="abc""
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;
if cf_Condition <> '' then
Result := Format('<style:map style:condition="%s" style:apply-style-name="%s" style:base-cell-address="%s" />', [
cf_Condition,
cf_StyleName,
firstCellOfRange
]);
*)
end;
function TsSpreadOpenDocWriter.WriteDefaultFontXMLAsString: String;
var
fnt: TsFont;
@ -7624,6 +7999,7 @@ begin
i+1, UTF8TextToXMLText(sheetname),
FALSE_TRUE[not (soHidden in sheet.Options)], bidi, tabColor
]));
if sheet.GetImageCount > 0 then
begin
// Embedded images written by fps refer to a graphic style "gr1"...
@ -8239,6 +8615,10 @@ begin
Unused(ARow, ACol);
valType := 'float';
lStyle := GetStyleName(ACell);
if lStyle <> '' then
lStyle := Format(' table:style-name="%s"', [lStyle]);
fmt := (FWorkbook as TsWorkbook).GetCellFormat(ACell^.FormatIndex);
if fmt.UsedFormattingFields <> [] then
begin
@ -8257,9 +8637,7 @@ begin
if (nfkCurrency in nfSection.Kind) then
valtype := 'currency'
end;
lStyle := ' table:style-name="ce' + IntToStr(ACell^.FormatIndex) + '"';
end else
lStyle := '';
end;
// Comment
comment := WriteCommentXMLAsString((FWorksheet as TsWorksheet).ReadComment(ACell));