How to Create a File Upload Page in React to Display Excel Data as a Table and Send it as an Array of Objects
Tags: webdev, react, tutorial, javascript
Published: 2023-07-18 03:35:05

In today's digital world, efficient data management plays a crucial role in various applications across diverse domains. One powerful feature that simplifies data import and manipulation is the ability to upload Excel files (XLSX) directly into web applications. In this tutorial, we'll explore how to build a React application that allows users to upload an XLSX file, display its data as a table, and seamlessly send the data to a backend as an array of objects. This functionality finds valuable applications in real-world scenarios, such as data import and management, inventory control, HR operations, and more.

## Step 1: Set Up the React Project
Create a new React project using create-react-app. Open your terminal and run the following command:

```
npx create-react-app excel-file-upload
cd excel-file-upload
```
## Step 2: Install Dependencies
We'll use xlsx for Excel file parsing, react-dropzone for file drop functionality, and react-bootstrap for styling. Install these dependencies by running:

```
npm install xlsx react-dropzone react-bootstrap @mui/material @mui/icons-material

```
## Step 3: Create the Excel File Uploader Component
Now, let's create the ExcelFileUploader component. Replace the content of src/App.js with the following:

```
// src/ExcelFileUploader.js
import React, { useState } from "react";
import * as XLSX from "xlsx";
import Dropzone from "react-dropzone";
import { Button } from "react-bootstrap";
import Row from "react-bootstrap/Row";
import Col from "react-bootstrap/Col";
import { Box, Modal } from "@mui/material";
import CloseIcon from "@mui/icons-material/Close";

const ExcelFileUploader = () => {
  // State variables
  const [data, setData] = useState([]);
  const [showForm, setShowForm] = useState(false);
  const [deletePrevious, setDeletePrevious] = useState(false);

  // Handle form close
  const handleFormClose = () => {
    setShowForm(false);
  };

  // Handle file drop
  const handleFileDrop = async (acceptedFiles) => {
    const file = acceptedFiles[0];
    if (file.type !== "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") {
      alert("We support only xlsx format. Please upload an Excel file.");
      return;
    }
    const reader = new FileReader();

    reader.onload = function (e) {
      const data = e.target.result;
      const workbook = XLSX.read(data, { type: "binary" });
      const sheetName = workbook.SheetNames[0];
      const worksheet = workbook.Sheets[sheetName];
      const parsedData = XLSX.utils.sheet_to_json(worksheet, { header: 1 });

      // Assuming the first row contains the column headers
      const headers = parsedData[0];
      const rows = parsedData.slice(1);

      const result = rows.map((row) => {
        const obj = {};
        headers.forEach((header, index) => {
          obj[header] = row[index];
        });
        return obj;
      });

      setData(result);
    };

    reader.readAsBinaryString(file);
  };

  // Handle form submission
  const handleSubmit = (e) => {
    e.preventDefault();
    if (data.length > 0) {
      // Convert data to the required format for backend
      const stockArray = data.map((item) => ({
        Name: item.Name,
        Description: item.Description,
        SKUCode: item["SKU Code"],
        StockCategory: item["Stock Category"],
        Price: item.Price,
        BrandName: item["Brand Name"],
        ProductName: item["Product Name"],
      }));

      // Send data to backend
      postAddCatering(stockArray);
    } else {
      alert("Please upload an Excel file before submitting.");
    }
  };

  // Send data to backend API
  const postAddCatering = async (stockArray) => {
    // Replace "https://example.com/" with your actual backend API URL
    const url = "https://example.com/";
    const myHeaders = new Headers();
    myHeaders.append("Content-Type", "application/json");

    const raw = JSON.stringify({
      payload: {
        body: {
          query_type: "upload_stocks",
          stock_array: stockArray,
          supplier_id: 1,
          deletePrevious: deletePrevious,
        },
      },
    });

    const requestOptions = {
      method: "POST",
      headers: myHeaders,
      body: raw,
      redirect: "follow",
    };

    try {
      const response = await fetch(url, requestOptions);
      const dataResponse = await response.json();
      if (dataResponse.success === true) {
        alert("Stock List Uploaded Successfully");
        window.location.reload();
      } else {
        alert("Please try again");
        window.location.reload();
      }
    } catch (error) {
      alert("Please try again");
      window.location.reload();
    }
  };

  // Render the component
  return (
    <div>
      <Dropzone onDrop={handleFileDrop}>
        {({ getRootProps, getInputProps }) => (
          <div {...getRootProps()}>
            <input {...getInputProps()} />
            <p>
              Drag and drop an Excel file here, or <strong>click to select one</strong>
            </p>
            <Button>Select</Button>
          </div>
        )}
      </Dropzone>
      <div style={{ paddingBottom: "20px", paddingTop: "20px", paddingLeft: "40%" }}>
        <Button onClick={() => setShowForm(true)}>Submit</Button>
      </div>
      {/* Display the table with data */}
      {/* ... (table code as in the original component) */}
      <Modal
        aria-labelledby="transition-modal-title"
        aria-describedby="transition-modal-description"
        open={showForm}
        onClose={handleFormClose}
        className="modalnvm"
      >
        <Box className="modalnvm-content">
          <CloseIcon
            className="plzHover"
            fontSize="large"
            style={{ margin: 10, float: "right" }}
            onClick={handleFormClose}
          />
          <label>
            <input
              className="paddingPlease"
              type="checkbox"
              checked={deletePrevious}
              onChange={(e) => setDeletePrevious(e.target.checked)}
            />
            <span className="paddingPlease">
              Would you like to delete the previous stock catalog?
            </span>
          </label>
          <span style={{ paddingRight: "40%" }}>
            <Button onClick={handleSubmit}>Confirm</Button>
          </span>
        </Box>
      </Modal>
    </div>
  );
};

export default ExcelFileUploader;

```
In this article, we have built a React application that allows users to upload an Excel file, view its content as a table, and send the data as an array of objects to a backend API. We used the xlsx library to parse the Excel file, react-dropzone for file drop functionality, and react-bootstrap for styling.