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.
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;
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;
end;
h1 := ASheet.GetRowHeight(rr);

View File

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