Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/28.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 有没有办法使用pandas.ExcelWriter自动调整Excel列宽?_Python_Excel_Pandas_Openpyxl - Fatal编程技术网

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

Python 有没有办法使用pandas.ExcelWriter自动调整Excel列宽?,python,excel,pandas,openpyxl,Python,Excel,Pandas,Openpyxl,我被要求生成一些Excel报告。我目前大量使用pandas来获取数据,因此我自然希望使用pandas.ExcelWriter方法生成这些报告。但是,固定列宽是一个问题 到目前为止,我的代码非常简单。假设我有一个名为“df”的数据帧: writer = pd.ExcelWriter(excel_file_path, engine='openpyxl') df.to_excel(writer, sheet_name="Summary") 我查看了pandas代码,但没有看到任何设置列宽的选项。宇宙

我被要求生成一些Excel报告。我目前大量使用pandas来获取数据,因此我自然希望使用pandas.ExcelWriter方法生成这些报告。但是,固定列宽是一个问题

到目前为止,我的代码非常简单。假设我有一个名为“df”的数据帧:

writer = pd.ExcelWriter(excel_file_path, engine='openpyxl')
df.to_excel(writer, sheet_name="Summary")
我查看了pandas代码,但没有看到任何设置列宽的选项。宇宙中有没有一个技巧可以使列自动调整以适应数据?或者,在xlsx文件修改之后,我可以做些什么来调整列宽

(我正在使用OpenPyXL库,并生成.xlsx文件——如果这有什么不同的话。)


谢谢。

现在可能没有自动执行的方法,但是当您使用openpyxl时,下面的一行(改编自上一个用户的另一个答案)允许您指定一个sane值(字符宽度):


最近我开始使用一个很好的包,名为StyleFrame

它获取数据帧,让您可以非常轻松地设置其样式

默认情况下,列宽是自动调整的

例如:

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

在版本1.4中,
best\u fit
参数被添加到
StyleFrame.to\u excel
。 看

更新2

下面是一个适用于StyleFrame 3.x.x的代码示例

from styleframe import StyleFrame
import pandas as pd

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

我之所以发布这篇文章,是因为我刚刚遇到了同样的问题,并且发现Xlsxwriter和pandas的官方文档中仍然列出了不支持的功能。我拼凑了一个解决方案,解决了我遇到的问题。我基本上只是遍历每一列,并使用sheetwork.set_column设置列宽==该列内容的最大长度

然而,有一点很重要。此解决方案不适合列标题,只适合列值。不过,如果您需要调整标题,那么这应该是一个简单的更改。希望这对某人有帮助:)

受此启发,我有以下几点:

# 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()

最简单的解决方案是在set_column方法中指定列的宽度

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

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

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()

通过使用pandas和xlsxwriter,您可以完成任务,下面的代码将在Python3.x中完美工作。有关使用XlsxWriter和pandas的更多详细信息,请访问此链接


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

使用
df.columns.values.tolist()
I生成列标题列表,并使用这些标题的长度来确定列的宽度

请参阅下面的完整代码:

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

在工作中,我总是将数据帧写入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


动态调整所有列的长度

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()

使用列名手动调整列

col_idx = df.columns.get_loc('columnName')
writer.sheets['sheetName'].set_column(col_idx, col_idx, 15)

使用列索引手动调整列

writer.sheets['sheetName'].set_column(col_idx, col_idx, 15)

如果上述任何一项不符合要求

AttributeError: 'Worksheet' object has no attribute 'set_column'
确保安装
xlsxriter

pip install xlsxwriter


要获得更全面的解释,您可以阅读关于TDS的文章。

您可以通过调用以下函数来解决问题,其中df是您想要获取尺寸的数据框,sheetname是您想要进行修改的excel中的工作表

def auto_width_columns(df, sheetname):
        workbook = writer.book  
        worksheet= writer.sheets[sheetname] 
    
        for i, col in enumerate(df.columns):
            column_len = max(df[col].astype(str).str.len().max(), len(col) + 2)
            worksheet.set_column(i, i, column_len)

是的,在对xlsx文件进行修改之后,您可以做一些事情来调整列宽。 使用xlwings创建柱。这是一个非常简单的解决方案,请参见示例代码的最后六行。此过程的优点是,您不必担心字体大小、字体类型或其他任何问题。 要求:Excel安装

import pandas as pd
import xlwings as xw

report_file = "test.xlsx"

df1 = pd.DataFrame([
    ('this is a long term1', 1, 1, 3),
    ('this is a long term2', 1, 2, 5),
    ('this is a long term3', 1, 1, 6),
    ('this is a long term2', 1, 1, 9),
    ], columns=['term', 'aaaa', 'bbbbbbb', "cccccccccccccccccccccccccccccccccccccccccccccc"])

writer = pd.ExcelWriter(report_file, engine="xlsxwriter")
df1.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("B:D", cell_format=num_format)
writer.save()

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

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

wb.save(report_file)
app.quit()

目前看来不可能,请在github上为这个增强打开一个问题(可能是一个PR?)。看起来没那么难。谢谢杰夫,我已经提交了这个问题。我不确定我是否有时间真正深入熊猫代码库来解决它,但你永远不知道:)是的……看到了你的问题……如果你需要帮助,请评论这个问题!(基本上需要将可选参数传递到
到_excel
,可能是
col\u style=dict
,其中包含col header样式元素(而不是默认的
header\u样式
,该样式现在似乎是硬编码的。我喜欢您使用pandas而不是另一个包的方式。我认为您需要
()
inner max function:`max(column_len(),len(col))+2`FYI:在我的例子中,我需要在“df.to_excel(…)”调用中使用“index=False”,否则列将被关闭1yep,如果您不能使用index=False(因为您在行上有一个多索引),我还必须将df.to_excel(writer,sheet\u name=sheetname,index=False)添加到df.to_excel(writer,sheet\u name=sheetname,index=False),然后您可以使用df.index.nlevels获取索引级别的深度,然后使用它添加到set列调用:
worksheet.set_列(idx+nlevels,idx+nlevels,max_len)
。否则,将为框架的第一列计算长度,然后应用于excel中的第一列,这可能是索引。对于仍在寻找此答案的任何人,
enumerate(df)
应为
enumerate(df.columns)
由于您在
df
@Dascienz中迭代每一列,因此迭代
dict
实际上会迭代
dict
中的键(您不必手动说
dict.keys()
),在
pd上迭代。DataFrame
在列上迭代。您不必手动在
df列上迭代
AttributeError: 'Worksheet' object has no attribute 'set_column'
pip install xlsxwriter
def auto_width_columns(df, sheetname):
        workbook = writer.book  
        worksheet= writer.sheets[sheetname] 
    
        for i, col in enumerate(df.columns):
            column_len = max(df[col].astype(str).str.len().max(), len(col) + 2)
            worksheet.set_column(i, i, column_len)
import pandas as pd
import xlwings as xw

report_file = "test.xlsx"

df1 = pd.DataFrame([
    ('this is a long term1', 1, 1, 3),
    ('this is a long term2', 1, 2, 5),
    ('this is a long term3', 1, 1, 6),
    ('this is a long term2', 1, 1, 9),
    ], columns=['term', 'aaaa', 'bbbbbbb', "cccccccccccccccccccccccccccccccccccccccccccccc"])

writer = pd.ExcelWriter(report_file, engine="xlsxwriter")
df1.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("B:D", cell_format=num_format)
writer.save()

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

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

wb.save(report_file)
app.quit()