fpspreadsheet: make sure that formulas are only recalculated when needed (in particalar only once after loading a file). Rename worksheet option soCalcAfterSaving to boCalcAfterSaving and assign it to the Workbook. (Add section "Incompatible changes" to wiki).

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3478 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2014-08-13 19:23:59 +00:00
parent 2dd6598e20
commit 67186349be
4 changed files with 48 additions and 32 deletions

View File

@@ -134,8 +134,9 @@ begin
workbook := TsWorkbook.Create;
try
workbook.Options := workbook.Options + [boCalcBeforeSaving];
worksheet := workbook.AddWorksheet('Financial');
worksheet.Options := worksheet.Options + [soCalcBeforeSaving];
worksheet.WriteColWidth(0, 40);
worksheet.WriteColWidth(1, 15);

View File

@@ -22,12 +22,14 @@ var
worksheet: TsWorksheet;
const
OutputFile='test_calc.xls';
begin
writeln('Starting program.');
workbook := TsWorkbook.Create;
try
workbook.Options := workbook.Options + [boCalcBeforeSaving];
worksheet := workbook.AddWorksheet('Calc_test');
worksheet.Options := worksheet.Options + [soCalcBeforeSaving];
worksheet.WriteColWidth(0, 20);
// A1

View File

@@ -459,12 +459,8 @@ type
@param soShowHeaders Show or hide the column or row headers of the spreadsheet
@param soHasFrozenPanes If set a number of rows and columns of the spreadsheet
is fixed and does not scroll. The number is defined by
LeftPaneWidth and TopPaneHeight.
@param soCalcBeforeSaving Calculates formulas before saving the file. Otherwise
there are no results when the file is loaded back by
fpspreadsheet. }
TsSheetOption = (soShowGridLines, soShowHeaders, soHasFrozenPanes,
soCalcBeforeSaving);
LeftPaneWidth and TopPaneHeight. }
TsSheetOption = (soShowGridLines, soShowHeaders, soHasFrozenPanes);
{@@ Set of user interface options
@ see TsSheetOption }
@@ -761,8 +757,10 @@ type
to memory)
@param boAutoCalc Automatically recalculate rpn formulas whenever
a cell value changes.
}
TsWorkbookOption = (boVirtualMode, boBufStream, boAutoCalc);
@param boCalcBeforeSaving Calculates formulas before saving the file.
Otherwise there are no results when the file is
loaded back by fpspreadsheet. }
TsWorkbookOption = (boVirtualMode, boBufStream, boAutoCalc, boCalcBeforeSaving);
{@@
Set of options flags for the workbook }
@@ -800,7 +798,7 @@ type
FVirtualColCount: Cardinal;
FVirtualRowCount: Cardinal;
FWriting: Boolean;
FCalculating: Boolean;
FCalculationLock: Integer;
FOptions: TsWorkbookOptions;
FOnWriteCellData: TsWorkbookWriteCellDataEvent;
FOnReadCellData: TsWorkbookReadCellDataEvent;
@@ -816,6 +814,7 @@ type
procedure GetLastRowColIndex(out ALastRow, ALastCol: Cardinal);
procedure PrepareBeforeReading;
procedure PrepareBeforeSaving;
procedure ReCalc;
procedure RemoveWorksheetsCallback(data, arg: pointer);
procedure UpdateCaches;
@@ -1730,7 +1729,7 @@ var
begin
// prevent infinite loop due to triggering of formula calculation whenever
// a cell changes during execution of CalcFormulas.
FWorkbook.FCalculating := true;
inc(FWorkbook.FCalculationLock);
try
// Step 1 - mark all formula cells as "not calculated"
node := FCells.FindLowest;
@@ -1747,7 +1746,7 @@ begin
node := FCells.FindSuccessor(node);
end;
finally
FWorkbook.FCalculating := false;
dec(FWorkbook.FCalculationLock);
end;
end;
@@ -1914,7 +1913,7 @@ end;
}
procedure TsWorksheet.ChangedCell(ARow, ACol: Cardinal);
begin
if not FWorkbook.FCalculating and (boAutoCalc in FWorkbook.Options) then
if (FWorkbook.FCalculationLock = 0) and (boAutoCalc in FWorkbook.Options) then
begin
if CellUsedInFormula(ARow, ACol) then
CalcFormulas;
@@ -4849,8 +4848,19 @@ begin
UpdateCaches;
// Calculated formulas (if requested)
if (boCalcBeforeSaving in FOptions) then
for sheet in FWorksheets do
sheet.CalcFormulas;
end;
{@@
Recalculates rpn formulas in all worksheets
}
procedure TsWorkbook.Recalc;
var
sheet: TsWorksheet;
begin
for sheet in FWorksheets do
if (soCalcBeforeSaving in sheet.Options) then
sheet.CalcFormulas;
end;
@@ -5026,6 +5036,8 @@ begin
PrepareBeforeReading;
AReader.ReadFromFile(AFileName, Self);
UpdateCaches;
if (boAutoCalc in Options) then
Recalc;
FFormat := AFormat;
finally
AReader.Free;
@@ -5083,7 +5095,7 @@ var
SheetType: TsSpreadsheetFormat;
lException: Exception;
begin
lException := pointer(1);
lException := pointer(1); // Must not be nil initially
SheetType := sfExcel8;
while (SheetType in [sfExcel2..sfExcel8, sfOpenDocument, sfOOXML]) and (lException <> nil) do
begin
@@ -5092,8 +5104,7 @@ begin
ReadFromFile(AFileName, SheetType);
lException := nil;
except
on E: Exception do
{ do nothing } ;
on E: Exception do { do nothing } ;
end;
if lException = nil then Break;
end;
@@ -5115,6 +5126,8 @@ begin
PrepareBeforeReading;
AReader.ReadFromStream(AStream, Self);
UpdateCaches;
if (boAutoCalc in Options) then
Recalc;
finally
AReader.Free;
end;

View File

@@ -180,10 +180,10 @@ begin
// Create test workbook
MyWorkbook := TsWorkbook.Create;
try
MyWorkSheet:= MyWorkBook.AddWorksheet(SHEET);
MyWorkSheet.Options := MyWorkSheet.Options + [soCalcBeforeSaving];
MyWorkbook.Options := MyWorkbook.Options + [boCalcBeforeSaving];
// Calculation of rpn formulas must be activated explicitly!
MyWorkSheet:= MyWorkBook.AddWorksheet(SHEET);
{ Write out test formulas.
This include file creates various rpn formulas and stores the expected
results in array "sollValues".