Home » excel » python – Read drop down values from excel using pandas

python – Read drop down values from excel using pandas

Posted by: admin May 14, 2020 Leave a comment

Questions:

I have a excel with a drop down cell. I have been trying to read the excel dropdown list but it only reads the selected option.

enter image description here

import pandas

df = pandas.read_excel("BQA.xlsx", header=0)
df.columns = df.columns.str.strip()

print(df)

Output:

 Empty DataFrame
 Columns: [Column 1, Column 2, Column 3, Column 4, yes]
 Index: []

Expected Output:

Empty DataFrame
Columns: [Column 1, Column 2, Column 3, Column 4, [yes, no, yes1, no1]]
Index: []
How to&Answers:

You could use openpyxl to extract the dropdown information: it’s stored in the data_validations for a given sheet. For example (newlines inserted for readability):

>>> wb = openpyxl.load_workbook("dropdown.xlsx")
>>> ws = wb["Sheet1"]
>>> ws.data_validations
<openpyxl.worksheet.datavalidation.DataValidationList object>
Parameters:
disablePrompts=None, xWindow=None, yWindow=None, count=1, 
dataValidation=[<openpyxl.worksheet.datavalidation.DataValidation object>
Parameters:
sqref=<MultiCellRange [E1]>, showErrorMessage=True, showDropDown=None, showInputMessage=True, 
allowBlank=False, errorTitle=None, error=None, promptTitle=None, prompt=None,
type='list', errorStyle=None, imeMode=None, operator=None, formula1='$L$4:$L$7', formula2=None]

I’m not going to handle all the possible cases, so this is just an example of the sorts of things you could do, but something like

def read_with_dropdown(book_name, sheet_name, range_str):
    wb = openpyxl.load_workbook(book_name)
    ws = wb[sheet_name]
    data = [[cell.value for cell in row] for row in ws[range_str]]

    validations = ws.data_validations.dataValidation
    for validation in validations:
        ranges = validation.sqref.ranges
        if len(ranges) != 1:
            raise NotImplementedError
        if validation.type == 'list':
            list_cells = ws[validation.formula1]
            values = [cell.value for cell_row in list_cells for cell in cell_row]
        else:
            raise NotImplementedError
        bounds = ranges[0].bounds
        try:
            data[bounds[1]-1][bounds[0]-1] = values
        except IndexError:
            pass
    return data

gives me (again, newlines inserted):

>>> data = read_with_dropdown("dropdown.xlsx", "Sheet1", "A1:E5")
>>> data
[['Column 1', 'Column 2', 'Column 3', 'Column 4', ['yes', 'no', 'yes1', 'no1']],
 [None, None, None, None, None],
 [None, None, None, None, None],
 [None, None, None, None, None],
 [None, None, None, None, None]]