Django: le classeur de sauvegarde openpyxl en pièce jointe

Salut j'ai une question rapide. Je n'ai pas trouvé de réponse sur internet peut-être que quelqu'un d'entre vous peut m'aider.

alors je veux sauvegarder le classeur comme pièce jointe mais je ne sais pas comment laisse voir un exemple :

    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

Puis j'ai essayé :

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

C'est le retour fichier xlsx en effet, mais dans le fichier il y a seulement l'objet adres pas le contenu du fichier:

<openpyxl.workbook.Workbook object at 0x00000000042806D8>

quelqu'un Peut-il aider ?

18
demandé sur Silwest 2013-04-15 17:11:07

3 réponses

faire un essai:

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

save_virtual_workbook a été spécialement conçu pour votre cas d'utilisation. Voici une docstring:

"""retourner un cahier d'exercices en mémoire, adapté à une réponse Django."""

29
répondu alecxe 2013-04-15 13:50:36

j'ai l'habitude d'utiliser

ws = wb.add_sheet("Pi")

au lieu de

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

de plus, vous pouvez essayer de faire: (voir documentation)

wb.save(stream)

puis utiliser stream dans HttpResponse.

2
répondu emigue 2013-04-15 13:41:45

Sur au moins certaines versions de django/python/openpyxl, la solution donnée ne fonctionne pas. Voir https://bitbucket.org/openpyxl/openpyxl/issues/657/save_virtual_workbook-generates-junk-data

Simple solution de travail:

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)

ce qui se passe ici, C'est que le HttpResponse de Django est un objet qui ressemble à un fichier. Workbook.save() peut prendre un fichier objet semblable. (En interne, il utilise zipfile, qui prend un nom de fichier ou un fichier-comme objet.)

si vous manipulez le fichier en mémoire, c'est la solution la plus simple et probablement la plus efficace. Une réponse en continu n'a pas vraiment de sens puisque les données ne sont pas créées avec un générateur. Même si save_virtual_workbook fonctionne, les données qu'il écrit sont générées sous forme de bloc avant qu'il ne soit lisible.

l'autre option serait de créer un fichier Temporaryfile nommé (à partir de tempfile ou Django wrapper), passez les dans Workbook.save(), puis utilisez FileResponse pour le streamer à partir du système de fichiers au lieu de la mémoire.

0
répondu melinath 2016-07-27 19:13:08