Upload Component - upload excel-file and use it as input for function

Hi.
I am working on a project where I use an excel-file as input (I read from the file using pandas) and then I do multiple calculations based on the data from the file. The excel-file itself has multiple worksheets. I then display my results in a gantt chart. Now when I run the code directly (I use spyder), it’s very simple, this is all it takes:

if __name__=='__main__':
    input_file = "JSP_dataset_test_5-3.xlsx"
    main_code(input_file)

What I would like to do now is do build dashboard that also displays my results but further allows for some interactivity. I need the user to be able to upload the excel file and this file should then be used as the input_file for my main_code. How should I do that?
I managed to build a dashboard without the upload component, just with a start button to run the code and gantt chart to display my results. Works perfectly.
But I can’t figure out the upload component. Can anyone help with that?

This is what I got so far:

import base64
import datetime
import io

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

import pandas as pd
import SCHED_main_code as sched

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

app.layout = html.Div([
             dcc.Upload(
                     id='upload-data',
                     children=html.Div([
                                       'Drag and Drop or ',
                                        html.A('Select Files')
                                            ]),
                     style={
                           'width': '100%',
                           'height': '60px',
                           'lineHeight': '60px',
                           'borderWidth': '1px',
                           'borderStyle': 'dashed',
                           'borderRadius': '5px',
                           'textAlign': 'center',
                           'margin': '10px'
                               },
    # Allow multiple files to be uploaded
                   multiple=True
                     ),
            html.Div(id='output-data-upload'),
 ])


 def parse_contents(contents, filename, date):
      content_type, content_string = contents.split(',')

      decoded = base64.b64decode(content_string)
      try:
           if 'csv' in filename:
           # Assume that the user uploaded a CSV file
                df = pd.read_csv(io.StringIO(decoded.decode('utf-8')), sheet_name='MS')
                df2 = pd.read_csv(io.StringIO(decoded.decode('utf-8')), sheet_name='PT')  
                df3 = pd.read_csv(io.StringIO(decoded.decode('utf-8')), sheet_name='PD')
                df4 = pd.read_csv(io.StringIO(decoded.decode('utf-8')), sheet_name='SM1')
                df5 = pd.read_csv(io.StringIO(decoded.decode('utf-8')), sheet_name='SM2')
                df6 = pd.read_csv(io.StringIO(decoded.decode('utf-8')), sheet_name='SM3')
                df7 = pd.read_csv(io.StringIO(decoded.decode('utf-8')), sheet_name='SM4')
                df8 = pd.read_csv(io.StringIO(decoded.decode('utf-8')), sheet_name='SM5')
                df9 = pd.read_csv(io.StringIO(decoded.decode('utf-8')), sheet_name='T')
           elif 'xls' in filename:
           # Assume that the user uploaded an excel file
                df = pd.read_excel(io.BytesIO(decoded), sheet_name='MS')
                df2 = pd.read_excel(io.BytesIO(decoded), sheet_name='PT')  
                df3 = pd.read_excel(io.BytesIO(decoded), sheet_name='PD')
                df4 = pd.read_excel(io.BytesIO(decoded), sheet_name='SM1')
                df5 = pd.read_excel(io.BytesIO(decoded), sheet_name='SM2')
                df6 = pd.read_excel(io.BytesIO(decoded), sheet_name='SM3')
                df7 = pd.read_excel(io.BytesIO(decoded), sheet_name='SM4')
                df8 = pd.read_excel(io.BytesIO(decoded), sheet_name='SM5')
                df9 = pd.read_excel(io.BytesIO(decoded), sheet_name='T')
        
      except Exception as e:
          print(e)
          return html.Div([
              'There was an error processing this file.'
                   ])

 #    data = sched.main_code(df,df2,df3,df4,df5,df6,df7,df8,df9) 
 #    gantt_data = data[0]
 #    gantt_figure = data[1]     

    return html.Div([
               html.H5(filename),
               html.H6(datetime.datetime.fromtimestamp(date)),

               dash_table.DataTable(
                   data=df.to_dict('rows'),
                   columns=[{'name': i, 'id': i} for i in df.columns]
                            ),
               html.Hr(),
           #    dcc.Graph(gantt_figure),
               html.Hr(),  # horizontal line

        # For debugging, display the raw contents provided by the web browser
               html.Div('Raw Content'),
               html.Pre(contents[0:200] + '...', style={
                         'whiteSpace': 'pre-wrap',
                         'wordBreak': 'break-all'
                     })
                   ])


@app.callback(Output('output-data-upload', 'children'),
              [Input('upload-data', 'contents')],
              [State('upload-data', 'filename'),
               State('upload-data', 'last_modified')])
def update_output(list_of_contents, list_of_names, list_of_dates):
    if list_of_contents is not None:
        children = [
            parse_contents(c, n, d) for c, n, d in
            zip(list_of_contents, list_of_names, list_of_dates)]
    return children



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

I copied most of the code from the example in the dash user guide. Now I managed to choose specific sheets from my uploaded excel file and display the contents in the DataTable. Adding a couple more DataTables and filling them with specific sheets was also not a problem.
But what I need to do is use the data as input for my importet module (this line is commented out in the parse_contents function). If I run that line, the app does not return anything. Not even the datatables that worked fine before.
The importet module (sched) returns a dataframe and a gantt figure (all defined and ready the use). I would like to display the gantt chart. I was able to display it in another app, but that was without the upload component.

1 Like