From 7679ef468c70d0069a21d8138b39b331908cd6c8 Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Wed, 27 Jan 2016 22:17:56 +0000 Subject: [PATCH] fpspreadsheet: Show message during writing when a formula is not supported by file format. Fix TsWorkbookSource ignoring its set options (i.e. ReadFormulas and AutoCalc working again). git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@4480 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- .../examples/visual/fpsctrls/main.lfm | 2 +- .../examples/visual/fpsgrid/mainform.lfm | 168 +++++++++++------- .../examples/visual/fpsgrid/mainform.pas | 18 ++ components/fpspreadsheet/fpsexprparser.pas | 1 - .../fpspreadsheet/fpspreadsheetctrls.pas | 2 +- .../fpspreadsheet/fpspreadsheetgrid.pas | 63 +++---- components/fpspreadsheet/fpsstrings.pas | 1 + .../reference/BIFFExplorer/BIFFExplorer.lpi | 10 +- components/fpspreadsheet/xlsbiff2.pas | 25 ++- components/fpspreadsheet/xlsbiff5.pas | 9 +- components/fpspreadsheet/xlscommon.pas | 77 +++++--- 11 files changed, 222 insertions(+), 154 deletions(-) diff --git a/components/fpspreadsheet/examples/visual/fpsctrls/main.lfm b/components/fpspreadsheet/examples/visual/fpsctrls/main.lfm index 8807a563b..0ba959614 100644 --- a/components/fpspreadsheet/examples/visual/fpsctrls/main.lfm +++ b/components/fpspreadsheet/examples/visual/fpsctrls/main.lfm @@ -29,7 +29,7 @@ object MainForm: TMainForm Width = 707 FrozenCols = 0 FrozenRows = 0 - ReadFormulas = False + ReadFormulas = True SelectionPen.JoinStyle = pjsMiter SelectionPen.Width = 3 TextOverflow = True diff --git a/components/fpspreadsheet/examples/visual/fpsgrid/mainform.lfm b/components/fpspreadsheet/examples/visual/fpsgrid/mainform.lfm index 6f943f3d8..20f24c11a 100644 --- a/components/fpspreadsheet/examples/visual/fpsgrid/mainform.lfm +++ b/components/fpspreadsheet/examples/visual/fpsgrid/mainform.lfm @@ -10,29 +10,29 @@ object Form1: TForm1 ShowHint = True LCLVersion = '1.7' object Panel1: TPanel - Left = 0 - Height = 41 - Top = 608 - Width = 894 - Align = alBottom + Left = 776 + Height = 649 + Top = 0 + Width = 118 + Align = alRight BevelOuter = bvNone - ClientHeight = 41 - ClientWidth = 894 + ClientHeight = 649 + ClientWidth = 118 TabOrder = 0 object BtnOpen: TButton - Left = 96 + Left = 8 Height = 25 - Top = 8 - Width = 75 + Top = 31 + Width = 99 Caption = 'Open...' OnClick = BtnOpenClick TabOrder = 0 end object BtnSave: TButton - Left = 183 + Left = 8 Height = 25 - Top = 8 - Width = 75 + Top = 58 + Width = 99 Caption = 'Save...' OnClick = BtnSaveClick TabOrder = 1 @@ -40,69 +40,99 @@ object Form1: TForm1 object BtnNew: TButton Left = 8 Height = 25 - Top = 8 - Width = 75 + Top = 4 + Width = 99 Caption = 'New...' OnClick = BtnNewClick TabOrder = 2 end - end - object WorksheetGrid: TsWorksheetGrid - Left = 0 - Height = 576 - Top = 32 - Width = 894 - AutoCalc = True - FrozenCols = 0 - FrozenRows = 0 - ReadFormulas = False - SelectionPen.JoinStyle = pjsMiter - SelectionPen.Width = 3 - WorkbookSource = WorksheetGrid.internal - Align = alClient - AutoAdvance = aaDown - ColCount = 10 - DefaultColWidth = 64 - DefaultRowHeight = 22 - MouseWheelOption = mwGrid - Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goRowSizing, goColSizing, goEditing, goThumbTracking, goDblClickAutoSize, goSmoothScroll, goHeaderHotTracking, goHeaderPushedLook, goFixedColSizing, goCellHints] - RowCount = 10 - TabOrder = 1 - TitleStyle = tsNative - end - object Panel2: TPanel - Left = 0 - Height = 32 - Top = 0 - Width = 894 - Align = alTop - BevelOuter = bvNone - ClientHeight = 32 - ClientWidth = 894 - TabOrder = 2 - object Label1: TLabel + object CbReadFormulas: TCheckBox Left = 8 - Height = 15 - Top = 8 - Width = 37 - Caption = 'Sheets:' - ParentColor = False + Height = 19 + Top = 96 + Width = 96 + Caption = 'Read formulas' + OnChange = CbReadFormulasChange + TabOrder = 3 end - object SheetsCombo: TComboBox - Left = 72 - Height = 23 - Top = 4 - Width = 818 - Anchors = [akTop, akLeft, akRight] - ItemHeight = 15 - ItemIndex = 0 - Items.Strings = ( - 'Sheet 1' - ) - OnSelect = SheetsComboSelect - Style = csDropDownList + object CbAutoCalc: TCheckBox + Left = 8 + Height = 19 + Top = 120 + Width = 70 + Caption = 'Auto calc' + OnChange = CbAutoCalcChange + TabOrder = 4 + end + end + object Panel3: TPanel + Left = 0 + Height = 649 + Top = 0 + Width = 776 + Align = alClient + BevelOuter = bvNone + Caption = 'Panel3' + ClientHeight = 649 + ClientWidth = 776 + TabOrder = 1 + object Panel2: TPanel + Left = 0 + Height = 32 + Top = 0 + Width = 776 + Align = alTop + BevelOuter = bvNone + ClientHeight = 32 + ClientWidth = 776 TabOrder = 0 - Text = 'Sheet 1' + object Label1: TLabel + Left = 8 + Height = 15 + Top = 8 + Width = 37 + Caption = 'Sheets:' + ParentColor = False + end + object SheetsCombo: TComboBox + Left = 72 + Height = 23 + Top = 4 + Width = 700 + Anchors = [akTop, akLeft, akRight] + ItemHeight = 15 + ItemIndex = 0 + Items.Strings = ( + 'Sheet 1' + ) + OnSelect = SheetsComboSelect + Style = csDropDownList + TabOrder = 0 + Text = 'Sheet 1' + end + end + object WorksheetGrid: TsWorksheetGrid + Left = 0 + Height = 617 + Top = 32 + Width = 776 + AutoCalc = True + FrozenCols = 0 + FrozenRows = 0 + ReadFormulas = True + SelectionPen.JoinStyle = pjsMiter + SelectionPen.Width = 3 + WorkbookSource = WorksheetGrid.internal + Align = alClient + AutoAdvance = aaDown + ColCount = 10 + DefaultColWidth = 64 + DefaultRowHeight = 22 + MouseWheelOption = mwGrid + Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goRowSizing, goColSizing, goEditing, goThumbTracking, goDblClickAutoSize, goSmoothScroll, goHeaderHotTracking, goHeaderPushedLook, goFixedColSizing, goCellHints] + RowCount = 10 + TabOrder = 1 + TitleStyle = tsNative end end object OpenDialog: TOpenDialog diff --git a/components/fpspreadsheet/examples/visual/fpsgrid/mainform.pas b/components/fpspreadsheet/examples/visual/fpsgrid/mainform.pas index dee311734..e9e961da7 100644 --- a/components/fpspreadsheet/examples/visual/fpsgrid/mainform.pas +++ b/components/fpspreadsheet/examples/visual/fpsgrid/mainform.pas @@ -17,6 +17,9 @@ type BtnOpen: TButton; BtnSave: TButton; BtnNew: TButton; + CbReadFormulas: TCheckBox; + CbAutoCalc: TCheckBox; + Panel3: TPanel; SheetsCombo: TComboBox; Label1: TLabel; OpenDialog: TOpenDialog; @@ -27,6 +30,8 @@ type procedure BtnNewClick(Sender: TObject); procedure BtnOpenClick(Sender: TObject); procedure BtnSaveClick(Sender: TObject); + procedure CbAutoCalcChange(Sender: TObject); + procedure CbReadFormulasChange(Sender: TObject); procedure FormCreate(Sender: TObject); procedure SheetsComboSelect(Sender: TObject); private @@ -143,6 +148,16 @@ begin end; end; +procedure TForm1.CbAutoCalcChange(Sender: TObject); +begin + WorksheetGrid.AutoCalc := CbAutoCalc.Checked; +end; + +procedure TForm1.CbReadFormulasChange(Sender: TObject); +begin + WorksheetGrid.ReadFormulas := CbReadFormulas.Checked; +end; + procedure TForm1.FormCreate(Sender: TObject); const THICK_BORDER: TsCellBorderStyle = (LineStyle: lsThick; Color: clNavy); @@ -195,6 +210,9 @@ begin WorksheetGrid.Cells[2,6] := '=B2^2*PI()'; WorksheetGrid.CellComment[2,6] := 'Area of the circle with radius given in cell B2'; WorksheetGrid.NumberFormat[2,6] := '0.000'; + + CbAutoCalc.Checked := WorksheetGrid.AutoCalc; + CbReadFormulas.Checked := WorksheetGrid.ReadFormulas; end; procedure TForm1.SheetsComboSelect(Sender: TObject); diff --git a/components/fpspreadsheet/fpsexprparser.pas b/components/fpspreadsheet/fpsexprparser.pas index 6f739a136..0112c1b82 100644 --- a/components/fpspreadsheet/fpsexprparser.pas +++ b/components/fpspreadsheet/fpsexprparser.pas @@ -3405,7 +3405,6 @@ begin else n := Length(FArgumentNodes); Result := ANext; -// for i:=Length(FArgumentNodes)-1 downto 0 do for i:=0 to High(FArgumentNodes) do Result := FArgumentNodes[i].AsRPNItem(Result); Result := RPNFunc(FID.Name, n, Result); diff --git a/components/fpspreadsheet/fpspreadsheetctrls.pas b/components/fpspreadsheet/fpspreadsheetctrls.pas index c2263cad3..8e57dc182 100644 --- a/components/fpspreadsheet/fpspreadsheetctrls.pas +++ b/components/fpspreadsheet/fpspreadsheetctrls.pas @@ -880,7 +880,6 @@ begin FWorkbook.OnRemovingWorksheet := @WorksheetRemovingHandler; FWorkbook.OnRenameWorksheet := @WorksheetRenamedHandler; FWorkbook.OnSelectWorksheet := @WorksheetSelectedHandler; -// FWorkbook.OnChangePalette := @WorkbookChangedPaletteHandler; // Pass options to workbook SetOptions(FOptions); end; @@ -945,6 +944,7 @@ var begin book := TsWorkbook.Create; try + book.Options := FOptions; if AAutoDetect then book.ReadfromFile(AFileName) else diff --git a/components/fpspreadsheet/fpspreadsheetgrid.pas b/components/fpspreadsheet/fpspreadsheetgrid.pas index f934d34a3..56b12aee4 100644 --- a/components/fpspreadsheet/fpspreadsheetgrid.pas +++ b/components/fpspreadsheet/fpspreadsheetgrid.pas @@ -1462,26 +1462,9 @@ procedure TsCustomWorksheetGrid.CreateNewWorkbook; begin GetWorkbookSource.CreateNewWorkbook; if FReadFormulas then - Workbook.Options := Workbook.Options + [boReadFormulas] else - Workbook.Options := Workbook.Options - [boReadFormulas]; + WorkbookSource.Options := WorkbookSource.Options + [boReadFormulas] else + WorkbookSource.Options := Workbooksource.Options - [boReadFormulas]; SetAutoCalc(FAutoCalc); - { - if FOwnsWorkbook then - FreeAndNil(FOwnedWorkbook); - - if FWorkbookSource <> nil then - FWorkbookSource.CreateNewWorkbook - else - begin - FOwnedWorkbook := TsWorkbook.Create; - FOwnsWorkbook := true; - if FReadFormulas then - FOwnedWorkbook.Options := FOwnedWorkbook.Options + [boReadFormulas] - else - FOwnedWorkbook.Options := FOwnedWorkbook.Options - [boReadFormulas]; - SetAutoCalc(FAutoCalc); - end; - } end; {@@ ---------------------------------------------------------------------------- @@ -5132,23 +5115,20 @@ begin end; procedure TsCustomWorksheetGrid.SetAutoCalc(AValue: Boolean); +var + optns: TsWorkbookOptions; begin FAutoCalc := AValue; - if Assigned(FWorkbookSource) then + if Assigned(WorkbookSource) then begin + optns := WorkbookSource.Options; if FAutoCalc then - FWorkbookSource.Options := FWorkbookSource.Options + [boAutoCalc] - else - FWorkbookSource.Options := FWorkbookSource.Options - [boAutoCalc]; - end; - - if Assigned(Workbook) then - begin - if FAutoCalc then - Workbook.Options := Workbook.Options + [boAutoCalc] - else - Workbook.Options := Workbook.Options - [boAutoCalc]; + Include(optns, boAutoCalc) else + Exclude(optns, boAutoCalc); + WorkbookSource.Options := optns; + if FInternalWorkbookSource <> nil then + FInternalWorkbookSource.Options := optns; end; end; @@ -5643,23 +5623,20 @@ begin end; procedure TsCustomWorksheetGrid.SetReadFormulas(AValue: Boolean); +var + optns: TsWorkbookOptions; begin FReadFormulas := AValue; - - if Assigned(FWorkbookSource) then + if Assigned(WorkbookSource) then begin + optns := WorkbookSource.Options; if FReadFormulas then - FWorkbookSource.Options := FWorkbookSource.Options + [boReadFormulas] + Include(optns, boReadFormulas) else - FWorkbookSource.Options := FWorkbookSource.Options - [boReadFormulas]; - end; - - if Assigned(Workbook) then - begin - if FReadFormulas then - Workbook.Options := Workbook.Options + [boReadFormulas] - else - Workbook.Options := Workbook.Options - [boReadFormulas]; + Exclude(optns, boReadFormulas); + WorkbookSource.Options := optns; + if FInternalWorkbookSource <> nil then + FInternalWorkbookSource.Options := optns; end; end; diff --git a/components/fpspreadsheet/fpsstrings.pas b/components/fpspreadsheet/fpsstrings.pas index 73c38a0a8..e10f1d48a 100644 --- a/components/fpspreadsheet/fpsstrings.pas +++ b/components/fpspreadsheet/fpsstrings.pas @@ -80,6 +80,7 @@ resourcestring rsIndexInSSTOutOfRange = 'Index %d in SST out of range (0-%d).'; rsAmbiguousDecThouSeparator = 'Assuming usage of decimal separator in "%s".'; rsCodePageNotSupported = 'Code page "%s" is not supported. Using "cp1252" (Latin 1) instead.'; + rsFormulaNotSupported = 'The formula in cell %s is not supported by this file format: %s'; rsNoValidHyperlinkInternal = 'The hyperlink "%s" is not a valid cell address.'; rsNoValidHyperlinkURI = 'The hyperlink "%s" is not a valid URI.'; diff --git a/components/fpspreadsheet/reference/BIFFExplorer/BIFFExplorer.lpi b/components/fpspreadsheet/reference/BIFFExplorer/BIFFExplorer.lpi index ba6d4eadd..858ebe714 100644 --- a/components/fpspreadsheet/reference/BIFFExplorer/BIFFExplorer.lpi +++ b/components/fpspreadsheet/reference/BIFFExplorer/BIFFExplorer.lpi @@ -20,15 +20,9 @@ - - - - - - @@ -57,9 +51,6 @@ - - - @@ -134,6 +125,7 @@ + diff --git a/components/fpspreadsheet/xlsbiff2.pas b/components/fpspreadsheet/xlsbiff2.pas index b8cacd12a..09197e181 100755 --- a/components/fpspreadsheet/xlsbiff2.pas +++ b/components/fpspreadsheet/xlsbiff2.pas @@ -98,6 +98,8 @@ type procedure WriteIXFE(AStream: TStream; XFIndex: Word); protected procedure AddBuiltinNumFormats; override; + function FunctionSupported(AExcelCode: Integer; + const AFuncName: String): Boolean; override; // procedure ListAllNumFormats; override; procedure WriteBlank(AStream: TStream; const ARow, ACol: Cardinal; ACell: PCell); override; @@ -1013,6 +1015,13 @@ begin InternalAddBuiltInNumFormats(FNumFormatList, Workbook.FormatSettings); end; +function TsSpreadBIFF2Writer.FunctionSupported(AExcelCode: Integer; + const AFuncName: String): Boolean; +begin + Result := inherited and (AExcelCode < 200); +end; + + {@@ ---------------------------------------------------------------------------- Determines the cell attributes needed for writing a cell content record, such as WriteLabel, WriteNumber, etc. @@ -1620,10 +1629,20 @@ var RPNLength: Word; RecordSizePos, FinalPos: Cardinal; xf: Word; + isSupported: Boolean; + unsupportedFormulas: String; begin if (ARow >= FLimitations.MaxRowCount) or (ACol >= FLimitations.MaxColCount) then exit; + { Check if formula is supported by this file format. If not, write only + the result } + isSupported := FormulaSupported(AFormula, unsupportedFormulas); + if not IsSupported then + Workbook.AddErrorMsg(rsFormulaNotSupported, [ + GetCellString(ARow, ACol), unsupportedformulas + ]); + RPNLength := 0; xf := FindXFIndex(ACell); @@ -1650,11 +1669,7 @@ begin AStream.WriteByte(1); { Formula data (RPN token array) } - { - if ACell^.SharedFormulaBase <> nil then - WriteRPNSharedFormulaLink(AStream, ACell, RPNLength) - else} - WriteRPNTokenArray(AStream, ACell, AFormula, false, RPNLength); + WriteRPNTokenArray(AStream, ACell, AFormula, false, IsSupported, RPNLength); { Finally write sizes after we know them } FinalPos := AStream.Position; diff --git a/components/fpspreadsheet/xlsbiff5.pas b/components/fpspreadsheet/xlsbiff5.pas index 54df98217..bb869358e 100755 --- a/components/fpspreadsheet/xlsbiff5.pas +++ b/components/fpspreadsheet/xlsbiff5.pas @@ -96,6 +96,7 @@ type TsSpreadBIFF5Writer = class(TsSpreadBIFFWriter) protected + function FunctionSupported(AExcelCode: Integer; const AFuncName: String): Boolean; override; procedure InternalWriteToStream(AStream: TStream); { Record writing methods } procedure WriteBOF(AStream: TStream; ADataType: Word); @@ -214,7 +215,7 @@ implementation uses Math, - fpsStrings, fpsRegFileFormats, fpsStreams, fpsPalette, fpsNumFormat; + fpsStrings, fpsRegFileFormats, fpsStreams, fpsPalette, fpsNumFormat, xlsconst; const { Excel record IDs } @@ -983,6 +984,12 @@ begin FCodePage := Excel5Settings.CodePage; end; +function TsSpreadBIFF5Writer.FunctionSupported(AExcelCode: Integer; + const AFuncName: String): Boolean; +begin + Result := inherited and (AExcelCode <> INT_EXCEL_SHEET_FUNC_HYPERLINK); +end; + {@@ ---------------------------------------------------------------------------- Writes an Excel BIFF5 record structure diff --git a/components/fpspreadsheet/xlscommon.pas b/components/fpspreadsheet/xlscommon.pas index c2afac25f..4e0989cc5 100644 --- a/components/fpspreadsheet/xlscommon.pas +++ b/components/fpspreadsheet/xlscommon.pas @@ -468,6 +468,8 @@ type procedure AddBuiltinNumFormats; override; function FindXFIndex(ACell: PCell): Integer; virtual; function FixLineEnding(const AText: String): String; + function FormulaSupported(ARPNFormula: TsRPNFormula; out AUnsupported: String): Boolean; + function FunctionSupported(AExcelCode: Integer; const AFuncName: String): Boolean; virtual; function GetLastRowIndex(AWorksheet: TsWorksheet): Integer; function GetLastColIndex(AWorksheet: TsWorksheet): Word; function GetPrintOptions: Word; virtual; @@ -544,7 +546,7 @@ type var RPNLength: Word); virtual; } procedure WriteRPNTokenArray(AStream: TStream; ACell: PCell; - const AFormula: TsRPNFormula; UseRelAddr: Boolean; var RPNLength: Word); + const AFormula: TsRPNFormula; UseRelAddr, IsSupported: Boolean; var RPNLength: Word); procedure WriteRPNTokenArraySize(AStream: TStream; ASize: Word); virtual; // Writes out a SELECTION record @@ -2517,6 +2519,37 @@ begin Result[i] := #10; end; +{@@ ---------------------------------------------------------------------------- + Checks if the specified formula is supported by this file format. +-------------------------------------------------------------------------------} +function TsSpreadBIFFWriter.FormulaSupported(ARPNFormula: TsRPNFormula; + out AUnsupported: String): Boolean; +var + exprDef: TsExprIdentifierDef; + i: Integer; +begin + Result := true; + AUnsupported := ''; + for i:=0 to Length(ARPNFormula)-1 do begin + if ARPNFormula[i].ElementKind = fekFunc then begin + exprDef := BuiltinIdentifiers.IdentifierByName(ARPNFormula[i].FuncName); + if not FunctionSupported(exprDef.ExcelCode, exprDef.Name) then + begin + Result := false; + AUnsupported := AUnsupported + ', ' + exprDef.Name + '()'; + end; + end; + end; + if AUnsupported <> '' then Delete(AUnsupported, 1, 2); +end; + +function TsSpreadBIFFWriter.FunctionSupported(AExcelCode: Integer; + const AFuncName: String): Boolean; +begin + Unused(AFuncName); + Result := AExcelCode <> INT_EXCEL_SHEET_FUNC_NOT_BIFF; +end; + function TsSpreadBIFFWriter.GetLastRowIndex(AWorksheet: TsWorksheet): Integer; begin Result := AWorksheet.GetLastRowIndex; @@ -3335,16 +3368,22 @@ procedure TsSpreadBIFFWriter.WriteRPNFormula(AStream: TStream; var RPNLength: Word = 0; RecordSizePos, StartPos, FinalPos: Int64; + isSupported: Boolean; + unsupportedFormulas: String; begin if (ARow >= FLimitations.MaxRowCount) or (ACol >= FLimitations.MaxColCount) then exit; if Length(AFormula) = 0 then exit; - { - if not ((Length(AFormula) > 0) or (ACell^.SharedFormulaBase <> nil)) then - exit; - } + + { Check if formula is supported by this file format. If not, write only + the result } + isSupported := FormulaSupported(AFormula, unsupportedFormulas); + if not IsSupported then + Workbook.AddErrorMsg(rsFormulaNotSupported, [ + GetCellString(ARow, ACol), unsupportedformulas + ]); { BIFF Record header } AStream.WriteWord(WordToLE(INT_EXCEL_ID_FORMULA)); @@ -3363,34 +3402,21 @@ begin WriteRPNResult(AStream, ACell); { Options flags } - AStream.WriteWord(WordToLE(MASK_FORMULA_RECALCULATE_ALWAYS)); + if IsSupported then + AStream.WriteWord(WordToLE(MASK_FORMULA_RECALCULATE_ALWAYS)) else + AStream.WriteWord(0); { Not used } AStream.WriteDWord(0); { Formula data (RPN token array) } - { - if ACell^.SharedFormulaBase <> nil then - WriteRPNSharedFormulaLink(AStream, ACell, RPNLength) - else - } - WriteRPNTokenArray(AStream, ACell, AFormula, false, RPNLength); + WriteRPNTokenArray(AStream, ACell, AFormula, false, IsSupported, RPNLength); { Write sizes in the end, after we known them } FinalPos := AStream.Position; AStream.Position := RecordSizePos; AStream.WriteWord(WordToLE(FinalPos - StartPos)); AStream.Position := FinalPos; - (* - { If the cell is the first cell of a range with a shared formula write the - shared formula RECORD here. The shared formula RECORD must follow the - first FORMULA record referring to the shared formula} - if (ACell^.SharedFormulaBase <> nil) and - (ARow = ACell^.SharedFormulaBase^.Row) and - (ACol = ACell^.SharedFormulaBase^.Col) - then - WriteSharedFormula(AStream, ACell^.SharedFormulaBase); - *) { Write following STRING record if formula result is a non-empty string. } if (ACell^.ContentType = cctUTF8String) and (ACell^.UTF8StringValue <> '') then @@ -3486,14 +3512,14 @@ end; Writes the token array of the given RPN formula and returns its size -------------------------------------------------------------------------------} procedure TsSpreadBIFFWriter.WriteRPNTokenArray(AStream: TStream; - ACell: PCell; const AFormula: TsRPNFormula; UseRelAddr: boolean; + ACell: PCell; const AFormula: TsRPNFormula; UseRelAddr, IsSupported: boolean; var RPNLength: Word); var i: Integer; n: Word; dr, dc: Integer; TokenArraySizePos: Int64; - FinalPos: Int64; + finalPos: Int64; exprDef: TsExprIdentifierDef; primaryExcelCode, secondaryExcelCode: Word; begin @@ -3504,6 +3530,9 @@ begin TokenArraySizePos := AStream.Position; WriteRPNTokenArraySize(AStream, 0); + if not IsSupported then + exit; + { Formula data (RPN token array) } for i := 0 to Length(AFormula) - 1 do begin