You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Plotly Dash Table 如何导出带自定义格式的Excel文件

Dash Table导出带格式Excel的实现方案

问题原因

你之前的写法无法生效的核心原因有两点:

  • dcc.send_data_frame() 的第一个入参要求是DataFrame自带的导出方法(例如df.to_excel),它会自动封装DataFrame的转换逻辑。而writer.save()执行后返回值为None,作用是直接将生成的Excel写入本地磁盘,无法传递给Download组件触发下载。
  • 带自定义格式的Excel无法仅通过df.to_excel生成,需要用XlsxWriter完成格式配置后,将完整的Excel字节流传给下载组件。

可行实现方案

不需要将Excel文件存储到本地磁盘,直接在内存中生成带格式的Excel文件,再传递给dcc.Download触发下载即可,完整示例代码如下:

import dash
from dash.dependencies import Output, Input
import dash_html_components as html
import dash_core_components as dcc
import pandas as pd
import numpy as np
from io import BytesIO
from xlsxwriter.utility import xl_rowcol_to_cell

app = dash.Dash(__name__)
app.layout = html.Div([
    html.Button("下载带格式Excel", id="btn_xlsx"),
    dcc.Download(id="download-dataframe-xlsx"),
])

# 这里替换为你自己的DataFrame数据
df = pd.read_excel("../in/excel-comp-datav2.xlsx")

@app.callback(
    Output("download-dataframe-xlsx", "data"),
    Input("btn_xlsx", "n_clicks"),
    prevent_initial_call=True,
)
def generate_formatted_excel(n_clicks):
    # 在内存中创建BytesIO对象,替代本地文件路径
    output = BytesIO()
    
    # 以下是你原有的带格式Excel生成逻辑,输出到内存的output对象
    number_rows = len(df.index)
    df = df.assign(total=(df['Jan'] + df['Feb'] + df['Mar']))
    df = df.assign(quota_pct=(1+(df['total'] - df['quota'])/df['quota']))

    # 把ExcelWriter的输出指定为内存的BytesIO对象
    writer = pd.ExcelWriter(output, engine='xlsxwriter')
    df.to_excel(writer, index=False, sheet_name='report')

    workbook = writer.book
    worksheet = writer.sheets['report']

    # 原有格式配置逻辑
    worksheet.set_zoom(90)
    money_fmt = workbook.add_format({'num_format': '$#,##0', 'bold': True})
    percent_fmt = workbook.add_format({'num_format': '0.0%', 'bold': True})
    total_fmt = workbook.add_format({'align': 'right', 'num_format': '$#,##0',
                                     'bold': True, 'bottom':6})
    total_percent_fmt = workbook.add_format({'align': 'right', 'num_format': '0.0%',
                                             'bold': True, 'bottom':6})

    worksheet.set_column('B:D', 20)
    worksheet.set_column('E:E', 5)
    worksheet.set_column('F:F', 10)
    worksheet.set_column('G:K', 12, money_fmt)
    worksheet.set_column('L:L', 12, percent_fmt)

    for column in range(6, 11):
        cell_location = xl_rowcol_to_cell(number_rows+1, column)
        start_range = xl_rowcol_to_cell(1, column)
        end_range = xl_rowcol_to_cell(number_rows, column)
        formula = "=SUM({:s}:{:s})".format(start_range, end_range)
        worksheet.write_formula(cell_location, formula, total_fmt)

    worksheet.write_string(number_rows+1, 5, "Total",total_fmt)
    percent_formula = "=1+(K{0}-G{0})/G{0}".format(number_rows+2)
    worksheet.write_formula(number_rows+1, 11, percent_formula, total_percent_fmt)

    color_range = "L2:L{}".format(number_rows+1)
    format1 = workbook.add_format({'bg_color': '#FFC7CE',
                                   'font_color': '#9C0006'})
    format2 = workbook.add_format({'bg_color': '#C6EFCE',
                                   'font_color': '#006100'})
    worksheet.conditional_format(color_range, {'type': 'top',
                                               'value': '5',
                                               'format': format2})
    worksheet.conditional_format(color_range, {'type': 'bottom',
                                               'value': '5',
                                               'format': format1})

    # 关闭writer,把所有内容写入BytesIO
    writer.close()
    # 把BytesIO的指针移到文件开头,读取完整字节流
    output.seek(0)
    
    # 用dcc.send_bytes返回内存中的Excel文件,指定文件名
    return dcc.send_bytes(output.read(), "带格式导出结果.xlsx")

if __name__ == "__main__":
    app.run_server(debug=True)

注意事项

  • 如果你使用的pandas版本低于1.3.0,writer.close()可以替换为writer.save(),两者功能一致。
  • 整个生成过程不会在本地磁盘产生临时文件,所有操作都在内存中完成,性能更高。

内容的提问来源于stack exchange,提问作者Galat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 11:54:09