How to add a JavaScript Excel XLSX viewer to a web application

Creating an Excel viewer in JavaScript can be a daunting task, but with SpreadJS JavaScript spreadsheets, the creation process is much simpler. In this tutorial blog, we will show you how to use the power of SpreadJS to create a viewer that allows you to open and save Excel files in a web browser, as well as protect the sheet from being edited and add a password. To continue reading this blog, be sure to download the sample — the content is reproduced from the official website.

Getting started with SpreadJS—JS has been cracked–please pay attention

The project will consist of three files: HTML, JavaScript file, and CSS file. We can start by incorporating SpreadJS into our project. You can do this a few different ways:

Reference local files

SpreadJS can be downloaded from our website and imported into our application: GrapeCity, Inc. Once downloaded, we can extract the ZIP file and copy the JS and CSS files into our application, specifically these files:

  • gc.spread.sheets.all.xx.xxmin.js
  • gc.spread.sheets.io.xx.xxmin.js
  • gc.spread.sheets.excel2013white.xx.xxcss

Once we have them in our application’s folder, we can reference them in our code:

<link rel="stylesheet" type="text/css" href="./styles/gc.spread.sheets.excel2013white.css">
<script src="./scripts/gc.spread.sheets.all.min.js" type="text/javascript"></script>
<script src="./scripts/gc.spread.sheets.io.min.js" type="text/javascript"></script>
<script src="./scripts/gc.spread.sheets.charts.min.js" type="text/javascript"></script>
<script src="./scripts/gc.spread.sheets.shapes.min.js" type="text/javascript"></script>

Refer to NPM

Another way to reference SpreadJS is through an NPM file. They can be added to the application using the following command:

npm install @grapecity/spread-sheets @grapecity/spread-sheets-io @grapecity/spread-sheets-charts @grapecity/spread-sheets-shapes @grapecity/spread-sheets-pivots

We can then reference these files in our code:

<link rel="stylesheet" type="text/css" href="./node_modules/@grapecity/spread-sheets/styles/gc.spread.sheets.excel2013white.css">
<script src="./node_modules/@grapecity/spread-sheets/dist/gc.spread.sheets.all.min.js" type="text/javascript"></script>
<script src="./node_modules/@grapecity/spread-sheets-io/dist/gc.spread.sheets.io.min.js" type="text/javascript"></script>
<script src="./node_modules/@grapecity/spread-sheets-charts/dist/gc.spread.sheets.charts.min.js" type="text/javascript"></script>
<script src="./node_modules/@grapecity/spread-sheets-shapes/dist/gc.spread.sheets.shapes.min.js" type="text/javascript"></script>

Create HTML content

Once these files are referenced, we can combine the HTML page and CSS styles. For styles, I have created the styles in advance:

body {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
}

.sample-tutorial {
    position: relative;
    height: 100%;
    overflow: hidden;
}

.sample-container {
    width: calc(100% - 280px);
    height: 100%;
    float: left;
}

.sample-spreadsheets {
    width: 100%;
    height: calc(100% - 25px);
    overflow: hidden;
}

.options-container {
    float: right;
    width: 280px;
    height: 100%;
    box-sizing: border-box;
    background: #fbfbfb;
    overflow: auto;
}

.sample-options {
    z-index: 1000;
}

.inputContainer {
    width: 100%;
    height: auto;
    border: 1px solid #eee;
    padding: 6px 12px;
    margin-bottom: 10px;
    box-sizing: border-box;
}

.settingButton {
    color: #fff;
    background: #82bc00;
    outline: 0;
    line-height: 1.5715;
    position: relative;
    display: inline-block;
    font-weight: 400;
    white-space: nowrap;
    text-align: center;
    height: 32px;
    padding: 4px 15px;
    font-size: 14px;
    border-radius: 2px;
    user-select: none;
    cursor: pointer;
    border: 1px solid #82bc00;
    box-sizing: border-box;
    margin-bottom: 10px;
    margin-top: 10px;
}

.settingButton:hover {
    color: #fff;
    border-color: #88b031;
    background: #88b031;
}

.settingButton:disabled {
    background: #e2dfdf;
    border-color: #ffffff;
}

.options-title {
    font-weight: bold;
    margin: 4px 2px;
}

#selectedFile {
    display: none;
}

select, input[type="text"], input[type="number"] {
    display: inline-block;
    margin-left: auto;
    width: 120px;
    font-weight: 400;
    outline: 0;
    line-height: 1.5715;
    border-radius: 2px;
    border: 1px solid #F4F8EB;
    box-sizing: border-box;
}

.passwordIpt {
    margin-top: 10px;
    height: 25px;
}

.passwordIpt[warning="true"] {
    border-color: red;
}

.passwordIpt[warning="true"]::placeholder {
    color: red;
    opacity: 0.8;
}

@keyframes shake {
    0% { transform: translate(1px, 1px) rotate(0deg); }
    10% { transform: translate(-1px, -2px) rotate(-1deg); }
    20% { transform: translate(-3px, 0px) rotate(1deg); }
    30% { transform: translate(3px, 2px) rotate(0deg); }
    40% { transform: translate(1px, -1px) rotate(1deg); }
    50% { transform: translate(-1px, 2px) rotate(-1deg); }
    60% { transform: translate(-3px, 1px) rotate(0deg); }
    70% { transform: translate(3px, 1px) rotate(-1deg); }
    80% { transform: translate(-1px, -1px) rotate(1deg); }
    90% { transform: translate(1px, 2px) rotate(0deg); }
    100% { transform: translate(1px, 1px) rotate(0deg); }
}

#warningBox {
    color: red;
}

We can then add all the buttons and UI needed for this application, including:

  • SpreadJS Example
  • Status Bar
  • Import part
    • Password text box
    • File selection button
    • import button
  • Export part
    • Password text box
    • export button

As we add each element to the HTML body section, we can use the appropriate styles for each element:

<body>
    <div class="sample-tutorial">
        <div class="sample-container">
            <div id="ss" class="sample-spreadsheets"></div>
            <div id="statusBar"></div>
        </div>
        <div class="options-container">
            <div class="option-row">
                <div class="inputContainer">
                    <div class="options-title">Import:</div>
                    <input class="passwordIpt" id="importPassword" type="password" placeholder="Password" disabled>
                    <br>
                    <div id="warningBox"></div>
                    <input id="selectedFile" type="file" accept=".xlsx" />
                    <button class="settingButton" id="selectBtn">Select</button>
                    <button class="settingButton" id="importBtn" disabled>Import</button>
                </div>
                <div class="inputContainer">
                    <div class="options-title">Export:</div>
                    <input class="passwordIpt" id="exportPassword" type="password" placeholder="Password">
                    <br>
                    <button class="settingButton" id="exportBtn">Export</button>
                </div>
            </div>
        </div>
    </div>
</body>

copy

Initialize SpreadJS

Now that we have referenced the file and set up the HTML content, we can initialize the SpreadJS instance and prepare to add the Excel import code in the app.js file. We can put this in the window’s onload function:

window.onload = function () {
  let spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss"));
}

Add buttons and features

For the purposes of this application, we can also make writing easier by creating some variables that can be used in the UI we create before the window.onload function:

const $ = selector => document.querySelector(selector);
const listen = (host, type, handler) => host.addEventListener(type, handler);

Now we can more easily create variables to reference different HTML elements within the window.onload function:

const importPassword = $('#importPassword');
const selectBtn = $('#selectBtn');
const fileSelect = $('#selectedFile');
const importBtn = $('#importBtn');
const warningBox = $('#warningBox');
const exportPassword = $('#exportPassword');
const exportBtn = $('#exportBtn');

We can now add event listeners and functions for the file selection button and password text box, as well as handlers for the incorrect password message:

listen(selectBtn, "click", () => fileSelect.click());

const fileSelectedHandler = () => {
    importPassword.disabled = false;
    importBtn.disabled = false;
}

listen(fileSelect, 'change', fileSelectedHandler);

const wrongPasswordHandler = message => {
    importPassword.setAttribute('warning', true);
    importPassword.style.animation = "shake 0.5s";
    setTimeout(() => importPassword.style.animation = "", 500);
    warningBox.innerText = message;
    importPassword.value = '';
};

listen(importPassword, 'focus', () => {
    warningBox.innerText = '';
    importPassword.removeAttribute('warning');
});

Import Excel files into SpreadJS

Now we can add code to import the Excel file into the SpreadJS instance. Since we may be importing password-protected files, we need to take this into account when calling the SpreadJS import function. We can also add event handlers after writing the function:

const importFileHandler = () => {
    let file = fileSelect.files[0];
    if (!file) return ;
    spread.import(file, console.log, error => {
        if (error.errorCode === GC.Spread.Sheets.IO.ErrorCode.noPassword || error.errorCode === GC.Spread.Sheets.IO.ErrorCode.invalidPassword) {
            wrongPasswordHandler(error.errorMessage);
        }
    }, {
        fileType: GC.Spread.Sheets.FileType.excel,
        password: importPassword.value
    });
};
listen(importBtn, 'click', importFileHandler);

Export Excel file from SpreadJS

Similar to importing, we can support users to enter passwords and add them to the Excel file when exporting, so we only need to pass in the password in the SpreadJS export function. We’ll also add an event handler for this:

const exportFileHandler = () => {
        let password = exportPassword.value;
        spread.export(blob => saveAs(blob, (password ? 'encrypted-' : '') + 'export.xlsx'), console.log, {
            fileType: GC.Spread.Sheets.FileType.excel,
            password: password
        });
    };
    listen(exportBtn, 'click', exportFileHandler);

Protect data

We can also protect data to prevent users from changing it. To do this, we can add a button to protect the current sheet of the workbook. It can be changed to suit any type of requirement, but for this example this will be the active worksheet. Similar to other buttons, we need to add a handler to click it, but with SpreadJS we can also specify protection options:

const protectHandler = () => {
    var option = {
        allowSelectLockedCells:true,
        allowSelectUnlockedCells:true,
        allowFilter: true,
        allowSort: false,
        allowResizeRows: true,
        allowResizeColumns: false,
        allowEditObjects: false,
        allowDragInsertRows: false,
        allowDragInsertColumns: false,
        allowInsertRows: false,
        allowInsertColumns: false,
        allowDeleteRows: false,
        allowDeleteColumns: false,
        allowOutlineColumns: false,
        allowOutlineRows: false
    };
    spread.getSheet(0).options.protectionOptions = option;
    spread.getSheet(0).options.isProtected = true;
};
listen(protectBtn, 'click', protectHandler);

copy

Run the application

All that’s left now is to run the application. Since we are making it using PureJS and HTML, we can simply open the HTML file in a web browser:

JavaScript Excel XLSX Viewer

We can click the “Select” button to select the Excel file to load, and then click the “Import” button to import it into SpreadJS:

JavaScript Excel XLSX Viewer

Now we can add a password by entering it in the Password text box under Export and click the Export button:

JavaScript Excel XLSX Viewer

You have now made your own Excel viewer using SpreadJS! With it, you can open, protect and add a password to your Excel files before exporting them in just a few simple steps.