diff --git a/components/fpspreadsheet/source/common/fpsexprparser.pas b/components/fpspreadsheet/source/common/fpsexprparser.pas index e82a85211..e88179648 100644 --- a/components/fpspreadsheet/source/common/fpsexprparser.pas +++ b/components/fpspreadsheet/source/common/fpsexprparser.pas @@ -3991,16 +3991,55 @@ end; constructor TsCellRangeExprNode.Create(AParser: TsExpressionParser; AWorksheet: TsWorksheet; ASheet1, ASheet2: String; ARow1, ACol1, ARow2, ACol2: Cardinal; AFlags: tsRelFlags; Is3DRange: Boolean); +var + tmp: Integer; begin FParser := AParser; FWorksheet := AWorksheet; + FFlags := []; + + if (ASheet1 = '') and (ASheet2 <> '') then + raise Exception.Create('Invalid parameters in cell range'); + FSheet[1] := GetWorkbook.GetWorksheetIndex(ASheet1); - if ASheet2 = '' then FSheet[2] := FSheet[1] else FSheet[2] := GetWorkbook.GetWorksheetIndex(ASheet2); - FRow[1] := ARow1; - FCol[1] := ACol1; - if ARow2 = Cardinal(-1) then FRow[2] := FRow[1] else FRow[2] := ARow2; - if ACol2 = Cardinal(-1) then FCol[2] := FCol[1] else FCol[2] := ACol2; - FFlags := AFlags; + if ASheet2 <> '' then + FSheet[2] := GetWorkbook.GetWorksheetIndex(ASheet2) + else + FSheet[2] := FSheet[1]; + EnsureOrder(FSheet[1], FSheet[2]); + + if ARow2 = Cardinal(-1) then + ARow2 := ARow1; + if ARow1 <= ARow2 then + begin + FRow[1] := ARow1; + FRow[2] := ARow2; + FCol[1] := ACol1; + if rfRelRow in AFlags then Include(FFlags, rfRelRow); + if rfRelRow2 in AFlags then Include(FFlags, rfRelRow2); + end else + begin + FRow[1] := ARow2; + FRow[2] := ARow1; + if rfRelRow in AFlags then Include(FFlags, rfRelRow2); + if rfRelRow2 in AFlags then Include(FFlags, rfRelRow); + end; + + if ACol2 = Cardinal(-1) then + ACol2 := ACol1; + if ACol1 <= ACol2 then + begin + FCol[1] := ACol1; + FCol[2] := ACol2; + if (rfRelCol in AFlags) then Include(FFlags, rfRelCol); + if (rfRelCol2 in AFlags) then Include(FFlags, rfRelCol2); + end else + begin + FCol[1] := ACol2; + FCol[2] := ACol1; + if (rfRelCol in AFlags) then Include(FFlags, rfRelCol2); + if (rfRelCol2 in AFlags) then Include(FFlags, rfRelCol); + end; F3dRange := Is3dRange; end; diff --git a/components/fpspreadsheet/source/common/fpspreadsheet.pas b/components/fpspreadsheet/source/common/fpspreadsheet.pas index 5795befaf..04680dc0e 100644 --- a/components/fpspreadsheet/source/common/fpspreadsheet.pas +++ b/components/fpspreadsheet/source/common/fpspreadsheet.pas @@ -5731,12 +5731,12 @@ begin parser := TsSpreadsheetParser.Create(self); try - if ALocalized then begin + if ALocalized then // Convert "localized" formula to standard format - parser.LocalizedExpression[Workbook.FormatSettings] := AFormula; - AFormula := parser.Expression; - end else + parser.LocalizedExpression[Workbook.FormatSettings] := AFormula + else parser.Expression := AFormula; + AFormula := parser.Expression; if parser.Has3DLinks then ACell.Flags := ACell.Flags + [cf3dFormula] else ACell.Flags := ACell.Flags - [cf3dFormula]; diff --git a/components/fpspreadsheet/tests/singleformulatests.pas b/components/fpspreadsheet/tests/singleformulatests.pas index 85dbcfa6e..446a3dc87 100644 --- a/components/fpspreadsheet/tests/singleformulatests.pas +++ b/components/fpspreadsheet/tests/singleformulatests.pas @@ -23,7 +23,8 @@ type procedure SetUp; override; procedure TearDown; override; procedure TestFloatFormula(AFormula: String; AExpected: Double; - ATestKind: TFormulaTestKind; AFormat: TsSpreadsheetFormat); + ATestKind: TFormulaTestKind; AFormat: TsSpreadsheetFormat; + AExpectedFormula: String = ''); published procedure AddConst_BIFF2; @@ -54,6 +55,10 @@ type procedure SumMultiSheetRange_OOXML; procedure SumMultiSheetRange_ODS; + procedure SumMultiSheetRange_FlippedCells_OOXML; + procedure SumMultiSheetRange_FlippedSheets_OOXML; + procedure SumMultiSheetRange_FlippedSheetsAndCells_OOXML; + end; implementation @@ -78,7 +83,8 @@ begin end; procedure TSpreadSingleFormulaTests.TestFloatFormula(AFormula: String; - AExpected: Double; ATestKind: TFormulaTestKind; AFormat: TsSpreadsheetFormat); + AExpected: Double; ATestKind: TFormulaTestKind; AFormat: TsSpreadsheetFormat; + AExpectedFormula: String = ''); const SHEET1 = 'Sheet1'; SHEET2 = 'Sheet2'; @@ -95,6 +101,7 @@ var actualValue: Double; begin TempFile := GetTempFileName; + if AExpectedFormula = '' then AExpectedFormula := AFormula; try // Create test workbook and write test formula and needed cells @@ -132,7 +139,7 @@ begin // Read formula before saving actualFormula := cell^.Formulavalue; - CheckEquals(AFormula, actualFormula, 'Unsaved formula text mismatch'); + CheckEquals(AExpectedFormula, actualFormula, 'Unsaved formula text mismatch'); // Read calculated value before saving actualvalue := worksheet.ReadAsNumber(TESTCELL_ROW, TESTCELL_COL); @@ -157,7 +164,7 @@ begin cell := worksheet.FindCell(TESTCELL_ROW, TESTCELL_COL); actualformula := cell^.FormulaValue; - CheckEquals(AFormula, actualformula, 'Saved formula text mismatch.'); + CheckEquals(AExpectedFormula, actualformula, 'Saved formula text mismatch.'); finally workbook.Free; end; @@ -290,6 +297,23 @@ begin TestFloatFormula('SUM(Sheet2:Sheet3!C3:C5)', 55.0, ftkCellRangeSheetRange, sfOpenDocument); end; +{ --- } + +procedure TSpreadSingleFormulaTests.SumMultiSheetRange_FlippedSheetsAndCells_OOXML; +begin + TestFloatFormula('SUM(Sheet3:Sheet2!C5:C3)', 55.0, ftkCellRangeSheetRange, sfOOXML, 'SUM(Sheet2:Sheet3!C3:C5)'); +end; + +procedure TSpreadSingleFormulaTests.SumMultiSheetRange_FlippedCells_OOXML; +begin + TestFloatFormula('SUM(Sheet2:Sheet3!C5:C3)', 55.0, ftkCellRangeSheetRange, sfOOXML, 'SUM(Sheet2:Sheet3!C3:C5)'); +end; + +procedure TSpreadSingleFormulaTests.SumMultiSheetRange_FlippedSheets_OOXML; +begin + TestFloatFormula('SUM(Sheet3:Sheet2!C3:C5)', 55.0, ftkCellRangeSheetRange, sfOOXML, 'SUM(Sheet2:Sheet3!C3:C5)'); +end; + initialization // Register to include these tests in a full run RegisterTest(TSpreadSingleFormulaTests);