You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
166 lines
3.9 KiB
166 lines
3.9 KiB
const _ = require('./under-dash');
|
|
const colCache = require('./col-cache');
|
|
|
|
class CellMatrix {
|
|
constructor(template) {
|
|
this.template = template;
|
|
this.sheets = {};
|
|
}
|
|
|
|
addCell(addressStr) {
|
|
this.addCellEx(colCache.decodeEx(addressStr));
|
|
}
|
|
|
|
getCell(addressStr) {
|
|
return this.findCellEx(colCache.decodeEx(addressStr), true);
|
|
}
|
|
|
|
findCell(addressStr) {
|
|
return this.findCellEx(colCache.decodeEx(addressStr), false);
|
|
}
|
|
|
|
findCellAt(sheetName, rowNumber, colNumber) {
|
|
const sheet = this.sheets[sheetName];
|
|
const row = sheet && sheet[rowNumber];
|
|
return row && row[colNumber];
|
|
}
|
|
|
|
addCellEx(address) {
|
|
if (address.top) {
|
|
for (let row = address.top; row <= address.bottom; row++) {
|
|
for (let col = address.left; col <= address.right; col++) {
|
|
this.getCellAt(address.sheetName, row, col);
|
|
}
|
|
}
|
|
} else {
|
|
this.findCellEx(address, true);
|
|
}
|
|
}
|
|
|
|
getCellEx(address) {
|
|
return this.findCellEx(address, true);
|
|
}
|
|
|
|
findCellEx(address, create) {
|
|
const sheet = this.findSheet(address, create);
|
|
const row = this.findSheetRow(sheet, address, create);
|
|
return this.findRowCell(row, address, create);
|
|
}
|
|
|
|
getCellAt(sheetName, rowNumber, colNumber) {
|
|
const sheet = this.sheets[sheetName] || (this.sheets[sheetName] = []);
|
|
const row = sheet[rowNumber] || (sheet[rowNumber] = []);
|
|
const cell =
|
|
row[colNumber] ||
|
|
(row[colNumber] = {
|
|
sheetName,
|
|
address: colCache.n2l(colNumber) + rowNumber,
|
|
row: rowNumber,
|
|
col: colNumber,
|
|
});
|
|
return cell;
|
|
}
|
|
|
|
removeCellEx(address) {
|
|
const sheet = this.findSheet(address);
|
|
if (!sheet) {
|
|
return;
|
|
}
|
|
const row = this.findSheetRow(sheet, address);
|
|
if (!row) {
|
|
return;
|
|
}
|
|
delete row[address.col];
|
|
}
|
|
|
|
forEachInSheet(sheetName, callback) {
|
|
const sheet = this.sheets[sheetName];
|
|
if (sheet) {
|
|
sheet.forEach((row, rowNumber) => {
|
|
if (row) {
|
|
row.forEach((cell, colNumber) => {
|
|
if (cell) {
|
|
callback(cell, rowNumber, colNumber);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
forEach(callback) {
|
|
_.each(this.sheets, (sheet, sheetName) => {
|
|
this.forEachInSheet(sheetName, callback);
|
|
});
|
|
}
|
|
|
|
map(callback) {
|
|
const results = [];
|
|
this.forEach(cell => {
|
|
results.push(callback(cell));
|
|
});
|
|
return results;
|
|
}
|
|
|
|
findSheet(address, create) {
|
|
const name = address.sheetName;
|
|
if (this.sheets[name]) {
|
|
return this.sheets[name];
|
|
}
|
|
if (create) {
|
|
return (this.sheets[name] = []);
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
findSheetRow(sheet, address, create) {
|
|
const {row} = address;
|
|
if (sheet && sheet[row]) {
|
|
return sheet[row];
|
|
}
|
|
if (create) {
|
|
return (sheet[row] = []);
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
findRowCell(row, address, create) {
|
|
const {col} = address;
|
|
if (row && row[col]) {
|
|
return row[col];
|
|
}
|
|
if (create) {
|
|
return (row[col] = this.template
|
|
? Object.assign(address, JSON.parse(JSON.stringify(this.template)))
|
|
: address);
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
spliceRows(sheetName, start, numDelete, numInsert) {
|
|
const sheet = this.sheets[sheetName];
|
|
if (sheet) {
|
|
const inserts = [];
|
|
for (let i = 0; i < numInsert; i++) {
|
|
inserts.push([]);
|
|
}
|
|
sheet.splice(start, numDelete, ...inserts);
|
|
}
|
|
}
|
|
|
|
spliceColumns(sheetName, start, numDelete, numInsert) {
|
|
const sheet = this.sheets[sheetName];
|
|
if (sheet) {
|
|
const inserts = [];
|
|
for (let i = 0; i < numInsert; i++) {
|
|
inserts.push(null);
|
|
}
|
|
_.each(sheet, row => {
|
|
row.splice(start, numDelete, ...inserts);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
module.exports = CellMatrix;
|