1351 lines
57 KiB
Python
1351 lines
57 KiB
Python
#***************************************************************************
|
|
#* Copyright (c) 2016 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
|
#* Copyright (c) 2016 Eivind Kvedalen <eivind@kvedalen.name> *
|
|
#* *
|
|
#* This program is free software; you can redistribute it and/or modify *
|
|
#* it under the terms of the GNU General Public License (GPL) *
|
|
#* as published by the Free Software Foundation; either version 2 of *
|
|
#* the License, or (at your option) any later version. *
|
|
#* for detail see the LICENCE text file. *
|
|
#* *
|
|
#* FreeCAD is distributed in the hope that it will be useful, *
|
|
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
#* GNU Library General Public License for more details. *
|
|
#* *
|
|
#* You should have received a copy of the GNU Library General Public *
|
|
#* License along with FreeCAD; if not, write to the Free Software *
|
|
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
|
#* USA *
|
|
#***************************************************************************/
|
|
|
|
import os
|
|
import sys
|
|
import math
|
|
import unittest
|
|
import FreeCAD
|
|
import Part
|
|
import Sketcher
|
|
import tempfile
|
|
from FreeCAD import Base
|
|
from FreeCAD import Units
|
|
|
|
v = Base.Vector
|
|
|
|
#----------------------------------------------------------------------------------
|
|
# define the functions to test the FreeCAD Spreadsheet module and expression engine
|
|
#----------------------------------------------------------------------------------
|
|
|
|
|
|
class SpreadsheetCases(unittest.TestCase):
|
|
def setUp(self):
|
|
self.doc = FreeCAD.newDocument()
|
|
self.TempPath = tempfile.gettempdir()
|
|
FreeCAD.Console.PrintLog( ' Using temp path: ' + self.TempPath + '\n')
|
|
|
|
def testAggregates(self):
|
|
""" Test all aggregate functions """
|
|
sheet = self.doc.addObject('Spreadsheet::Sheet','Spreadsheet')
|
|
sheet = self.doc.addObject('Spreadsheet::Sheet','Spreadsheet')
|
|
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;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.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.assertTrue(sheet.D1.startswith(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, Units.Quantity('5 mm'))
|
|
self.assertEqual(sheet.G2, Units.Quantity('4 mm'))
|
|
self.assertEqual(sheet.G3, Units.Quantity('6 mm'))
|
|
self.assertEqual(sheet.G4, 3)
|
|
self.assertEqual(sheet.G5, Units.Quantity('1 mm'))
|
|
self.assertEqual(sheet.G6, Units.Quantity('15 mm'))
|
|
|
|
self.assertTrue(sheet.H1.startswith(u'ERR: Quantity::operator +=(): Unit mismatch in plus operation'))
|
|
self.assertTrue(sheet.H2.startswith(u'ERR: Quantity::operator <(): quantities need to have same unit to compare'))
|
|
self.assertTrue(sheet.H3.startswith(u'ERR: Quantity::operator >(): quantities need to have same unit to compare'))
|
|
self.assertEqual(sheet.H4, 4)
|
|
self.assertTrue(sheet.H5.startswith(u'ERR: Quantity::operator -(): Unit mismatch in minus operation'))
|
|
self.assertTrue(sheet.H6.startswith(u'ERR: Quantity::operator +=(): Unit mismatch in plus operation'))
|
|
|
|
def assertMostlyEqual(self, a, b):
|
|
if type(a) is Units.Quantity:
|
|
self.assertTrue( math.fabs(a.Value - b.Value) < 1e-14)
|
|
self.assertTrue( a.Unit == b.Unit)
|
|
else:
|
|
self.assertTrue( math.fabs(a - b) < 1e-14)
|
|
|
|
def testFunctions(self):
|
|
""" Test all built-in simple functions """
|
|
doc = FreeCAD.newDocument()
|
|
sheet = self.doc.addObject('Spreadsheet::Sheet','Spreadsheet')
|
|
sheet.set('A1', '=cos(60)') # Cos
|
|
sheet.set('B1', '=cos(60deg)')
|
|
sheet.set('C1', '=cos(pi / 2 * 1rad)')
|
|
sheet.set('A2', '=sin(30)') # Sin
|
|
sheet.set('B2', '=sin(30deg)')
|
|
sheet.set('C2', '=sin(pi / 6 * 1rad)')
|
|
sheet.set('A3', '=tan(45)') # Tan
|
|
sheet.set('B3', '=tan(45deg)')
|
|
sheet.set('C3', '=tan(pi / 4 * 1rad)')
|
|
sheet.set('A4', '=abs(3)') # Abs
|
|
sheet.set('B4', '=abs(-3)')
|
|
sheet.set('C4', '=abs(-3mm)')
|
|
sheet.set('A5', '=exp(3)') # Exp
|
|
sheet.set('B5', '=exp(-3)')
|
|
sheet.set('C5', '=exp(-3mm)')
|
|
sheet.set('A6', '=log(3)') # Log
|
|
sheet.set('B6', '=log(-3)')
|
|
sheet.set('C6', '=log(-3mm)')
|
|
sheet.set('A7', '=log10(10)') # Log10
|
|
sheet.set('B7', '=log10(-3)')
|
|
sheet.set('C7', '=log10(-3mm)')
|
|
sheet.set('A8', '=round(3.4)')# Round
|
|
sheet.set('B8', '=round(3.6)')
|
|
sheet.set('C8', '=round(-3.4)')
|
|
sheet.set('D8', '=round(-3.6)')
|
|
sheet.set('E8', '=round(3.4mm)')
|
|
sheet.set('F8', '=round(3.6mm)')
|
|
sheet.set('G8', '=round(-3.4mm)')
|
|
sheet.set('H8', '=round(-3.6mm)')
|
|
sheet.set('A9', '=trunc(3.4)')# Trunc
|
|
sheet.set('B9', '=trunc(3.6)')
|
|
sheet.set('C9', '=trunc(-3.4)')
|
|
sheet.set('D9', '=trunc(-3.6)')
|
|
sheet.set('E9', '=trunc(3.4mm)')
|
|
sheet.set('F9', '=trunc(3.6mm)')
|
|
sheet.set('G9', '=trunc(-3.4mm)')
|
|
sheet.set('H9', '=trunc(-3.6mm)')
|
|
sheet.set('A10', '=ceil(3.4)') # Ceil
|
|
sheet.set('B10', '=ceil(3.6)')
|
|
sheet.set('C10', '=ceil(-3.4)')
|
|
sheet.set('D10', '=ceil(-3.6)')
|
|
sheet.set('E10', '=ceil(3.4mm)')
|
|
sheet.set('F10', '=ceil(3.6mm)')
|
|
sheet.set('G10', '=ceil(-3.4mm)')
|
|
sheet.set('H10', '=ceil(-3.6mm)')
|
|
sheet.set('A11', '=floor(3.4)')# Floor
|
|
sheet.set('B11', '=floor(3.6)')
|
|
sheet.set('C11', '=floor(-3.4)')
|
|
sheet.set('D11', '=floor(-3.6)')
|
|
sheet.set('E11', '=floor(3.4mm)')
|
|
sheet.set('F11', '=floor(3.6mm)')
|
|
sheet.set('G11', '=floor(-3.4mm)')
|
|
sheet.set('H11', '=floor(-3.6mm)')
|
|
sheet.set('A12', '=asin(0.5)') # Asin
|
|
sheet.set('B12', '=asin(0.5mm)')
|
|
sheet.set('A13', '=acos(0.5)') # Acos
|
|
sheet.set('B13', '=acos(0.5mm)')
|
|
sheet.set('A14', '=atan(sqrt(3))') # Atan
|
|
sheet.set('B14', '=atan(0.5mm)')
|
|
sheet.set('A15', '=sinh(0.5)') # Sinh
|
|
sheet.set('B15', '=sinh(0.5mm)')
|
|
sheet.set('A16', '=cosh(0.5)') # Cosh
|
|
sheet.set('B16', '=cosh(0.5mm)')
|
|
sheet.set('A17', '=tanh(0.5)') # Tanh
|
|
sheet.set('B17', '=tanh(0.5mm)')
|
|
sheet.set('A18', '=sqrt(4)') # Sqrt
|
|
sheet.set('B18', '=sqrt(4mm^2)')
|
|
sheet.set('A19', '=mod(7; 4)') # Mod
|
|
sheet.set('B19', '=mod(-7; 4)')
|
|
sheet.set('C19', '=mod(7mm; 4)')
|
|
sheet.set('D19', '=mod(7mm; 4mm)')
|
|
sheet.set('A20', '=atan2(3; 3)') # Atan2
|
|
sheet.set('B20', '=atan2(-3; 3)')
|
|
sheet.set('C20', '=atan2(3mm; 3)')
|
|
sheet.set('D20', '=atan2(3mm; 3mm)')
|
|
sheet.set('A21', '=pow(7; 4)') # Pow
|
|
sheet.set('B21', '=pow(-7; 4)')
|
|
sheet.set('C21', '=pow(7mm; 4)')
|
|
sheet.set('D21', '=pow(7mm; 4mm)')
|
|
sheet.set('A23', '=hypot(3; 4)') # Hypot
|
|
sheet.set('B23', '=hypot(-3; 4)')
|
|
sheet.set('C23', '=hypot(3mm; 4)')
|
|
sheet.set('D23', '=hypot(3mm; 4mm)')
|
|
sheet.set('A24', '=hypot(3; 4; 5)') # Hypot
|
|
sheet.set('B24', '=hypot(-3; 4; 5)')
|
|
sheet.set('C24', '=hypot(3mm; 4; 5)')
|
|
sheet.set('D24', '=hypot(3mm; 4mm; 5mm)')
|
|
sheet.set('A26', '=cath(5; 3)') # Cath
|
|
sheet.set('B26', '=cath(-5; 3)')
|
|
sheet.set('C26', '=cath(5mm; 3)')
|
|
sheet.set('D26', '=cath(5mm; 3mm)')
|
|
|
|
l = math.sqrt(5 * 5 + 4*4 + 3*3)
|
|
sheet.set('A27', '=cath(%0.15f; 5; 4)' % l) # Cath
|
|
sheet.set('B27', '=cath(%0.15f; -5; 4)' % l)
|
|
sheet.set('C27', '=cath(%0.15f mm; 5mm; 4)' % l)
|
|
sheet.set('D27', '=cath(%0.15f mm; 5mm; 4mm)' % l)
|
|
|
|
self.doc.recompute()
|
|
self.assertMostlyEqual(sheet.A1, 0.5) # Cos
|
|
self.assertMostlyEqual(sheet.B1, 0.5)
|
|
self.assertMostlyEqual(sheet.C1, 0)
|
|
self.assertMostlyEqual(sheet.A2, 0.5) # Sin
|
|
self.assertMostlyEqual(sheet.B2, 0.5)
|
|
self.assertMostlyEqual(sheet.C2, 0.5)
|
|
self.assertMostlyEqual(sheet.A3, 1) # Tan
|
|
self.assertMostlyEqual(sheet.B3, 1)
|
|
self.assertMostlyEqual(sheet.C3, 1 )
|
|
self.assertMostlyEqual(sheet.A4, 3) # Abs
|
|
self.assertMostlyEqual(sheet.B4, 3)
|
|
self.assertMostlyEqual(sheet.C4, Units.Quantity('3 mm'))
|
|
self.assertMostlyEqual(sheet.A5, math.exp(3)) # Exp
|
|
self.assertMostlyEqual(sheet.B5, math.exp(-3))
|
|
self.assertTrue(sheet.C5.startswith(u'ERR: Unit must be empty.'))
|
|
self.assertMostlyEqual(sheet.A6, math.log(3)) # Log
|
|
self.assertTrue(math.isnan(sheet.B6))
|
|
self.assertTrue(sheet.C6.startswith(u'ERR: Unit must be empty.'))
|
|
self.assertMostlyEqual(sheet.A7, math.log10(10)) # Log10
|
|
self.assertTrue(math.isnan(sheet.B7))
|
|
self.assertTrue(sheet.C7.startswith(u'ERR: Unit must be empty.'))
|
|
self.assertMostlyEqual(sheet.A8, 3) # Round
|
|
self.assertMostlyEqual(sheet.B8, 4)
|
|
self.assertMostlyEqual(sheet.C8, -3)
|
|
self.assertMostlyEqual(sheet.D8, -4)
|
|
self.assertEqual(sheet.E8, Units.Quantity('3 mm'))
|
|
self.assertEqual(sheet.F8, Units.Quantity('4 mm'))
|
|
self.assertEqual(sheet.G8, Units.Quantity('-3 mm'))
|
|
self.assertEqual(sheet.H8, Units.Quantity('-4 mm'))
|
|
self.assertMostlyEqual(sheet.A9, 3)# Trunc
|
|
self.assertMostlyEqual(sheet.B9, 3)
|
|
self.assertMostlyEqual(sheet.C9, -3)
|
|
self.assertMostlyEqual(sheet.D9, -3)
|
|
self.assertEqual(sheet.E9, Units.Quantity('3 mm'))
|
|
self.assertEqual(sheet.F9, Units.Quantity('3 mm'))
|
|
self.assertEqual(sheet.G9, Units.Quantity('-3 mm'))
|
|
self.assertEqual(sheet.H9, Units.Quantity('-3 mm'))
|
|
self.assertMostlyEqual(sheet.A10, 4) # Ceil
|
|
self.assertMostlyEqual(sheet.B10, 4)
|
|
self.assertMostlyEqual(sheet.C10, -3)
|
|
self.assertMostlyEqual(sheet.D10, -3)
|
|
self.assertMostlyEqual(sheet.E10, Units.Quantity('4 mm'))
|
|
self.assertMostlyEqual(sheet.F10, Units.Quantity('4 mm'))
|
|
self.assertMostlyEqual(sheet.G10, Units.Quantity('-3 mm'))
|
|
self.assertMostlyEqual(sheet.H10, Units.Quantity('-3 mm'))
|
|
self.assertMostlyEqual(sheet.A11, 3)# Floor
|
|
self.assertMostlyEqual(sheet.B11, 3)
|
|
self.assertMostlyEqual(sheet.C11, -4)
|
|
self.assertMostlyEqual(sheet.D11, -4)
|
|
self.assertMostlyEqual(sheet.E11, Units.Quantity('3 mm'))
|
|
self.assertMostlyEqual(sheet.F11, Units.Quantity('3 mm'))
|
|
self.assertMostlyEqual(sheet.G11, Units.Quantity('-4 mm'))
|
|
self.assertMostlyEqual(sheet.H11, Units.Quantity('-4 mm'))
|
|
self.assertMostlyEqual(sheet.A12, Units.Quantity('30 deg')) # Asin
|
|
self.assertTrue(sheet.B12.startswith(u'ERR: Unit must be empty.'))
|
|
self.assertMostlyEqual(sheet.A13, Units.Quantity('60 deg')) # Acos
|
|
self.assertTrue(sheet.B13.startswith(u'ERR: Unit must be empty.'))
|
|
self.assertMostlyEqual(sheet.A14, Units.Quantity('60 deg')) # Atan
|
|
self.assertTrue(sheet.B14.startswith(u'ERR: Unit must be empty.'))
|
|
self.assertMostlyEqual(sheet.A15, math.sinh(0.5)) # Sinh
|
|
self.assertTrue(sheet.B15.startswith(u'ERR: Unit must be empty.'))
|
|
self.assertMostlyEqual(sheet.A16, math.cosh(0.5)) # Cosh
|
|
self.assertTrue(sheet.B16.startswith(u'ERR: Unit must be empty.'))
|
|
self.assertMostlyEqual(sheet.A17, math.tanh(0.5)) # Tanh
|
|
self.assertTrue(sheet.B17.startswith(u'ERR: Unit must be empty.'))
|
|
self.assertMostlyEqual(sheet.A18, 2) # Sqrt
|
|
self.assertMostlyEqual(sheet.B18, Units.Quantity('2 mm'))
|
|
self.assertMostlyEqual(sheet.A19, 3) # Mod
|
|
self.assertMostlyEqual(sheet.B19, -3)
|
|
self.assertMostlyEqual(sheet.C19, Units.Quantity('3 mm'))
|
|
self.assertEqual(sheet.D19, 3)
|
|
self.assertMostlyEqual(sheet.A20, Units.Quantity('45 deg')) # Atan2
|
|
self.assertMostlyEqual(sheet.B20, Units.Quantity('-45 deg'))
|
|
self.assertTrue(sheet.C20.startswith(u'ERR: Units must be equal'))
|
|
self.assertMostlyEqual(sheet.D20, Units.Quantity('45 deg'))
|
|
self.assertMostlyEqual(sheet.A21, 2401) # Pow
|
|
self.assertMostlyEqual(sheet.B21, 2401)
|
|
self.assertMostlyEqual(sheet.C21, Units.Quantity('2401mm^4'))
|
|
self.assertTrue(sheet.D21.startswith(u'ERR: Exponent is not allowed to have a unit.'))
|
|
self.assertMostlyEqual(sheet.A23, 5) # Hypot
|
|
self.assertMostlyEqual(sheet.B23, 5)
|
|
self.assertTrue(sheet.C23.startswith(u'ERR: Units must be equal'))
|
|
self.assertMostlyEqual(sheet.D23, Units.Quantity('5mm'))
|
|
|
|
l = math.sqrt(3*3 + 4*4 + 5*5)
|
|
self.assertMostlyEqual(sheet.A24, l) # Hypot
|
|
self.assertMostlyEqual(sheet.B24, l)
|
|
self.assertTrue(sheet.C24.startswith(u'ERR: Units must be equal'))
|
|
self.assertMostlyEqual(sheet.D24, Units.Quantity("7.07106781186548 mm"))
|
|
self.assertMostlyEqual(sheet.A26, 4) # Cath
|
|
self.assertMostlyEqual(sheet.B26, 4)
|
|
self.assertTrue(sheet.C26.startswith(u'ERR: Units must be equal'))
|
|
self.assertMostlyEqual(sheet.D26, Units.Quantity('4mm'))
|
|
|
|
l = math.sqrt(5 * 5 + 4*4 + 3*3)
|
|
l = math.sqrt(l * l - 5*5 - 4*4)
|
|
self.assertMostlyEqual(sheet.A27, l) # Cath
|
|
self.assertMostlyEqual(sheet.B27, l)
|
|
self.assertTrue(sheet.C27.startswith(u'ERR: Units must be equal'))
|
|
self.assertMostlyEqual(sheet.D27, Units.Quantity("3 mm"))
|
|
FreeCAD.closeDocument(doc.Name)
|
|
|
|
def testRelationalOperators(self):
|
|
""" Test relational operators """
|
|
sheet = self.doc.addObject('Spreadsheet::Sheet','Spreadsheet')
|
|
# All should be 1 as result
|
|
sheet.set('A1', '=1 == 1 ? 1 : 0')
|
|
sheet.set('A2', '=1 != 1 ? 0 : 1')
|
|
sheet.set('A3', '=1e9 == 1e9 ? 1 : 0')
|
|
sheet.set('A4', '=1e9 != 1e9 ? 0 : 1')
|
|
sheet.set('A5', '=1 > 1 ? 0 : 1')
|
|
sheet.set('A6', '=2 > 1 ? 1 : 0')
|
|
sheet.set('A7', '=1 > 2 ? 0 : 1')
|
|
sheet.set('A8', '=1 < 1 ? 0 : 1')
|
|
sheet.set('A9', '=1 < 2 ? 1 : 0')
|
|
sheet.set('A10', '=2 < 1 ? 0 : 1')
|
|
sheet.set('A11', '=1 >= 1 ? 1 : 0')
|
|
sheet.set('A12', '=2 >= 1 ? 1 : 0')
|
|
sheet.set('A13', '=1 >= 2 ? 0 : 1')
|
|
sheet.set('A14', '=1 <= 1 ? 1 : 1')
|
|
sheet.set('A15', '=1 <= 2 ? 1 : 0')
|
|
sheet.set('A16', '=2 <= 1 ? 0 : 1')
|
|
sheet.set('A17', '=1 >= 1.000000000000001 ? 0 : 1')
|
|
sheet.set('A18', '=1 >= 1.0000000000000001 ? 1 : 0')
|
|
sheet.set('A19', '=1 <= 1.000000000000001 ? 1 : 0')
|
|
sheet.set('A20', '=1 <= 1.0000000000000001 ? 1 : 0')
|
|
sheet.set('A21', '=1 == 1.000000000000001 ? 0 : 1')
|
|
sheet.set('A22', '=1 == 1.0000000000000001 ? 1 : 0')
|
|
sheet.set('A23', '=1 != 1.000000000000001 ? 1 : 0')
|
|
sheet.set('A24', '=1 != 1.0000000000000001 ? 0 : 1')
|
|
|
|
self.doc.recompute()
|
|
self.assertEqual(sheet.A1, 1)
|
|
self.assertEqual(sheet.A2, 1)
|
|
self.assertEqual(sheet.A3, 1)
|
|
self.assertEqual(sheet.A4, 1)
|
|
self.assertEqual(sheet.A5, 1)
|
|
self.assertEqual(sheet.A6, 1)
|
|
self.assertEqual(sheet.A7, 1)
|
|
self.assertEqual(sheet.A8, 1)
|
|
self.assertEqual(sheet.A9, 1)
|
|
self.assertEqual(sheet.A10, 1)
|
|
self.assertEqual(sheet.A11, 1)
|
|
self.assertEqual(sheet.A12, 1)
|
|
self.assertEqual(sheet.A13, 1)
|
|
self.assertEqual(sheet.A14, 1)
|
|
self.assertEqual(sheet.A15, 1)
|
|
self.assertEqual(sheet.A16, 1)
|
|
self.assertEqual(sheet.A17, 1)
|
|
self.assertEqual(sheet.A18, 1)
|
|
self.assertEqual(sheet.A19, 1)
|
|
self.assertEqual(sheet.A20, 1)
|
|
self.assertEqual(sheet.A21, 1)
|
|
self.assertEqual(sheet.A22, 1)
|
|
self.assertEqual(sheet.A23, 1)
|
|
self.assertEqual(sheet.A24, 1)
|
|
|
|
def testUnits(self):
|
|
""" Units -- test unit calculations. """
|
|
sheet = self.doc.addObject('Spreadsheet::Sheet','Spreadsheet')
|
|
sheet.set('A1', '=2mm + 3mm')
|
|
sheet.set('A2', '=2mm - 3mm')
|
|
sheet.set('A3', '=2mm * 3mm')
|
|
sheet.set('A4', '=4mm / 2mm')
|
|
sheet.set('A5', '=(4mm)^2')
|
|
sheet.set('A6', '=5(mm^2)')
|
|
sheet.set('A7', '=5mm^2') # ^2 operates on whole number
|
|
sheet.set('A8', '=5')
|
|
sheet.set('A9', '=5*1/K') # Currently fails
|
|
sheet.set('A10', '=5 K^-1') # Currently fails
|
|
sheet.set('A11', '=9.8 m/s^2') # Currently fails
|
|
sheet.setDisplayUnit('A8', '1/K')
|
|
self.doc.recompute()
|
|
self.assertEqual(sheet.A1, Units.Quantity('5mm'))
|
|
self.assertEqual(sheet.A2, Units.Quantity('-1 mm'))
|
|
self.assertEqual(sheet.A3, Units.Quantity('6 mm^2'))
|
|
self.assertEqual(sheet.A4, Units.Quantity('2'))
|
|
self.assertEqual(sheet.A5, Units.Quantity('16 mm^2'))
|
|
self.assertEqual(sheet.A6, Units.Quantity('5 mm^2'))
|
|
self.assertEqual(sheet.A7, Units.Quantity('5 mm^2'))
|
|
self.assertEqual(sheet.A8, Units.Quantity('5'))
|
|
self.assertEqual(sheet.A9, Units.Quantity('5 K^-1'))
|
|
self.assertEqual(sheet.A10, Units.Quantity('5 K^-1'))
|
|
self.assertEqual(sheet.A11, Units.Quantity('9.8 m/s^2'))
|
|
|
|
def testPrecedence(self):
|
|
""" Precedence -- test precedence for relational operators and conditional operator. """
|
|
sheet = self.doc.addObject('Spreadsheet::Sheet','Spreadsheet')
|
|
sheet.set('A1', '=1 < 2 ? 3 : 4')
|
|
sheet.set('A2', '=1 + 2 < 3 + 4 ? 5 + 6 : 7 + 8')
|
|
sheet.set('A3', '=1 + 2 * 1 < 3 + 4 ? 5 * 2 + 6 * 3 + 2 ^ 4 : 7 * 2 + 8 * 3 + 2 ^ 3')
|
|
sheet.set('A4', '=123')
|
|
sheet.set('A5', '=123 + 321')
|
|
sheet.set('A6', '=123 * 2 + 321')
|
|
sheet.set('A7', '=123 * 2 + 333 / 3')
|
|
sheet.set('A8', '=123 * (2 + 321)')
|
|
sheet.set('A9', '=3 ^ 4')
|
|
sheet.set('A10', '=3 ^ 4 * 2')
|
|
sheet.set('A11', '=3 ^ (4 * 2)')
|
|
sheet.set('A12', '=3 ^ 4 + 4')
|
|
sheet.set('A13', '=1 + 4 / 2 + 5')
|
|
sheet.set('A14', '=(3 + 6) / (1 + 2)')
|
|
sheet.set('A15', '=1 * 2 / 3 * 4')
|
|
sheet.set('A16', '=(1 * 2) / (3 * 4)')
|
|
# Test associativity
|
|
sheet.set('A17', '=3 ^ 4 ^ 2') # exponentiation is left-associative; to follow excel, openoffice, matlab, octave
|
|
sheet.set('A18', '=3 ^ (4 ^ 2)') # exponentiation is left-associative
|
|
sheet.set('A19', '=(3 ^ 4) ^ 2') # exponentiation is left-associative
|
|
sheet.set('A20', '=3 + 4 + 2')
|
|
sheet.set('A21', '=3 + (4 + 2)')
|
|
sheet.set('A22', '=(3 + 4) + 2')
|
|
sheet.set('A23', '=3 - 4 - 2')
|
|
sheet.set('A24', '=3 - (4 - 2)')
|
|
sheet.set('A25', '=(3 - 4) - 2')
|
|
sheet.set('A26', '=3 * 4 * 2')
|
|
sheet.set('A27', '=3 * (4 * 2)')
|
|
sheet.set('A28', '=(3 * 4) * 2')
|
|
sheet.set('A29', '=3 / 4 / 2')
|
|
sheet.set('A30', '=3 / (4 / 2)')
|
|
sheet.set('A31', '=(3 / 4) / 2')
|
|
sheet.set('A32', '=pi * 3')
|
|
sheet.set('A33', '=A32 / 3')
|
|
sheet.set('A34', '=1 < 2 ? <<A>> : <<B>>')
|
|
sheet.set('A35', '=min(A32:A33)')
|
|
sheet.set('A36', '=(1 < 2 ? 0 : 1) * 3')
|
|
sheet.set('A37', '=8/(2^2*2)')
|
|
sheet.set('A38', '=(2^2*2)/8')
|
|
sheet.set('A39', '=2^(2*2)/8')
|
|
sheet.set('A40', '=8/2^(2*2)')
|
|
sheet.set('A41', '=-1')
|
|
sheet.set('A42', '=-(1)')
|
|
sheet.set('A43', '=-(1 + 1)')
|
|
sheet.set('A44', '=-(1 - 1)')
|
|
sheet.set('A45', '=-(-1 + 1)')
|
|
sheet.set('A46', '=-(-1 + -1)')
|
|
sheet.set('A47', '=+1')
|
|
sheet.set('A48', '=+(1)')
|
|
sheet.set('A49', '=+(1 + 1)')
|
|
sheet.set('A50', '=+(1 - 1)')
|
|
sheet.set('A51', '=+(-1 + 1)')
|
|
sheet.set('A52', '=+(-1 + -1)')
|
|
|
|
self.doc.addObject("Part::Cylinder", "Cylinder")
|
|
# We cannot use Thickness, as this feature requires a source shape,
|
|
# otherwise it will cause recomputation failure. The new logic of
|
|
# App::Document will not continue recompute any dependent objects
|
|
|
|
# self.doc.addObject("Part::Thickness", "Pipe")
|
|
self.doc.addObject("Part::Box", "Box")
|
|
self.doc.Box.Length = 1
|
|
|
|
sheet.set('B1', '101')
|
|
sheet.set('A53', '=-(-(B1-1)/2)')
|
|
sheet.set('A54', '=-(Cylinder.Radius + Box.Length - 1"/2)')
|
|
|
|
self.doc.recompute()
|
|
self.assertEqual(sheet.getContents("A1"), "=1 < 2 ? 3 : 4")
|
|
self.assertEqual(sheet.getContents("A2"), "=1 + 2 < 3 + 4 ? 5 + 6 : 7 + 8")
|
|
self.assertEqual(sheet.getContents("A3"), "=1 + 2 * 1 < 3 + 4 ? 5 * 2 + 6 * 3 + 2 ^ 4 : 7 * 2 + 8 * 3 + 2 ^ 3")
|
|
self.assertEqual(sheet.A1, 3)
|
|
self.assertEqual(sheet.A2, 11)
|
|
self.assertEqual(sheet.A3, 44)
|
|
self.assertEqual(sheet.A4, 123)
|
|
self.assertEqual(sheet.A5, 444)
|
|
self.assertEqual(sheet.A6, 567)
|
|
self.assertEqual(sheet.A7, 357)
|
|
self.assertEqual(sheet.A8, 39729)
|
|
self.assertEqual(sheet.A9, 81)
|
|
self.assertEqual(sheet.A10, 162)
|
|
self.assertEqual(sheet.A11, 6561)
|
|
self.assertEqual(sheet.A12, 85)
|
|
self.assertEqual(sheet.A13, 8)
|
|
self.assertEqual(sheet.A14, 3)
|
|
self.assertEqual(sheet.A15, 8.0/3)
|
|
self.assertEqual(sheet.A16, 1.0/6)
|
|
self.assertEqual(sheet.A17, 6561)
|
|
self.assertEqual(sheet.A18, 43046721)
|
|
self.assertEqual(sheet.A19, 6561)
|
|
self.assertEqual(sheet.A20, 9)
|
|
self.assertEqual(sheet.A21, 9)
|
|
self.assertEqual(sheet.A22, 9)
|
|
self.assertEqual(sheet.A23, -3)
|
|
self.assertEqual(sheet.A24, 1)
|
|
self.assertEqual(sheet.A25, -3)
|
|
self.assertEqual(sheet.A26, 24)
|
|
self.assertEqual(sheet.A27, 24)
|
|
self.assertEqual(sheet.A28, 24)
|
|
self.assertEqual(sheet.A29, 3.0/8)
|
|
self.assertEqual(sheet.A30, 3.0/2)
|
|
self.assertEqual(sheet.A31, 3.0/8)
|
|
self.assertEqual(sheet.A37, 1)
|
|
self.assertEqual(sheet.A38, 1)
|
|
self.assertEqual(sheet.A39, 2)
|
|
self.assertEqual(sheet.A40, 0.5)
|
|
self.assertEqual(sheet.A41, -1)
|
|
self.assertEqual(sheet.A42, -1)
|
|
self.assertEqual(sheet.A43, -2)
|
|
self.assertEqual(sheet.A44, 0)
|
|
self.assertEqual(sheet.A45, 0)
|
|
self.assertEqual(sheet.A46, 2)
|
|
self.assertEqual(sheet.A47, 1)
|
|
self.assertEqual(sheet.A48, 1)
|
|
self.assertEqual(sheet.A49, 2)
|
|
self.assertEqual(sheet.A50, 0)
|
|
self.assertEqual(sheet.A51, 0)
|
|
self.assertEqual(sheet.A52, -2)
|
|
self.assertEqual(sheet.A53, 50)
|
|
self.assertEqual(sheet.A54, Units.Quantity('9.7mm'))
|
|
self.assertEqual(sheet.getContents('A1'), '=1 < 2 ? 3 : 4')
|
|
self.assertEqual(sheet.getContents('A2'), '=1 + 2 < 3 + 4 ? 5 + 6 : 7 + 8')
|
|
self.assertEqual(sheet.getContents('A3'), '=1 + 2 * 1 < 3 + 4 ? 5 * 2 + 6 * 3 + 2 ^ 4 : 7 * 2 + 8 * 3 + 2 ^ 3')
|
|
self.assertEqual(sheet.getContents('A4'), '123')
|
|
self.assertEqual(sheet.getContents('A5'), '=123 + 321')
|
|
self.assertEqual(sheet.getContents('A6'), '=123 * 2 + 321')
|
|
self.assertEqual(sheet.getContents('A7'), '=123 * 2 + 333 / 3')
|
|
self.assertEqual(sheet.getContents('A8'), '=123 * (2 + 321)')
|
|
self.assertEqual(sheet.getContents('A9'), '=3 ^ 4')
|
|
self.assertEqual(sheet.getContents('A10'), '=3 ^ 4 * 2')
|
|
self.assertEqual(sheet.getContents('A11'), '=3 ^ (4 * 2)')
|
|
self.assertEqual(sheet.getContents('A12'), '=3 ^ 4 + 4')
|
|
self.assertEqual(sheet.getContents('A13'), '=1 + 4 / 2 + 5')
|
|
self.assertEqual(sheet.getContents('A14'), '=(3 + 6) / (1 + 2)')
|
|
self.assertEqual(sheet.getContents('A15'), '=1 * 2 / 3 * 4')
|
|
self.assertEqual(sheet.getContents('A16'), '=1 * 2 / (3 * 4)')
|
|
self.assertEqual(sheet.getContents('A17'), '=3 ^ 4 ^ 2')
|
|
self.assertEqual(sheet.getContents('A18'), '=3 ^ (4 ^ 2)')
|
|
self.assertEqual(sheet.getContents('A19'), '=3 ^ 4 ^ 2')
|
|
self.assertEqual(sheet.getContents('A20'), '=3 + 4 + 2')
|
|
self.assertEqual(sheet.getContents('A21'), '=3 + 4 + 2')
|
|
self.assertEqual(sheet.getContents('A22'), '=3 + 4 + 2')
|
|
self.assertEqual(sheet.getContents('A23'), '=3 - 4 - 2')
|
|
self.assertEqual(sheet.getContents('A24'), '=3 - (4 - 2)')
|
|
self.assertEqual(sheet.getContents('A25'), '=3 - 4 - 2')
|
|
self.assertEqual(sheet.getContents('A26'), '=3 * 4 * 2')
|
|
self.assertEqual(sheet.getContents('A27'), '=3 * 4 * 2')
|
|
self.assertEqual(sheet.getContents('A28'), '=3 * 4 * 2')
|
|
self.assertEqual(sheet.getContents('A29'), '=3 / 4 / 2')
|
|
self.assertEqual(sheet.getContents('A30'), '=3 / (4 / 2)')
|
|
self.assertEqual(sheet.getContents('A31'), '=3 / 4 / 2')
|
|
self.assertEqual(sheet.getContents('A32'), '=pi * 3')
|
|
self.assertEqual(sheet.getContents('A33'), '=A32 / 3')
|
|
self.assertEqual(sheet.getContents('A34'), '=1 < 2 ? <<A>> : <<B>>')
|
|
self.assertEqual(sheet.getContents('A35'), '=min(A32:A33)')
|
|
self.assertEqual(sheet.getContents('A36'), '=(1 < 2 ? 0 : 1) * 3')
|
|
self.assertEqual(sheet.getContents('A37'), '=8 / (2 ^ 2 * 2)')
|
|
self.assertEqual(sheet.getContents('A38'), '=2 ^ 2 * 2 / 8')
|
|
self.assertEqual(sheet.getContents('A39'), '=2 ^ (2 * 2) / 8')
|
|
self.assertEqual(sheet.getContents('A40'), '=8 / 2 ^ (2 * 2)')
|
|
self.assertEqual(sheet.getContents('A41'), '=-1')
|
|
self.assertEqual(sheet.getContents('A42'), '=-1')
|
|
self.assertEqual(sheet.getContents('A43'), '=-(1 + 1)')
|
|
self.assertEqual(sheet.getContents('A44'), '=-(1 - 1)')
|
|
self.assertEqual(sheet.getContents('A45'), '=-(-1 + 1)')
|
|
self.assertEqual(sheet.getContents('A46'), '=-(-1 + -1)')
|
|
self.assertEqual(sheet.getContents('A47'), '=+1')
|
|
self.assertEqual(sheet.getContents('A48'), '=+1')
|
|
self.assertEqual(sheet.getContents('A49'), '=+(1 + 1)')
|
|
self.assertEqual(sheet.getContents('A50'), '=+(1 - 1)')
|
|
self.assertEqual(sheet.getContents('A51'), '=+(-1 + 1)')
|
|
self.assertEqual(sheet.getContents('A52'), '=+(-1 + -1)')
|
|
|
|
def testNumbers(self):
|
|
""" Test different numbers """
|
|
sheet = self.doc.addObject('Spreadsheet::Sheet','Spreadsheet')
|
|
sheet.set('A1', '1')
|
|
sheet.set('A2', '1.5')
|
|
sheet.set('A3', '.5')
|
|
sheet.set('A4', '1e2')
|
|
sheet.set('A5', '1E2')
|
|
sheet.set('A6', '1e-2')
|
|
sheet.set('A7', '1E-2')
|
|
sheet.set('A8', '1.5e2')
|
|
sheet.set('A9', '1.5E2')
|
|
sheet.set('A10', '1.5e-2')
|
|
sheet.set('A11', '1.5E-2')
|
|
sheet.set('A12', '.5e2')
|
|
sheet.set('A13', '.5E2')
|
|
sheet.set('A14', '.5e-2')
|
|
sheet.set('A15', '.5E-2')
|
|
sheet.set('A16', '1/1')
|
|
sheet.set('A17', '1/2')
|
|
sheet.set('A18', '2/4')
|
|
self.doc.recompute()
|
|
self.assertEqual(sheet.A1, 1)
|
|
self.assertEqual(sheet.A2, 1.5)
|
|
self.assertEqual(sheet.A3, 0.5)
|
|
self.assertEqual(sheet.A4, 1e2)
|
|
self.assertEqual(sheet.A5, 1e2)
|
|
self.assertEqual(sheet.A6, 1e-2)
|
|
self.assertEqual(sheet.A7, 1e-2)
|
|
self.assertEqual(sheet.A8, 1.5e2)
|
|
self.assertEqual(sheet.A9, 1.5e2)
|
|
self.assertEqual(sheet.A10, 1.5e-2)
|
|
self.assertEqual(sheet.A11, 1.5e-2)
|
|
self.assertEqual(sheet.A12, 0.5e2)
|
|
self.assertEqual(sheet.A13, 0.5e2)
|
|
self.assertEqual(sheet.A14, 0.5e-2)
|
|
self.assertEqual(sheet.A15, 0.5e-2)
|
|
self.assertEqual(sheet.A16, 1)
|
|
self.assertEqual(sheet.A17, 0.5)
|
|
self.assertEqual(sheet.A18, 0.5)
|
|
|
|
def testQuantitiesAndFractionsAsNumbers(self):
|
|
""" Test quantities and simple fractions as numbers """
|
|
sheet = self.doc.addObject('Spreadsheet::Sheet','Spreadsheet')
|
|
sheet.set('A1', '1mm')
|
|
sheet.set('A2', '1/2')
|
|
sheet.set('A3', '4mm/2')
|
|
sheet.set('A4', '2/mm')
|
|
sheet.set('A5', '4/2mm')
|
|
sheet.set('A6', '6mm/3s')
|
|
self.doc.recompute()
|
|
self.assertEqual(sheet.A1, Units.Quantity('1 mm'))
|
|
self.assertEqual(sheet.A2, 0.5)
|
|
self.assertEqual(sheet.A3, Units.Quantity('2 mm'))
|
|
self.assertEqual(sheet.A4, Units.Quantity('2 1/mm'))
|
|
self.assertEqual(sheet.A5, Units.Quantity('2 1/mm'))
|
|
self.assertEqual(sheet.A6, Units.Quantity('2 mm/s'))
|
|
|
|
def testRemoveRows(self):
|
|
""" Removing rows -- check renaming of internal cells """
|
|
sheet = self.doc.addObject('Spreadsheet::Sheet','Spreadsheet')
|
|
sheet.set('A3', '123')
|
|
sheet.set('A1', '=A3')
|
|
sheet.removeRows('2', 1)
|
|
self.assertEqual(sheet.getContents("A1"),"=A2")
|
|
|
|
def testInsertRows(self):
|
|
""" Inserting rows -- check renaming of internal cells """
|
|
sheet = self.doc.addObject('Spreadsheet::Sheet','Spreadsheet')
|
|
sheet.set('B1', '=B2')
|
|
sheet.set('B2', '124')
|
|
# Calling getContents() here activates ObjectIdentifier internal cache,
|
|
# which needs to be tested as well.
|
|
self.assertEqual(sheet.getContents("B1"),"=B2")
|
|
sheet.insertRows('2', 1)
|
|
self.assertEqual(sheet.getContents("B1"),"=B3")
|
|
|
|
def testIssue3225(self):
|
|
""" Inserting rows -- check renaming of internal cells """
|
|
sheet = self.doc.addObject('Spreadsheet::Sheet','Spreadsheet')
|
|
sheet.set('B2', '25')
|
|
sheet.set('B3', '=B2')
|
|
sheet.insertRows('2', 1)
|
|
self.assertEqual(sheet.getContents("B4"),"=B3")
|
|
|
|
def testRenameAlias(self):
|
|
""" Test renaming of alias1 to alias2 in a spreadsheet """
|
|
sheet = self.doc.addObject('Spreadsheet::Sheet','Spreadsheet')
|
|
sheet.set('B1', '124')
|
|
sheet.setAlias('B1', 'alias1')
|
|
sheet.set('B2', '=alias1')
|
|
self.doc.recompute()
|
|
self.assertEqual(sheet.get("alias1"), 124)
|
|
self.assertEqual(sheet.get("B1"), 124)
|
|
self.assertEqual(sheet.get("B2"), 124)
|
|
sheet.setAlias('B1', 'alias2')
|
|
self.doc.recompute()
|
|
self.assertEqual(sheet.get("alias2"), 124)
|
|
self.assertEqual(sheet.getContents("B2"),"=alias2")
|
|
|
|
def testRenameAlias2(self):
|
|
""" Test renaming of alias1 to alias2 in a spreadsheet, when referenced from another object """
|
|
sheet = self.doc.addObject('Spreadsheet::Sheet','Spreadsheet')
|
|
sheet.set('B1', '124')
|
|
sheet.setAlias('B1', 'alias1')
|
|
box = self.doc.addObject('Part::Box', 'Box')
|
|
box.setExpression('Length', 'Spreadsheet.alias1')
|
|
sheet.setAlias('B1', 'alias2')
|
|
self.assertEqual(box.ExpressionEngine[0][1], "Spreadsheet.alias2");
|
|
|
|
def testRenameAlias3(self):
|
|
""" Test renaming of document object referenced from another object """
|
|
sheet = self.doc.addObject('Spreadsheet::Sheet','Spreadsheet')
|
|
sheet.set('B1', '124')
|
|
sheet.setAlias('B1', 'alias1')
|
|
box = self.doc.addObject('Part::Box', 'Box')
|
|
box.setExpression('Length', 'Spreadsheet.alias1')
|
|
box2 = self.doc.addObject('Part::Box', 'Box')
|
|
box2.setExpression('Length', '<<Spreadsheet>>.alias1')
|
|
sheet.Label = "Params"
|
|
self.assertEqual(box.ExpressionEngine[0][1], "Spreadsheet.alias1");
|
|
self.assertEqual(box2.ExpressionEngine[0][1], "<<Params>>.alias1");
|
|
|
|
def testAlias(self):
|
|
""" Playing with aliases """
|
|
sheet = self.doc.addObject("Spreadsheet::Sheet","Calc")
|
|
sheet.setAlias("A1","Test")
|
|
self.assertEqual(sheet.getAlias("A1"),"Test")
|
|
|
|
sheet.set("A1","4711")
|
|
self.doc.recompute()
|
|
self.assertEqual(sheet.get("Test"),4711)
|
|
self.assertEqual(sheet.get("Test"),sheet.get("A1"))
|
|
|
|
def testAmbiguousAlias(self):
|
|
""" Try to set the same alias twice (bug #2402) """
|
|
sheet = self.doc.addObject("Spreadsheet::Sheet","Calc")
|
|
sheet.setAlias("A1","Test")
|
|
try:
|
|
sheet.setAlias("A2","Test")
|
|
self.fail("An ambiguous alias was set which shouldn't be allowed")
|
|
except Exception:
|
|
self.assertEqual(sheet.getAlias("A2"),None)
|
|
|
|
def testClearAlias(self):
|
|
""" This was causing a crash """
|
|
sheet = self.doc.addObject("Spreadsheet::Sheet","Calc")
|
|
sheet.setAlias("A1","Test")
|
|
sheet.setAlias("A1","")
|
|
self.assertEqual(sheet.getAlias("A1"),None)
|
|
|
|
def testSetInvalidAlias(self):
|
|
""" Try to use a cell address as alias name """
|
|
sheet = self.doc.addObject("Spreadsheet::Sheet","Calc")
|
|
try:
|
|
sheet.setAlias("A1","B1")
|
|
except Exception:
|
|
self.assertEqual(sheet.getAlias("A1"),None)
|
|
else:
|
|
self.fail("A cell address was used as alias which shouldn't be allowed")
|
|
|
|
def testSetInvalidAlias2(self):
|
|
""" Try to use a unit (reserved word) as alias name """
|
|
sheet = self.doc.addObject("Spreadsheet::Sheet","Calc")
|
|
try:
|
|
sheet.setAlias("A1","mA")
|
|
except Exception:
|
|
self.assertEqual(sheet.getAlias("A1"), None)
|
|
else:
|
|
self.fail("A unit (reserved word) was used as alias which shouldn't be allowed")
|
|
|
|
def testPlacementName(self):
|
|
""" Object name is equal to property name (bug #2389) """
|
|
if not FreeCAD.GuiUp:
|
|
return
|
|
|
|
import FreeCADGui
|
|
o = self.doc.addObject("Part::FeaturePython","Placement")
|
|
FreeCADGui.Selection.addSelection(o)
|
|
|
|
def testInvoluteGear(self):
|
|
""" Support of boolean or integer values """
|
|
try:
|
|
import InvoluteGearFeature
|
|
except ImportError:
|
|
return
|
|
InvoluteGearFeature.makeInvoluteGear('InvoluteGear')
|
|
self.doc.recompute()
|
|
sketch=self.doc.addObject('Sketcher::SketchObject','Sketch')
|
|
sketch.addGeometry(Part.LineSegment(v(0,0,0),v(10,10,0)),False)
|
|
sketch.addConstraint(Sketcher.Constraint('Distance',0,65.285388))
|
|
sketch.setExpression('Constraints[0]', 'InvoluteGear.NumberOfTeeth')
|
|
self.doc.recompute()
|
|
self.assertIn('Up-to-date',sketch.State)
|
|
|
|
def testSketcher(self):
|
|
""" Mixup of Label and Name (bug #2407)"""
|
|
sketch=self.doc.addObject('Sketcher::SketchObject','Sketch')
|
|
sheet=self.doc.addObject('Spreadsheet::Sheet','Spreadsheet')
|
|
sheet.setAlias('A1', 'Length')
|
|
self.doc.recompute()
|
|
sheet.set('A1', '47,11')
|
|
self.doc.recompute()
|
|
|
|
index=sketch.addGeometry(Part.LineSegment(v(0,0,0),v(10,10,0)),False)
|
|
sketch.addConstraint(Sketcher.Constraint('Distance',index,14.0))
|
|
self.doc.recompute()
|
|
sketch.setExpression('Constraints[0]', u'<<Spreadsheet>>.Length')
|
|
self.doc.recompute()
|
|
sheet.Label="Calc"
|
|
self.doc.recompute()
|
|
self.assertEqual(sketch.ExpressionEngine[0][1],'<<Calc>>.Length')
|
|
self.assertIn('Up-to-date',sketch.State)
|
|
|
|
def testCrossDocumentLinks(self):
|
|
""" Expressions across files are not saved (bug #2442) """
|
|
|
|
# Create a box
|
|
box = self.doc.addObject('Part::Box', 'Box')
|
|
|
|
# Create a second document with a cylinder
|
|
doc2 = FreeCAD.newDocument()
|
|
cylinder = doc2.addObject('Part::Cylinder', 'Cylinder')
|
|
cylinder.setExpression('Radius', 'cube#Cube.Height')
|
|
|
|
# Save and close first document
|
|
self.doc.saveAs(self.TempPath + os.sep + 'cube.fcstd')
|
|
FreeCAD.closeDocument(self.doc.Name)
|
|
|
|
# Save and close second document
|
|
doc2.saveAs(self.TempPath + os.sep + 'cylinder.fcstd')
|
|
FreeCAD.closeDocument(doc2.Name)
|
|
|
|
# Open both documents again
|
|
self.doc = FreeCAD.openDocument(self.TempPath + os.sep + 'cube.fcstd')
|
|
doc2 = FreeCAD.openDocument(self.TempPath + os.sep + 'cylinder.fcstd')
|
|
|
|
# Check reference between them
|
|
self.assertEqual(doc2.getObject('Cylinder').ExpressionEngine[0][1], 'cube#Cube.Height')
|
|
|
|
# Close second document
|
|
FreeCAD.closeDocument(doc2.Name)
|
|
|
|
def testMatrix(self):
|
|
''' Test Matrix/Vector/Placement/Rotation operations'''
|
|
|
|
def plm_equal(plm1, plm2):
|
|
from math import sqrt
|
|
qpair = zip(plm1.Rotation.Q, plm2.Rotation.Q)
|
|
qdiff1 = sqrt(sum([(v1 - v2)**2 for v1,v2 in qpair]))
|
|
qdiff2 = sqrt(sum([(v1 + v2)**2 for v1,v2 in qpair]))
|
|
return (plm1.Base-plm2.Base).Length < 1e-7 and (qdiff1 < 1e-12 or dqiff2 < 1e-12)
|
|
|
|
sheet = self.doc.addObject('Spreadsheet::Sheet','Spreadsheet')
|
|
|
|
mat = FreeCAD.Matrix()
|
|
mat.scale(2,1,2)
|
|
imat = mat.inverse()
|
|
|
|
vec = FreeCAD.Vector(2,1,2)
|
|
|
|
rot = FreeCAD.Rotation(FreeCAD.Vector(0,1,0),45)
|
|
irot = rot.inverted()
|
|
|
|
pla = FreeCAD.Placement(vec,rot)
|
|
ipla = pla.inverse()
|
|
|
|
sheet.set('A1', '=create(<<vector>>, 2, 1, 2)')
|
|
|
|
# different ways of calling mscale()
|
|
sheet.set('B1', '=mscale(create(<<matrix>>), A1)')
|
|
sheet.set('C1', '=mscale(create(<<matrix>>), tuple(2, 1, 2))')
|
|
sheet.set('A2', '=mscale(create(<<matrix>>), 2, 1, 2)')
|
|
|
|
# test matrix power operation
|
|
sheet.set('B2', '=A2^-2')
|
|
sheet.set('C2', '=A2^-1')
|
|
sheet.set('D2', '=A2^0')
|
|
sheet.set('E2', '=A2^1')
|
|
sheet.set('F2', '=A2^2')
|
|
sheet.set('G2', '=create(<<matrix>>, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)')
|
|
sheet.set('H2', '=G2^-1')
|
|
|
|
sheet.set('A3', '=create(<<rotation>>, create(<<vector>>, 0, 1, 0), 45)')
|
|
|
|
# test rotation power operation
|
|
sheet.set('B3', '=A3^-2')
|
|
sheet.set('C3', '=A3^-1')
|
|
sheet.set('D3', '=A3^0')
|
|
sheet.set('E3', '=A3^1')
|
|
sheet.set('F3', '=A3^2')
|
|
|
|
sheet.set('A4', '=create(<<placement>>, A1, A3)')
|
|
|
|
# test placement power operation
|
|
sheet.set('B4', '=A4^-2')
|
|
sheet.set('C4', '=A4^-1')
|
|
sheet.set('D4', '=A4^0')
|
|
sheet.set('E4', '=A4^1')
|
|
sheet.set('F4', '=A4^2')
|
|
|
|
# vector transformation with mixing matrix and placement and rotation
|
|
sheet.set('A5', '=A2*A3*A4*A1')
|
|
sheet.set('B5', '=B2*B4*B3*A1')
|
|
sheet.set('C5', '=C3*C2*C4*A1')
|
|
sheet.set('D5', '=D3*D4*D2*A1')
|
|
sheet.set('E5', '=E4*E2*E3*A1')
|
|
sheet.set('F5', '=F3*F4*F2*A1')
|
|
|
|
# inverse of the above transformation with power -1 and minvert()
|
|
sheet.set('A6', '=A4^-1 * minvert(A3) * A2^-1 * A5')
|
|
sheet.set('B6', '=minvert(B3) * B4^-1 * minvert(B2) * B5')
|
|
sheet.set('C6', '=C4^-1 * C2^-1 * C3^-1 * C5')
|
|
sheet.set('D6', '=minvert(D4*D2) * minvert(D3) * D5')
|
|
sheet.set('E6', '=(E2 * E3)^-1 * E4^-1 * E5')
|
|
sheet.set('F6', '=(F3*F4*F2)^-1 * F5')
|
|
|
|
self.doc.recompute()
|
|
|
|
self.assertEqual(sheet.A1,vec)
|
|
|
|
self.assertEqual(sheet.B1,mat)
|
|
self.assertEqual(sheet.C1,mat)
|
|
self.assertEqual(sheet.A2,mat)
|
|
|
|
self.assertEqual(sheet.B2,imat*imat)
|
|
self.assertEqual(sheet.B2,mat**-2)
|
|
self.assertEqual(sheet.C2,imat)
|
|
self.assertEqual(sheet.C2,mat**-1)
|
|
self.assertEqual(sheet.D2,FreeCAD.Matrix())
|
|
self.assertEqual(sheet.D2,mat**0)
|
|
self.assertEqual(sheet.E2,mat)
|
|
self.assertEqual(sheet.E2,mat**1)
|
|
self.assertEqual(sheet.F2,mat*mat)
|
|
self.assertEqual(sheet.F2,mat**2)
|
|
|
|
self.assertTrue(sheet.H2.startswith(u'ERR: Cannot invert singular matrix'))
|
|
|
|
self.assertEqual(sheet.A3,rot)
|
|
|
|
rtol = 1e-12
|
|
self.assertTrue(sheet.B3.isSame(irot*irot,rtol))
|
|
self.assertTrue(sheet.B3.isSame(rot**-2,rtol))
|
|
self.assertTrue(sheet.C3.isSame(irot,rtol))
|
|
self.assertTrue(sheet.C3.isSame(rot**-1,rtol))
|
|
self.assertTrue(sheet.D3.isSame(FreeCAD.Rotation(),rtol))
|
|
self.assertTrue(sheet.D3.isSame(rot**0,rtol))
|
|
self.assertTrue(sheet.E3.isSame(rot,rtol))
|
|
self.assertTrue(sheet.E3.isSame(rot**1,rtol))
|
|
self.assertTrue(sheet.F3.isSame(rot*rot,rtol))
|
|
self.assertTrue(sheet.F3.isSame(rot**2,rtol))
|
|
|
|
self.assertEqual(sheet.A4,pla)
|
|
|
|
self.assertTrue(plm_equal(sheet.B4,ipla*ipla))
|
|
self.assertTrue(plm_equal(sheet.B4,pla**-2))
|
|
self.assertTrue(plm_equal(sheet.C4,ipla))
|
|
self.assertTrue(plm_equal(sheet.C4,pla**-1))
|
|
self.assertTrue(plm_equal(sheet.D4,FreeCAD.Placement()))
|
|
self.assertTrue(plm_equal(sheet.D4,pla**0))
|
|
self.assertTrue(plm_equal(sheet.E4,pla))
|
|
self.assertTrue(plm_equal(sheet.E4,pla**1))
|
|
self.assertTrue(plm_equal(sheet.F4,pla*pla))
|
|
self.assertTrue(plm_equal(sheet.F4,pla**2))
|
|
|
|
tol = 1e-10
|
|
|
|
self.assertLess(sheet.A5.distanceToPoint(
|
|
sheet.A2.multiply(sheet.A3.Matrix).multiply(sheet.A4.Matrix).multVec(vec)),tol)
|
|
self.assertLess(sheet.B5.distanceToPoint(
|
|
sheet.B2.multiply(sheet.B4.Matrix).multiply(sheet.B3.Matrix).multVec(vec)),tol)
|
|
self.assertLess(sheet.C5.distanceToPoint(
|
|
sheet.C3.Matrix.multiply(sheet.C2).multiply(sheet.C4.Matrix).multVec(vec)),tol)
|
|
self.assertLess(sheet.D5.distanceToPoint(
|
|
sheet.D3.Matrix.multiply(sheet.D4.Matrix).multiply(sheet.D2).multVec(vec)),tol)
|
|
self.assertLess(sheet.E5.distanceToPoint(
|
|
sheet.E4.Matrix.multiply(sheet.E2).multiply(sheet.E3.Matrix).multVec(vec)),tol)
|
|
self.assertLess(sheet.F5.distanceToPoint(
|
|
sheet.F3.Matrix.multiply(sheet.F4.Matrix).multiply(sheet.F2).multVec(vec)),tol)
|
|
|
|
self.assertLess(sheet.A6.distanceToPoint(vec),tol)
|
|
self.assertLess(sheet.B6.distanceToPoint(vec),tol)
|
|
self.assertLess(sheet.C6.distanceToPoint(vec),tol)
|
|
self.assertLess(sheet.D6.distanceToPoint(vec),tol)
|
|
self.assertLess(sheet.E6.distanceToPoint(vec),tol)
|
|
self.assertLess(sheet.F6.distanceToPoint(vec),tol)
|
|
|
|
def testIssue3128(self):
|
|
""" Regression test for issue 3128; mod should work with arbitrary units for both arguments """
|
|
sheet = self.doc.addObject('Spreadsheet::Sheet','Spreadsheet')
|
|
sheet.set('A1', '=mod(7mm;3mm)')
|
|
sheet.set('A2', '=mod(7kg;3mm)')
|
|
self.doc.recompute()
|
|
self.assertEqual(sheet.A1, Units.Quantity('1'))
|
|
self.assertEqual(sheet.A2, Units.Quantity('1 kg/mm'))
|
|
|
|
def testIssue3363(self):
|
|
""" Regression test for issue 3363; Nested conditionals statement fails with additional conditional statement in false-branch"""
|
|
sheet = self.doc.addObject('Spreadsheet::Sheet','Spreadsheet')
|
|
sheet.set('A1', '1')
|
|
sheet.set('B1', '=A1==1?11:(A1==2?12:13)')
|
|
sheet.set('C1', '=A1==1?(A1==2?12:13) : 11')
|
|
self.doc.recompute()
|
|
|
|
# Save and close first document
|
|
self.doc.saveAs(self.TempPath + os.sep + 'conditionals.fcstd')
|
|
FreeCAD.closeDocument(self.doc.Name)
|
|
|
|
# Open documents again
|
|
self.doc = FreeCAD.openDocument(self.TempPath + os.sep + 'conditionals.fcstd')
|
|
|
|
sheet = self.doc.getObject('Spreadsheet')
|
|
self.assertEqual(sheet.getContents('B1'), '=A1 == 1 ? 11 : (A1 == 2 ? 12 : 13)')
|
|
self.assertEqual(sheet.getContents('C1'), '=A1 == 1 ? (A1 == 2 ? 12 : 13) : 11')
|
|
|
|
def testIssue3432(self):
|
|
""" Regression test for issue 3432; numbers with units are ignored from aggregates"""
|
|
sheet = self.doc.addObject('Spreadsheet::Sheet','Spreadsheet')
|
|
sheet.set('A1', '1mm')
|
|
sheet.set('B1', '2mm')
|
|
sheet.set('C1', '=max(A1:B1;3mm)')
|
|
self.doc.recompute()
|
|
self.assertEqual(sheet.get('C1'), Units.Quantity('3 mm'))
|
|
|
|
def testIssue4156(self):
|
|
""" Regression test for issue 4156; necessarily use of leading '=' to enter an expression, creates inconsistent behavior depending on the spreadsheet state"""
|
|
sheet = self.doc.addObject('Spreadsheet::Sheet','Spreadsheet')
|
|
sheet.set('A3', 'A1')
|
|
sheet.set('A1', '1000')
|
|
self.doc.recompute()
|
|
sheet.set('A3', '')
|
|
sheet.set('A3', 'A1')
|
|
self.assertEqual(sheet.getContents('A3'), 'A1')
|
|
|
|
def testInsertRowsAlias(self):
|
|
""" Regression test for issue 4429; insert rows to sheet with aliases"""
|
|
sheet = self.doc.addObject('Spreadsheet::Sheet','Spreadsheet')
|
|
sheet.set('A3', '1')
|
|
sheet.setAlias('A3', 'alias1')
|
|
sheet.set('A4', '=alias1 + 1')
|
|
sheet.setAlias('A4', 'alias2')
|
|
sheet.set('A5', '=alias2 + 1')
|
|
self.doc.recompute()
|
|
sheet.insertRows('1', 1)
|
|
self.doc.recompute()
|
|
self.assertEqual(sheet.A6, 3)
|
|
|
|
def testInsertColumnsAlias(self):
|
|
""" Regression test for issue 4429; insert columns to sheet with aliases"""
|
|
sheet = self.doc.addObject('Spreadsheet::Sheet','Spreadsheet')
|
|
sheet.set('C1', '1')
|
|
sheet.setAlias('C1', 'alias1')
|
|
sheet.set('D1', '=alias1 + 1')
|
|
sheet.setAlias('D1', 'alias2')
|
|
sheet.set('E1', '=alias2 + 1')
|
|
self.doc.recompute()
|
|
sheet.insertColumns('A', 1)
|
|
self.doc.recompute()
|
|
self.assertEqual(sheet.F1, 3)
|
|
|
|
def testRemoveRowsAlias(self):
|
|
""" Regression test for issue 4429; remove rows from sheet with aliases"""
|
|
sheet = self.doc.addObject('Spreadsheet::Sheet','Spreadsheet')
|
|
sheet.set('A3', '1')
|
|
sheet.setAlias('A3', 'alias1')
|
|
sheet.set('A5', '=alias1 + 1')
|
|
sheet.setAlias('A5', 'alias2')
|
|
sheet.set('A4', '=alias2 + 1')
|
|
self.doc.recompute()
|
|
sheet.removeRows('1', 1)
|
|
self.doc.recompute()
|
|
self.assertEqual(sheet.A3, 3)
|
|
|
|
def testRemoveRowsAliasReuseName(self):
|
|
""" Regression test for issue 4492; deleted aliases remains in database"""
|
|
sheet = self.doc.addObject('Spreadsheet::Sheet','Spreadsheet')
|
|
sheet.setAlias('B2', 'test')
|
|
self.doc.recompute()
|
|
sheet.removeRows('2', 1)
|
|
sheet.setAlias('B3','test')
|
|
|
|
def testRemoveColumnsAlias(self):
|
|
""" Regression test for issue 4429; remove columns from sheet with aliases"""
|
|
sheet = self.doc.addObject('Spreadsheet::Sheet','Spreadsheet')
|
|
sheet.set('C1', '1')
|
|
sheet.setAlias('C1', 'alias1')
|
|
sheet.set('E1', '=alias1 + 1')
|
|
sheet.setAlias('E1', 'alias2')
|
|
sheet.set('D1', '=alias2 + 1')
|
|
self.doc.recompute()
|
|
sheet.removeColumns('A', 1)
|
|
self.doc.recompute()
|
|
self.assertEqual(sheet.C1, 3)
|
|
|
|
def testRemoveColumnsAliasReuseName(self):
|
|
""" Regression test for issue 4492; deleted aliases remains in database"""
|
|
sheet = self.doc.addObject('Spreadsheet::Sheet','Spreadsheet')
|
|
sheet.setAlias('B2', 'test')
|
|
self.doc.recompute()
|
|
sheet.removeColumns('B', 1)
|
|
sheet.setAlias('C3','test')
|
|
|
|
def testUndoAliasCreationReuseName(self):
|
|
""" Test deleted aliases by undo remains in database"""
|
|
sheet = self.doc.addObject('Spreadsheet::Sheet','Spreadsheet')
|
|
|
|
self.doc.UndoMode = 1
|
|
self.doc.openTransaction("create alias")
|
|
sheet.setAlias('B2', 'test')
|
|
self.doc.commitTransaction()
|
|
self.doc.recompute()
|
|
|
|
self.doc.undo()
|
|
self.doc.recompute()
|
|
sheet.setAlias('C3','test')
|
|
|
|
def testCrossLinkEmptyPropertyName(self):
|
|
# https://forum.freecadweb.org/viewtopic.php?f=3&t=58603
|
|
base = FreeCAD.newDocument("base")
|
|
sheet = base.addObject('Spreadsheet::Sheet','Spreadsheet')
|
|
sheet.setAlias('A1', 'x')
|
|
sheet.set('x', '42mm')
|
|
base.recompute()
|
|
|
|
square = FreeCAD.newDocument("square")
|
|
body = square.addObject('PartDesign::Body','Body')
|
|
box = square.addObject('PartDesign::AdditiveBox','Box')
|
|
body.addObject(box)
|
|
box.Length = 10.00
|
|
box.Width = 10.00
|
|
box.Height = 10.00
|
|
square.recompute()
|
|
|
|
basePath = self.TempPath + os.sep + 'base.FCStd'
|
|
base.saveAs(basePath)
|
|
squarePath = self.TempPath + os.sep + 'square.FCStd'
|
|
square.saveAs(squarePath)
|
|
|
|
base.save()
|
|
square.save()
|
|
|
|
FreeCAD.closeDocument(square.Name)
|
|
FreeCAD.closeDocument(base.Name)
|
|
|
|
##
|
|
## preparation done
|
|
base = FreeCAD.openDocument(basePath)
|
|
square = FreeCAD.openDocument(squarePath)
|
|
|
|
square.Box.setExpression('Length', u'base#Spreadsheet.x')
|
|
square.recompute()
|
|
|
|
square.save()
|
|
base.save()
|
|
FreeCAD.closeDocument(square.Name)
|
|
FreeCAD.closeDocument(base.Name)
|
|
|
|
def testExpressionWithAlias(self):
|
|
# https://forum.freecadweb.org/viewtopic.php?p=564502#p564502
|
|
ss1 = self.doc.addObject("Spreadsheet::Sheet", "Input")
|
|
ss1.setAlias('A1', 'one')
|
|
ss1.setAlias('A2', 'two')
|
|
ss1.set("A1","1")
|
|
ss1.set("A2","2")
|
|
self.doc.recompute()
|
|
|
|
ss2 = self.doc.addObject("Spreadsheet::Sheet", "Output")
|
|
ss2.set("A1","=Input.A1 + Input.A2")
|
|
ss2.set("A2","=Input.one + Input.two")
|
|
ss2.set("A3","=<<Input>>.A1 + <<Input>>.A2")
|
|
ss2.set("A4","=<<Input>>.one + <<Input>>.two")
|
|
self.doc.recompute()
|
|
|
|
self.assertEqual(ss2.get("A1"), 3)
|
|
self.assertEqual(ss2.get("A2"), 3)
|
|
self.assertEqual(ss2.get("A3"), 3)
|
|
self.assertEqual(ss2.get("A4"), 3)
|
|
|
|
project_path = self.TempPath + os.sep + 'alias.FCStd'
|
|
self.doc.saveAs(project_path)
|
|
FreeCAD.closeDocument(self.doc.Name)
|
|
self.doc = FreeCAD.openDocument(project_path)
|
|
ss1 = self.doc.Input
|
|
ss2 = self.doc.Output
|
|
|
|
self.assertEqual(ss2.get("A1"), 3)
|
|
self.assertEqual(ss2.get("A2"), 3)
|
|
self.assertEqual(ss2.get("A3"), 3)
|
|
self.assertEqual(ss2.get("A4"), 3)
|
|
|
|
ss1.set("A1","2")
|
|
self.doc.recompute()
|
|
|
|
self.assertEqual(ss1.get("A1"), 2)
|
|
self.assertEqual(ss1.get("one"), 2)
|
|
|
|
self.assertEqual(ss2.get("A1"), 4)
|
|
self.assertEqual(ss2.get("A2"), 4)
|
|
self.assertEqual(ss2.get("A3"), 4)
|
|
self.assertEqual(ss2.get("A4"), 4)
|
|
|
|
def testIssue6844(self):
|
|
body = self.doc.addObject("App::FeaturePython", "Body")
|
|
body.addProperty("App::PropertyEnumeration", "Configuration")
|
|
body.Configuration = ["Item1", "Item2", "Item3"]
|
|
|
|
sheet = self.doc.addObject("Spreadsheet::Sheet", "Sheet")
|
|
sheet.addProperty("App::PropertyString", "A2")
|
|
sheet.A2 = "Item2"
|
|
sheet.addProperty("App::PropertyEnumeration", "body")
|
|
sheet.body = ["Item1", "Item2", "Item3"]
|
|
|
|
sheet.setExpression(".body.Enum", "cells[<<A2:|>>]")
|
|
sheet.setExpression(".cells.Bind.B1.ZZ1", "tuple(.cells; <<B>> + str(hiddenref(Body.Configuration) + 2); <<ZZ>> + str(hiddenref(Body.Configuration) + 2))")
|
|
|
|
self.doc.recompute()
|
|
self.doc.UndoMode = 0
|
|
self.doc.removeObject("Body")
|
|
sheet.clearAll()
|
|
|
|
def testIssue6840(self):
|
|
body = self.doc.addObject("App::FeaturePython", "Body")
|
|
body.addProperty("App::PropertyEnumeration", "Configuration")
|
|
body.Configuration = ["Item1", "Item2", "Item3"]
|
|
|
|
sheet = self.doc.addObject("Spreadsheet::Sheet", "Sheet")
|
|
sheet.addProperty("App::PropertyString", "A2")
|
|
sheet.A2 = "Item2"
|
|
sheet.addProperty("App::PropertyEnumeration", "body")
|
|
sheet.body = ["Item1", "Item2", "Item3"]
|
|
|
|
sheet.setExpression(".body.Enum", "cells[<<A2:|>>]")
|
|
sheet.setExpression(".cells.Bind.B1.ZZ1", "tuple(.cells; <<B>> + str(hiddenref(Body.Configuration) + 2); <<ZZ>> + str(hiddenref(Body.Configuration) + 2))")
|
|
|
|
self.doc.recompute()
|
|
self.doc.clearDocument()
|
|
|
|
def testFixPR6843(self):
|
|
sheet = self.doc.addObject("Spreadsheet::Sheet", "Sheet")
|
|
sheet.set("A5", "a")
|
|
sheet.set("A6", "b")
|
|
self.doc.recompute()
|
|
sheet.insertRows("6", 1)
|
|
self.doc.recompute()
|
|
self.assertEqual(sheet.A5, "a")
|
|
self.assertEqual(sheet.A7, "b")
|
|
with self.assertRaises(AttributeError):
|
|
self.assertEqual(sheet.A6, "")
|
|
|
|
def testBindAcrossSheets(self):
|
|
ss1 = self.doc.addObject("Spreadsheet::Sheet", "Spreadsheet1")
|
|
ss2 = self.doc.addObject("Spreadsheet::Sheet", "Spreadsheet2")
|
|
ss2.set("B1", "B1")
|
|
ss2.set("B2", "B2")
|
|
ss2.set("C1", "C1")
|
|
ss2.set("C2", "C2")
|
|
ss2.set("D1", "D1")
|
|
ss2.set("D2", "D2")
|
|
|
|
ss1.setExpression('.cells.Bind.A3.C4', 'tuple(Spreadsheet2.cells, <<B1>>, <<D2>>)')
|
|
self.doc.recompute()
|
|
|
|
self.assertEqual(ss1.A3, ss2.B1)
|
|
self.assertEqual(ss1.A4, ss2.B2)
|
|
self.assertEqual(ss1.B3, ss2.C1)
|
|
self.assertEqual(ss1.B4, ss2.C2)
|
|
self.assertEqual(ss1.C3, ss2.D1)
|
|
self.assertEqual(ss1.C4, ss2.D2)
|
|
|
|
self.assertEqual(len(ss1.ExpressionEngine), 1)
|
|
ss1.setExpression('.cells.Bind.A3.C4', None)
|
|
self.doc.recompute()
|
|
|
|
def testBindHiddenRefAcrossSheets(self):
|
|
ss1 = self.doc.addObject("Spreadsheet::Sheet", "Spreadsheet1")
|
|
ss2 = self.doc.addObject("Spreadsheet::Sheet", "Spreadsheet2")
|
|
ss2.set("B1", "B1")
|
|
ss2.set("B2", "B2")
|
|
ss2.set("C1", "C1")
|
|
ss2.set("C2", "C2")
|
|
ss2.set("D1", "D1")
|
|
ss2.set("D2", "D2")
|
|
|
|
self.doc.recompute()
|
|
ss1.setExpression('.cells.Bind.A3.C4', None)
|
|
ss1.setExpression('.cells.BindHiddenRef.A3.C4', 'hiddenref(tuple(Spreadsheet2.cells, <<B1>>, <<D2>>))')
|
|
self.doc.recompute()
|
|
|
|
ss1.recompute() # True
|
|
self.assertEqual(ss1.A3, ss2.B1)
|
|
|
|
ss1.setExpression('.cells.Bind.A3.C4', None)
|
|
ss1.setExpression('.cells.BindHiddenRef.A3.C4', None)
|
|
self.doc.recompute()
|
|
self.assertEqual(len(ss1.ExpressionEngine), 0)
|
|
|
|
def testMergeCells(self):
|
|
ss1 = self.doc.addObject("Spreadsheet::Sheet", "Spreadsheet1")
|
|
ss1.mergeCells('A1:B4')
|
|
ss1.mergeCells('C1:D4')
|
|
self.doc.recompute()
|
|
ss1.set("B1", "fail")
|
|
self.doc.recompute()
|
|
with self.assertRaises(AttributeError):
|
|
self.assertEqual(ss1.B1, "fail")
|
|
|
|
def testMergeCellsAndBind(self):
|
|
ss1 = self.doc.addObject("Spreadsheet::Sheet", "Spreadsheet1")
|
|
ss1.mergeCells('A1:B1')
|
|
ss1.setExpression('.cells.Bind.A1.A1', 'tuple(.cells, <<A2>>, <<A2>>)')
|
|
ss1.set("A2", "test")
|
|
self.doc.recompute()
|
|
self.assertEqual(ss1.A1, ss1.A2)
|
|
ss1.set("B1", "fail")
|
|
self.doc.recompute()
|
|
with self.assertRaises(AttributeError):
|
|
self.assertEqual(ss1.B1, "fail")
|
|
|
|
def tearDown(self):
|
|
#closing doc
|
|
FreeCAD.closeDocument(self.doc.Name)
|