cannot import name 'save_virtual_workbook' from 'openpyxl.writer.excel'
Asked Answered
C

4

9

Is there an update to the library?

Before it worked perfectly, and today I updated and it no longer loads

I searched but I can't find any other option

Combe answered 31/1, 2023 at 15:37 Comment(5)
Welcome to stackoverflow. Without source code and a clear error message, it's impossible to answer your question. Please see How to Ask, then edit your question and add your code, as text, formatted (use the {} button), as a minimal reproducible example.Robbinrobbins
Although not mentioned in the release notes, it seems that version 3.1.0 (released today) removed it...Gerome
This was deprecated a long time ago and was also removed from the documentation.Yanyanaton
save_virtual_workbook is a deprecated in openpyxl. Last version openpyxl with this function 3.0.10. codeCreature
seems we now need to save a temp file, then open it and get the buffer back into RAM? Seems wasteful...Cuddy
C
9

Looks like the new recommendation from the developers is to use a temp-file: https://openpyxl.readthedocs.io/en/3.1/tutorial.html?highlight=save#saving-as-a-stream

update: I ended up having to use this with modifications

from tempfile import NamedTemporaryFile
from openpyxl import Workbook

wb = Workbook()

with NamedTemporaryFile() as tmp:
    tmp.close() # with statement opened tmp, close it so wb.save can open it
    wb.save(tmp.name)
    with open(tmp.name, 'rb') as f:
        f.seek(0) # probably not needed anymore
        new_file_object = f.read()

because the with statement opens the file and then wb.save (which expects a string filename) attempts to open it, resulting in an Exception

Cuddy answered 2/2, 2023 at 16:19 Comment(0)
J
5

The official recommendation does not work (as-is) on Windows + it uses the filesystem to save the workbook, even if only briefly.

Here a better method in my mind which is all in-memory:

with io.BytesIO() as buffer:
    wb.save(buffer)
    content = buffer.getvalue()

This works because the underlying ZipFile() used here accepts a file-like object in addition to filename.

Jarnagin answered 21/3, 2023 at 16:31 Comment(0)
W
4

I solve this issue by installing an older version 3.0.10 pip install openpyxl==3.0.10

Weigle answered 2/2, 2023 at 10:25 Comment(0)
P
1

For Django:

    file_stream = BytesIO()
    workbook.save(file_stream)
    response = HttpResponse(content=file_stream.getvalue(), content_type="application/ms-excel")
    response.content_type = "application/octet-stream;"
    response["Content-Disposition"] = f"attachment; filename=export.xlsx"
    return response
Pairoar answered 1/4, 2024 at 14:12 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.