Quick Start Guide | |
---|---|
Tutorial Concept |
Learn how to integrate a secure client-side Excel .XLSX viewer using a React spreadsheet component. |
What You Will Need | |
Controls Referenced |
Many businesses rely on spreadsheets, especially Microsoft Excel, for managing operations. Therefore, it's crucial to access and manage these files within enterprise React applications. SpreadJS, a React spreadsheet component, allows users to load, edit, and save complex XLSX files across various frameworks. In this blog, we'll demonstrate how to add an XLSX Viewer to your React 18 web application using SpreadJS. This article will guide you through importing Excel files into a user-friendly interface and protecting the React worksheet to restrict user edits.
Add Spreadsheets to Your React Enterprise Web Apps. Download SpreadJS Now!
How to Add an Excel XLSX Viewer to React Web Applications:
- Create a React Spreadsheet Application
- Add Excel Import Code - Import Method
- Invoke the Protect and Unprotect Methods
Download the sample application to follow along with this blog.
Create a React Spreadsheet Application
First, create a React project by opening the Command Prompt window and then type the following commands:
npx create-react-app sjs-react-viewer
cd sjs-react-viewer
npm start
Install the necessary SpreadJS NPM modules in your project using the following command:
npm install @mescius/spread-sheets @mescius/spread-sheets-react @mescius/spread-sheets-io @mescius/spread-sheets-charts @mescius/spread-sheets-shapes
Import the SpreadJS CSS in your app's index.js file using the following code:
import '@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css';
At the beginning of your App.js file, import the required modules. These imports will enable access to the spreadsheet object of SpreadJS and add support for charts, shapes, and importing/exporting in the React spreadsheet instance.
import React, { Component } from "react";
import { SpreadSheets } from "@mescius/spread-sheets-react";
import * as GC from "@mescius/spread-sheets";
import "@mescius/spread-sheets-charts";
import "@mescius/spread-sheets-shapes";
import "@mescius/spread-sheets-io";
Define some constants that will be used in the application:
const passwordWrongTip = "Password is not correct!";
const alreadyProtect = "The worksheet is already protected!";
const unprotectImg = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB0UlEQVR4nO2YzU7CQBDHNyae9A30qF6NNlFv7QzhqheukN1An4Mbnv14A70YwgERX0XiWRNBKl8eMDGuGWy0LopoS0tl/8kkZLMT/r+dmW1axrS0tAKTYRjziJgCgFNEvAKAR0Tsub9pLUV72DTKsqw9ALhGRDkqaA/tZdOifD4/h4j7PxlX4gURC5QbtX/2B/PeKERqnlrBPU1vi/QR8dCyrO1kMrlAYZrmDgAcAcCTWgkA2I3EPA2j2vMAcAMA69/lJBKJDQC4VWfCiGKw6UZRT36UeU/e5heVSLGw5V6LXhMHv8g9VuBPWNhCxJoCsDVuLs2EkltjYct9QL2bME1zcdxc2qsA9FjYUq/EsPN9SwOgrsD4yuVyy5zzIue8K4SQkwz+9h8lzvlqkOadSRsXwyBOJpNZ8g1AJx+2efEBcRYEQDdCgLZvgKjMCzc0gNAVELqFfGkmW8i2bXl5cS7bTkO2mnVZrZQHa7EBqFbKUj73PwWtxQag7TSGAGgtNgCtZn0I4OH+Lj4A1bi3kG3bA8NUiVgOsQgwmAYQugJSt9Cst1An7q+UpQgBir4B0un0mhCiGYF5J5vNrrAgRN9n6BNHSO3UoZMPzLyW1j/XK1zJDTLJ864hAAAAAElFTkSuQmCC";
const protectImg = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB10lEQVR4nO2Yz0rDQBDGB0Ev+gZ6VK+iAfWWzJRe9dL3qfVQlWwR/7yBXqT0JepD2Nar0h4s2ERq3YArW4LGrdZq0qSx+8FACDvw/XZmNmQBtLS0IpNhGLNElEPESyK6QcQnInL9Z/kuJ9fAJMqyrF1EbBCRGBZyjVwLk6J8Pj9DRAc/GVfilYiKMjdp//AH88EoJmpetoK/m8EW6RHRqWVZW9lsdl6GaZrbiHiGiC9qJRBxJxHzchjVnkfEO0Rc+y4nk8msI+K9OhNGEoMtTxR154eZD+RtfFGJHMQt/1gMmjj5Re65An8BcYuIagrA5qi5ciaU3BrELf8D9W7CNM2FUXPlWgXAhbilHolx54eWBiBdgdElDmGJMyhzBo7HQIwzOAOHM6j0jmAlOvM2tMdt3FNBbGiLEiyGBpA7H7d576MaV1EAOAkCPIYGSMq854cG8HQFQLdQKE1nCx3Pie71vnBbDeE266JbLfTfpQagWy0Ix3E+RR8iLQBuqzEA4LZuUwTQrA8CNGtpb6G9lA1xtdCvRCqH2IswQAMwXQGhW2iqW4jb0En1LyVnUEkQoBwaoMdglTN4iN28De3nEixDFJL3M/KKI4524jZ05M5HZl5L65/rDc6nQtkkwmMVAAAAAElFTkSuQmCC";
Update the component App, which initializes its state to manage a selected file, spreadsheet protection status, and password. It sets up inline styles for a spreadsheet container and prepares a placeholder for the spreadsheet reference.
class App extends Component {
constructor(props) {
super(props);
this.hostStyle = {
width: "950px",
height: "600px",
};
this.spread = null;
this.state = {
selectedFile: null,
protectSheet: false,
password: "",
};
}
}
Update the render method to extract protectSheet and password from the state and organize the layout with a flex container. It includes a div for the SpreadJS react spreadsheets component, which initializes the workbook, a sidebar containing a file input, a button to open the selected file, an image indicating sheet protection status, a password input field, and buttons to protect or unprotect the sheet, with their disabled state based on protectSheet.
render() {
const { protectSheet, password } = this.state;
return (
<div style={{ display: "flex" }}>
<div style={{ width: "950px", height: "600px" }}>
<SpreadSheets
workbookInitialized={(spread) => this.initSpread(spread)}
hostStyle={this.hostStyle}
></SpreadSheets>
</div>
<div style={{ width: "15%", padding: "20px", background: "#ddd" }}>
<p>Open Excel Files (.xlsx)</p>
<input type="file" onChange={this.handleFileChange} />
<button onClick={this.handleOpenExcel}>Open Excel</button>
<br />
<br />
<img
id="protectStatus"
style={{ height: "25px" }}
src={protectSheet ? protectImg : unprotectImg}
/>
<p>
Password:
<input
id="protectPassword"
type="password"
value={password}
onChange={(e) => this.setState({ password: e.target.value })}
/>{" "}
</p>
<br />
<input
type="button"
value="Protect"
id="protectBtn"
onClick={() => {
this.setProtectSheet();
}}
style={{ width: "100px" }}
disabled={protectSheet}
/>
<input
type="button"
value="Unprotect"
id="unprotectBtn"
onClick={() => {
this.setUnprotectSheet();
}}
style={{ width: "100px", marginLeft: "10px" }}
disabled={!protectSheet}
/>
</div>
</div>
);
}
Users can modify the workbook when it is being initialized; in this case, we want two worksheets in the instance on page load.
initSpread(spread) {
this.spread = spread;
this.spread.setSheetCount(2);
}
Create empty functions for all of the needed actions. We will add the code logic for each of these functions later in this blog.
// Get the selected Excel file
handleFileChange = (e) => {
};
// Open the instance as an Excel File
handleOpenExcel = () => {
};
// Unprotect the worksheet
setUnprotectSheet() {
};
// Protect the workshet
setProtectSheet() {
};
Save all the files, and run the React app:
npm start
You have now created a React Spreadsheet app.
Add Excel Import Code to the React App
Importing an Excel file into the React spreadsheet application requires us to handle the change and invoke the spreadsheets import method. The handleFileChange function will be used to capture the selected Excel file when it's changed and update the component's state with the selected file.
// Get the selected Excel file
handleFileChange = (e) => {
this.setState({
selectedFile: e.target.files[0],
});
};
The handleOpenExcel function is triggered when the user clicks the "Open Excel" button. It first checks if a file is selected. If not, it returns early. If a file is selected, it constructs import options specifying the FileType as Excel. Then, it calls the import method of the SpreadJS instance (this.spread) with the selected file and import options.
// Open the instance as an Excel File
handleOpenExcel = () => {
const file = this.state.selectedFile;
if (!file) {
return;
}
// Specify the file type to ensure proper import
const options = {
fileType: GC.Spread.Sheets.FileType.excel,
};
this.spread.import(
file,
() => {
console.log("Import successful");
},
(e) => {
console.error("Error during import:", e);
},
options
);
};
Alternatively, you can read an Excel file from a URL on a server. Read more in this blog.
Run the app, notice an Excel (.xlsx) file can now be imported, viewed, and modified in the React spreadsheet component.
Protect the React Spreadsheet
After successfully importing an Excel file into SpreadJS, users can easily interact with the spreadsheet data. Alternatively, you may find it necessary to restrict editing on the spreadsheet. To accomplish this, SpreadJS offers the Worksheet protect method.
In the setProtectSheet() function, get the active worksheet, check to see if it is already protected, and if not, then invoke the protect method with a password if one is applied:
// Protect the worksheet
setProtectSheet() {
let sheet = this.spread.getActiveSheet();
if (sheet.options.isProtected) {
alert(alreadyProtect);
return;
}
const password = this.state.password;
sheet.protect(password);
this.setState({
protectSheet: true,
password: "",
});
}
Allow authorized users to unprotect a worksheet to make changes by providing a password and invoking the worksheets unprotect method within the setUnprotectSheet() function.
// Unprotect the worksheet
setUnprotectSheet() {
const password = this.state.password;
let sheet = this.spread.getActiveSheet();
if (sheet.hasPassword()) {
let success = sheet.unprotect(password);
if (!success) {
alert(passwordWrongTip);
return;
}
} else {
sheet.unprotect();
}
this.setState({
protectSheet: false,
password: "",
});
}
Run the sample app and notice users can now protect and unprotect the React spreadsheet using a password.
Learn More About React Spreadsheet Components
This article only scratches the surface of the full capabilities of SpreadJS, a React spreadsheet component. Review the documentation to see some of the many available features, and check out our online demos to see the features in action and interact with the sample code. Integrating a spreadsheet component into your applications allows you to customize your users' experience and provide them with familiar spreadsheet functionality without referring them to an external program. Check out our video to learn more:
Check out our other blog article in this series, where we demonstrate how to create Excel .xlsx Viewer applications in other frameworks: