diff --git a/components/fpspreadsheet/source/common/fpsexprparser.pas b/components/fpspreadsheet/source/common/fpsexprparser.pas index d63865391..efaa00d89 100644 --- a/components/fpspreadsheet/source/common/fpsexprparser.pas +++ b/components/fpspreadsheet/source/common/fpsexprparser.pas @@ -1689,6 +1689,12 @@ begin if sheet = nil then sheet := FWorksheet.Workbook.AddWorksheet(sheetName, true); Result := TsCellExprNode.Create(self, sheet, CurrentToken, true) + end else + if TokenType = ttCellRange then begin + sheet := FWorksheet.WorkBook.GetWorksheetByName(sheetName); + if sheet = nil then + sheet := FWorksheet.Workbook.AddWorksheet(sheetName, true); + Result := TsCellRangeExprNode.Create(self, sheet, CurrentToken); end; end else if (TokenType = ttCellRange) then diff --git a/components/fpspreadsheet/source/common/fpspreadsheet.pas b/components/fpspreadsheet/source/common/fpspreadsheet.pas index 9f3f8c55f..9c81c84fb 100644 --- a/components/fpspreadsheet/source/common/fpspreadsheet.pas +++ b/components/fpspreadsheet/source/common/fpspreadsheet.pas @@ -852,6 +852,9 @@ type function GetNumberFormat(AIndex: Integer): TsNumFormatParams; function GetNumberFormatCount: Integer; + { Calculation } + procedure CalcFormulas; + { Clipboard } procedure CopyToClipboardStream(AStream: TStream; AFormat: TsSpreadsheetFormat; AParams: TsStreamParams = []); @@ -1354,10 +1357,15 @@ end; "not calculated" they are calculated and then tagged as "calculated". This results in an iterative calculation procedure. In the end, all cells are calculated. + + NOTE: IF THE WORKSHEET CONTAINS CELLS WHICH LINK TO OTHER WORKSHEETS THEN + THIS CALCULATION MAY NOT BE CORRECT. USE THE SAME METHOD OF THE WORKBOOK + INSTEAD !!! -------------------------------------------------------------------------------} procedure TsWorksheet.CalcFormulas; var cell: PCell; + i: Integer; begin if (boIgnoreFormulas in Workbook.Options) then exit; @@ -9657,6 +9665,51 @@ begin Result := FNumFormatList.Count; end; +{@@ ---------------------------------------------------------------------------- + Calculates all formulas of the workbook. + + Since formulas may reference not-yet-calculated cells, this occurs in + two steps: + 1. All formula cells are marked as "not calculated". + 2. Cells are calculated. If referenced cells are found as being + "not calculated" they are calculated and then tagged as "calculated". + This results in an iterative calculation procedure. In the end, all cells + are calculated. +-------------------------------------------------------------------------------} +procedure TsWorkbook.CalcFormulas; +var + cell: PCell; + p: Pointer; + sheet: TsWorksheet; + i: Integer; +begin + if (boIgnoreFormulas in Options) then + exit; + + // prevent infinite loop due to triggering of formula calculation whenever + // a cell changes during execution of CalcFormulas. + inc(FCalculationLock); + try + // Step 1 - mark all formula cells as "not calculated" + for p in FWorksheets do begin + sheet := TsWorksheet(p); + for cell in sheet.Cells do + if HasFormula(cell) then + sheet.SetCalcState(cell, csNotCalculated); + end; + + // Step 2 - calculate cells. If a not-yet-calculated cell is found it is + for p in FWorksheets do begin + sheet := TsWorksheet(p); + for cell in TsWorksheet(sheet).Cells do + if HasFormula(cell) and (cell^.ContentType <> cctError) then + sheet.CalcFormula(cell); + end; + finally + dec(FCalculationLock); + end; +end; + {@@ ---------------------------------------------------------------------------- Writes the selected cells to a stream for usage in the clipboard. Transfer to the clipboard has do be done by the calling routine since