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
Component Definition
export default function ExcelFilePreview({ file, onClose, uploadFunction }) {
const [excelData, setExcelData] = useState(null);
const [loading, setLoading] = useState(true);
const [progress, setProgress] = useState(0);
}
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);
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]);
useEffect
hook, component that handles the processing of the Excel file.
FileReader
- created to read the content of the Excel file.- When the reader finishes loading the file, it converts the data into a
Uint8Array
. - The
xlsx
library is used to parse the Excel data, extract the first sheet, and convert it into a JSON format. - The extracted data is stored in the
excelData
state variable. - During processing, a loading animation is displayed, and the
progress
variable is updated incrementally to reflect the file processing progress. - After processing, the
loading
state is set tofalse
.
Handling Form Submission
const handleSubmit = () => {
if (excelData) {
uploadFunction(file);
onClose();
}
};
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>
);
The above code is defined with the return
statement
- It displays the file name without the
.xlsx
extension(in thefileName
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.