Source code for formulas.functions.info

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
#
# Copyright 2016-2023 European Commission (JRC);
# Licensed under the EUPL (the 'Licence');
# You may not use this work except in compliance with the Licence.
# You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl

"""
Python equivalents of information Excel functions.
"""
import functools
import numpy as np
import schedula as sh
from . import (
    wrap_ranges_func, Error, Array, XlError, wrap_func, is_number, flatten,
    _text2num
)

FUNCTIONS = {}


[docs] class IsErrArray(Array): _default = False _collapse_value = True
[docs] def iserr(val): try: b = np.asarray([isinstance(v, XlError) and v is not Error.errors['#N/A'] for v in val.ravel().tolist()], bool) b.resize(val.shape) return b.view(IsErrArray) except AttributeError: # val is not an array. return iserr(np.asarray([[val]], object))[0][0].view(IsErrArray)
FUNCTIONS['ISERR'] = wrap_ranges_func(iserr)
[docs] class IsErrorArray(IsErrArray): _default = True
[docs] def iserror(val, check=lambda x: isinstance(x, XlError), array=IsErrorArray): try: b = np.asarray([check(v) for v in val.ravel().tolist()], bool) b.resize(val.shape) return b.view(array) except AttributeError: # val is not an array. return iserror( np.asarray([[val]], object), check, array )[0][0].view(array)
[docs] class IsNumberArray(IsErrArray): _collapse_value = False
[docs] class IsNaArray(IsErrArray): _collapse_value = False _default = True
[docs] def isna(value): return value == Error.errors['#N/A']
[docs] def xiseven_odd(number, odd=False): number = tuple(flatten(number, None)) if len(number) > 1 or isinstance(number[0], bool): return Error.errors['#VALUE!'] number = number[0] if isinstance(number, XlError): return number if number is sh.EMPTY: number = 0 v = int(_text2num(number)) % 2 return v != 0 if odd else v == 0
FUNCTIONS['ISODD'] = wrap_ranges_func(functools.partial(xiseven_odd, odd=True)) FUNCTIONS['ISEVEN'] = wrap_ranges_func(xiseven_odd) FUNCTIONS['ISERROR'] = wrap_ranges_func(iserror) FUNCTIONS['ISNUMBER'] = wrap_ranges_func(functools.partial( iserror, check=lambda x: is_number(x, xl_return=False), array=IsNumberArray )) FUNCTIONS['ISBLANK'] = wrap_ranges_func(functools.partial( iserror, check=lambda x: x is sh.EMPTY, array=IsNumberArray )) FUNCTIONS['ISTEXT'] = wrap_ranges_func(functools.partial( iserror, check=lambda x: isinstance(x, str) and not isinstance(x, sh.Token), array=IsNumberArray )) FUNCTIONS['ISNONTEXT'] = wrap_ranges_func(functools.partial( iserror, check=lambda x: not isinstance(x, str) or isinstance(x, sh.Token), array=IsErrorArray )) FUNCTIONS['ISLOGICAL'] = wrap_ranges_func(functools.partial( iserror, check=lambda x: isinstance(x, bool), array=IsNumberArray )) FUNCTIONS['ISNA'] = wrap_ranges_func(functools.partial( iserror, check=isna, array=IsNaArray ))
[docs] def xna(): return Error.errors['#N/A']
FUNCTIONS['NA'] = wrap_func(xna)