【问题标题】:Saving openpyxl file via text and filestream通过文本和文件流保存 openpyxl 文件
【发布时间】:2012-01-18 04:08:19
【问题描述】:

我正在将 OpenPyXL 构建到一个应用程序中,该应用程序需要一个包含 excel 文件内容的字符串,以便它通过文件流写入。

根据我对 OpenPyXL 源代码的调查,它看起来并不支持这种输出。有没有人有修改 openpyxl 以支持此功能的经验?

或任何一般性建议/解决方法?

谢谢。

【问题讨论】:

    标签: python excel filestream openpyxl


    【解决方案1】:

    jcollado 的回答实际上是有效的,但在 openpyxl.writer.excel 中还有一个名为“save_virtual_workbook”的函数(遗憾的是尚未记录),它将获取您的工作簿并将工作簿作为字符串返回:

    from openpyxl.workbook import Workbook
    from openpyxl.writer.excel import save_virtual_workbook
    
    wb = Workbook()
    print save_virtual_workbook(wb)
    

    您要查找的是 save_virtual_workbook() 返回的字符串

    【讨论】:

    • 这正是我需要通过文件流保存的。您也可以将其保存为:io.BytesIO(save_virtual_workbook(wb))
    • 我们不应该再使用这个功能了。 Deprecated: Use a NamedTemporaryFile。见the documentation
    【解决方案2】:

    在 openpyxl 2.6 中调用 save_virtual_workbook 方法会发出以下警告:

    DeprecationWarning: Call to deprecated function save_virtual_workbook (Use a NamedTemporaryFile).
    

    在某些时候,save_virtual_workbook 将从 openpyxl 中删除。

    在 Python 3 中,将 openpyxl 工作簿保存到文件流的典型用法变为:

    from io import BytesIO
    from tempfile import NamedTemporaryFile
    from openpyxl import Workbook
    
    wb = Workbook()
    with NamedTemporaryFile() as tmp:
        wb.save(tmp.name)
        output = BytesIO(tmp.read())
    
    

    查看 WorkBook save 方法的实现后,“文件名”被直接发送到 ZipFile,它接受路径或类似文件的对象,因此不需要 NamedTemporaryFile,只需使用内存中的 BytesIO:

    from io import BytesIO
    from openpyxl import Workbook
    
    wb = Workbook()
    virtual_workbook = BytesIO()
    wb.save(virtual_workbook)
    
    # now use virtual_workbook to send to a stream; email attachment, etc
    
    

    【讨论】:

    • 能否请您回答一下我们应该如何发送 virtual_workbook 以发送到流或电子邮件或通过 API 响应。
    【解决方案3】:

    如何使用StringIO 对象来保存文件的内容:

    from openpyxl.workbook import Workbook
    from StringIO import StringIO
    
    output = StringIO()
    wb = Workbook()
    wb.save(output)
    print output.getvalue()
    

    您要查找的字符串是本示例最后一行打印的内容。

    【讨论】:

    • 这似乎不起作用.. wb.save() 只是期待一个文件名(一个 str-object),而不是一个 IO-Byte-object 的东西
    • 确认这不起作用。无论您向 wb 的 save 方法提供什么,都试图将其用作文件名。
    • 我的 openpyxl 2.3.3。适用于此,但需要io.BytesIO
    • 只是为了支持这一点-检查openpxyl code on this,它只是将filename传递给Python的ZipFile library,它接受或者文件名 一个类似文件的对象(例如BytesIO)。不幸的是,自从出现这种情况以来,我一直无法找到。
    【解决方案4】:

    save_virtual_workbook 兼容的实现自 2.6 版起已弃用:

    from io import BytesIO
    from tempfile import NamedTemporaryFile
    
    
    def save_virtual_workbook(workbook):
        with NamedTemporaryFile() as tf:
            workbook.save(tf.name)
            in_memory = BytesIO(tf.read())
            return in_memory.getvalue()
    

    【讨论】:

    • 我已经尝试过这种方法,但我得到了Object of type bytes is not JSON serializable。更多信息:stackoverflow.com/questions/62519571/…
    • @JackTheKnife 你在使用 Django Rest 框架吗?如果您能提供最少的代码,将会很有帮助。
    【解决方案5】:
    from openpyxl import Workbook
    from io import BytesIO
    
    rows = [[1,2], [3,4]]
    
    book = Workbook()
    sheet = book.active
    
    for row in rows:
        sheet.append(row)
    
    io = BytesIO
    book.save(io)
    
    content = io.getValue()
    
    return Response(
        content,
        mimetype=magic.from_buffer(content, mime=True),
        headers={
        'Content-Disposition': 'attachment;filename=' + 'test.xlsx'}
    )
    

    【讨论】:

    • 我需要 openpyxl 来使用字体颜色
    • 有一个错字,应该是content = io.getvalue()
    • 此解决方案不适用于最新版本的 python 和 openpyxl。 TypeError: descriptor 'tell' of '_io.BytesIO' object needs an argument
    • @MrAlihoseiny 您收到此错误是因为 io 已分配给 BytesIO 的功能。要获取BytesIO 的值,请像这样调用io = BytesIO()
    猜你喜欢
    • 2017-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多