UNPKG

@atomictech/xlsx-write-stream

Version:

Stream huge amount of data into an XLSX generated file stream with minimum memory footprint.

159 lines (140 loc) 15.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = exports.defaultStyleDefinitions = exports.getBestNumberTypeStyleKey = exports.TypeStyleKey = void 0; const generateNumFmt = styleDefinition => ` <numFmt numFmtId="${styleDefinition.numFmtId}" formatCode="${styleDefinition.formatCode}" />`; const generateNumFmts = styleDefinitions => { const customFormats = Object.entries(styleDefinitions).reduce((result, [key, value]) => { if (value.formatCode) result[key] = value; return result; }, {}); return ` <numFmts count="${Object.keys(customFormats).length}">\n${Object.values(customFormats).map(generateNumFmt).join('\n')}\n </numFmts>`; }; const generateXf = styleDefinition => ` <xf numFmtId="${styleDefinition.numFmtId}" fontId="0" fillId="0" borderId="0" xfId="0"/>`; const generateCellXfs = styleDefinitions => ` <cellXfs count="${Object.keys(styleDefinitions).length}">\n${Object.values(styleDefinitions).map(generateXf).join('\n')}\n </cellXfs>`; const TypeStyleKey = { NUMBER: 'default', INT: 'int', FLOAT: 'float', BIG_INT: 'bigInt', BIG_FLOAT: 'bigFloat', EXP_NUMBER: 'expNumber', TEXT: 'text', DATE: 'date', DATETIME: 'datetime' }; exports.TypeStyleKey = TypeStyleKey; const getBestNumberTypeStyleKey = number => { const positiveNumber = Math.abs(number); if (positiveNumber.toString().length >= 11) { return TypeStyleKey.EXP_NUMBER; } if (positiveNumber % 1 === 0) { return positiveNumber >= 1000 ? TypeStyleKey.BIG_INT : TypeStyleKey.INT; } return positiveNumber >= 1000 ? TypeStyleKey.BIG_FLOAT : TypeStyleKey.FLOAT; }; exports.getBestNumberTypeStyleKey = getBestNumberTypeStyleKey; const defaultStyleDefinitions = { default: { numFmtId: 0 }, int: { numFmtId: 1 }, float: { numFmtId: 2 }, bigInt: { numFmtId: 3 }, bigFloat: { numFmtId: 4 }, expNumber: { numFmtId: 11 }, text: { numFmtId: 49 }, date: { formatCode: 'yyyy-mm-dd' }, datetime: { formatCode: 'yyyy-mm-dd hh:mm:ss' } }; exports.defaultStyleDefinitions = defaultStyleDefinitions; const minNumFmtId = 200; const patchDefinitions = styleDefinitions => { let styleIndex = 0; let nextNumFmtId = minNumFmtId; for (const [, styleDefinition] of Object.entries(styleDefinitions)) { styleDefinition.index = styleIndex++; if (!styleDefinition.numFmtId) { if (!styleDefinition.formatCode) continue; styleDefinition.numFmtId = nextNumFmtId++; } } }; class Styles { constructor(styleDefinitions = {}) { this.typeStyleDefinitions = Object.assign({}, defaultStyleDefinitions, styleDefinitions); patchDefinitions(this.typeStyleDefinitions); } getStyleId(typeStyle) { return this.typeStyleDefinitions[typeStyle].index; } render() { return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x14ac" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac"> ${generateNumFmts(this.typeStyleDefinitions)} <fonts count="1" x14ac:knownFonts="1"> <font> <sz val="11"/> <color theme="1"/> <name val="Calibri"/> <family val="2"/> <scheme val="minor"/> </font> </fonts> <fills count="2"> <fill> <patternFill patternType="none"/> </fill> <fill> <patternFill patternType="gray125"/> </fill> </fills> <borders count="1"> <border> <left/> <right/> <top/> <bottom/> <diagonal/> </border> </borders> <cellStyleXfs count="1"> <xf numFmtId="0" fontId="0" fillId="0" borderId="0"/> </cellStyleXfs> ${generateCellXfs(this.typeStyleDefinitions)} <cellStyles count="1"> <cellStyle name="Normal" xfId="0" builtinId="0"/> </cellStyles> <dxfs count="0"/> <tableStyles count="0" defaultTableStyle="TableStyleMedium2" defaultPivotStyle="PivotStyleLight16"/> <extLst> <ext uri="{EB79DEF2-80B8-43e5-95BD-54CBDDF9020C}" xmlns:x14="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"> <x14:slicerStyles defaultSlicerStyle="SlicerStyleLight1"/> </ext> </extLst> </styleSheet>`; } } exports.default = Styles; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90ZW1wbGF0ZXMvc3R5bGVzLmpzIl0sIm5hbWVzIjpbImdlbmVyYXRlTnVtRm10Iiwic3R5bGVEZWZpbml0aW9uIiwibnVtRm10SWQiLCJmb3JtYXRDb2RlIiwiZ2VuZXJhdGVOdW1GbXRzIiwic3R5bGVEZWZpbml0aW9ucyIsImN1c3RvbUZvcm1hdHMiLCJPYmplY3QiLCJlbnRyaWVzIiwicmVkdWNlIiwicmVzdWx0Iiwia2V5IiwidmFsdWUiLCJrZXlzIiwibGVuZ3RoIiwidmFsdWVzIiwibWFwIiwiam9pbiIsImdlbmVyYXRlWGYiLCJnZW5lcmF0ZUNlbGxYZnMiLCJUeXBlU3R5bGVLZXkiLCJOVU1CRVIiLCJJTlQiLCJGTE9BVCIsIkJJR19JTlQiLCJCSUdfRkxPQVQiLCJFWFBfTlVNQkVSIiwiVEVYVCIsIkRBVEUiLCJEQVRFVElNRSIsImdldEJlc3ROdW1iZXJUeXBlU3R5bGVLZXkiLCJudW1iZXIiLCJwb3NpdGl2ZU51bWJlciIsIk1hdGgiLCJhYnMiLCJ0b1N0cmluZyIsImRlZmF1bHRTdHlsZURlZmluaXRpb25zIiwiZGVmYXVsdCIsImludCIsImZsb2F0IiwiYmlnSW50IiwiYmlnRmxvYXQiLCJleHBOdW1iZXIiLCJ0ZXh0IiwiZGF0ZSIsImRhdGV0aW1lIiwibWluTnVtRm10SWQiLCJwYXRjaERlZmluaXRpb25zIiwic3R5bGVJbmRleCIsIm5leHROdW1GbXRJZCIsImluZGV4IiwiU3R5bGVzIiwiY29uc3RydWN0b3IiLCJ0eXBlU3R5bGVEZWZpbml0aW9ucyIsImFzc2lnbiIsImdldFN0eWxlSWQiLCJ0eXBlU3R5bGUiLCJyZW5kZXIiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQSxNQUFNQSxjQUFjLEdBQUdDLGVBQWUsSUFBSyx5QkFBd0JBLGVBQWUsQ0FBQ0MsUUFBUyxpQkFBZ0JELGVBQWUsQ0FBQ0UsVUFBVyxNQUF2STs7QUFDQSxNQUFNQyxlQUFlLEdBQUdDLGdCQUFnQixJQUFJO0FBQzFDLFFBQU1DLGFBQWEsR0FB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Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUVsQyxlQUFlLENBQUMsS0FBS2tDLG9CQUFOLENBQTRCO0FBQzdDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQTlDSTtBQStDRDs7QUExRHlCIiwic291cmNlc0NvbnRlbnQiOlsiY29uc3QgZ2VuZXJhdGVOdW1GbXQgPSBzdHlsZURlZmluaXRpb24gPT4gYCAgICA8bnVtRm10IG51bUZtdElkPVwiJHtzdHlsZURlZmluaXRpb24ubnVtRm10SWR9XCIgZm9ybWF0Q29kZT1cIiR7c3R5bGVEZWZpbml0aW9uLmZvcm1hdENvZGV9XCIgLz5gO1xuY29uc3QgZ2VuZXJhdGVOdW1GbXRzID0gc3R5bGVEZWZpbml0aW9ucyA9PiB7XG4gIGNvbnN0IGN1c3RvbUZvcm1hdHMgPSBPYmplY3QuZW50cmllcyhzdHlsZURlZmluaXRpb25zKS5yZWR1Y2UoKHJlc3VsdCwgW2tleSwgdmFsdWVdKSA9PiB7XG4gICAgaWYgKHZhbHVlLmZvcm1hdENvZGUpIHJlc3VsdFtrZXldID0gdmFsdWU7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSwge30pO1xuICByZXR1cm4gYCAgPG51bUZtdHMgY291bnQ9XCIke09iamVjdC5rZXlzKGN1c3RvbUZvcm1hdHMpLmxlbmd0aH1cIj5cXG4ke09iamVjdC52YWx1ZXMoY3VzdG9tRm9ybWF0cylcbiAgICAubWFwKGdlbmVyYXRlTnVtRm10KVxuICAgIC5qb2luKCdcXG4nKX1cXG4gIDwvbnVtRm10cz5gO1xufTtcblxuY29uc3QgZ2VuZXJhdGVYZiA9IHN0eWxlRGVmaW5pdGlvbiA9PiBgICAgIDx4ZiBudW1GbXRJZD1cIiR7c3R5bGVEZWZpbml0aW9uLm51bUZtdElkfVwiIGZvbnRJZD1cIjBcIiBmaWxsSWQ9XCIwXCIgYm9yZGVySWQ9XCIwXCIgeGZJZD1cIjBcIi8+YDtcbmNvbnN0IGdlbmVyYXRlQ2VsbFhmcyA9IHN0eWxlRGVmaW5pdGlvbnMgPT5cbiAgYCAgPGNlbGxYZnMgY291bnQ9XCIke09iamVjdC5rZXlzKHN0eWxlRGVmaW5pdGlvbnMpLmxlbmd0aH1cIj5cXG4ke09iamVjdC52YWx1ZXMoc3R5bGVEZWZpbml0aW9ucylcbiAgICAubWFwKGdlbmVyYXRlWGYpXG4gICAgLmpvaW4oJ1xcbicpfVxcbiAgPC9jZWxsWGZzPmA7XG5cbmV4cG9ydCBjb25zdCBUeXBlU3R5bGVLZXkgPSB7XG4gIE5VTUJFUjogJ2RlZmF1bHQnLFxuICBJTlQ6ICdpbnQnLFxuICBGTE9BVDogJ2Zsb2F0JyxcbiAgQklHX0lOVDogJ2JpZ0ludCcsXG4gIEJJR19GTE9BVDogJ2JpZ0Zsb2F0JyxcbiAgRVhQX05VTUJFUjogJ2V4cE51bWJlcicsXG4gIFRFWFQ6ICd0ZXh0JyxcbiAgREFURTogJ2RhdGUnLFxuICBEQVRFVElNRTogJ2RhdGV0aW1lJ1xufTtcblxuZXhwb3J0IGNvbnN0IGdldEJlc3ROdW1iZXJUeXBlU3R5bGVLZXkgPSBudW1iZXIgPT4ge1xuICBjb25zdCBwb3NpdGl2ZU51bWJlciA9IE1hdGguYWJzKG51bWJlcik7XG4gIGlmIChwb3NpdGl2ZU51bWJlci50b1N0cmluZygpLmxlbmd0aCA+PSAxMSkge1xuICAgIHJldHVybiBUeXBlU3R5bGVLZXkuRVhQX05VTUJFUjtcbiAgfVxuICBpZiAocG9zaXRpdmVOdW1iZXIgJSAxID09PSAwKSB7XG4gICAgcmV0dXJuIHBvc2l0aXZlTnVtYmVyID49IDEwMDAgPyBUeXBlU3R5bGVLZXkuQklHX0lOVCA6IFR5cGVTdHlsZUtleS5JTlQ7XG4gIH1cbiAgcmV0dXJuIHBvc2l0aXZlTnVtYmVyID49IDEwMDAgPyBUeXBlU3R5bGVLZXkuQklHX0ZMT0FUIDogVHlwZVN0eWxlS2V5LkZMT0FUO1xufTtcblxuZXhwb3J0IGNvbnN0IGRlZmF1bHRTdHlsZURlZmluaXRpb25zID0ge1xuICBkZWZhdWx0OiB7IG51bUZtdElkOiAwIH0sXG4gIGludDogeyBudW1GbXRJZDogMSB9LFxuICBmbG9hdDogeyBudW1GbXRJZDogMiB9LFxuICBiaWdJbnQ6IHsgbnVtRm10SWQ6IDMgfSxcbiAgYmlnRmxvYXQ6IHsgbnVtRm10SWQ6IDQgfSxcbiAgZXhwTnVtYmVyOiB7IG51bUZtdElkOiAxMSB9LFxuICB0ZXh0OiB7IG51bUZtdElkOiA0OSB9LFxuICBkYXRlOiB7IGZvcm1hdENvZGU6ICd5eXl5LW1tLWRkJyB9LFxuICBkYXRldGltZTogeyBmb3JtYXRDb2RlOiAneXl5eS1tbS1kZCBoaDptbTpzcycgfVxufTtcblxuY29uc3QgbWluTnVtRm10SWQgPSAyMDA7XG5jb25zdCBwYXRjaERlZmluaXRpb25zID0gc3R5bGVEZWZpbml0aW9ucyA9PiB7XG4gIGxldCBzdHlsZUluZGV4ID0gMDtcbiAgbGV0IG5leHROdW1GbXRJZCA9IG1pbk51bUZtdElkO1xuXG4gIGZvciAoY29uc3QgWywgc3R5bGVEZWZpbml0aW9uXSBvZiBPYmplY3QuZW50cmllcyhzdHlsZURlZmluaXRpb25zKSkge1xuICAgIHN0eWxlRGVmaW5pdGlvbi5pbmRleCA9IHN0eWxlSW5kZXgrKztcblxuICAgIGlmICghc3R5bGVEZWZpbml0aW9uLm51bUZtdElkKSB7XG4gICAgICBpZiAoIXN0eWxlRGVmaW5pdGlvbi5mb3JtYXRDb2RlKSBjb250aW51ZTtcblxuICAgICAgc3R5bGVEZWZpbml0aW9uLm51bUZtdElkID0gbmV4dE51bUZtdElkKys7XG4gICAgfVxuICB9XG59O1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTdHlsZXMge1xuICBjb25zdHJ1Y3RvcihzdHlsZURlZmluaXRpb25zID0ge30pIHtcbiAgICB0aGlzLnR5cGVTdHlsZURlZmluaXRpb25zID0gT2JqZWN0LmFzc2lnbih7fSwgZGVmYXVsdFN0eWxlRGVmaW5pdGlvbnMsIHN0eWxlRGVmaW5pdGlvbnMpO1xuICAgIHBhdGNoRGVmaW5pdGlvbnModGhpcy50eXBlU3R5bGVEZWZpbml0aW9ucyk7XG4gIH1cblxuICBnZXRTdHlsZUlkKHR5cGVTdHlsZSkge1xuICAgIHJldHVybiB0aGlzLnR5cGVTdHlsZURlZmluaXRpb25zW3R5cGVTdHlsZV0uaW5kZXg7XG4gIH1cblxuICByZW5kZXIoKSB7XG4gICAgcmV0dXJuIGA8P3htbCB2ZXJzaW9uPVwiMS4wXCIgZW5jb2Rpbmc9XCJVVEYtOFwiIHN0YW5kYWxvbmU9XCJ5ZXNcIj8+XG48c3R5bGVTaGVldCB4bWxucz1cImh0dHA6Ly9zY2hlbWFzLm9wZW54bWxmb3JtYXRzLm9yZy9zcHJlYWRzaGVldG1sLzIwMDYvbWFpblwiXG4gIHhtbG5zOm1jPVwiaHR0cDovL3NjaGVtYXMub3BlbnhtbGZvcm1hdHMub3JnL21hcmt1cC1jb21wYXRpYmlsaXR5LzIwMDZcIiBtYzpJZ25vcmFibGU9XCJ4MTRhY1wiXG4gIHhtbG5zOngxNGFjPVwiaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS9vZmZpY2Uvc3ByZWFkc2hlZXRtbC8yMDA5LzkvYWNcIj5cbiR7Z2VuZXJhdGVOdW1GbXRzKHRoaXMudHlwZVN0eWxlRGVmaW5pdGlvbnMpfVxuICA8Zm9udHMgY291bnQ9XCIxXCIgeDE0YWM6a25vd25Gb250cz1cIjFcIj5cbiAgICA8Zm9udD5cbiAgICAgIDxzeiB2YWw9XCIxMVwiLz5cbiAgICAgIDxjb2xvciB0aGVtZT1cIjFcIi8+XG4gICAgICA8bmFtZSB2YWw9XCJDYWxpYnJpXCIvPlxuICAgICAgPGZhbWlseSB2YWw9XCIyXCIvPlxuICAgICAgPHNjaGVtZSB2YWw9XCJtaW5vclwiLz5cbiAgICA8L2ZvbnQ+XG4gIDwvZm9udHM+XG4gIDxmaWxscyBjb3VudD1cIjJcIj5cbiAgICA8ZmlsbD5cbiAgICAgIDxwYXR0ZXJuRmlsbCBwYXR0ZXJuVHlwZT1cIm5vbmVcIi8+XG4gICAgPC9maWxsPlxuICAgIDxmaWxsPlxuICAgICAgPHBhdHRlcm5GaWxsIHBhdHRlcm5UeXBlPVwiZ3JheTEyNVwiLz5cbiAgICA8L2ZpbGw+XG4gIDwvZmlsbHM+XG4gIDxib3JkZXJzIGNvdW50PVwiMVwiPlxuICAgIDxib3JkZXI+XG4gICAgICA8bGVmdC8+XG4gICAgICA8cmlnaHQvPlxuICAgICAgPHRvcC8+XG4gICAgICA8Ym90dG9tLz5cbiAgICAgIDxkaWFnb25hbC8+XG4gICAgPC9ib3JkZXI+XG4gIDwvYm9yZGVycz5cbiAgPGNlbGxTdHlsZVhmcyBjb3VudD1cIjFcIj5cbiAgICA8eGYgbnVtRm10SWQ9XCIwXCIgZm9udElkPVwiMFwiIGZpbGxJZD1cIjBcIiBib3JkZXJJZD1cIjBcIi8+XG4gIDwvY2VsbFN0eWxlWGZzPlxuJHtnZW5lcmF0ZUNlbGxYZnModGhpcy50eXBlU3R5bGVEZWZpbml0aW9ucyl9XG4gIDxjZWxsU3R5bGVzIGNvdW50PVwiMVwiPlxuICAgIDxjZWxsU3R5bGUgbmFtZT1cIk5vcm1hbFwiIHhmSWQ9XCIwXCIgYnVpbHRpbklkPVwiMFwiLz5cbiAgPC9jZWxsU3R5bGVzPlxuICA8ZHhmcyBjb3VudD1cIjBcIi8+XG4gIDx0YWJsZVN0eWxlcyBjb3VudD1cIjBcIiBkZWZhdWx0VGFibGVTdHlsZT1cIlRhYmxlU3R5bGVNZWRpdW0yXCIgZGVmYXVsdFBpdm90U3R5bGU9XCJQaXZvdFN0eWxlTGlnaHQxNlwiLz5cbiAgPGV4dExzdD5cbiAgICA8ZXh0IHVyaT1cIntFQjc5REVGMi04MEI4LTQzZTUtOTVCRC01NENCRERGOTAyMEN9XCJcbiAgICAgIHhtbG5zOngxND1cImh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vb2ZmaWNlL3NwcmVhZHNoZWV0bWwvMjAwOS85L21haW5cIj5cbiAgICAgIDx4MTQ6c2xpY2VyU3R5bGVzIGRlZmF1bHRTbGljZXJTdHlsZT1cIlNsaWNlclN0eWxlTGlnaHQxXCIvPlxuICAgIDwvZXh0PlxuICA8L2V4dExzdD5cbjwvc3R5bGVTaGVldD5gO1xuICB9XG59XG4iXX0=