read-excel-file 9.2.0 → 9.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitlab-ci.yml +1 -1
- package/CHANGELOG.md +5 -0
- package/README.md +153 -50
- package/bundle/read-excel-file.min.js +1 -1
- package/bundle/read-excel-file.min.js.map +1 -1
- package/bundle/read-excel-file.min.old.js +2 -0
- package/bundle/read-excel-file.min.old.js.map +1 -0
- package/commonjs/export/convertValuesFromUint8ArraysToStrings.js +3 -0
- package/commonjs/export/convertValuesFromUint8ArraysToStrings.js.map +1 -1
- package/commonjs/export/parseSheet.js +12 -9
- package/commonjs/export/parseSheet.js.map +1 -1
- package/commonjs/export/readSheetBrowser.js +6 -2
- package/commonjs/export/readSheetBrowser.js.map +1 -1
- package/commonjs/export/readSheetNode.js +6 -2
- package/commonjs/export/readSheetNode.js.map +1 -1
- package/commonjs/export/readSheetUniversal.js +14 -2
- package/commonjs/export/readSheetUniversal.js.map +1 -1
- package/commonjs/export/readSheetWebWorker.js +12 -2
- package/commonjs/export/readSheetWebWorker.js.map +1 -1
- package/commonjs/export/readXlsxFileBrowser.js +6 -2
- package/commonjs/export/readXlsxFileBrowser.js.map +1 -1
- package/commonjs/export/readXlsxFileNode.js +6 -2
- package/commonjs/export/readXlsxFileNode.js.map +1 -1
- package/commonjs/export/readXlsxFileUniversal.js +14 -2
- package/commonjs/export/readXlsxFileUniversal.js.map +1 -1
- package/commonjs/export/readXlsxFileWebWorker.js +12 -2
- package/commonjs/export/readXlsxFileWebWorker.js.map +1 -1
- package/commonjs/export/unpackXlsxFileBrowser.js +29 -6
- package/commonjs/export/unpackXlsxFileBrowser.js.map +1 -1
- package/commonjs/export/unpackXlsxFileNode.js +6 -0
- package/commonjs/export/unpackXlsxFileNode.js.map +1 -1
- package/commonjs/export/unpackXlsxFileUniversal.js +6 -0
- package/commonjs/export/unpackXlsxFileUniversal.js.map +1 -1
- package/commonjs/export/unpackXlsxFileWebWorker.js +14 -0
- package/commonjs/export/unpackXlsxFileWebWorker.js.map +1 -0
- package/commonjs/parseSheetData/parseSheetData.js +6 -6
- package/commonjs/parseSheetData/parseSheetData.js.map +1 -1
- package/commonjs/utility/checkpoint.js +33 -0
- package/commonjs/utility/checkpoint.js.map +1 -0
- package/commonjs/utility/isObject.js +15 -0
- package/commonjs/utility/isObject.js.map +1 -0
- package/commonjs/utility/isPromise.js +18 -0
- package/commonjs/utility/isPromise.js.map +1 -0
- package/commonjs/xlsx/convertCellsToData2dArray.js +0 -3
- package/commonjs/xlsx/convertCellsToData2dArray.js.map +1 -1
- package/commonjs/xlsx/isDateFormatStyle.js +2 -2
- package/commonjs/xlsx/isDateFormatStyle.js.map +1 -1
- package/commonjs/xlsx/parseCell.js +89 -24
- package/commonjs/xlsx/parseCell.js.map +1 -1
- package/{modules/xlsx/parseCellCoordinates.js → commonjs/xlsx/parseCellAddress.js} +18 -7
- package/commonjs/xlsx/parseCellAddress.js.map +1 -0
- package/commonjs/xlsx/parseCellValue.js +7 -23
- package/commonjs/xlsx/parseCellValue.js.map +1 -1
- package/commonjs/xlsx/parseFilePaths.js +31 -32
- package/commonjs/xlsx/parseFilePaths.js.map +1 -1
- package/commonjs/xlsx/parseNumber.js +20 -0
- package/commonjs/xlsx/parseNumber.js.map +1 -0
- package/commonjs/xlsx/parseSharedString.js +64 -0
- package/commonjs/xlsx/parseSharedString.js.map +1 -0
- package/commonjs/xlsx/parseSharedStrings.js +45 -5
- package/commonjs/xlsx/parseSharedStrings.js.map +1 -1
- package/commonjs/xlsx/parseSheet.js +93 -9
- package/commonjs/xlsx/parseSheet.js.map +1 -1
- package/commonjs/xlsx/parseSheetData.js +68 -0
- package/commonjs/xlsx/parseSheetData.js.map +1 -0
- package/commonjs/xlsx/parseSpreadsheetContents.js +244 -43
- package/commonjs/xlsx/parseSpreadsheetContents.js.map +1 -1
- package/commonjs/xlsx/parseSpreadsheetInfo.js +67 -36
- package/commonjs/xlsx/parseSpreadsheetInfo.js.map +1 -1
- package/commonjs/xlsx/parseStyles.js +89 -36
- package/commonjs/xlsx/parseStyles.js.map +1 -1
- package/commonjs/xml/dom.js +2 -1
- package/commonjs/xml/dom.js.map +1 -1
- package/commonjs/xml/parseXmlStream.js +14 -0
- package/commonjs/xml/parseXmlStream.js.map +1 -0
- package/commonjs/xml/parseXmlStream.sax.js +109 -0
- package/commonjs/xml/parseXmlStream.sax.js.map +1 -0
- package/commonjs/xml/parseXmlStream.saxen.code.js +953 -0
- package/commonjs/xml/parseXmlStream.saxen.code.js.map +1 -0
- package/commonjs/xml/parseXmlStream.saxen.js +85 -0
- package/commonjs/xml/parseXmlStream.saxen.js.map +1 -0
- package/commonjs/xml/xlsx.js +75 -40
- package/commonjs/xml/xlsx.js.map +1 -1
- package/commonjs/zip/unzipFromArrayBuffer.js +5 -14
- package/commonjs/zip/unzipFromArrayBuffer.js.map +1 -1
- package/commonjs/zip/unzipFromStream.fflate.js +154 -25
- package/commonjs/zip/unzipFromStream.fflate.js.map +1 -1
- package/commonjs/zip/unzipFromStream.js.map +1 -1
- package/commonjs/zip/unzipFromStream.unzipper.js +37 -26
- package/commonjs/zip/unzipFromStream.unzipper.js.map +1 -1
- package/modules/export/convertValuesFromUint8ArraysToStrings.js +2 -0
- package/modules/export/convertValuesFromUint8ArraysToStrings.js.map +1 -1
- package/modules/export/parseSheet.js +12 -9
- package/modules/export/parseSheet.js.map +1 -1
- package/modules/export/readSheetBrowser.js +5 -2
- package/modules/export/readSheetBrowser.js.map +1 -1
- package/modules/export/readSheetNode.js +5 -2
- package/modules/export/readSheetNode.js.map +1 -1
- package/modules/export/readSheetUniversal.js +14 -2
- package/modules/export/readSheetUniversal.js.map +1 -1
- package/modules/export/readSheetWebWorker.js +12 -2
- package/modules/export/readSheetWebWorker.js.map +1 -1
- package/modules/export/readXlsxFileBrowser.js +5 -2
- package/modules/export/readXlsxFileBrowser.js.map +1 -1
- package/modules/export/readXlsxFileNode.js +5 -2
- package/modules/export/readXlsxFileNode.js.map +1 -1
- package/modules/export/readXlsxFileUniversal.js +14 -2
- package/modules/export/readXlsxFileUniversal.js.map +1 -1
- package/modules/export/readXlsxFileWebWorker.js +12 -2
- package/modules/export/readXlsxFileWebWorker.js.map +1 -1
- package/modules/export/unpackXlsxFileBrowser.js +26 -6
- package/modules/export/unpackXlsxFileBrowser.js.map +1 -1
- package/modules/export/unpackXlsxFileNode.js +3 -0
- package/modules/export/unpackXlsxFileNode.js.map +1 -1
- package/modules/export/unpackXlsxFileUniversal.js +3 -0
- package/modules/export/unpackXlsxFileUniversal.js.map +1 -1
- package/modules/export/unpackXlsxFileWebWorker.js +6 -0
- package/modules/export/unpackXlsxFileWebWorker.js.map +1 -0
- package/modules/parseSheetData/parseSheetData.js +4 -4
- package/modules/parseSheetData/parseSheetData.js.map +1 -1
- package/modules/utility/checkpoint.js +25 -0
- package/modules/utility/checkpoint.js.map +1 -0
- package/modules/utility/isObject.js +9 -0
- package/modules/utility/isObject.js.map +1 -0
- package/modules/utility/isPromise.js +12 -0
- package/modules/utility/isPromise.js.map +1 -0
- package/modules/xlsx/convertCellsToData2dArray.js +0 -3
- package/modules/xlsx/convertCellsToData2dArray.js.map +1 -1
- package/modules/xlsx/isDateFormatStyle.js +2 -2
- package/modules/xlsx/isDateFormatStyle.js.map +1 -1
- package/modules/xlsx/parseCell.js +85 -24
- package/modules/xlsx/parseCell.js.map +1 -1
- package/{commonjs/xlsx/parseCellCoordinates.js → modules/xlsx/parseCellAddress.js} +12 -13
- package/modules/xlsx/parseCellAddress.js.map +1 -0
- package/modules/xlsx/parseCellValue.js +7 -23
- package/modules/xlsx/parseCellValue.js.map +1 -1
- package/modules/xlsx/parseFilePaths.js +31 -33
- package/modules/xlsx/parseFilePaths.js.map +1 -1
- package/modules/xlsx/parseNumber.js +14 -0
- package/modules/xlsx/parseNumber.js.map +1 -0
- package/modules/xlsx/parseSharedString.js +55 -0
- package/modules/xlsx/parseSharedString.js.map +1 -0
- package/modules/xlsx/parseSharedStrings.js +46 -5
- package/modules/xlsx/parseSharedStrings.js.map +1 -1
- package/modules/xlsx/parseSheet.js +91 -9
- package/modules/xlsx/parseSheet.js.map +1 -1
- package/modules/xlsx/parseSheetData.js +55 -0
- package/modules/xlsx/parseSheetData.js.map +1 -0
- package/modules/xlsx/parseSpreadsheetContents.js +242 -43
- package/modules/xlsx/parseSpreadsheetContents.js.map +1 -1
- package/modules/xlsx/parseSpreadsheetInfo.js +67 -37
- package/modules/xlsx/parseSpreadsheetInfo.js.map +1 -1
- package/modules/xlsx/parseStyles.js +88 -36
- package/modules/xlsx/parseStyles.js.map +1 -1
- package/modules/xml/dom.js +2 -1
- package/modules/xml/dom.js.map +1 -1
- package/modules/xml/parseXmlStream.js +18 -0
- package/modules/xml/parseXmlStream.js.map +1 -0
- package/modules/xml/parseXmlStream.sax.js +103 -0
- package/modules/xml/parseXmlStream.sax.js.map +1 -0
- package/modules/xml/parseXmlStream.saxen.code.js +947 -0
- package/modules/xml/parseXmlStream.saxen.code.js.map +1 -0
- package/modules/xml/parseXmlStream.saxen.js +79 -0
- package/modules/xml/parseXmlStream.saxen.js.map +1 -0
- package/modules/xml/xlsx.js +72 -36
- package/modules/xml/xlsx.js.map +1 -1
- package/modules/zip/unzipFromArrayBuffer.js +5 -14
- package/modules/zip/unzipFromArrayBuffer.js.map +1 -1
- package/modules/zip/unzipFromStream.fflate.js +157 -24
- package/modules/zip/unzipFromStream.fflate.js.map +1 -1
- package/modules/zip/unzipFromStream.js +56 -2
- package/modules/zip/unzipFromStream.js.map +1 -1
- package/modules/zip/unzipFromStream.unzipper.js +38 -26
- package/modules/zip/unzipFromStream.unzipper.js.map +1 -1
- package/package.json +4 -6
- package/commonjs/xlsx/parseCellCoordinates.js.map +0 -1
- package/commonjs/xlsx/parseCells.js +0 -34
- package/commonjs/xlsx/parseCells.js.map +0 -1
- package/commonjs/xlsx/parseSheetDimensions.js +0 -43
- package/commonjs/xlsx/parseSheetDimensions.js.map +0 -1
- package/commonjs/xml/xml.js +0 -13
- package/commonjs/xml/xml.js.map +0 -1
- package/commonjs/xml/xmlBrowser.js +0 -17
- package/commonjs/xml/xmlBrowser.js.map +0 -1
- package/commonjs/xml/xpath/xlsx-xpath.js +0 -92
- package/commonjs/xml/xpath/xlsx-xpath.js.map +0 -1
- package/commonjs/xml/xpath/xpathBrowser.js +0 -33
- package/commonjs/xml/xpath/xpathBrowser.js.map +0 -1
- package/commonjs/xml/xpath/xpathNode.js +0 -16
- package/commonjs/xml/xpath/xpathNode.js.map +0 -1
- package/modules/xlsx/parseCellCoordinates.js.map +0 -1
- package/modules/xlsx/parseCells.js +0 -27
- package/modules/xlsx/parseCells.js.map +0 -1
- package/modules/xlsx/parseSheetDimensions.js +0 -37
- package/modules/xlsx/parseSheetDimensions.js.map +0 -1
- package/modules/xml/xml.js +0 -7
- package/modules/xml/xml.js.map +0 -1
- package/modules/xml/xmlBrowser.js +0 -11
- package/modules/xml/xmlBrowser.js.map +0 -1
- package/modules/xml/xpath/xlsx-xpath.js +0 -73
- package/modules/xml/xpath/xlsx-xpath.js.map +0 -1
- package/modules/xml/xpath/xpathBrowser.js +0 -27
- package/modules/xml/xpath/xpathBrowser.js.map +0 -1
- package/modules/xml/xpath/xpathNode.js +0 -9
- package/modules/xml/xpath/xpathNode.js.map +0 -1
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import parseCell, { createInitialStateInCell, onOpenTagInCell, onCloseTagInCell, onTextInCell } from './parseCell.js';
|
|
2
|
+
export default function parseSheetData(state, sharedStrings, styles, epoch1904, options) {
|
|
3
|
+
return state.cells.map(function (_ref) {
|
|
4
|
+
var attributes = _ref.attributes,
|
|
5
|
+
value = _ref.value,
|
|
6
|
+
inlineString = _ref.inlineString;
|
|
7
|
+
return parseCell(attributes, value, inlineString, sharedStrings, styles, epoch1904, options);
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
export function createInitialStateInSheetData() {
|
|
11
|
+
return {
|
|
12
|
+
c: undefined,
|
|
13
|
+
cells: []
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export function onOpenTagInSheetData(tagName, attributes, state) {
|
|
17
|
+
if (tagName === 'c') {
|
|
18
|
+
state.c = createInitialStateInCell();
|
|
19
|
+
state.c.attributes = attributes;
|
|
20
|
+
} else if (state.c) {
|
|
21
|
+
onOpenTagInCell(tagName, attributes, state.c);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export function onCloseTagInSheetData(tagName, state) {
|
|
25
|
+
if (tagName === 'c') {
|
|
26
|
+
state.cells.push({
|
|
27
|
+
attributes: state.c.attributes,
|
|
28
|
+
value: state.c.value,
|
|
29
|
+
inlineString: state.c.inlineString
|
|
30
|
+
});
|
|
31
|
+
state.c = undefined;
|
|
32
|
+
} else if (state.c) {
|
|
33
|
+
onCloseTagInCell(tagName, state.c);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export function onTextInSheetData(text, state) {
|
|
37
|
+
if (state.c) {
|
|
38
|
+
onTextInCell(text, state.c);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Here, it could also parse "merged cells" and then return them in some special way.
|
|
43
|
+
// But then it's not clear what should be the way to return such merged cells.
|
|
44
|
+
// I.e. should it just return it as a duplicate value in each one of the merged cells?
|
|
45
|
+
// Or should it keep the current behavior of only returning the value of the top-most left-most cell
|
|
46
|
+
// and then just return `null` for the rest of the cells in a "merged cells" group?
|
|
47
|
+
// Perhaps the latter (current) approach is the most sensible one, so there's no need
|
|
48
|
+
// to change anything.
|
|
49
|
+
//
|
|
50
|
+
// const mergedCells = getMergedCellCoordinates(sheetDocument)
|
|
51
|
+
// for (const mergedCell of mergedCells) {
|
|
52
|
+
// const [from, to] = mergedCell.split(':').map(parseCellAddress)
|
|
53
|
+
// console.log('Merged Cell.', 'From:', from, 'To:', to)
|
|
54
|
+
// }
|
|
55
|
+
//# sourceMappingURL=parseSheetData.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseSheetData.js","names":["parseCell","createInitialStateInCell","onOpenTagInCell","onCloseTagInCell","onTextInCell","parseSheetData","state","sharedStrings","styles","epoch1904","options","cells","map","_ref","attributes","value","inlineString","createInitialStateInSheetData","c","undefined","onOpenTagInSheetData","tagName","onCloseTagInSheetData","push","onTextInSheetData","text"],"sources":["../../source/xlsx/parseSheetData.js"],"sourcesContent":["import parseCell, {\r\n createInitialStateInCell,\r\n onOpenTagInCell,\r\n onCloseTagInCell,\r\n onTextInCell\r\n} from './parseCell.js'\r\n\r\nexport default function parseSheetData(state, sharedStrings, styles, epoch1904, options) {\r\n return state.cells.map(({ attributes, value, inlineString }) => {\r\n return parseCell(\r\n attributes,\r\n value,\r\n inlineString,\r\n sharedStrings,\r\n styles,\r\n epoch1904,\r\n options\r\n )\r\n })\r\n}\r\n\r\nexport function createInitialStateInSheetData() {\r\n return {\r\n c: undefined,\r\n cells: []\r\n }\r\n}\r\n\r\nexport function onOpenTagInSheetData(tagName, attributes, state) {\r\n if (tagName === 'c') {\r\n state.c = createInitialStateInCell()\r\n state.c.attributes = attributes\r\n } else if (state.c) {\r\n onOpenTagInCell(tagName, attributes, state.c)\r\n }\r\n}\r\n\r\nexport function onCloseTagInSheetData(tagName, state) {\r\n if (tagName === 'c') {\r\n state.cells.push({\r\n attributes: state.c.attributes,\r\n value: state.c.value,\r\n inlineString: state.c.inlineString\r\n })\r\n state.c = undefined\r\n } else if (state.c) {\r\n onCloseTagInCell(tagName, state.c)\r\n }\r\n}\r\n\r\nexport function onTextInSheetData(text, state) {\r\n if (state.c) {\r\n onTextInCell(text, state.c)\r\n }\r\n}\r\n\r\n// Here, it could also parse \"merged cells\" and then return them in some special way.\r\n// But then it's not clear what should be the way to return such merged cells.\r\n// I.e. should it just return it as a duplicate value in each one of the merged cells?\r\n// Or should it keep the current behavior of only returning the value of the top-most left-most cell\r\n// and then just return `null` for the rest of the cells in a \"merged cells\" group?\r\n// Perhaps the latter (current) approach is the most sensible one, so there's no need\r\n// to change anything.\r\n//\r\n// const mergedCells = getMergedCellCoordinates(sheetDocument)\r\n// for (const mergedCell of mergedCells) {\r\n// const [from, to] = mergedCell.split(':').map(parseCellAddress)\r\n// console.log('Merged Cell.', 'From:', from, 'To:', to)\r\n// }"],"mappings":"AAAA,OAAOA,SAAS,IACdC,wBAAwB,EACxBC,eAAe,EACfC,gBAAgB,EAChBC,YAAY,QACP,gBAAgB;AAEvB,eAAe,SAASC,cAAcA,CAACC,KAAK,EAAEC,aAAa,EAAEC,MAAM,EAAEC,SAAS,EAAEC,OAAO,EAAE;EACvF,OAAOJ,KAAK,CAACK,KAAK,CAACC,GAAG,CAAC,UAAAC,IAAA,EAAyC;IAAA,IAAtCC,UAAU,GAAAD,IAAA,CAAVC,UAAU;MAAEC,KAAK,GAAAF,IAAA,CAALE,KAAK;MAAEC,YAAY,GAAAH,IAAA,CAAZG,YAAY;IACvD,OAAOhB,SAAS,CACdc,UAAU,EACVC,KAAK,EACLC,YAAY,EACZT,aAAa,EACbC,MAAM,EACNC,SAAS,EACTC,OACF,CAAC;EACH,CAAC,CAAC;AACJ;AAEA,OAAO,SAASO,6BAA6BA,CAAA,EAAG;EAC9C,OAAO;IACLC,CAAC,EAAEC,SAAS;IACZR,KAAK,EAAE;EACT,CAAC;AACH;AAEA,OAAO,SAASS,oBAAoBA,CAACC,OAAO,EAAEP,UAAU,EAAER,KAAK,EAAE;EAC/D,IAAIe,OAAO,KAAK,GAAG,EAAE;IACnBf,KAAK,CAACY,CAAC,GAAGjB,wBAAwB,CAAC,CAAC;IACpCK,KAAK,CAACY,CAAC,CAACJ,UAAU,GAAGA,UAAU;EACjC,CAAC,MAAM,IAAIR,KAAK,CAACY,CAAC,EAAE;IAClBhB,eAAe,CAACmB,OAAO,EAAEP,UAAU,EAAER,KAAK,CAACY,CAAC,CAAC;EAC/C;AACF;AAEA,OAAO,SAASI,qBAAqBA,CAACD,OAAO,EAAEf,KAAK,EAAE;EACpD,IAAIe,OAAO,KAAK,GAAG,EAAE;IACnBf,KAAK,CAACK,KAAK,CAACY,IAAI,CAAC;MACfT,UAAU,EAAER,KAAK,CAACY,CAAC,CAACJ,UAAU;MAC9BC,KAAK,EAAET,KAAK,CAACY,CAAC,CAACH,KAAK;MACpBC,YAAY,EAAEV,KAAK,CAACY,CAAC,CAACF;IACxB,CAAC,CAAC;IACFV,KAAK,CAACY,CAAC,GAAGC,SAAS;EACrB,CAAC,MAAM,IAAIb,KAAK,CAACY,CAAC,EAAE;IAClBf,gBAAgB,CAACkB,OAAO,EAAEf,KAAK,CAACY,CAAC,CAAC;EACpC;AACF;AAEA,OAAO,SAASM,iBAAiBA,CAACC,IAAI,EAAEnB,KAAK,EAAE;EAC7C,IAAIA,KAAK,CAACY,CAAC,EAAE;IACXd,YAAY,CAACqB,IAAI,EAAEnB,KAAK,CAACY,CAAC,CAAC;EAC7B;AACF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA"}
|
|
@@ -1,66 +1,162 @@
|
|
|
1
|
+
var _excluded = ["parseNumber"];
|
|
2
|
+
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); }
|
|
1
3
|
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."); }
|
|
2
4
|
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); }
|
|
3
5
|
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; }
|
|
6
|
+
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; }
|
|
7
|
+
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; }
|
|
8
|
+
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; }
|
|
9
|
+
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; }
|
|
10
|
+
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; }
|
|
11
|
+
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
|
|
12
|
+
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); }
|
|
4
13
|
import parseSpreadsheetInfo from './parseSpreadsheetInfo.js';
|
|
5
14
|
import parseFilePaths from './parseFilePaths.js';
|
|
6
15
|
import parseStyles from './parseStyles.js';
|
|
7
16
|
import parseSharedStrings from './parseSharedStrings.js';
|
|
8
17
|
import parseSheet from './parseSheet.js';
|
|
18
|
+
import parseNumberDefault from './parseNumber.js';
|
|
19
|
+
import checkpoint, { latestCheckpointTimestamp } from '../utility/checkpoint.js';
|
|
20
|
+
import isPromise from '../utility/isPromise.js';
|
|
9
21
|
|
|
10
22
|
// For an introduction in reading `.xlsx` files see "The minimum viable XLSX reader":
|
|
11
23
|
// https://www.brendanlong.com/the-minimum-viable-xlsx-reader.html
|
|
12
24
|
|
|
13
25
|
/**
|
|
14
26
|
* Reads data from an `.xlsx` file.
|
|
27
|
+
* @param {function} parseXmlStream — SAX XML parser.
|
|
15
28
|
* @param {Record<string,string>} contents - A map of `.xml` files inside the `.xlsx` file (which itself is just a zipped directory).
|
|
16
|
-
* @param {object} xml — An object having a single property — `createDocument(string)` function.
|
|
17
29
|
* @param {object} [options]
|
|
18
|
-
* @return {Sheet[]}
|
|
30
|
+
* @return {Promise<Sheet[]>}
|
|
19
31
|
*/
|
|
20
|
-
|
|
32
|
+
function parseSpreadsheetContents(parseXmlStream, contents) {
|
|
21
33
|
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
};
|
|
34
|
+
// Because of how `.xlsx` file contents are defined in the specification,
|
|
35
|
+
// it will have to be read in 3 passes:
|
|
36
|
+
// * First pass — read the actual file paths
|
|
37
|
+
// * Second pass — read "shared strings" and "styles"
|
|
38
|
+
// * Thirs pass — read the sheets data
|
|
28
39
|
|
|
29
|
-
|
|
30
|
-
// These paths aren't standardized between different spreadsheet editors.
|
|
31
|
-
// https://github.com/tidyverse/readxl/issues/104
|
|
32
|
-
var filePaths = parseFilePaths(getFileContent('xl/_rels/workbook.xml.rels'), xml);
|
|
33
|
-
|
|
34
|
-
// The usual file path for "shared strings" is "xl/sharedStrings.xml".
|
|
35
|
-
var sharedStrings = filePaths.sharedStrings ? parseSharedStrings(getFileContent(filePaths.sharedStrings), xml) : [];
|
|
36
|
-
|
|
37
|
-
// The usual file path for "styles" is "xl/styles.xml".
|
|
38
|
-
var styles = filePaths.styles ? parseStyles(getFileContent(filePaths.styles), xml) : {};
|
|
39
|
-
var _parseSpreadsheetInfo = parseSpreadsheetInfo(getFileContent('xl/workbook.xml'), xml),
|
|
40
|
-
sheets = _parseSpreadsheetInfo.sheets,
|
|
41
|
-
epoch1904 = _parseSpreadsheetInfo.epoch1904;
|
|
42
|
-
var sheetIdsToRead = options.sheets && options.sheets.map(function (sheet) {
|
|
43
|
-
return getSheetId(sheet, sheets);
|
|
44
|
-
});
|
|
40
|
+
checkpoint('parse spreadsheet info and file paths');
|
|
45
41
|
|
|
46
|
-
//
|
|
42
|
+
// Get spreadsheet info and the paths to files.
|
|
43
|
+
return readFiles(getXmlFilesAtFixedPaths(), contents, parseXmlStream).then(function (_ref) {
|
|
44
|
+
var spreadsheetInfo = _ref.spreadsheetInfo,
|
|
45
|
+
filePaths = _ref.filePaths;
|
|
46
|
+
checkpoint('parse "shared strings" and "styles"');
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
48
|
+
// Parse "shared strings" and "styles".
|
|
49
|
+
return readFiles(getXmlFilesAtNonFixedPaths(filePaths), contents, parseXmlStream).then(function (_ref2) {
|
|
50
|
+
var sharedStrings = _ref2.sharedStrings,
|
|
51
|
+
styles = _ref2.styles;
|
|
52
|
+
var sheetRelationIdsToRead = options.sheets ? options.sheets.map(function (sheet) {
|
|
53
|
+
return getSheetRelationId(sheet, spreadsheetInfo.sheets);
|
|
54
|
+
}) : spreadsheetInfo.sheets.map(function (_) {
|
|
55
|
+
return _.relationId;
|
|
56
|
+
});
|
|
57
|
+
checkpoint("parse sheet".concat(sheetRelationIdsToRead.length === 1 ? '' : 's', " data"));
|
|
58
|
+
|
|
59
|
+
// Parse sheets data.
|
|
60
|
+
return readFiles(getSheetDataXmlFiles(filePaths, sheetRelationIdsToRead, {
|
|
61
|
+
sharedStrings: sharedStrings,
|
|
62
|
+
styles: styles,
|
|
63
|
+
epoch1904: spreadsheetInfo.epoch1904,
|
|
64
|
+
options: options
|
|
65
|
+
}), contents, parseXmlStream).then(function (sheetsData) {
|
|
66
|
+
checkpoint('end');
|
|
67
|
+
// Return sheets data.
|
|
68
|
+
return sheetRelationIdsToRead.map(function (sheetRelationId) {
|
|
69
|
+
return {
|
|
70
|
+
sheet: getSheetNameByRelationId(sheetRelationId, spreadsheetInfo.sheets),
|
|
71
|
+
data: sheetsData[sheetRelationId]
|
|
72
|
+
};
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Reads data from an `.xlsx` file in a worker.
|
|
81
|
+
* @param {function} [createWorkerFunction] — Creates a worker function.
|
|
82
|
+
* @param {function} parseXmlStream — SAX XML parser.
|
|
83
|
+
* @param {Record<string,string>} contents - A map of `.xml` files inside the `.xlsx` file (which itself is just a zipped directory).
|
|
84
|
+
* @param {object} [options]
|
|
85
|
+
* @return {Promise<Sheet[]>}
|
|
86
|
+
*/
|
|
87
|
+
export default function parseSpreadsheetContentsInWorker(createWorkerFunction, parseXmlStream, contents, options) {
|
|
88
|
+
// Assign the default `parseNumber()` function in the `options`.
|
|
89
|
+
// The reason is that the worker code requires it to be non-`undefined`.
|
|
90
|
+
// Otherwise, it would throw "parseNumber is not defined".
|
|
91
|
+
if (!(options && options.parseNumber)) {
|
|
92
|
+
options = _objectSpread(_objectSpread({}, options), {}, {
|
|
93
|
+
parseNumber: parseNumberDefault
|
|
57
94
|
});
|
|
58
95
|
}
|
|
59
96
|
|
|
60
|
-
//
|
|
61
|
-
|
|
97
|
+
// Using a worker requires specifying all the top-level variables or functions that it uses.
|
|
98
|
+
// Currently, that list looks a little bit too long so for now workers aren't used for parsing sheet data.
|
|
99
|
+
// See the comment in `createWorkerFunction()` call for more details.
|
|
100
|
+
// createWorkerFunction = undefined
|
|
101
|
+
|
|
102
|
+
// If the environment doesn't support "workers", parse spreadsheet contents "synchronously".
|
|
103
|
+
// This will "block" the main thread while parsing.
|
|
104
|
+
if (!createWorkerFunction) {
|
|
105
|
+
return parseSpreadsheetContents(parseXmlStream, contents, options);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Any functions have to be removed from the `options` in order for them to be "serializable"
|
|
109
|
+
// before sending them to the worker thread.
|
|
110
|
+
var _options = options,
|
|
111
|
+
parseNumber = _options.parseNumber,
|
|
112
|
+
optionsJson = _objectWithoutProperties(_options, _excluded);
|
|
113
|
+
|
|
114
|
+
// Create a worker.
|
|
115
|
+
var workerFn = createWorkerFunction(function (data) {
|
|
116
|
+
// Reconstruct the `options`.
|
|
117
|
+
var options = _objectSpread(_objectSpread({}, data.optionsJson), {}, {
|
|
118
|
+
parseNumber: parseNumber
|
|
119
|
+
});
|
|
120
|
+
// Parse sheet data from the `.xml` files.
|
|
121
|
+
return parseSpreadsheetContents(parseXmlStream, data.contents, options);
|
|
122
|
+
});
|
|
123
|
+
workerFn.addDependencies(
|
|
124
|
+
// Any "outside" dependencies that're referenced in the function (below).
|
|
125
|
+
function () {
|
|
126
|
+
return [parseXmlStream, parseNumber, parseSpreadsheetContents, getSheetRelationId, getSheetNameByRelationId, getXmlFilesAtFixedPaths, getXmlFilesAtNonFixedPaths, getSheetDataXmlFiles, readFiles, checkpoint, latestCheckpointTimestamp, isPromise
|
|
127
|
+
// parseSheet,
|
|
128
|
+
//
|
|
129
|
+
// This is not the full list by any means. There's more. Quite a lot more of them.
|
|
130
|
+
// It started looking a bit too much so I stopped adding the dependencies here.
|
|
131
|
+
// Now I understand why `fflate`'s source code is all written in a single
|
|
132
|
+
// multi-thousand-line `index.ts` file. The thing is, once one starts splitting
|
|
133
|
+
// the code into modules, they'd have to manually export any top-level variables
|
|
134
|
+
// or functions from those modules and import them here in order to specify them
|
|
135
|
+
// in the list of dependencies. And even if doing so for every top-level variable
|
|
136
|
+
// or function in every imported module doesn't seem like an impossible task,
|
|
137
|
+
// imagine someone refactoring the code later and extracting new top-level
|
|
138
|
+
// variables or functions. Without 100% code coverage requirement, it won't be caught
|
|
139
|
+
// at build time and can only be caught in production, which isn't ideal to say the least.
|
|
140
|
+
// So it seems like users of this package will have to just deal with the "blocking"
|
|
141
|
+
// nature of the sheet data parser, because I won't follow into `fflate`'s steps
|
|
142
|
+
// and rewrite this package as a single `index.js` file.
|
|
143
|
+
// Users of this package will have to manually put their code in a worker
|
|
144
|
+
// in case they'd prefer it to run in a separate thread to prevent "blocking"
|
|
145
|
+
// the main thread when parsing sheet data.
|
|
146
|
+
];
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
// Post a message with some data to the worker
|
|
150
|
+
// so that it starts processing the data
|
|
151
|
+
// and later posts a message back to the main thread
|
|
152
|
+
// with the result of the calculation.
|
|
153
|
+
return workerFn.callOnce({
|
|
154
|
+
optionsJson: optionsJson,
|
|
155
|
+
contents: contents
|
|
156
|
+
}); // (optional) add `transferList` argument.
|
|
62
157
|
}
|
|
63
|
-
|
|
158
|
+
|
|
159
|
+
function getSheetRelationId(sheet, sheets) {
|
|
64
160
|
if (typeof sheet === 'string') {
|
|
65
161
|
for (var _iterator = _createForOfIteratorHelperLoose(sheets), _step; !(_step = _iterator()).done;) {
|
|
66
162
|
var _sheet = _step.value;
|
|
@@ -68,8 +164,8 @@ function getSheetId(sheet, sheets) {
|
|
|
68
164
|
return _sheet.relationId;
|
|
69
165
|
}
|
|
70
166
|
}
|
|
71
|
-
throw new Error("Sheet \"".concat(sheet, "\" not found. Available sheets: ").concat(sheets.map(function (
|
|
72
|
-
var name =
|
|
167
|
+
throw new Error("Sheet \"".concat(sheet, "\" not found. Available sheets: ").concat(sheets.map(function (_ref3) {
|
|
168
|
+
var name = _ref3.name;
|
|
73
169
|
return "\"".concat(name, "\"");
|
|
74
170
|
}).join(', ')));
|
|
75
171
|
} else {
|
|
@@ -79,13 +175,116 @@ function getSheetId(sheet, sheets) {
|
|
|
79
175
|
throw new Error("Sheet number out of bounds: ".concat(sheet, ". Available sheets count: ").concat(sheets.length));
|
|
80
176
|
}
|
|
81
177
|
}
|
|
82
|
-
function
|
|
178
|
+
function getSheetNameByRelationId(sheetRelationId, sheets) {
|
|
83
179
|
for (var _iterator2 = _createForOfIteratorHelperLoose(sheets), _step2; !(_step2 = _iterator2()).done;) {
|
|
84
180
|
var sheet = _step2.value;
|
|
85
|
-
if (sheet.relationId ===
|
|
181
|
+
if (sheet.relationId === sheetRelationId) {
|
|
86
182
|
return sheet.name;
|
|
87
183
|
}
|
|
88
184
|
}
|
|
89
|
-
throw new Error("Sheet ID not found: ".concat(
|
|
185
|
+
throw new Error("Sheet relation ID not found: ".concat(sheetRelationId));
|
|
186
|
+
}
|
|
187
|
+
function getXmlFilesAtFixedPaths() {
|
|
188
|
+
return {
|
|
189
|
+
// Read the paths to certain files inside the `.xlsx` file, which is itself just a `.zip` archive.
|
|
190
|
+
// These paths aren't standardized between different spreadsheet editors.
|
|
191
|
+
// https://github.com/tidyverse/readxl/issues/104
|
|
192
|
+
'xl/_rels/workbook.xml.rels': {
|
|
193
|
+
name: 'filePaths',
|
|
194
|
+
parse: parseFilePaths
|
|
195
|
+
},
|
|
196
|
+
// General info on the spreadsheet.
|
|
197
|
+
'xl/workbook.xml': {
|
|
198
|
+
name: 'spreadsheetInfo',
|
|
199
|
+
parse: parseSpreadsheetInfo
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
function getXmlFilesAtNonFixedPaths(filePaths) {
|
|
204
|
+
var _ref4;
|
|
205
|
+
return _ref4 = {}, _defineProperty(_ref4, filePaths.sharedStrings || 'xl/sharedStrings.xml', {
|
|
206
|
+
name: 'sharedStrings',
|
|
207
|
+
// `parseSharedStrings()` returns a `Promise`.
|
|
208
|
+
parse: parseSharedStrings,
|
|
209
|
+
// It seems that "sharedStrings.xml" is not required to exist.
|
|
210
|
+
// For example, that could be the case when a spreadsheet doesn't contain any strings.
|
|
211
|
+
// https://github.com/catamphetamine/read-excel-file/issues/85
|
|
212
|
+
fallback: []
|
|
213
|
+
}), _defineProperty(_ref4, filePaths.styles || 'xl/styles.xml', {
|
|
214
|
+
name: 'styles',
|
|
215
|
+
parse: parseStyles,
|
|
216
|
+
fallback: {}
|
|
217
|
+
}), _ref4;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Returns the list of sheet data `.xml` files.
|
|
221
|
+
function getSheetDataXmlFiles(filePaths, sheetRelationIdsToRead, sheetDataParserParameters) {
|
|
222
|
+
return Object.keys(filePaths.sheets).filter(function (sheetRelationId) {
|
|
223
|
+
return sheetRelationIdsToRead.includes(sheetRelationId);
|
|
224
|
+
}).reduce(function (filesInfo, sheetRelationId) {
|
|
225
|
+
return _objectSpread(_objectSpread({}, filesInfo), {}, _defineProperty({}, filePaths.sheets[sheetRelationId], {
|
|
226
|
+
name: sheetRelationId,
|
|
227
|
+
// `parseSheet()` returns a `Promise`.
|
|
228
|
+
parse: function parse(content, parseXmlStream) {
|
|
229
|
+
return parseSheet(content, parseXmlStream, sheetDataParserParameters);
|
|
230
|
+
}
|
|
231
|
+
}));
|
|
232
|
+
}, {});
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// In case of converting `.zip` file reader from a "read-and-return" one to a "streaming" one,
|
|
236
|
+
// this function could be modified to process the files as they come rather than all-at-once.
|
|
237
|
+
|
|
238
|
+
// Reads files from inside an `.xlsx` archive by file paths.
|
|
239
|
+
//
|
|
240
|
+
// In case of converting `.zip` file reader from a "read-and-return" one to a "streaming" one,
|
|
241
|
+
// this function could be modified to process the files as they come rather than all-at-once.
|
|
242
|
+
//
|
|
243
|
+
// But there's a catch: inside an `.xlsx` file, some file paths are not fixed
|
|
244
|
+
// and are instead defined in "xl/_rels/workbook.xml.rels" file,
|
|
245
|
+
// which presents a "chicken and an egg" dilemma: how could one possibly
|
|
246
|
+
// read an `.xlsx` file in one go when the order of the files inside it isn't fixed
|
|
247
|
+
// and could be random. Most likely, in the majority of cases, "xl/_rels/workbook.xml.rels"
|
|
248
|
+
// file is gonna be one of the first in a given `.xlsx` archive, but still it's not guaranteed.
|
|
249
|
+
// A solution would be reading an `.xlsx` file in two passes: one pass would be just to read
|
|
250
|
+
// the "xl/_rels/workbook.xml.rels" and ignore decompressing anything else,
|
|
251
|
+
// and then the second pass would be to read all other files whose paths are now known.
|
|
252
|
+
//
|
|
253
|
+
// Returns:
|
|
254
|
+
// * If none of the `parse()` functions returned a `Promise`, it returns a map of files' contents.
|
|
255
|
+
// * If any of the `parse()` functions returned a `Promise`, it returns a `Promise` that resolves to a map of files' contents.
|
|
256
|
+
//
|
|
257
|
+
function readFiles(filesInfo, contents, parseXmlStream) {
|
|
258
|
+
// Get files' contents.
|
|
259
|
+
var results = {};
|
|
260
|
+
var _loop = function _loop() {
|
|
261
|
+
var filePath = _Object$keys[_i];
|
|
262
|
+
var fileInfo = filesInfo[filePath];
|
|
263
|
+
results[fileInfo.name] = contents[filePath] === undefined ? fileInfo.fallback === undefined ? function () {
|
|
264
|
+
throw new Error("\"".concat(filePath, "\" file not found inside the `.xlsx` file"));
|
|
265
|
+
}() : fileInfo.fallback : fileInfo.parse(contents[filePath], parseXmlStream);
|
|
266
|
+
};
|
|
267
|
+
for (var _i = 0, _Object$keys = Object.keys(filesInfo); _i < _Object$keys.length; _i++) {
|
|
268
|
+
_loop();
|
|
269
|
+
}
|
|
270
|
+
// Resolve any `Promise`s.
|
|
271
|
+
var promises = [];
|
|
272
|
+
var _loop2 = function _loop2() {
|
|
273
|
+
var name = _Object$keys2[_i2];
|
|
274
|
+
if (isPromise(results[name])) {
|
|
275
|
+
promises.push(results[name].then(function (result) {
|
|
276
|
+
results[name] = result;
|
|
277
|
+
}));
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
for (var _i2 = 0, _Object$keys2 = Object.keys(results); _i2 < _Object$keys2.length; _i2++) {
|
|
281
|
+
_loop2();
|
|
282
|
+
}
|
|
283
|
+
if (promises.length > 0) {
|
|
284
|
+
return Promise.all(promises).then(function () {
|
|
285
|
+
return results;
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
return results;
|
|
90
289
|
}
|
|
91
290
|
//# sourceMappingURL=parseSpreadsheetContents.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseSpreadsheetContents.js","names":["parseSpreadsheetInfo","parseFilePaths","parseStyles","parseSharedStrings","parseSheet","parseSpreadsheetContents","contents","xml","options","arguments","length","undefined","getFileContent","filePath","Error","concat","filePaths","sharedStrings","styles","_parseSpreadsheetInfo","sheets","epoch1904","sheetIdsToRead","map","sheet","getSheetId","sheetsData","_i","_Object$keys","Object","keys","sheetId","includes","push","getSheetNameById","data","_iterator","_createForOfIteratorHelperLoose","_step","done","_sheet","value","name","relationId","_ref","join","_iterator2","_step2"],"sources":["../../source/xlsx/parseSpreadsheetContents.js"],"sourcesContent":["import parseSpreadsheetInfo from './parseSpreadsheetInfo.js'\r\nimport parseFilePaths from './parseFilePaths.js'\r\nimport parseStyles from './parseStyles.js'\r\nimport parseSharedStrings from './parseSharedStrings.js'\r\nimport parseSheet from './parseSheet.js'\r\n\r\n// For an introduction in reading `.xlsx` files see \"The minimum viable XLSX reader\":\r\n// https://www.brendanlong.com/the-minimum-viable-xlsx-reader.html\r\n\r\n/**\r\n * Reads data from an `.xlsx` file.\r\n * @param {Record<string,string>} contents - A map of `.xml` files inside the `.xlsx` file (which itself is just a zipped directory).\r\n * @param {object} xml — An object having a single property — `createDocument(string)` function.\r\n * @param {object} [options]\r\n * @return {Sheet[]}\r\n */\r\nexport default function parseSpreadsheetContents(contents, xml, options = {}) {\r\n const getFileContent = (filePath) => {\r\n if (!contents[filePath]) {\r\n throw new Error(`\"${filePath}\" file not found inside the *.xlsx file zip archive`)\r\n }\r\n return contents[filePath]\r\n }\r\n\r\n // Read the paths to certain files inside the `.xlsx` file, which is itself just a `.zip` archive.\r\n // These paths aren't standardized between different spreadsheet editors.\r\n // https://github.com/tidyverse/readxl/issues/104\r\n const filePaths = parseFilePaths(getFileContent('xl/_rels/workbook.xml.rels'), xml)\r\n\r\n // The usual file path for \"shared strings\" is \"xl/sharedStrings.xml\".\r\n const sharedStrings = filePaths.sharedStrings\r\n ? parseSharedStrings(getFileContent(filePaths.sharedStrings), xml)\r\n : []\r\n\r\n // The usual file path for \"styles\" is \"xl/styles.xml\".\r\n const styles = filePaths.styles\r\n ? parseStyles(getFileContent(filePaths.styles), xml)\r\n : {}\r\n\r\n const { sheets, epoch1904 } = parseSpreadsheetInfo(getFileContent('xl/workbook.xml'), xml)\r\n\r\n const sheetIdsToRead = options.sheets && options.sheets.map(sheet => getSheetId(sheet, sheets))\r\n\r\n // Parse sheets data.\r\n\r\n const sheetsData = []\r\n\r\n for (const sheetId of Object.keys(filePaths.sheets)) {\r\n if (sheetIdsToRead && !sheetIdsToRead.includes(sheetId)) {\r\n continue\r\n }\r\n\r\n sheetsData.push({\r\n sheet: getSheetNameById(sheetId, sheets),\r\n data: parseSheet(\r\n getFileContent(filePaths.sheets[sheetId]),\r\n xml,\r\n sharedStrings,\r\n styles,\r\n epoch1904,\r\n options\r\n )\r\n })\r\n }\r\n\r\n // Return spreadsheet data.\r\n return sheetsData\r\n}\r\n\r\nfunction getSheetId(sheet, sheets) {\r\n if (typeof sheet === 'string') {\r\n for (const _sheet of sheets) {\r\n if (_sheet.name === sheet) {\r\n return _sheet.relationId\r\n }\r\n }\r\n\t\tthrow new Error(`Sheet \"${sheet}\" not found. Available sheets: ${sheets.map(({ name }) => `\"${name}\"`).join(', ')}`)\r\n } else {\r\n\t\tif (sheet <= sheets.length) {\r\n return sheets[sheet - 1].relationId\r\n }\r\n throw new Error(`Sheet number out of bounds: ${sheet}. Available sheets count: ${sheets.length}`)\r\n }\r\n}\r\n\r\nfunction getSheetNameById(sheetId, sheets) {\r\n for (const sheet of sheets) {\r\n if (sheet.relationId === sheetId) {\r\n return sheet.name\r\n }\r\n }\r\n throw new Error(`Sheet ID not found: ${sheetId}`)\r\n}"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"parseSpreadsheetContents.js","names":["parseSpreadsheetInfo","parseFilePaths","parseStyles","parseSharedStrings","parseSheet","parseNumberDefault","checkpoint","latestCheckpointTimestamp","isPromise","parseSpreadsheetContents","parseXmlStream","contents","options","arguments","length","undefined","readFiles","getXmlFilesAtFixedPaths","then","_ref","spreadsheetInfo","filePaths","getXmlFilesAtNonFixedPaths","_ref2","sharedStrings","styles","sheetRelationIdsToRead","sheets","map","sheet","getSheetRelationId","_","relationId","concat","getSheetDataXmlFiles","epoch1904","sheetsData","sheetRelationId","getSheetNameByRelationId","data","parseSpreadsheetContentsInWorker","createWorkerFunction","parseNumber","_objectSpread","_options","optionsJson","_objectWithoutProperties","_excluded","workerFn","addDependencies","callOnce","_iterator","_createForOfIteratorHelperLoose","_step","done","_sheet","value","name","Error","_ref3","join","_iterator2","_step2","parse","_ref4","_defineProperty","fallback","sheetDataParserParameters","Object","keys","filter","includes","reduce","filesInfo","content","results","_loop","filePath","_Object$keys","_i","fileInfo","promises","_loop2","_Object$keys2","_i2","push","result","Promise","all"],"sources":["../../source/xlsx/parseSpreadsheetContents.js"],"sourcesContent":["import parseSpreadsheetInfo from './parseSpreadsheetInfo.js'\r\nimport parseFilePaths from './parseFilePaths.js'\r\nimport parseStyles from './parseStyles.js'\r\nimport parseSharedStrings from './parseSharedStrings.js'\r\nimport parseSheet from './parseSheet.js'\r\nimport parseNumberDefault from './parseNumber.js'\r\n\r\nimport checkpoint, { latestCheckpointTimestamp } from '../utility/checkpoint.js'\r\nimport isPromise from '../utility/isPromise.js'\r\n\r\n// For an introduction in reading `.xlsx` files see \"The minimum viable XLSX reader\":\r\n// https://www.brendanlong.com/the-minimum-viable-xlsx-reader.html\r\n\r\n/**\r\n * Reads data from an `.xlsx` file.\r\n * @param {function} parseXmlStream — SAX XML parser.\r\n * @param {Record<string,string>} contents - A map of `.xml` files inside the `.xlsx` file (which itself is just a zipped directory).\r\n * @param {object} [options]\r\n * @return {Promise<Sheet[]>}\r\n */\r\nfunction parseSpreadsheetContents(parseXmlStream, contents, options = {}) {\r\n // Because of how `.xlsx` file contents are defined in the specification,\r\n // it will have to be read in 3 passes:\r\n // * First pass — read the actual file paths\r\n // * Second pass — read \"shared strings\" and \"styles\"\r\n // * Thirs pass — read the sheets data\r\n\r\n checkpoint('parse spreadsheet info and file paths')\r\n\r\n // Get spreadsheet info and the paths to files.\r\n return readFiles(\r\n getXmlFilesAtFixedPaths(),\r\n contents,\r\n parseXmlStream\r\n ).then(({ spreadsheetInfo, filePaths }) => {\r\n checkpoint('parse \"shared strings\" and \"styles\"')\r\n\r\n // Parse \"shared strings\" and \"styles\".\r\n return readFiles(\r\n getXmlFilesAtNonFixedPaths(filePaths),\r\n contents,\r\n parseXmlStream\r\n ).then(({ sharedStrings, styles }) => {\r\n const sheetRelationIdsToRead = options.sheets\r\n ? options.sheets.map(sheet => getSheetRelationId(sheet, spreadsheetInfo.sheets))\r\n : spreadsheetInfo.sheets.map(_ => _.relationId)\r\n\r\n checkpoint(`parse sheet${sheetRelationIdsToRead.length === 1 ? '' : 's'} data`)\r\n\r\n // Parse sheets data.\r\n return readFiles(\r\n getSheetDataXmlFiles(filePaths, sheetRelationIdsToRead, {\r\n sharedStrings,\r\n styles,\r\n epoch1904: spreadsheetInfo.epoch1904,\r\n options\r\n }),\r\n contents,\r\n parseXmlStream\r\n ).then((sheetsData) => {\r\n checkpoint('end')\r\n // Return sheets data.\r\n return sheetRelationIdsToRead.map((sheetRelationId) => ({\r\n sheet: getSheetNameByRelationId(sheetRelationId, spreadsheetInfo.sheets),\r\n data: sheetsData[sheetRelationId]\r\n }))\r\n })\r\n })\r\n })\r\n}\r\n\r\n/**\r\n * Reads data from an `.xlsx` file in a worker.\r\n * @param {function} [createWorkerFunction] — Creates a worker function.\r\n * @param {function} parseXmlStream — SAX XML parser.\r\n * @param {Record<string,string>} contents - A map of `.xml` files inside the `.xlsx` file (which itself is just a zipped directory).\r\n * @param {object} [options]\r\n * @return {Promise<Sheet[]>}\r\n */\r\nexport default function parseSpreadsheetContentsInWorker(createWorkerFunction, parseXmlStream, contents, options) {\r\n // Assign the default `parseNumber()` function in the `options`.\r\n // The reason is that the worker code requires it to be non-`undefined`.\r\n // Otherwise, it would throw \"parseNumber is not defined\".\r\n if (!(options && options.parseNumber)) {\r\n options = {\r\n ...options,\r\n parseNumber: parseNumberDefault\r\n }\r\n }\r\n\r\n // Using a worker requires specifying all the top-level variables or functions that it uses.\r\n // Currently, that list looks a little bit too long so for now workers aren't used for parsing sheet data.\r\n // See the comment in `createWorkerFunction()` call for more details.\r\n // createWorkerFunction = undefined\r\n\r\n // If the environment doesn't support \"workers\", parse spreadsheet contents \"synchronously\".\r\n // This will \"block\" the main thread while parsing.\r\n if (!createWorkerFunction) {\r\n return parseSpreadsheetContents(parseXmlStream, contents, options)\r\n }\r\n\r\n // Any functions have to be removed from the `options` in order for them to be \"serializable\"\r\n // before sending them to the worker thread.\r\n const { parseNumber, ...optionsJson } = options\r\n\r\n // Create a worker.\r\n const workerFn = createWorkerFunction(\r\n (data) => {\r\n // Reconstruct the `options`.\r\n const options = {\r\n ...data.optionsJson,\r\n parseNumber\r\n }\r\n // Parse sheet data from the `.xml` files.\r\n return parseSpreadsheetContents(parseXmlStream, data.contents, options)\r\n }\r\n )\r\n\r\n workerFn.addDependencies(\r\n // Any \"outside\" dependencies that're referenced in the function (below).\r\n () => [\r\n parseXmlStream,\r\n parseNumber,\r\n parseSpreadsheetContents,\r\n getSheetRelationId,\r\n getSheetNameByRelationId,\r\n getXmlFilesAtFixedPaths,\r\n getXmlFilesAtNonFixedPaths,\r\n getSheetDataXmlFiles,\r\n readFiles,\r\n checkpoint,\r\n latestCheckpointTimestamp,\r\n isPromise,\r\n // parseSheet,\r\n //\r\n // This is not the full list by any means. There's more. Quite a lot more of them.\r\n // It started looking a bit too much so I stopped adding the dependencies here.\r\n // Now I understand why `fflate`'s source code is all written in a single\r\n // multi-thousand-line `index.ts` file. The thing is, once one starts splitting\r\n // the code into modules, they'd have to manually export any top-level variables\r\n // or functions from those modules and import them here in order to specify them\r\n // in the list of dependencies. And even if doing so for every top-level variable\r\n // or function in every imported module doesn't seem like an impossible task,\r\n // imagine someone refactoring the code later and extracting new top-level\r\n // variables or functions. Without 100% code coverage requirement, it won't be caught\r\n // at build time and can only be caught in production, which isn't ideal to say the least.\r\n // So it seems like users of this package will have to just deal with the \"blocking\"\r\n // nature of the sheet data parser, because I won't follow into `fflate`'s steps\r\n // and rewrite this package as a single `index.js` file.\r\n // Users of this package will have to manually put their code in a worker\r\n // in case they'd prefer it to run in a separate thread to prevent \"blocking\"\r\n // the main thread when parsing sheet data.\r\n ]\r\n )\r\n\r\n // Post a message with some data to the worker\r\n // so that it starts processing the data\r\n // and later posts a message back to the main thread\r\n // with the result of the calculation.\r\n return workerFn.callOnce({ optionsJson, contents }) // (optional) add `transferList` argument.\r\n}\r\n\r\nfunction getSheetRelationId(sheet, sheets) {\r\n if (typeof sheet === 'string') {\r\n for (const _sheet of sheets) {\r\n if (_sheet.name === sheet) {\r\n return _sheet.relationId\r\n }\r\n }\r\n\t\tthrow new Error(`Sheet \"${sheet}\" not found. Available sheets: ${sheets.map(({ name }) => `\"${name}\"`).join(', ')}`)\r\n } else {\r\n\t\tif (sheet <= sheets.length) {\r\n return sheets[sheet - 1].relationId\r\n }\r\n throw new Error(`Sheet number out of bounds: ${sheet}. Available sheets count: ${sheets.length}`)\r\n }\r\n}\r\n\r\nfunction getSheetNameByRelationId(sheetRelationId, sheets) {\r\n for (const sheet of sheets) {\r\n if (sheet.relationId === sheetRelationId) {\r\n return sheet.name\r\n }\r\n }\r\n throw new Error(`Sheet relation ID not found: ${sheetRelationId}`)\r\n}\r\n\r\nfunction getXmlFilesAtFixedPaths() {\r\n return {\r\n // Read the paths to certain files inside the `.xlsx` file, which is itself just a `.zip` archive.\r\n // These paths aren't standardized between different spreadsheet editors.\r\n // https://github.com/tidyverse/readxl/issues/104\r\n 'xl/_rels/workbook.xml.rels': {\r\n name: 'filePaths',\r\n parse: parseFilePaths\r\n },\r\n\r\n // General info on the spreadsheet.\r\n 'xl/workbook.xml': {\r\n name: 'spreadsheetInfo',\r\n parse: parseSpreadsheetInfo\r\n }\r\n }\r\n}\r\n\r\nfunction getXmlFilesAtNonFixedPaths(filePaths) {\r\n return {\r\n // The usual file path for \"shared strings\" is \"xl/sharedStrings.xml\".\r\n [filePaths.sharedStrings || 'xl/sharedStrings.xml']: {\r\n name: 'sharedStrings',\r\n // `parseSharedStrings()` returns a `Promise`.\r\n parse: parseSharedStrings,\r\n // It seems that \"sharedStrings.xml\" is not required to exist.\r\n // For example, that could be the case when a spreadsheet doesn't contain any strings.\r\n // https://github.com/catamphetamine/read-excel-file/issues/85\r\n fallback: []\r\n },\r\n\r\n // The usual file path for \"styles\" is \"xl/styles.xml\".\r\n [filePaths.styles || 'xl/styles.xml']: {\r\n name: 'styles',\r\n parse: parseStyles,\r\n fallback: {}\r\n }\r\n }\r\n}\r\n\r\n// Returns the list of sheet data `.xml` files.\r\nfunction getSheetDataXmlFiles(filePaths, sheetRelationIdsToRead, sheetDataParserParameters) {\r\n return Object.keys(filePaths.sheets)\r\n .filter((sheetRelationId) => sheetRelationIdsToRead.includes(sheetRelationId))\r\n .reduce((filesInfo, sheetRelationId) => ({\r\n ...filesInfo,\r\n [filePaths.sheets[sheetRelationId]]: {\r\n name: sheetRelationId,\r\n // `parseSheet()` returns a `Promise`.\r\n parse: (content, parseXmlStream) => parseSheet(content, parseXmlStream, sheetDataParserParameters)\r\n }\r\n }), {})\r\n}\r\n\r\n// In case of converting `.zip` file reader from a \"read-and-return\" one to a \"streaming\" one,\r\n// this function could be modified to process the files as they come rather than all-at-once.\r\n\r\n// Reads files from inside an `.xlsx` archive by file paths.\r\n//\r\n// In case of converting `.zip` file reader from a \"read-and-return\" one to a \"streaming\" one,\r\n// this function could be modified to process the files as they come rather than all-at-once.\r\n//\r\n// But there's a catch: inside an `.xlsx` file, some file paths are not fixed\r\n// and are instead defined in \"xl/_rels/workbook.xml.rels\" file,\r\n// which presents a \"chicken and an egg\" dilemma: how could one possibly\r\n// read an `.xlsx` file in one go when the order of the files inside it isn't fixed\r\n// and could be random. Most likely, in the majority of cases, \"xl/_rels/workbook.xml.rels\"\r\n// file is gonna be one of the first in a given `.xlsx` archive, but still it's not guaranteed.\r\n// A solution would be reading an `.xlsx` file in two passes: one pass would be just to read\r\n// the \"xl/_rels/workbook.xml.rels\" and ignore decompressing anything else,\r\n// and then the second pass would be to read all other files whose paths are now known.\r\n//\r\n// Returns:\r\n// * If none of the `parse()` functions returned a `Promise`, it returns a map of files' contents.\r\n// * If any of the `parse()` functions returned a `Promise`, it returns a `Promise` that resolves to a map of files' contents.\r\n//\r\nfunction readFiles(filesInfo, contents, parseXmlStream) {\r\n // Get files' contents.\r\n const results = {}\r\n for (const filePath of Object.keys(filesInfo)) {\r\n const fileInfo = filesInfo[filePath]\r\n results[fileInfo.name] = contents[filePath] === undefined\r\n ? (\r\n fileInfo.fallback === undefined\r\n ? (() => { throw new Error(`\"${filePath}\" file not found inside the \\`.xlsx\\` file`) })()\r\n : fileInfo.fallback\r\n )\r\n : fileInfo.parse(contents[filePath], parseXmlStream)\r\n }\r\n // Resolve any `Promise`s.\r\n const promises = []\r\n for (const name of Object.keys(results)) {\r\n if (isPromise(results[name])) {\r\n promises.push(results[name].then((result) => {\r\n results[name] = result\r\n }))\r\n }\r\n }\r\n if (promises.length > 0) {\r\n return Promise.all(promises).then(() => results)\r\n }\r\n return results\r\n}"],"mappings":"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"}
|
|
@@ -1,42 +1,72 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export default function parseSpreadsheetInfo(content,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Parses spreadsheet info.
|
|
3
|
+
* @param {string} content
|
|
4
|
+
* @param {function} parseXmlStream — SAX XML parser.
|
|
5
|
+
* @returns {object} An object of shape `{ epoch1904: boolean, sheets: Sheet[] }`.
|
|
6
|
+
*/
|
|
7
|
+
export default function parseSpreadsheetInfo(content, parseXmlStream) {
|
|
8
|
+
return parseXmlStream(content, {
|
|
9
|
+
createInitialState: createInitialStateInWorkbookXml,
|
|
10
|
+
onOpenTag: onOpenTagInWorkbookXml
|
|
11
|
+
}).then(function (state) {
|
|
12
|
+
return {
|
|
13
|
+
epoch1904: state.workbookPr ? state.workbookPr.epoch1904 : false,
|
|
14
|
+
sheets: state.sheets
|
|
15
|
+
};
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
function createInitialStateInWorkbookXml() {
|
|
19
|
+
return {
|
|
20
|
+
workbookPr: undefined,
|
|
21
|
+
sheets: []
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function onOpenTagInWorkbookXml(tagName, attributes, state) {
|
|
25
|
+
if (tagName === 'workbookPr') {
|
|
26
|
+
// The official Open XML specification dictates that the top-level `<workbook/>` element
|
|
27
|
+
// should only contain exactly one `<workbookPr/>` element. In case of multiple ones,
|
|
28
|
+
// only the first one is being read and the rest are simply ignored.
|
|
29
|
+
//
|
|
30
|
+
// There's a `1904-based-dates.xlsx` test case that happens to include multiple `<workbookPr/>`
|
|
31
|
+
// elements by accident, most likely because I edited its `.xml` files by hand and didn't notice
|
|
32
|
+
// the already-existing `<workbookPr/>` tag.
|
|
33
|
+
//
|
|
34
|
+
// At first I thought about just fixing that one `.xlsx` test file but later
|
|
35
|
+
// I saw that another library called `SheetJS` specifically handles such cases
|
|
36
|
+
// by only reading the first `<workbookPr/>` element and ignoring the rest,
|
|
37
|
+
// so I though that perhaps it would make some sense to do same thing here.
|
|
38
|
+
// https://github.com/SheetJS/sheetjs/issues/1619
|
|
39
|
+
//
|
|
40
|
+
if (!state.workbookPr) {
|
|
41
|
+
// Read `<workbookPr/>` element attributes to detect whether dates are 1900-based or 1904-based.
|
|
42
|
+
// https://support.microsoft.com/en-gb/help/214330/differences-between-the-1900-and-the-1904-date-system-in-excel
|
|
43
|
+
// http://webapp.docx4java.org/OnlineDemo/ecma376/SpreadsheetML/workbookPr.html
|
|
44
|
+
state.workbookPr = {
|
|
45
|
+
epoch1904: attributes.date1904 === '1'
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
} else if (tagName === 'sheet') {
|
|
49
|
+
// Example of `<sheets/>` element:
|
|
50
|
+
// ```
|
|
51
|
+
// <sheets>
|
|
52
|
+
// <sheet
|
|
53
|
+
// xmlns:ns="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
|
|
54
|
+
// name="Sheet1"
|
|
55
|
+
// sheetId="1"
|
|
56
|
+
// ns:id="rId3"/>
|
|
57
|
+
// </sheets>
|
|
58
|
+
// ```
|
|
59
|
+
if (attributes.name) {
|
|
60
|
+
state.sheets.push({
|
|
61
|
+
// `sheetId` attribute value is an arbitrary, `1`-based unique positive integer
|
|
62
|
+
// assigned to a worksheet, typically starting at `1` for the first sheet.
|
|
63
|
+
// Deleting and adding new sheets might cause the sheetId values to become non-sequential.
|
|
64
|
+
// For example, `sheetId`s could be `1`, `2`, `4`, if sheet `3` was deleted.
|
|
65
|
+
id: Number(attributes.sheetId),
|
|
66
|
+
name: attributes.name,
|
|
67
|
+
relationId: attributes['r:id']
|
|
34
68
|
});
|
|
35
69
|
}
|
|
36
70
|
}
|
|
37
|
-
return {
|
|
38
|
-
epoch1904: epoch1904,
|
|
39
|
-
sheets: sheets
|
|
40
|
-
};
|
|
41
71
|
}
|
|
42
72
|
//# sourceMappingURL=parseSpreadsheetInfo.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseSpreadsheetInfo.js","names":["
|
|
1
|
+
{"version":3,"file":"parseSpreadsheetInfo.js","names":["parseSpreadsheetInfo","content","parseXmlStream","createInitialState","createInitialStateInWorkbookXml","onOpenTag","onOpenTagInWorkbookXml","then","state","epoch1904","workbookPr","sheets","undefined","tagName","attributes","date1904","name","push","id","Number","sheetId","relationId"],"sources":["../../source/xlsx/parseSpreadsheetInfo.js"],"sourcesContent":["/**\r\n * Parses spreadsheet info.\r\n * @param {string} content\r\n * @param {function} parseXmlStream — SAX XML parser.\r\n * @returns {object} An object of shape `{ epoch1904: boolean, sheets: Sheet[] }`.\r\n */\r\nexport default function parseSpreadsheetInfo(content, parseXmlStream) {\r\n return parseXmlStream(content, {\r\n createInitialState: createInitialStateInWorkbookXml,\r\n onOpenTag: onOpenTagInWorkbookXml\r\n }).then((state) => {\r\n return {\r\n epoch1904: state.workbookPr ? state.workbookPr.epoch1904 : false,\r\n sheets: state.sheets\r\n }\r\n })\r\n}\r\n\r\nfunction createInitialStateInWorkbookXml() {\r\n return {\r\n workbookPr: undefined,\r\n sheets: []\r\n }\r\n}\r\n\r\nfunction onOpenTagInWorkbookXml(tagName, attributes, state) {\r\n if (tagName === 'workbookPr') {\r\n // The official Open XML specification dictates that the top-level `<workbook/>` element\r\n // should only contain exactly one `<workbookPr/>` element. In case of multiple ones,\r\n // only the first one is being read and the rest are simply ignored.\r\n //\r\n // There's a `1904-based-dates.xlsx` test case that happens to include multiple `<workbookPr/>`\r\n // elements by accident, most likely because I edited its `.xml` files by hand and didn't notice\r\n // the already-existing `<workbookPr/>` tag.\r\n //\r\n // At first I thought about just fixing that one `.xlsx` test file but later\r\n // I saw that another library called `SheetJS` specifically handles such cases\r\n // by only reading the first `<workbookPr/>` element and ignoring the rest,\r\n // so I though that perhaps it would make some sense to do same thing here.\r\n // https://github.com/SheetJS/sheetjs/issues/1619\r\n //\r\n if (!state.workbookPr) {\r\n // Read `<workbookPr/>` element attributes to detect whether dates are 1900-based or 1904-based.\r\n // https://support.microsoft.com/en-gb/help/214330/differences-between-the-1900-and-the-1904-date-system-in-excel\r\n // http://webapp.docx4java.org/OnlineDemo/ecma376/SpreadsheetML/workbookPr.html\r\n state.workbookPr = {\r\n epoch1904: attributes.date1904 === '1'\r\n }\r\n }\r\n } else if (tagName === 'sheet') {\r\n // Example of `<sheets/>` element:\r\n // ```\r\n // <sheets>\r\n // <sheet\r\n // xmlns:ns=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"\r\n // name=\"Sheet1\"\r\n // sheetId=\"1\"\r\n // ns:id=\"rId3\"/>\r\n // </sheets>\r\n // ```\r\n if (attributes.name) {\r\n state.sheets.push({\r\n // `sheetId` attribute value is an arbitrary, `1`-based unique positive integer\r\n // assigned to a worksheet, typically starting at `1` for the first sheet.\r\n // Deleting and adding new sheets might cause the sheetId values to become non-sequential.\r\n // For example, `sheetId`s could be `1`, `2`, `4`, if sheet `3` was deleted.\r\n id: Number(attributes.sheetId),\r\n name: attributes.name,\r\n relationId: attributes['r:id']\r\n })\r\n }\r\n }\r\n}"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA,eAAe,SAASA,oBAAoBA,CAACC,OAAO,EAAEC,cAAc,EAAE;EACpE,OAAOA,cAAc,CAACD,OAAO,EAAE;IAC7BE,kBAAkB,EAAEC,+BAA+B;IACnDC,SAAS,EAAEC;EACb,CAAC,CAAC,CAACC,IAAI,CAAC,UAACC,KAAK,EAAK;IACjB,OAAO;MACLC,SAAS,EAAED,KAAK,CAACE,UAAU,GAAGF,KAAK,CAACE,UAAU,CAACD,SAAS,GAAG,KAAK;MAChEE,MAAM,EAAEH,KAAK,CAACG;IAChB,CAAC;EACH,CAAC,CAAC;AACJ;AAEA,SAASP,+BAA+BA,CAAA,EAAG;EACzC,OAAO;IACLM,UAAU,EAAEE,SAAS;IACrBD,MAAM,EAAE;EACV,CAAC;AACH;AAEA,SAASL,sBAAsBA,CAACO,OAAO,EAAEC,UAAU,EAAEN,KAAK,EAAE;EAC1D,IAAIK,OAAO,KAAK,YAAY,EAAE;IAC5B;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,CAACL,KAAK,CAACE,UAAU,EAAE;MACrB;MACA;MACA;MACAF,KAAK,CAACE,UAAU,GAAG;QACjBD,SAAS,EAAEK,UAAU,CAACC,QAAQ,KAAK;MACrC,CAAC;IACH;EACF,CAAC,MAAM,IAAIF,OAAO,KAAK,OAAO,EAAE;IAC9B;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAIC,UAAU,CAACE,IAAI,EAAE;MACnBR,KAAK,CAACG,MAAM,CAACM,IAAI,CAAC;QAChB;QACA;QACA;QACA;QACAC,EAAE,EAAEC,MAAM,CAACL,UAAU,CAACM,OAAO,CAAC;QAC9BJ,IAAI,EAAEF,UAAU,CAACE,IAAI;QACrBK,UAAU,EAAEP,UAAU,CAAC,MAAM;MAC/B,CAAC,CAAC;IACJ;EACF;AACF"}
|