Skip to content

Commit

Permalink
feat(logic), #27: Add OR, XOR, AND, NOT functions.
Browse files Browse the repository at this point in the history
  • Loading branch information
vinci1it2000 committed Apr 24, 2019
1 parent e4411b6 commit e756b79
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 3 deletions.
32 changes: 29 additions & 3 deletions formulas/functions/logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@
"""
Python equivalents of logical Excel functions.
"""
from . import wrap_ufunc, Error, flatten, get_error, value_return
import functools
import numpy as np
from . import (
wrap_ufunc, Error, flatten, get_error, value_return, wrap_func, raise_errors
)

FUNCTIONS = {}

Expand Down Expand Up @@ -71,6 +75,28 @@ def xswitch(val, *args):
'function': wrap_ufunc(
xswitch, input_parser=lambda *a: a, return_func=value_return,
check_error=lambda first, *a: get_error(first),
),
'solve_cycle': solve_cycle
)
}


def xand(logical, *logicals, func=np.logical_and.reduce):
check, arr = lambda x: not raise_errors(x) and not isinstance(x, str), []
for a in (logical,) + logicals:
v = list(flatten(a, check=check))
arr.extend(v)
if not v and not isinstance(a, np.ndarray):
return Error.errors['#VALUE!']
return func(arr) if arr else Error.errors['#VALUE!']


FUNCTIONS['AND'] = {'function': wrap_func(xand)}
FUNCTIONS['OR'] = {'function': wrap_func(
functools.partial(xand, func=np.logical_or.reduce)
)}
FUNCTIONS['_XLFN.XOR'] = FUNCTIONS['XOR'] = {'function': wrap_func(
functools.partial(xand, func=np.logical_xor.reduce)
)}

FUNCTIONS['NOT'] = {'function': wrap_ufunc(
np.logical_not, input_parser=lambda *a: a, return_func=value_return
)}
8 changes: 8 additions & 0 deletions test/test_cell.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ def inp_ranges(*rng):
@ddt.ddt
class TestCell(unittest.TestCase):
@ddt.idata((
('A1', '=OR({0,0,0},FALSE,"0")', {}, '<Ranges>(A1)=[[#VALUE!]]'),
('A1', '=OR(B1,FALSE)', {'B1':[['0']]}, '<Ranges>(A1)=[[False]]'),
('A1', '=OR("0",FALSE)', {'B1':[['0']]}, '<Ranges>(A1)=[[#VALUE!]]'),
('A1', '=XOR({0,0,0},FALSE,FALSE)', {}, '<Ranges>(A1)=[[False]]'),
('A1', '=XOR({0,0},FALSE,FALSE)', {}, '<Ranges>(A1)=[[False]]'),
('A1', '=XOR(TRUE,TRUE)', {}, '<Ranges>(A1)=[[False]]'),
('A1', '=OR(TRUE,#REF!,"0")', {}, '<Ranges>(A1)=[[#REF!]]'),
('A1', '=OR(FALSE,"0",#REF!)', {}, '<Ranges>(A1)=[[#VALUE!]]'),
('A1', '=INDEX({2,3;4,5},FALSE,"0")', {}, '<Ranges>(A1)=[[2]]'),
('A1', '=INDEX({2,3;4,5}, -1)', {}, '<Ranges>(A1)=[[#VALUE!]]'),
('A1', '=INDEX(B1:C1, 1, 1)', {'B1:C1': [[sh.EMPTY, 2]]},
Expand Down
Binary file modified test/test_files/circular.xlsx
Binary file not shown.
Binary file modified test/test_files/test.xlsx
Binary file not shown.

0 comments on commit e756b79

Please sign in to comment.