在新窗口中打开演示可以打开设计器:
ReportSheet支持以下数据输入事件。您可以使用以下代码绑定数据输入事件:
ReportSheetDataChanging和ReportSheetDataChanged
ReportSheetDataChanging在报表表格通过更新、插入或删除进行更改时发生。允许验证或取消数据操作。
ReportSheetDataChanged在报表表格通过更新、插入或删除更改数据时发生。允许将数据更改提交到服务器。
ReportSheetRecordsSubmitting和ReportSheetRecordsSubmitted
ReportSheetRecordsSubmitting在报表表格提交更改到服务器之前发生。允许对所有数据更改进行最终验证或取消操作。
ReportSheetRecordsSubmitted在报表表格将更改提交到服务器后发生。允许用户提供来自服务器的提交结果的UI反馈。
window.onload = async () => {
const loadingTip = addLoadingTip();
const { spread, designer } = createSpreadAndDesigner();
const res = await fetch('$DEMOROOT$/zh/sample/features/report-sheet/data-entry/events/spread.json');
await spread.fromJSON(correctTableUrl(await res.json()));
loadingTip.remove();
_bindDataEntrySubmitEvents(spread);
if (designer) {
designer.refresh();
}
}
function createSpreadAndDesigner() {
const demoHost = document.getElementById('demo-host');
if (window !== top) {
return {
spread: new GC.Spread.Sheets.Workbook(demoHost, { sheetCount: 1 }),
}
} else {
const designer = new GC.Spread.Sheets.Designer.Designer(demoHost, undefined, undefined, { sheetCount: 1 });
return {
designer,
spread: designer.getWorkbook(),
}
}
}
function addLoadingTip() {
const div = document.createElement('div');
div.style.position = 'absolute';
div.style.inset = '0';
div.style.display = 'flex';
div.style.alignItems = 'center';
div.style.justifyContent = 'center';
div.style.background = 'white';
div.style.zIndex = '100';
div.textContent = 'Loading data from server ...';
document.body.appendChild(div);
return div;
}
function correctTableUrl(json) {
const baseUrl = '$DEMOROOT$';
const localUrl = 'http://localhost:8070/spreadjs/demos';
const replaceUrl = (obj) => {
if (obj && obj.url && obj.url.startsWith(localUrl)) {
obj.url = obj.url.replace(localUrl, baseUrl);
}
}
if (json.dataManager && json.dataManager.tables) {
json.dataManager.tables.forEach((table) => {
if (table.dataSourceOption && table.dataSourceOption.remote) {
Object.values(table.dataSourceOption.remote).forEach(replaceUrl);
}
});
}
return json;
}
let time;
function _showWindowTip (message, success) {
let tipContainer = document.querySelector('.tip-container');
if (!tipContainer) {
const div = document.createElement('div');
div.classList.add("tip-container");
document.body.appendChild(div);
tipContainer = div;
}
let innerContainer = document.createElement('div');
innerContainer.className = `tip-inner-container ${success ? 'success' : 'failed'}`;
innerContainer.innerHTML = `
<h1>${success ? "Success" : "Failed"}</h1>
<p>${message}</p>
`;
tipContainer.appendChild(innerContainer);
if (time) {
clearTimeout(time);
}
time = setTimeout(() => {
tipContainer.innerHTML = "";
clearTimeout(time);
time = 0;
}, 4000);
}
function _bindDataEntrySubmitEvents (spread) {
let reportSheet = spread.getActiveSheetTab();
if (reportSheet) {
reportSheet.bind(GC.Spread.Sheets.Events.ReportSheetDataChanging, (event, args) => {
let { row, col, newValue, type } = args;
if (type === "update") {
if (col <= 4 && typeof newValue !== "string") {
args.cancel = true;
_showWindowTip("New value should be string at col " + col);
} else if (col === 5 && typeof newValue !== "number") {
args.cancel = true;
_showWindowTip("New value should be number at col " + col);
} else {
type = type[0].toUpperCase() + type.substring(1);
_showWindowTip(`${(type)} at cell Row: ${row} col: ${col}`, true);
}
} else {
type = type[0].toUpperCase() + type.substring(1);
_showWindowTip(`${type} at cell Row: ${row} col: ${col}`, true);
}
});
reportSheet.bind(GC.Spread.Sheets.Events.ReportSheetRecordsSubmitted, (event, args) => {
let { updateSuccessRecords, updateFailedRecords, deleteSuccessRecords, deleteFailedRecords } = args;
let updateSuccessCells = [], deleteSuccessCells = [], updateFailedCells = [], deleteFailedCells = [];
updateSuccessRecords.forEach((r) => {
for (let key in r.info) {
if (r.info.hasOwnProperty(key) && r.info[key].state === "updated") {
updateSuccessCells.push({
row: r.info[key].row,
col: r.info[key].col,
});
}
}
});
deleteSuccessRecords.forEach((r) => {
for (let key in r.info) {
if (r.info.hasOwnProperty(key)) {
deleteSuccessCells.push({
row: r.info[key].row,
col: r.info[key].col,
});
}
}
});
updateFailedRecords.forEach((r) => {
for (let key in r.info) {
if (r.info.hasOwnProperty(key) && r.info[key].state === "updated") {
updateFailedCells.push({
row: r.info[key].row,
col: r.info[key].col,
reason: r.reason === undefined ? "null" : r.reason
});
}
}
});
deleteFailedRecords.forEach((r) => {
for (let key in r.info) {
if (r.info.hasOwnProperty(key)) {
deleteFailedCells.push({
row: r.info[key].row,
col: r.info[key].col,
reason: r.reason === undefined ? "null" : r.reason
});
}
}
});
updateSuccessCells.forEach((cell, i) => {
setTimeout(() => {
_showWindowTip(`Update successfully at cell Row: ${cell.row} col: ${cell.col}`, true);
}, i * 100);
});
setTimeout(() => {
deleteSuccessCells.forEach((cell, i) => {
setTimeout(() => {
_showWindowTip(`Delete successfully at cell Row: ${cell.row} col: ${cell.col}`, true);
}, i * 100);
});
}, updateSuccessCells.length * 100);
setTimeout(() => {
updateFailedCells.forEach((cell, i) => {
setTimeout(() => {
_showWindowTip(`Update failed at cell Row: ${cell.row} col: ${cell.col}, reason is ${cell.reason}`);
}, i * 100);
});
}, (updateSuccessCells.length + deleteSuccessCells.length) * 100);
setTimeout(() => {
deleteFailedCells.forEach((cell, i) => {
setTimeout(() => {
_showWindowTip(`Delete failed at cell Row: ${cell.row} col: ${cell.col}, reason is ${cell.reason}`);
}, i * 100);
});
}, (updateSuccessCells.length + deleteSuccessCells.length + updateFailedCells.length) * 100);
});
}
}
<!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" />
<meta name="spreadjs culture" content="zh-cn" />
<link rel="stylesheet" type="text/css" href="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets/styles/gc.spread.sheets.excel2013white.css">
<link rel="stylesheet" type="text/css" href="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-designer/styles/gc.spread.sheets.designer.min.css">
<link rel="stylesheet" type="text/css" href="styles.css">
<script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets/dist/gc.spread.sheets.all.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-print/dist/gc.spread.sheets.print.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-shapes/dist/gc.spread.sheets.shapes.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-charts/dist/gc.spread.sheets.charts.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-reportsheet-addon/dist/gc.spread.report.reportsheet.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-resources-zh/dist/gc.spread.sheets.resources.zh.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/spread/source/js/license.js" type="text/javascript"></script>
<script>
const designerDependencyScripts = [
'$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-barcode/dist/gc.spread.sheets.barcode.min.js',
'$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-pdf/dist/gc.spread.sheets.pdf.min.js',
'$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-pivot-addon/dist/gc.spread.pivot.pivottables.min.js',
'$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-slicers/dist/gc.spread.sheets.slicers.min.js',
'$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-tablesheet/dist/gc.spread.sheets.tablesheet.min.js',
'$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-ganttsheet/dist/gc.spread.sheets.ganttsheet.min.js',
'$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-formula-panel/dist/gc.spread.sheets.formulapanel.min.js',
'$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-io/dist/gc.spread.sheets.io.min.js',
'$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-designer-resources-cn/dist/gc.spread.sheets.designer.resource.cn.min.js',
'$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-designer/dist/gc.spread.sheets.designer.all.min.js',
'$DEMOROOT$/spread/source/js/designer/license.js',
]
function appendScriptNode (src) {
const script = document.createElement('script');
script.src = src;
script.async = false;
script.type = 'text/javascript';
document.head.appendChild(script);
}
if (top === window) { // not in iframe
designerDependencyScripts.forEach(appendScriptNode);
}
</script>
<script src="app.js" type="text/javascript"></script>
</head>
<body>
<div class="sample-tutorial">
<div id="demo-host"></div>
</div>
</body>
</html>
body {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.sample-tutorial {
position: relative;
height: 100%;
overflow: hidden;
}
#demo-host {
width: 100%;
height: 100%;
overflow: hidden;
float: left;
}
.tip-container {
position: absolute;
display: flex;
align-items: center;
justify-content: start;
z-index: 100;
min-width: 300px;
min-height: 60%;
max-height: 100%;
right: 0;
top: 0;
overflow: hidden;
flex-direction: column;
}
.tip-inner-container {
position: relative;
display: flex;
height: 52px;
background-color: white;
flex-direction: column;
min-width: 200px;
margin-bottom: 10px;
padding: 0px 25px 0 10px;
border-radius: 10px;
box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 5px 0px, rgba(0, 0, 0, 0.1) 0px 2px 3px 0px;
align-items: start;
animation-name: tip-animation;
animation-duration: 4s;
animation-fill-mode: forwards;
color: rgb(51, 51, 51);
font-family: sans-serif;
}
.success {
border-left: solid 8px rgb(154, 233, 140);
}
.failed {
border-left: solid 8px rgb(227, 144, 143);
}
.tip-inner-container h1 {
margin: 0;
padding-top: 5px;
font-size: 17.6px;
font-weight: 500;
}
.tip-inner-container p {
margin: 0;
padding-top: 5px;
font-size: 12.8px;
}
@keyframes tip-animation {
0% {
left: 300px;
opacity: 0;
}
20% {
left: 10px;
opacity: 1;
}
75% {
left: 10px;
opacity: 1;
}
100% {
left: 300px;
opacity: 0;
}
}