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;
 |