read-excel-file 7.0.3 → 8.0.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.
Files changed (265) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/README.md +212 -205
  3. package/browser/index.cjs +8 -5
  4. package/browser/index.d.ts +58 -16
  5. package/browser/index.js +7 -5
  6. package/browser/input.d.ts +1 -0
  7. package/bundle/read-excel-file.min.js +1 -1
  8. package/bundle/read-excel-file.min.js.map +1 -1
  9. package/commonjs/export/parseSheet.js +20 -0
  10. package/commonjs/export/parseSheet.js.map +1 -0
  11. package/commonjs/export/readSheetBrowser.js +29 -0
  12. package/commonjs/export/readSheetBrowser.js.map +1 -0
  13. package/commonjs/export/readSheetNode.js +29 -0
  14. package/commonjs/export/readSheetNode.js.map +1 -0
  15. package/commonjs/export/readSheetUniversal.js +29 -0
  16. package/commonjs/export/readSheetUniversal.js.map +1 -0
  17. package/commonjs/export/readSheetWebWorker.js +29 -0
  18. package/commonjs/export/readSheetWebWorker.js.map +1 -0
  19. package/commonjs/export/readXlsxFileBrowser.js +6 -8
  20. package/commonjs/export/readXlsxFileBrowser.js.map +1 -1
  21. package/commonjs/export/readXlsxFileNode.js +7 -9
  22. package/commonjs/export/readXlsxFileNode.js.map +1 -1
  23. package/commonjs/export/readXlsxFileUniversal.js +7 -9
  24. package/commonjs/export/readXlsxFileUniversal.js.map +1 -1
  25. package/commonjs/export/readXlsxFileWebWorker.js +6 -8
  26. package/commonjs/export/readXlsxFileWebWorker.js.map +1 -1
  27. package/commonjs/export/unpackXlsxFileBrowser.js +2 -1
  28. package/commonjs/export/unpackXlsxFileBrowser.js.map +1 -1
  29. package/commonjs/export/unpackXlsxFileNode.js +4 -3
  30. package/commonjs/export/unpackXlsxFileNode.js.map +1 -1
  31. package/commonjs/export/unpackXlsxFileUniversal.js +13 -3
  32. package/commonjs/export/unpackXlsxFileUniversal.js.map +1 -1
  33. package/commonjs/parseData/InvalidError.js.map +1 -0
  34. package/commonjs/parseData/parseData.js +503 -0
  35. package/commonjs/parseData/parseData.js.map +1 -0
  36. package/commonjs/parseData/parseData.test.js.map +1 -0
  37. package/commonjs/{types → parseData/types}/Boolean.js +1 -1
  38. package/commonjs/parseData/types/Boolean.js.map +1 -0
  39. package/commonjs/parseData/types/Date.js +21 -0
  40. package/commonjs/parseData/types/Date.js.map +1 -0
  41. package/commonjs/{types → parseData/types}/Number.js +1 -1
  42. package/commonjs/parseData/types/Number.js.map +1 -0
  43. package/commonjs/{types → parseData/types}/String.js +1 -1
  44. package/commonjs/parseData/types/String.js.map +1 -0
  45. package/commonjs/{types → parseData/types/additional}/Email.js +3 -3
  46. package/commonjs/parseData/types/additional/Email.js.map +1 -0
  47. package/commonjs/parseData/types/additional/Email.test.js.map +1 -0
  48. package/commonjs/{types → parseData/types/additional}/Integer.js +2 -2
  49. package/commonjs/parseData/types/additional/Integer.js.map +1 -0
  50. package/commonjs/parseData/types/additional/Integer.test.js.map +1 -0
  51. package/commonjs/{types → parseData/types/additional}/URL.js +3 -3
  52. package/commonjs/parseData/types/additional/URL.js.map +1 -0
  53. package/commonjs/parseData/types/additional/URL.test.js.map +1 -0
  54. package/commonjs/xlsx/{getData.js → convertCellsToData2dArray.js} +16 -37
  55. package/commonjs/xlsx/convertCellsToData2dArray.js.map +1 -0
  56. package/commonjs/xlsx/{isDateTimestamp.js → isDateFormat.js} +58 -56
  57. package/commonjs/xlsx/isDateFormat.js.map +1 -0
  58. package/commonjs/xlsx/isDateFormat.test.js.map +1 -0
  59. package/commonjs/xlsx/isDateFormatStyle.js +193 -0
  60. package/commonjs/xlsx/isDateFormatStyle.js.map +1 -0
  61. package/commonjs/xlsx/parseCell.js +16 -18
  62. package/commonjs/xlsx/parseCell.js.map +1 -1
  63. package/commonjs/xlsx/parseCellCoordinates.js +44 -0
  64. package/commonjs/xlsx/parseCellCoordinates.js.map +1 -0
  65. package/commonjs/xlsx/parseCellValue.js +14 -11
  66. package/commonjs/xlsx/parseCellValue.js.map +1 -1
  67. package/commonjs/xlsx/parseCells.js +14 -6
  68. package/commonjs/xlsx/parseCells.js.map +1 -1
  69. package/commonjs/xlsx/parseExcelDate.js +139 -0
  70. package/commonjs/xlsx/parseExcelDate.js.map +1 -0
  71. package/commonjs/xlsx/parseExcelDate.test.js.map +1 -0
  72. package/commonjs/xlsx/parseSheet.js +9 -11
  73. package/commonjs/xlsx/parseSheet.js.map +1 -1
  74. package/commonjs/xlsx/{parseDimensions.js → parseSheetDimensions.js} +7 -6
  75. package/commonjs/xlsx/parseSheetDimensions.js.map +1 -0
  76. package/commonjs/xlsx/parseSpreadsheetContents.js +96 -0
  77. package/commonjs/xlsx/parseSpreadsheetContents.js.map +1 -0
  78. package/commonjs/xlsx/parseSpreadsheetInfo.js +47 -0
  79. package/commonjs/xlsx/parseSpreadsheetInfo.js.map +1 -0
  80. package/commonjs/xlsx/reconstructSheetDimensionsFromSheetCells.js +29 -0
  81. package/commonjs/xlsx/reconstructSheetDimensionsFromSheetCells.js.map +1 -0
  82. package/commonjs/xml/xlsx.js +9 -9
  83. package/commonjs/xml/xlsx.js.map +1 -1
  84. package/commonjs/xml/xpath/xlsx-xpath.js +8 -8
  85. package/commonjs/xml/xpath/xlsx-xpath.js.map +1 -1
  86. package/commonjs/xml/xpath/xpathBrowser.js +4 -4
  87. package/commonjs/xml/xpath/xpathBrowser.js.map +1 -1
  88. package/commonjs/xml/xpath/xpathNode.js +2 -2
  89. package/commonjs/xml/xpath/xpathNode.js.map +1 -1
  90. package/modules/export/parseSheet.js +13 -0
  91. package/modules/export/parseSheet.js.map +1 -0
  92. package/modules/export/readSheetBrowser.js +23 -0
  93. package/modules/export/readSheetBrowser.js.map +1 -0
  94. package/modules/export/readSheetNode.js +23 -0
  95. package/modules/export/readSheetNode.js.map +1 -0
  96. package/modules/export/readSheetUniversal.js +23 -0
  97. package/modules/export/readSheetUniversal.js.map +1 -0
  98. package/modules/export/readSheetWebWorker.js +23 -0
  99. package/modules/export/readSheetWebWorker.js.map +1 -0
  100. package/modules/export/readXlsxFileBrowser.js +6 -8
  101. package/modules/export/readXlsxFileBrowser.js.map +1 -1
  102. package/modules/export/readXlsxFileNode.js +7 -9
  103. package/modules/export/readXlsxFileNode.js.map +1 -1
  104. package/modules/export/readXlsxFileUniversal.js +7 -9
  105. package/modules/export/readXlsxFileUniversal.js.map +1 -1
  106. package/modules/export/readXlsxFileWebWorker.js +6 -8
  107. package/modules/export/readXlsxFileWebWorker.js.map +1 -1
  108. package/modules/export/unpackXlsxFileBrowser.js +3 -1
  109. package/modules/export/unpackXlsxFileBrowser.js.map +1 -1
  110. package/modules/export/unpackXlsxFileNode.js +4 -3
  111. package/modules/export/unpackXlsxFileNode.js.map +1 -1
  112. package/modules/export/unpackXlsxFileUniversal.js +13 -3
  113. package/modules/export/unpackXlsxFileUniversal.js.map +1 -1
  114. package/modules/parseData/InvalidError.js.map +1 -0
  115. package/modules/parseData/parseData.js +494 -0
  116. package/modules/parseData/parseData.js.map +1 -0
  117. package/modules/parseData/parseData.test.js.map +1 -0
  118. package/modules/{types → parseData/types}/Boolean.js +1 -1
  119. package/modules/parseData/types/Boolean.js.map +1 -0
  120. package/modules/parseData/types/Date.js +14 -0
  121. package/modules/parseData/types/Date.js.map +1 -0
  122. package/modules/{types → parseData/types}/Number.js +1 -1
  123. package/modules/parseData/types/Number.js.map +1 -0
  124. package/modules/{types → parseData/types}/String.js +1 -1
  125. package/modules/parseData/types/String.js.map +1 -0
  126. package/modules/{types → parseData/types/additional}/Email.js +3 -3
  127. package/modules/parseData/types/additional/Email.js.map +1 -0
  128. package/modules/parseData/types/additional/Email.test.js.map +1 -0
  129. package/modules/{types → parseData/types/additional}/Integer.js +2 -2
  130. package/modules/parseData/types/additional/Integer.js.map +1 -0
  131. package/modules/parseData/types/additional/Integer.test.js.map +1 -0
  132. package/modules/{types → parseData/types/additional}/URL.js +3 -3
  133. package/modules/parseData/types/additional/URL.js.map +1 -0
  134. package/modules/parseData/types/additional/URL.test.js.map +1 -0
  135. package/modules/xlsx/{getData.js → convertCellsToData2dArray.js} +15 -36
  136. package/modules/xlsx/convertCellsToData2dArray.js.map +1 -0
  137. package/modules/xlsx/{isDateTimestamp.js → isDateFormat.js} +57 -55
  138. package/modules/xlsx/isDateFormat.js.map +1 -0
  139. package/modules/xlsx/isDateFormat.test.js.map +1 -0
  140. package/modules/xlsx/isDateFormatStyle.js +186 -0
  141. package/modules/xlsx/isDateFormatStyle.js.map +1 -0
  142. package/modules/xlsx/parseCell.js +17 -19
  143. package/modules/xlsx/parseCell.js.map +1 -1
  144. package/modules/xlsx/parseCellCoordinates.js +38 -0
  145. package/modules/xlsx/parseCellCoordinates.js.map +1 -0
  146. package/modules/xlsx/parseCellValue.js +14 -11
  147. package/modules/xlsx/parseCellValue.js.map +1 -1
  148. package/modules/xlsx/parseCells.js +14 -6
  149. package/modules/xlsx/parseCells.js.map +1 -1
  150. package/modules/xlsx/parseExcelDate.js +133 -0
  151. package/modules/xlsx/parseExcelDate.js.map +1 -0
  152. package/modules/xlsx/parseExcelDate.test.js.map +1 -0
  153. package/modules/xlsx/parseSheet.js +9 -11
  154. package/modules/xlsx/parseSheet.js.map +1 -1
  155. package/modules/xlsx/{parseDimensions.js → parseSheetDimensions.js} +4 -4
  156. package/modules/xlsx/parseSheetDimensions.js.map +1 -0
  157. package/modules/xlsx/parseSpreadsheetContents.js +91 -0
  158. package/modules/xlsx/parseSpreadsheetContents.js.map +1 -0
  159. package/modules/xlsx/parseSpreadsheetInfo.js +42 -0
  160. package/modules/xlsx/parseSpreadsheetInfo.js.map +1 -0
  161. package/modules/xlsx/reconstructSheetDimensionsFromSheetCells.js +23 -0
  162. package/modules/xlsx/reconstructSheetDimensionsFromSheetCells.js.map +1 -0
  163. package/modules/xml/xlsx.js +6 -6
  164. package/modules/xml/xlsx.js.map +1 -1
  165. package/modules/xml/xpath/xlsx-xpath.js +6 -6
  166. package/modules/xml/xpath/xlsx-xpath.js.map +1 -1
  167. package/modules/xml/xpath/xpathBrowser.js +4 -4
  168. package/modules/xml/xpath/xpathBrowser.js.map +1 -1
  169. package/modules/xml/xpath/xpathNode.js +2 -2
  170. package/modules/xml/xpath/xpathNode.js.map +1 -1
  171. package/node/index.cjs +8 -5
  172. package/node/index.d.ts +56 -21
  173. package/node/index.js +7 -5
  174. package/node/input.d.ts +5 -0
  175. package/package.json +1 -1
  176. package/types/parseData/parseData.d.ts +38 -0
  177. package/types/parseData/parseDataError.d.ts +239 -0
  178. package/types/parseData/parseDataSchema.d.ts +48 -0
  179. package/types/parseData/parseDataValueType.d.ts +45 -0
  180. package/types/types.d.ts +20 -0
  181. package/universal/index.cjs +8 -5
  182. package/universal/index.d.ts +58 -16
  183. package/universal/index.js +7 -5
  184. package/universal/input.d.ts +1 -0
  185. package/web-worker/index.cjs +8 -5
  186. package/web-worker/index.d.ts +58 -16
  187. package/web-worker/index.js +7 -5
  188. package/web-worker/input.d.ts +1 -0
  189. package/commonjs/export/readSheetNamesBrowser.js +0 -23
  190. package/commonjs/export/readSheetNamesBrowser.js.map +0 -1
  191. package/commonjs/export/readSheetNamesNode.js +0 -23
  192. package/commonjs/export/readSheetNamesNode.js.map +0 -1
  193. package/commonjs/export/readSheetNamesUniversal.js +0 -23
  194. package/commonjs/export/readSheetNamesUniversal.js.map +0 -1
  195. package/commonjs/export/readSheetNamesWebWorker.js +0 -23
  196. package/commonjs/export/readSheetNamesWebWorker.js.map +0 -1
  197. package/commonjs/types/Boolean.js.map +0 -1
  198. package/commonjs/types/Date.js +0 -36
  199. package/commonjs/types/Date.js.map +0 -1
  200. package/commonjs/types/Email.js.map +0 -1
  201. package/commonjs/types/Email.test.js.map +0 -1
  202. package/commonjs/types/Integer.js.map +0 -1
  203. package/commonjs/types/Integer.test.js.map +0 -1
  204. package/commonjs/types/InvalidError.js.map +0 -1
  205. package/commonjs/types/Number.js.map +0 -1
  206. package/commonjs/types/String.js.map +0 -1
  207. package/commonjs/types/URL.js.map +0 -1
  208. package/commonjs/types/URL.test.js.map +0 -1
  209. package/commonjs/xlsx/coordinates.js +0 -55
  210. package/commonjs/xlsx/coordinates.js.map +0 -1
  211. package/commonjs/xlsx/getData.js.map +0 -1
  212. package/commonjs/xlsx/isDateTimestamp.js.map +0 -1
  213. package/commonjs/xlsx/parseDate.js +0 -73
  214. package/commonjs/xlsx/parseDate.js.map +0 -1
  215. package/commonjs/xlsx/parseDate.test.js.map +0 -1
  216. package/commonjs/xlsx/parseDimensions.js.map +0 -1
  217. package/commonjs/xlsx/parseProperties.js +0 -46
  218. package/commonjs/xlsx/parseProperties.js.map +0 -1
  219. package/commonjs/xlsx/parseXlsxFileContents.js +0 -119
  220. package/commonjs/xlsx/parseXlsxFileContents.js.map +0 -1
  221. package/commonjs/xlsx/parseXlsxFileContentsWithOptionalSchema.js +0 -45
  222. package/commonjs/xlsx/parseXlsxFileContentsWithOptionalSchema.js.map +0 -1
  223. package/commonjs/xlsx/schema/mapToObjects.js +0 -482
  224. package/commonjs/xlsx/schema/mapToObjects.js.map +0 -1
  225. package/commonjs/xlsx/schema/mapToObjects.test.js.map +0 -1
  226. package/modules/export/readSheetNamesBrowser.js +0 -17
  227. package/modules/export/readSheetNamesBrowser.js.map +0 -1
  228. package/modules/export/readSheetNamesNode.js +0 -17
  229. package/modules/export/readSheetNamesNode.js.map +0 -1
  230. package/modules/export/readSheetNamesUniversal.js +0 -17
  231. package/modules/export/readSheetNamesUniversal.js.map +0 -1
  232. package/modules/export/readSheetNamesWebWorker.js +0 -17
  233. package/modules/export/readSheetNamesWebWorker.js.map +0 -1
  234. package/modules/types/Boolean.js.map +0 -1
  235. package/modules/types/Date.js +0 -29
  236. package/modules/types/Date.js.map +0 -1
  237. package/modules/types/Email.js.map +0 -1
  238. package/modules/types/Email.test.js.map +0 -1
  239. package/modules/types/Integer.js.map +0 -1
  240. package/modules/types/Integer.test.js.map +0 -1
  241. package/modules/types/InvalidError.js.map +0 -1
  242. package/modules/types/Number.js.map +0 -1
  243. package/modules/types/String.js.map +0 -1
  244. package/modules/types/URL.js.map +0 -1
  245. package/modules/types/URL.test.js.map +0 -1
  246. package/modules/xlsx/coordinates.js +0 -48
  247. package/modules/xlsx/coordinates.js.map +0 -1
  248. package/modules/xlsx/getData.js.map +0 -1
  249. package/modules/xlsx/isDateTimestamp.js.map +0 -1
  250. package/modules/xlsx/parseDate.js +0 -67
  251. package/modules/xlsx/parseDate.js.map +0 -1
  252. package/modules/xlsx/parseDate.test.js.map +0 -1
  253. package/modules/xlsx/parseDimensions.js.map +0 -1
  254. package/modules/xlsx/parseProperties.js +0 -41
  255. package/modules/xlsx/parseProperties.js.map +0 -1
  256. package/modules/xlsx/parseXlsxFileContents.js +0 -114
  257. package/modules/xlsx/parseXlsxFileContents.js.map +0 -1
  258. package/modules/xlsx/parseXlsxFileContentsWithOptionalSchema.js +0 -39
  259. package/modules/xlsx/parseXlsxFileContentsWithOptionalSchema.js.map +0 -1
  260. package/modules/xlsx/schema/mapToObjects.js +0 -472
  261. package/modules/xlsx/schema/mapToObjects.js.map +0 -1
  262. package/modules/xlsx/schema/mapToObjects.test.js.map +0 -1
  263. package/types.d.ts +0 -121
  264. /package/commonjs/{types → parseData}/InvalidError.js +0 -0
  265. /package/modules/{types → parseData}/InvalidError.js +0 -0
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # `read-excel-file`
2
2
 
3
- Read `.xlsx` files in a web browser or in Node.js.
3
+ Read `.xlsx` files in a browser or in Node.js.
4
4
 
5
5
  It also supports parsing spreadsheet rows into JSON objects using a [schema](#schema).
6
6
 
@@ -8,9 +8,60 @@ It also supports parsing spreadsheet rows into JSON objects using a [schema](#sc
8
8
 
9
9
  Also check out [`write-excel-file`](https://www.npmjs.com/package/write-excel-file) for writing `.xlsx` files.
10
10
 
11
+ <details>
12
+ <summary>Migrating from <code>6.x</code> to <code>7.x</code></summary>
13
+
14
+ ######
15
+
16
+ * Renamed the default export `"read-excel-file"` to `"read-excel-file/browser"`, and it uses [Web Workers](https://developer.mozilla.org/docs/Web/API/Web_Workers_API/Using_web_workers) now.
17
+ * Old: `import readExcelFile from "read-excel-file"`
18
+ * New: `import readExcelFile from "read-excel-file/browser"`
19
+ * The minimum required Node.js version is 18.
20
+ </details>
21
+
22
+ <details>
23
+ <summary>Migrating from <code>7.x</code> to <code>8.x</code></summary>
24
+
25
+ ######
26
+
27
+ * Renamed the default exported function to a named exported function `readSheet`.
28
+ * Old: `import readExcelFile from "read-excel-file/browser"`
29
+ * New: `import { readSheet } from "read-excel-file/browser"`
30
+ * And same for other exports like `"read-excel-file/node"`, etc.
31
+ * The default exported function now returns all sheets in a form of an array of objects: `[{ sheet: "Sheet 1", data: [['a1','b1','c1'],['a2','b2','c2']] }, ...]`.
32
+ * Removed `getSheets: true` parameter. The default exported function now returns all sheets.
33
+ * Removed exported `readSheetNames()` function. The default exported function now returns all sheets.
34
+ * Removed `schema` parameter. Instead, use exported function `parseData(data, schema)` to map data to an array of objects.
35
+ * Old: `import readXlsxFile from "read-excel-file"` and then `const { rows, errors } = await readXlsxFile(..., { schema })`
36
+ * New: `import { readSheet, parseData } from "read-excel-file/browser"` and then `const result = parseData(await readSheet(...), schema)`
37
+ * The `result` of the function is an array where each element represents a "data row" and has shape `{ object, errors }`.
38
+ * Depending on whether there were any errors when parsing a given "data row", either `object` or `errors` property will be `undefined`.
39
+ * The `errors` don't have a `row` property anymore because it could be derived from "data row" number.
40
+ * Removed `transformData` parameter because `schema` parameter was removed. A developer could transform the `data` themself and then pass it to `parseData()` function.
41
+ * Removed `isColumnOriented` parameter.
42
+ * Removed `ignoreEmptyRows` parameter. Empty rows somewhere in the middle are not ignored now.
43
+ * Renamed some options that're used when parsing using a `schema`:
44
+ * `schemaPropertyValueForMissingColumn` → `propertyValueWhenColumnIsMissing`
45
+ * `schemaPropertyValueForMissingValue` → `propertyValueWhenCellIsEmpty`
46
+ * `schemaPropertyShouldSkipRequiredValidationForMissingColumn` → (removed)
47
+ * `getEmptyObjectValue` → `transformEmptyObject`
48
+ * The leading `.` character is now removed from the `path` parameter.
49
+ * `getEmptyArrayValue` → `transformEmptyArray`
50
+ * The leading `.` character is now removed from the `path` parameter.
51
+ * Previously, when parsing comma-separated values, it used to ignore any commas that're surrounded by quotes, similar to how it's done in `.csv` files. Now it no longer does that.
52
+ * Previously, when parsing using a schema, it used to force-convert all `type: Date` schema properties from any numeric cell value to a `Date` with a given timestamp. Now it demands the cell values for all such `type: Date` schema properties to already be correctly recognized as `Date`s when they're returned from `readSheet()` or `readExcelFile()` function. And I'd personally assume that in any sane (non-contrived) real-world usage scenario that would be the case, so it doesn't really seem like a "breaking change". And if, for some strange reason, that happens not to be the case, `parseData()` function will throw an error: `not_a_date`.
53
+ * Previously, when parsing using a schema, it used to skip `required` validation for completely-empty rows. It no longer does that.
54
+ * Removed exported function `parseExcelDate()` because there seems to be no need to have it exported.
55
+ * (TypeScript) Renamed exported types:
56
+ * `Type` → `ParseDataValueType`
57
+ * `Error` or `SchemaParseCellValueError` → `ParseDataError`
58
+ * `CellValueRequiredError` → `ParseDataValueRequiredError`
59
+ * `ParsedObjectsResult` → `ParseDataResult`
60
+ </details>
61
+
11
62
  ## Performance
12
63
 
13
- Here're the results of reading [sample `.xlsx` files](https://examplefile.com/document/xlsx) of different sizes:
64
+ Here're the results of reading [sample `.xlsx` files](https://examplefile.com/document/xlsx) of different size:
14
65
 
15
66
  |File Size| Browser | Node.js |
16
67
  |---------|---------|-----------|
@@ -28,95 +79,84 @@ Alternatively, one could include it on a web page [directly](#cdn) via a `<scrip
28
79
 
29
80
  ## Use
30
81
 
31
- ### Browser
32
-
33
- Example 1: User chooses a file and the web application reads it.
34
-
35
- ```html
36
- <input type="file" id="input" />
37
- ```
82
+ The default exported function — let's call it `readExcelFile()` — reads an `.xslx` file and returns a `Promise` that resolves to an array of "sheets". At least one "sheet" always exists. Each "sheet" is an object with properties:
83
+ * `sheet` — Sheet name.
84
+ * Example: `"Sheet1"`
85
+ * `data` — Sheet data. An array of rows. Each row is an array of values — `string`, `number`, `boolean` or `Date`.
86
+ * Example: `[ ['John Smith',35,true,...], ['Kate Brown',28,false,...], ... ]`
38
87
 
39
88
  ```js
40
- import readXlsxFile from 'read-excel-file/browser'
41
-
42
- const input = document.getElementById('input')
43
-
44
- input.addEventListener('change', () => {
45
- readXlsxFile(input.files[0]).then((rows) => {
46
- // `rows` is an array of "rows".
47
- // Each "row" is an array of "cells".
48
- // Each "cell" is a value: string, number, Date, boolean.
49
- })
50
- })
89
+ await readExcelFile(file)
90
+
91
+ // Returns
92
+ [{
93
+ sheet: 'Sheet1',
94
+ data: [
95
+ ['John Smith',35,true,...],
96
+ ['Kate Brown',28,false,...],
97
+ ...
98
+ ]
99
+ }, {
100
+ sheet: 'Sheet2',
101
+ data: ...
102
+ }]
51
103
  ```
52
104
 
53
- Example 2: Application fetches a file from a URL and reads it.
105
+ In simple cases when there're no multiple sheets in an `.xlsx` file, or if only one sheet in an `.xlsx` file is of any interest, use a named exported function `readSheet()`. It's same as the default exported function shown above with the only difference that it returns just `data` instead of `[{ name: 'Sheet1', data }]`, so it's just a bit simpler to use. It has an optional second argument — `sheet` — which could be a sheet number (starting from `1`) or a sheet name. By default, it reads the first sheet.
54
106
 
55
107
  ```js
56
- fetch('https://example.com/spreadsheet.xlsx')
57
- .then(response => response.blob())
58
- .then(blob => readXlsxFile(blob))
59
- .then((rows) => {
60
- // `rows` is an array of "rows".
61
- // Each "row" is an array of "cells".
62
- // Each "cell" is a value: string, number, Date, boolean.
63
- })
108
+ await readSheet(file)
109
+
110
+ // Returns
111
+ [
112
+ ['John Smith',35,true,...],
113
+ ['Kate Brown',28,false,...],
114
+ ...
115
+ ]
64
116
  ```
65
117
 
66
- In summary, it can read data from a [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File), a [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) or an [`ArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer).
118
+ As for where to `import` those two functions from, the package provides a separate `import` path for each different environment, as described below.
67
119
 
68
- Note: Internet Explorer 11 is an old browser that doesn't support [`Promise`](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Promise) and would require a [polyfill](https://www.npmjs.com/package/promise-polyfill) to work.
120
+ ### Browser
69
121
 
70
- ### Node.js
122
+ It can read a [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File), a [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) or an [`ArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer).
71
123
 
72
- Example 1: Read data from a file at file path.
124
+ Example: User chooses a file and the web application reads it.
73
125
 
74
- ```js
75
- // Import from '/node' subpackage.
76
- import readXlsxFile from 'read-excel-file/node'
77
-
78
- // Read data from a file by file path.
79
- readXlsxFile('/path/to/file').then((rows) => {
80
- // `rows` is an array of "rows".
81
- // Each "row" is an array of "cells".
82
- // Each "cell" is a value: string, number, Date, boolean.
83
- })
126
+ ```html
127
+ <input type="file" id="input" />
84
128
  ```
85
129
 
86
- Example 2: Read data from a [`Stream`](https://nodejs.org/api/stream.html)
87
-
88
130
  ```js
89
- // Read data from a `Stream`.
90
- readXlsxFile(fs.createReadStream('/path/to/file')).then((rows) => {
91
- // `rows` is an array of "rows".
92
- // Each "row" is an array of "cells".
93
- // Each "cell" is a value: string, number, Date, boolean.
131
+ import { readSheet } from 'read-excel-file/browser'
132
+
133
+ const input = document.getElementById('input')
134
+
135
+ input.addEventListener('change', () => {
136
+ const data = await readSheet(input.files[0])
94
137
  })
95
138
  ```
96
139
 
97
- It could also read data from a [`Buffer`](https://nodejs.org/api/buffer.html) or a [`Blob`](https://developer.mozilla.org/docs/Web/API/Blob).
98
-
99
- In summary, it can read data from a file path, a [`Stream`](https://nodejs.org/api/stream.html), a [`Buffer`](https://nodejs.org/api/buffer.html) or a [`Blob`](https://developer.mozilla.org/docs/Web/API/Blob).
140
+ Note: Internet Explorer 11 is an old browser that doesn't support [`Promise`](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Promise), and hence requires a [polyfill](https://www.npmjs.com/package/promise-polyfill).
100
141
 
101
- ### Universal
142
+ <details>
143
+ <summary>Example 2: Reading from a URL</summary>
102
144
 
103
- The one that works both in a web browser and Node.js. Only supports a [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) for input, which could be a bit less convenient for some.
145
+ ######
104
146
 
105
147
  ```js
106
- // Import from '/universal' subpackage.
107
- import readXlsxFile from 'read-excel-file/universal'
108
-
109
- // Read data from a `Blob` with `.xlsx` file contents.
110
- readXlsxFile(blob).then((rows) => {
111
- // `rows` is an array of "rows".
112
- // Each "row" is an array of "cells".
113
- // Each "cell" is a value: string, number, Date, boolean.
114
- })
148
+ const response = await fetch('https://example.com/spreadsheet.xlsx')
149
+ const block = await response.blob()
150
+ const data = await readSheet(blob)
115
151
  ```
152
+ </details>
116
153
 
117
- ### Web Worker
154
+ <details>
155
+ <summary>Example 3: Using <code>read-excel-file</code> in a Web Worker</summary>
156
+
157
+ ######
118
158
 
119
- Example 1: User chooses a file and the web application reads it in a [Web Worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers) to avoid freezing the UI on large files.
159
+ All exports of `read-excel-file` already use a [Web Worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers) under the hood when reading `.xlsx` file contents. This is in order to avoid freezing the UI when reading large files. So using an additional Web Worker on top of that isn't really necessary. Still, for those who require it, this example shows how a user chooses a file and the web application reads it in a [Web Worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers).
120
160
 
121
161
  ```js
122
162
  // Step 1: Initialize Web Worker.
@@ -144,127 +184,125 @@ input.addEventListener('change', () => {
144
184
  ##### `web-worker.js`
145
185
 
146
186
  ```js
147
- // Import from '/web-worker' subpackage.
148
- import readXlsxFile from 'read-excel-file/web-worker'
149
-
150
- onmessage = function(event) {
151
- readXlsxFile(event.data).then((rows) => {
152
- // `rows` is an array of "rows".
153
- // Each "row" is an array of "cells".
154
- // Each "cell" is a value: string, number, Date, boolean.
155
- postMessage(rows)
156
- })
187
+ import { readSheet } from 'read-excel-file/web-worker'
188
+
189
+ onmessage = async function(event) {
190
+ const sheetData = await readSheet(event.data)
191
+ postMessage(sheetData)
157
192
  }
158
193
  ```
194
+ </details>
159
195
 
160
- ## Multiple Sheets
196
+ ### Node.js
161
197
 
162
- By default, it only reads the first "sheet" in the file. If you have multiple sheets in your file then pass either a sheet number (starting from `1`) or a sheet name in the `options` argument.
198
+ It can read a file path, a [`Stream`](https://nodejs.org/api/stream.html), a [`Buffer`](https://nodejs.org/api/buffer.html) or a [`Blob`](https://developer.mozilla.org/docs/Web/API/Blob).
163
199
 
164
- Example 1: Reads the second sheet.
200
+ Example 1: Read from a file path.
165
201
 
166
202
  ```js
167
- readXlsxFile(file, { sheet: 2 }).then((data) => {
168
- ...
169
- })
203
+ import { readSheet } from 'read-excel-file/node'
204
+
205
+ const data = await readSheet('/path/to/file')
170
206
  ```
171
207
 
172
- Example 2: Reads the sheet called "Sheet1".
208
+ Example 2: Read from a [`Stream`](https://nodejs.org/api/stream.html)
173
209
 
174
210
  ```js
175
- readXlsxFile(file, { sheet: 'Sheet1' }).then((data) => {
176
- ...
177
- })
211
+ import { readSheet } from 'read-excel-file/node'
212
+
213
+ const data = await readSheet(fs.createReadStream('/path/to/file'))
178
214
  ```
179
215
 
180
- To get the names of all available sheets, use `readSheetNames()` function:
216
+ ### Universal
217
+
218
+ This one works both in a web browser and Node.js. It can only read from a [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) or an [`ArrayBuffer`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer), which could be a bit less convenient for general use.
181
219
 
182
220
  ```js
183
- // The function could be imported from any sub-package:
184
- // 'read-excel-file/browser', 'read-exel-file/node', 'read-excel-file/web-worker', etc.
185
- import { readSheetNames } from 'read-excel-file/browser'
221
+ import { readSheet } from 'read-excel-file/universal'
186
222
 
187
- readSheetNames(file).then((sheetNames) => {
188
- // sheetNames === ['Sheet1', 'Sheet2']
189
- })
223
+ const data = await readSheet(blob)
190
224
  ```
191
225
 
192
- ## Dates
226
+ ## Strings
193
227
 
194
- `.xlsx` file format originally had no dedicated "date" type, so dates are in almost all cases stored simply as numbers, equal to the count of days since `01/01/1900`. To correctly interpret such numbers as dates, each date cell has a special ["format"](https://xlsxwriter.readthedocs.io/format.html#format-set-num-format) (example: `"d mmm yyyy"`) that instructs the spreadsheet viewer application to format the number in the cell as a date in a given format.
228
+ By default, it automatically trims all string values. To disable this behavior, pass `trim: false` option.
195
229
 
196
- When using `readXlsxFile()` with a [`schema`](#schema) parameter, all columns having `type: Date` are automatically parsed as dates.
230
+ ```js
231
+ readExcelFile(file, { trim: false })
232
+ ```
197
233
 
198
- When using `readXlsxFile()` without a `schema` parameter, it attempts to guess whether the cell value is a date or a number by looking at the cell's "format" — if the "format" is one of the [standard date formats](https://docs.microsoft.com/en-us/dotnet/api/documentformat.openxml.spreadsheet.numberingformat?view=openxml-2.8.1) then the cell value is interpreted as a date. So usually there's no need to configure anything and it usually works out-of-the-box.
234
+ ## Dates
199
235
 
200
- Sometimes though, an `.xlsx` file might use a non-standard date format like `"mm/dd/yyyy"`. To read such files correctly, pass a `dateFormat` parameter to tell it to parse cells having such "format" as date cells.
236
+ `.xlsx` file format originally had no dedicated "date" type, so dates are in almost all cases stored simply as numbers, equal to the count of days since `01/01/1900` (with a few [quirks](https://www.reddit.com/r/AskStatistics/comments/7uk40z/excel_calculates_dates_wrong_so_please_be_careful/)). To correctly interpret such numbers as dates, each date cell in an `.xlsx` file specifies a certain ["format"](https://xlsxwriter.readthedocs.io/format.html#format-set-num-format) — for example, `"d mmm yyyy"` that instructs a spreadsheet viewer application to interpret the numeric value in the cell as a date rather than a number, and display it using the specified format.
201
237
 
202
- ```js
203
- readXlsxFile(file, { dateFormat: 'mm/dd/yyyy' })
204
- ```
238
+ Being no different from a generic spreadsheet viewer application, this package follows the same practice: it attempts to guess whether a given cell value is a date or a number by looking at the cell's "format" — if the "format" is one of the known [standard date formats](https://docs.microsoft.com/en-us/dotnet/api/documentformat.openxml.spreadsheet.numberingformat?view=openxml-2.8.1) then the cell value is interpreted as a date rather than a number. So usually there's no need to configure anything and it usually "just works" out-of-the-box.
239
+
240
+ Although there's still a possibility for an `.xlsx` file to specify a totally-custom non-standard date format. In such case, a developer could pass a `dateFormat` parameter to tell this package to parse cells having that specific "format" as date ones rather than numeric ones: `readExcelFile(file, { dateFormat: 'mm/dd/yyyy' })`.
205
241
 
206
242
  ## Numbers
207
243
 
208
- In `.xlsx` files, numbers are stored as strings. `read-excel-file` manually parses such numeric cell values from strings to numbers. But there's an inherent issue with javascript numbers in general: their [floating-point precision](https://www.youtube.com/watch?v=2gIxbTn7GSc) might not be enough for applications that require 100% precision. An example would be finance and banking. To support such demanding use-cases, this library supports passing a custom `parseNumber(string)` function as an option.
244
+ When reading an `.xlsx` file, any numeric values are parsed from a string to a javascript `number`. But there's an inherent issue with javascript `number`s in general their [floating-point precision](https://www.youtube.com/watch?v=2gIxbTn7GSc) is sometimes less than ideal. For example, `0.1 + 0.2 != 0.3`. Yet, applications in areas such as finance or banking usually require 100% floating-point precision, which is usually worked around by using a custom implementation of a "decimal" data type such as [`decimal.js`](https://www.npmjs.com/package/decimal.js).
245
+
246
+ This package supports passing a custom `parseNumber(string)` function as an option when reading an `.xlsx` file. By default, it parses a `string` to a javascript `number`, but one could pass any custom implementation.
209
247
 
210
- Example: Use "decimals" to represent numbers with 100% precision in banking applications.
248
+ Example: Use "decimal" data type to perform further calculations on fractional numbers with 100% precision.
211
249
 
212
250
  ```js
213
251
  import Decimal from 'decimal.js'
214
252
 
215
- readXlsxFile(file, {
253
+ readExcelFile(file, {
216
254
  parseNumber: (string) => new Decimal(string)
217
255
  })
218
256
  ```
219
257
 
220
- ## Strings
221
-
222
- By default, it automatically trims all string cell values. To disable this feature, pass `trim: false` option.
223
-
224
- ```js
225
- readXlsxFile(file, { trim: false })
226
- ```
227
-
228
258
  ## Formulas
229
259
 
230
- Dynamically calculated cells using formulas (`SUM`, etc) are not supported.
231
-
232
- ## Performance
233
-
234
- There have been some reports about performance issues when reading extremely large `.xlsx` spreadsheets using this library. It's true that this library's main point have been usability and convenience, and not performance when handling huge datasets. For example, the time of parsing a file with 100,000 rows could be up to 10 seconds. If your application has to quickly read huge datasets, perhaps consider using something like [`xlsx`](https://github.com/catamphetamine/read-excel-file/issues/38#issuecomment-544286628) package instead. There're no comparative benchmarks between the two packages, so we don't know how much the difference would be. If you'll be making any benchmarks, share those in the "Issues" so that we could include them in this readme.
260
+ This package doesn't support reading cells that use formulas to calculate the value: `SUM`, `AVERAGE`, etc.
235
261
 
236
262
  ## Schema
237
263
 
238
- To read spreadsheet data and then convert each row to a JSON object, pass a `schema` option to `readXlsxFile()`. When doing so, instead of returning an array of rows of cells, it will return an object of shape `{ rows, errors }` where `rows` is gonna be an array of JSON objects created from the spreadsheet rows according to the `schema`, and `errors` is gonna be an array of any errors encountered during the conversion.
264
+ Oftentimes, the task is not just to read the "raw" spreadsheet data but also to convert each row of that data to a JSON object having a certain structure. Because it's such a common task, this package exports a named function `parseData(data, schema)` which does exactly that. It parses sheet data into an array of JSON objects according to a pre-defined `schema` which describes how should a row of data be converted to a JSON object.
265
+
266
+ ```js
267
+ import { readSheet, parseData } from "read-excel-file/browser"
268
+
269
+ const data = await readSheet(file)
270
+ const schema = { ... }
271
+ for (const { object, errors } of parseData(data, schema)) {
272
+ if (errors) {
273
+ console.error(errors)
274
+ } else {
275
+ console.log(object)
276
+ }
277
+ }
278
+ ```
239
279
 
240
- The spreadsheet should adhere to a certain structure: first goes a header row with only column titles, rest are the data rows.
280
+ The `parseData()` function returns an array where each element represents a "data row" and has shape `{ object, errors }`. Depending on whether there were any errors when parsing a given "data row", either `object` or `errors` property will be `undefined`.
241
281
 
242
- The `schema` should describe every property of the JSON object:
282
+ The sheet data that is being parsed should adhere to a simple structure: the first row should be a header row with just column titles, and each following row should specify the values for those columns.
243
283
 
244
- * what is the property name
245
- * what column to read the value from
246
- * how to validate the value
247
- * how to parse the value
284
+ The `schema` argument should describe the structure of the resulting JSON objects. An example of a `schema` is provided at the end of this section.
248
285
 
249
- A key of a `schema` entry represents the name of the property. The value of the `schema` entry describes the rest:
286
+ Specifically, a `schema` should be an object having the same keys as a resulting JSON object, with values being nested objects having the following properties:
250
287
 
251
288
  * `column` — The title of the column to read the value from.
252
289
  * If the column is missing from the spreadsheet, the property value will be `undefined`.
253
- * This can be overridden by passing `schemaPropertyValueForMissingColumn` option. Is `undefined` by default.
290
+ * This can be overridden by passing `propertyValueWhenColumnIsMissing` option. Is `undefined` by default.
254
291
  * If the column is present in the spreadsheet but is empty, the property value will be `null`.
255
- * This can be overridden by passing `schemaPropertyValueForMissingValue` option. Is `null` by default.
292
+ * This can be overridden by passing `propertyValueWhenCellIsEmpty` option. Is `null` by default.
256
293
  * `required` — (optional) Is the value required?
257
294
  * Could be one of:
258
295
  * `required: boolean`
259
296
  * `true` — The column must not be missing from the spreadsheet and the cell value must not be empty.
260
- * `false` — The column can be missing from the spreadsheet and the cell value can be empty.
297
+ * `false` — The column can be missing from the spreadsheet, or the cell value can be empty.
261
298
  * `required: (object) => boolean` — A function returning `true` or `false` depending on the other properties of the object.
262
- * It could be configured to skip `required` validation for missing columns by passing `schemaPropertyShouldSkipRequiredValidationForMissingColumn` function as an option. By default it's `(column, { object }) => false` meaning that when `column` is missing from the spreadsheet, it will not skip `required` validation for it.
299
+ <!-- * To skip `required` validation for a column that is missing from a spreadsheet, one could pass `shouldSkipRequiredValidationWhenColumnIsMissing` option. It should be a function: `(columnTitle, { object }) => boolean`. By default it always returns `false` meaning that when `columnTitle` is missing from the spreadsheet, it will not skip performing the `required` validation for it. -->
263
300
  * `validate(value)` — (optional) Validates the value. Is only called for non-empty cells. If the value is invalid, this function should throw an error.
264
- * `schema` — (optional) If the value is going to be a nested object, `schema` should describe all of its properties.
265
- * If all of its property values happen to be empty (`undefined` or `null`), the nested object will be replaced with `null`.
266
- * This can be overridden by passing `getEmptyObjectValue(object, { path? })` function as an option. By default, it returns `null`.
267
- * `type` (optional) If the value is not going to be a nested object, `type` should define the type of the value. It will determine how the cell value will be converted to the property value. If no `type` is specified then the cell value is returned "as is": as a string, number, date or boolean.
301
+ * `schema` — (optional) If the value is going to be a nested object, `schema` should describe that nested object.
302
+ * If when parsing such nested object, all of its property values happen to be empty `undefined` or `null` — then the nested object will be itself set to `null`.
303
+ * This can be overridden by passing `transformEmptyObject(object, { path? })` function as an option. By default, it returns `null`.
304
+ * This applies both to nested objects and to the top-level object itself.
305
+ * `type` — (optional) If the value is not going to be a nested object, `type` should describe the type of the value. It will determine how the cell value will be converted to a property value. If no `type` is specified then the property value will be same as the cell value.
268
306
  * Valid `type`s:
269
307
  * Standard types:
270
308
  * `String`
@@ -276,25 +314,28 @@ A key of a `schema` entry represents the name of the property. The value of the
276
314
  * `Email`
277
315
  * `URL`
278
316
  * Custom type:
279
- * A function that receives a cell value and returns a parsed value. Returning `undefined` will have same effect as returning `null`. If the value is invalid, it should throw an error.
280
- * If the cell value consists of comma-separated values (example: `"a, b, c"`) then `type` could be specified as `[type]` for any of the valid `type`s described above.
281
- * Example: `{ type: [String] }` or `{ type: [(value) => parseValue(value)] }`
282
- * If the cell value is empty, or if every element of the array is `null` or `undefined`, then the array property value is gonna be `null` by default.
283
- * This can be overridden by passing `getEmptyArrayValue(array, { path })` function as an option. By default, it returns `null`.
317
+ * A function that receives a cell value and returns any kind of a parsed value. Returning `undefined` will have same effect as returning `null`. If the value is invalid, it should throw an error.
318
+ * If the cell value is comprised of comma-separated values (example: `"a, b, c"`) and if it should be parsed as an array of such values, then the property `type` could be specified as an array — `type: [elementType]` where `elementType` could be any valid `type` described above. For example, if a property is defined as `{ type: [String] }` and the cell value is `"a, b, c"` then the property value will be parsed as `["a", "b", "c"]`.
319
+ * If the cell is empty, or if every element of the parsed array is `null` or `undefined`, then the property value itself will be set to `null`.
320
+ * This can be overridden by passing `transformEmptyArray(array, { path })` function as an option. By default, it returns `null`.
321
+ * The separator could be specified by passing `arrayValueSeparator` option. By default, it's `","`.
322
+ * The separated parts of a cell value will be trimmed.
284
323
 
285
- If there're any errors during the conversion of spreadsheet data to JSON objects, the `errors` property returned from the function will be a non-empty array. Each `error` object has properties:
324
+ If there're any errors during the conversion process, the `errors` property returned from the function will be a non-empty array (by default, it's an empty array). Each `error` object has properties:
286
325
 
287
326
  * `error: string` — The error code. Examples: `"required"`, `"invalid"`.
288
- * If a custom `validate()` function is defined and it throws a `new Error(message)` then the `error` property will be the same as the `message` value.
289
- * If a custom `type()` function is defined and it throws a `new Error(message)` then the `error` property will be the same as the `message` value.
290
- * `reason?: string` — An optional secondary error code providing more details about the error: "`error.error` because `error.reason`". Currently, it's only returned for standard `type`s.
291
- * Example: `{ error: "invalid", reason: "not_a_number" }` for `type: Number` means that "the cell value is _invalid_ **because** it's _not a number_".
292
- * `row: number` — The row number in the original file. `1` means the first row, etc.
327
+ * If a custom `validate()` function is defined and it throws a `new Error(message)` then the `error` property will be the same as the `message` argument.
328
+ * If a custom `type()` function is defined and it throws a `new Error(message)` then the `error` property will be the same as the `message` argument.
329
+ * `reason?: string` — An optional secondary error code providing more details about the error. I.e. "`error.error` happened specifically because of `error.reason`". Currently, it could only be returned for the standard `type`s.
330
+ * Example: `{ error: "invalid", reason: "not_a_number" }` for a `type: Number` property means that "the cell value is _invalid_ **because** it's _not a number_".
331
+ * `row: number` — The row number, starting from `1`.
332
+ * `row: 1` means "first row of data", etc.
333
+ * Don't mind the header row.
293
334
  * `column: string` — The column title.
294
335
  * `value?: any` — The cell value.
295
- * `type?: any` — The `type` of the property, as defined in the `schema`.
336
+ * `type?: any` — The `type` of the property, as defined by the `schema`.
296
337
 
297
- Below is an example of using a `schema`.
338
+ Example:
298
339
 
299
340
  ```js
300
341
  // An example .xlsx document:
@@ -352,35 +393,37 @@ const schema = {
352
393
  }
353
394
  }
354
395
 
355
- readXlsxFile(file, { schema }).then(({ rows, errors }) => {
356
- // `errors` list items have shape: `{ row, column, error, reason?, value?, type? }`.
357
- errors.length === 0
358
-
359
- rows === [{
360
- date: new Date(2018, 2, 24),
361
- numberOfStudents: 10,
362
- course: {
363
- isFree: true,
364
- title: 'Chemistry'
365
- },
366
- contact: '+11234567890',
367
- status: 'SCHEDULED'
368
- }]
369
- })
396
+ const data = await readSheet(file)
397
+
398
+ const { rows, errors } = parseData(data, schema)
399
+
400
+ // `errors` list items have shape: `{ row, column, error, reason?, value?, type? }`.
401
+ errors.length === 0
402
+
403
+ rows === [{
404
+ date: new Date(2018, 3 - 1, 24),
405
+ numberOfStudents: 10,
406
+ course: {
407
+ isFree: true,
408
+ title: 'Chemistry'
409
+ },
410
+ contact: '+11234567890',
411
+ status: 'SCHEDULED'
412
+ }]
370
413
  ```
371
414
 
372
- #### Schema: Tips and Features
415
+ <!-- #### Schema: Tips and Features -->
373
416
 
374
417
  <!-- If no `type` is specified then the cell value is returned "as is": as a string, number, date or boolean. -->
375
418
 
376
419
  <!-- There are also some additional exported `type`s available: -->
377
420
 
378
421
  <details>
379
- <summary>How to transform cell value using a <strong>custom <code>type</code></strong> function.</summary>
422
+ <summary>An example of a <strong>custom <code>type</code></strong></summary>
380
423
 
381
424
  #####
382
425
 
383
- Here's an example of a custom `type` parsing function. It will only be called for a non-empty cell and will transform the cell value.
426
+ Here's an example of a basic custom `type`. It calls a custom `parseValue()` function to parse a cell value, and produces an `"invalid"` error if the value couldn't be parsed. If a cell is empty, it will not be parsed.
384
427
 
385
428
  ```js
386
429
  {
@@ -401,44 +444,25 @@ Here's an example of a custom `type` parsing function. It will only be called fo
401
444
 
402
445
  <!-- A schema entry for a column may also define an optional `validate(value)` function for validating the parsed value: in that case, it must `throw` an `Error` if the `value` is invalid. The `validate(value)` function is only called when `value` is not empty (not `null` / `undefined`). -->
403
446
 
404
- <!--
405
447
  <details>
406
- <summary>How to <strong>not skip empty rows</strong>.</summary>
448
+ <summary>An example of a <strong>React component to output <code>errors</code></strong></summary>
407
449
 
408
450
  #####
409
451
 
410
- By default, it skips any empty rows. To disable that behavior, pass `ignoreEmptyRows: false` option.
411
-
412
452
  ```js
413
- readXlsxFile(file, {
414
- schema,
415
- ignoreEmptyRows: false
416
- })
417
- ```
418
- </details>
419
- -->
420
-
421
- <details>
422
- <summary>A <strong>React component for displaying errors</strong> that occured during schema parsing/validation.</summary>
423
-
424
- #####
425
-
426
- ```js
427
- import { parseExcelDate } from 'read-excel-file/browser'
428
-
429
- function ParseExcelFileErrors({ errors }) {
453
+ function ErrorsList({ errors }) {
430
454
  return (
431
455
  <ul>
432
456
  {errors.map((error, i) => (
433
457
  <li key={i}>
434
- <ParseExcelFileError error={error}>
458
+ <ErrorItem error={error}>
435
459
  </li>
436
460
  ))}
437
461
  </ul>
438
462
  )
439
463
  }
440
464
 
441
- function ParseExcelFileError({ error: errorDetails }) {
465
+ function ErrorItem({ error: errorDetails }) {
442
466
  const { type, value, error, reason, row, column } = errorDetails
443
467
 
444
468
  // Error summary.
@@ -468,26 +492,9 @@ function stringifyValue(value) {
468
492
  ```
469
493
  </details>
470
494
 
471
- ## Fix Spreadsheet Structure When Using Schema
472
-
473
- Sometimes, a spreadsheet doesn't have the required structure to read it using a `schema`. For example, header row might be missing, or there could be some purely presentational / empty / "garbage" rows that should be skipped. To fix that, pass a `transformData(data)` function as an option. It will transform spreadsheet content before it is parsed with `schema`. The `data` argument is an array of rows, each row being an array of cell values.
474
-
475
- ```js
476
- readXlsxFile(file, {
477
- schema,
478
- transformData(data) {
479
- // Example 1: Add a missing header row.
480
- return [['ID', 'NAME', ...]].concat(data)
481
- // Example 2: Remove empty rows.
482
- return data.filter(row => row.some(cell => cell !== null))
483
- }
484
- })
485
- ```
486
- </details>
487
-
488
495
  ## Browser Support
489
496
 
490
- An `.xlsx` file is just a `*.zip` archive with an `*.xslx` file extension. This package uses [`fflate`](https://www.npmjs.com/package/fflate) for `*.zip` decompression. See `fflate`'s [browser support](https://www.npmjs.com/package/fflate#browser-support) for further details.
497
+ An `.xlsx` file is just a `.zip` archive with an `.xslx` file extension. This package uses [`fflate`](https://www.npmjs.com/package/fflate) for `.zip` decompression. See `fflate`'s [browser support](https://www.npmjs.com/package/fflate#browser-support) for further details.
491
498
 
492
499
  ## CDN
493
500
 
package/browser/index.cjs CHANGED
@@ -1,7 +1,10 @@
1
1
  exports = module.exports = require('../commonjs/export/readXlsxFileBrowser.js').default
2
2
  exports['default'] = require('../commonjs/export/readXlsxFileBrowser.js').default
3
- exports.readSheetNames = require('../commonjs/export/readSheetNamesBrowser.js').default
4
- exports.parseExcelDate = require('../commonjs/xlsx/parseDate.js').default
5
- exports.Integer = require('../commonjs/types/Integer.js').default
6
- exports.Email = require('../commonjs/types/Email.js').default
7
- exports.URL = require('../commonjs/types/URL.js').default
3
+
4
+ exports.readSheet = require('../commonjs/export/readSheetBrowser.js').default
5
+
6
+ // `parseData()`
7
+ exports.parseData = require('../commonjs/parseData/parseData.js').default
8
+ exports.Integer = require('../commonjs/parseData/types/additional/Integer.js').default
9
+ exports.Email = require('../commonjs/parseData/types/additional/Email.js').default
10
+ exports.URL = require('../commonjs/parseData/types/additional/URL.js').default