DEV Community

Cover image for Creating a CSV to Graph Generator App Using ToolJet and Python Libraries ๐Ÿš€
Karan Rathod for ToolJet

Posted on • Originally published at blog.tooljet.com

Creating a CSV to Graph Generator App Using ToolJet and Python Libraries ๐Ÿš€

In this tutorial, we'll create a CSV to Graph Generator app using ToolJet and Python code. This app enables users to upload a CSV file and generate various types of graphs, including line, scatter, bar, histogram, and box plots. Since ToolJet supports Python (and JavaScript) code out of the box, we'll incorporate Python code and the matplotlib library to handle the graph generation. Additionally, we'll use ToolJet's customizable pre-built components to design an intuitive user interface in minutes.

Here's a quick preview of the complete application:

Image description

Check out this tutorial to learn how to develop a QR code generator using ToolJet.


Prerequisites


Begin by creating an application named CSV To Graph Generator.

Step 1: Designing the User Interface

Let's use ToolJet's visual app builder to quickly design the UI.

Designing the Header

  • Drag and drop a Text component onto the canvas for the header. Rename this component to headerText and set its text to "CSV TO GRAPH GENERATOR."
  • Customize its styling properties to have:
    • Text size: 25
    • Font weight: bolder
    • Text color: #375fcfff
    • Text alignment: right

This will serve as the header text of your app.

  • Add an Icon component, naming it logo. Set the icon to IconChartAreaFilled and the icon color to #375fcfff. Position it appropriately on the canvas to complement the header text.

Image description

Creating the CSV Upload Section

  • Drag a Container component onto the canvas. Style this container with:
    • Border radius: 7
    • Background color: #fff
    • Box shadow: 2px 2px 1px 1px #aec0f5ff

This container will hold all the input fields and output preview.

  • Inside the container, add a File Picker component and rename it to fileUploader. Set its Accept file types property to {"csv/*"} to accept CSV files. Enable the Parse content toggle, and select File type as CSV.

  • Next, add a Dropdown component next to the File Picker, rename it to graphSelectionDropdown. Set the component's Option values to ["line", "scatter", "bar", "histogram", "box"] and Option labels to ["Line", "Scatter", "Bar", "Histogram", "Box"].

  • Below the dropdown, add a Button component and rename it to generateGraphButton. Set its text to "Generate Graph".

Image description

Double curly braces in ToolJet are used to pass custom code and refer or access values.

Creating the Image Preview

To display the generated graph, add an Image component below the File Picker and Button.

Image description

The UI is now ready!


Step 2: Using Python Libraries through Queries

ToolJet's query builder offers a convenient way to use custom code or connect with external data sources, services, and libraries. We will use it to create a Python query that uses the CSV data and interacts with the matplotlib library to generate graphs.

  • Expand the query panel at the bottom, create a new query named generateGraph, and choose Python as the data source.
  • Enter the below code in your Python query:

    import matplotlib.pyplot as plt
    import pandas as pd
    import numpy as np
    from io import BytesIO
    import base64
    import io
    
    def create_plot():
        try:
            csv_string = components.fileUploader.file[0].content
            graph_type = components.graphSelectionDropdown.value
            print("Debug info:", csv_string, graph_type)
    
            df = pd.read_csv(io.StringIO(csv_string))
            columns = df.columns.tolist()
    
            if len(columns) < 2:
                raise ValueError("CSV must contain at least two columns")
    
            x_column = columns[0]
            y_columns = columns[1:]
    
            plt.figure(figsize=(12, 6))
    
            if graph_type == 'line':
                for col in y_columns:
                    plt.plot(df[x_column], df[col], label=col)
                plt.title(f'Line Plot: {x_column} vs {", ".join(y_columns)}')
                plt.legend()
                plt.xticks(rotation=45, ha='right')
            elif graph_type == 'scatter':
                if len(y_columns) >= 2:
                    plt.scatter(df[y_columns[0]], df[y_columns[1]])
                    plt.title(f'Scatter Plot: {y_columns[0]} vs {y_columns[1]}')
                    plt.xlabel(y_columns[0])
                    plt.ylabel(y_columns[1])
                else:
                    plt.scatter(df[x_column], df[y_columns[0]])
                    plt.title(f'Scatter Plot: {x_column} vs {y_columns[0]}')
                    plt.xlabel(x_column)
                    plt.ylabel(y_columns[0])
            elif graph_type == 'bar':
                x = range(len(df[x_column]))
                width = 0.8 / len(y_columns)
                for i, col in enumerate(y_columns):
                    plt.bar([xi + i*width for xi in x], df[col], width, label=col)
                plt.xlabel(x_column)
                plt.ylabel('Value')
                plt.title(f'Bar Plot: {", ".join(y_columns)}')
                plt.xticks([xi + width*(len(y_columns)-1)/2 for xi in x], df[x_column], rotation=45, ha='right')
                plt.legend()
            elif graph_type == 'histogram':
                for col in y_columns:
                    plt.hist(df[col], bins=10, alpha=0.5, label=col)
                plt.title(f'Histogram: {", ".join(y_columns)}')
                plt.xlabel('Value')
                plt.ylabel('Frequency')
                plt.legend()
            elif graph_type == 'box':
                plt.boxplot([df[col] for col in y_columns])
                plt.title(f'Box Plot: {", ".join(y_columns)}')
                plt.xticks(range(1, len(y_columns) + 1), y_columns, rotation=45, ha='right')
                plt.ylabel('Value')
            else:
                raise ValueError(f"Invalid graph type: {graph_type}. Choose 'line', 'scatter', 'bar', 'histogram', or 'box'.")
    
            plt.grid(True)
            plt.tight_layout()
    
            buffer = BytesIO()
            plt.savefig(buffer, format='png')
            buffer.seek(0)
    
            img_str = base64.b64encode(buffer.getvalue()).decode('utf-8')
    
            plt.close()
    
            return img_str
        except Exception as e:
            print(f"Error in create_plot: {str(e)}")
            return None
    
    create_plot()
    

Image description

Once this is configured, you can select a CSV file in the File Picker, select the graph type, and click on the Run button in the query panel. You can see the output generated by the query under preview.


Step 3: Connecting the UI Components with the Query

Time to bind the query to the components.

Configuring the Image Preview

  • In the Data property of the Image component, enter the following code to bind the query's result:

    {{'data:image;base64,' + queries.generateGraph.data}}
    
  • For the Loading state property of the Image component, click on the fx button to enter custom code and enter the below code:

    {{queries.generateGraph.isLoading}}
    

Triggering the Query Based on Button Click

Bind the query to the generateGraphButton by adding an on Click event that triggers the generateGraph query. This setup ensures that the script runs and generates the graph when the button is clicked.

Image description

After this setup, every time you upload a CSV file, select a graph type, and click on the generateGraphButton, the graph will be created and a preview will be visible in the Image component.

Image description


Conclusion

By following these steps, we've successfully built a dynamic and user-friendly CSV to Graph Generator app with ToolJet. We utilized ToolJet's visual app builder to craft an elegant and intuitive UI, used the query builder to integrate a Python library for graph generation, and demonstrated how to customize ToolJet applications to deliver a smooth user experience.

To learn and explore more about ToolJet, check out the ToolJet docs or connect with us and post your queries on our Slack channel.

Top comments (2)

Collapse
 
baconsmith profile image
Bacon Smith

Please do some more tutorials on Python. These are very useful for prototyping.

Collapse
 
karanrathod316 profile image
Karan Rathod

Sure, we will look into it.