有没有办法用pandas.ExcelWriter自动调整Excel列宽?

bad*_*eas 68 python excel pandas openpyxl

我被要求生成一些Excel报告.我目前正在为我的数据大量使用pandas,所以我当然希望使用pandas.ExcelWriter方法来生成这些报告.但是固定的列宽是个问题.

到目前为止我的代码很简单.假设我有一个名为'df'的数据框:

writer = pd.ExcelWriter(excel_file_path)
df.to_excel(writer, sheet_name="Summary")
Run Code Online (Sandbox Code Playgroud)

我正在查看pandas代码,我真的没有看到任何设置列宽的选项.宇宙中有没有一个技巧可以使列自动调整到数据?或者我可以在xlsx文件之后做些什么来调整列宽?

(我正在使用OpenPyXL库,并生成.xlsx文件 - 如果这有任何区别.)

谢谢.

ali*_*dry 33

受用户6178746的回答启发,我有以下内容:

# 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()
Run Code Online (Sandbox Code Playgroud)

  • 如果您收到“AttributeError: 'Worksheet' object has no attribute 'set_column'”,则您可能缺少 XlsxWriter,并且 pandas 正在依赖 openpyxl。`pip install XlsxWriter` 应该可以解决它:) (8认同)
  • 仅供参考:在我的情况下,我需要在"df.to_excel(...)"调用中使用"index = False",否则列被1关闭 (5认同)
  • 如果您不能使用 index=False (因为您在行上有一个多索引),那么您可以使用 df.index.nlevels 获取索引级别深度,然后使用它添加到您的 set 列调用中:`worksheet.set_column (idx+nlevels, idx+nlevels, max_len)`。否则长度是*计算*帧的第一列,然后*应用*到excel中的第一列,这可能是索引。 (4认同)
  • @Dascienz以相同的方式对dict进行迭代,实际上对dict的键进行迭代(您不必手动说出dict.keys()),对pd.DataFrame进行迭代。列。您不必手动遍历`df.columns`。 (2认同)
  • Pandas 支持计算字符串长度和其他内容的良好表示法: `series.astype(str).map(len).max()` 可以重写为: `series.astype(str).str.len().max ()`。 (2认同)

小智 22

我发布这个是因为我遇到了同样的问题,发现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()
Run Code Online (Sandbox Code Playgroud)


ojd*_*jdo 19

现在可能没有自动方法,但是当你使用openpyxl时,以下行(改编自用户Bufke关于如何手动操作的另一个答案)允许你指定一个合理的值(字符宽度):

writer.sheets['Summary'].column_dimensions['A'].width = 15
Run Code Online (Sandbox Code Playgroud)


Ash*_*007 15

通过使用 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()
Run Code Online (Sandbox Code Playgroud)


小智 14

我最近开始使用一个很好的包称为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()
Run Code Online (Sandbox Code Playgroud)

你也可以改变列宽:

sf.set_column_width(columns=['aaaaaaaaaaa', 'bbbbbbbbb'],
                    width=35.3)
Run Code Online (Sandbox Code Playgroud)


UPDATE

在版本1.4 best_fit中添加了参数StyleFrame.to_excel.请参阅文档.

  • @Hagbard 从版本 3 开始,导入应该是“from styleframe import StyleFrame”,以便符合 PEP8 名称约定 (2认同)

Gio*_*ous 13

动态调整所有列长

writer = pd.ExcelWriter('/path/to/output/file.xlsx') 
df.to_excel(writer, sheet_name='sheetName', index=False, na_rep='NaN')

for column in df:
    column_length = max(df[column].astype(str).map(len).max(), len(column))
    col_idx = df.columns.get_loc(column)
    writer.sheets['sheetName'].set_column(col_idx, col_idx, column_length)

writer.save()
Run Code Online (Sandbox Code Playgroud)

使用列名手动调整列

col_idx = df.columns.get_loc('columnName')
writer.sheets['sheetName'].set_column(col_idx, col_idx, 15)
Run Code Online (Sandbox Code Playgroud)

使用列索引手动调整列

writer.sheets['sheetName'].set_column(col_idx, col_idx, 15)
Run Code Online (Sandbox Code Playgroud)

如果上述任何一项失败

AttributeError: 'Worksheet' object has no attribute 'set_column'
Run Code Online (Sandbox Code Playgroud)

确保安装xlsxwriter

pip install xlsxwriter
Run Code Online (Sandbox Code Playgroud)

有关更全面的解释,您可以阅读文章如何在 TDS 上使用 Pandas ExcelWriter 自动调整 Excel 列的宽度

  • 工作完美,包括自动宽度、按列名称显示的显式宽度以及通过安装 xlswriter 解决的异常。谢谢 :) (2认同)

jac*_*536 8

我发现根据列标题而不是列内容调整列更有用。

使用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
Run Code Online (Sandbox Code Playgroud)


kgi*_*ibm 6

结合其他答案和评论,还支持多索引:

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()
Run Code Online (Sandbox Code Playgroud)


raf*_*.ch 5

在工作中,我总是将数据帧写入 excel 文件。因此,我没有一遍又一遍地编写相同的代码,而是创建了一个模数。现在我只是导入它并使用它来编写和格式化 excel 文件。但是有一个缺点,如果数据框特别大,则需要很长时间。所以这里是代码:

def result_to_excel(output_name, dataframes_list, sheet_names_list, output_dir):
    out_path = os.path.join(output_dir, output_name)
    writerReport = pd.ExcelWriter(out_path, engine='xlsxwriter',
                    datetime_format='yyyymmdd', date_format='yyyymmdd')
    workbook = writerReport.book
    # loop through the list of dataframes to save every dataframe into a new sheet in the excel file
    for i, dataframe in enumerate(dataframes_list):
        sheet_name = sheet_names_list[i]  # choose the sheet name from sheet_names_list
        dataframe.to_excel(writerReport, sheet_name=sheet_name, index=False, startrow=0)
        # Add a header format.
        format = workbook.add_format({
            'bold': True,
            'border': 1,
            'fg_color': '#0000FF',
            'font_color': 'white'})
        # Write the column headers with the defined format.
        worksheet = writerReport.sheets[sheet_name]
        for col_num, col_name in enumerate(dataframe.columns.values):
            worksheet.write(0, col_num, col_name, format)
        worksheet.autofilter(0, 0, 0, len(dataframe.columns) - 1)
        worksheet.freeze_panes(1, 0)
        # loop through the columns in the dataframe to get the width of the column
        for j, col in enumerate(dataframe.columns):
            max_width = max([len(str(s)) for s in dataframe[col].values] + [len(col) + 2])
            # define a max width to not get to wide column
            if max_width > 50:
                max_width = 50
            worksheet.set_column(j, j, max_width)
    writerReport.save()
    return output_dir + output_name

Run Code Online (Sandbox Code Playgroud)


mou*_*wsy 5

是的,您可以对 xlsx 文件执行一些操作来自动调整列宽。使用 xlwings 来autofit列。这是一个非常简单的解决方案,请参阅示例代码的最后 6 行。此过程的优点是您不必担心字体大小、字体类型或其他任何问题。要求:Excel安装。

import pandas as pd
import xlwings as xw

path = r"test.xlsx"

# Export your dataframe in question.
df = pd._testing.makeDataFrame()
df.to_excel(path)

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

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

    wb.save(path)
    wb.close()
Run Code Online (Sandbox Code Playgroud)