Мне предлагается создать несколько отчетов Excel. В настоящее время я использую pandas довольно сильно для своих данных, поэтому, естественно, я хотел бы использовать метод pandas.ExcelWriter для генерации этих отчетов. Однако фиксированные ширины столбцов являются проблемой.
Код, который я до сих пор достаточно прост. Скажем, у меня есть dataframe, называемый 'df':
writer = pd.ExcelWriter(excel_file_path)
df.to_excel(writer, sheet_name="Summary")
Я просматривал код pandas, и я не вижу никаких параметров для установки ширины столбцов. Есть ли трюк в юниверсе, чтобы сделать его таким, чтобы столбцы автоматически настраивались на данные? Или я могу что-то сделать после факта в файл xlsx, чтобы настроить ширину столбцов?
(Я использую библиотеку OpenPyXL и генерирую файлы .xlsx - если это имеет значение.)
Спасибо.
Вероятно, нет автоматического способа сделать это прямо сейчас, но поскольку вы используете openpyxl, следующая строка (адаптирована из другого ответа пользователя Bufke на как это сделать вручную) позволяет вам указывать нормальное значение (в ширине символов):
writer.sheets['Summary'].column_dimensions['A'].width = 15
Вдохновленный 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()
Есть хороший пакет, который я начал использовать недавно, называемый 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)
best_fit
. Кроме того, когда я попробовал это, я получил очень плохие результаты .
Я публикую это, потому что я просто столкнулся с той же проблемой и обнаружил, что официальная документация для Xlsxwriter и pandas по-прежнему содержит перечисленные функции как неподдерживаемые. Я взломал решение, которое решило проблему, с которой я столкнулся. Я в основном просто перебираю каждый столбец и использую workheet.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']
#Find the number of columns to iterate through
columns = len(my_dataframe.columns)
column_series = pd.Series(range(columns))
column_list = column_series.tolist()
#Iterate through each column and set the width == the max length in that column.
for i in column_list:
#find length of column i
column_len = my_dataframe[[i]].astype(str).apply(lambda x: x.str.len()).max().max()
#set the column length
worksheet.set_column(i,i,column_len)
writer.save()
ИЗМЕНИТЬ
Ниже приведено обновление, в котором рассматривается проблема столбца. Если заголовок столбца больше длины максимального столбца, чем используется заголовок столбца. Я также добавил буфер из 2, чтобы дать небольшое дополнение.
#Iterate through each column and set the width == the max length in that column.
for i in column_list:
#filter for header
header = my_dataframe[[i]].astype(str).columns.values
#Get length of header
header_len = len(header.max()) + 2
#Get length of column values
column_len = my_dataframe[[i]].astype(str).apply(lambda x: x.str.len()).max().max() + 2
#Choose the greater of the column length or column value length
if header_len >= column_len:
worksheet.set_column(i,i,header_len)
else:
worksheet.set_column(i,i,column_len)
writer.save()