def checkMax(row, col_name, arg, *args):
    """
    row[col_name] must be less than or equal to arg.
    else, return error message.
    """
    cell_value = row[col_name]
    if not cell_value:
        return None
    elif isinstance(cell_value, float):
        if np.isnan(cell_value):
            return None
    try:
        arg_val = float(arg)
    except ValueError:
        if arg in row.index:
            arg_val = row[arg]
        else:
            return None
    if cb.is_null(arg_val):
        return None
    #arg = float(arg)
    try:
        if float(cell_value) <= float(arg_val):
            return None
        else:
            return "{} ({}) must be <= {} ({})".format(str(cell_value), col_name, str(arg_val), str(arg))
    # this happens when the value isn't a float (an error which will be caught elsewhere)
    except ValueError:
        return None
row[col_name] must be less than or equal to arg.
    else, return error message.