You can get the redoStack of SpreadJS using the getRedoStack method.
You can get the undoStack of SpreadJS using the getUndoStack method.
You can get or set the max size of the redoStack/undoStack using the maxSize method.
import { Component, NgModule, enableProdMode } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { SpreadSheetsModule } from '@mescius/spread-sheets-angular';
import { getData } from './app.data';
import GC from '@mescius/spread-sheets';
import './styles.css';
function _getElementById(id:string) {
return document.getElementById(id);
}
@Component({
selector: 'app-component',
templateUrl: 'src/app.component.html'
})
export class AppComponent {
autoGenerateColumns = false;
spread: GC.Spread.Sheets.Workbook;
hostStyle = {
width: '100%',
height: '100%'
};
constructor() {
}
initSpread($event: any) {
this.spread = $event.spread;
this.attachEvents();
this.executeCommand();
this.updateInfo();
}
attachEvents() {
var spread = this.spread;
spread.fromJSON(getData()[0]);
var events = GC.Spread.Sheets.Events;
spread.bind(events.ValueChanged, this.updateInfo.bind(this));
spread.bind(events.ViewZoomed, this.updateInfo.bind(this));
spread.bind(events.ColumnChanged, this.updateInfo.bind(this));
spread.bind(events.ColumnWidthChanged, this.updateInfo.bind(this));
spread.bind(events.RowChanged, this.updateInfo.bind(this));
spread.bind(events.RowHeightChanged, this.updateInfo.bind(this));
let setButton = _getElementById("gc-max-size-set");
let maxSizeDom = _getElementById("gc-max-size") as HTMLInputElement;
let redoButton = _getElementById("gc-redo-button") as HTMLTextAreaElement;
let undoButton = _getElementById("gc-undo-button") as HTMLTextAreaElement;
let undoManager = spread.undoManager();
setButton.addEventListener("click", () => {
let value = Number(maxSizeDom.value);
if (!isNaN(value)) {
spread.undoManager().maxSize(value);
}
});
redoButton.addEventListener("click", () => {
undoManager.redo();
this.updateInfo();
});
undoButton.addEventListener("click", () => {
undoManager.undo();
this.updateInfo();
});
}
executeCommand() {
var spread = this.spread;
var commandManager = spread.commandManager();
let sheet = spread.getActiveSheet();
let sheetName = sheet.name();
commandManager.execute({
cmd: "resizeColumn",
sheetName: sheetName,
size: 70,
rowHeader: false,
columns: [{
firstCol: 0,
lastCol: 5
}],
});
commandManager.execute({
cmd: "editCell",
sheetName: sheetName,
row: 0,
col: 0,
newValue: "Edit Cell",
autoFormat: true,
});
commandManager.execute({
cmd: "resizeRow",
sheetName: sheetName,
rows: [{
firstRow: 0,
lastRow: 5,
}],
size: 30,
columnHeader: false,
})
spread.undoManager().undo();
}
updateInfo() {
var undoManager = this.spread.undoManager();
setTimeout(() => {
this.updateUndoInfo(undoManager);
this.updateRedoInfo(undoManager);
}, 0);
}
updateUndoInfo(undoManager:any) {
var undoStack = undoManager.getUndoStack();
var description = this.getDescription(undoStack);
let undoContainer = _getElementById("gc-undo-stack-container") as HTMLTextAreaElement;
undoContainer.value = description;
}
updateRedoInfo(undoManager:any) {
var redoStack = undoManager.getRedoStack();
let description = this.getDescription(redoStack);
let redoContainer = _getElementById("gc-redo-stack-container") as HTMLTextAreaElement;
redoContainer.value = description;
}
getDescription(actionStack:any[]) {
let description = "";
for (var i = 0; i < actionStack.length; i++) {
description = description + (i + 1) + "." + actionStack[i].cmd + "\r\n";
}
return description;
}
}
@NgModule({
imports: [BrowserModule, SpreadSheetsModule],
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">
<!-- 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">
<!-- Workbook host element -->
<div id="ss" class="sample-spreadsheets">
<gc-spread-sheets [hostStyle]="hostStyle" (workbookInitialized)="initSpread($event)">
<gc-worksheet [dataSource]="dataSource" [autoGenerateColumns]='autoGenerateColumns'>
<gc-column dataField="Film" width=160></gc-column>
<gc-column dataField="Genre" width=70></gc-column>
<gc-column dataField="Lead Studio" width=90></gc-column>
<gc-column dataField="Audience Score %" width=110></gc-column>
<gc-column dataField="Profitability" width=80></gc-column>
<gc-column dataField="Rating"></gc-column>
<gc-column dataField="Worldwide Gross" width=110></gc-column>
<gc-column dataField="Year"></gc-column>
</gc-worksheet>
</gc-spread-sheets>
</div>
<div class="options-container">
<label>Make any changes such as editing text or resizing row and cols then undo or redo your actions using the below buttons.</label>
<div class="option-row">
<input type="button" value="Redo" class="gc-redo" id="gc-redo-button">
<input type="button" value="Undo" class="gc-undo" id="gc-undo-button">
</div>
<div class="gc-undo-stack-container option-row">
<label>The undoStack includes the following command:</label>
<textarea type="text" class="gc-stack-list" id="gc-undo-stack-container" cols="30"></textarea>
</div>
<div class="gc-redo-stack-container option-row">
<label>The redoStack includes the following command:</label>
<textarea type="text" class="gc-stack-list" id="gc-redo-stack-container" cols="30"></textarea>
</div>
<div class="option-row">
<label>Undo/Redo Stack Max Size</label>
<input type="number" min="0" max="2147483647" id="gc-max-size" class="gc-max-size" value="10">
<input type="button" id="gc-max-size-set" value="set">
</div>
</div>
</div>
export function getData(){
var data = [{
"version":"12.0.0",
"tabStripRatio":0.6,
"sheetCount":1,
"sheets":{
"Sheet1":{
"name":"Sheet1",
"rowCount":114,
"columnCount":21,
"activeRow":2,
"activeCol":2,
"data":{
"dataTable":{
"2":{
"2":{
"value":"Student",
"style":
{
"foreColor" : "#FFFFFF",
"backColor" : "#82BC00",
"hAlign" : 1
}
},
"3":{
"value":"Language",
"style": {
"foreColor" : "#FFFFFF",
"backColor" : "#82BC00",
"hAlign" : 1
}
},
"4":{
"value":"Math",
"style": {
"foreColor" : "#FFFFFF",
"backColor" : "#82BC00",
"hAlign" : 1
}
},
"5":{
"value":"Science",
"style": {
"foreColor" : "#FFFFFF",
"backColor" : "#82BC00",
"hAlign" : 1
}
},
"6":{
"value":"Music",
"style": {
"foreColor" : "#FFFFFF",
"backColor" : "#82BC00",
"hAlign" : 1
}
},
"7":{
"value":"History",
"style": {
"foreColor" : "#FFFFFF",
"backColor" : "#82BC00",
"hAlign" : 1
}
}
},
"3":{
"2":{
"value":"Ally",
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"3":{
"value":95.2,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"4":{
"value":65.2,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"5":{
"value":75.2,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"6":{
"value":95.2,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"7":{
"value":91.8,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
}
},
"4":{
"2":{
"value":"Tom",
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"3":{
"value":81.8,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"4":{
"value":95.2,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"5":{
"value":95,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"6":{
"value":75.2,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"7":{
"value":88,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
}
},
"5":{
"2":{
"value":"Jack",
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"3":{
"value":95.2,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"4":{
"value":68.2,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"5":{
"value":65.2,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"6":{
"value":88,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"7":{
"value":79,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
}
},
"6":{
"2":{
"value":"John",
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"3":{
"value":68.2,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"4":{
"value":81.8,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"5":{
"value":86,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"6":{
"value":75,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"7":{
"value":86,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
}
},
"7":{
"2":{
"value":"Lily",
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"3":{
"value":95.2,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"4":{
"value":65.2,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"5":{
"value":95.2,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"6":{
"value":95.2,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"7":{
"value":91.8,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
}
},
"8":{
"2":{
"value":"Linda",
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"3":{
"value":75.2,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"4":{
"value":95.2,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"5":{
"value":88,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"6":{
"value":65.2,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"7":{
"value":65.2,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
}
},
"9":{
"2":{
"value":"Will",
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"3":{
"value":95.2,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"4":{
"value":94.8,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"5":{
"value":94,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"6":{
"value":55.2,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
},
"7":{
"value":88,
"style":{"backColor" : "#F4F8EB", "hAlign" : 1}
}
}
}
},
}
}
}];
return data;
}
.sample-tutorial {
position: relative;
height: 100%;
overflow: hidden;
}
body {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.sample-spreadsheets {
width: calc(100% - 280px);
height: 100%;
overflow: hidden;
float: left;
}
.options-container{
float: right;
width: 280px;
padding: 12px;
height: 100%;
box-sizing: border-box;
background: #fbfbfb;
overflow: auto;
}
.option-row {
font-size: 14px;
padding: 5px;
margin-top: 10px;
}
.gc-stack-list{
width: 100%;
height: 150px;
margin-top: 10px;
}
.gc-stack-button{
margin: 0 5px;
}
(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-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);