嗨,我有一个简单的问题。我没有在互联网上找到答案,也许有人可以帮助我。
所以我想将工作簿保存为附件,但我不知道如何看待示例:
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文件,但是在文件中只有对象不是文件的内容:
<openpyxl.workbook.Workbook object at 0x00000000042806D8>
有人可以帮忙吗?
答案 0 :(得分:29)
试一试:
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 :(得分:3)
我通常使用
ws = wb.add_sheet("Pi")
而不是
ws = wb.create_sheet()
ws.title = "Pi"
此外,你可以尝试:(见documentation)
wb.save(stream)
然后在HttpResponse中使用流。
答案 2 :(得分:1)
至少在某些版本的django / python / 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从文件系统中传输它而不是记忆。