defined-name-xform.js 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. const BaseXform = require('../base-xform');
  2. const colCache = require('../../../utils/col-cache');
  3. class DefinedNamesXform extends BaseXform {
  4. render(xmlStream, model) {
  5. // <definedNames>
  6. // <definedName name="name">name.ranges.join(',')</definedName>
  7. // <definedName name="_xlnm.Print_Area" localSheetId="0">name.ranges.join(',')</definedName>
  8. // </definedNames>
  9. xmlStream.openNode('definedName', {
  10. name: model.name,
  11. localSheetId: model.localSheetId,
  12. });
  13. xmlStream.writeText(model.ranges.join(','));
  14. xmlStream.closeNode();
  15. }
  16. parseOpen(node) {
  17. switch (node.name) {
  18. case 'definedName':
  19. this._parsedName = node.attributes.name;
  20. this._parsedLocalSheetId = node.attributes.localSheetId;
  21. this._parsedText = [];
  22. return true;
  23. default:
  24. return false;
  25. }
  26. }
  27. parseText(text) {
  28. this._parsedText.push(text);
  29. }
  30. parseClose() {
  31. this.model = {
  32. name: this._parsedName,
  33. ranges: extractRanges(this._parsedText.join('')),
  34. };
  35. if (this._parsedLocalSheetId !== undefined) {
  36. this.model.localSheetId = parseInt(this._parsedLocalSheetId, 10);
  37. }
  38. return false;
  39. }
  40. }
  41. function isValidRange(range) {
  42. try {
  43. colCache.decodeEx(range);
  44. return true;
  45. } catch (err) {
  46. return false;
  47. }
  48. }
  49. function extractRanges(parsedText) {
  50. const ranges = [];
  51. let quotesOpened = false;
  52. let last = '';
  53. parsedText.split(',').forEach(item => {
  54. if (!item) {
  55. return;
  56. }
  57. const quotes = (item.match(/'/g) || []).length;
  58. if (!quotes) {
  59. if (quotesOpened) {
  60. last += `${item},`;
  61. } else if (isValidRange(item)) {
  62. ranges.push(item);
  63. }
  64. return;
  65. }
  66. const quotesEven = quotes % 2 === 0;
  67. if (!quotesOpened && quotesEven && isValidRange(item)) {
  68. ranges.push(item);
  69. } else if (quotesOpened && !quotesEven) {
  70. quotesOpened = false;
  71. if (isValidRange(last + item)) {
  72. ranges.push(last + item);
  73. }
  74. last = '';
  75. } else {
  76. quotesOpened = true;
  77. last += `${item},`;
  78. }
  79. });
  80. return ranges;
  81. }
  82. module.exports = DefinedNamesXform;