더티 개념은 다음과 같이 정의됩니다:
일반적으로 셀 값을 변경할 때만 수정됩니다.
셀이 수정된 경우 현재 행도 수정됩니다.
하나의 행이 삽입되고 셀에서 값이 설정된 경우, 행은 수정된 행이 아니라 삽입된 행으로 간주됩니다. 셀은 수정된 셀로 간주되지 않습니다.
바인딩된 데이터를 로드할 때 항목은 수정된 것으로 간주되지 않지만, 바인딩된 데이터의 값이 변경된 후에는 수정된 것으로 간주됩니다.
항목은 실행 취소 작업 후에도 수정 상태를 유지합니다.
시트에서 getDirtyRows 메서드를 호출하면 모든 더티 행을 가져올 수 있습니다. 기존에 바인딩된 데이터가 있는 경우 사용자는 더티 행에서 row, item 및 originalItem을 가져오고, 그렇지 않으면 값이 있는 row만 가져옵니다.
getDirtyCells 메서드를 호출하면 모든 더티 셀을 가져올 수 있습니다. 지정된 범위가 주어지면 다음 순서로 작업 인수를 제공하십시오.
row: 범위에 있는 왼쪽 위 셀의 행 인덱스입니다.
col: 범위에 있는 왼쪽 위 셀의 열 인덱스입니다.
rowCount: 범위의 총 행 수입니다.
colCount: 범위의 총 열 수입니다.
각 더티 셀은 다음 정보를 제공합니다: row, col, oldValue, newValue.
시트에서 getDeletedRows 메서드를 호출하면 삭제된 행을 모두 가져올 수 있습니다. 기존에 바인딩된 데이터가 있는 경우 사용자는 더티 행에서 row 및 originalItem을 가져오고, 그렇지 않으면 값이 있는 row만 가져옵니다.
시트에서 getInsertRows 메서드를 호출하면 삽입된 모든 행을 가져올 수 있습니다. 삽입된 각 행은 row 및 item(데이터)에 대한 정보를 제공합니다.
더티, 삽입 및 삭제된 상태는 clearPendingChanges에 의해 지워질 수 있습니다. 이는 setRowCount, setColumnCount, fromJSON 또는 setDataSource를 호출하면 자동으로 지워집니다. 또한 범위별로 더티/삽입됨/삭제됨 상태를 지울 수도 있습니다. 지우기 작업을 지정하려면 선택적 개체 매개 변수인 clearChangeInfo를 제공합니다.
clearChangeInfo.row: [선택] 지워진 범위의 행 인덱스
clearChangeInfo.col: [선택] 지워진 범위의 열 인덱스
clearChangeInfo.rowCount: [선택] 지워진 범위의 행 수
clearChangeInfo.colCount: [선택] 지워진 범위의 열 수
clearChangeInfo.clearType: [선택] 보류 중인 변경사항의 삭제 유형(더티/삽입/삭제 포함), 기본값은 더티. 그 값은 GC.Spread.Sheets.ClearPendingChangeType의 열거형입니다.
<template>
<div class="sample-tutorial">
<gc-spread-sheets class="sample-spreadsheets" @workbookInitialized="initSpread">
<gc-worksheet>
</gc-worksheet>
</gc-spread-sheets>
<div class="options-container">
<p>Insert/delete rows or change row/column count using the buttons below.</p>
<p>You can then get the dirty (what’s changed) rows or cells by clicking the “Get Dirty Rows”, “Get All Dirty Cells”, etc. buttons.</p>
<div class="option-row">
<input type="button" id="btnInsertRow" value="Insert Row" title="Insert an new row at selected row" @click="insertRow($event)" />
<input type="button" id="btnDeleteRow" value="Delete Rows" title="Deleted seleted rows" @click="deleteRow($event)" />
</div>
<p>If clear pending change by range, please select range in sheet and select type with Dirty/Insert/Delete.</p>
<div class="option-row">
<div>
<input id="clearByRange" type="checkbox">
<label for="clearByRange">Clear by Range</label>
</div>
<div>
<input id="clearDirty" type="checkbox">
<label for="clearDirty">Dirty</label>
<input id="clearInsert" type="checkbox">
<label for="clearInsert">Insert</label>
<input id="clearDelete" type="checkbox">
<label for="clearDelete">Delete</label>
</div>
<input type="button" id="btnClearPendingChanges" value="Clear Pending Changes" title="Clear pending changes" @click="clearPendingChanges($event)" />
</div>
<div class="option-row">
<input type="button" id="btnSetRowCount" value="Set Row Count" title="Set row count to 60" @click="setRowCount($event)" />
<input type="button" id="btnSetColumnCount" value="Set Column Count" title="Set column count to 16" @click="setColumnCount($event)" />
</div>
<div class="option-row">
<input type="button" id="btnGetDirtyRows" value="Get Dirty Rows" @click="getDirtyRows($event)" />
<input type="button" id="btnGetDirtyCells" value="Get All Dirty Cells" @click="getAllDirtyCells($event)" />
<input type="button" id="btnGetSelectionDirtyCells" value="Get Selection Dirty Cells" @click="getSelectionDirty($event)" />
</div>
<div class="option-row">
<input type="button" id="btnGetInsertRows" value="Get Insert Rows" @click="getInsertRow($event)" />
<input type="button" id="btnGetDeleteRows" value="Get Delete Rows" @click="getDeleteRow($event)" />
</div>
<div class="option-row" style="width:100%;height:80px;">
<textarea id="taResult" style="width:100%;padding:0;float:right;height:80px;background:none" v-model="text"></textarea>
</div>
</div>
</div>
</template>
<script>
import Vue from "vue";
import '@mescius/spread-sheets-resources-ko';
GC.Spread.Common.CultureManager.culture("ko-kr");
import "@mescius/spread-sheets-vue";
import GC from "@mescius/spread-sheets";
import "./styles.css";
let App = Vue.extend({
name: "app",
data: function () {
return {
text: ""
};
},
methods: {
initSpread: function (spread) {
const spreadNS = GC.Spread.Sheets;
this.spread = spread;
let sheet = spread.getSheet(0);
sheet.suspendPaint();
for (let r = 0; r < 30; r++) {
sheet.setText(r, 0, "A" + (r + 1));
}
for (let c = 1; c < 20; c++) {
sheet.setText(0, c, String.fromCharCode(65 + c) + "1");
}
sheet.resumePaint();
sheet.clearPendingChanges();
let self = this;
spread.bind(spreadNS.Events.CellChanged, function (event, data) {
let row = data.row,
col = data.col;
if (row === undefined || col === undefined) {
return;
}
if (sheet.hasPendingChanges(row, col)) {
let dirtyDataArray = sheet.getDirtyCells(row, col);
if (dirtyDataArray.length > 0) {
self.appendResult(getChangedCellData(dirtyDataArray[0]));
}
}
});
spread.bind(spreadNS.Events.RowChanged, function (event, data) {
let row = data.row,
count = data.count,
propName = data.propertyName;
if (row === undefined || count === undefined || propName === undefined) {
return;
}
if (propName === "addRows" || propName === "deleteRows") {
self.appendResult(propName + " @ " + row + (count > 1 ? " count: " + count : ""));
}
});
},
insertRow() {
let sheet = this.spread.getActiveSheet();
let sels = sheet.getSelections();
let len = sels.length;
if (len > 0) {
let s = sels[0];
sheet.addRows(s.row, 1);
}
},
deleteRow() {
let sheet = this.spread.getActiveSheet();
let sels = sheet.getSelections();
let len = sels.length;
if (len > 0) {
let s = sels[0];
sheet.deleteRows(s.row, s.rowCount);
}
},
clearPendingChanges() {
let sheet = this.spread.getActiveSheet();
let clearByRange = _getElementById("clearByRange").checked;
if (clearByRange) {
let dirty = _getElementById("clearDirty").checked ? 1 : 0;
let insert = _getElementById("clearInsert").checked ? 2 : 0;
let deleted = _getElementById("clearDelete").checked ? 4 : 0;
let clearType = dirty | insert | deleted;
let selections = sheet.getSelections();
selections.forEach((selection) => {
sheet.clearPendingChanges({
clearType: clearType, row: selection.row, rowCount: selection.rowCount, col: selection.col, colCount: selection.colCount
});
});
} else {
sheet.clearPendingChanges();
}
this.text = '';
},
setRowCount() {
let sheet = this.spread.getActiveSheet();
sheet.setRowCount(60);
},
setColumnCount() {
let sheet = this.spread.getActiveSheet();
sheet.setColumnCount(16);
},
getDirtyRows() {
let sheet = this.spread.getActiveSheet();
let rows = sheet.getDirtyRows();
if (rows.length > 0) {
this.appendResult("Dirty rows @ " + rows.map(function (item) {
return item.row;
}).join(", "));
}
},
getAllDirtyCells() {
let sheet = this.spread.getActiveSheet();
let cells = sheet.getDirtyCells();
if (cells.length > 0) {
this.appendResult("Dirty Cells:\n" + cells.map(function (item) {
return getDirtyCellData(item);
}).join("\n"));
}
},
getSelectionDirty() {
let sheet = this.spread.getActiveSheet();
let sels = sheet.getSelections();
let len = sels.length;
if (len > 0) {
let s = sels[0];
let row = s.row,
col = s.col;
if (row < 0) {
row = 0;
}
if (col < 0) {
col = 0;
}
let cells = sheet.getDirtyCells(row, col, s.rowCount, s.colCount);
if (cells.length > 0) {
this.appendResult("Dirty Cells:\n" + cells.map(function (item) {
return getDirtyCellData(item);
}).join("\n"));
}
}
},
getInsertRow() {
let sheet = this.spread.getActiveSheet();
let rows = sheet.getInsertRows();
if (rows.length > 0) {
this.appendResult("Inserted rows @ " + rows.map(function (item) {
return item.row;
}).join(", "));
}
},
getDeleteRow() {
let sheet = this.spread.getActiveSheet();
let rows = sheet.getDeletedRows();
if (rows.length > 0) {
this.appendResult("Deleted rows @ " + rows.map(function (item) {
return item.row;
}).join(", "));
}
},
appendResult(txt) {
this.text = this.text + txt + "\n";
}
}
});
function _getElementById(id) {
return document.getElementById(id);
}
function getChangedCellData(dirtyItem) {
return ["Cell (", dirtyItem.row, ",", dirtyItem.col, ") changed from ", dirtyItem.oldValue, " to ", dirtyItem.newValue].join("");
}
function getDirtyCellData(dirtyItem) {
return ["Cell (", dirtyItem.row, ",", dirtyItem.col, ") oldValue: ", dirtyItem.oldValue, " newValue: ", dirtyItem.newValue].join("");
}
new Vue({
render: h => h(App)
}).$mount("#app");
</script>
<!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$/ko/vue/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css">
<!-- SystemJS -->
<script src="$DEMOROOT$/ko/vue/node_modules/systemjs/dist/system.src.js"></script>
<script src="systemjs.config.js"></script>
<script>
System.import('./src/app.vue');
System.import('$DEMOROOT$/ko/lib/vue/license.js');
</script>
</head>
<body>
<div id="app"></div>
</body>
</html>
.sample-tutorial {
position: relative;
height: 100%;
overflow: hidden;
}
.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;
}
p{
padding:2px 10px;
background-color:lavender;
}
input[type="button"] {
width: 100%;
margin-bottom: 2px;
}
body {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
(function (global) {
System.config({
transpiler: 'plugin-babel',
babelOptions: {
es2015: true
},
meta: {
'*.css': { loader: 'css' },
'*.vue': { loader: 'vue-loader' }
},
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-resources-ko': 'npm:@mescius/spread-sheets-resources-ko/index.js',
'@mescius/spread-sheets-vue': 'npm:@mescius/spread-sheets-vue/index.js',
'@grapecity/jsob-test-dependency-package/react-components': 'npm:@grapecity/jsob-test-dependency-package/react-components/index.js',
'jszip': 'npm:jszip/dist/jszip.js',
'css': 'npm:systemjs-plugin-css/css.js',
'vue': 'npm:vue/dist/vue.min.js',
'vue-loader': 'npm:systemjs-vue-browser/index.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'
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
src: {
defaultExtension: 'js'
},
rxjs: {
defaultExtension: 'js'
},
"node_modules": {
defaultExtension: 'js'
}
}
});
})(this);