read-excel-file 5.2.7 → 5.2.11
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/CHANGELOG.md +5 -0
- package/README.md +4 -0
- package/bundle/read-excel-file.min.js +2 -2
- package/bundle/read-excel-file.min.js.map +1 -1
- package/commonjs/read/coordinates.js +56 -0
- package/commonjs/read/coordinates.js.map +1 -0
- package/commonjs/read/dropEmptyColumns.js +52 -0
- package/commonjs/read/dropEmptyColumns.js.map +1 -0
- package/commonjs/read/dropEmptyColumns.test.js.map +1 -0
- package/commonjs/read/dropEmptyRows.js +55 -0
- package/commonjs/read/dropEmptyRows.js.map +1 -0
- package/commonjs/read/dropEmptyRows.test.js.map +1 -0
- package/commonjs/read/getData.js +99 -0
- package/commonjs/read/getData.js.map +1 -0
- package/commonjs/read/parseCell.js +71 -0
- package/commonjs/read/parseCell.js.map +1 -0
- package/commonjs/read/parseCellValue.js +204 -0
- package/commonjs/read/parseCellValue.js.map +1 -0
- package/commonjs/read/parseCells.js +30 -0
- package/commonjs/read/parseCells.js.map +1 -0
- package/commonjs/read/parseDimensions.js +47 -0
- package/commonjs/read/parseDimensions.js.map +1 -0
- package/commonjs/read/parseFilePaths.js +83 -0
- package/commonjs/read/parseFilePaths.js.map +1 -0
- package/commonjs/read/parseProperties.js +48 -0
- package/commonjs/read/parseProperties.js.map +1 -0
- package/commonjs/read/parseSharedStrings.js +17 -0
- package/commonjs/read/parseSharedStrings.js.map +1 -0
- package/commonjs/read/parseSheet.js +25 -0
- package/commonjs/read/parseSheet.js.map +1 -0
- package/commonjs/read/parseStyles.js +72 -0
- package/commonjs/read/parseStyles.js.map +1 -0
- package/commonjs/read/readXlsx.js +25 -657
- package/commonjs/read/readXlsx.js.map +1 -1
- package/commonjs/types/URL.js +56 -2
- package/commonjs/types/URL.js.map +1 -1
- package/commonjs/xml/dom.js +17 -3
- package/commonjs/xml/dom.js.map +1 -1
- package/commonjs/xml/xlsx-xpath.js +10 -0
- package/commonjs/xml/xlsx-xpath.js.map +1 -1
- package/commonjs/xml/xlsx.js +22 -0
- package/commonjs/xml/xlsx.js.map +1 -1
- package/commonjs/xml/xmlNode.js +1 -1
- package/commonjs/xml/xmlNode.js.map +1 -1
- package/{index.d.ts.test → index.d.ts} +1 -4
- package/modules/read/coordinates.js +48 -0
- package/modules/read/coordinates.js.map +1 -0
- package/modules/read/dropEmptyColumns.js +45 -0
- package/modules/read/dropEmptyColumns.js.map +1 -0
- package/modules/read/dropEmptyColumns.test.js.map +1 -0
- package/modules/read/dropEmptyRows.js +48 -0
- package/modules/read/dropEmptyRows.js.map +1 -0
- package/modules/read/dropEmptyRows.test.js.map +1 -0
- package/modules/read/getData.js +88 -0
- package/modules/read/getData.js.map +1 -0
- package/modules/read/parseCell.js +59 -0
- package/modules/read/parseCell.js.map +1 -0
- package/modules/read/parseCellValue.js +192 -0
- package/modules/read/parseCellValue.js.map +1 -0
- package/modules/read/parseCells.js +19 -0
- package/modules/read/parseCells.js.map +1 -0
- package/modules/read/parseDimensions.js +38 -0
- package/modules/read/parseDimensions.js.map +1 -0
- package/modules/read/parseFilePaths.js +76 -0
- package/modules/read/parseFilePaths.js.map +1 -0
- package/modules/read/parseProperties.js +40 -0
- package/modules/read/parseProperties.js.map +1 -0
- package/modules/read/parseSharedStrings.js +9 -0
- package/modules/read/parseSharedStrings.js.map +1 -0
- package/modules/read/parseSheet.js +13 -0
- package/modules/read/parseSheet.js.map +1 -0
- package/modules/read/parseStyles.js +64 -0
- package/modules/read/parseStyles.js.map +1 -0
- package/modules/read/readXlsx.js +20 -653
- package/modules/read/readXlsx.js.map +1 -1
- package/modules/types/URL.js +56 -2
- package/modules/types/URL.js.map +1 -1
- package/modules/xml/dom.js +14 -3
- package/modules/xml/dom.js.map +1 -1
- package/modules/xml/xlsx-xpath.js +6 -0
- package/modules/xml/xlsx-xpath.js.map +1 -1
- package/modules/xml/xlsx.js +19 -1
- package/modules/xml/xlsx.js.map +1 -1
- package/modules/xml/xmlNode.js +1 -1
- package/modules/xml/xmlNode.js.map +1 -1
- package/node/{index.d.ts.test → index.d.ts} +1 -1
- package/package.json +6 -5
- package/schema/{index.d.ts.test → index.d.ts} +0 -0
- package/types.d.ts +1 -4
- package/commonjs/read/readXlsx.test.js.map +0 -1
- package/modules/read/readXlsx.test.js.map +0 -1
|
@@ -4,22 +4,20 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports["default"] = readXlsx;
|
|
7
|
-
exports.dropEmptyRows = dropEmptyRows;
|
|
8
|
-
exports.dropEmptyColumns = dropEmptyColumns;
|
|
9
7
|
|
|
10
|
-
var
|
|
8
|
+
var _parseProperties = _interopRequireDefault(require("./parseProperties"));
|
|
11
9
|
|
|
12
|
-
var
|
|
10
|
+
var _parseFilePaths = _interopRequireDefault(require("./parseFilePaths"));
|
|
13
11
|
|
|
14
|
-
|
|
12
|
+
var _parseStyles = _interopRequireDefault(require("./parseStyles"));
|
|
15
13
|
|
|
16
|
-
|
|
14
|
+
var _parseSharedStrings = _interopRequireDefault(require("./parseSharedStrings"));
|
|
17
15
|
|
|
18
|
-
|
|
16
|
+
var _parseSheet = _interopRequireDefault(require("./parseSheet"));
|
|
19
17
|
|
|
20
|
-
|
|
18
|
+
var _getData = _interopRequireDefault(require("./getData"));
|
|
21
19
|
|
|
22
|
-
function
|
|
20
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
|
23
21
|
|
|
24
22
|
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."); }
|
|
25
23
|
|
|
@@ -33,10 +31,7 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
|
|
|
33
31
|
|
|
34
32
|
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
35
33
|
|
|
36
|
-
//
|
|
37
|
-
var letters = ["", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]; // https://hexdocs.pm/xlsxir/number_styles.html
|
|
38
|
-
|
|
39
|
-
var BUILT_IN_DATE_NUMBER_FORMAT_IDS = [14, 15, 16, 17, 18, 19, 20, 21, 22, 27, 30, 36, 45, 46, 47, 50, 57]; // "The minimum viable XLSX reader"
|
|
34
|
+
// For an introduction in reading `*.xlsx` files see "The minimum viable XLSX reader":
|
|
40
35
|
// https://www.brendanlong.com/the-minimum-viable-xlsx-reader.html
|
|
41
36
|
|
|
42
37
|
/**
|
|
@@ -47,7 +42,6 @@ var BUILT_IN_DATE_NUMBER_FORMAT_IDS = [14, 15, 16, 17, 18, 19, 20, 21, 22, 27, 3
|
|
|
47
42
|
* @param {object} contents - A list of XML files inside XLSX file (which is a zipped directory).
|
|
48
43
|
* @return {object} An object of shape `{ data, cells, properties }`. `data: string[][]` is an array of rows, each row being an array of cell values. `cells: string[][]` is an array of rows, each row being an array of cells. `properties: object` is the spreadsheet properties (e.g. whether date epoch is 1904 instead of 1900).
|
|
49
44
|
*/
|
|
50
|
-
|
|
51
45
|
function readXlsx(contents, xml) {
|
|
52
46
|
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
53
47
|
|
|
@@ -59,12 +53,12 @@ function readXlsx(contents, xml) {
|
|
|
59
53
|
// https://github.com/tidyverse/readxl/issues/104
|
|
60
54
|
|
|
61
55
|
|
|
62
|
-
var filePaths =
|
|
56
|
+
var filePaths = (0, _parseFilePaths["default"])(contents['xl/_rels/workbook.xml.rels'], xml); // Default file path for "shared strings": "xl/sharedStrings.xml".
|
|
63
57
|
|
|
64
|
-
var values = filePaths.sharedStrings ?
|
|
58
|
+
var values = filePaths.sharedStrings ? (0, _parseSharedStrings["default"])(contents[filePaths.sharedStrings], xml) : []; // Default file path for "styles": "xl/styles.xml".
|
|
65
59
|
|
|
66
|
-
var styles = filePaths.styles ?
|
|
67
|
-
var properties =
|
|
60
|
+
var styles = filePaths.styles ? (0, _parseStyles["default"])(contents[filePaths.styles], xml) : {};
|
|
61
|
+
var properties = (0, _parseProperties["default"])(contents['xl/workbook.xml'], xml); // A feature for getting the list of sheets in an Excel file.
|
|
68
62
|
// https://github.com/catamphetamine/read-excel-file/issues/14
|
|
69
63
|
|
|
70
64
|
if (options.getSheets) {
|
|
@@ -77,632 +71,42 @@ function readXlsx(contents, xml) {
|
|
|
77
71
|
} // Find the sheet by name, or take the first one.
|
|
78
72
|
|
|
79
73
|
|
|
80
|
-
var
|
|
81
|
-
|
|
82
|
-
if (typeof options.sheet === 'number') {
|
|
83
|
-
var _sheet = properties.sheets[options.sheet - 1];
|
|
84
|
-
sheetRelationId = _sheet && _sheet.relationId;
|
|
85
|
-
} else {
|
|
86
|
-
for (var _iterator = _createForOfIteratorHelperLoose(properties.sheets), _step; !(_step = _iterator()).done;) {
|
|
87
|
-
var _sheet2 = _step.value;
|
|
88
|
-
|
|
89
|
-
if (_sheet2.name === options.sheet) {
|
|
90
|
-
sheetRelationId = _sheet2.relationId;
|
|
91
|
-
break;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
} // If the sheet wasn't found then throw an error.
|
|
74
|
+
var sheetId = getSheetId(options.sheet, properties.sheets); // If the sheet wasn't found then throw an error.
|
|
95
75
|
// Example: "xl/worksheets/sheet1.xml".
|
|
96
76
|
|
|
97
|
-
|
|
98
|
-
if (!sheetRelationId || !filePaths.sheets[sheetRelationId]) {
|
|
77
|
+
if (!sheetId || !filePaths.sheets[sheetId]) {
|
|
99
78
|
throw createSheetNotFoundError(options.sheet, properties.sheets);
|
|
100
79
|
} // Parse sheet data.
|
|
101
80
|
|
|
102
81
|
|
|
103
|
-
var sheet =
|
|
104
|
-
|
|
105
|
-
if (sheet.cells.length === 0) {
|
|
106
|
-
if (options.properties) {
|
|
107
|
-
return {
|
|
108
|
-
data: [],
|
|
109
|
-
properties: properties
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
return [];
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
var _sheet$dimensions = _slicedToArray(sheet.dimensions, 2),
|
|
117
|
-
leftTop = _sheet$dimensions[0],
|
|
118
|
-
rightBottom = _sheet$dimensions[1];
|
|
119
|
-
|
|
120
|
-
var colsCount = rightBottom.column - leftTop.column + 1;
|
|
121
|
-
var rowsCount = rightBottom.row - leftTop.row + 1; // `sheet.cells` seem to not necessarily be sorted by row and column.
|
|
122
|
-
|
|
123
|
-
var data = new Array(rowsCount);
|
|
124
|
-
var i = 0;
|
|
82
|
+
var sheet = (0, _parseSheet["default"])(contents[filePaths.sheets[sheetId]], xml, values, styles, properties, options); // Get spreadsheet data.
|
|
125
83
|
|
|
126
|
-
|
|
127
|
-
data[i] = new Array(colsCount);
|
|
128
|
-
var j = 0;
|
|
129
|
-
|
|
130
|
-
while (j < colsCount) {
|
|
131
|
-
data[i][j] = null;
|
|
132
|
-
j++;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
i++;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
for (var _iterator2 = _createForOfIteratorHelperLoose(sheet.cells), _step2; !(_step2 = _iterator2()).done;) {
|
|
139
|
-
var cell = _step2.value;
|
|
140
|
-
var row = cell.row - leftTop.row;
|
|
141
|
-
var column = cell.column - leftTop.column;
|
|
142
|
-
data[row][column] = cell.value;
|
|
143
|
-
} // Fill in the row map.
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
var _options = options,
|
|
147
|
-
rowMap = _options.rowMap;
|
|
148
|
-
|
|
149
|
-
if (rowMap) {
|
|
150
|
-
var _i2 = 0;
|
|
151
|
-
|
|
152
|
-
while (_i2 < data.length) {
|
|
153
|
-
rowMap[_i2] = _i2;
|
|
154
|
-
_i2++;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
data = dropEmptyRows(dropEmptyColumns(data, {
|
|
159
|
-
onlyTrimAtTheEnd: true
|
|
160
|
-
}), {
|
|
161
|
-
onlyTrimAtTheEnd: true,
|
|
162
|
-
rowMap: rowMap
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
if (options.transformData) {
|
|
166
|
-
data = options.transformData(data); // data = options.transformData(data, {
|
|
167
|
-
// dropEmptyRowsAndColumns(data) {
|
|
168
|
-
// return dropEmptyRows(dropEmptyColumns(data), { rowMap })
|
|
169
|
-
// }
|
|
170
|
-
// })
|
|
171
|
-
}
|
|
84
|
+
var data = (0, _getData["default"])(sheet, options); // Can return properties, if required.
|
|
172
85
|
|
|
173
86
|
if (options.properties) {
|
|
174
87
|
return {
|
|
175
88
|
data: data,
|
|
176
89
|
properties: properties
|
|
177
90
|
};
|
|
178
|
-
}
|
|
91
|
+
} // Return spreadsheet data.
|
|
179
92
|
|
|
180
|
-
return data;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
function calculateDimensions(cells) {
|
|
184
|
-
var comparator = function comparator(a, b) {
|
|
185
|
-
return a - b;
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
var allRows = cells.map(function (cell) {
|
|
189
|
-
return cell.row;
|
|
190
|
-
}).sort(comparator);
|
|
191
|
-
var allCols = cells.map(function (cell) {
|
|
192
|
-
return cell.column;
|
|
193
|
-
}).sort(comparator);
|
|
194
|
-
var minRow = allRows[0];
|
|
195
|
-
var maxRow = allRows[allRows.length - 1];
|
|
196
|
-
var minCol = allCols[0];
|
|
197
|
-
var maxCol = allCols[allCols.length - 1];
|
|
198
|
-
return [{
|
|
199
|
-
row: minRow,
|
|
200
|
-
column: minCol
|
|
201
|
-
}, {
|
|
202
|
-
row: maxRow,
|
|
203
|
-
column: maxCol
|
|
204
|
-
}];
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
function colToInt(col) {
|
|
208
|
-
// `for ... of ...` would require Babel polyfill for iterating a string.
|
|
209
|
-
var n = 0;
|
|
210
|
-
var i = 0;
|
|
211
|
-
|
|
212
|
-
while (i < col.length) {
|
|
213
|
-
n *= 26;
|
|
214
|
-
n += letters.indexOf(col[i]);
|
|
215
|
-
i++;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
return n;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
function CellCoords(coords) {
|
|
222
|
-
// Examples: "AA2091", "R988", "B1"
|
|
223
|
-
coords = coords.split(/(\d+)/);
|
|
224
|
-
return [// Row.
|
|
225
|
-
parseInt(coords[1]), // Column.
|
|
226
|
-
colToInt(coords[0].trim())];
|
|
227
|
-
} // Example of a `<c/>`ell element:
|
|
228
|
-
//
|
|
229
|
-
// <c>
|
|
230
|
-
// <f>string</f> — formula.
|
|
231
|
-
// <v>string</v> — formula pre-computed value.
|
|
232
|
-
// <is>
|
|
233
|
-
// <t>string</t> — an `inlineStr` string (rather than a "common string" from a dictionary).
|
|
234
|
-
// <r>
|
|
235
|
-
// <rPr>
|
|
236
|
-
// ...
|
|
237
|
-
// </rPr>
|
|
238
|
-
// <t>string</t>
|
|
239
|
-
// </r>
|
|
240
|
-
// <rPh sb="1" eb="1">
|
|
241
|
-
// <t>string</t>
|
|
242
|
-
// </rPh>
|
|
243
|
-
// <phoneticPr fontId="1"/>
|
|
244
|
-
// </is>
|
|
245
|
-
// <extLst>
|
|
246
|
-
// <ext>
|
|
247
|
-
// <!--any element-->
|
|
248
|
-
// </ext>
|
|
249
|
-
// </extLst>
|
|
250
|
-
// </c>
|
|
251
|
-
//
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
function Cell(cellNode, sheet, xml, values, styles, properties, options) {
|
|
255
|
-
var coords = CellCoords(cellNode.getAttribute('r'));
|
|
256
|
-
var valueElement = (0, _xlsx.getCellValue)(sheet, cellNode); // For `xpath`, `value` can be `undefined` while for native `DOMParser` it's `null`.
|
|
257
|
-
// So using `value && ...` instead of `if (value !== undefined) { ... }` here
|
|
258
|
-
// for uniform compatibility with both `xpath` and native `DOMParser`.
|
|
259
|
-
|
|
260
|
-
var value = valueElement && valueElement.textContent;
|
|
261
|
-
var type;
|
|
262
|
-
|
|
263
|
-
if (cellNode.hasAttribute('t')) {
|
|
264
|
-
type = cellNode.getAttribute('t');
|
|
265
|
-
} else {
|
|
266
|
-
// Default cell type is "n" (numeric).
|
|
267
|
-
// http://www.datypic.com/sc/ooxml/t-ssml_CT_Cell.html
|
|
268
|
-
type = 'n';
|
|
269
|
-
} // Available Excel cell types:
|
|
270
|
-
// https://github.com/SheetJS/sheetjs/blob/19620da30be2a7d7b9801938a0b9b1fd3c4c4b00/docbits/52_datatype.md
|
|
271
|
-
//
|
|
272
|
-
// Some other document (seems to be old):
|
|
273
|
-
// http://webapp.docx4java.org/OnlineDemo/ecma376/SpreadsheetML/ST_CellType.html
|
|
274
|
-
//
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
switch (type) {
|
|
278
|
-
// If the cell contains formula string.
|
|
279
|
-
case 'str':
|
|
280
|
-
value = value.trim();
|
|
281
|
-
|
|
282
|
-
if (value === '') {
|
|
283
|
-
value = undefined;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
break;
|
|
287
|
-
// If the cell contains an "inline" (not "shared") string.
|
|
288
|
-
|
|
289
|
-
case 'inlineStr':
|
|
290
|
-
if (cellNode.firstChild && cellNode.firstChild.tagName === 'is' && cellNode.firstChild.firstChild && cellNode.firstChild.firstChild.tagName === 't') {
|
|
291
|
-
value = cellNode.firstChild.firstChild.textContent;
|
|
292
|
-
} else {
|
|
293
|
-
throw new Error("Unsupported \"inline string\" cell value structure: ".concat(cellNode.textContent));
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
value = value.trim();
|
|
297
|
-
|
|
298
|
-
if (value === '') {
|
|
299
|
-
value = undefined;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
break;
|
|
303
|
-
// If the cell contains a "shared" string.
|
|
304
|
-
// "Shared" strings is a way for an Excel editor to reduce
|
|
305
|
-
// the file size by storing "commonly used" strings in a dictionary
|
|
306
|
-
// and then referring to such strings by their index in that dictionary.
|
|
307
|
-
|
|
308
|
-
case 's':
|
|
309
|
-
// If a cell has no value then there's no `<c/>` element for it.
|
|
310
|
-
// If a `<c/>` element exists then it's not empty.
|
|
311
|
-
// The `<v/>`alue is a key in the "shared strings" dictionary of the
|
|
312
|
-
// XLSX file, so look it up in the `values` dictionary by the numeric key.
|
|
313
|
-
value = values[parseInt(value)];
|
|
314
|
-
value = value.trim();
|
|
315
|
-
|
|
316
|
-
if (value === '') {
|
|
317
|
-
value = undefined;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
break;
|
|
321
|
-
|
|
322
|
-
case 'b':
|
|
323
|
-
value = value === '1' ? true : false;
|
|
324
|
-
break;
|
|
325
|
-
// Stub: blank stub cell that is ignored by data processing utilities.
|
|
326
|
-
|
|
327
|
-
case 'z':
|
|
328
|
-
value = undefined;
|
|
329
|
-
break;
|
|
330
|
-
// Error: `value` is a numeric code.
|
|
331
|
-
// They also wrote: "and `w` property stores its common name".
|
|
332
|
-
// It's unclear what they meant by that.
|
|
333
|
-
|
|
334
|
-
case 'e':
|
|
335
|
-
value = decodeError(value);
|
|
336
|
-
break;
|
|
337
|
-
// Date: a string to be parsed as a date.
|
|
338
|
-
// (usually a string in "ISO 8601" format)
|
|
339
|
-
|
|
340
|
-
case 'd':
|
|
341
|
-
if (value === undefined) {
|
|
342
|
-
break;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
value = new Date(value);
|
|
346
|
-
break;
|
|
347
|
-
|
|
348
|
-
case 'n':
|
|
349
|
-
if (value === undefined) {
|
|
350
|
-
break;
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
value = parseFloat(value); // XLSX does have "d" type for dates, but it's not commonly used.
|
|
354
|
-
// specific format for dates.
|
|
355
|
-
// Sometimes a date can be heuristically detected.
|
|
356
|
-
// https://github.com/catamphetamine/read-excel-file/issues/3#issuecomment-395770777
|
|
357
|
-
//
|
|
358
|
-
// Format IDs:
|
|
359
|
-
// https://xlsxwriter.readthedocs.io/format.html#format-set-num-format
|
|
360
|
-
//
|
|
361
|
-
|
|
362
|
-
if (cellNode.hasAttribute('s')) {
|
|
363
|
-
var styleId = parseInt(cellNode.getAttribute('s'));
|
|
364
|
-
var style = styles[styleId];
|
|
365
|
-
|
|
366
|
-
if (!style) {
|
|
367
|
-
throw new Error("Cell style not found: ".concat(styleId));
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
if (BUILT_IN_DATE_NUMBER_FORMAT_IDS.indexOf(parseInt(style.numberFormat.id)) >= 0 || options.dateFormat && style.numberFormat.template === options.dateFormat || options.smartDateParser !== false && style.numberFormat.template && isDateTemplate(style.numberFormat.template)) {
|
|
371
|
-
value = (0, _parseDate["default"])(value, properties);
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
break;
|
|
376
|
-
|
|
377
|
-
default:
|
|
378
|
-
throw new TypeError("Cell type not supported: ".concat(type));
|
|
379
|
-
} // Convert empty values to `null`.
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
if (value === undefined) {
|
|
383
|
-
value = null;
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
return {
|
|
387
|
-
row: coords[0],
|
|
388
|
-
column: coords[1],
|
|
389
|
-
value: value
|
|
390
|
-
};
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
function dropEmptyRows(data) {
|
|
394
|
-
var _ref2 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
|
|
395
|
-
rowMap = _ref2.rowMap,
|
|
396
|
-
_ref2$accessor = _ref2.accessor,
|
|
397
|
-
accessor = _ref2$accessor === void 0 ? function (_) {
|
|
398
|
-
return _;
|
|
399
|
-
} : _ref2$accessor,
|
|
400
|
-
onlyTrimAtTheEnd = _ref2.onlyTrimAtTheEnd;
|
|
401
|
-
|
|
402
|
-
// Drop empty rows.
|
|
403
|
-
var i = data.length - 1;
|
|
404
|
-
|
|
405
|
-
while (i >= 0) {
|
|
406
|
-
// Check if the row is empty.
|
|
407
|
-
var empty = true;
|
|
408
|
-
|
|
409
|
-
for (var _iterator3 = _createForOfIteratorHelperLoose(data[i]), _step3; !(_step3 = _iterator3()).done;) {
|
|
410
|
-
var cell = _step3.value;
|
|
411
|
-
|
|
412
|
-
if (accessor(cell) !== null) {
|
|
413
|
-
empty = false;
|
|
414
|
-
break;
|
|
415
|
-
}
|
|
416
|
-
} // Remove the empty row.
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
if (empty) {
|
|
420
|
-
data.splice(i, 1);
|
|
421
|
-
|
|
422
|
-
if (rowMap) {
|
|
423
|
-
rowMap.splice(i, 1);
|
|
424
|
-
}
|
|
425
|
-
} else if (onlyTrimAtTheEnd) {
|
|
426
|
-
break;
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
i--;
|
|
430
|
-
}
|
|
431
93
|
|
|
432
94
|
return data;
|
|
433
95
|
}
|
|
434
96
|
|
|
435
|
-
function
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
return _;
|
|
440
|
-
} : _ref3$accessor,
|
|
441
|
-
onlyTrimAtTheEnd = _ref3.onlyTrimAtTheEnd;
|
|
442
|
-
|
|
443
|
-
var i = data[0].length - 1;
|
|
444
|
-
|
|
445
|
-
while (i >= 0) {
|
|
446
|
-
var empty = true;
|
|
447
|
-
|
|
448
|
-
for (var _iterator4 = _createForOfIteratorHelperLoose(data), _step4; !(_step4 = _iterator4()).done;) {
|
|
449
|
-
var row = _step4.value;
|
|
450
|
-
|
|
451
|
-
if (accessor(row[i]) !== null) {
|
|
452
|
-
empty = false;
|
|
453
|
-
break;
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
if (empty) {
|
|
458
|
-
var j = 0;
|
|
459
|
-
|
|
460
|
-
while (j < data.length) {
|
|
461
|
-
data[j].splice(i, 1);
|
|
462
|
-
j++;
|
|
463
|
-
}
|
|
464
|
-
} else if (onlyTrimAtTheEnd) {
|
|
465
|
-
break;
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
i--;
|
|
97
|
+
function getSheetId(sheet, sheets) {
|
|
98
|
+
if (typeof sheet === 'number') {
|
|
99
|
+
var _sheet = sheets[sheet - 1];
|
|
100
|
+
return _sheet && _sheet.relationId;
|
|
469
101
|
}
|
|
470
102
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
function parseSheet(content, xml, values, styles, properties, options) {
|
|
475
|
-
var sheet = xml.createDocument(content);
|
|
476
|
-
var cells = (0, _xlsx.getCells)(sheet);
|
|
477
|
-
|
|
478
|
-
if (cells.length === 0) {
|
|
479
|
-
return {
|
|
480
|
-
cells: []
|
|
481
|
-
};
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
cells = cells.map(function (node) {
|
|
485
|
-
return Cell(node, sheet, xml, values, styles, properties, options);
|
|
486
|
-
});
|
|
487
|
-
var dimensions = (0, _xlsx.getDimensions)(sheet);
|
|
488
|
-
|
|
489
|
-
if (dimensions) {
|
|
490
|
-
dimensions = dimensions.split(':').map(CellCoords).map(function (_ref4) {
|
|
491
|
-
var _ref5 = _slicedToArray(_ref4, 2),
|
|
492
|
-
row = _ref5[0],
|
|
493
|
-
column = _ref5[1];
|
|
494
|
-
|
|
495
|
-
return {
|
|
496
|
-
row: row,
|
|
497
|
-
column: column
|
|
498
|
-
};
|
|
499
|
-
}); // When there's only a single cell on a sheet
|
|
500
|
-
// there can sometimes be just "A1" for the dimensions string.
|
|
501
|
-
|
|
502
|
-
if (dimensions.length === 1) {
|
|
503
|
-
dimensions = [dimensions[0], dimensions[0]];
|
|
504
|
-
}
|
|
505
|
-
} else {
|
|
506
|
-
dimensions = calculateDimensions(cells);
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
return {
|
|
510
|
-
cells: cells,
|
|
511
|
-
dimensions: dimensions
|
|
512
|
-
};
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
function parseValues(content, xml) {
|
|
516
|
-
if (!content) {
|
|
517
|
-
return [];
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
return (0, _xlsx.getSharedStrings)(xml.createDocument(content));
|
|
521
|
-
} // http://officeopenxml.com/SSstyles.php
|
|
522
|
-
// Returns an array of cell styles.
|
|
523
|
-
// A cell style index is its ID.
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
function parseStyles(content, xml) {
|
|
527
|
-
if (!content) {
|
|
528
|
-
return {};
|
|
529
|
-
} // 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
|
|
530
|
-
// https://www.office-forums.com/threads/cellxfs-cellstylexfs.2163519/
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
var doc = xml.createDocument(content);
|
|
534
|
-
var baseStyles = (0, _xlsx.getBaseStyles)(doc).map(parseCellStyle);
|
|
535
|
-
var numberFormats = (0, _xlsx.getNumberFormats)(doc).map(parseNumberFormatStyle).reduce(function (formats, format) {
|
|
536
|
-
// Format ID is a numeric index.
|
|
537
|
-
// There're some standard "built-in" formats (in Excel) up to about `100`.
|
|
538
|
-
formats[format.id] = format;
|
|
539
|
-
return formats;
|
|
540
|
-
}, []);
|
|
541
|
-
|
|
542
|
-
var getCellStyle = function getCellStyle(xf) {
|
|
543
|
-
if (xf.hasAttribute('xfId')) {
|
|
544
|
-
return _objectSpread(_objectSpread({}, baseStyles[xf.xfId]), parseCellStyle(xf, numberFormats));
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
return parseCellStyle(xf, numberFormats);
|
|
548
|
-
};
|
|
549
|
-
|
|
550
|
-
return (0, _xlsx.getCellStyles)(doc).map(getCellStyle);
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
function parseNumberFormatStyle(numFmt) {
|
|
554
|
-
return {
|
|
555
|
-
id: numFmt.getAttribute('numFmtId'),
|
|
556
|
-
template: numFmt.getAttribute('formatCode')
|
|
557
|
-
};
|
|
558
|
-
} // http://www.datypic.com/sc/ooxml/e-ssml_xf-2.html
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
function parseCellStyle(xf, numFmts) {
|
|
562
|
-
var style = {};
|
|
563
|
-
|
|
564
|
-
if (xf.hasAttribute('numFmtId')) {
|
|
565
|
-
var numberFormatId = xf.getAttribute('numFmtId'); // Built-in number formats don't have a `<numFmt/>` element in `styles.xml`.
|
|
566
|
-
// https://hexdocs.pm/xlsxir/number_styles.html
|
|
103
|
+
for (var _iterator = _createForOfIteratorHelperLoose(sheets), _step; !(_step = _iterator()).done;) {
|
|
104
|
+
var _sheet2 = _step.value;
|
|
567
105
|
|
|
568
|
-
if (
|
|
569
|
-
|
|
570
|
-
} else {
|
|
571
|
-
style.numberFormat = {
|
|
572
|
-
id: numberFormatId
|
|
573
|
-
};
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
return style;
|
|
578
|
-
} // I guess `xl/workbook.xml` file should always be present inside the *.xlsx archive.
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
function parseProperties(content, xml) {
|
|
582
|
-
var book = xml.createDocument(content);
|
|
583
|
-
var properties = {}; // Read `<workbookPr/>` element to detect whether dates are 1900-based or 1904-based.
|
|
584
|
-
// https://support.microsoft.com/en-gb/help/214330/differences-between-the-1900-and-the-1904-date-system-in-excel
|
|
585
|
-
// http://webapp.docx4java.org/OnlineDemo/ecma376/SpreadsheetML/workbookPr.html
|
|
586
|
-
|
|
587
|
-
var workbookProperties = (0, _xlsx.getWorkbookProperties)(book);
|
|
588
|
-
|
|
589
|
-
if (workbookProperties && workbookProperties.getAttribute('date1904') === '1') {
|
|
590
|
-
properties.epoch1904 = true;
|
|
591
|
-
} // Get sheets info (indexes, names, if they're available).
|
|
592
|
-
// Example:
|
|
593
|
-
// <sheets>
|
|
594
|
-
// <sheet
|
|
595
|
-
// xmlns:ns="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
|
|
596
|
-
// name="Sheet1"
|
|
597
|
-
// sheetId="1"
|
|
598
|
-
// ns:id="rId3"/>
|
|
599
|
-
// </sheets>
|
|
600
|
-
// http://www.datypic.com/sc/ooxml/e-ssml_sheet-1.html
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
properties.sheets = [];
|
|
604
|
-
|
|
605
|
-
var addSheetInfo = function addSheetInfo(sheet) {
|
|
606
|
-
if (sheet.getAttribute('name')) {
|
|
607
|
-
properties.sheets.push({
|
|
608
|
-
id: sheet.getAttribute('sheetId'),
|
|
609
|
-
name: sheet.getAttribute('name'),
|
|
610
|
-
relationId: sheet.getAttribute('r:id')
|
|
611
|
-
});
|
|
612
|
-
}
|
|
613
|
-
};
|
|
614
|
-
|
|
615
|
-
(0, _xlsx.getSheets)(book).forEach(addSheetInfo);
|
|
616
|
-
return properties;
|
|
617
|
-
}
|
|
618
|
-
/**
|
|
619
|
-
* Returns sheet file paths.
|
|
620
|
-
* Seems that the correct place to look for the `sheetId` -> `filename` mapping
|
|
621
|
-
* is `xl/_rels/workbook.xml.rels` file.
|
|
622
|
-
* https://github.com/tidyverse/readxl/issues/104
|
|
623
|
-
* @param {string} content — `xl/_rels/workbook.xml.rels` file contents.
|
|
624
|
-
* @param {object} xml
|
|
625
|
-
* @return {object}
|
|
626
|
-
*/
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
function parseFilePaths(content, xml) {
|
|
630
|
-
// Example:
|
|
631
|
-
// <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
|
|
632
|
-
// ...
|
|
633
|
-
// <Relationship
|
|
634
|
-
// Id="rId3"
|
|
635
|
-
// Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet"
|
|
636
|
-
// Target="worksheets/sheet1.xml"/>
|
|
637
|
-
// </Relationships>
|
|
638
|
-
var document = xml.createDocument(content);
|
|
639
|
-
var filePaths = {
|
|
640
|
-
sheets: {},
|
|
641
|
-
sharedStrings: undefined,
|
|
642
|
-
styles: undefined
|
|
643
|
-
};
|
|
644
|
-
|
|
645
|
-
var addFilePathInfo = function addFilePathInfo(relationship) {
|
|
646
|
-
var filePath = relationship.getAttribute('Target');
|
|
647
|
-
var fileType = relationship.getAttribute('Type');
|
|
648
|
-
|
|
649
|
-
switch (fileType) {
|
|
650
|
-
case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles':
|
|
651
|
-
filePaths.styles = getFilePath(filePath);
|
|
652
|
-
break;
|
|
653
|
-
|
|
654
|
-
case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings':
|
|
655
|
-
filePaths.sharedStrings = getFilePath(filePath);
|
|
656
|
-
break;
|
|
657
|
-
|
|
658
|
-
case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet':
|
|
659
|
-
filePaths.sheets[relationship.getAttribute('Id')] = getFilePath(filePath);
|
|
660
|
-
break;
|
|
661
|
-
}
|
|
662
|
-
};
|
|
663
|
-
|
|
664
|
-
(0, _xlsx.getRelationships)(document).forEach(addFilePathInfo); // Seems like "sharedStrings.xml" is not required to exist.
|
|
665
|
-
// For example, when the spreadsheet doesn't contain any strings.
|
|
666
|
-
// https://github.com/catamphetamine/read-excel-file/issues/85
|
|
667
|
-
// if (!filePaths.sharedStrings) {
|
|
668
|
-
// throw new Error('"sharedStrings.xml" file not found in the *.xlsx file')
|
|
669
|
-
// }
|
|
670
|
-
|
|
671
|
-
return filePaths;
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
function getFilePath(path) {
|
|
675
|
-
// Normally, `path` is a relative path inside the ZIP archive,
|
|
676
|
-
// like "worksheets/sheet1.xml", or "sharedStrings.xml", or "styles.xml".
|
|
677
|
-
// There has been one weird case when file path was an absolute path,
|
|
678
|
-
// like "/xl/worksheets/sheet1.xml" (specifically for sheets):
|
|
679
|
-
// https://github.com/catamphetamine/read-excel-file/pull/95
|
|
680
|
-
// Other libraries (like `xlsx`) and software (like Google Docs)
|
|
681
|
-
// seem to support such absolute file paths, so this library does too.
|
|
682
|
-
if (path[0] === '/') {
|
|
683
|
-
return path.slice('/'.length);
|
|
684
|
-
} // // Seems like a path could also be a URL.
|
|
685
|
-
// // http://officeopenxml.com/anatomyofOOXML-xlsx.php
|
|
686
|
-
// if (/^[a-z]+\:\/\//.test(path)) {
|
|
687
|
-
// return path
|
|
688
|
-
// }
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
return 'xl/' + path;
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
function isDateTemplate(template) {
|
|
695
|
-
var tokens = template.split(/\W+/);
|
|
696
|
-
|
|
697
|
-
for (var _iterator5 = _createForOfIteratorHelperLoose(tokens), _step5; !(_step5 = _iterator5()).done;) {
|
|
698
|
-
var token = _step5.value;
|
|
699
|
-
|
|
700
|
-
if (['MM', 'DD', 'YY', 'YYYY'].indexOf(token) < 0) {
|
|
701
|
-
return false;
|
|
106
|
+
if (_sheet2.name === sheet) {
|
|
107
|
+
return _sheet2.relationId;
|
|
702
108
|
}
|
|
703
109
|
}
|
|
704
|
-
|
|
705
|
-
return true;
|
|
706
110
|
}
|
|
707
111
|
|
|
708
112
|
function createSheetNotFoundError(sheet, sheets) {
|
|
@@ -710,41 +114,5 @@ function createSheetNotFoundError(sheet, sheets) {
|
|
|
710
114
|
return "\"".concat(sheet.name, "\" (#").concat(i + 1, ")");
|
|
711
115
|
}).join(', ');
|
|
712
116
|
return new Error("Sheet ".concat(typeof sheet === 'number' ? '#' + sheet : '"' + sheet + '"', " not found in the *.xlsx file.").concat(sheets ? ' Available sheets: ' + sheetsList + '.' : ''));
|
|
713
|
-
} // Decodes numeric error code to a string code.
|
|
714
|
-
// https://github.com/SheetJS/sheetjs/blob/19620da30be2a7d7b9801938a0b9b1fd3c4c4b00/docbits/52_datatype.md
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
function decodeError(errorCode) {
|
|
718
|
-
// While the error values are determined by the application,
|
|
719
|
-
// the following are some example error values that could be used:
|
|
720
|
-
switch (errorCode) {
|
|
721
|
-
case 0x00:
|
|
722
|
-
return '#NULL!';
|
|
723
|
-
|
|
724
|
-
case 0x07:
|
|
725
|
-
return '#DIV/0!';
|
|
726
|
-
|
|
727
|
-
case 0x0F:
|
|
728
|
-
return '#VALUE!';
|
|
729
|
-
|
|
730
|
-
case 0x17:
|
|
731
|
-
return '#REF!';
|
|
732
|
-
|
|
733
|
-
case 0x1D:
|
|
734
|
-
return '#NAME?';
|
|
735
|
-
|
|
736
|
-
case 0x24:
|
|
737
|
-
return '#NUM!';
|
|
738
|
-
|
|
739
|
-
case 0x2A:
|
|
740
|
-
return '#N/A';
|
|
741
|
-
|
|
742
|
-
case 0x2B:
|
|
743
|
-
return '#GETTING_DATA';
|
|
744
|
-
|
|
745
|
-
default:
|
|
746
|
-
// Such error code doesn't exist. I made it up.
|
|
747
|
-
return "#ERROR_".concat(errorCode);
|
|
748
|
-
}
|
|
749
117
|
}
|
|
750
118
|
//# sourceMappingURL=readXlsx.js.map
|