Dash DataTable - Is it possible to save DataTable output after adding row and additional manual modification of cells

Is it possible to save to CSV Dash DataTable after user’s manual modification (for example changing text in the cells)?

Script below add new row to Dash DataTable. For test purpose please change manually as well cell value…

1) Can save Dash DataTable output after adding line and manual modification to CSV file? I have already created "Save new row" button, which is intended to save file to CSV file.
  1. Is there any possibility in dash to create message to user, for example if user clicks more than one time to the “add new row” button?

import dash
from dash.dependencies import Input, Output, State
import dash_core_components as dcc
import dash_html_components as html
import dash_table_experiments as dt

app = dash.Dash()

app.scripts.config.serve_locally = True
app.css.config.serve_locally = True

INITIAL_ROWS = [
{‘a’: ‘Miami’, ‘b’: “FL”},
{‘a’: ‘Redwood City’, ‘b’: “CA”},
{‘a’: ‘Chicago’, ‘b’: “IL”}
]

EXTRA_ROWS = [
{‘a’: ‘Naperville’, ‘b’: “IL”}]

app.layout = html.Div([
dt.DataTable(rows=INITIAL_ROWS, row_selectable=False,
filterable=True, sortable=True,
selected_row_indices=[], id=‘my_cities_datatable’),
html.Button(“Add new row”, id=‘get_new_row_button_id’),
html.Button(“Save new row”, id=‘save_new_row_button_id’),
], className=“container”)

@app.callback(
Output(‘my_cities_datatable’, ‘rows’),
[Input(‘get_new_row_button_id’, ‘n_clicks’),
Input(‘get_new_row_button_id’, ‘id’)])
def get_new_row(n_clicks, id_name):
print
“n_clicks=%s, id_name=%s” % (n_clicks, id_name)
if n_clicks == None:
return INITIAL_ROWS
if n_clicks ==1:
return INITIAL_ROWS + EXTRA_ROWS
if n_clicks > 1:
return print(“save current row before adding another row”)

app.css.append_css({
“external_url”: “https://codepen.io/chriddyp/pen/bWLwgP.css
})

if name == ‘main’:
app.run_server(debug=True)

1 Like

I second this request. You can download the rows (after modification) to csv using Download raw data
But if you initiate any callback before downloading them, the changes made will be lost. I haven’t quiet figured out a workaround yet.

This solution works for me:

# -*- coding: utf-8 -*-

import dash
from dash.dependencies import Input, Output, State
import dash_core_components as dcc
import dash_html_components as html
import dash_table_experiments as dt
import json
import pandas as pd
import plotly


app = dash.Dash()

app.scripts.config.serve_locally = True

DF_SIMPLE = pd.DataFrame({
    'x': ['A', 'B', 'C', 'D', 'E', 'F'],
    'y': [4, 3, 1, 2, 3, 6],
    'z': ['a', 'b', 'c', 'a', 'b', 'c']
})


app.layout = html.Div([
    html.H4('Editable DataTable'),
    dt.DataTable(
        rows=DF_SIMPLE.to_dict('records'),


        # optional - sets the order of columns
        columns=sorted(DF_SIMPLE.columns),

        filterable=True,
        sortable=True,
        editable=True,

        id='editable-table'
    ),
    html.Div([
        html.Button('Save', id='save-button'),
        html.P(id='editable-table-hidden', style={'display':'none'}),
        html.P(id='save-button-hidden', style={'display':'none'}),
    

    ], className='row')
], className='container')


@app.callback(
    Output('editable-table-hidden', 'children'),
    [Input('editable-table', 'rows')])
def update_selected_row_indices(rows):
    global DF_SIMPLE
    DF_SIMPLE = pd.DataFrame(rows)
    return json.dumps(rows, indent=2)


@app.callback(
    Output('save-button-hidden', 'children'),
    [Input('save-button', 'n_clicks')])
def clicks(n_clicks):
    if n_clicks > 0:
        DF_SIMPLE.to_csv('df.csv', index=False, encoding='utf-8')


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

This doesn’t really work though. Once I refresh the page, the table returns the original values.

2 Likes

Have you figured it out? How to keep values changed when you refresh the page? I am having the same issue.

1 Like

I couldn’t do it in Dash not sure if it’s intended for complex data tables, I have learned JavaScript and program tables in ag- grid…

1 Like

I added a ‘save’ button, which triggers a callback that’s saves data table to csv.
Theres another thread that explains adding the row, ill attach it here when I find it

Great, please share when you find it.

This is in our documentation! Please read through the dash table user guide, we spent a ton of time outlining all of these use cases.
This is in part 5 (“Adding or removing rows”)
image
dash table user guide here: Dash DataTable | Dash for Python Documentation | Plotly

3 Likes

Hey Chris! I checked the link you provided above but is there any documentation specific to when the end user edits specific cells of the table? That is, after they make the necessary changes, the datatable is saved and even after refreshing the page it shows the table with the corrected changes.

2 Likes

@ragesz - I don’t think the table data saves to the original df. The data behind the table is saved in a separate list of Dicts. But you can use Pandas from_records to put that in a DF and save it.

@application.callback(Output('table-action-outputs', 'children'),
              [Input('table-editing-simple', 'data_timestamp'),
              Input('table-editing-simple', 'active_cell'),
              Input('table-editing-simple', 'data')])
def update_database(time_updated, cell_coordinates, table_data):
    time_updated_new = round(time_updated / 1000) + 10
    saved = pd.DataFrame.from_records(table_data)
    saved.to_csv('/home/username/data_cleaning_app_updates.csv', index=False)
4 Likes

Could you utilize the Store() component? I started playing around with a dataframe editor with the thought process being:

Select DF
Store DF in component
Display DF in Table populated and created via app.callback() to children
User Edits DF
User ‘Saves’
Overwrite DF in Component
Repeat until completed