fpspreadsheet: Move conditional format list from worksheet to workbook (to facilitate handling for ODS).

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7503 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2020-06-30 10:45:14 +00:00
parent ea76276469
commit b80085c78d
5 changed files with 123 additions and 91 deletions

View File

@ -70,35 +70,36 @@ type
{ Conditional format item } { Conditional format item }
TsConditionalFormat = class TsConditionalFormat = class
private private
FWorksheet: TsBasicWorksheet;
FCellRange: TsCellRange; FCellRange: TsCellRange;
FRules: TsCFRules; FRules: TsCFRules;
function GetRules(AIndex: Integer): TsCFRule; function GetRules(AIndex: Integer): TsCFRule;
function GetRulesCount: Integer; function GetRulesCount: Integer;
public public
constructor Create(ACellRange: TsCellRange); constructor Create(AWorksheet: TsBasicWorksheet; ACellRange: TsCellRange);
destructor Destroy; override; destructor Destroy; override;
property CellRange: TsCellRange read FCellRange; property CellRange: TsCellRange read FCellRange;
property Rules[AIndex: Integer]: TsCFRule read GetRules; property Rules[AIndex: Integer]: TsCFRule read GetRules;
property RulesCount: Integer read GetRulesCount; property RulesCount: Integer read GetRulesCount;
property Worksheet: TsBasicWorksheet read FWorksheet;
end; end;
TsConditionalFormatList = class(TFPObjectList) TsConditionalFormatList = class(TFPObjectList)
private
FWorksheet: TsBasicWorksheet;
protected protected
function AddRule(ARange: TsCellRange; ARule: TsCFRule): Integer; function AddRule(ASheet: TsBasicWorksheet; ARange: TsCellRange;
ARule: TsCFRule): Integer;
public public
function AddCellRule(ARange: TsCellRange; ACondition: TsCFCondition; function AddCellRule(ASheet: TsBasicWorksheet; ARange: TsCellRange;
ACellFormatIndex: Integer): Integer; overload; ACondition: TsCFCondition; ACellFormatIndex: Integer): Integer; overload;
function AddCellRule(ARange: TsCellRange; ACondition: TsCFCondition; function AddCellRule(ASheet: TsBasicWorksheet; ARange: TsCellRange;
AParam: Variant; ACellFormatIndex: Integer): Integer; overload; ACondition: TsCFCondition; AParam: Variant; ACellFormatIndex: Integer): Integer; overload;
function AddCellRule(ARange: TsCellRange; ACondition: TsCFCondition; function AddCellRule(ASheet: TsBasicWorksheet; ARange: TsCellRange;
AParam1, AParam2: Variant; ACellFormatIndex: Integer): Integer; overload; ACondition: TsCFCondition; AParam1, AParam2: Variant; ACellFormatIndex: Integer): Integer; overload;
procedure AddColorRangeRule(ARange: TsCellRange); procedure AddColorRangeRule(ASheet: TsBasicWorksheet; ARange: TsCellRange);
procedure AddDataBarRule(ARange: TsCellRange); procedure AddDataBarRule(ASheet: TsBasicWorksheet; ARange: TsCellRange);
procedure Delete(AIndex: Integer); procedure Delete(AIndex: Integer);
function Find(ARange: TsCellRange): Integer; function Find(ASheet: TsBasicWorksheet; ARange: TsCellRange): Integer;
end; end;
@ -170,9 +171,11 @@ end;
{ TsConditonalFormat } { TsConditonalFormat }
constructor TsConditionalFormat.Create(ACellRange: TsCellRange); constructor TsConditionalFormat.Create(AWorksheet: TsBasicWorksheet;
ACellRange: TsCellRange);
begin begin
inherited Create; inherited Create;
FWorksheet := AWorksheet;
FCellRange := ACellRange; FCellRange := ACellRange;
FRules := TsCFRules.Create; FRules := TsCFRules.Create;
end; end;
@ -202,15 +205,15 @@ end;
the rule describing the format. the rule describing the format.
The rules are grouped for the same cell ranges. The rules are grouped for the same cell ranges.
-------------------------------------------------------------------------------} -------------------------------------------------------------------------------}
function TsConditionalFormatList.AddRule(ARange: TsCellRange; function TsConditionalFormatList.AddRule(ASheet: TsBasicWorksheet;
ARule: TsCFRule): Integer; ARange: TsCellRange; ARule: TsCFRule): Integer;
var var
CF: TsConditionalFormat; CF: TsConditionalFormat;
idx: Integer; idx: Integer;
begin begin
idx := Find(ARange); idx := Find(ASheet, ARange);
if idx = -1 then begin if idx = -1 then begin
CF := TsConditionalFormat.Create(ARange); CF := TsConditionalFormat.Create(ASheet, ARange);
idx := Add(CF); idx := Add(CF);
end else end else
CF := TsConditionalFormat(Items[idx]); CF := TsConditionalFormat(Items[idx]);
@ -220,8 +223,9 @@ end;
// TODO: Add pre-checks for compatibility of condition and operands // TODO: Add pre-checks for compatibility of condition and operands
function TsConditionalFormatList.AddCellRule(ARange: TsCellRange; function TsConditionalFormatList.AddCellRule(ASheet: TsBasicWorksheet;
ACondition: TsCFCondition; ACellFormatIndex: Integer): Integer; ARange: TsCellRange; ACondition: TsCFCondition;
ACellFormatIndex: Integer): Integer;
var var
rule: TsCFCellRule; rule: TsCFCellRule;
begin begin
@ -230,11 +234,12 @@ begin
rule.Operand1 := varNull; rule.Operand1 := varNull;
rule.Operand2 := varNull; rule.Operand2 := varNull;
rule.FormatIndex := ACellFormatIndex; rule.FormatIndex := ACellFormatIndex;
Result := AddRule(ARange, rule); Result := AddRule(ASheet, ARange, rule);
end; end;
function TsConditionalFormatList.AddCellRule(ARange: TsCellRange; function TsConditionalFormatList.AddCellRule(ASheet: TsBasicWorksheet;
ACondition: TsCFCondition; AParam: Variant; ACellFormatIndex: Integer): Integer; ARange: TsCellRange; ACondition: TsCFCondition; AParam: Variant;
ACellFormatIndex: Integer): Integer;
var var
rule: TsCFCellRule; rule: TsCFCellRule;
begin begin
@ -243,11 +248,11 @@ begin
rule.Operand1 := AParam; rule.Operand1 := AParam;
rule.Operand2 := varNull; rule.Operand2 := varNull;
rule.FormatIndex := ACellFormatIndex; rule.FormatIndex := ACellFormatIndex;
Result := AddRule(ARange, rule); Result := AddRule(ASheet, ARange, rule);
end; end;
function TsConditionalFormatList.AddCellRule(ARange: TsCellRange; function TsConditionalFormatList.AddCellRule(ASheet: TsBasicWorksheet;
ACondition: TsCFCondition; AParam1, AParam2: Variant; ARange: TsCellRange; ACondition: TsCFCondition; AParam1, AParam2: Variant;
ACellFormatIndex: Integer): Integer; ACellFormatIndex: Integer): Integer;
var var
rule: TsCFCellRule; rule: TsCFCellRule;
@ -257,15 +262,17 @@ begin
rule.Operand1 := AParam1; rule.Operand1 := AParam1;
rule.Operand2 := AParam2; rule.Operand2 := AParam2;
rule.FormatIndex := ACellFormatIndex; rule.FormatIndex := ACellFormatIndex;
Result := AddRule(ARange, rule); Result := AddRule(ASheet, ARange, rule);
end; end;
procedure TsConditionalFormatList.AddColorRangeRule(ARange: TsCellRange); procedure TsConditionalFormatList.AddColorRangeRule(ASheet: TsBasicWorksheet;
ARange: TsCellRange);
begin begin
raise EXception.Create('ColorRange not yet implemented.'); raise EXception.Create('ColorRange not yet implemented.');
end; end;
procedure TsConditionalFormatlist.AddDataBarRule(ARange: TsCellRange); procedure TsConditionalFormatlist.AddDataBarRule(ASheet: TsBasicWorksheet;
ARange: TsCellRange);
begin begin
raise Exception.Create('DataBars not yet implemented.'); raise Exception.Create('DataBars not yet implemented.');
end; end;
@ -287,7 +294,7 @@ begin
for r := CF.CellRange.Row1 to CF.CellRange.Row2 do for r := CF.CellRange.Row1 to CF.CellRange.Row2 do
for c := CF.CellRange.Col1 to CF.CellRange.Col2 do for c := CF.CellRange.Col1 to CF.CellRange.Col2 do
begin begin
cell := TsWorksheet(FWorksheet).FindCell(r, c); cell := TsWorksheet(CF.Worksheet).FindCell(r, c);
if Assigned(cell) and (Length(cell^.ConditionalFormatIndex) > 0) then begin if Assigned(cell) and (Length(cell^.ConditionalFormatIndex) > 0) then begin
for i := AIndex+1 to High(cell^.ConditionalFormatIndex) do for i := AIndex+1 to High(cell^.ConditionalFormatIndex) do
cell^.ConditionalFormatIndex[i-1] := cell^.ConditionalFormatIndex[i]; cell^.ConditionalFormatIndex[i-1] := cell^.ConditionalFormatIndex[i];
@ -304,7 +311,8 @@ end;
This function searches all format item whether a given cell ranges is This function searches all format item whether a given cell ranges is
already listed. already listed.
-------------------------------------------------------------------------------} -------------------------------------------------------------------------------}
function TsConditionalFormatList.Find(ARange: TsCellRange): Integer; function TsConditionalFormatList.Find(ASheet: TsBasicWorksheet;
ARange: TsCellRange): Integer;
var var
i: Integer; i: Integer;
CF: TsConditionalFormat; CF: TsConditionalFormat;
@ -313,6 +321,8 @@ begin
for i := 0 to Count-1 do for i := 0 to Count-1 do
begin begin
CF := TsConditionalFormat(Items[i]); CF := TsConditionalFormat(Items[i]);
if CF.Worksheet = ASheet then
begin
CFRange := CF.CellRange; CFRange := CF.CellRange;
if (CFRange.Row1 = ARange.Row1) and (CFRange.Row2 = ARange.Row2) and if (CFRange.Row1 = ARange.Row1) and (CFRange.Row2 = ARange.Row2) and
(CFRange.Col1 = ARange.Col1) and (CFRange.Col2 = ARange.Col2) then (CFRange.Col1 = ARange.Col1) and (CFRange.Col2 = ARange.Col2) then
@ -321,6 +331,7 @@ begin
exit; exit;
end; end;
end; end;
end;
Result := -1; Result := -1;
end; end;

View File

@ -75,7 +75,6 @@ type
FHyperlinks: TsHyperlinks; FHyperlinks: TsHyperlinks;
FFormulas: TsFormulas; FFormulas: TsFormulas;
FImages: TFPList; FImages: TFPList;
FConditionalFormats: TsConditionalFormatList;
FRows, FCols: TIndexedAVLTree; // This lists contain only rows or cols with styles different from default FRows, FCols: TIndexedAVLTree; // This lists contain only rows or cols with styles different from default
FActiveCellRow: Cardinal; FActiveCellRow: Cardinal;
FActiveCellCol: Cardinal; FActiveCellCol: Cardinal;
@ -109,7 +108,6 @@ type
FOnWriteCellData: TsWorksheetWriteCellDataEvent; FOnWriteCellData: TsWorksheetWriteCellDataEvent;
{ Setter/Getter } { Setter/Getter }
function GetConditionalFormatCount: Integer;
function GetDefaultColWidth: Single; function GetDefaultColWidth: Single;
function GetDefaultRowHeight: Single; function GetDefaultRowHeight: Single;
function GetFormatSettings: TFormatSettings; function GetFormatSettings: TFormatSettings;
@ -386,7 +384,6 @@ type
AValue: TsCellProtections); overload; AValue: TsCellProtections); overload;
{ Conditional formatting } { Conditional formatting }
function ReadConditionalFormat(AIndex: Integer): TsConditionalFormat;
function WriteConditionalCellFormat(ARange: TsCellRange; ACondition: TsCFCondition; function WriteConditionalCellFormat(ARange: TsCellRange; ACondition: TsCFCondition;
ACellFormatIndex: Integer): Integer; overload; ACellFormatIndex: Integer): Integer; overload;
function WriteConditionalCellFormat(ARange: TsCellRange; ACondition: TsCFCondition; function WriteConditionalCellFormat(ARange: TsCellRange; ACondition: TsCFCondition;
@ -610,8 +607,6 @@ type
property Cells: TsCells read FCells; property Cells: TsCells read FCells;
{@@ List of all column records of the worksheet having a non-standard column width } {@@ List of all column records of the worksheet having a non-standard column width }
property Cols: TIndexedAVLTree read FCols; property Cols: TIndexedAVLTree read FCols;
{@@ Count of conditional format entries }
property ConditionalFormatCount: Integer read GetConditionalFormatCount;
{@@ Information how the worksheet is encrypted } {@@ Information how the worksheet is encrypted }
property CryptoInfo: TsCryptoInfo read FCryptoInfo write FCryptoInfo; property CryptoInfo: TsCryptoInfo read FCryptoInfo write FCryptoInfo;
{@@ List of all comment records } {@@ List of all comment records }
@ -741,6 +736,7 @@ type
FFontList: TFPList; FFontList: TFPList;
FNumFormatList: TFPList; FNumFormatList: TFPList;
FCellFormatList: TsCellFormatList; FCellFormatList: TsCellFormatList;
FConditionalFormatList: TsConditionalFormatList;
FEmbeddedObjList: TFPList; FEmbeddedObjList: TFPList;
{ Internal methods } { Internal methods }
@ -825,6 +821,10 @@ type
function GetPointerToCellFormat(AIndex: Integer): PsCellFormat; function GetPointerToCellFormat(AIndex: Integer): PsCellFormat;
procedure RemoveAllCellFormats(AKeepDefaultFormat: Boolean); procedure RemoveAllCellFormats(AKeepDefaultFormat: Boolean);
{ Conditional formatting }
function GetConditionalFormat(AIndex: Integer): TsConditionalFormat;
function GetNumConditionalFormats: Integer;
{ Font handling } { Font handling }
function AddFont(const AFontName: String; ASize: Single; AStyle: TsFontStyles; function AddFont(const AFontName: String; ASize: Single; AStyle: TsFontStyles;
AColor: TsColor; APosition: TsFontPosition = fpNormal): Integer; overload; AColor: TsColor; APosition: TsFontPosition = fpNormal): Integer; overload;
@ -1185,7 +1185,6 @@ begin
FHyperlinks := TsHyperlinks.Create; FHyperlinks := TsHyperlinks.Create;
FFormulas := TsFormulas.Create; FFormulas := TsFormulas.Create;
FImages := TFPList.Create; FImages := TFPList.Create;
FConditionalFormats := TsConditionalFormatList.Create;
FPageLayout := TsPageLayout.Create(self); FPageLayout := TsPageLayout.Create(self);
@ -1229,7 +1228,6 @@ begin
FHyperlinks.Free; FHyperlinks.Free;
FFormulas.Free; FFormulas.Free;
FImages.Free; FImages.Free;
FConditionalFormats.Free;
inherited Destroy; inherited Destroy;
end; end;
@ -8705,6 +8703,7 @@ begin
FNumFormatList := TsNumFormatList.Create(FormatSettings, true); FNumFormatList := TsNumFormatList.Create(FormatSettings, true);
FCellFormatList := TsCellFormatList.Create(false); FCellFormatList := TsCellFormatList.Create(false);
FConditionalFormatList := TsConditionalFormatList.Create;
FEmbeddedObjList := TFPList.Create; FEmbeddedObjList := TFPList.Create;
// Add default cell format // Add default cell format
@ -8725,6 +8724,7 @@ begin
EnableNotifications; EnableNotifications;
FWorksheets.Free; FWorksheets.Free;
FConditionalFormatList.Free;
FCellFormatList.Free; FCellFormatList.Free;
FNumFormatList.Free; FNumFormatList.Free;
@ -9860,6 +9860,19 @@ begin
end; end;
{ Conditional formats }
function TsWorkbook.GetConditionalFormat(AIndex: Integer): TsConditionalFormat;
begin
Result := FConditionalFormatList[AIndex] as TsConditionalFormat;
end;
function TsWorkbook.GetNumConditionalFormats: Integer;
begin
Result := FConditionalFormatList.Count;
end;
{ Font handling } { Font handling }
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------

View File

@ -1,20 +1,5 @@
{ Included by fpspreadsheet.pas } { Included by fpspreadsheet.pas }
{ Returns the count of conditional format items }
function TsWorksheet.GetConditionalFormatCount: Integer;
begin
Result := FConditionalFormats.Count;
end;
{@@ ----------------------------------------------------------------------------
Returns the conditional format item stored in the CF list at the specified
index.
-------------------------------------------------------------------------------}
function TsWorksheet.ReadConditionalFormat(AIndex: Integer): TsConditionalFormat;
begin
Result := TsConditionalFormat(FConditionalFormats[AIndex]);
end;
procedure StoreCFIndexInCells(AWorksheet: TsWorksheet; AIndex: Integer; procedure StoreCFIndexInCells(AWorksheet: TsWorksheet; AIndex: Integer;
ARange: TsCellRange); ARange: TsCellRange);
var var
@ -42,8 +27,8 @@ end;
function TsWorksheet.WriteConditionalCellFormat(ARange: TsCellRange; function TsWorksheet.WriteConditionalCellFormat(ARange: TsCellRange;
ACondition: TsCFCondition; ACellFormatIndex: Integer): Integer; ACondition: TsCFCondition; ACellFormatIndex: Integer): Integer;
begin begin
Result := FConditionalFormats.AddCellRule(ARange, ACondition, Result := FWorkbook.FConditionalFormatList.AddCellRule(Self, ARange,
ACellFormatIndex); ACondition, ACellFormatIndex);
StoreCFIndexInCells(self, Result, ARange); StoreCFIndexInCells(self, Result, ARange);
end; end;
@ -58,7 +43,7 @@ end;
function TsWorksheet.WriteConditionalCellFormat(ARange: TsCellRange; function TsWorksheet.WriteConditionalCellFormat(ARange: TsCellRange;
ACondition: TsCFCondition; AParam: Variant; ACellFormatIndex: Integer): Integer; ACondition: TsCFCondition; AParam: Variant; ACellFormatIndex: Integer): Integer;
begin begin
Result := FConditionalFormats.AddCellRule(ARange, ACondition, Result := FWorkbook.FConditionalFormatList.AddCellRule(Self, ARange, ACondition,
AParam, ACellFormatIndex); AParam, ACellFormatIndex);
StoreCFIndexInCells(self, Result, ARange); StoreCFIndexInCells(self, Result, ARange);
end; end;
@ -75,7 +60,7 @@ function TsWorksheet.WriteConditionalCellFormat(ARange: TsCellRange;
ACondition: TsCFCondition; AParam1, AParam2: Variant; ACondition: TsCFCondition; AParam1, AParam2: Variant;
ACellFormatIndex: Integer): Integer; ACellFormatIndex: Integer): Integer;
begin begin
Result := FConditionalFormats.AddCellRule(ARange, ACondition, Result := FWorkbook.FConditionalFormatList.AddCellRule(Self, ARange, ACondition,
AParam1, AParam2, ACellFormatIndex); AParam1, AParam2, ACellFormatIndex);
StoreCFIndexInCells(self, Result, ARange); StoreCFIndexInCells(self, Result, ARange);
end; end;

View File

@ -194,6 +194,7 @@ function CombineTextAndRichTextParams(AText: String;
procedure SplitTextAndRichTextParams(AValue: String; procedure SplitTextAndRichTextParams(AValue: String;
out AText: String; out ARichText: TsRichTextParams); out AText: String; out ARichText: TsRichTextParams);
function SplitStr(const AText: String; ADelimiter: Char): TStringArray; function SplitStr(const AText: String; ADelimiter: Char): TStringArray;
function SafeQuoteStr(AString: String): String;
function UnquoteStr(AString: String): String; function UnquoteStr(AString: String): String;
function InitSearchParams(ASearchText: String = ''; AOptions: TsSearchOptions = []; function InitSearchParams(ASearchText: String = ''; AOptions: TsSearchOptions = [];
@ -2371,6 +2372,25 @@ begin
end; end;
end; end;
{@@ ----------------------------------------------------------------------------
Makes sure that the string is encloed by quotes (").
Avoids duplicate quotation.
-------------------------------------------------------------------------------}
function SafeQuoteStr(AString: String): String;
begin
if AString = '' then
Result := '""'
else
if Length(AString) = 1 then
Result := '"' + AString + '"'
else
begin
Result := AString;
if AString[1] <> '"' then Result := '"' + Result;
if AString[Length(AString)] <> '"' then Result := Result + '"';
end;
end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
Removes quotation characters which enclose a string Removes quotation characters which enclose a string
-------------------------------------------------------------------------------} -------------------------------------------------------------------------------}

View File

@ -3081,11 +3081,9 @@ begin
SetLength(FDifferentialFormatIndexList, n); SetLength(FDifferentialFormatIndexList, n);
book := TsWorkbook(FWorkbook); book := TsWorkbook(FWorkbook);
for i:=0 to book.GetWorksheetCount-1 do begin for j := 0 to book.GetNumConditionalFormats-1 do
sheet := book.GetWorksheetByIndex(i);
for j := 0 to sheet.ConditionalFormatCount-1 do
begin begin
CF := sheet.ReadConditionalFormat(j); CF := book.GetConditionalFormat(j);
for k := 0 to CF.RulesCount-1 do for k := 0 to CF.RulesCount-1 do
if CF.Rules[k] is TsCFCellRule then if CF.Rules[k] is TsCFCellRule then
begin begin
@ -3106,7 +3104,6 @@ begin
end; end;
end; end;
end; end;
end;
{ Creates a list of all fill styles found in the workbook. { Creates a list of all fill styles found in the workbook.
The list contains indexes into the array FFormattingStyles for each unique The list contains indexes into the array FFormattingStyles for each unique
@ -3555,22 +3552,28 @@ end;
procedure TsSpreadOOXMLWriter.WriteConditionalFormats(AStream: TStream; procedure TsSpreadOOXMLWriter.WriteConditionalFormats(AStream: TStream;
AWorksheet: TsBasicWorksheet); AWorksheet: TsBasicWorksheet);
var var
book: TsWorkbook;
worksheet: TsWorksheet absolute AWorksheet; worksheet: TsWorksheet absolute AWorksheet;
i: Integer; i: Integer;
CF: TsConditionalFormat; CF: TsConditionalFormat;
priority: Integer = 0; priority: Integer = 0;
ncf: Integer;
begin begin
if worksheet.ConditionalFormatCount = 0 then book := TsWorkbook(FWorkbook);
ncf := book.GetNumConditionalFormats;
if ncf = 0 then
exit; exit;
for i := 0 to worksheet.ConditionalFormatCount-1 do for i := 0 to ncf-1 do
begin begin
CF := worksheet.ReadConditionalFormat(i); CF := book.GetConditionalFormat(i);
if CF.Worksheet = AWorksheet then
inc(priority, CF.RulesCount); inc(priority, CF.RulesCount);
end; end;
for i := 0 to worksheet.ConditionalFormatCount-1 do begin for i := 0 to ncf-1 do begin
CF := worksheet.ReadConditionalFormat(i); CF := book.GetConditionalFormat(i);
if CF.Worksheet = AWorksheet then
WriteConditionalFormat(AStream, CF, priority); WriteConditionalFormat(AStream, CF, priority);
end; end;
end; end;