如何使用 xlsxwriter 格式化索引列?

Posted

技术标签:

【中文标题】如何使用 xlsxwriter 格式化索引列?【英文标题】:How can I format the index column(s) with xlsxwriter? 【发布时间】:2017-02-15 00:04:56 【问题描述】:

我正在使用 xlsxwriterset_column 函数来格式化我的 excel 输出中的列。

但是,当应用于索引列(或多索引情况下的索引列)时,格式似乎被忽略了。

我找到了一种解决方法,到目前为止是使用 reset_index 引入一个假索引,然后将 index=False 传递给 to_excel 函数,然后是多索引也将消失。

有什么想法吗?

import pandas as pd
import numpy as np

from Config import TEMP_XL_FILE

def temp():
    ' temp'
    pdf = pd.DataFrame(np.random.randn(6,4), columns=list('ABCD'))
    pdf.set_index('A', drop=True, inplace=True)
    writer = pd.ExcelWriter(TEMP_XL_FILE, engine='xlsxwriter')
    pdf.to_excel(writer, 'temp')
    workbook = writer.book
    worksheet = writer.sheets['temp']
    tempformat = workbook.add_format('num_format': '0%', 'align': 'center')
    worksheet.set_column(-1, 3, None, tempformat)
    writer.save()

if __name__ == '__main__':
    temp()

【问题讨论】:

您能提供给我们您的代码吗? 在 XlsxWriter 和 Excel 中,单元格格式覆盖行格式覆盖列格式。在这种情况下,Pandas 将单元格格式(合并)应用于索引单元格,因此set_column() 格式没有效果。我认为无法通过 API 覆盖或设置 Panda 的索引格式(datetime_formatdate_format 除外), 【参考方案1】:

pandas ExcelWriter 会覆盖索引列中的 XlsxWriter 格式。 为防止这种情况,请将熊猫 header_style 更改为 None

header_style = "font": "bold": True,
                "borders": "top": "thin",
                            "right": "thin",
                            "bottom": "thin",
                            "left": "thin",
                "alignment": "horizontal": "center",
                              "vertical": "top" 

这样做:

import pandas.io.formats.excel

pandas.io.formats.excel.header_style = None

另见

xlsxwriter not applying format to header row of dataframe - Python Pandas Pandas raising: AttributeError: module 'pandas.core' has no attribute 'format'

【讨论】:

至少在 1.1.5 中,这是损坏的,header_style 符号在 excel 模块中不存在。【参考方案2】:

据我了解,Pandas 设置索引行的格式。有办法重置它,但这些解决方案不是很可靠。实际格式化也相当困难。

用所需格式写出索引列最适合我

import pandas as pd

# The data that we're feeding to ExcelWriter
df = pd.DataFrame(
    
        "Col A": ["a", "a", "b", "b"],
        "Col B": ["a", "b", "c", "d"],
        "Col C": [1, 2, 3, 4],
    
)

# The Excel file we're creating
writer = pd.ExcelWriter("pandas_out.xlsx", engine="xlsxwriter")
df.to_excel(writer, sheet_name="Sheet1", index=False) # Prevents Pandas from outputting an index

# The variables we'll use to do our modifications
workbook = writer.book
worksheet = writer.sheets["Sheet1"]

worksheet.set_row(0, 30) # Set index row height to 30

# Find more info here: https://xlsxwriter.readthedocs.io/format.html#format-methods-and-format-properties
header_format = workbook.add_format(
    
        "bold": True,
        "valign": "vcenter",
        "align": "center",
        "bg_color": "#d6d6d6",
        "border": True,
    
)

# Write the column headers with the defined format.
for col_num, value in enumerate(df.columns.values):
    worksheet.write(0, col_num, value, header_format)

# Set format of data
format1 = workbook.add_format("align": "center")
worksheet.set_column('A:Z', 10, format1) # Width of cell

writer.save()

【讨论】:

您不只是编写列,而是从 Pandas 已经设置的内容中覆盖它们。这并不理想。您可以改为定义自己的格式化程序并保留 Pandas 自己的默认列循环。【参考方案3】:

要添加到@Max 的答案,这对我来说适用于 pandas 1.1.5:

import pandas.io.formats.excel

pandas.io.formats.excel.ExcelFormatter.header_style = None

【讨论】:

这似乎用静态覆盖了实例属性,这是个坏主意。 你能推荐一个更好的方法吗? 从 ExcelFormatter 派生并使用它来覆盖 header_style 实现;不要做任何猴子补丁;并在需要时使用新的格式化程序类。【参考方案4】: 不要对库进行猴子补丁,从格式化程序类派生 不必费心重写所有代码来自己创建单元格 使用 Pandas 在内部为单元格内容定义的中间“类 CSS”格式化语言;这都写在pandas/io/excel/_xlsxwriter.py

这适用于 1.1.5:

import numpy as np
import pandas as pd
from pandas.io.formats.excel import ExcelFormatter
from typing import Dict, Any

# from Config import TEMP_XL_FILE
TEMP_XL_FILE = 'headers.xlsx'

class CenteredFormatter(ExcelFormatter):
    @property
    def header_style(self) -> Dict[str, Any]:
        d = dict(super().header_style)
        d.setdefault('alignment', )['horizontal'] = 'center'
        d.setdefault('number_format', )['format_code'] = '0%'
        return d


def temp() -> None:
    with pd.ExcelWriter(TEMP_XL_FILE, engine='xlsxwriter') as writer:
        pdf = pd.DataFrame(np.random.randn(6, 4), columns=list('ABCD'))
        pdf.set_index('A', drop=True, inplace=True)
        formatter = CenteredFormatter(pdf)
        formatter.write(writer, sheet_name='temp')

if __name__ == '__main__':
    temp()

【讨论】:

以上是关于如何使用 xlsxwriter 格式化索引列?的主要内容,如果未能解决你的问题,请参考以下文章

python xlsxwriter写excel并操作各种格式属性

python xlsxwriter 在同一个单元格写入不同的格式文本

如何使用 xlsxwriter - python 更改图例字体大小

XlsxWriter - 图表列和图例颜色不匹配

根据值合并行(熊猫到 excel - xlsxwriter)

如何使用 XlsxWriter 冻结第一行和第一列?