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
			| 
											2 years ago
										 | 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; |