Password Support

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

Description
app.component.ts
index.html
app.component.html
styles.css
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
import { Component, NgModule, enableProdMode, ViewChild, ElementRef } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { FormsModule } from '@angular/forms'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { SpreadSheetsModule } from '@mescius/spread-sheets-angular'; import GC from '@mescius/spread-sheets'; import '@mescius/spread-sheets-io'; import '@mescius/spread-sheets-shapes'; import '@mescius/spread-sheets-charts'; 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"; import './styles.css'; declare var saveAs: any; @Component({ selector: 'app-component', templateUrl: 'src/app.component.html' }) export class AppComponent { spread: GC.Spread.Sheets.Workbook; hostStyle = { width: '100%', height: 'calc(100% - 25px)', overflow: 'hidden', float: 'left' }; selectedFile: File = null; importPassword = ''; warningMessage = ''; shakeAnimation = ''; importDisabled = true; showWarning = false; @ViewChild('selectFile') selectFile: ElementRef; constructor () { } initSpread ($event: any) { this.spread = $event.spread; } selectFileHandler () { this.selectFile.nativeElement.click(); } importFileHandler () { const wrongPasswordHandler = message => { this.showWarning = true; this.shakeAnimation = "shake 0.5s"; setTimeout(() => this.shakeAnimation = "", 500); this.warningMessage = message; this.importPassword = ''; }; this.spread.import(this.selectedFile, 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: this.importPassword }); } exportFileHandler () { let password = this.exportPassword; this.spread.export(blob => saveAs(blob, (password ? 'encrypted-' : '') + 'export.xlsx'), console.log, { fileType: GC.Spread.Sheets.FileType.excel, password: password }); } selectedFileChange (e: any) { this.selectedFile = e.target.files[0]; this.importDisabled = false; } initPassword() { this.showWarning = false; this.warningMessage = ''; } } @NgModule({ imports: [BrowserModule, SpreadSheetsModule, FormsModule], declarations: [AppComponent], exports: [AppComponent], bootstrap: [AppComponent] }) export class AppModule { } enableProdMode(); // Bootstrap application with hash style navigation and global services. platformBrowserDynamic().bootstrapModule(AppModule);
<!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/angular/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <script src="$DEMOROOT$/spread/source/js/FileSaver.js" type="text/javascript"></script> <!-- Polyfills --> <script src="$DEMOROOT$/en/angular/node_modules/core-js/client/shim.min.js"></script> <script src="$DEMOROOT$/en/angular/node_modules/zone.js/fesm2015/zone.min.js"></script> <!-- SystemJS --> <script src="$DEMOROOT$/en/angular/node_modules/systemjs/dist/system.js"></script> <script src="systemjs.config.js"></script> <script> // workaround to load 'rxjs/operators' from the rxjs bundle System.import('rxjs').then(function (m) { System.import('@angular/compiler'); System.set(SystemJS.resolveSync('rxjs/operators'), System.newModule(m.operators)); System.import('$DEMOROOT$/en/lib/angular/license.ts'); System.import('./src/app.component'); }); </script> </head> <body> <app-component></app-component> </body> </html>
<div class="sample-tutorial"> <div class="sample-container"> <gc-spread-sheets [hostStyle]="hostStyle" (workbookInitialized)="initSpread($event)"> <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" [(ngModel)]="importPassword" [disabled]="importDisabled" [style.animation] = "shakeAnimation" [attr.warning] = "showWarning" (focus) = "initPassword()" > <br> <div id="warningBox" [innerText]="warningMessage"></div> <input #selectFile id="selectedFile" type="file" accept=".xlsx" (change)="selectedFileChange($event)"/> <button class="settingButton" id="selectBtn" (click)="selectFileHandler()">Select</button> <button class="settingButton" id="importBtn" (click)="importFileHandler()" [disabled]="importDisabled">Import</button> </div> <div class="inputContainer"> <div class="options-title">Export:</div> <input class="passwordIpt" id="exportPassword" type="password" placeholder="Password" name="exportPassword" [(ngModel)]="exportPassword"> <br> <button class="settingButton" id="exportBtn" (click)="exportFileHandler()">Export</button> </div> </div> </div> </div>
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; }
(function (global) { System.config({ transpiler: 'ts', typescriptOptions: { tsconfig: true }, meta: { 'typescript': { "exports": "ts" }, '*.css': { loader: 'css' } }, paths: { // paths serve as alias 'npm:': 'node_modules/' }, // map tells the System loader where to look for things map: { 'core-js': 'npm:core-js/client/shim.min.js', 'zone': 'npm:zone.js/fesm2015/zone.min.js', 'rxjs': 'npm:rxjs/dist/bundles/rxjs.umd.min.js', '@angular/core': 'npm:@angular/core/fesm2022', '@angular/common': 'npm:@angular/common/fesm2022/common.mjs', '@angular/compiler': 'npm:@angular/compiler/fesm2022/compiler.mjs', '@angular/platform-browser': 'npm:@angular/platform-browser/fesm2022/platform-browser.mjs', '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/fesm2022/platform-browser-dynamic.mjs', '@angular/common/http': 'npm:@angular/common/fesm2022/http.mjs', '@angular/router': 'npm:@angular/router/fesm2022/router.mjs', '@angular/forms': 'npm:@angular/forms/fesm2022/forms.mjs', 'jszip': 'npm:jszip/dist/jszip.min.js', 'typescript': 'npm:typescript/lib/typescript.js', 'ts': './plugin.js', 'tslib':'npm:tslib/tslib.js', 'css': 'npm:systemjs-plugin-css/css.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-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', '@mescius/spread-sheets-angular': 'npm:@mescius/spread-sheets-angular/fesm2020/mescius-spread-sheets-angular.mjs', '@grapecity/jsob-test-dependency-package/react-components': 'npm:@grapecity/jsob-test-dependency-package/react-components/index.js' }, // packages tells the System loader how to load when no filename and/or no extension packages: { src: { defaultExtension: 'ts' }, rxjs: { defaultExtension: 'js' }, "node_modules": { defaultExtension: 'js' }, "node_modules/@angular": { defaultExtension: 'mjs' }, "@mescius/spread-sheets-angular": { defaultExtension: 'mjs' }, '@angular/core': { defaultExtension: 'mjs', main: 'core.mjs' } } }); })(this);