def test_multiply(self): self.assertEqual(RangeCore.multiply(2, 2), 4) self.assertEqual(RangeCore.multiply(1, 0), 0) self.assertIsInstance(RangeCore.multiply(ExcelError('#VALUE'), 1), ExcelError) self.assertIsInstance(RangeCore.multiply(1, ExcelError('#VALUE')), ExcelError)
def test_divide(self): self.assertEqual(RangeCore.divide(2, 2), 1) self.assertIsInstance(RangeCore.divide(1, 0), ExcelError) self.assertIsInstance(RangeCore.divide(ExcelError('#VALUE'), 1), ExcelError) self.assertIsInstance(RangeCore.divide(1, ExcelError('#VALUE')), ExcelError)
def test_xirr_errors(self): self.assertIsInstance( xirr([-100, 30, 30, 30, ExcelError('#NUM')], [43571, 43721, 43871, 44021, 44171], 0), ExcelError) self.assertIsInstance( xirr([-100, 30, 30, 30, 30], [43571, 43721, 43871, 44021, ExcelError('#NUM')], 0), ExcelError)
def find_associated_value(ref, item): # This function is ALMOST equivalent to RangeCore.find_associated_cell, but retrieves the value and not the Cell. row, col = ref if isinstance(item, RangeCore): try: if (item.length) == 0: # if a Range is empty, it means normally that all its cells are empty item_value = 0 elif item.type == "vertical": if item.__cellmap is not None: item_value = item[(row, item.origin[1])].value if (row, item.origin[1]) in item else None else: item_value = item[(row, item.origin[1])] if (row, item.origin[1]) in item else None elif item.type == "horizontal": if item.__cellmap is not None: try: item_value = item[(item.origin[0], col)].value if (item.origin[0], col) in item else None except: raise Exception else: item_value = item[(item.origin[0], col)] if (item.origin[0], col) in item else None else: raise ExcelError('#VALUE!', 'cannot use find_associated_value on %s' % item.type) except ExcelError as e: raise Exception('First argument of Range operation is not valid: ' + e.value) elif item is None: item_value = 0 else: item_value = item return item_value
def apply_all(func, first, second, ref = None): # This function applies a function to range operands, for all the cells in the Ranges function = func_dict[func] # Here, the first arg of RangeCore() has little importance: TBC if isinstance(first, RangeCore) and isinstance(second, RangeCore): if first.length != second.length: raise ExcelError('#VALUE!', 'apply_all must have 2 Ranges of identical length') vals = [function( x.value if type(x) == Cell else x, y.value if type(y) == Cell else y ) for x,y in zip(first.cells, second.cells)] return RangeCore(first.addresses, vals, nrows = first.nrows, ncols = first.ncols) elif isinstance(first, RangeCore): vals = [function( x.value if type(x) == Cell else x, second ) for x in first.cells] return RangeCore(first.addresses, vals, nrows = first.nrows, ncols = first.ncols) elif isinstance(second, RangeCore): vals = [function( first, x.value if type(x) == Cell else x ) for x in second.cells] return RangeCore(second.addresses, vals, nrows = second.nrows, ncols = second.ncols) else: return function(first, second)
def is_inferior_or_equal(a, b): try: a = check_value(a) b = check_value(b) return a < b or is_almost_equal(a, b) except Exception as e: return ExcelError('#N/A', e)
def is_not_equal(a, b): try: if not isinstance(a, (str, unicode)): a = check_value(a) if not isinstance(a, (str, unicode)): b = check_value(b) return a != b except Exception as e: return ExcelError('#N/A', e)
def add(a, b): try: a = check_value(a) b = check_value(b) if isinstance(a, str) or isinstance(b, str): a = str(a) b = str(b) return a + b except Exception as e: return ExcelError('#N/A', e)
def is_equal(a, b): try: if not isinstance(a, (str, unicode)): a = check_value(a) if not isinstance(b, (str, unicode)): b = check_value(b) return is_almost_equal(a, b, precision = 0.00001) except Exception as e: return ExcelError('#N/A', e)
def check_value(a): if isinstance(a, ExcelError): return a elif isinstance(a, str) and a in ErrorCodes: return ExcelError(a) try: # This is to avoid None or Exception returned by Range operations if float(a) or isinstance(a, (unicode, str)): return a else: return 0 except: if a == 'True': return True elif a == 'False': return False else: return 0
def is_strictly_inferior(a, b): try: return check_value(a) < check_value(b) except Exception as e: return ExcelError('#N/A', e)
def divide(a, b): try: return float(check_value(a)) / float(check_value(b)) except Exception as e: return ExcelError('#DIV/0!', e)
def multiply(a, b): try: return check_value(a) * check_value(b) except Exception as e: return ExcelError('#N/A', e)
def minus(a, b = None): # b is not used, but needed in the signature. Maybe could be better try: return -check_value(a) except Exception as e: return ExcelError('#N/A', e)
def substract(a, b): try: return check_value(a) - check_value(b) except Exception as e: return ExcelError('#N/A', e)
def add(a, b): try: return check_value(a) + check_value(b) except Exception as e: return ExcelError('#N/A', e)
def test_npv_errors(self): self.assertIsInstance(npv(0.06, [1, 2, ExcelError('#NUM')]), ExcelError) self.assertIsInstance(npv(ExcelError('#NUM'), [1, 2, 3]), ExcelError)
def test_power(self): self.assertEqual(RangeCore.power(2, 2), 4) self.assertIsInstance(RangeCore.power(ExcelError('#VALUE'), 1), ExcelError) self.assertIsInstance(RangeCore.power(1, ExcelError('#VALUE')), ExcelError)
def power(a, b): try: return pow(float(check_value(a)), float(check_value(b))) except Exception as e: return ExcelError('#VALUE!', e)
def test_irr_errors(self): self.assertIsInstance(irr( [-100, 39, 59, 55, ExcelError('#NUM')], 0), ExcelError)