2013-04-15 9 views
14

Witam Mam krótkie pytanie. Nie znalazłem odpowiedzi w Internecie, może ktoś z was może mi pomóc.Django: openpyxl zapisuje skoroszyt jako załącznik

więc chcę zapisać skoroszyt jako załącznik, ale nie wiem, jak pozwala zobaczyć przykład:

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 

Potem próbowałem:

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

To powrocie .xlsx rzeczywiście, ale w pliku jest tylko adres obiektu, a nie zawartość pliku:

<openpyxl.workbook.Workbook object at 0x00000000042806D8> 

Czy ktoś może pomóc?

+0

Czy próbowałeś utworzyć instancję 'output = StringIO.StringIO()', a następnie napisać do niej metodą 'openpyxl.writer.excel.save_workbook' i przekazać' output.getvalue() 'do konstruktora' HttpResponse'? Daj mi znać, jeśli to pomoże - dodam to jako odpowiedź. – alecxe

+0

Jeszcze jedną opcją jest użycie metody 'openpyxl.writer.excel.save_virtual_workbook'. – alecxe

+0

'response = HttpResponse (save_virtual_workbook (wb), content_type = 'application/vnd.ms-excel')' Working Thanks mate :)) zrób ten komentarz jako odpowiedź Zaznaczę go jako poprawiony – Silwest

Odpowiedz

27

Spróbować:

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

save_virtual_workbook został specjalnie zaprojektowany dla przypadku użycia. Oto docstring:

"" "Zwraca skoroszyt w pamięci, odpowiedni do odpowiedzi Django" ""

+1

Thx! Nie było to od razu oczywiste w dokumentacji, ponieważ jest tylko wspomniane w wygenerowanych dokumentach. – shangxiao

+0

To działa, Ale kiedy pobrałem go na stronie Front End (Created of Angular Js), To daje mi trochę rzeczy unicode (Dirty danych). Czy muszę dodać coś w kodzie Angular? –

2

Zwykle używam

ws = wb.add_sheet("Pi") 

zamiast

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

Ponadto, można spróbować zrobić: (patrz documentation)

wb.save(stream) 

a następnie za pomocą strumienia w HttpResponse.

+0

Jaki jest typ tego strumienia wartość? – Silwest

+0

Możesz użyć StringIO, np. – emigue

0

przynajmniej na niektórych wersjach Django/Python/openpyxl, dana rozwiązanie nie działa. Zobacz https://bitbucket.org/openpyxl/openpyxl/issues/657/save_virtual_workbook-generates-junk-data

Proste Roztwór roboczy:

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) 

Co się dzieje jest to, że HttpResponse Django jest obiektem plikopodobnym. Workbook.save() może przyjąć obiekt podobny do pliku. (Wewnętrznie używa on nazwy zipfile, która przyjmuje nazwę pliku lub obiektu podobnego do pliku.)

Jeśli manipulujesz plikiem w pamięci, jest to najprostsze i prawdopodobnie najskuteczniejsze rozwiązanie. Odpowiedź dotycząca przesyłania strumieniowego nie ma większego sensu, ponieważ dane nie są tworzone za pomocą generatora. Nawet jeśli działa save_virtual_workbook, zapisywane dane są generowane jako blok przed odczytem.

Innym rozwiązaniem byłoby stworzenie NamedTemporaryFile (od tempfile lub opakowanie Django), które przechodzą do Workbook.save(), a następnie użyć FileResponse strumień że z plików, a nie z pamięci.

Powiązane problemy