2013-04-15 141 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到流從文件系統,而不是從存儲器中。

相關問題