Django: openpyxl saving workbook as attachment

匿名 (未验证) 提交于 2019-12-03 02:06:01

问题:

Hi I have a quick question. I didn't find answer in internet maybe someone of you can help me.

So i want to save workbook as attachment but I don't know how lets see an example :

    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 

Then I tried :

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

It's returning xlsx file indeed but in file there is only object adres not the content of file:

Can someone help ?

回答1:

Give it a try:

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

save_virtual_workbook was specially designed for your use case. Here's a docstring:

"""Return an in-memory workbook, suitable for a Django response."""



回答2:

I usually use

ws = wb.add_sheet("Pi") 

instead of

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

Moreover, you can try to do: (see documentation)

wb.save(stream) 

and then use stream in HttpResponse.



回答3:

On at least some versions of django/python/openpyxl, the given solution does not work. See https://bitbucket.org/openpyxl/openpyxl/issues/657/save_virtual_workbook-generates-junk-data

Simple working solution:

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) 

What's happening here is that Django's HttpResponse is a file-like object. Workbook.save() can take a file-like object. (Internally, it uses zipfile, which takes either a filename or a file-like object.)

If you're manipulating the file in memory, this is the simplest and probably most efficient solution. A streaming response doesn't really make sense since the data is not being created with a generator. Even if save_virtual_workbook works, the data it writes is generated as a block before it's readable.

The other option would be to create a NamedTemporaryFile (from tempfile or Django's wrapper), pass that into Workbook.save(), then use FileResponse to stream that from the filesystem instead of from memory.



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!