You've already forked lazarus-ccr
fpspreadsheet: Fix reading/writing of cell error values in biff. Insert/delete unit tests with formulas are correct now. Fix crash in BIFFExplorer related to reading of formulas.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3582 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -2718,7 +2718,7 @@ begin
|
||||
rtDateTime : Result := RPNNumber(FValue.ResDateTime, ANext);
|
||||
rtBoolean : Result := RPNBool(FValue.ResBoolean, ANext);
|
||||
rtFloat : Result := RPNNumber(FValue.ResFloat, ANext);
|
||||
rtError : Result := RPNErr(ord(FValue.ResError), ANext);
|
||||
rtError : Result := RPNErr(FValue.ResError, ANext);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -1251,179 +1251,6 @@ var
|
||||
'wheat' // $16
|
||||
);
|
||||
|
||||
(*
|
||||
{ Properties of formula elements }
|
||||
|
||||
type
|
||||
{@@ Properties of formula elements:
|
||||
@param Symbol Symbol used in the formula
|
||||
@param MinParams Minimum count of parameters used in this function
|
||||
@param MaxParams Maximum count of parameters used in this function
|
||||
@param Func Function to be calculated }
|
||||
TFEProp = record
|
||||
Symbol: String;
|
||||
MinParams, MaxParams: Byte;
|
||||
Func: TsFormulaFunc;
|
||||
end;
|
||||
|
||||
var
|
||||
FEProps: array[TFEKind] of TFEProp = ( // functions marked by ( * )
|
||||
{ Operands } // are only partially supported
|
||||
(Symbol:''; MinParams:Byte(-1); MaxParams:Byte(-1); Func:nil), // fekCell
|
||||
(Symbol:''; MinParams:Byte(-1); MaxParams:Byte(-1); Func:nil), // fekCellRef
|
||||
(Symbol:''; MinParams:Byte(-1); MaxParams:Byte(-1); Func:nil), // fekCellRange
|
||||
(Symbol:''; MinParams:Byte(-1); MaxParams:Byte(-1); Func:nil), // fekCellOffset
|
||||
(Symbol:''; MinParams:Byte(-1); MaxParams:Byte(-1); Func:nil), // fekCellNum
|
||||
(Symbol:''; MinParams:Byte(-1); MaxParams:Byte(-1); Func:nil), // fekCellInteger
|
||||
(Symbol:''; MinParams:Byte(-1); MaxParams:Byte(-1); Func:nil), // fekCellString
|
||||
(Symbol:''; MinParams:Byte(-1); MaxParams:Byte(-1); Func:nil), // fekCellBool
|
||||
(Symbol:''; MinParams:Byte(-1); MaxParams:Byte(-1); Func:nil), // fekCellErr
|
||||
(Symbol:''; MinParams:Byte(-1); MaxParams:Byte(-1); Func:nil), // fekCellMissingArg
|
||||
{ Basic operations }
|
||||
(Symbol:'+'; MinParams:2; MaxParams:2; Func:fpsAdd), // fekAdd
|
||||
(Symbol:'-'; MinParams:2; MaxParams:2; Func:fpsSub), // fekSub
|
||||
(Symbol:'*'; MinParams:2; MaxParams:2; Func:fpsMul), // fekMul
|
||||
(Symbol:'/'; MinParams:2; MaxParams:2; Func:fpsDiv), // fekDiv
|
||||
(Symbol:'%'; MinParams:1; MaxParams:1; Func:fpsPercent), // fekPercent
|
||||
(Symbol:'^'; MinParams:2; MaxParams:2; Func:fpsPower), // fekPower
|
||||
(Symbol:'-'; MinParams:1; MaxParams:1; Func:fpsUMinus), // fekUMinus
|
||||
(Symbol:'+'; MinParams:1; MaxParams:1; Func:fpsUPlus), // fekUPlus
|
||||
(Symbol:'&'; MinParams:2; MaxParams:2; Func:fpsConcat), // fekConcat (string concatenation)
|
||||
(Symbol:'='; MinParams:2; MaxParams:2; Func:fpsEqual), // fekEqual
|
||||
(Symbol:'>'; MinParams:2; MaxParams:2; Func:fpsGreater), // fekGreater
|
||||
(Symbol:'>='; MinParams:2; MaxParams:2; Func:fpsGreaterEqual), // fekGreaterEqual
|
||||
(Symbol:'<'; MinParams:2; MaxParams:2; Func:fpsLess), // fekLess
|
||||
(Symbol:'<='; MinParams:2; MaxParams:2; Func:fpsLessEqual), // fekLessEqual
|
||||
(Symbol:'<>'; MinParams:2; MaxParams:2; Func:fpsNotEqual), // fekNotEqual
|
||||
(Symbol:''; MinParams:1; MaxParams:1; Func:nil), // fekParen -- no need to calculate!
|
||||
{ math }
|
||||
(Symbol:'ABS'; MinParams:1; MaxParams:1; Func:fpsABS), // fekABS
|
||||
(Symbol:'ACOS'; MinParams:1; MaxParams:1; Func:fpsACOS), // fekACOS
|
||||
(Symbol:'ACOSH'; MinParams:1; MaxParams:1; Func:fpsACOSH), // fekACOSH
|
||||
(Symbol:'ASIN'; MinParams:1; MaxParams:1; Func:fpsASIN), // fekASIN
|
||||
(Symbol:'ASINH'; MinParams:1; MaxParams:1; Func:fpsASINH), // fekASINH
|
||||
(Symbol:'ATAN'; MinParams:1; MaxParams:1; Func:fpsATAN), // fekATAN
|
||||
(Symbol:'ATANH'; MinParams:1; MaxParams:1; Func:fpsATANH), // fekATANH,
|
||||
(Symbol:'COS'; MinParams:1; MaxParams:1; Func:fpsCOS), // fekCOS
|
||||
(Symbol:'COSH'; MinParams:1; MaxParams:1; Func:fpsCOSH), // fekCOSH
|
||||
(Symbol:'DEGREES'; MinParams:1; MaxParams:1; Func:fpsDEGREES), // fekDEGREES
|
||||
(Symbol:'EXP'; MinParams:1; MaxParams:1; Func:fpsEXP), // fekEXP
|
||||
(Symbol:'INT'; MinParams:1; MaxParams:1; Func:fpsINT), // fekINT
|
||||
(Symbol:'LN'; MinParams:1; MaxParams:1; Func:fpsLN), // fekLN
|
||||
(Symbol:'LOG'; MinParams:1; MaxParams:2; Func:fpsLOG), // fekLOG,
|
||||
(Symbol:'LOG10'; MinParams:1; MaxParams:1; Func:fpsLOG10), // fekLOG10
|
||||
(Symbol:'PI'; MinParams:0; MaxParams:0; Func:fpsPI), // fekPI
|
||||
(Symbol:'RADIANS'; MinParams:1; MaxParams:1; Func:fpsRADIANS), // fekRADIANS
|
||||
(Symbol:'RAND'; MinParams:0; MaxParams:0; Func:fpsRAND), // fekRAND
|
||||
(Symbol:'ROUND'; MinParams:2; MaxParams:2; Func:fpsROUND), // fekROUND,
|
||||
(Symbol:'SIGN'; MinParams:1; MaxParams:1; Func:fpsSIGN), // fekSIGN
|
||||
(Symbol:'SIN'; MinParams:1; MaxParams:1; Func:fpsSIN), // fekSIN
|
||||
(Symbol:'SINH'; MinParams:1; MaxParams:1; Func:fpsSINH), // fekSINH
|
||||
(Symbol:'SQRT'; MinParams:1; MaxParams:1; Func:fpsSQRT), // fekSQRT,
|
||||
(Symbol:'TAN'; MinParams:1; MaxParams:1; Func:fpsTAN), // fekTAN
|
||||
(Symbol:'TANH'; MinParams:1; MaxParams:1; Func:fpsTANH), // fekTANH,
|
||||
{ date/time }
|
||||
(Symbol:'DATE'; MinParams:3; MaxParams:3; Func:fpsDATE), // fekDATE
|
||||
(Symbol:'DATEDIF'; MinParams:3; MaxParams:3; Func:fpsDATEDIF), // fekDATEDIF ( * )
|
||||
(Symbol:'DATEVALUE'; MinParams:1; MaxParams:1; Func:fpsDATEVALUE), // fekDATEVALUE
|
||||
(Symbol:'DAY'; MinParams:1; MaxParams:1; Func:fpsDAY), // fekDAY
|
||||
(Symbol:'HOUR'; MinParams:1; MaxParams:1; Func:fpsHOUR), // fekHOUR
|
||||
(Symbol:'MINUTE'; MinParams:1; MaxParams:1; Func:fpsMINUTE), // fekMINUTE
|
||||
(Symbol:'MONTH'; MinParams:1; MaxParams:1; Func:fpsMONTH), // fekMONTH
|
||||
(Symbol:'NOW'; MinParams:0; MaxParams:0; Func:fpsNOW), // fekNOW
|
||||
(Symbol:'SECOND'; MinParams:1; MaxParams:1; Func:fpsSECOND), // fekSECOND
|
||||
(Symbol:'TIME'; MinParams:3; MaxParams:3; Func:fpsTIME), // fekTIME
|
||||
(Symbol:'TIMEVALUE'; MinParams:1; MaxParams:1; Func:fpsTIMEVALUE), // fekTIMEVALUE
|
||||
(Symbol:'TODAY'; MinParams:0; MaxParams:0; Func:fpsTODAY), // fekTODAY
|
||||
(Symbol:'WEEKDAY'; MinParams:1; MaxParams:2; Func:fpsWEEKDAY), // fekWEEKDAY
|
||||
(Symbol:'YEAR'; MinParams:1; MaxParams:1; Func:fpsYEAR), // fekYEAR
|
||||
{ statistical }
|
||||
(Symbol:'AVEDEV'; MinParams:1; MaxParams:30; Func:fpsAVEDEV), // fekAVEDEV
|
||||
(Symbol:'AVERAGE'; MinParams:1; MaxParams:30; Func:fpsAVERAGE), // fekAVERAGE
|
||||
(Symbol:'BETADIST'; MinParams:3; MaxParams:5; Func:nil), // fekBETADIST
|
||||
(Symbol:'BETAINV'; MinParams:3; MaxParams:5; Func:nil), // fekBETAINV
|
||||
(Symbol:'BINOMDIST'; MinParams:4; MaxParams:4; Func:nil), // fekBINOMDIST
|
||||
(Symbol:'CHIDIST'; MinParams:2; MaxParams:2; Func:nil), // fekCHIDIST
|
||||
(Symbol:'CHIINV'; MinParams:2; MaxParams:2; Func:nil), // fekCHIINV
|
||||
(Symbol:'COUNT'; MinParams:0; MaxParams:30; Func:fpsCOUNT), // fekCOUNT
|
||||
(Symbol:'COUNTA'; MinParams:0; MaxParams:30; Func:fpsCOUNTA), // fekCOUNTA
|
||||
(Symbol:'COUNTBLANK';MinParams:1; MaxParams:1; Func:fpsCOUNTBLANK), // fekCOUNTBLANK
|
||||
(Symbol:'COUNTIF'; MinParams:2; MaxParams:2; Func:fpsCOUNTIF), // fekCOUNTIF
|
||||
(Symbol:'MAX'; MinParams:1; MaxParams:30; Func:fpsMAX), // fekMAX
|
||||
(Symbol:'MEDIAN'; MinParams:1; MaxParams:30; Func:nil), // fekMEDIAN
|
||||
(Symbol:'MIN'; MinParams:1; MaxParams:30; Func:fpsMIN), // fekMIN
|
||||
(Symbol:'PERMUT'; MinParams:2; MaxParams:2; Func:nil), // fekPERMUT
|
||||
(Symbol:'POISSON'; MinParams:3; MaxParams:3; Func:nil), // fekPOISSON
|
||||
(Symbol:'PRODUCT'; MinParams:0; MaxParams:30; Func:fpsPRODUCT), // fekPRODUCT
|
||||
(Symbol:'STDEV'; MinParams:1; MaxParams:30; Func:fpsSTDEV), // fekSTDEV
|
||||
(Symbol:'STDEVP'; MinParams:1; MaxParams:30; Func:fpsSTDEVP), // fekSTDEVP
|
||||
(Symbol:'SUM'; MinParams:0; MaxParams:30; Func:fpsSUM), // fekSUM
|
||||
(Symbol:'SUMIF'; MinParams:2; MaxParams:3; Func:fpsSUMIF), // fekSUMIF
|
||||
(Symbol:'SUMSQ'; MinParams:0; MaxParams:30; Func:fpsSUMSQ), // fekSUMSQ
|
||||
(Symbol:'VAR'; MinParams:1; MaxParams:30; Func:fpsVAR), // fekVAR
|
||||
(Symbol:'VARP'; MinParams:1; MaxParams:30; Func:fpsVARP), // fekVARP
|
||||
{ financial }
|
||||
(Symbol:'FV'; MinParams:3; MaxParams:5; Func:nil), // fekFV
|
||||
(Symbol:'NPER'; MinParams:3; MaxParams:5; Func:nil), // fekNPER
|
||||
(Symbol:'PMT'; MinParams:3; MaxParams:5; Func:nil), // fekPMT
|
||||
(Symbol:'PV'; MinParams:3; MaxParams:5; Func:nil), // fekPV
|
||||
(Symbol:'RATE'; MinParams:3; MaxParams:6; Func:nil), // fekRATE
|
||||
{ logical }
|
||||
(Symbol:'AND'; MinParams:0; MaxParams:30; Func:fpsAND), // fekAND
|
||||
(Symbol:'FALSE'; MinParams:0; MaxParams:0; Func:fpsFALSE), // fekFALSE
|
||||
(Symbol:'IF'; MinParams:2; MaxParams:3; Func:fpsIF), // fekIF
|
||||
(Symbol:'NOT'; MinParams:1; MaxParams:1; Func:fpsNOT), // fekNOT
|
||||
(Symbol:'OR'; MinParams:1; MaxParams:30; Func:fpsOR), // fekOR
|
||||
(Symbol:'TRUE'; MinParams:0; MaxParams:0; Func:fpsTRUE), // fekTRUE
|
||||
{ string }
|
||||
(Symbol:'CHAR'; MinParams:1; MaxParams:1; Func:fpsCHAR), // fekCHAR
|
||||
(Symbol:'CODE'; MinParams:1; MaxParams:1; Func:fpsCODE), // fekCODE
|
||||
(Symbol:'LEFT'; MinParams:1; MaxParams:2; Func:fpsLEFT), // fekLEFT
|
||||
(Symbol:'LOWER'; MinParams:1; MaxParams:1; Func:fpsLOWER), // fekLOWER
|
||||
(Symbol:'MID'; MinParams:3; MaxParams:3; Func:fpsMID), // fekMID
|
||||
(Symbol:'PROPER'; MinParams:1; MaxParams:1; Func:nil), // fekPROPER
|
||||
(Symbol:'REPLACE'; MinParams:4; MaxParams:4; Func:fpsREPLACE), // fekREPLACE
|
||||
(Symbol:'RIGHT'; MinParams:1; MaxParams:2; Func:fpsRIGHT), // fekRIGHT
|
||||
(Symbol:'SUBSTITUTE';MinParams:3; MaxParams:4; Func:fpsSUBSTITUTE), // fekSUBSTITUTE ( * )
|
||||
(Symbol:'TRIM'; MinParams:1; MaxParams:1; Func:fpsTRIM), // fekTRIM
|
||||
(Symbol:'UPPER'; MinParams:1; MaxParams:1; Func:fpsUPPER), // fekUPPER
|
||||
{ lookup/reference }
|
||||
(Symbol:'COLUMN'; MinParams:0; MaxParams:1; Func:fpsCOLUMN), // fekCOLUMN
|
||||
(Symbol:'COLUMNS'; MinParams:1; MaxParams:1; Func:fpsCOLUMNS), // fekCOLUMNS
|
||||
(Symbol:'ROW'; MinParams:0; MaxParams:1; Func:fpsROW), // fekROW
|
||||
(Symbol:'ROWS'; MinParams:1; MaxParams:1; Func:fpsROWS), // fekROWS
|
||||
{ info }
|
||||
(Symbol:'CELL'; MinParams:1; MaxParams:2; Func:fpsCELLINFO), // fekCELLINFO ( * )
|
||||
(Symbol:'INFO'; MinParams:1; MaxParams:1; Func:fpsINFO), // fekINFO ( * )
|
||||
(Symbol:'ISBLANK'; MinParams:1; MaxParams:1; Func:fpsISBLANK), // fekIsBLANK
|
||||
(Symbol:'ISERR'; MinParams:1; MaxParams:1; Func:fpsISERR), // fekIsERR
|
||||
(Symbol:'ISERROR'; MinParams:1; MaxParams:1; Func:fpsISERROR), // fekIsERROR
|
||||
(Symbol:'ISLOGICAL'; MinParams:1; MaxParams:1; Func:fpsISLOGICAL), // fekIsLOGICAL
|
||||
(Symbol:'ISNA'; MinParams:1; MaxParams:1; Func:fpsISNA), // fekIsNA
|
||||
(Symbol:'ISNONTEXT'; MinParams:1; MaxParams:1; Func:fpsISNONTEXT), // fekIsNONTEXT
|
||||
(Symbol:'ISNUMBER'; MinParams:1; MaxParams:1; Func:fpsISNUMBER), // fekIsNUMBER
|
||||
(Symbol:'ISREF'; MinParams:1; MaxParams:1; Func:fpsISREF), // fekIsRef
|
||||
(Symbol:'ISTEXT'; MinParams:1; MaxParams:1; Func:fpsISTEXT), // fekIsTEXT
|
||||
(Symbol:'VALUE'; MinParams:1; MaxParams:1; Func:fpsVALUE), // fekValue
|
||||
{ Other operations }
|
||||
(Symbol:'SUM'; MinParams:1; MaxParams:1; Func:nil) // fekOpSUM (Unary sum operation). Note: CANNOT be used for summing sell contents; use fekSUM}
|
||||
);
|
||||
|
||||
{@@
|
||||
Registers a function used when calculating a formula.
|
||||
This feature allows to extend the built-in functions directly available in
|
||||
fpspreadsheet.
|
||||
|
||||
@param AFormulaKind Identifier of the formula element
|
||||
@param AFunc Function to be executed when the identifier is met
|
||||
in an rpn formula. The function declaration MUST
|
||||
follow the structure given by TsFormulaFunc.
|
||||
}
|
||||
procedure RegisterFormulaFunc(AFormulaKind: TFEKind; AFunc: Pointer);
|
||||
begin
|
||||
FEProps[AFormulaKind].Func := TsFormulaFunc(AFunc);
|
||||
end;
|
||||
*)
|
||||
|
||||
{@@
|
||||
Registers a new reader/writer pair for a given spreadsheet file format
|
||||
|
@ -38,7 +38,7 @@ function RPNCellRange(ARow, ACol, ARow2, ACol2: Integer; AFlags: TsRelFlags;
|
||||
ANext: PRPNItem): PRPNItem; overload;
|
||||
function RPNCellOffset(ARowOffset, AColOffset: Integer; AFlags: TsRelFlags;
|
||||
ANext: PRPNItem): PRPNItem;
|
||||
function RPNErr(AErrCode: Byte; ANext: PRPNItem): PRPNItem;
|
||||
function RPNErr(AErrCode: TsErrorValue; ANext: PRPNItem): PRPNItem;
|
||||
function RPNInteger(AValue: Word; ANext: PRPNItem): PRPNItem;
|
||||
function RPNMissingArg(ANext: PRPNItem): PRPNItem;
|
||||
function RPNNumber(AValue: Double; ANext: PRPNItem): PRPNItem;
|
||||
@ -245,11 +245,11 @@ end;
|
||||
@param ANext Pointer to the next RPN item in the list
|
||||
@see TsErrorValue
|
||||
}
|
||||
function RPNErr(AErrCode: Byte; ANext: PRPNItem): PRPNItem;
|
||||
function RPNErr(AErrCode: TsErrorValue; ANext: PRPNItem): PRPNItem;
|
||||
begin
|
||||
Result := NewRPNItem;
|
||||
Result^.FE.ElementKind := fekErr;
|
||||
Result^.FE.IntValue := AErrCode;
|
||||
Result^.FE.IntValue := ord(AErrCode);
|
||||
Result^.Next := ANext;
|
||||
end;
|
||||
|
||||
|
@ -31,19 +31,6 @@
|
||||
<OtherUnitFiles Value="mrumenu"/>
|
||||
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
|
||||
</SearchPaths>
|
||||
<Parsing>
|
||||
<SyntaxOptions>
|
||||
<IncludeAssertionCode Value="True"/>
|
||||
</SyntaxOptions>
|
||||
</Parsing>
|
||||
<CodeGeneration>
|
||||
<Checks>
|
||||
<IOChecks Value="True"/>
|
||||
<RangeChecks Value="True"/>
|
||||
<OverflowChecks Value="True"/>
|
||||
<StackChecks Value="True"/>
|
||||
</Checks>
|
||||
</CodeGeneration>
|
||||
<Linking>
|
||||
<Debugging>
|
||||
<DebugInfoType Value="dsDwarf2Set"/>
|
||||
@ -144,6 +131,7 @@
|
||||
<Unit3>
|
||||
<Filename Value="bebiffutils.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="beBIFFUtils"/>
|
||||
</Unit3>
|
||||
<Unit4>
|
||||
<Filename Value="behtml.pas"/>
|
||||
|
@ -2286,7 +2286,7 @@ begin
|
||||
b := FBuffer[FBufferIndex];
|
||||
if FCurrRow = Row then begin
|
||||
FDetails.Add('Error code:'#13);
|
||||
FDetails.Add(Format('Code $%.2x --> "%s"', [b, b]));
|
||||
FDetails.Add(Format('Code $%.2x --> "%s"', [b, GetErrorValueStr(TsErrorValue(b))]));
|
||||
end;
|
||||
ShowInRow(FCurrRow, FBufferIndex, numBytes, Format('$%.2x', [b]), 'Error code');
|
||||
end;
|
||||
|
@ -483,7 +483,7 @@ begin
|
||||
SollFormula := '#REF!';
|
||||
SollLayout := '12345678|'+
|
||||
'23456789|'+
|
||||
'34568890|'+
|
||||
'3456E890|'+ // "E" = error
|
||||
// '45678901|'+
|
||||
'56789012|'+
|
||||
'67890123';
|
||||
@ -585,19 +585,19 @@ begin
|
||||
MyCell := MyWorksheet.FindCell(row, col);
|
||||
if MyCell = nil then
|
||||
actual := actual + ' '
|
||||
else begin
|
||||
else
|
||||
case MyCell^.ContentType of
|
||||
cctEmpty : actual := actual + ' ';
|
||||
cctNumber: actual := actual + IntToStr(Round(Mycell^.NumberValue));
|
||||
cctError : actual := actual + 'E';
|
||||
end;
|
||||
if HasFormula(MyCell) then begin
|
||||
CheckEquals(
|
||||
MyWorksheet.ReadFormulaAsString(MyCell),
|
||||
InsDelTestData[ATestIndex].SollFormula,
|
||||
'Formula mismatch, cell '+CellNotation(MyWorksheet, Row, Col)
|
||||
);
|
||||
end;
|
||||
if HasFormula(MyCell) then
|
||||
begin
|
||||
CheckEquals(
|
||||
MyWorksheet.ReadFormulaAsString(MyCell),
|
||||
InsDelTestData[ATestIndex].SollFormula,
|
||||
'Formula mismatch, cell '+CellNotation(MyWorksheet, Row, Col)
|
||||
);
|
||||
end;
|
||||
end;
|
||||
CheckEquals(actual, expected,
|
||||
|
@ -48,7 +48,6 @@
|
||||
<Unit1>
|
||||
<Filename Value="datetests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="datetests"/>
|
||||
</Unit1>
|
||||
<Unit2>
|
||||
<Filename Value="stringtests.pas"/>
|
||||
@ -57,6 +56,7 @@
|
||||
<Unit3>
|
||||
<Filename Value="numberstests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="numberstests"/>
|
||||
</Unit3>
|
||||
<Unit4>
|
||||
<Filename Value="manualtests.pas"/>
|
||||
@ -66,20 +66,20 @@
|
||||
<Unit5>
|
||||
<Filename Value="testsutility.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="testsutility"/>
|
||||
</Unit5>
|
||||
<Unit6>
|
||||
<Filename Value="internaltests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="internaltests"/>
|
||||
</Unit6>
|
||||
<Unit7>
|
||||
<Filename Value="formattests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="formattests"/>
|
||||
</Unit7>
|
||||
<Unit8>
|
||||
<Filename Value="colortests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="colortests"/>
|
||||
</Unit8>
|
||||
<Unit9>
|
||||
<Filename Value="fonttests.pas"/>
|
||||
@ -110,12 +110,10 @@
|
||||
<Unit15>
|
||||
<Filename Value="errortests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="errortests"/>
|
||||
</Unit15>
|
||||
<Unit16>
|
||||
<Filename Value="virtualmodetests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="virtualmodetests"/>
|
||||
</Unit16>
|
||||
<Unit17>
|
||||
<Filename Value="insertdeletetests.pas"/>
|
||||
|
@ -190,6 +190,11 @@ type
|
||||
function ConvertDateTimeToExcelDateTime
|
||||
(const ADateTime: TDateTime; ADateMode: TDateMode): Double;
|
||||
|
||||
// Converts the error byte read from cells or formulas to fps error value
|
||||
function ConvertFromExcelError(AValue: Byte): TsErrorValue;
|
||||
// Converts an fps error value to the byte code needed in xls files
|
||||
function ConvertToExcelError(AValue: TsErrorValue): byte;
|
||||
|
||||
type
|
||||
{ Contents of the XF record to be stored in the XFList of the reader }
|
||||
TXFListData = class
|
||||
@ -501,6 +506,31 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function ConvertFromExcelError(AValue: Byte): TsErrorValue;
|
||||
begin
|
||||
case AValue of
|
||||
ERR_INTERSECTION_EMPTY : Result := errEmptyIntersection; // #NULL!
|
||||
ERR_DIVIDE_BY_ZERO : Result := errDivideByZero; // #DIV/0!
|
||||
ERR_WRONG_TYPE_OF_OPERAND : Result := errWrongType; // #VALUE!
|
||||
ERR_ILLEGAL_REFERENCE : Result := errIllegalRef; // #REF!
|
||||
ERR_WRONG_NAME : Result := errWrongName; // #NAME?
|
||||
ERR_OVERFLOW : Result := errOverflow; // #NUM!
|
||||
ERR_ARG_ERROR : Result := errArgError; // #N/A!
|
||||
end;
|
||||
end;
|
||||
|
||||
function ConvertToExcelError(AValue: TsErrorValue): byte;
|
||||
begin
|
||||
case AValue of
|
||||
errEmptyIntersection : Result := ERR_INTERSECTION_EMPTY; // #NULL!
|
||||
errDivideByZero : Result := ERR_DIVIDE_BY_ZERO; // #DIV/0!
|
||||
errWrongType : Result := ERR_WRONG_TYPE_OF_OPERAND; // #VALUE!
|
||||
errIllegalRef : Result := ERR_ILLEGAL_REFERENCE; // #REF!
|
||||
errWrongName : Result := ERR_WRONG_NAME; // #NAME?
|
||||
errOverflow : Result := ERR_OVERFLOW; // #NUM!
|
||||
errArgError : Result := ERR_ARG_ERROR; // #N/A;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TsBIFFNumFormatList }
|
||||
|
||||
@ -959,7 +989,8 @@ begin
|
||||
AStream.ReadDWord;
|
||||
|
||||
{ Create cell }
|
||||
if FIsVirtualMode then begin // "Virtual" cell
|
||||
if FIsVirtualMode then // "Virtual" cell
|
||||
begin
|
||||
InitCell(ARow, ACol, FVirtualCell);
|
||||
cell := @FVirtualCell;
|
||||
end else
|
||||
@ -975,21 +1006,14 @@ begin
|
||||
FWorksheet.WriteBoolValue(cell, Data[2] = 1);
|
||||
|
||||
2: begin // Error value
|
||||
case Data[2] of
|
||||
ERR_INTERSECTION_EMPTY : err := errEmptyIntersection;
|
||||
ERR_DIVIDE_BY_ZERO : err := errDivideByZero;
|
||||
ERR_WRONG_TYPE_OF_OPERAND: err := errWrongType;
|
||||
ERR_ILLEGAL_REFERENCE : err := errIllegalRef;
|
||||
ERR_WRONG_NAME : err := errWrongName;
|
||||
ERR_OVERFLOW : err := errOverflow;
|
||||
ERR_ARG_ERROR : err := errArgError;
|
||||
end;
|
||||
err := ConvertFromExcelError(Data[2]);
|
||||
FWorksheet.WriteErrorValue(cell, err);
|
||||
end;
|
||||
|
||||
3: FWorksheet.WriteBlank(cell);
|
||||
end
|
||||
else begin
|
||||
else
|
||||
begin
|
||||
{
|
||||
if SizeOf(Double) <> 8 then
|
||||
raise Exception.Create('Double is not 8 bytes');
|
||||
@ -1007,7 +1031,8 @@ begin
|
||||
end;
|
||||
|
||||
{ Formula token array }
|
||||
if boReadFormulas in FWorkbook.Options then begin
|
||||
if boReadFormulas in FWorkbook.Options then
|
||||
begin
|
||||
ok := ReadRPNTokenArray(AStream, cell);
|
||||
if not ok then
|
||||
FWorksheet.WriteErrorValue(cell, errFormulaNotSupported);
|
||||
@ -1506,7 +1531,7 @@ begin
|
||||
INT_EXCEL_TOKEN_TSTR:
|
||||
rpnItem := RPNString(ReadString_8BitLen(AStream), rpnItem);
|
||||
INT_EXCEL_TOKEN_TERR:
|
||||
rpnItem := RPNErr(AStream.ReadByte, rpnItem);
|
||||
rpnItem := RPNErr(ConvertFromExcelError(AStream.ReadByte), rpnItem);
|
||||
INT_EXCEL_TOKEN_TBOOL:
|
||||
rpnItem := RPNBool(AStream.ReadByte=1, rpnItem);
|
||||
INT_EXCEL_TOKEN_TINT:
|
||||
@ -2361,15 +2386,7 @@ begin
|
||||
cctError:
|
||||
begin
|
||||
Data[0] := 2;
|
||||
case ACell^.ErrorValue of
|
||||
errEmptyIntersection: Data[1] := ERR_INTERSECTION_EMPTY;// #NULL!
|
||||
errDivideByZero : Data[1] := ERR_DIVIDE_BY_ZERO; // #DIV/0!
|
||||
errWrongType : Data[1] := ERR_WRONG_TYPE_OF_OPERAND; // #VALUE!
|
||||
errIllegalRef : Data[1] := ERR_ILLEGAL_REFERENCE; // #REF!
|
||||
errWrongName : Data[1] := ERR_WRONG_NAME; // #NAME?
|
||||
errOverflow : Data[1] := ERR_OVERFLOW; // #NUM!
|
||||
errArgError : Data[1] := ERR_ARG_ERROR; // #N/A;
|
||||
end;
|
||||
Data[1] := ConvertToExcelError(ACell^.ErrorValue);
|
||||
Data[3] := $FFFF;
|
||||
end;
|
||||
end;
|
||||
@ -2410,7 +2427,7 @@ procedure TsSpreadBIFFWriter.WriteRPNTokenArray(AStream: TStream;
|
||||
var RPNLength: Word);
|
||||
var
|
||||
i: Integer;
|
||||
n: Word;
|
||||
w, n: Word;
|
||||
dr, dc: Integer;
|
||||
TokenArraySizePos: Int64;
|
||||
FinalPos: Int64;
|
||||
@ -2500,7 +2517,7 @@ begin
|
||||
|
||||
INT_EXCEL_TOKEN_TINT: { fekNum, but integer }
|
||||
begin
|
||||
AStream.WriteBuffer(AFormula[i].IntValue, 2);
|
||||
AStream.WriteWord(WordToLE(AFormula[i].IntValue));
|
||||
inc(RPNLength, 2);
|
||||
end;
|
||||
|
||||
@ -2517,6 +2534,12 @@ begin
|
||||
inc(RPNLength, 1);
|
||||
end;
|
||||
|
||||
INT_EXCEL_TOKEN_TERR: { fekErr }
|
||||
begin
|
||||
AStream.WriteByte(ConvertToExcelError(TsErrorValue(AFormula[i].IntValue)));
|
||||
inc(RPNLength, 1);
|
||||
end;
|
||||
|
||||
// Functions with fixed parameter count
|
||||
INT_EXCEL_TOKEN_FUNC_R, INT_EXCEL_TOKEN_FUNC_V, INT_EXCEL_TOKEN_FUNC_A:
|
||||
begin
|
||||
|
Reference in New Issue
Block a user