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

View File

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

View File

@ -1,20 +1,5 @@
{ 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;
ARange: TsCellRange);
var
@ -42,8 +27,8 @@ end;
function TsWorksheet.WriteConditionalCellFormat(ARange: TsCellRange;
ACondition: TsCFCondition; ACellFormatIndex: Integer): Integer;
begin
Result := FConditionalFormats.AddCellRule(ARange, ACondition,
ACellFormatIndex);
Result := FWorkbook.FConditionalFormatList.AddCellRule(Self, ARange,
ACondition, ACellFormatIndex);
StoreCFIndexInCells(self, Result, ARange);
end;
@ -58,7 +43,7 @@ end;
function TsWorksheet.WriteConditionalCellFormat(ARange: TsCellRange;
ACondition: TsCFCondition; AParam: Variant; ACellFormatIndex: Integer): Integer;
begin
Result := FConditionalFormats.AddCellRule(ARange, ACondition,
Result := FWorkbook.FConditionalFormatList.AddCellRule(Self, ARange, ACondition,
AParam, ACellFormatIndex);
StoreCFIndexInCells(self, Result, ARange);
end;
@ -75,7 +60,7 @@ function TsWorksheet.WriteConditionalCellFormat(ARange: TsCellRange;
ACondition: TsCFCondition; AParam1, AParam2: Variant;
ACellFormatIndex: Integer): Integer;
begin
Result := FConditionalFormats.AddCellRule(ARange, ACondition,
Result := FWorkbook.FConditionalFormatList.AddCellRule(Self, ARange, ACondition,
AParam1, AParam2, ACellFormatIndex);
StoreCFIndexInCells(self, Result, ARange);
end;

View File

@ -194,6 +194,7 @@ function CombineTextAndRichTextParams(AText: String;
procedure SplitTextAndRichTextParams(AValue: String;
out AText: String; out ARichText: TsRichTextParams);
function SplitStr(const AText: String; ADelimiter: Char): TStringArray;
function SafeQuoteStr(AString: String): String;
function UnquoteStr(AString: String): String;
function InitSearchParams(ASearchText: String = ''; AOptions: TsSearchOptions = [];
@ -2371,6 +2372,25 @@ begin
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
-------------------------------------------------------------------------------}

View File

@ -3081,30 +3081,27 @@ begin
SetLength(FDifferentialFormatIndexList, n);
book := TsWorkbook(FWorkbook);
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
begin
rule := TsCFCellRule(CF.Rules[k]);
idx := -1;
for d := 0 to High(FDifferentialFormatIndexList) do
if FDifferentialFormatIndexList[d] = rule.FormatIndex then
begin
idx := d;
break;
end;
if idx = -1 then
for j := 0 to book.GetNumConditionalFormats-1 do
begin
CF := book.GetConditionalFormat(j);
for k := 0 to CF.RulesCount-1 do
if CF.Rules[k] is TsCFCellRule then
begin
rule := TsCFCellRule(CF.Rules[k]);
idx := -1;
for d := 0 to High(FDifferentialFormatIndexList) do
if FDifferentialFormatIndexList[d] = rule.FormatIndex then
begin
SetLength(FDifferentialFormatIndexList, n+1);
FDifferentialFormatIndexList[n] := rule.FormatIndex;
inc(n);
end;
idx := d;
break;
end;
if idx = -1 then
begin
SetLength(FDifferentialFormatIndexList, n+1);
FDifferentialFormatIndexList[n] := rule.FormatIndex;
inc(n);
end;
end;
end;
end;
end;
@ -3555,23 +3552,29 @@ end;
procedure TsSpreadOOXMLWriter.WriteConditionalFormats(AStream: TStream;
AWorksheet: TsBasicWorksheet);
var
book: TsWorkbook;
worksheet: TsWorksheet absolute AWorksheet;
i: Integer;
CF: TsConditionalFormat;
priority: Integer = 0;
ncf: Integer;
begin
if worksheet.ConditionalFormatCount = 0 then
book := TsWorkbook(FWorkbook);
ncf := book.GetNumConditionalFormats;
if ncf = 0 then
exit;
for i := 0 to worksheet.ConditionalFormatCount-1 do
for i := 0 to ncf-1 do
begin
CF := worksheet.ReadConditionalFormat(i);
inc(priority, CF.RulesCount);
CF := book.GetConditionalFormat(i);
if CF.Worksheet = AWorksheet then
inc(priority, CF.RulesCount);
end;
for i := 0 to worksheet.ConditionalFormatCount-1 do begin
CF := worksheet.ReadConditionalFormat(i);
WriteConditionalFormat(AStream, CF, priority);
for i := 0 to ncf-1 do begin
CF := book.GetConditionalFormat(i);
if CF.Worksheet = AWorksheet then
WriteConditionalFormat(AStream, CF, priority);
end;
end;