UNPKG

read-excel-file

Version:

Read small to medium `*.xlsx` files in a browser or Node.js. Parse to JSON with a strict schema.

121 lines (115 loc) 5.35 kB
function _createForOfIteratorHelperLoose(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (it) return (it = it.call(o)).next.bind(it); if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; return function () { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } // XLSX does have "d" type for dates, but it's not commonly used. // Instead, it prefers using "n" type for storing dates as timestamps. // // Whether a numeric value is a number or a date timestamp, it sometimes could be // detected by looking at the value "format" and seeing if it's a date-specific one. // https://github.com/catamphetamine/read-excel-file/issues/3#issuecomment-395770777 // // The list of generic numeric value "formats": // https://xlsxwriter.readthedocs.io/format.html#format-set-num-format // export default function isDateTimestamp(styleId, styles, options) { if (styleId) { var style = styles[styleId]; if (!style) { throw new Error("Cell style not found: ".concat(styleId)); } if (!style.numberFormat) { return false; } if ( // Whether it's a "number format" that's conventionally used for storing date timestamps. BUILT_IN_DATE_NUMBER_FORMAT_IDS.indexOf(Number(style.numberFormat.id)) >= 0 || // Whether it's a "number format" that uses a "formatting template" // that the developer is certain is a date formatting template. options.dateFormat && style.numberFormat.template === options.dateFormat || // Whether the "smart formatting template" feature is not disabled // and it has detected that it's a date formatting template by looking at it. options.smartDateParser !== false && style.numberFormat.template && isDateTemplate(style.numberFormat.template)) { return true; } } } // https://hexdocs.pm/xlsxir/number_styles.html var BUILT_IN_DATE_NUMBER_FORMAT_IDS = [14, 15, 16, 17, 18, 19, 20, 21, 22, 27, 30, 36, 45, 46, 47, 50, 57]; // On some date formats, there's an "[$-414]" prefix. // I don't have any idea what that is. // // https://stackoverflow.com/questions/4730152/what-indicates-an-office-open-xml-cell-contains-a-date-time-value // // Examples: // // * 27 (built-in format) "[$-404]e/m/d" // * 164 (custom format) "[$-414]mmmm\ yyyy;@" // var DATE_FORMAT_WEIRD_PREFIX = /^\[\$-414\]/; // On some date formats, there's an ";@" postfix. // I don't have any idea what that is. // Examples: // // * 164 (custom format) "m/d/yyyy;@" // * 164 (custom format) "[$-414]mmmm\ yyyy;@" // var DATE_FORMAT_WEIRD_POSTFIX = /;@$/; function isDateTemplate(template) { // Date format tokens could be in upper case or in lower case. // There seems to be no single standard. // So lowercase the template first. template = template.toLowerCase(); // On some date formats, there's an "[$-414]" prefix. // I don't have any idea what that is. Trim it. template = template.replace(DATE_FORMAT_WEIRD_PREFIX, ''); // On some date formats, there's an ";@" postfix. // I don't have any idea what that is. Trim it. template = template.replace(DATE_FORMAT_WEIRD_POSTFIX, ''); var tokens = template.split(/\W+/); for (var _iterator = _createForOfIteratorHelperLoose(tokens), _step; !(_step = _iterator()).done;) { var token = _step.value; if (DATE_TEMPLATE_TOKENS.indexOf(token) < 0) { return false; } } return true; } // These tokens could be in upper case or in lower case. // There seems to be no single standard, so using lower case. var DATE_TEMPLATE_TOKENS = [ // Seconds (min two digits). Example: "05". 'ss', // Minutes (min two digits). Example: "05". Could also be "Months". Weird. 'mm', // Hours. Example: "1". 'h', // Hours (min two digits). Example: "01". 'hh', // "AM" part of "AM/PM". Lowercased just in case. 'am', // "PM" part of "AM/PM". Lowercased just in case. 'pm', // Day. Example: "1" 'd', // Day (min two digits). Example: "01" 'dd', // Month (numeric). Example: "1". 'm', // Month (numeric, min two digits). Example: "01". Could also be "Minutes". Weird. 'mm', // Month (shortened month name). Example: "Jan". 'mmm', // Month (full month name). Example: "January". 'mmmm', // Two-digit year. Example: "20". 'yy', // Full year. Example: "2020". 'yyyy', // I don't have any idea what "e" means. // It's used in "built-in" XLSX formats: // * 27 '[$-404]e/m/d'; // * 36 '[$-404]e/m/d'; // * 50 '[$-404]e/m/d'; // * 57 '[$-404]e/m/d'; 'e']; //# sourceMappingURL=isDateTimestamp.js.map