With incremental calculation, SpreadJS will calculate the cells with the period, and check and respond to the UI events every period.
This prevents the UI from freezing for a long time when the workbook contains many formulas.
In order to use the incremental calculation feature, you need to set the workbook option incrementalCalculation to true or load the file with incrementalCalculation. For example:
When incremental calculation, user can get the calculation progress by the CalculationProgress event.
For example:
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import './styles.css';
import { AppFunc } from './app-func';
import { App } from './app-class';
// 1. Functional Component sample
ReactDOM.render(<AppFunc />, document.getElementById('app'));
// 2. Class Component sample
// ReactDOM.render(<App />, document.getElementById('app'));
import * as React from 'react';
import { SpreadSheets, Worksheet } from '@mescius/spread-sheets-react';
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';
const useState = React.useState;
export function AppFunc() {
const [spread, setSpread] = useState(null);
const [selectedFile, setSelectedFile] = useState(null);
const initSpread = (spread) => {
setSpread(spread);
const statusBar = new GC.Spread.Sheets.StatusBar.StatusBar(
document.getElementById('statusBar')
);
statusBar.bind(spread);
fetch(getFileUrl()).then((res) => res.blob()).then((file) =>
spread.open(file, null, null, {
openMode: 2, // incremental loading
fullRecalc: true,
incrementalCalculation: true
})
);
}
const selectedFileChange = (e) => {
const selectedFile = e.target.files[0];
setSelectedFile(selectedFile);
}
const optionChanged = (e) => {
spread.options.incrementalCalculation = e.target.checked;
}
const calculateAll = () => {
spread.calculate();
}
const getFileUrl = () => {
return '$DEMOROOT$/spread/source/data/incremental-calculation.sjs';
}
const isSJSFile = (file) => {
const fileName = file.name;
const extensionName = fileName.substring(fileName.lastIndexOf('.') + 1);
return extensionName === 'sjs';
}
const open = () => {
const file = selectedFile;
if (!file) {
return;
}
const options = {
openMode: 2, // incremental loading
fullRecalc: true,
dynamicReferences: false,
incrementalCalculation: spread.options.incrementalCalculation
};
if (isSJSFile(file)) {
spread.open(file, function () { }, function () { }, options);
} else {
spread.import(file, function () { }, function () { }, options);
}
}
return <div class="sample-tutorial">
<div class="sample-container">
<div class="sample-spreadsheets">
<SpreadSheets workbookInitialized={spread => initSpread(spread)}>
<Worksheet>
</Worksheet>
</SpreadSheets>
</div>
<div id="statusBar"></div>
</div>
<div className="options-container">
<div className="option-row">
<div class="inputContainer">
<input id="selectedFile" type="file" accept=".sjs, .xlsx, .xlsm, .ssjson, .json, .csv" onChange={selectedFileChange} />
<button class="settingButton" id="open" onClick={open}>Open</button>
<div className="options">
<div className="item">
<input
type="checkbox"
id="enable-incremental-calculation"
onChange={optionChanged}
defaultChecked={true}
/>
<label htmlFor="enable-incremental-calculation">Enable incremental calculation</label>
</div>
</div>
<button class="settingButton" id="open" onClick={calculateAll}>Calculate All</button>
</div>
</div>
</div>
</div>;
}
import * as React from 'react';
import { SpreadSheets, Worksheet } from '@mescius/spread-sheets-react';
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';
const Component = React.Component;
window.GC = GC;
export class App extends Component {
constructor(props) {
super(props);
this.spread = null;
this.state = {
selectedFile: null
};
this.open = this.open.bind(this);
this.calculateAll = this.calculateAll.bind(this);
this.selectedFileChange = this.selectedFileChange.bind(this);
this.optionChanged = this.optionChanged.bind(this);
}
render() {
return <div class="sample-tutorial">
<div class="sample-container">
<div class="sample-spreadsheets">
<SpreadSheets workbookInitialized={spread => this.initSpread(spread)}>
<Worksheet>
</Worksheet>
</SpreadSheets>
</div>
<div id="statusBar"></div>
</div>
<div className="options-container">
<div className="option-row">
<div class="inputContainer">
<input id="selectedFile" type="file" accept=".sjs, .xlsx, .xlsm, .ssjson, .json, .csv" onChange={this.selectedFileChange} />
<button class="settingButton" id="open" onClick={this.open}>Open</button>
<div className="options">
<div className="item">
<input
type="checkbox"
id="enable-incremental-calculation"
onChange={this.optionChanged}
defaultChecked={true}
/>
<label htmlFor="enable-incremental-calculation">Enable incremental calculation</label>
</div>
</div>
<button class="settingButton" id="open" onClick={this.calculateAll}>Calculate All</button>
</div>
</div>
</div>
</div>;
}
initSpread(spread) {
this.spread = spread;
const statusBar = new GC.Spread.Sheets.StatusBar.StatusBar(
document.getElementById('statusBar')
);
statusBar.bind(spread);
fetch(this.getFileUrl()).then((res) => res.blob()).then((file) =>
spread.open(file, null, null, {
openMode: 2, // incremental loading
fullRecalc: true,
incrementalCalculation: true
})
);
}
selectedFileChange(e) {
const selectedFile = e.target.files[0];
this.setState({ ...this.state, selectedFile });
}
optionChanged(e) {
this.spread.options.incrementalCalculation = e.target.checked;
}
calculateAll() {
this.spread.calculate();
}
getFileUrl() {
return '$DEMOROOT$/spread/source/data/incremental-calculation.sjs';
}
isSJSFile(file) {
const fileName = file.name;
const extensionName = fileName.substring(fileName.lastIndexOf('.') + 1);
return extensionName === 'sjs';
}
open() {
const file = this.state.selectedFile;
if (!file) {
return;
}
const options = {
openMode: 2, // incremental loading
fullRecalc: true,
dynamicReferences: false,
incrementalCalculation: this.spread.options.incrementalCalculation
};
if (this.isSJSFile(file)) {
this.spread.open(file, function () {}, function () {}, options);
} else {
this.spread.import(file, function () {}, function () {}, options);
}
}
}
<!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/react/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css">
<script src="$DEMOROOT$/spread/source/js/FileSaver.js" type="text/javascript"></script>
<!-- SystemJS -->
<script src="$DEMOROOT$/en/react/node_modules/systemjs/dist/system.src.js"></script>
<script src="systemjs.config.js"></script>
<script>
System.import('$DEMOROOT$/en/lib/react/license.js').then(function () {
System.import('./src/app');
});
</script>
</head>
<body>
<div id="app"></div>
</body>
</html>
body {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
#app {
height: 100%;
}
.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;
}
#statusBar {
bottom: 0;
height: 25px;
width: 100%;
position: relative;
}
.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;
}
.options-title {
font-weight: bold;
margin: 4px 2px;
}
#selectedFile {
width: 180px;
}
#saveFileType {
width: 120px;
height: 31px;
}
.options .item {
margin: 5px 0px;
display: flex;
}
.save-options .item {
margin: 5px 0px;
display: flex;
}
label {
margin-left: 3px;
}
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;
}
(function (global) {
System.config({
transpiler: 'plugin-babel',
babelOptions: {
es2015: true,
react: true
},
meta: {
'*.css': { loader: 'css' }
},
paths: {
// paths serve as alias
'npm:': 'node_modules/'
},
// map tells the System loader where to look for things
map: {
'@mescius/spread-sheets': 'npm:@mescius/spread-sheets/index.js',
'@mescius/spread-sheets-print': 'npm:@mescius/spread-sheets-print/index.js',
'@mescius/spread-sheets-react': 'npm:@mescius/spread-sheets-react/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',
'@grapecity/jsob-test-dependency-package/react-components': 'npm:@grapecity/jsob-test-dependency-package/react-components/index.js',
'react': 'npm:react/umd/react.production.min.js',
'react-dom': 'npm:react-dom/umd/react-dom.production.min.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'
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
src: {
defaultExtension: 'jsx'
},
"node_modules": {
defaultExtension: 'js'
},
}
});
})(this);