2016-06-10 126 views
4

我刚开始使用XlsxWriter,我想编写自己的方法来简化编写excels,因为我拥有的数据总是具有相同的格式。XlsxWriter和Python继承

我想完全透明地写一个继承XlsxWriter的模块,并且对于那些不需要我的方法的人来说,使用我的模块是一样的,直接使用XlsxWriter,而如果某个时候需要我的方法之一可以使用它,而不需要对代码进行任何更改或者在同一个文件/对象中添加更多的对象。

于是我开始写一个模块:

import xlsxwriter 

class XlsxMaster(xlsxwriter.Workbook): 

    def __init__(self, filename): 
     super(XlsxMaster, self).__init__(filename) 

    def write_results(self): 
     print "write results" 

那么我可以用:

from xlsx_Master import XlsxMaster 

workbook = XlsxMaster('./Expenses01.xlsx') 
worksheet = workbook.add_worksheet() 
worksheet.write_results() 

的问题是,作为工作表对象从xlsxwriter.worksheet派生,而不是从这个不起作用我的模块,它可以通过workbook.write_results()正确调用,但这不是我想要的。 如何以这种方式向xlsxwriter.worksheet添加方法? 我不知道如何解决这个优雅。也许有一种方法,或者也许我从一开始就采取了错误的方式。

回答

2

write_results工作表的一种方法,因此您必须创建一个继承自Worksheet的类。在那里你可以写你的write_results您必须重新实现创建工作表的方法。纵观代码,这是_add_sheet

不优雅,我很害怕,但这就是你要求的。

+0

我认为这是一个解决方案,但它会占用大量的工作,因为这是第一个障碍,我相信我会找到许多别人的时候我会用图表,格式等..我仍然希望有另一种解决方案,而不是创建其他类并重写现有的方法来添加新的方法,也许我将不得不面对严酷的事实,没有别的方法 –

3

我采取了一种稍微不同的方法,它的工作方式足以在Web应用程序中生成xls输出。

我没有重写xlswriter的东西,而是开发了一个Facade对象,它与我想要做的匹配,然后调用底层的xlswriter资源来完成这项工作。

import xlsxwriter 

class ExcelWriter(object): 

    def getColFormatInfo(self, fieldname): 
     #some app-specific stuff... 
     f = FieldFormat.factory(self.rdb, fieldname) 
     # width = 30 
     label = f.SHORTNAME 
     width = max(f.LENGTH, len(label)) 
     return width, label 

    def __init__(self, rdb, title): 
     self.rdb = rdb 
     self.fnp = "/tmp/%s.xlsx" % (title) 
     wb = self.workbook = xlsxwriter.Workbook(self.fnp) 

     #http://xlsxwriter.readthedocs.org/en/latest/format.html#set_bg_color 
     self.fmt_title = wb.add_format(dict(bold=True)) 
     self.fmt_title.set_bg_color("#F5F5F5") 
     self.fmt_title.set_border(1) 

     self.fmt_colheader = wb.add_format(dict(bold=True)) 
     self.fmt_colheader.set_bottom(2) 


     self.fmt_link = wb.add_format({'color': 'blue', 'underline': 1}) 

    def add_worksheet(self, wsname): 
     return self.workbook.add_worksheet(wsname) 

    def write_title(self, ws, row, col, s): 
     ws.write(row, col, s, self.fmt_title) 

    def write_colheader(self, ws, row, col, s): 
     ws.write(row, col, s, self.fmt_colheader) 

    def write(self, ws, row, col, s): 
     ws.write(row, col, s) 

    def write_url(self, ws, row, col, url, s): 
     ws.write_url(row, col, url, self.fmt_link, s) 

正如你所看到的,我所做的一切是预先计算一些XLS格式,并在使用的东西他们喜欢write_colheader

但是,您可以概括该方法来创建更多用户友好的简单功能,以在幕后执行复杂的xlswriter操作。

我找不到我用来与之交互的代码,但它工作得很好。唯一的是,这是很多手动把xyz放在1,13我写的代码类型。我的网络应用程序的正常html侧使用django-tables2来生成html,并且代码少得多。

所以我的计划是回去重写报表,使其更加基于声明式,并带有报表前端,然后将所有的基本命令传递给ExcelWriter - 我仍然期待ExcelWriter有大致相同类型的API。

哦,除了基于声明的更改之外,我会立即在新实现中更改的一件事是将格式化常量(如背景颜色#F5F5F5)存储在Json文件中,并在初始化时将它传递给ExcelWriter :

喜欢的东西:

self.fmt_title.set_bg_color(
    self.j_config.get("fmt_title",{}).get("bg_color", "F5F5F5") 
    ) 

关于老年退休金计划有关具有变量传递发表评论,这里有一些更新的功能DEFS作为一个可能的解决方法。

def add_worksheet(self, wsname): 
    ws = self.current_ws = self.workbook.add_worksheet(wsname) 
    return ws 

#you'd also need to have a set_current_ws function 

def write_url(self, row, col, url, s, ws=None, fmt=None): 
    ws = ws or self.current_ws 
    fmt = fmt or self.fmt_link 

    ws.write_url(row, col, url, fmt, s) 
+0

这肯定是另一种成功的方法来实现它,但是离我想要的有点远。至于每一种方法,我都必须通过工作表来处理。对我来说毫无戏剧性,但因为即使简单一些,他也会使用我的脚本,他会看到它“更多的东西”。即使现在我仍然更喜欢@pacholik,即使实施更复杂,我也会考虑这个想法。 –

+0

已注意。我添加了一些可能的更改。在一天结束时,这是一个偏好问题 - 我倾向于对继承问题有偏见,以解决大多数OOP问题。在这种情况下,仅在我看来,我发现使用Facade可以让我专注于我的域问题,即编写特定类型的Excel内容。而不必担心XlsWriter的类内部,如果你使用继承,你必须跟踪它。一如往常,你的里程可能会有所不同 –