2021-06-22 15:12:25 +00:00
|
|
|
from .info import lazy_value_or_error, is_error
|
2020-07-27 18:57:36 +00:00
|
|
|
from usertypes import AltText # pylint: disable=unused-import,import-error
|
|
|
|
|
|
|
|
|
|
|
|
def AND(logical_expression, *logical_expressions):
|
|
|
|
"""
|
|
|
|
Returns True if all of the arguments are logically true, and False if any are false.
|
|
|
|
Same as `all([value1, value2, ...])`.
|
|
|
|
|
|
|
|
>>> AND(1)
|
|
|
|
True
|
|
|
|
>>> AND(0)
|
|
|
|
False
|
|
|
|
>>> AND(1, 1)
|
|
|
|
True
|
|
|
|
>>> AND(1,2,3,4)
|
|
|
|
True
|
|
|
|
>>> AND(1,2,3,4,0)
|
|
|
|
False
|
|
|
|
"""
|
|
|
|
return all((logical_expression,) + logical_expressions)
|
|
|
|
|
|
|
|
|
|
|
|
def FALSE():
|
|
|
|
"""
|
|
|
|
Returns the logical value `False`. You may also use the value `False` directly. This
|
|
|
|
function is provided primarily for compatibility with other spreadsheet programs.
|
|
|
|
|
|
|
|
>>> FALSE()
|
|
|
|
False
|
|
|
|
"""
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
def IF(logical_expression, value_if_true, value_if_false):
|
|
|
|
"""
|
|
|
|
Returns one value if a logical expression is `True` and another if it is `False`.
|
|
|
|
|
|
|
|
The equivalent Python expression is:
|
|
|
|
```
|
|
|
|
value_if_true if logical_expression else value_if_false
|
|
|
|
```
|
|
|
|
|
|
|
|
Since Grist supports multi-line formulas, you may also use Python blocks such as:
|
|
|
|
```
|
|
|
|
if logical_expression:
|
|
|
|
return value_if_true
|
|
|
|
else:
|
|
|
|
return value_if_false
|
|
|
|
```
|
|
|
|
|
|
|
|
NOTE: Grist follows Excel model by only evaluating one of the value expressions, by
|
|
|
|
automatically wrapping the expressions to use lazy evaluation. This allows `IF(False, 1/0, 1)`
|
|
|
|
to evaluate to `1` rather than raise an exception.
|
|
|
|
|
|
|
|
>>> IF(12, "Yes", "No")
|
|
|
|
'Yes'
|
|
|
|
>>> IF(None, "Yes", "No")
|
|
|
|
'No'
|
|
|
|
>>> IF(True, 0.85, 0.0)
|
|
|
|
0.85
|
|
|
|
>>> IF(False, 0.85, 0.0)
|
|
|
|
0.0
|
|
|
|
|
|
|
|
More tests:
|
2021-06-22 15:12:25 +00:00
|
|
|
>>> IF(True, lambda: (1/0), lambda: (17)) # doctest: +IGNORE_EXCEPTION_DETAIL
|
2020-07-27 18:57:36 +00:00
|
|
|
Traceback (most recent call last):
|
|
|
|
...
|
|
|
|
ZeroDivisionError: integer division or modulo by zero
|
|
|
|
>>> IF(False, lambda: (1/0), lambda: (17))
|
|
|
|
17
|
|
|
|
"""
|
|
|
|
return lazy_value(value_if_true) if logical_expression else lazy_value(value_if_false)
|
|
|
|
|
|
|
|
|
|
|
|
def IFERROR(value, value_if_error=""):
|
|
|
|
"""
|
|
|
|
Returns the first argument if it is not an error value, otherwise returns the second argument if
|
|
|
|
present, or a blank if the second argument is absent.
|
|
|
|
|
|
|
|
NOTE: Grist handles values that raise an exception by wrapping them to use lazy evaluation.
|
|
|
|
|
|
|
|
>>> IFERROR(float('nan'), "**NAN**")
|
|
|
|
'**NAN**'
|
|
|
|
>>> IFERROR(17.17, "**NAN**")
|
|
|
|
17.17
|
|
|
|
>>> IFERROR("Text")
|
|
|
|
'Text'
|
|
|
|
>>> IFERROR(AltText("hello"))
|
|
|
|
''
|
|
|
|
|
|
|
|
More tests:
|
|
|
|
>>> IFERROR(lambda: (1/0.1), "X")
|
|
|
|
10.0
|
|
|
|
>>> IFERROR(lambda: (1/0.0), "X")
|
|
|
|
'X'
|
|
|
|
>>> IFERROR(lambda: AltText("A"), "err")
|
|
|
|
'err'
|
|
|
|
>>> IFERROR(lambda: None, "err")
|
|
|
|
|
|
|
|
>>> IFERROR(lambda: foo.bar, 123)
|
|
|
|
123
|
|
|
|
>>> IFERROR(lambda: "test".bar(), 123)
|
|
|
|
123
|
|
|
|
>>> IFERROR(lambda: "test".bar())
|
|
|
|
''
|
|
|
|
>>> IFERROR(lambda: "test".upper(), 123)
|
|
|
|
'TEST'
|
|
|
|
"""
|
|
|
|
value = lazy_value_or_error(value)
|
|
|
|
return value if not is_error(value) else value_if_error
|
|
|
|
|
|
|
|
|
|
|
|
def NOT(logical_expression):
|
|
|
|
"""
|
|
|
|
Returns the opposite of a logical value: `NOT(True)` returns `False`; `NOT(False)` returns
|
|
|
|
`True`. Same as `not logical_expression`.
|
|
|
|
|
|
|
|
>>> NOT(123)
|
|
|
|
False
|
|
|
|
>>> NOT(0)
|
|
|
|
True
|
|
|
|
"""
|
|
|
|
return not logical_expression
|
|
|
|
|
|
|
|
|
|
|
|
def OR(logical_expression, *logical_expressions):
|
|
|
|
"""
|
|
|
|
Returns True if any of the arguments is logically true, and false if all of the
|
|
|
|
arguments are false.
|
|
|
|
Same as `any([value1, value2, ...])`.
|
|
|
|
|
|
|
|
>>> OR(1)
|
|
|
|
True
|
|
|
|
>>> OR(0)
|
|
|
|
False
|
|
|
|
>>> OR(1, 1)
|
|
|
|
True
|
|
|
|
>>> OR(0, 1)
|
|
|
|
True
|
|
|
|
>>> OR(0, 0)
|
|
|
|
False
|
|
|
|
>>> OR(0,False,0.0,"",None)
|
|
|
|
False
|
|
|
|
>>> OR(0,None,3,0)
|
|
|
|
True
|
|
|
|
"""
|
|
|
|
return any((logical_expression,) + logical_expressions)
|
|
|
|
|
|
|
|
|
|
|
|
def TRUE():
|
|
|
|
"""
|
|
|
|
Returns the logical value `True`. You may also use the value `True` directly. This
|
|
|
|
function is provided primarily for compatibility with other spreadsheet programs.
|
|
|
|
|
|
|
|
>>> TRUE()
|
|
|
|
True
|
|
|
|
"""
|
|
|
|
return True
|
|
|
|
|
|
|
|
def lazy_value(value):
|
|
|
|
"""
|
|
|
|
Evaluates a lazy value by calling it when it's a callable, or returns it unchanged otherwise.
|
|
|
|
"""
|
|
|
|
return value() if callable(value) else value
|