From 25c56b78646cbeb486a8a2a77b32c59737ac04fe Mon Sep 17 00:00:00 2001 From: Eivind Kvedalen Date: Sat, 12 Nov 2016 08:29:46 +0100 Subject: [PATCH] Spreadsheet: Fix for issue #2646: Spreadsheet-Sum-Function does not work with units This fix also fixes the other aggregates. --- src/App/Expression.cpp | 6 +- src/Mod/Spreadsheet/TestSpreadsheet.py | 118 +++++++++++++++++++++---- 2 files changed, 102 insertions(+), 22 deletions(-) diff --git a/src/App/Expression.cpp b/src/App/Expression.cpp index 0d249e56ebc5..4fba2458062a 100644 --- a/src/App/Expression.cpp +++ b/src/App/Expression.cpp @@ -733,7 +733,7 @@ class Collector { Collector() : first(true) { } virtual void collect(Quantity value) { if (first) - value.setUnit(value.getUnit()); + q.setUnit(value.getUnit()); } virtual Quantity getQuantity() const { return q; @@ -779,7 +779,7 @@ class StdDevCollector : public Collector { void collect(Quantity value) { Collector::collect(value); if (first) { - M2 = Quantity(0, value.getUnit()); + M2 = Quantity(0, value.getUnit() * value.getUnit()); mean = Quantity(0, value.getUnit()); n = 0; } @@ -795,7 +795,7 @@ class StdDevCollector : public Collector { if (n < 2) throw ExpressionError("Invalid number of entries: at least two required."); else - return (M2 / (n - 1.0)).pow(Quantity(0.5)); + return Quantity((M2 / (n - 1.0)).pow(Quantity(0.5)).getValue(), mean.getUnit()); } private: diff --git a/src/Mod/Spreadsheet/TestSpreadsheet.py b/src/Mod/Spreadsheet/TestSpreadsheet.py index 05aaea3d1c3e..2cd26b5beac4 100644 --- a/src/Mod/Spreadsheet/TestSpreadsheet.py +++ b/src/Mod/Spreadsheet/TestSpreadsheet.py @@ -29,34 +29,114 @@ def setUp(self): def testAggregates(self): """ Test all aggregate functions """ sheet = self.doc.addObject('Spreadsheet::Sheet','Spreadsheet') - sheet.set('B3', '4') - sheet.set('B4', '5') - sheet.set('B5', '6') + sheet.set('B13', '4') + sheet.set('B14', '5') + sheet.set('B15', '6') + sheet.set('C13', '4mm') + sheet.set('C14', '5mm') + sheet.set('C15', '6mm') + sheet.set('C16', '6') + sheet.set('A1', '=sum(1)') sheet.set('A2', '=sum(1;2)') sheet.set('A3', '=sum(1;2;3)') - sheet.set('A4', '=sum(1;2;3;B3)') - sheet.set('A5', '=sum(1;2;3;B3:B5)') - sheet.set('A6', '=stddev(1;2;3)') - sheet.set('A7', '=average(1;2;3)') - sheet.set('A8', '=count(1;2;3)') - sheet.set('A9', '=min(1;2;3)') - sheet.set('A10', '=max(1;2;3)') - sheet.set('A11', '=stddev(B3)') - sheet.set('A12', '=stddev(B3:B5)') + sheet.set('A4', '=sum(1;2;3;B13)') + sheet.set('A5', '=sum(1;2;3;B13:B15)') + + sheet.set('B1', '=min(1)') + sheet.set('B2', '=min(1;2)') + sheet.set('B3', '=min(1;2;3)') + sheet.set('B4', '=min(1;2;3;B13)') + sheet.set('B5', '=min(1;2;3;B13:B15)') + + sheet.set('C1', '=max(1)') + sheet.set('C2', '=max(1;2)') + sheet.set('C3', '=max(1;2;3)') + sheet.set('C4', '=max(1;2;3;B13)') + sheet.set('C5', '=max(1;2;3;B13:B15)') + + sheet.set('D1', '=stddev(1)') + sheet.set('D2', '=stddev(1;2)') + sheet.set('D3', '=stddev(1;2;3)') + sheet.set('D4', '=stddev(1;2;3;B13)') + sheet.set('D5', '=stddev(1;2;3;B13:B15)') + + sheet.set('E1', '=count(1)') + sheet.set('E2', '=count(1;2)') + sheet.set('E3', '=count(1;2;3)') + sheet.set('E4', '=count(1;2;3;B13)') + sheet.set('E5', '=count(1;2;3;B13:B15)') + + sheet.set('F1', '=average(1)') + sheet.set('F2', '=average(1;2)') + sheet.set('F3', '=average(1;2;3)') + sheet.set('F4', '=average(1;2;3;B13)') + sheet.set('F5', '=average(1;2;3;B13:B15)') + + sheet.set('G1', '=average(C13:C15)') + sheet.set('G2', '=min(C13:C15)') + sheet.set('G3', '=max(C13:C15)') + sheet.set('G4', '=count(C13:C15)') + sheet.set('G5', '=stddev(C13:C15)') + sheet.set('G6', '=sum(C13:C15)') + + sheet.set('H1', '=average(C13:C16)') + sheet.set('H2', '=min(C13:C16)') + sheet.set('H3', '=max(C13:C16)') + sheet.set('H4', '=count(C13:C16)') + sheet.set('H5', '=stddev(C13:C16)') + sheet.set('H6', '=sum(C13:C16)') + self.doc.recompute() self.assertEqual(sheet.A1, 1) self.assertEqual(sheet.A2, 3) self.assertEqual(sheet.A3, 6) self.assertEqual(sheet.A4, 10) self.assertEqual(sheet.A5, 21) - self.assertEqual(sheet.A6, 1) - self.assertEqual(sheet.A7, 2) - self.assertEqual(sheet.A8, 3) - self.assertEqual(sheet.A9, 1) - self.assertEqual(sheet.A10, 3) - self.assertEqual(sheet.A11, u'ERR: Invalid number of entries: at least two required.') - self.assertEqual(sheet.A12, 1) + + self.assertEqual(sheet.B1, 1) + self.assertEqual(sheet.B2, 1) + self.assertEqual(sheet.B3, 1) + self.assertEqual(sheet.B4, 1) + self.assertEqual(sheet.B5, 1) + + self.assertEqual(sheet.C1, 1) + self.assertEqual(sheet.C2, 2) + self.assertEqual(sheet.C3, 3) + self.assertEqual(sheet.C4, 4) + self.assertEqual(sheet.C5, 6) + + self.assertEqual(sheet.D1, u'ERR: Invalid number of entries: at least two required.') + self.assertEqual(sheet.D2, 0.7071067811865476) + self.assertEqual(sheet.D3, 1.0) + self.assertEqual(sheet.D4, 1.2909944487358056) + self.assertEqual(sheet.D5, 1.8708286933869707) + + self.assertEqual(sheet.E1, 1) + self.assertEqual(sheet.E2, 2) + self.assertEqual(sheet.E3, 3) + self.assertEqual(sheet.E4, 4) + self.assertEqual(sheet.E5, 6) + + self.assertEqual(sheet.F1, 1) + self.assertEqual(sheet.F2, (1.0 + 2.0) / 2.0) + self.assertEqual(sheet.F3, (1.0 + 2 + 3) / 3) + self.assertEqual(sheet.F4, (1.0 + 2 + 3 + 4) / 4) + self.assertEqual(sheet.F5, (1.0 + 2 + 3 + 4 + 5 + 6) / 6) + + self.assertEqual(sheet.G1, Quantity('5 mm')) + self.assertEqual(sheet.G2, Quantity('4 mm')) + self.assertEqual(sheet.G3, Quantity('6 mm')) + self.assertEqual(sheet.G4, 3) + self.assertEqual(sheet.G5, Quantity('1 mm')) + self.assertEqual(sheet.G6, Quantity('15 mm')) + + self.assertEqual(sheet.H1, u'ERR: Quantity::operator +=(): Unit mismatch in plus operation') + self.assertEqual(sheet.H2, u'ERR: Quantity::operator <(): quantities need to have same unit to compare') + self.assertEqual(sheet.H3, u'ERR: Quantity::operator >(): quantities need to have same unit to compare') + self.assertEqual(sheet.H4, 4) + self.assertEqual(sheet.H5, u'ERR: Quantity::operator +(): Unit mismatch in minus operation') + self.assertEqual(sheet.H6, u'ERR: Quantity::operator +=(): Unit mismatch in plus operation') def assertMostlyEqual(self, a, b): if type(a) is Quantity: