Return a rows.Table created from imported XLS file.

def import_from_xls(
    filename_or_fobj,
    sheet_name=None,
    sheet_index=0,
    start_row=None,
    start_column=None,
    end_row=None,
    end_column=None,
    *args,
    **kwargs
):
    """Return a rows.Table created from imported XLS file."""

    source = Source.from_file(filename_or_fobj, mode="rb", plugin_name="xls")
    source.fobj.close()
    book = xlrd.open_workbook(
        source.uri, formatting_info=True, logfile=open(os.devnull, mode="w")
    )

    if sheet_name is not None:
        sheet = book.sheet_by_name(sheet_name)
    else:
        sheet = book.sheet_by_index(sheet_index)
    # TODO: may re-use Excel data types

    # Get header and rows
    # xlrd library reads rows and columns starting from 0 and ending on
    # sheet.nrows/ncols - 1. rows accepts the same pattern
    # The xlrd library reads rows and columns starting from 0 and ending on
    # sheet.nrows/ncols - 1. rows also uses 0-based indexes, so no
    # transformation is needed
    min_row, min_column = get_table_start(sheet)
    max_row, max_column = sheet.nrows - 1, sheet.ncols - 1
    # TODO: consider adding a parameter `ignore_padding=True` and when it's
    # True, consider `start_row` starting from `min_row` and `start_column`
    # starting from `min_col`.
    start_row = max(start_row if start_row is not None else min_row, min_row)
    end_row = min(end_row if end_row is not None else max_row, max_row)
    start_column = max(
        start_column if start_column is not None else min_column, min_column
    )
    end_column = min(end_column if end_column is not None else max_column, max_column)

    table_rows = [
        [
            cell_value(sheet, row_index, column_index)
            for column_index in range(start_column, end_column + 1)
        ]
        for row_index in range(start_row, end_row + 1)
    ]

    meta = {"imported_from": "xls", "source": source, "name": sheet.name}
    return create_table(table_rows, meta=meta, *args, **kwargs)