cell-matrix.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. const _ = require('./under-dash');
  2. const colCache = require('./col-cache');
  3. class CellMatrix {
  4. constructor(template) {
  5. this.template = template;
  6. this.sheets = {};
  7. }
  8. addCell(addressStr) {
  9. this.addCellEx(colCache.decodeEx(addressStr));
  10. }
  11. getCell(addressStr) {
  12. return this.findCellEx(colCache.decodeEx(addressStr), true);
  13. }
  14. findCell(addressStr) {
  15. return this.findCellEx(colCache.decodeEx(addressStr), false);
  16. }
  17. findCellAt(sheetName, rowNumber, colNumber) {
  18. const sheet = this.sheets[sheetName];
  19. const row = sheet && sheet[rowNumber];
  20. return row && row[colNumber];
  21. }
  22. addCellEx(address) {
  23. if (address.top) {
  24. for (let row = address.top; row <= address.bottom; row++) {
  25. for (let col = address.left; col <= address.right; col++) {
  26. this.getCellAt(address.sheetName, row, col);
  27. }
  28. }
  29. } else {
  30. this.findCellEx(address, true);
  31. }
  32. }
  33. getCellEx(address) {
  34. return this.findCellEx(address, true);
  35. }
  36. findCellEx(address, create) {
  37. const sheet = this.findSheet(address, create);
  38. const row = this.findSheetRow(sheet, address, create);
  39. return this.findRowCell(row, address, create);
  40. }
  41. getCellAt(sheetName, rowNumber, colNumber) {
  42. const sheet = this.sheets[sheetName] || (this.sheets[sheetName] = []);
  43. const row = sheet[rowNumber] || (sheet[rowNumber] = []);
  44. const cell =
  45. row[colNumber] ||
  46. (row[colNumber] = {
  47. sheetName,
  48. address: colCache.n2l(colNumber) + rowNumber,
  49. row: rowNumber,
  50. col: colNumber,
  51. });
  52. return cell;
  53. }
  54. removeCellEx(address) {
  55. const sheet = this.findSheet(address);
  56. if (!sheet) {
  57. return;
  58. }
  59. const row = this.findSheetRow(sheet, address);
  60. if (!row) {
  61. return;
  62. }
  63. delete row[address.col];
  64. }
  65. forEachInSheet(sheetName, callback) {
  66. const sheet = this.sheets[sheetName];
  67. if (sheet) {
  68. sheet.forEach((row, rowNumber) => {
  69. if (row) {
  70. row.forEach((cell, colNumber) => {
  71. if (cell) {
  72. callback(cell, rowNumber, colNumber);
  73. }
  74. });
  75. }
  76. });
  77. }
  78. }
  79. forEach(callback) {
  80. _.each(this.sheets, (sheet, sheetName) => {
  81. this.forEachInSheet(sheetName, callback);
  82. });
  83. }
  84. map(callback) {
  85. const results = [];
  86. this.forEach(cell => {
  87. results.push(callback(cell));
  88. });
  89. return results;
  90. }
  91. findSheet(address, create) {
  92. const name = address.sheetName;
  93. if (this.sheets[name]) {
  94. return this.sheets[name];
  95. }
  96. if (create) {
  97. return (this.sheets[name] = []);
  98. }
  99. return undefined;
  100. }
  101. findSheetRow(sheet, address, create) {
  102. const {row} = address;
  103. if (sheet && sheet[row]) {
  104. return sheet[row];
  105. }
  106. if (create) {
  107. return (sheet[row] = []);
  108. }
  109. return undefined;
  110. }
  111. findRowCell(row, address, create) {
  112. const {col} = address;
  113. if (row && row[col]) {
  114. return row[col];
  115. }
  116. if (create) {
  117. return (row[col] = this.template
  118. ? Object.assign(address, JSON.parse(JSON.stringify(this.template)))
  119. : address);
  120. }
  121. return undefined;
  122. }
  123. spliceRows(sheetName, start, numDelete, numInsert) {
  124. const sheet = this.sheets[sheetName];
  125. if (sheet) {
  126. const inserts = [];
  127. for (let i = 0; i < numInsert; i++) {
  128. inserts.push([]);
  129. }
  130. sheet.splice(start, numDelete, ...inserts);
  131. }
  132. }
  133. spliceColumns(sheetName, start, numDelete, numInsert) {
  134. const sheet = this.sheets[sheetName];
  135. if (sheet) {
  136. const inserts = [];
  137. for (let i = 0; i < numInsert; i++) {
  138. inserts.push(null);
  139. }
  140. _.each(sheet, row => {
  141. row.splice(start, numDelete, ...inserts);
  142. });
  143. }
  144. }
  145. }
  146. module.exports = CellMatrix;