Implementing the Excel File Preview Component

Implementing the Excel File Preview Component
Implementing the Excel File Preview Component

In this blog post, we'll take a deep dive into a React component -->ExcelFilePreview designed to handle and preview Excel files, enabling users to preview Excel data before deciding to upload it. We'll dissect the code step by step to understand its functionality.

Introduction

The ExcelFilePreview component is built using React and relies on the xlsx library for Excel file handling. It provides users with a modal interface that displays the contents of an Excel file, empowering them to preview the data before making an upload decision. Let's explore the code that makes this happen.

Importing Dependencies

import React, { useState, useEffect } from "react";
import XLSX from "xlsx";
import Modal from "@mui/material/Modal";
import Box from "@mui/material/Box";
import Paper from "@mui/material/Paper";
import Table from "@mui/material/Table";
import TableBody from "@mui/material/TableBody";
import TableCell from "@mui/material/TableCell";
import TableContainer from "@mui/material/TableContainer";
import TableHead from "@mui/material/TableHead";
import TableRow from "@mui/material/TableRow";
import Button from "@mui/material/Button";
import "./ExcelFilePreview.css"; // You can create a CSS file for styling
importing dependencies

Component Definition

export default function ExcelFilePreview({ file, onClose, uploadFunction }) {
  const [excelData, setExcelData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [progress, setProgress] = useState(0);
}
Component Definition

The ExcelFilePreview component is defined as a functional React component that accepting the props: file, onClose, and uploadFunction.

  • file: Represents the Excel file that users want to preview.
  • onClose: A callback function to close the modal.
  • uploadFunction: A function responsible for uploading the selected Excel file from other components.

State Management

  const [excelData, setExcelData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [progress, setProgress] = useState(0);
State Management
  • excelData: state variable holds the data extracted from the Excel file.
  • loading: indicates whether the file is still being processed.
  • progress: This variable represents the progress of processing the file, ranging from 0 to 100%.(counter++)

Handling File Processing with useEffect

  useEffect(() => {
    if (file) {
      const reader = new FileReader();
      reader.onload = (e) => {
        const data = new Uint8Array(e.target.result);
        const workbook = XLSX.read(data, { type: "array" });
        const sheetName = workbook.SheetNames[0];
        const sheet = workbook.Sheets[sheetName];
        const dataJson = XLSX.utils.sheet_to_json(sheet, { header: 1 });
        setExcelData(dataJson);

        for (let i = 1; i <= 100; i++) {
          setTimeout(() => {
            setProgress(i);
          }, i * 10);
        }

        setTimeout(() => {
          setLoading(false);
        }, 1000);
      };
      reader.readAsArrayBuffer(file);
    }
  }, [file]);
Handling File Processing with useEffect

useEffect hook, component that handles the processing of the Excel file.

  1. FileReader - created to read the content of the Excel file.
  2. When the reader finishes loading the file, it converts the data into a Uint8Array.
  3. The xlsx library is used to parse the Excel data, extract the first sheet, and convert it into a JSON format.
  4. The extracted data is stored in the excelData state variable.
  5. During processing, a loading animation is displayed, and the progress variable is updated incrementally to reflect the file processing progress.
  6. After processing, the loading state is set to false.

Handling Form Submission

  const handleSubmit = () => {
    if (excelData) {
      uploadFunction(file);
      onClose();
    }
  };
Handling Form Submission


handleSubmit function is called when the user decides to upload the Excel file. It checks if excelData contains data, indicating that the file has been processed. If data is available, it triggers the uploadFunction to upload the file and closes the modal using the onClose callback.

Displaying the Modal

  return (
    <Modal open={true} onClose={onClose}>
      <Box
        sx={{
          position: "absolute",
          top: "50%",
          left: "50%",
          transform: "translate(-50%, -50%)",
          width: "80%",
          maxHeight: "80%",
          bgcolor: "background.paper",
          boxShadow: 24,
          p: 4,
          display: "flex",
          flexDirection: "column",
        }}
      >
        <h2 style={{ fontSize: '24px', color: 'green' }}>FileName - {fileName}</h2>
        {loading ? (
          <div style={{ textAlign: "center" }}>
            <p>Loading... {progress}%</p>
            <div className="loader"></div>
          </div>
        ) : (
          <TableContainer
            component={Paper}
            sx={{
              flex: 1,
              overflowY: "auto",
              "& .MuiTableCell-root": {
                borderBottom: "1px solid #e0e0e0",
              },
            }}
          >
            <Table>
              <TableHead>
                <TableRow>
                  {excelData &&
                    excelData[0].map((cell, index) => (
                      <TableCell
                        key={index}
                        style={{
                          position: "sticky",
                          top: 0,
                          background: "grey",
                          zIndex: 1,
                          fontWeight: "bold",
                        }}
                      >
                        {cell}
                      </TableCell>
                    ))}
                </TableRow>
              </TableHead>
              <TableBody>
                {excelData &&
                  excelData.slice(1).map((row, rowIndex) => (
                    <TableRow key={rowIndex}>
                      {row.map((cell, cellIndex) => (
                        <TableCell key={cellIndex}>{cell}</TableCell>
                      ))}
                    </TableRow>
                  ))}
              </TableBody>
            </Table>
          </TableContainer>
        )}
        <div style={{ textAlign: "center", marginTop: "16px" }}>
          <Button
            variant="contained"
            onClick={handleSubmit}
            style={{ marginRight: "16px" }}
          >
            Upload File
          </Button>
          <Button variant="contained" onClick={onClose}>
            Close
          </Button>
        </div>
      </Box>
    </Modal>
  );
Displaying the Modal


The above code is defined with the return statement

  • It displays the file name without the .xlsx extension(in the fileName heading).
  • During processing, a loading spinner and progress percentage are shown.
  • Once processing is complete, a table displays the Excel data.
  • Buttons are provided for uploading the file and closing the modal.