Domanda

I'm using xlwt to create tables in excel. In excel there is a feature format as table which makes the table have an automatic filters for each column. Is there a way to do it using python?

È stato utile?

Soluzione 2

OK, after searching the web, I realized that with xlwt it's not possible to do it, but with XlsxWriter it's possible and very easy and convenient.

Altri suggerimenti

You can do it with Pandas also. Here's an example:

import pandas as pd

df = pd.DataFrame({
    'city': ['New York', 'London', 'Prague'], 
    'population': [19.5, 7.4, 1.3], 
    'date_of_birth': ['1625', '43', 'early 8th century'],
    'status_of_magnetism': ['nice to visit', 'nice to visit', 'definetely MUST visit']
})

# initialize ExcelWriter and set df as output
writer = pd.ExcelWriter(r'D:\temp\sample.xlsx', engine='xlsxwriter') 
df.to_excel(writer, sheet_name='Cities', index=False)

# worksheet is an instance of Excel sheet "Cities" - used for inserting the table
worksheet = writer.sheets['Cities']
# workbook is an instance of the whole book - used i.e. for cell format assignment 
workbook = writer.book

Then define format of a cell (i.e. rotate text, set vertical and horizontal align) via workbook.add_format

header_cell_format = workbook.add_format()
header_cell_format.set_rotation(90)
header_cell_format.set_align('center')
header_cell_format.set_align('vcenter')

Then...

# create list of dicts for header names 
#  (columns property accepts {'header': value} as header name)
col_names = [{'header': col_name} for col_name in df.columns]

# add table with coordinates: first row, first col, last row, last col; 
#  header names or formatting can be inserted into dict 
worksheet.add_table(0, 0, df.shape[0], df.shape[1]-1, {
    'columns': col_names,
    # 'style' = option Format as table value and is case sensitive 
    # (look at the exact name into Excel)
    'style': 'Table Style Medium 10'
})

Alternatively worksheet.add_table('A1:D{}'.format(shape[0]), {...}) can be used, but for df with more columns or shifted start position the AA, AB,... combinations would have to be calculated (instead of "D")

And finally - the following loop rewrites headers and applies header_cell_format. Which we already did in worksheet.add_table(...) and so it looks redundant, but this is a way to use Excel's AutoFit option - without this all header cells would have default width (or cell height if you use the 90degs rotation) and so either not the whole content would be visble, or set_shrink() would have to be applied...and then the content wouldn't be readable :). (tested in Office 365)

# skip the loop completly if AutoFit for header is not needed
for i, col in enumerate(col_names):
    # apply header_cell_format to cell on [row:0, column:i] and write text value from col_names in
    worksheet.write(0, i, col['header'], header_cell_format)

# save writer object and created Excel file with data from DataFrame     
writer.save()

If you want to apply table formatting to a dataframe that you output to excel using XlsxWriter use the docs at https://xlsxwriter.readthedocs.io/example_pandas_table.html Per the comment recommendation.

The following was my original less elegant solution format_tbl:

import pandas as pd

def format_tbl(writer, sheet_name, df):
    outcols = df.columns
    if len(outcols) > 25:
        raise ValueError('table width out of range for current logic')
    tbl_hdr = [{'header':c} for c in outcols]
    bottom_num = len(df)+1
    right_letter = chr(65-1+len(outcols))
    tbl_corner = right_letter + str(bottom_num)

    worksheet = writer.sheets[sheet_name]
    worksheet.add_table('A1:' + tbl_corner,  {'columns':tbl_hdr})


df = pd.DataFrame({
    'city': ['New York', 'London', 'Prague'], 
    'population': [19.5, 7.4, 1.3], 
    'date_of_birth': ['1625', '43', 'early 8th century'],
    'status_of_magnetism': ['nice to visit', 'nice to visit', 'definetely MUST visit']
})

fn_out='blah.xlsx'
with pd.ExcelWriter(fn_out, mode='w', engine='xlsxwriter') as writer: 
    sheet_name='xxx'
    df.to_excel(writer, sheet_name=sheet_name, index=False)
    format_tbl(writer, sheet_name, df)



Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top