Подтвердить что ты не робот

Есть ли способ автоматической настройки ширины столбцов Excel с помощью pandas.ExcelWriter?

Мне предлагается создать несколько отчетов Excel. В настоящее время я использую pandas довольно сильно для своих данных, поэтому, естественно, я хотел бы использовать метод pandas.ExcelWriter для генерации этих отчетов. Однако фиксированные ширины столбцов являются проблемой.

Код, который я до сих пор достаточно прост. Скажем, у меня есть dataframe, называемый 'df':

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

Я просматривал код pandas, и я не вижу никаких параметров для установки ширины столбцов. Есть ли трюк в юниверсе, чтобы сделать его таким, чтобы столбцы автоматически настраивались на данные? Или я могу что-то сделать после факта в файл xlsx, чтобы настроить ширину столбцов?

(Я использую библиотеку OpenPyXL и генерирую файлы .xlsx - если это имеет значение.)

Спасибо.

4b9b3361

Ответ 1

Вдохновленный user6178746 ответ, у меня есть следующее:

# Given a dict of dataframes, for example:
# dfs = {'gadgets': df_gadgets, 'widgets': df_widgets}

writer = pd.ExcelWriter(filename, engine='xlsxwriter')
for sheetname, df in dfs.items():  # loop through 'dict' of dataframes
    df.to_excel(writer, sheet_name=sheetname)  # send df to writer
    worksheet = writer.sheets[sheetname]  # pull worksheet object
    for idx, col in enumerate(df):  # loop through all columns
        series = df[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, idx, max_len)  # set column width
writer.save()

Ответ 2

Вероятно, нет автоматического способа сделать это прямо сейчас, но поскольку вы используете openpyxl, следующая строка (адаптирована из другого ответа пользователя Bufke на как это сделать вручную) позволяет вам указывать нормальное значение (в ширине символов):

writer.sheets['Summary'].column_dimensions['A'].width = 15

Ответ 3

Я публикую это, потому что столкнулся с той же проблемой и обнаружил, что в официальной документации для Xlsxwriter и pandas эта функция по-прежнему указана как неподдерживаемая. Я взломал решение, которое решило проблему, с которой я столкнулся. Я просто перебираю каждый столбец и использую worksheet.set_column, чтобы установить ширину столбца == максимальную длину содержимого этого столбца.

Однако, одно важное замечание. Это решение не соответствует заголовкам столбцов, просто значениям столбцов. Это должно быть легко изменить, если вам нужно вместо этого подгонять заголовки. Надеюсь, это поможет кому-то :)

import pandas as pd
import sqlalchemy as sa
import urllib


read_server = 'serverName'
read_database = 'databaseName'

read_params = urllib.quote_plus("DRIVER={SQL Server};SERVER="+read_server+";DATABASE="+read_database+";TRUSTED_CONNECTION=Yes")
read_engine = sa.create_engine("mssql+pyodbc:///?odbc_connect=%s" % read_params)

#Output some SQL Server data into a dataframe
my_sql_query = """ SELECT * FROM dbo.my_table """
my_dataframe = pd.read_sql_query(my_sql_query,con=read_engine)

#Set destination directory to save excel.
xlsFilepath = r'H:\my_project' + "\\" + 'my_file_name.xlsx'
writer = pd.ExcelWriter(xlsFilepath, engine='xlsxwriter')

#Write excel to file using pandas to_excel
my_dataframe.to_excel(writer, startrow = 1, sheet_name='Sheet1', index=False)

#Indicate workbook and worksheet for formatting
workbook = writer.book
worksheet = writer.sheets['Sheet1']

#Iterate through each column and set the width == the max length in that column. A padding length of 2 is also added.
for i, col in enumerate(my_dataframe.columns):
    # find length of column i
    column_len = my_dataframe[col].astype(str).str.len().max()
    # Setting the length if the column header is larger
    # than the max column value length
    column_len = max(column_len, len(col)) + 2
    # set the column length
    worksheet.set_column(i, i, column_len)
writer.save()

Ответ 4

Есть хороший пакет, который я начал использовать недавно, называется StyleFrame.

он получает DataFrame и позволяет очень легко его стилизовать...

по умолчанию ширина столбцов регулируется автоматически.

например:

from StyleFrame import StyleFrame
import pandas as pd

df = pd.DataFrame({'aaaaaaaaaaa': [1, 2, 3], 
                   'bbbbbbbbb': [1, 1, 1],
                   'ccccccccccc': [2, 3, 4]})
excel_writer = StyleFrame.ExcelWriter('example.xlsx')
sf = StyleFrame(df)
sf.to_excel(excel_writer=excel_writer, row_to_add_filters=0,
            columns_and_rows_to_freeze='B2')
excel_writer.save()

Вы также можете изменить ширину столбцов:

sf.set_column_width(columns=['aaaaaaaaaaa', 'bbbbbbbbb'],
                    width=35.3)


ОБНОВИТЬ

В версии 1.4 аргумент best_fit был добавлен в StyleFrame.to_excel. Смотрите документацию.

Ответ 5

Используя pandas и xlsxwriter, вы можете выполнить свою задачу, приведенный ниже код будет отлично работать в Python 3.x. Для получения дополнительной информации о работе с XlsxWriter с пандами эта ссылка может быть полезна https://xlsxwriter.readthedocs.io/working_with_pandas.html

import pandas as pd
writer = pd.ExcelWriter(excel_file_path, engine='xlsxwriter')
df.to_excel(writer, sheet_name="Summary")
workbook = writer.book
worksheet = writer.sheets["Summary"]
#set the column width as per your requirement
worksheet.set_column('A:A', 25)
writer.save()

Ответ 6

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

Ответ 7

Я обнаружил, что было бы более полезно настроить столбец на основе заголовка столбца, а не содержимого столбца.

Используя df.columns.values.tolist(), я генерирую список заголовков столбцов и использую длины этих заголовков, чтобы определить ширину столбцов.

Смотрите полный код ниже:

import pandas as pd
import xlsxwriter

writer = pd.ExcelWriter(filename, engine='xlsxwriter')
df.to_excel(writer, index=False, sheet_name=sheetname)

workbook = writer.book # Access the workbook
worksheet= writer.sheets[sheetname] # Access the Worksheet

header_list = df.columns.values.tolist() # Generate list of headers
for i in range(0, len(header_list)):
    worksheet.set_column(i, i, len(header_list[i])) # Set column widths based on len(header)

writer.save() # Save the excel file

Ответ 8

Самое простое решение - указать ширину столбца в методе set_column.

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

Ответ 9

Объединение других ответов и комментариев, а также поддержка мультииндексов:

def autosize_excel_columns(worksheet, df):
  autosize_excel_columns_df(worksheet, df.index.to_frame())
  autosize_excel_columns_df(worksheet, df, offset=df.index.nlevels)

def autosize_excel_columns_df(worksheet, df, offset=0):
  for idx, col in enumerate(df):
    series = df[col]
    max_len = max((
      series.astype(str).map(len).max(),
      len(str(series.name))
    )) + 1
    worksheet.set_column(idx+offset, idx+offset, max_len)

sheetname=...
df.to_excel(writer, sheet_name=sheetname, freeze_panes=(df.columns.nlevels, df.index.nlevels))
worksheet = writer.sheets[sheetname]
autosize_excel_columns(worksheet, df)
writer.save()