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 stylingComponent 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
xlsxlibrary 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
excelDatastate variable. - During processing, a loading animation is displayed, and the
progressvariable is updated incrementally to reflect the file processing progress. - After processing, the
loadingstate 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
.xlsxextension(in thefileNameheading). - 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.