151 votes

Existe-t-il un moyen d'ajuster automatiquement la largeur des colonnes Excel avec pandas.ExcelWriter ?

On me demande de générer des rapports Excel. J'utilise actuellement pandas de manière assez intensive pour mes données, et j'aimerais donc naturellement utiliser la méthode pandas.ExcelWriter pour générer ces rapports. Cependant, la largeur fixe des colonnes pose un problème.

Le code que j'ai jusqu'à présent est assez simple. Disons que j'ai un cadre de données appelé 'df' :

writer = pd.ExcelWriter(excel_file_path, engine='openpyxl')
df.to_excel(writer, sheet_name="Summary")

J'ai examiné le code de pandas, et je ne vois pas vraiment d'options pour définir la largeur des colonnes. Existe-t-il un moyen de faire en sorte que les colonnes s'adaptent automatiquement aux données ? Ou y a-t-il quelque chose que je puisse faire après coup dans le fichier xlsx pour ajuster la largeur des colonnes ?

(J'utilise la bibliothèque OpenPyXL, et je génère des fichiers .xlsx - si cela fait une différence).

Merci.

3voto

Ssubrat Rrudra Points 88
import re
import openpyxl
..
for col in _ws.columns:
    max_lenght = 0
    print(col[0])
    col_name = re.findall('\w\d', str(col[0]))
    col_name = col_name[0]
    col_name = re.findall('\w', str(col_name))[0]
    print(col_name)
    for cell in col:
        try:
            if len(str(cell.value)) > max_lenght:
                max_lenght = len(cell.value)
        except:
            pass
    adjusted_width = (max_lenght+2)
    _ws.column_dimensions[col_name].width = adjusted_width

2voto

mouwsy Points 323

Oui, il y a quelque chose que vous pouvez faire après coup dans le fichier xlsx pour ajuster la largeur des colonnes. Utilisez xlwings pour autofit colonnes. C'est une solution assez simple, voir les six dernières lignes du code de l'exemple. L'avantage de cette procédure est que vous n'avez pas à vous soucier de la taille de la police, du type de police ou de quoi que ce soit d'autre. Exigence : Installation d'Excel.

import pandas as pd
import xlwings as xw

file_path = r"report_formtting_files.xlsx"

df = pd._testing.makeDataFrame()

writer = pd.ExcelWriter(file_path, engine="xlsxwriter")
df.to_excel(writer, sheet_name="Sheet1", index=False)
workbook = writer.book
worksheet1 = writer.sheets["Sheet1"]
num_format = workbook.add_format({"num_format": '#,##0.00'})
worksheet1.set_column("A:D", cell_format=num_format)
writer.close()

# Autofit all columns with xlwings.
with xw.App(visible=False) as app:
    wb = xw.Book(file_path)

    for ws in wb.sheets:
        ws.autofit(axis="columns")

    wb.save(file_path)
    wb.close()

1voto

Ashish Jith Points 61

La solution la plus simple est de spécifier la largeur de la colonne dans la méthode set_column.

    for worksheet in writer.sheets.values():
        worksheet.set_column(0,last_column_value, required_width_constant)

1voto

gijsvandinther Points 11

Cette fonction fonctionne pour moi, elle corrige également la largeur de l'index.

def write_to_excel(writer, X, sheet_name, sep_only=False):
    #writer=writer object
    #X=dataframe
    #sheet_name=name of sheet
    #sep_only=True:write only as separate excel file, False: write as sheet to the writer object
    if sheet_name=="": 
        print("specify sheet_name!")
    else:
        X.to_excel(f"{output_folder}{prefix_excel_save}_{sheet_name}.xlsx")
        if not sep_only: 
            X.to_excel(writer, sheet_name=sheet_name)

            #fix column widths
            worksheet = writer.sheets[sheet_name]  # pull worksheet object
            for idx, col in enumerate(X.columns):  # loop through all columns
                series = X[col]
                max_len = max((
                    series.astype(str).map(len).max(),  # len of largest item
                    len(str(series.name))  # len of column name/header
                    )) + 1  # adding a little extra space
                worksheet.set_column(idx+1, idx+1, max_len)  # set column width (=1 because index = 1)

            #fix index width
            max_len=pd.Series(X.index.values).astype(str).map(len).max()+1
            worksheet.set_column(0, 0, max_len)

        if sep_only: 
            print(f'{sheet_name} is written as seperate file')
        else:
            print(f'{sheet_name} is written as seperate file')
            print(f'{sheet_name} is written as sheet')
    return writer

exemple d'appel :

writer = write_to_excel(writer, dataframe, "Statistical_Analysis")

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X