如何用ipywidget按钮下载带样式的Pandas DataFrame Excel文件?
解决带样式Pandas DataFrame的ipywidget按钮下载问题
以下是修正后的完整代码,同时解决你提出的两个疑问:
import ipywidgets import numpy as np import pandas as pd import io import base64 from IPython.display import HTML, display from ipywidgets import widgets from typing import Callable import pandas.io.formats.style class DownloadButtonExcel(ipywidgets.Button): """ 带动态内容的下载按钮 点击按钮时通过回调生成带样式的Excel文件并触发下载,无需本地存储文件 """ def __init__(self, filename: str, contents: Callable[[], pandas.io.formats.style.Styler], **kwargs): super(DownloadButtonExcel, self).__init__(**kwargs) self.filename = filename self.contents = contents self.on_click(self.__on_click) self.output = widgets.Output() display(self.output) def __on_click(self, b): # 点击按钮时才获取带样式的DataFrame styler = self.contents() # 使用内存缓冲区存储Excel内容,不写入本地文件 buffer = io.BytesIO() styler.to_excel(buffer, engine='openpyxl') buffer.seek(0) # 将缓冲区内容编码为base64,生成可嵌入HTML的Data URI b64 = base64.b64encode(buffer.read()).decode() data_uri = f"data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,{b64}" # 生成唯一ID避免浏览器缓存 digest = pd.util.hash_pandas_object(styler.data).sum() id = f"dl_{digest}" with self.output: # 清空之前的输出,避免重复生成下载链接 self.output.clear_output(wait=True) display( HTML( f""" <html> <body> <a id="{id}" download="{self.filename}" href="{data_uri}"></a> <script> document.getElementById('{id}').click(); </script> </body> </html> """ ) ) # 测试示例 df = pd.DataFrame( [[38.0, 2.0, 18.0, 22.0, 21, np.nan],[19, 439, 6, 452, 226,232]], index=pd.Index(['Tumour (Positive)', 'Non-Tumour (Negative)'], name='Actual Label:'), columns=pd.MultiIndex.from_product( [['Decision Tree', 'Regression', 'Random'],['Tumour', 'Non-Tumour']], names=['Model:', 'Predicted:'] ) ) df_style = df.style.format(precision=2).background_gradient().hide(axis='index') download_button_excel = DownloadButtonExcel( filename="Test.xlsx", contents=lambda: df_style, description="下载带样式Excel", style={"button_color": "#4CAF50"} )
问题解决说明
1. 实现类似CSV的编解码下载逻辑
- 不再使用本地文件存储,改用
io.BytesIO内存缓冲区暂存Styler生成的Excel内容 - 通过
base64.b64encode将二进制Excel内容编码为字符串,生成符合Data URI规范的链接,直接嵌入到HTML的<a>标签中,浏览器会识别并触发文件下载,完全在内存中完成处理,不会留下本地文件
2. 将Excel生成逻辑移至点击触发函数内
- 所有Excel文件的生成、编码逻辑都放在按钮的
__on_click方法中,只有当用户点击按钮时才会执行styler.to_excel等操作,避免提前生成文件,完全由点击事件触发下载流程
内容的提问来源于stack exchange,提问作者Chenyang
相关产品推荐
相关产品推荐

