fpspreadsheet: Caching the result of the worksheet's GetLastColIndex and GetLastRowIndex for better writing performance of large ods files (which query these data in the row loop). Has no significant effect, though.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3302 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2014-07-09 14:56:09 +00:00
parent 1979ed4e77
commit 63283c100a
2 changed files with 89 additions and 35 deletions

View File

@@ -2782,10 +2782,12 @@ begin
// Look for empty rows with the same style, they need the "number-rows-repeated" element. // Look for empty rows with the same style, they need the "number-rows-repeated" element.
rowsRepeated := 1; rowsRepeated := 1;
if ASheet.GetCellCountInRow(r) = 0 then begin if (ASheet.GetFirstCellOfRow(r) = nil) then begin
// if ASheet.GetCellCountInRow(r) = 0 then begin
rr := r + 1; rr := r + 1;
while (rr <= lastRow) do begin while (rr <= lastRow) do begin
if ASheet.GetCellCountInRow(rr) > 0 then begin if ASheet.GetFirstCellOfRow(rr) = nil then begin
// if ASheet.GetCellCountInRow(rr) > 0 then begin
break; break;
end; end;
h1 := ASheet.GetRowHeight(rr); h1 := ASheet.GetRowHeight(rr);

View File

@@ -479,6 +479,8 @@ type
FLeftPaneWidth: Integer; FLeftPaneWidth: Integer;
FTopPaneHeight: Integer; FTopPaneHeight: Integer;
FOptions: TsSheetOptions; FOptions: TsSheetOptions;
FLastRowIndex: Cardinal;
FLastColIndex: Cardinal;
FOnChangeCell: TsCellEvent; FOnChangeCell: TsCellEvent;
FOnChangeFont: TsCellEvent; FOnChangeFont: TsCellEvent;
@@ -508,6 +510,7 @@ type
{ Utils } { Utils }
class function CellPosToText(ARow, ACol: Cardinal): string; class function CellPosToText(ARow, ACol: Cardinal): string;
procedure RemoveAllCells; procedure RemoveAllCells;
procedure UpdateCaches;
{ Reading of values } { Reading of values }
function ReadAsUTF8Text(ARow, ACol: Cardinal): ansistring; overload; function ReadAsUTF8Text(ARow, ACol: Cardinal): ansistring; overload;
@@ -636,9 +639,9 @@ type
function GetNextCell(): PCell; function GetNextCell(): PCell;
function GetFirstCellOfRow(ARow: Cardinal): PCell; function GetFirstCellOfRow(ARow: Cardinal): PCell;
function GetLastCellOfRow(ARow: Cardinal): PCell; function GetLastCellOfRow(ARow: Cardinal): PCell;
function GetLastColIndex: Cardinal; function GetLastColIndex(AForceCalculation: Boolean = false): Cardinal;
function GetLastColNumber: Cardinal; deprecated 'Use GetLastColIndex'; function GetLastColNumber: Cardinal; deprecated 'Use GetLastColIndex';
function GetLastRowIndex: Cardinal; function GetLastRowIndex(AForceCalculation: Boolean = false): Cardinal;
function GetLastRowNumber: Cardinal; deprecated 'Use GetLastRowIndex'; function GetLastRowNumber: Cardinal; deprecated 'Use GetLastRowIndex';
{ Data manipulation methods - For Rows and Cols } { Data manipulation methods - For Rows and Cols }
@@ -708,6 +711,7 @@ type
{ Internal methods } { Internal methods }
procedure PrepareBeforeSaving; procedure PrepareBeforeSaving;
procedure RemoveWorksheetsCallback(data, arg: pointer); procedure RemoveWorksheetsCallback(data, arg: pointer);
procedure UpdateCaches;
public public
{@@ A copy of SysUtil's DefaultFormatSettings to provide some kind of {@@ A copy of SysUtil's DefaultFormatSettings to provide some kind of
@@ -1414,6 +1418,9 @@ begin
FRows := TIndexedAVLTree.Create(@CompareRows); FRows := TIndexedAVLTree.Create(@CompareRows);
FCols := TIndexedAVLTree.Create(@CompareCols); FCols := TIndexedAVLTree.Create(@CompareCols);
FLastRowIndex := 0;
FLastColIndex := 0;
FOptions := [soShowGridLines, soShowHeaders]; FOptions := [soShowGridLines, soShowHeaders];
end; end;
@@ -1761,6 +1768,10 @@ begin
Result^.BorderStyles := DEFAULT_BORDERSTYLES; Result^.BorderStyles := DEFAULT_BORDERSTYLES;
Cells.Add(Result); Cells.Add(Result);
if FLastColIndex = 0 then FLastColIndex := GetLastColIndex(true)
else FLastColIndex := Max(FLastColIndex, ACol);
if FLastRowIndex = 0 then FLastRowIndex := GetLastRowIndex(true)
else FLastRowIndex := Max(FLastRowIndex, ARow);
end; end;
end; end;
@@ -1897,30 +1908,38 @@ end;
Use GetCellCount to verify if there is at least one cell with contents in the Use GetCellCount to verify if there is at least one cell with contents in the
worksheet. worksheet.
@param AForceCalculation The index of the last column is continuously updated
whenever a new cell is created. If AForceCalculation
is true all cells are scanned to determine the index
of the last column.
@see GetCellCount @see GetCellCount
} }
function TsWorksheet.GetLastColIndex: Cardinal; function TsWorksheet.GetLastColIndex(AForceCalculation: Boolean = false): Cardinal;
var var
AVLNode: TAVLTreeNode; AVLNode: TAVLTreeNode;
i: Integer; i: Integer;
begin begin
Result := 0; if AForceCalculation then begin
Result := 0;
// Traverse the tree from lowest to highest. // Traverse the tree from lowest to highest.
// Since tree primary sort order is on Row // Since tree primary sort order is on Row
// highest Col could exist anywhere. // highest Col could exist anywhere.
AVLNode := FCells.FindLowest; AVLNode := FCells.FindLowest;
While Assigned(AVLNode) do While Assigned(AVLNode) do
begin begin
Result := Math.Max(Result, PCell(AVLNode.Data)^.Col); Result := Math.Max(Result, PCell(AVLNode.Data)^.Col);
AVLNode := FCells.FindSuccessor(AVLNode); AVLNode := FCells.FindSuccessor(AVLNode);
end; end;
// In addition, there may be column records defining the column width even
// In addition, there may be column records defining the column width even // without content
// without content for i:=0 to FCols.Count-1 do
for i:=0 to FCols.Count-1 do if FCols[i] <> nil then
if FCols[i] <> nil then Result := Math.Max(Result, PCol(FCols[i])^.Col);
Result := Math.Max(Result, PCol(FCols[i])^.Col); // Store the result
FLastColIndex := Result;
end
else
Result := FLastColIndex;
end; end;
{@@ {@@
@@ -1979,23 +1998,31 @@ end;
Use GetCellCount to verify if there is at least one cell with contents in the Use GetCellCount to verify if there is at least one cell with contents in the
worksheet. worksheet.
@param AForceCalculation The index of the last row is continuously updated
whenever a new cell is created. If AForceCalculation
is true all cells are scanned to determine the index
of the last row.
@see GetCellCount @see GetCellCount
} }
function TsWorksheet.GetLastRowIndex: Cardinal; function TsWorksheet.GetLastRowIndex(AForceCalculation: Boolean = false): Cardinal;
var var
AVLNode: TAVLTreeNode; AVLNode: TAVLTreeNode;
i: Integer; i: Integer;
begin begin
Result := 0; if AForceCalculation then begin
Result := 0;
AVLNode := FCells.FindHighest; AVLNode := FCells.FindHighest;
if Assigned(AVLNode) then if Assigned(AVLNode) then
Result := PCell(AVLNode.Data).Row; Result := PCell(AVLNode.Data).Row;
// In addition, there may be row records even for empty rows.
// In addition, there may be row records even for empty rows. for i:=0 to FRows.Count-1 do
for i:=0 to FRows.Count-1 do if FRows[i] <> nil then
if FRows[i] <> nil then Result := Math.Max(Result, PRow(FRows[i])^.Row);
Result := Math.Max(Result, PRow(FRows[i])^.Row); // Store result
FLastRowIndex := Result;
end
else
Result := FLastRowIndex
end; end;
{@@ {@@
@@ -2295,7 +2322,7 @@ begin
// Now we construct the string from the parts stored in the stringlist. // Now we construct the string from the parts stored in the stringlist.
// Every item processed is deleted from the list for error detection. // Every item processed is deleted from the list for error detection.
// In order not to confuse mix up we start at the end of the list and // In order not to confuse indexes we start at the end of the list and
// work forward. // work forward.
i := L.Count-1; i := L.Count-1;
while (L.Count > 0) and (i >= 0) do begin while (L.Count > 0) and (i >= 0) do begin
@@ -2433,6 +2460,15 @@ begin
FCells.Clear; FCells.Clear;
end; end;
{@@
Helper method to update internal caching variables
}
procedure TsWorksheet.UpdateCaches;
begin
FLastColIndex := GetLastColIndex(true);
FLastRowIndex := GetLastRowIndex(true);
end;
{@@ {@@
Writes UTF-8 encoded text to a cell. Writes UTF-8 encoded text to a cell.
@@ -3656,6 +3692,8 @@ begin
FillChar(Result^, SizeOf(TRow), #0); FillChar(Result^, SizeOf(TRow), #0);
Result^.Row := ARow; Result^.Row := ARow;
FRows.Add(Result); FRows.Add(Result);
if FLastRowIndex = 0 then FLastRowIndex := GetLastRowIndex(true)
else FLastRowIndex := Max(FLastRowIndex, ARow);
end; end;
end; end;
@@ -3674,6 +3712,8 @@ begin
FillChar(Result^, SizeOf(TCol), #0); FillChar(Result^, SizeOf(TCol), #0);
Result^.Col := ACol; Result^.Col := ACol;
FCols.Add(Result); FCols.Add(Result);
if FLastColIndex = 0 then FLastColIndex := GetLastColIndex(true)
else FLastColIndex := Max(FLastColIndex, ACol);
end; end;
end; end;
@@ -3887,6 +3927,17 @@ begin
TsWorksheet(data).Free; TsWorksheet(data).Free;
end; end;
{@@
Helper method to update internal caching variables
}
procedure TsWorkbook.UpdateCaches;
var
sheet: TsWorksheet;
begin
for sheet in FWorksheets do
sheet.UpdateCaches;
end;
{@@ {@@
Constructor of the workbook class. Among others, it initializes the built-in Constructor of the workbook class. Among others, it initializes the built-in
fonts, defines the default font, and sets up the FormatSettings for localization fonts, defines the default font, and sets up the FormatSettings for localization
@@ -4012,6 +4063,7 @@ begin
try try
FFileName := AFileName; FFileName := AFileName;
AReader.ReadFromFile(AFileName, Self); AReader.ReadFromFile(AFileName, Self);
UpdateCaches;
FFormat := AFormat; FFormat := AFormat;
finally finally
AReader.Free; AReader.Free;
@@ -4096,9 +4148,9 @@ var
AReader: TsCustomSpreadReader; AReader: TsCustomSpreadReader;
begin begin
AReader := CreateSpreadReader(AFormat); AReader := CreateSpreadReader(AFormat);
try try
AReader.ReadFromStream(AStream, Self); AReader.ReadFromStream(AStream, Self);
UpdateCaches;
finally finally
AReader.Free; AReader.Free;
end; end;