diff --git a/components/fpspreadsheet/xlsbiff8.pas b/components/fpspreadsheet/xlsbiff8.pas index 19280ad59..b164ff43c 100755 --- a/components/fpspreadsheet/xlsbiff8.pas +++ b/components/fpspreadsheet/xlsbiff8.pas @@ -186,6 +186,7 @@ const { Cell Addresses constants } MASK_EXCEL_ROW = $3FFF; + MASK_EXCEL_COL_BITS_BIFF8=$00FF; MASK_EXCEL_RELATIVE_ROW = $4000; MASK_EXCEL_RELATIVE_COL = $8000; @@ -842,6 +843,7 @@ var RPNLength: Word; TokenArraySizePos, RecordSizePos, FinalPos: Int64; TokenID: Byte; + lSecondaryID: Word; begin RPNLength := 0; FormulaResult := 0.0; @@ -880,7 +882,7 @@ begin for i := 0 to Length(AFormula) - 1 do begin { Token identifier } - TokenID := FormulaElementKindToExcelTokenID(AFormula[i].ElementKind); + TokenID := FormulaElementKindToExcelTokenID(AFormula[i].ElementKind, lSecondaryID); AStream.WriteByte(TokenID); Inc(RPNLength); @@ -889,9 +891,9 @@ begin { Operand Tokens } INT_EXCEL_TOKEN_TREFR, INT_EXCEL_TOKEN_TREFV, INT_EXCEL_TOKEN_TREFA: { fekCell } begin - AStream.WriteWord(AFormula[i].Row and MASK_EXCEL_ROW); - AStream.WriteByte(AFormula[i].Col); - Inc(RPNLength, 3); + AStream.WriteWord(AFormula[i].Row); + AStream.WriteWord(AFormula[i].Col and MASK_EXCEL_COL_BITS_BIFF8); + Inc(RPNLength, 4); end; INT_EXCEL_TOKEN_TAREA_R: { fekCellRange } @@ -931,6 +933,13 @@ begin Inc(RPNLength, 3); end; + // Functions + INT_EXCEL_TOKEN_FUNC_R, INT_EXCEL_TOKEN_FUNC_V, INT_EXCEL_TOKEN_FUNC_A: + begin + AStream.WriteWord(lSecondaryID); + Inc(RPNLength, 2); + end; + else end; end; diff --git a/components/fpspreadsheet/xlscommon.pas b/components/fpspreadsheet/xlscommon.pas index 9a8411f64..31fbd0034 100644 --- a/components/fpspreadsheet/xlscommon.pas +++ b/components/fpspreadsheet/xlscommon.pas @@ -44,13 +44,17 @@ const INT_EXCEL_TOKEN_TREFA = $64; { Function Tokens } + INT_EXCEL_TOKEN_FUNC_R = $21; + INT_EXCEL_TOKEN_FUNC_V = $41; + INT_EXCEL_TOKEN_FUNC_A = $61; + INT_EXCEL_TOKEN_FUNCVAR_R = $22; INT_EXCEL_TOKEN_FUNCVAR_V = $42; INT_EXCEL_TOKEN_FUNCVAR_A = $62; INT_EXCEL_TOKEN_TAREA_R = $25; { Built-in functions } - INT_EXCEL_SHEET_FUNC_ABS = 24; + INT_EXCEL_SHEET_FUNC_ABS = 24; // $18 INT_EXCEL_SHEET_FUNC_ROUND = 27; { Control Tokens, Special Tokens } @@ -124,7 +128,7 @@ type function GetLastRowIndex(AWorksheet: TsWorksheet): Integer; procedure GetLastColCallback(ACell: PCell; AStream: TStream); function GetLastColIndex(AWorksheet: TsWorksheet): Word; - function FormulaElementKindToExcelTokenID(AElementKind: TFEKind): Byte; + function FormulaElementKindToExcelTokenID(AElementKind: TFEKind; out ASecondaryID: Word): Byte; // Other records which didn't change // Workbook Globals records procedure WriteCodepage(AStream: TStream; AEncoding: TsEncoding); @@ -271,8 +275,10 @@ begin end; function TsSpreadBIFFWriter.FormulaElementKindToExcelTokenID( - AElementKind: TFEKind): Byte; + AElementKind: TFEKind; out ASecondaryID: Word): Byte; begin + ASecondaryID := 0; + case AElementKind of { Operand Tokens } fekCell: Result := INT_EXCEL_TOKEN_TREFR; @@ -284,8 +290,16 @@ begin fekDiv: Result := INT_EXCEL_TOKEN_TDIV; fekMul: Result := INT_EXCEL_TOKEN_TMUL; { Build-in Functions} - fekABS: Result := INT_EXCEL_SHEET_FUNC_ABS; - fekROUND: Result := INT_EXCEL_SHEET_FUNC_ROUND; + fekABS: + begin + Result := INT_EXCEL_TOKEN_FUNC_V; + ASecondaryID := INT_EXCEL_SHEET_FUNC_ABS; + end; + fekROUND: + begin + Result := INT_EXCEL_TOKEN_FUNC_V; + ASecondaryID := INT_EXCEL_SHEET_FUNC_ROUND; + end; { Other operations } fekOpSUM: Result := INT_EXCEL_TOKEN_TATTR; else