Password Support

SpreadJS File Format supports the use of passwords to import and export xlsx files.

Description
app.vue
index.html
Copy to CodeMine

SpreadJS File Format supports encryption and decryption using passwords when importing and exporting.

Export Example:

let spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss"));
spread.getActiveSheet().setValue(1, 1, "SpreadJS Secret");

let password = "spreadjs2023";
spread.export(blob => saveAs(blob, "encrypted-export.xlsx"), console.log, {
   fileType: GC.Spread.Sheets.FileType.excel,
   password: password
});

Import Example

spread.import(file, successCallback, error => {
   console.log(error.errorMessage, `Error Code: ${error.errorCode}`);
}, {
   fileType: GC.Spread.Sheets.FileType.excel,
   password: password
})

errorCode is defined by GC.Spread.Sheets.IO.ErrorCode

///* enum GC.Spread.Sheets.IO.ErrorCode
/**
 * Specifies the io error code.
 * @enum {number}
 */
export let ErrorCode = {
    /**
     *  File read and write exception.
     */
    fileIOError: 0,
    /**
     *  Incorrect file format.
     */
    fileFormatError: 1,
    /**
     *  Need a password.
     */
    noPassword: 2,
    /**
     *  invalid Password.
     */
    invalidPassword: 3,
};
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
<template> <div class="sample-tutorial"> <div class="sample-container"> <gc-spread-sheets class="sample-spreadsheets" @workbookInitialized="initSpread"> <gc-worksheet> </gc-worksheet> </gc-spread-sheets> <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" name="importPassword" v-model="importPasswordRef" :disabled="importDisabledRef" v-bind:style="{ animation: shakeAnimationRef }" v-bind:warning="showWarningRef" v-on:focus="initPassword()"> <br> <div id="warningBox">{{ warningMessageRef }}</div> <input id="selectedFile" type="file" accept=".xlsx" v-on:change="selectedFileChange($event)" ref="selectFile" /> <button class="settingButton" id="selectBtn" v-on:click="selectFileHandler">Select</button> <button class="settingButton" id="importBtn" v-on:click="importFileHandler" :disabled="importDisabledRef">Import</button> </div> <div class="inputContainer"> <div class="options-title">Export:</div> <input class="passwordIpt" id="exportPassword" type="password" placeholder="Password" name="exportPassword" v-model="exportPasswordRef"> <br> <button class="settingButton" id="exportBtn" v-on:click="exportFileHandler()">Export</button> </div> </div> </div> </div> </template> <script setup> import GC from "@mescius/spread-sheets"; import { ref, toRaw } from "vue"; import '@mescius/spread-sheets-io'; import '@mescius/spread-sheets-charts'; import '@mescius/spread-sheets-shapes'; import '@mescius/spread-sheets-slicers'; import '@mescius/spread-sheets-pivot-addon'; import '@mescius/spread-sheets-reportsheet-addon'; import "@mescius/spread-sheets-tablesheet"; import "@mescius/spread-sheets-ganttsheet"; const spreadRef = ref(null); const selectFile = ref(null); const selectedFileRef = ref(null); const importPasswordRef = ref(''); const warningMessageRef = ref(''); const shakeAnimationRef = ref(''); const importDisabledRef = ref(true); const showWarningRef = ref(false); const exportPasswordRef = ref(''); const initSpread = (spread) => { spreadRef.value = spread; }; const selectedFileChange = (e) => { selectedFileRef.value = e.target.files[0]; importDisabledRef.value = false; }; const selectFileHandler = () => { selectFile.value && selectFile.value.click(); }; const importFileHandler = () => { const wrongPasswordHandler = message => { showWarningRef.value = true; shakeAnimationRef.value = "shake 0.5s"; setTimeout(() => shakeAnimationRef.value = "", 500); warningMessageRef.value = message; importPasswordRef.value = ''; }; spreadRef.value.import(selectedFileRef.value, 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: importPasswordRef.value }); }; const exportFileHandler = () => { let password = exportPasswordRef.value; spreadRef.value.export(blob => saveAs(blob, (password ? 'encrypted-' : '') + 'export.xlsx'), console.log, { fileType: GC.Spread.Sheets.FileType.excel, password: password }); }; const initPassword = () => { showWarningRef.value = false; warningMessageRef.value = ''; }; </script> <style scoped> #app { height: 100%; } 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; margin-right: 5px; } .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; } </style>
<!DOCTYPE html> <html style="height:100%;font-size:14px;"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <title>SpreadJS VUE</title> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/en/vue3/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <script src="$DEMOROOT$/spread/source/js/FileSaver.js" type="text/javascript"></script> <script src="$DEMOROOT$/en/vue3/node_modules/systemjs/dist/system.src.js"></script> <script src="./systemjs.config.js"></script> <script src="./compiler.js" type="module"></script> <script> var System = SystemJS; System.import("./src/app.js"); System.import('$DEMOROOT$/en/lib/vue3/license.js'); </script> </head> <body> <div id="app"></div> </body> </html>
(function (global) { SystemJS.config({ transpiler: 'plugin-babel', babelOptions: { es2015: true }, paths: { // paths serve as alias 'npm:': 'node_modules/' }, packageConfigPaths: [ './node_modules/*/package.json', "./node_modules/@mescius/*/package.json", "./node_modules/@babel/*/package.json", "./node_modules/@vue/*/package.json" ], map: { 'vue': "npm:vue/dist/vue.esm-browser.js", 'tiny-emitter': 'npm:tiny-emitter/index.js', 'plugin-babel': 'npm:systemjs-plugin-babel/plugin-babel.js', "systemjs-babel-build": "npm:systemjs-plugin-babel/systemjs-babel-browser.js", '@mescius/spread-sheets': 'npm:@mescius/spread-sheets/index.js', '@mescius/spread-sheets-print': 'npm:@mescius/spread-sheets-print/index.js', '@mescius/spread-sheets-vue': 'npm:@mescius/spread-sheets-vue/index.js', '@mescius/spread-sheets-io': 'npm:@mescius/spread-sheets-io/index.js', '@mescius/spread-sheets-charts': 'npm:@mescius/spread-sheets-charts/index.js', '@mescius/spread-sheets-shapes': 'npm:@mescius/spread-sheets-shapes/index.js', '@mescius/spread-sheets-slicers': 'npm:@mescius/spread-sheets-slicers/index.js', '@mescius/spread-sheets-pivot-addon': 'npm:@mescius/spread-sheets-pivot-addon/index.js', '@mescius/spread-sheets-reportsheet-addon': 'npm:@mescius/spread-sheets-reportsheet-addon/index.js', '@mescius/spread-sheets-tablesheet': 'npm:@mescius/spread-sheets-tablesheet/index.js', '@mescius/spread-sheets-ganttsheet': 'npm:@mescius/spread-sheets-ganttsheet/index.js', }, meta: { '*.css': { loader: 'systemjs-plugin-css' }, '*.vue': { loader: "../plugin-vue/index.js" } } }); })(this);