使用一个方法/函数来格式化xlsx writer。

7
我正在尝试动态地样式化和编写Excel文件。这是我的代码:
import pandas as pd
import copy

class OutputWriter(object):

    def __init__(self, fmt_func, sheet_name='data'):
        '''
        Initializing...
        '''
        # NOTICE: Initialising with path set None since I do not know path yet
        wrt = pd.ExcelWriter(None, engine='xlsxwriter')
        self._writer = fmt_func(wrt, sheet_name)
        self._sheet_name = sheet_name

    def save(self, df, o_path):
        '''
        Save the file to a path
        '''
        # setting path in writer before saving
        self._writer.path = o_path
        df.to_excel(self._writer, sheet_name=self._sheet_name)
        self._writer.save()

# Change first row color to blue
def fmt_func_blue(wrt, sheet_name):
    # ERROR Cannot clone `wrt` path is not set
    writer = copy.deepcopy(wrt)
    sheet = writer.sheets[sheet_name]
    workbook = writer.book

    # Proceed to color first row blue
    header_fmt = workbook.add_format({
        'text_wrap': True,
        'bg_color': '#191970',
        'font_color': '#FFFFFF',
    })
    header_fmt.set_align('center')
    header_fmt.set_align('vcenter')
    sheet.set_row(0, None, header_fmt)
    return writer

# Change first row color to red 
def fmt_func_red(wrt, sheet_name):
    writer = copy.deepcopy(wrt)
    # I haven't saved the excel file so there are no sheets
    sheet = writer.sheets[sheet_name]
    workbook = writer.book

    # Proceed to color first row red
    header_fmt = workbook.add_format({
        'text_wrap': True,
        'bg_color': '#FF2200',
        'font_color': '#FFFFFF',
    })
    header_fmt.set_align('center')
    header_fmt.set_align('vcenter')
    sheet.set_row(0, None, header_fmt)
    return writer

writer_red = OutputWriter(fmt_func_red, sheet_name='red')
writer_blue = OutputWriter(fmt_func_blue, sheet_name='blue')

我有两个问题:

1)我无法在样式函数中克隆xlwriter对象

2)在我尝试为Excel文件设置样式时,工作簿中没有工作表。

有没有办法让这个工作?


请提供可重现的代码。这样不行。fmt_func_red函数内部使用了self,但是没有在函数中传递。请创建一个可重现的版本,可以直接运行。 - Tarun Lalwani
2
仍然有很多错误。请修复代码,然后在问题中提到的问题仍然存在时再发布。在更新之前运行代码。 - Tarun Lalwani
@GüntherEberl,为什么需要调用save()?这个问题与save()无关。 - cowlinator
@GüntherEberl 我已经按照你的建议进行了编辑。虽然我认为导入相当隐式。 - Ajit
@cowlinator 当使用xlsxwriter作为写入器时,您只有一次机会将数据放入工作表中,无法更改已存在的工作表。用户尝试在将数据帧转储到工作表之前对工作表应用格式。这种方法可能不起作用。但是,您只能在保存时注意到这一点。 - Günther Eberl
显示剩余2条评论
1个回答

2

1)我无法在样式函数中克隆xlwriter对象。

如果工作簿还不存在(或者只是创建了一个没有值的工作簿,这里通过扩展路径来检查是否有价值),则无法克隆工作簿。让我们解决抛出的错误,更改:

def fmt_func_blue(wrt, sheet_name):
    # ERROR Cannot clone `wrt` path is not set
    writer = copy.deepcopy(wrt)

为了

def fmt_func_blue(wrt, sheet_name):
    # ERROR Cannot clone `wrt` path is not set
    writer=wrt
    if writer.book.filename:
      writer = copy.deepcopy(wrt)
    else:
      # Any changes to the new workbook will be reflected on the new 
      # workbook of the writer(created in init) not on a copy.
      # If you want your class init writer untouched, 
      # and want to format a completely new instance of workbook, recreate 
      # a new writer and assign it to the local writer here.
      print('Warning: Working with new workbook')#or use log

这应该能解决问题,记住不需要克隆一个完全为空的工作簿。但如果出于某种设计需要这样做,则需要自己创建一个克隆,就像在init中创建一个完全空的工作簿一样。
2) 当我尝试为Excel文件设置样式时,我的工作簿中没有工作表。
嗯,不能对不存在的工作表进行格式化。因此,只需创建一个工作表,并将数据框架(或任何其他)数据稍后填充到已经格式化的工作表中。我建议以下更改:
# I haven't saved the excel file so there are no sheets
sheet = writer.sheets[sheet_name]

to

sheet=None
if sheet_name in writer.sheets:
  sheet = writer.sheets[sheet_name]
else:
  print('Warning: Creating new sheet for formatting <'+sheet_name+'>') # or use log
  sheet= workbook.add_worksheet(sheet_name)

这里是可行的代码链接:https://repl.it/@bulbus/TrustyBabyishForms。当你尝试运行它时,安装库文件需要一些时间。我在示例代码中进行了一些安全性修改和方法调整。

我的示例代码输出结果如下:

Warning: Working with new workbook
Warning: Creating new sheet for formatting <red>
Warning: Working with new workbook
Warning: Creating new sheet for formatting <blue>

你发布的代码是可行的,只要你不尝试使用save()函数将数据框保存到其中:异常:工作表名称"red"(大小写不敏感)已被使用。 - Günther Eberl
关于这个错误,请参考 https://dev59.com/5WIj5IYBdhLWcg3wfVB8 。看起来在 to_excel 之前加上一行代码就可以解决问题了。self._writer.sheets=dict((ws.title, ws) for ws in self._writer.book.worksheets) - kaza

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接