Agustin
Agustin

Reputation: 1526

Dash datatable save to excel or csv with popup window

Is it possible to save a dash datatable locally with the standard popup window? Where one can select location, file_name etc?

Thanks!

Upvotes: 1

Views: 4321

Answers (2)

Thomas
Thomas

Reputation: 1

A little late, but one solution that I found can be to use a clientside_callback and the showSaveFilePicker javascript function like such, where I download some data from a dcc.Store to a json file:

clientside_callback(
    """
    async function(data) {
        if (!data) {
            return dash_clientside.no_update;
        }
        try {
            const fileHandle = await window.showSaveFilePicker({
                suggestedName: 'data.json',
                types: [{
                    description: 'JSON file',
                    accept: {
                        'application/json': ['.json'],
                    },
                }],
            });
            const writableStream = await fileHandle.createWritable();
            await writableStream.write(data);
            await writableStream.close();
            return true;
        } catch (error) {
            console.log('error: ', error);
            return dash_clientside.no_update;
        }
    }
""",
    Output("dummy", "children"), # the callback doesn't return anything so a dummy output is used.
    Input("data_store", "data"), # data from the dcc.Store
)

Upvotes: 0

emher
emher

Reputation: 6014

I am not sure if the desired behavior can be achieved with the default table export mechanism (enabled by setting export_format argument), but it can be done using the Download component from dash-extensions==0.0.28. Here is a small example of the latter,

import dash
import dash_html_components as html
import pandas as pd

from dash.dependencies import Output, Input, State
from dash_extensions import Download
from dash_table import DataTable
from dash_extensions.snippets import send_data_frame

dt = DataTable(columns=[{"id": v, "name": v} for v in range(5)], data=[{v: v * 10 for v in range(5)}], id="table")
app = dash.Dash(prevent_initial_callbacks=True)
app.layout = html.Div([dt, html.Button("Download", id="btn"), Download(id="download")])


@app.callback(Output("download", "data"), [Input("btn", "n_clicks")], [State("table", "data")])
def download_table(n_clicks, data):
    df = pd.DataFrame.from_records(data)
    return send_data_frame(df.to_csv, "some_data.csv", index=False)


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

EDIT: As per Dash 1.20.0 the Download component has been merged into dash-core-components. The above example can thus be rewritten without the use of any third-party libraries,

import dash
import dash_html_components as html
import dash_core_components as dcc
import pandas as pd
from dash.dependencies import Output, Input, State
from dash_table import DataTable

dt = DataTable(columns=[{"id": v, "name": v} for v in range(5)], data=[{v: v * 10 for v in range(5)}], id="table")
app = dash.Dash(prevent_initial_callbacks=True)
app.layout = html.Div([dt, html.Button("Download", id="btn"), dcc.Download(id="download")])

@app.callback(Output("download", "data"), [Input("btn", "n_clicks")], [State("table", "data")])
def download_table(n_clicks, data):
    df = pd.DataFrame.from_records(data)
    return dcc.send_data_frame(df.to_csv, "some_data.csv", index=False)

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

Upvotes: 3

Related Questions