You've already forked lazarus-ccr
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:
@@ -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);
|
||||||
|
@@ -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;
|
||||||
|
Reference in New Issue
Block a user