Video: Interval Filter using PyXLL
The first part of the video shows the function in use, filtering a composite range of user-entered values.
The second part of the video is more interesting.
I have a list of 10 random probabilities which are generated using a PyXLL function, mix_func(). The list is returned to the spreadsheet — as a single object — in a single cell.
Then the filter_int_compare function returns only those values between 0.0 and 0.5, ‘CO’.
Notice that the dynamic ranges are dynamically formatted, using PyXLL.
Here are introductory screenshots.



These would have engineering use in filtering a list of values that fit (or do not fit) within a given range.
I start with a straightforward (naive) approach to writing the function and then add a more useful (maybe more sophisticated) approach to writing it.
I offer a look at my code.
Please note that the code shown is neither succinct nor final — it is written in a ‘long-hand’ expository form, with the intent being that it can be easily followed.
NaiveThe first function is a boolean PyXLL function that returns a literal (closed, closed) interval check.
The second function is a boolean PyXLL function that does the logical complement of the literal (closed, closed) interval check.
def between_compare(bracket_number1, bracket_number2, number_entry):
@xl_func(“float bracket_number1, float bracket_number2, float number_entry: bool”)
def not_between_compare(bracket_number1, bracket_number2, number_entry):
from numbers import Number
@xl_func("float bracket_number1, float bracket_number2, float number_entry: bool")
def between_compare(bracket_number1, bracket_number2, number_entry):
"""NAIVE Given an Excel cell, filter the numeric value, retaining only if within the interval
Args:
bracket_number1: one extreme value in the interval
bracket_number2: the other extreme value in the interval
number_entry: a single Excel cell to be filtered
Returns:
Value if it meets the comparison specification. Otherwise, the string 'empty'
"""
if not (isinstance(bracket_number1, Number)
and isinstance(bracket_number2, Number)
and isinstance(number_entry, Number)):
raise ValueError("Expected all numeric values")
if (bracket_number1 < number_entry < bracket_number2 or
bracket_number2 < number_entry < bracket_number1):
return True
else:
return False
@xl_func("float bracket_number1, float bracket_number2, float number_entry: bool")
def not_between_compare(bracket_number1, bracket_number2, number_entry):
return not between_compare(bracket_number1, bracket_number2, number_entry)
"""complement of NAIVE between_compare()"""
~~~
Maybe more sophisticated
I added an input parameter to allow closed or open intervals (any combination).
Then I built a function abbreviation: ‘interval_compare’ is abbreviated to ‘int_comp’.
Then I built a function, ‘filter_int_comp’ incorporating sorted results and/or unique results.
Guide to interval types:
The interval type may be specified using either the character designation or the symbolic designation.
| Character | Symbol | Meaning |
| CC | [] | closed at each end |
| CO | [) | closed at small number open at large number |
| OC | (] | open at small number closed at large number |
| OO | () | open at each end |
def interval_compare(bracket_number1, bracket_number2, interval_type, number_entry):
@xl_func(“float bracket_number1, float bracket_number2, str interval_type, var number_entry_range[][], bool sortQ, bool reverseQ, bool unique_onlyQ: var”, volatile=False)
def filter_int_comp(bracket_number1, bracket_number2, interval_type, number_entry_range, sortQ=False, reverseQ=False, unique_onlyQ=False):
@xl_func(“int x: object”)
def mix_func(x):
@xl_func(“object x: var”)
def unmix_func(x):
from numbers import Number
@xl_func("float bracket_number1, float bracket_number2, str interval_type, float number_entry: bool", volatile=False)
def interval_compare(bracket_number1, bracket_number2, interval_type, number_entry):
"""Given an Excel cell, filter the numeric value, retaining only if within the interval
Args:
bracket_number1: one extreme value in the interval
bracket_number2: the other extreme value in the interval
interval_type: type of interval closure (closed/open and combinations)
number_entry: a single Excel cell to be filtered
sortQ: a boolean, True indicates an ascending sort
reverseQ: a boolean, True indicates sorted descending
unique_onlyQ: a boolean, indicates removal of duplicates
Returns:
List of values meeting the comparison specification, if any. Otherwise, the string 'empty'
Raises:
ValueError("Expected 2 numeric values and string interval_type")
"""
if not (isinstance(bracket_number1, Number)
and isinstance(bracket_number2, Number)
and isinstance(interval_type, str)):
raise ValueError("Expected 2 numeric values and string interval_type")
ivupper = interval_type.upper()
if not(ivupper in ['[]','[)','(]','()','CC','CO','OC','OO']):
raise ValueError("Interval_type must be \n['[]','[)','(]','()','CC','CO','OC','OO']")
if ivupper in ['[]','CC']:
if (bracket_number1 < number_entry < bracket_number2 or
bracket_number2 < number_entry < bracket_number1):
return True
elif ivupper in ['[)','CO']:
if (bracket_number1 < number_entry <= bracket_number2 or
bracket_number2 < number_entry <= bracket_number1):
return True
elif ivupper in ['(]','OC']:
if (bracket_number1 <= number_entry < bracket_number2 or
bracket_number2 <= number_entry < bracket_number1):
return True
elif ivupper in ['()','OO']:
if (bracket_number1 <= number_entry <= bracket_number2 or
bracket_number2 <= number_entry <= bracket_number1):
return True
else:
return False
# this is a boolean PyXLL function suitable for a single value as input
@xl_func("float bracket_number1, float bracket_number2, str interval_type, float number_entry: bool", volatile=False)
def int_comp(bracket_number1, bracket_number2, interval_type, number_entry):
return interval_compare(bracket_number1, bracket_number2, interval_type, number_entry)
"""alias for interval_compare()"""
# this is a boolean PyXLL function suitable for a range of values as input
@xl_func("float bracket_number1, float bracket_number2, str interval_type, var number_entry_range[][], bool sortQ, bool reverseQ, bool unique_onlyQ: var", volatile=False)
def filter_int_comp(bracket_number1, bracket_number2, interval_type, number_entry_range, sortQ=False, reverseQ=False, unique_onlyQ=False):
"""Given an Excel range, filter the numeric values, retaining only those that are within the interval
Args:
bracket_number1: one extreme value in the interval
bracket_number2: the other extreme value in the interval
interval_type: type of interval closure (closed/open and combinations)
number_entry_range: an Excel RANGE to be filtered
sortQ: a boolean, True indicates sorted ascending
reverseQ: a boolean, True indicates sorted descending
unique_onlyQ: a boolean, indicates removal of duplicates
Returns:
List of values meeting the comparison specification, if any. Otherwise, the string 'empty'
Raises:
string 'Error in multiple range input': If the function fails.
"""
ret = []
rg_flattened = itertools.chain.from_iterable(number_entry_range)
for e in rg_flattened:
e_value = None
if e == '' or e is None:
# no conversion
e_value = ''
else:
try:
e_value = e.Value
except:
e_value = e
if type(e_value) == float:
comparison = int_comp(bracket_number1, bracket_number2, interval_type, e_value)
if comparison:
ret.append(e_value)
if unique_onlyQ:
ret = list(set(ret))
if sortQ:
ret.sort()
if reverseQ:
ret.reverse()
if len(ret) == 0:
return "empty"
else:
return ret
from random import random
# @xl_func("int x: object")
@xl_func("int x: object")
def mix_func(x):
"""Return a list of x random values
Args:
x: integer number of values to produce
Returns:
an x-length list of random numbers
Raises:
zero, if x == 0
"Function error" if function fails
Disclosure:
Lifted from Page 56 of https://www.pyxll.com/docs/pyxll-5.5.4.pdf
"""
try:
if x == 0:
# returned as a number to Excel
return 0
# return a list of values as an 'object'
array = [random() for i in range(x)]
return array
except:
return "Function error"
@xl_func("object x: var")
def unmix_func(x):
"""Return a list of lists
Args:
x: a 1-dimensional list object
Returns:
a list of lists (suitable for PyXLL)
Raises:
"empty" if function fails
"""
try:
return [[e] for e in x]
except:
return 'empty'
~~~
Here is the video.
What is the probability that you will have
… or exactly 14 heads out of a total of 20 coin tosses?


