2013-04-15 41 views
14

嗨,我有一个简短的问题。我没有在互联网上找到答案,也许有人可以帮助我。Django:openpyxl保存工作簿作为附件

所以我要保存工作簿作为附件,但我不知道如何让我们看看一个例子:

from openpyxl import Workbook 
    from openpyxl.cell import get_column_letter 
    wb = Workbook(encoding='utf-8') 
    dest_filename = 'file.xlsx' 
    ws = wb.worksheets[0] 
    ws.title = "range names" 
    for col_idx in xrange(1, 40): 
     col = get_column_letter(col_idx) 
     for row in xrange(1, 600): 
      ws.cell('%s%s'%(col, row)).value = '%s%s' % (col, row) 
    ws = wb.create_sheet() 
    ws.title = 'Pi' 
    ws.cell('F5').value = 3.14 

然后我尝试:

response = HttpResponse(wb, content_type='application/vnd.ms-excel') 
response['Content-Disposition'] = 'attachment; filename="foo.xls"' 
return response 

它的确但返回XLSX文件中的文件只有对象adres没有文件内容:

<openpyxl.workbook.Workbook object at 0x00000000042806D8> 

有人可以帮忙吗?

+0

您是否试过实例化'output = StringIO.StringIO()',然后通过'openpyxl.writer.excel.save_workbook'方法写入并将'output.getvalue()'传递给'HttpResponse'构造函数?让我知道它是否有帮助 - 我将添加它作为答案。 – alecxe

+0

另一个选择是使用'openpyxl.writer.excel.save_virtual_workbook'方法。 – alecxe

+0

'response = HttpResponse(save_virtual_workbook(wb),content_type ='application/vnd.ms-excel')' Working Thanks mate :))将此评论作为答复我会将其标记为已更正 – Silwest

回答

27

试试看:

from openpyxl.writer.excel import save_virtual_workbook 
... 
response = HttpResponse(save_virtual_workbook(wb), content_type='application/vnd.ms-excel') 

save_virtual_workbook是专为您的使用案例。这里的一个文档字符串:

“”。“返回一个内存中工作簿时,适合于一个Django响应”“”

+1

Thx!这在文档中并不是很明显,因为它只在生成的文档中提到。 – shangxiao

+0

它正在工作,但是当我在Front End端(由Angular Js创建)下载它时,它给了我一些unicode的东西(脏数据)。我需要在Angular代码中添加一些东西吗? –

2

我通常使用

ws = wb.add_sheet("Pi") 

,而不是

ws = wb.create_sheet() 
ws.title = "Pi" 

而且,你可以尝试做:(见documentation

wb.save(stream) 

,然后在使用的HttpResponse流。

+0

此流的类型是什么价值? – Silwest

+0

您可以使用StringIO,例如 – emigue

0

在至少一些的django /蟒/ openpyxl的版本中,给定的溶液不起作用。见https://bitbucket.org/openpyxl/openpyxl/issues/657/save_virtual_workbook-generates-junk-data

简单有效的解决方案:

wb = Workbook(write_only=True, encoding='utf-8') 
ws = wb.create_sheet() 
for row in data: 
    ws.append([str(cell) for cell in row]) 
response = HttpResponse(content_type='application/vnd.ms-excel') 
wb.save(response) 

这里发生的事情是,Django的HttpResponse对象是一个类似文件的对象。 Workbook.save()可以采取类似文件的对象。 (在内部,它使用zipfile,它使用文件名或类似文件的对象)。

如果您在内存中操作文件,这是最简单也可能是最有效的解决方案。由于数据不是使用生成器创建的,因此流式响应没有意义。即使save_virtual_workbook有效,它所写入的数据在其可读之前也会以块形式生成。

另一种选择是创建一个NamedTemporaryFile(从tempfile或Django的包装器),传递到Workbook.save(),然后使用FileResponse到流从文件系统,而不是从存储器中。

相关问题