2013-04-15 8 views
14

Hallo ich habe eine kurze Frage. Ich habe keine Antwort im Internet gefunden, vielleicht kann jemand von Ihnen mir helfen.Django: openpyx speichern Arbeitsmappe als Anhang

So mag ich Arbeitsmappe als Anlage speichern, aber ich weiß nicht, wie ein Beispiel können sehen:

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 

Dann habe ich versucht:

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

es in der Tat aber xlsx Datei ist Rückkehr in Datei es gibt nur Objekt adres nicht den Inhalt der Datei:

<openpyxl.workbook.Workbook object at 0x00000000042806D8> 

Kann jemand helfen?

+0

Haben Sie versucht, 'output = StringIO.StringIO()' zu instanziieren, dann schreiben Sie über die 'openpyxl.writer.excel.save_workbook' Methode dorthin und übergeben Sie' output.getvalue() 'an' HttpResponse' Konstruktor? Lass es mich wissen, wenn es hilft - ich füge es als Antwort hinzu. – alecxe

+0

Eine weitere Option ist die 'openpyxl.writer.excel.save_virtual_workbook' Methode. – alecxe

+0

'Antwort = HttpResponse (save_virtual_workbook (wb), content_type = 'Anwendung/vnd.ms-Excel')' Arbeiten Dank Kumpel :)) diesen Kommentar als Antwort machen Ich werde es als korrigiert markieren – Silwest

Antwort

27

es versuchen:

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

save_virtual_workbook speziell für Ihren Anwendungsfall konzipiert wurde. Hier ist ein docstring:

"" "Liefern eine In-Memory-Arbeitsmappe, geeignet für eine Django Antwort" ""

+1

Danke! Das war nicht sofort in der Dokumentation offensichtlich, da es nur in den generierten Dokumenten erwähnt wird – shangxiao

+0

Es funktioniert, aber wenn ich es auf der Front End-Seite (Erstellt von Angular Js) heruntergeladen habe, gibt es mir einige Unicode-Dinge (Dirty data). Muss ich etwas in Angular Code hinzufügen? –

2

Normalerweise verwende ich

ws = wb.add_sheet("Pi") 

statt

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

Darüber hinaus können Sie versuchen zu tun: (siehe documentation)

wb.save(stream) 

und dann in Httpresponse verwenden Stream.

+0

Was ist der Typ dieses Streams Wert ? – Silwest

+0

Sie können StringIO, z. – emigue

0

auf mindestens einige Versionen von django/Python/openpyxl, die gegebene Lösung funktioniert nicht. Siehe https://bitbucket.org/openpyxl/openpyxl/issues/657/save_virtual_workbook-generates-junk-data

Einfache Arbeitslösung:

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) 

Was hier passiert, ist, dass Djangos Httpresponse ist eine dateiähnliche Objekt. Workbook.save() kann ein dateiähnliches Objekt aufnehmen. (Intern verwendet es zipfile, das entweder einen Dateinamen oder ein dateiähnliches Objekt verwendet.)

Wenn Sie die Datei im Speicher bearbeiten, ist dies die einfachste und wahrscheinlich effizienteste Lösung. Eine Streaming-Antwort ist nicht wirklich sinnvoll, da die Daten nicht mit einem Generator erstellt werden. Selbst wenn save_virtual_workbook funktioniert, werden die Daten, die geschrieben werden, als Block generiert, bevor sie lesbar sind.

Die andere Option eine NamedTemporaryFile wäre (von tempfile oder Djangos Wrapper) zu erstellen, übergibt, dass in Workbook.save(), dann FileResponse verwenden, statt aus dem Speicher der aus dem Dateisystem zu streamen.

Verwandte Themen