UNPKG

read-excel-file

Version:

Read `.xlsx` files in a web browser or in Node.js

130 lines 7.73 kB
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } var _excluded = ["xfId"]; function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); } function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } /** * Parses `.xlsx` file styles. * http://officeopenxml.com/SSstyles.php * Returns an array of cell styles. * A cell style index is the cell style ID. * @param {string} content * @param {function} parseXml — SAX XML parser. * @returns {object} styles */ export default function parseStyles(content, parseXml) { // https://social.msdn.microsoft.com/Forums/sqlserver/en-US/708978af-b598-45c4-a598-d3518a5a09f0/howwhen-is-cellstylexfs-vs-cellxfs-applied-to-a-cell?forum=os_binaryfile // https://www.office-forums.com/threads/cellxfs-cellstylexfs.2163519/ var state = createInitialState(); return parseXml(content, state, onOpenTag, onCloseTag, null).then(function () { return getResultFromState(state); }); function createInitialState() { return { numberFormats: [], baseStyles: [], // The first `164` elements of the `styles` array are going to be `undefined` // because those represent the built-in "default" styles in `.xlsx` specification. // These "default" styles have IDs from `0` to `163`, i.e. according to their index. styles: [], cellStyleXfs: false, cellXfs: false }; } function getResultFromState(state) { return state.styles.map(function (style) { if (style.xfId) { var xfId = style.xfId, styleProperties = _objectWithoutProperties(style, _excluded); return _objectSpread(_objectSpread({}, state.baseStyles[xfId]), styleProperties); } else { return style; } }); } function onOpenTag(tagName, attributes, state) { if (tagName === 'numFmt') { // `<numFmts/>` element contains `<numFmt/>` elements. // `<numFmt/>` defines a "number format" template. // The value of `numFmtId` attribute is a (numeric) ID of this "number format". var numFmtId = Number(attributes.numFmtId); var numberFormat = { id: numFmtId }; // // If (and only if) `numFmtId` is >= 164, it is supposed to specify a `formatCode` (a template). // // For some reason, Microsoft Excel 2007 doesn't allow to redefine `numFmtId="99"` // but at the same time does allow redefining `numFmtId="100"`. // // Google AI says: // // "Standard built-in Excel formats use IDs from 0 to 49 (and some regional ones up to 81). // IDs 164 and above are officially reserved for custom formats, but third-party spreadsheet // generators or older templates frequently assign custom IDs starting at 100 (or lower)" // // Because of such "non-strict" behavior of Microsoft Excel 2007 regarding overwriting // number formats with ID >= 100, this package mimicks such "non-strict" approach. // if (numFmtId >= 100) { numberFormat.template = attributes.formatCode; } state.numberFormats[numFmtId] = numberFormat; } else if (tagName === 'cellStyleXfs') { // `<cellStyleXfs/>` contains "base styles" that could be extended by `<cellXfs/>`. // These styles don't apply to individual cells directly. They can only be extended. state.cellStyleXfs = true; } else if (tagName === 'cellXfs') { // `<cellXfs/>` contains individual cell styles. They can extend "base styles". state.cellXfs = true; } else if (tagName === 'xf') { if (state.cellStyleXfs) { // The index of a `<xf/>` element is by definition its numeric ID. // Therefore, even empty `style` elements still must be put into the array. state.baseStyles.push(parseCellStyle(attributes)); } else if (state.cellXfs) { var style = parseCellStyle(attributes, state.numberFormats); // A style might extend a "base style" by its numeric ID. if (attributes.xfId) { style.xfId = Number(attributes.xfId); } // The index of a `<xf/>` element is by definition its numeric ID. // Therefore, even empty `style` elements still must be put into the array. state.styles.push(style); } } } function onCloseTag(tagName, state) { if (tagName === 'cellStyleXfs') { state.cellStyleXfs = false; } else if (tagName === 'cellXfs') { state.cellXfs = false; } } function parseCellStyle(attributes, numberFormats) { var style = {}; // `numFmtId` in `<cellStyleXfs/>` and `<cellXfs/>` is a numerical ID // referencing the cell's "number format". Values from `0` to `163` are built-in formats, // while values `164` and above are custom formats defined in the `<numFmts/>` element. if (attributes.numFmtId) { var numFmtId = Number(attributes.numFmtId); // Built-in number formats don't have a `<numFmt/>` element in `styles.xml`. // https://hexdocs.pm/xlsxir/number_styles.html if (numberFormats && numberFormats[numFmtId]) { // Non-built-in number format. style.numberFormat = numberFormats[numFmtId]; } else { // Built-in number format. style.numberFormat = { id: numFmtId }; } } return style; } } //# sourceMappingURL=parseStyles.js.map