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