fpspreadsheet: Fix memory leak in virtual mode due to incorrectly initialized strings in the cell record.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3352 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2014-07-20 18:19:43 +00:00
parent ecaa1d67cb
commit 7a3a9060e9
5 changed files with 69 additions and 19 deletions

View File

@ -78,6 +78,7 @@
<Linking>
<Debugging>
<DebugInfoType Value="dsDwarf2Set"/>
<UseHeaptrc Value="True"/>
</Debugging>
</Linking>
</CompilerOptions>

View File

@ -7,7 +7,7 @@ uses
cthreads,
{$ENDIF}{$ENDIF}
Classes, laz_fpspreadsheet,
{ you can add units after this }
{ you can add units after this } lazutf8,
SysUtils, variants, fpspreadsheet, xlsbiff2, xlsbiff5, xlsbiff8, xlsxooxml;
type
@ -41,12 +41,11 @@ var
// This makes the style of the "headerTemplate" cell available to
// formatting of all virtual cells in row 0.
// Important: The template cell must be an existing cell in the worksheet.
end else {
if odd(random(10)) then }begin
s := Format('R=%d-C=%d', [ARow, ACol]);
AData := s;
end {else
AData := 10000*ARow + ACol};
end else
if odd(random(10)) then begin
AData := Format('R=%d-C=%d', [ARow, ACol]);
end else
AData := 10000*ARow + ACol;
// you can use the OnNeedData also to provide feedback on how the process
// progresses:
@ -65,8 +64,8 @@ begin
{ These are the essential commands to activate virtual mode: }
workbook.WritingOptions := [woVirtualMode, woBufStream];
// workbook.WritingOptions := [woVirtualMode];
// workbook.WritingOptions := [woVirtualMode, woBufStream];
workbook.WritingOptions := [woVirtualMode];
{ woBufStream can be omitted, but is important for large files: it causes
writing temporary data to a buffered file stream instead of a pure
memory stream which can overflow memory. The option can slow down the
@ -75,7 +74,7 @@ begin
{ Next two numbers define the size of virtual spreadsheet.
In case of a database, VirtualRowCount is the RecordCount, VirtualColCount
the number of fields to be written to the spreadsheet file }
workbook.VirtualRowCount := 60000;
workbook.VirtualRowCount := 20000;
workbook.VirtualColCount := 100;
{ The event handler for OnNeedCellData links the workbook to the method
@ -96,19 +95,20 @@ begin
{ In case of a database, you would open the dataset before calling this: }
t := Now;
workbook.WriteToFile('test_virtual.xlsx', sfOOXML, true);
//workbook.WriteToFile('test_virtual.xls', sfExcel8, true);
//workbook.WriteToFile('test_virtual.xlsx', sfOOXML, true);
workbook.WriteToFile('test_virtual.xls', sfExcel8, true);
t := Now - t;
finally
workbook.Free;
end;
WriteLn(Format('Execution time: %.3f sec', [t*24*60*60]));
WriteLn('Press [ENTER] to quit...');
ReadLn;
finally
dataprovider.Free;
end;
WriteLn(Format('Execution time: %.3f sec', [t*24*60*60]));
WriteLn('Press [ENTER] to quit...');
ReadLn;
end.

View File

@ -1072,6 +1072,9 @@ function GetFileFormatName(AFormat: TsSpreadsheetFormat): String;
procedure MakeLEPalette(APalette: PsPalette; APaletteSize: Integer);
function SameCellBorders(ACell1, ACell2: PCell): Boolean;
procedure InitCell(var ACell: TCell);
implementation
uses
@ -1460,6 +1463,47 @@ begin
end;
end;
{@@
Initalizes a new cell
}
procedure InitCell(var ACell: TCell);
begin
ACell.RPNFormulaValue := nil;
ACell.FormulaValue.FormulaStr := '';
ACell.UTF8StringValue := '';
ACell.NumberFormatStr := '';
FillChar(ACell, SizeOf(ACell), 0);
end;
(*
Col: Cardinal; // zero-based
Row: Cardinal; // zero-based
ContentType: TCellContentType;
{ Possible values for the cells }
FormulaValue: TsFormula;
RPNFormulaValue: TsRPNFormula;
NumberValue: double;
UTF8StringValue: ansistring;
DateTimeValue: TDateTime;
BoolValue: Boolean;
ErrorValue: TsErrorValue;
{ Formatting fields }
{ When adding/deleting formatting fields don't forget to update CopyFormat! }
UsedFormattingFields: TsUsedFormattingFields;
FontIndex: Integer;
TextRotation: TsTextRotation;
HorAlignment: TsHorAlignment;
VertAlignment: TsVertAlignment;
Border: TsCellBorders;
BorderStyles: TsCelLBorderStyles;
BackgroundColor: TsColor;
NumberFormat: TsNumberFormat;
NumberFormatStr: String;
RGBBackgroundColor: TFPColor; // only valid if BackgroundColor=scRGBCOLOR
{ Status flags }
CalcState: TsCalcState;
*)
{ TsWorksheet }
{@@
@ -5803,6 +5847,7 @@ end;
function NewRPNItem: PRPNItem;
begin
Result := GetMem(SizeOf(TRPNItem));
Result^.FE.StringValue := '';
FillChar(Result^.FE, SizeOf(Result^.FE), 0);
Result^.FE.StringValue := '';
end;

View File

@ -2577,7 +2577,8 @@ var
begin
for r := 0 to Workbook.VirtualRowCount-1 do begin
for c := 0 to Workbook.VirtualColCount-1 do begin
FillChar(lCell, SizeOf(lCell), 0);
InitCell(lCell);
// FillChar(lCell, SizeOf(lCell), 0);
value := varNull;
styleCell := nil;
Workbook.OnNeedCellData(Workbook, r, c, value, styleCell);
@ -2607,6 +2608,7 @@ begin
end else
lCell.ContentType := cctEmpty;
WriteCellCallback(@lCell, AStream);
value := varNULL;
end;
end;
end;

View File

@ -249,12 +249,12 @@ begin
SetLength(FFormattingStyles, 2);
// Default style
FillChar(FFormattingStyles[0], SizeOf(TCell), 0);
InitCell(FFormattingStyles[0]);
FFormattingStyles[0].BorderStyles := DEFAULT_BORDERSTYLES;
FFormattingStyles[0].Row := 0;
// Bold style
FillChar(FFormattingStyles[1], SizeOf(TCell), 0);
InitCell(FFormattingStyles[1]);
FFormattingStyles[1].UsedFormattingFields := [uffBold];
FFormattingStyles[1].FontIndex := 1; // this is the "bold" font
FFormattingStyles[1].Row := 1;
@ -917,7 +917,8 @@ begin
AppendToStream(FSSheets[FCurSheetNum], Format(
'<row r="%d" spans="1:%d"%s>', [r+1, Workbook.VirtualColCount, rh]));
for c := 0 to Workbook.VirtualColCount-1 do begin
FillChar(lCell, SizeOf(lCell), 0);
//FillChar(lCell, SizeOf(lCell), 0);
InitCell(lCell);
CellPosText := CurSheet.CellPosToText(r, c);
value := varNull;
styleCell := nil;
@ -948,6 +949,7 @@ begin
lCell.BoolValue := value <> 0;
end;
WriteCellCallback(@lCell, FSSheets[FCurSheetNum]);
varClear(value);
end;
AppendToStream(FSSheets[FCurSheetNum],
'</row>');