From 3fa5fd28cac1213a1cd34901315b7a61f38a705c Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Tue, 19 Aug 2014 11:46:32 +0000 Subject: [PATCH] fpspreadsheet: Complete calculation of shared rpn formulas. git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3497 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- components/fpspreadsheet/fpspreadsheet.pas | 43 ++++++++++++++++--- components/fpspreadsheet/tests/errortests.pas | 6 +-- components/fpspreadsheet/xlsbiff8.pas | 4 +- 3 files changed, 41 insertions(+), 12 deletions(-) diff --git a/components/fpspreadsheet/fpspreadsheet.pas b/components/fpspreadsheet/fpspreadsheet.pas index 3ec0be55e..6292eaa22 100755 --- a/components/fpspreadsheet/fpspreadsheet.pas +++ b/components/fpspreadsheet/fpspreadsheet.pas @@ -1737,8 +1737,19 @@ begin exit; // Cell contains an RPN formula --> calculate the formula - if Length(cell^.RPNFormulaValue) > 0 then + if (Length(cell^.RPNFormulaValue) > 0) or + ((cell^.SharedFormulaBase <> nil) and (Length(cell^.SharedFormulaBase^.RPNFormulaValue) > 0)) + then CalcRPNFormula(cell); + + // Here should be other case of string formula: + { + else + if (Length(cell^.FormulaValue.FormulaStr) > 0) or + ((cell^.SharedFormulaBase <> nil) and (Length(cell^.SharedFormulaBase^.FomrulaValue.FormulaStr) > 0)) + then + CalcStringFormula(cell); + } end; {@@ @@ -1805,11 +1816,15 @@ var r,c: Cardinal; formula: TsRPNFormula; begin - if (Length(ACell^.RPNFormulaValue) = 0) or - (ACell^.ContentType = cctError) - then + if (ACell^.ContentType = cctError) then exit; + if (ACell^.SharedFormulaBase = nil) and (Length(ACell^.RPNFormulaValue) = 0) then + exit; + + if (ACell^.SharedFormulaBase <> nil) and (Length(ACell^.SharedFormulaBase^.RPNFormulaValue) = 0) + then exit; + ACell^.CalcState := csCalculating; args := TsArgumentStack.Create; @@ -1848,13 +1863,27 @@ begin end; fekCellOffset: begin - cell := FindCell(aCell^.Row + SmallInt(fe.Row), ACell^.Col + SmallInt(fe.Col)); - if cell <> nil then + if ACell^.SharedFormulaBase = nil then begin + WriteErrorValue(ACell, errIllegalRef); + exit; + end; + if (rfRelRow in fe.RelFlags) + then r := ACell^.Row + SmallInt(fe.Row) + else r := ACell^.SharedFormulaBase^.Row; + if (rfRelCol in fe.RelFlags) + then c := ACell^.Col + SmallInt(fe.Col) + else c := ACell^.SharedFormulaBase^.Col; + cell := FindCell(r, c); + if cell <> nil then begin case cell^.CalcState of csNotCalculated: CalcRPNFormula(cell); csCalculating : raise Exception.Create(lpCircularReference); end; - args.PushCell(cell, self); + args.PushCell(cell, self); + end else begin + WriteErrorValue(ACell, errIllegalRef); + exit; + end; end; fekNum: args.PushNumber(fe.DoubleValue, self); diff --git a/components/fpspreadsheet/tests/errortests.pas b/components/fpspreadsheet/tests/errortests.pas index cae068bd9..d6cc4d630 100644 --- a/components/fpspreadsheet/tests/errortests.pas +++ b/components/fpspreadsheet/tests/errortests.pas @@ -8,9 +8,9 @@ interface uses // Not using lazarus package as the user may be working with multiple versions - // Instead, add .. to unit search path - Classes, SysUtils, fpcunit, testutils, testregistry, - fpsallformats, fpspreadsheet {and a project requirement for lclbase for utf8 handling}, + // Instead, add ".." to unit search path + Classes, SysUtils, fpcunit, testregistry, + fpspreadsheet {and a project requirement for lclbase for utf8 handling}, fpsutils, testsutility; type diff --git a/components/fpspreadsheet/xlsbiff8.pas b/components/fpspreadsheet/xlsbiff8.pas index 37f640c62..81d8b1755 100755 --- a/components/fpspreadsheet/xlsbiff8.pas +++ b/components/fpspreadsheet/xlsbiff8.pas @@ -1656,12 +1656,12 @@ var c: Word; begin // 2 bytes for row offset - dr := WordLEToN(AStream.ReadWord); + dr := ShortInt(WordLEToN(AStream.ReadWord)); ARowOffset := dr; // 2 bytes for column offset c := WordLEToN(AStream.ReadWord); - dc := Lo(c); + dc := ShortInt(Lo(c)); AColOffset := dc; // Extract info on absolute/relative addresses.