UNPKG

x-data-spreadsheet

Version:
357 lines (325 loc) 9.32 kB
import helper from './helper'; import { expr2expr } from './alphabet'; class Rows { constructor({ len, height }) { this._ = {}; this.len = len; // default row height this.height = height; } getHeight(ri) { if (this.isHide(ri)) return 0; const row = this.get(ri); if (row && row.height) { return row.height; } return this.height; } setHeight(ri, v) { const row = this.getOrNew(ri); row.height = v; } unhide(idx) { let index = idx; while (index > 0) { index -= 1; if (this.isHide(index)) { this.setHide(index, false); } else break; } } isHide(ri) { const row = this.get(ri); return row && row.hide; } setHide(ri, v) { const row = this.getOrNew(ri); if (v === true) row.hide = true; else delete row.hide; } setStyle(ri, style) { const row = this.getOrNew(ri); row.style = style; } sumHeight(min, max, exceptSet) { return helper.rangeSum(min, max, (i) => { if (exceptSet && exceptSet.has(i)) return 0; return this.getHeight(i); }); } totalHeight() { return this.sumHeight(0, this.len); } get(ri) { return this._[ri]; } getOrNew(ri) { this._[ri] = this._[ri] || { cells: {} }; return this._[ri]; } getCell(ri, ci) { const row = this.get(ri); if (row !== undefined && row.cells !== undefined && row.cells[ci] !== undefined) { return row.cells[ci]; } return null; } getCellMerge(ri, ci) { const cell = this.getCell(ri, ci); if (cell && cell.merge) return cell.merge; return [0, 0]; } getCellOrNew(ri, ci) { const row = this.getOrNew(ri); row.cells[ci] = row.cells[ci] || {}; return row.cells[ci]; } // what: all | text | format setCell(ri, ci, cell, what = 'all') { const row = this.getOrNew(ri); if (what === 'all') { row.cells[ci] = cell; } else if (what === 'text') { row.cells[ci] = row.cells[ci] || {}; row.cells[ci].text = cell.text; } else if (what === 'format') { row.cells[ci] = row.cells[ci] || {}; row.cells[ci].style = cell.style; if (cell.merge) row.cells[ci].merge = cell.merge; } } setCellText(ri, ci, text) { const cell = this.getCellOrNew(ri, ci); cell.text = text; } // what: all | format | text copyPaste(srcCellRange, dstCellRange, what, autofill = false, cb = () => {}) { const { sri, sci, eri, eci, } = srcCellRange; const dsri = dstCellRange.sri; const dsci = dstCellRange.sci; const deri = dstCellRange.eri; const deci = dstCellRange.eci; const [rn, cn] = srcCellRange.size(); const [drn, dcn] = dstCellRange.size(); // console.log(srcIndexes, dstIndexes); let isAdd = true; let dn = 0; if (deri < sri || deci < sci) { isAdd = false; if (deri < sri) dn = drn; else dn = dcn; } for (let i = sri; i <= eri; i += 1) { if (this._[i]) { for (let j = sci; j <= eci; j += 1) { if (this._[i].cells && this._[i].cells[j]) { for (let ii = dsri; ii <= deri; ii += rn) { for (let jj = dsci; jj <= deci; jj += cn) { const nri = ii + (i - sri); const nci = jj + (j - sci); const ncell = helper.cloneDeep(this._[i].cells[j]); // ncell.text if (autofill && ncell && ncell.text && ncell.text.length > 0) { const { text } = ncell; let n = (jj - dsci) + (ii - dsri) + 2; if (!isAdd) { n -= dn + 1; } if (text[0] === '=') { ncell.text = text.replace(/\w{1,3}\d/g, (word) => { let [xn, yn] = [0, 0]; if (sri === dsri) { xn = n - 1; // if (isAdd) xn -= 1; } else { yn = n - 1; } if (/^\d+$/.test(word)) return word; return expr2expr(word, xn, yn); }); } else if ((rn <= 1 && cn > 1 && (dsri > eri || deri < sri)) || (cn <= 1 && rn > 1 && (dsci > eci || deci < sci)) || (rn <= 1 && cn <= 1)) { const result = /[\\.\d]+$/.exec(text); // console.log('result:', result); if (result !== null) { const index = Number(result[0]) + n - 1; ncell.text = text.substring(0, result.index) + index; } } } this.setCell(nri, nci, ncell, what); cb(nri, nci, ncell); } } } } } } } cutPaste(srcCellRange, dstCellRange) { const ncellmm = {}; this.each((ri) => { this.eachCells(ri, (ci) => { let nri = parseInt(ri, 10); let nci = parseInt(ci, 10); if (srcCellRange.includes(ri, ci)) { nri = dstCellRange.sri + (nri - srcCellRange.sri); nci = dstCellRange.sci + (nci - srcCellRange.sci); } ncellmm[nri] = ncellmm[nri] || { cells: {} }; ncellmm[nri].cells[nci] = this._[ri].cells[ci]; }); }); this._ = ncellmm; } // src: Array<Array<String>> paste(src, dstCellRange) { if (src.length <= 0) return; const { sri, sci } = dstCellRange; src.forEach((row, i) => { const ri = sri + i; row.forEach((cell, j) => { const ci = sci + j; this.setCellText(ri, ci, cell); }); }); } insert(sri, n = 1) { const ndata = {}; this.each((ri, row) => { let nri = parseInt(ri, 10); if (nri >= sri) { nri += n; this.eachCells(ri, (ci, cell) => { if (cell.text && cell.text[0] === '=') { cell.text = cell.text.replace(/\w{1,3}\d/g, word => expr2expr(word, 0, n, (x, y) => y >= sri)); } }); } ndata[nri] = row; }); this._ = ndata; this.len += n; } delete(sri, eri) { const n = eri - sri + 1; const ndata = {}; this.each((ri, row) => { const nri = parseInt(ri, 10); if (nri < sri) { ndata[nri] = row; } else if (ri > eri) { ndata[nri - n] = row; this.eachCells(ri, (ci, cell) => { if (cell.text && cell.text[0] === '=') { cell.text = cell.text.replace(/\w{1,3}\d/g, word => expr2expr(word, 0, -n, (x, y) => y > eri)); } }); } }); this._ = ndata; this.len -= n; } insertColumn(sci, n = 1) { this.each((ri, row) => { const rndata = {}; this.eachCells(ri, (ci, cell) => { let nci = parseInt(ci, 10); if (nci >= sci) { nci += n; if (cell.text && cell.text[0] === '=') { cell.text = cell.text.replace(/\w{1,3}\d/g, word => expr2expr(word, n, 0, x => x >= sci)); } } rndata[nci] = cell; }); row.cells = rndata; }); } deleteColumn(sci, eci) { const n = eci - sci + 1; this.each((ri, row) => { const rndata = {}; this.eachCells(ri, (ci, cell) => { const nci = parseInt(ci, 10); if (nci < sci) { rndata[nci] = cell; } else if (nci > eci) { rndata[nci - n] = cell; if (cell.text && cell.text[0] === '=') { cell.text = cell.text.replace(/\w{1,3}\d/g, word => expr2expr(word, -n, 0, x => x > eci)); } } }); row.cells = rndata; }); } // what: all | text | format | merge deleteCells(cellRange, what = 'all') { cellRange.each((i, j) => { this.deleteCell(i, j, what); }); } // what: all | text | format | merge deleteCell(ri, ci, what = 'all') { const row = this.get(ri); if (row !== null) { const cell = this.getCell(ri, ci); if (cell !== null) { if (what === 'all') { delete row.cells[ci]; } else if (what === 'text') { if (cell.text) delete cell.text; if (cell.value) delete cell.value; } else if (what === 'format') { if (cell.style !== undefined) delete cell.style; if (cell.merge) delete cell.merge; } else if (what === 'merge') { if (cell.merge) delete cell.merge; } } } } maxCell() { const keys = Object.keys(this._); const ri = keys[keys.length - 1]; const col = this._[ri]; if (col) { const { cells } = col; const ks = Object.keys(cells); const ci = ks[ks.length - 1]; return [parseInt(ri, 10), parseInt(ci, 10)]; } return [0, 0]; } each(cb) { Object.entries(this._).forEach(([ri, row]) => { cb(ri, row); }); } eachCells(ri, cb) { if (this._[ri] && this._[ri].cells) { Object.entries(this._[ri].cells).forEach(([ci, cell]) => { cb(ci, cell); }); } } setData(d) { if (d.len) { this.len = d.len; delete d.len; } this._ = d; } getData() { const { len } = this; return Object.assign({ len }, this._); } } export default {}; export { Rows, };