SpreadJS File Format supports encryption and decryption using passwords when importing and exporting.
Export Example:
Import Example
errorCode is defined by GC.Spread.Sheets.IO.ErrorCode
const $ = selector => document.querySelector(selector);
const listen = (host, type, handler) => host.addEventListener(type, handler);
window.onload = function () {
let spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss"));
const importPassword = $('#importPassword');
const selectBtn = $('#selectBtn');
const fileSelect = $('#selectedFile');
const importBtn = $('#importBtn');
const warningBox = $('#warningBox');
const exportPassword = $('#exportPassword');
const exportBtn = $('#exportBtn');
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');
});
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);
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);
};
<!doctype html>
<html style="height:100%;font-size:14px;">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" type="text/css" href="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css">
<script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets/dist/gc.spread.sheets.all.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-io/dist/gc.spread.sheets.io.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-shapes/dist/gc.spread.sheets.shapes.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-charts/dist/gc.spread.sheets.charts.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-slicers/dist/gc.spread.sheets.slicers.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-pivot-addon/dist/gc.spread.pivot.pivottables.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-reportsheet-addon/dist/gc.spread.report.reportsheet.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-tablesheet/dist/gc.spread.sheets.tablesheet.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-ganttsheet/dist/gc.spread.sheets.ganttsheet.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/spread/source/js/FileSaver.js" type="text/javascript"></script>
<script src="$DEMOROOT$/spread/source/js/license.js" type="text/javascript"></script>
<script src="app.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>
<div class="sample-tutorial">
<div class="sample-container">
<div id="ss" class="sample-spreadsheets"></div>
<div id="statusBar"></div>
</div>
<aside class="options-container" aria-label="Password settings">
<div class="panel-header">
<h1>Password Settings</h1>
<p class="panel-description">Import and export encrypted Excel files with optional passwords.</p>
</div>
<div class="option-row">
<div class="inputContainer">
<div class="options-title">Import File</div>
<label for="importPassword">Password</label>
<input class="passwordIpt" id="importPassword" type="password" placeholder="Password" disabled>
<div id="warningBox"></div>
<input id="selectedFile" type="file" accept=".xlsx" />
<div class="inline-actions">
<button class="settingButton" id="selectBtn">Select</button>
<button class="settingButton" id="importBtn" disabled>Import</button>
</div>
</div>
<div class="inputContainer">
<div class="options-title">Export File</div>
<label for="exportPassword">Password</label>
<input class="passwordIpt" id="exportPassword" type="password" placeholder="Password">
<div class="inline-actions">
<button class="settingButton" id="exportBtn">Export</button>
</div>
</div>
</div>
</aside>
</div></body>
</html>
html,
body {
height: 100%;
margin: 0;
}
body {
position: absolute;
inset: 0;
color: #1f2933;
background: #f7f8fa;
}
.sample-tutorial {
display: flex;
height: 100%;
overflow: hidden;
}
.sample-container {
display: flex;
flex: 1 1 auto;
flex-direction: column;
min-width: 0;
height: 100%;
}
.sample-spreadsheets {
flex: 1 1 auto;
min-height: 0;
overflow: hidden;
}
.options-container {
flex: 0 0 320px;
width: 320px;
height: 100%;
padding: 18px 16px;
box-sizing: border-box;
overflow: auto;
overflow-x: hidden;
background: #fff;
border-left: 1px solid #e5e7eb;
}
.panel-header {
padding-bottom: 14px;
margin-bottom: 16px;
border-bottom: 1px solid #edf0f3;
}
.panel-header h1 {
margin: 0 0 6px;
font-size: 18px;
font-weight: 600;
line-height: 1.25;
}
.panel-description {
margin: 0;
color: #5f6b7a;
font-size: 12px;
line-height: 1.4;
}
.option-row {
display: grid;
gap: 14px;
}
.inputContainer {
display: grid;
gap: 7px;
width: 100%;
min-width: 0;
padding-bottom: 14px;
border-bottom: 1px solid #edf0f3;
box-sizing: border-box;
}
.inputContainer:last-child {
border-bottom: 0;
}
.options-title {
color: #111827;
font-size: 13px;
font-weight: 600;
line-height: 1.35;
}
.options-container label {
color: #4b5563;
font-size: 12px;
line-height: 1.35;
}
.passwordIpt {
width: 100%;
min-width: 0;
height: 30px;
padding: 0 8px;
color: #1f2933;
border: 1px solid #cfd6df;
border-radius: 6px;
box-sizing: border-box;
outline: 0;
}
.passwordIpt:focus {
border-color: #2f6fed;
box-shadow: 0 0 0 2px rgba(47, 111, 237, 0.14);
}
.passwordIpt[warning="true"] {
border-color: #dc2626;
}
.passwordIpt[warning="true"]::placeholder {
color: #dc2626;
opacity: 0.8;
}
#warningBox {
min-height: 16px;
color: #dc2626;
font-size: 12px;
line-height: 1.35;
}
#selectedFile {
display: none;
}
.inline-actions {
display: flex;
gap: 8px;
align-items: center;
min-width: 0;
}
.settingButton {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 76px;
height: 32px;
padding: 0 12px;
color: #1d4ed8;
background: #fff;
border: 1px solid #9db7f5;
border-radius: 6px;
box-sizing: border-box;
font-size: 13px;
font-weight: 500;
line-height: 1;
white-space: nowrap;
cursor: pointer;
}
.settingButton:hover {
color: #123f9d;
border-color: #5f86e8;
background: #f7faff;
}
.settingButton:disabled {
color: #9aa4b2;
background: #f3f5f7;
border-color: #d8dee6;
cursor: not-allowed;
}
@keyframes shake {
0% { transform: translate(1px, 1px) rotate(0deg); }
10% { transform: translate(-1px, -2px) rotate(-1deg); }
20% { transform: translate(-3px, 0) 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); }
}
@media (max-width: 760px) {
.sample-tutorial {
flex-direction: column;
}
.sample-container {
flex: 1 1 55%;
height: 55%;
}
.options-container {
flex: 1 1 45%;
width: 100%;
height: 45%;
border-top: 1px solid #e5e7eb;
border-left: 0;
}
}