@lyit/exceljs 4.4.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 (543) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +3398 -0
  3. package/README_zh.md +2878 -0
  4. package/dist/LICENSE +22 -0
  5. package/dist/es5/csv/csv.js +182 -0
  6. package/dist/es5/csv/csv.js.map +1 -0
  7. package/dist/es5/csv/line-buffer.js +68 -0
  8. package/dist/es5/csv/line-buffer.js.map +1 -0
  9. package/dist/es5/csv/stream-converter.js +110 -0
  10. package/dist/es5/csv/stream-converter.js.map +1 -0
  11. package/dist/es5/doc/anchor.js +73 -0
  12. package/dist/es5/doc/anchor.js.map +1 -0
  13. package/dist/es5/doc/cell.js +960 -0
  14. package/dist/es5/doc/cell.js.map +1 -0
  15. package/dist/es5/doc/column.js +274 -0
  16. package/dist/es5/doc/column.js.map +1 -0
  17. package/dist/es5/doc/data-validations.js +18 -0
  18. package/dist/es5/doc/data-validations.js.map +1 -0
  19. package/dist/es5/doc/defined-names.js +173 -0
  20. package/dist/es5/doc/defined-names.js.map +1 -0
  21. package/dist/es5/doc/enums.js +49 -0
  22. package/dist/es5/doc/enums.js.map +1 -0
  23. package/dist/es5/doc/form-checkbox.js +342 -0
  24. package/dist/es5/doc/form-checkbox.js.map +1 -0
  25. package/dist/es5/doc/image.js +69 -0
  26. package/dist/es5/doc/image.js.map +1 -0
  27. package/dist/es5/doc/modelcontainer.js +16 -0
  28. package/dist/es5/doc/modelcontainer.js.map +1 -0
  29. package/dist/es5/doc/note.js +64 -0
  30. package/dist/es5/doc/note.js.map +1 -0
  31. package/dist/es5/doc/pivot-table.js +247 -0
  32. package/dist/es5/doc/pivot-table.js.map +1 -0
  33. package/dist/es5/doc/range.js +229 -0
  34. package/dist/es5/doc/range.js.map +1 -0
  35. package/dist/es5/doc/row.js +391 -0
  36. package/dist/es5/doc/row.js.map +1 -0
  37. package/dist/es5/doc/table.js +542 -0
  38. package/dist/es5/doc/table.js.map +1 -0
  39. package/dist/es5/doc/workbook.js +221 -0
  40. package/dist/es5/doc/workbook.js.map +1 -0
  41. package/dist/es5/doc/worksheet.js +996 -0
  42. package/dist/es5/doc/worksheet.js.map +1 -0
  43. package/dist/es5/exceljs.bare.js +14 -0
  44. package/dist/es5/exceljs.bare.js.map +1 -0
  45. package/dist/es5/exceljs.browser.js +36 -0
  46. package/dist/es5/exceljs.browser.js.map +1 -0
  47. package/dist/es5/exceljs.nodejs.js +15 -0
  48. package/dist/es5/exceljs.nodejs.js.map +1 -0
  49. package/dist/es5/index.js +15 -0
  50. package/dist/es5/stream/xlsx/hyperlink-reader.js +90 -0
  51. package/dist/es5/stream/xlsx/hyperlink-reader.js.map +1 -0
  52. package/dist/es5/stream/xlsx/sheet-comments-writer.js +94 -0
  53. package/dist/es5/stream/xlsx/sheet-comments-writer.js.map +1 -0
  54. package/dist/es5/stream/xlsx/sheet-rels-writer.js +94 -0
  55. package/dist/es5/stream/xlsx/sheet-rels-writer.js.map +1 -0
  56. package/dist/es5/stream/xlsx/workbook-reader.js +361 -0
  57. package/dist/es5/stream/xlsx/workbook-reader.js.map +1 -0
  58. package/dist/es5/stream/xlsx/workbook-writer.js +347 -0
  59. package/dist/es5/stream/xlsx/workbook-writer.js.map +1 -0
  60. package/dist/es5/stream/xlsx/worksheet-reader.js +392 -0
  61. package/dist/es5/stream/xlsx/worksheet-reader.js.map +1 -0
  62. package/dist/es5/stream/xlsx/worksheet-writer.js +652 -0
  63. package/dist/es5/stream/xlsx/worksheet-writer.js.map +1 -0
  64. package/dist/es5/utils/auto-drain.js +18 -0
  65. package/dist/es5/utils/auto-drain.js.map +1 -0
  66. package/dist/es5/utils/browser-buffer-decode.js +15 -0
  67. package/dist/es5/utils/browser-buffer-decode.js.map +1 -0
  68. package/dist/es5/utils/browser-buffer-encode.js +18 -0
  69. package/dist/es5/utils/browser-buffer-encode.js.map +1 -0
  70. package/dist/es5/utils/cell-matrix.js +149 -0
  71. package/dist/es5/utils/cell-matrix.js.map +1 -0
  72. package/dist/es5/utils/col-cache.js +258 -0
  73. package/dist/es5/utils/col-cache.js.map +1 -0
  74. package/dist/es5/utils/copy-style.js +43 -0
  75. package/dist/es5/utils/copy-style.js.map +1 -0
  76. package/dist/es5/utils/encryptor.js +58 -0
  77. package/dist/es5/utils/encryptor.js.map +1 -0
  78. package/dist/es5/utils/iterate-stream.js +46 -0
  79. package/dist/es5/utils/iterate-stream.js.map +1 -0
  80. package/dist/es5/utils/parse-sax.js +66 -0
  81. package/dist/es5/utils/parse-sax.js.map +1 -0
  82. package/dist/es5/utils/shared-formula.js +42 -0
  83. package/dist/es5/utils/shared-formula.js.map +1 -0
  84. package/dist/es5/utils/shared-strings.js +37 -0
  85. package/dist/es5/utils/shared-strings.js.map +1 -0
  86. package/dist/es5/utils/stream-base64.js +66 -0
  87. package/dist/es5/utils/stream-base64.js.map +1 -0
  88. package/dist/es5/utils/stream-buf.js +365 -0
  89. package/dist/es5/utils/stream-buf.js.map +1 -0
  90. package/dist/es5/utils/string-buf.js +73 -0
  91. package/dist/es5/utils/string-buf.js.map +1 -0
  92. package/dist/es5/utils/string-builder.js +32 -0
  93. package/dist/es5/utils/string-builder.js.map +1 -0
  94. package/dist/es5/utils/stuttered-pipe.js +61 -0
  95. package/dist/es5/utils/stuttered-pipe.js.map +1 -0
  96. package/dist/es5/utils/typed-stack.js +23 -0
  97. package/dist/es5/utils/typed-stack.js.map +1 -0
  98. package/dist/es5/utils/under-dash.js +168 -0
  99. package/dist/es5/utils/under-dash.js.map +1 -0
  100. package/dist/es5/utils/utils.js +205 -0
  101. package/dist/es5/utils/utils.js.map +1 -0
  102. package/dist/es5/utils/xml-stream.js +151 -0
  103. package/dist/es5/utils/xml-stream.js.map +1 -0
  104. package/dist/es5/utils/zip-stream.js +79 -0
  105. package/dist/es5/utils/zip-stream.js.map +1 -0
  106. package/dist/es5/xlsx/defaultnumformats.js +230 -0
  107. package/dist/es5/xlsx/defaultnumformats.js.map +1 -0
  108. package/dist/es5/xlsx/rel-type.js +22 -0
  109. package/dist/es5/xlsx/rel-type.js.map +1 -0
  110. package/dist/es5/xlsx/xform/base-xform.js +139 -0
  111. package/dist/es5/xlsx/xform/base-xform.js.map +1 -0
  112. package/dist/es5/xlsx/xform/book/defined-name-xform.js +85 -0
  113. package/dist/es5/xlsx/xform/book/defined-name-xform.js.map +1 -0
  114. package/dist/es5/xlsx/xform/book/sheet-xform.js +32 -0
  115. package/dist/es5/xlsx/xform/book/sheet-xform.js.map +1 -0
  116. package/dist/es5/xlsx/xform/book/workbook-calc-properties-xform.js +24 -0
  117. package/dist/es5/xlsx/xform/book/workbook-calc-properties-xform.js.map +1 -0
  118. package/dist/es5/xlsx/xform/book/workbook-pivot-cache-xform.js +27 -0
  119. package/dist/es5/xlsx/xform/book/workbook-pivot-cache-xform.js.map +1 -0
  120. package/dist/es5/xlsx/xform/book/workbook-properties-xform.js +27 -0
  121. package/dist/es5/xlsx/xform/book/workbook-properties-xform.js.map +1 -0
  122. package/dist/es5/xlsx/xform/book/workbook-view-xform.js +51 -0
  123. package/dist/es5/xlsx/xform/book/workbook-view-xform.js.map +1 -0
  124. package/dist/es5/xlsx/xform/book/workbook-xform.js +244 -0
  125. package/dist/es5/xlsx/xform/book/workbook-xform.js.map +1 -0
  126. package/dist/es5/xlsx/xform/comment/comment-xform.js +103 -0
  127. package/dist/es5/xlsx/xform/comment/comment-xform.js.map +1 -0
  128. package/dist/es5/xlsx/xform/comment/comments-xform.js +76 -0
  129. package/dist/es5/xlsx/xform/comment/comments-xform.js.map +1 -0
  130. package/dist/es5/xlsx/xform/comment/style/vml-position-xform.js +35 -0
  131. package/dist/es5/xlsx/xform/comment/style/vml-position-xform.js.map +1 -0
  132. package/dist/es5/xlsx/xform/comment/style/vml-protection-xform.js +32 -0
  133. package/dist/es5/xlsx/xform/comment/style/vml-protection-xform.js.map +1 -0
  134. package/dist/es5/xlsx/xform/comment/vml-anchor-xform.js +53 -0
  135. package/dist/es5/xlsx/xform/comment/vml-anchor-xform.js.map +1 -0
  136. package/dist/es5/xlsx/xform/comment/vml-client-data-xform.js +98 -0
  137. package/dist/es5/xlsx/xform/comment/vml-client-data-xform.js.map +1 -0
  138. package/dist/es5/xlsx/xform/comment/vml-notes-xform.js +235 -0
  139. package/dist/es5/xlsx/xform/comment/vml-notes-xform.js.map +1 -0
  140. package/dist/es5/xlsx/xform/comment/vml-shape-xform.js +93 -0
  141. package/dist/es5/xlsx/xform/comment/vml-shape-xform.js.map +1 -0
  142. package/dist/es5/xlsx/xform/comment/vml-textbox-xform.js +61 -0
  143. package/dist/es5/xlsx/xform/comment/vml-textbox-xform.js.map +1 -0
  144. package/dist/es5/xlsx/xform/composite-xform.js +51 -0
  145. package/dist/es5/xlsx/xform/composite-xform.js.map +1 -0
  146. package/dist/es5/xlsx/xform/core/app-heading-pairs-xform.js +30 -0
  147. package/dist/es5/xlsx/xform/core/app-heading-pairs-xform.js.map +1 -0
  148. package/dist/es5/xlsx/xform/core/app-titles-of-parts-xform.js +27 -0
  149. package/dist/es5/xlsx/xform/core/app-titles-of-parts-xform.js.map +1 -0
  150. package/dist/es5/xlsx/xform/core/app-xform.js +93 -0
  151. package/dist/es5/xlsx/xform/core/app-xform.js.map +1 -0
  152. package/dist/es5/xlsx/xform/core/content-types-xform.js +198 -0
  153. package/dist/es5/xlsx/xform/core/content-types-xform.js.map +1 -0
  154. package/dist/es5/xlsx/xform/core/core-xform.js +160 -0
  155. package/dist/es5/xlsx/xform/core/core-xform.js.map +1 -0
  156. package/dist/es5/xlsx/xform/core/relationship-xform.js +23 -0
  157. package/dist/es5/xlsx/xform/core/relationship-xform.js.map +1 -0
  158. package/dist/es5/xlsx/xform/core/relationships-xform.js +65 -0
  159. package/dist/es5/xlsx/xform/core/relationships-xform.js.map +1 -0
  160. package/dist/es5/xlsx/xform/drawing/base-cell-anchor-xform.js +47 -0
  161. package/dist/es5/xlsx/xform/drawing/base-cell-anchor-xform.js.map +1 -0
  162. package/dist/es5/xlsx/xform/drawing/blip-fill-xform.js +61 -0
  163. package/dist/es5/xlsx/xform/drawing/blip-fill-xform.js.map +1 -0
  164. package/dist/es5/xlsx/xform/drawing/blip-xform.js +39 -0
  165. package/dist/es5/xlsx/xform/drawing/blip-xform.js.map +1 -0
  166. package/dist/es5/xlsx/xform/drawing/c-nv-pic-pr-xform.js +35 -0
  167. package/dist/es5/xlsx/xform/drawing/c-nv-pic-pr-xform.js.map +1 -0
  168. package/dist/es5/xlsx/xform/drawing/c-nv-pr-xform.js +62 -0
  169. package/dist/es5/xlsx/xform/drawing/c-nv-pr-xform.js.map +1 -0
  170. package/dist/es5/xlsx/xform/drawing/cell-position-xform.js +82 -0
  171. package/dist/es5/xlsx/xform/drawing/cell-position-xform.js.map +1 -0
  172. package/dist/es5/xlsx/xform/drawing/ctrl-prop-xform.js +75 -0
  173. package/dist/es5/xlsx/xform/drawing/ctrl-prop-xform.js.map +1 -0
  174. package/dist/es5/xlsx/xform/drawing/drawing-xform.js +98 -0
  175. package/dist/es5/xlsx/xform/drawing/drawing-xform.js.map +1 -0
  176. package/dist/es5/xlsx/xform/drawing/ext-lst-xform.js +40 -0
  177. package/dist/es5/xlsx/xform/drawing/ext-lst-xform.js.map +1 -0
  178. package/dist/es5/xlsx/xform/drawing/ext-xform.js +38 -0
  179. package/dist/es5/xlsx/xform/drawing/ext-xform.js.map +1 -0
  180. package/dist/es5/xlsx/xform/drawing/hlink-click-xform.js +38 -0
  181. package/dist/es5/xlsx/xform/drawing/hlink-click-xform.js.map +1 -0
  182. package/dist/es5/xlsx/xform/drawing/nv-pic-pr-xform.js +59 -0
  183. package/dist/es5/xlsx/xform/drawing/nv-pic-pr-xform.js.map +1 -0
  184. package/dist/es5/xlsx/xform/drawing/one-cell-anchor-xform.js +63 -0
  185. package/dist/es5/xlsx/xform/drawing/one-cell-anchor-xform.js.map +1 -0
  186. package/dist/es5/xlsx/xform/drawing/pic-xform.js +67 -0
  187. package/dist/es5/xlsx/xform/drawing/pic-xform.js.map +1 -0
  188. package/dist/es5/xlsx/xform/drawing/sp-pr.js +30 -0
  189. package/dist/es5/xlsx/xform/drawing/sp-pr.js.map +1 -0
  190. package/dist/es5/xlsx/xform/drawing/two-cell-anchor-xform.js +62 -0
  191. package/dist/es5/xlsx/xform/drawing/two-cell-anchor-xform.js.map +1 -0
  192. package/dist/es5/xlsx/xform/list-xform.js +91 -0
  193. package/dist/es5/xlsx/xform/list-xform.js.map +1 -0
  194. package/dist/es5/xlsx/xform/pivot-table/cache-field.js +72 -0
  195. package/dist/es5/xlsx/xform/pivot-table/cache-field.js.map +1 -0
  196. package/dist/es5/xlsx/xform/pivot-table/pivot-cache-definition-xform.js +74 -0
  197. package/dist/es5/xlsx/xform/pivot-table/pivot-cache-definition-xform.js.map +1 -0
  198. package/dist/es5/xlsx/xform/pivot-table/pivot-cache-records-xform.js +100 -0
  199. package/dist/es5/xlsx/xform/pivot-table/pivot-cache-records-xform.js.map +1 -0
  200. package/dist/es5/xlsx/xform/pivot-table/pivot-table-xform.js +229 -0
  201. package/dist/es5/xlsx/xform/pivot-table/pivot-table-xform.js.map +1 -0
  202. package/dist/es5/xlsx/xform/sheet/auto-filter-xform.js +40 -0
  203. package/dist/es5/xlsx/xform/sheet/auto-filter-xform.js.map +1 -0
  204. package/dist/es5/xlsx/xform/sheet/cell-xform.js +450 -0
  205. package/dist/es5/xlsx/xform/sheet/cell-xform.js.map +1 -0
  206. package/dist/es5/xlsx/xform/sheet/cf/cf-rule-xform.js +282 -0
  207. package/dist/es5/xlsx/xform/sheet/cf/cf-rule-xform.js.map +1 -0
  208. package/dist/es5/xlsx/xform/sheet/cf/cfvo-xform.js +25 -0
  209. package/dist/es5/xlsx/xform/sheet/cf/cfvo-xform.js.map +1 -0
  210. package/dist/es5/xlsx/xform/sheet/cf/color-scale-xform.js +38 -0
  211. package/dist/es5/xlsx/xform/sheet/cf/color-scale-xform.js.map +1 -0
  212. package/dist/es5/xlsx/xform/sheet/cf/conditional-formatting-xform.js +45 -0
  213. package/dist/es5/xlsx/xform/sheet/cf/conditional-formatting-xform.js.map +1 -0
  214. package/dist/es5/xlsx/xform/sheet/cf/conditional-formattings-xform.js +77 -0
  215. package/dist/es5/xlsx/xform/sheet/cf/conditional-formattings-xform.js.map +1 -0
  216. package/dist/es5/xlsx/xform/sheet/cf/databar-xform.js +54 -0
  217. package/dist/es5/xlsx/xform/sheet/cf/databar-xform.js.map +1 -0
  218. package/dist/es5/xlsx/xform/sheet/cf/ext-lst-ref-xform.js +71 -0
  219. package/dist/es5/xlsx/xform/sheet/cf/ext-lst-ref-xform.js.map +1 -0
  220. package/dist/es5/xlsx/xform/sheet/cf/formula-xform.js +22 -0
  221. package/dist/es5/xlsx/xform/sheet/cf/formula-xform.js.map +1 -0
  222. package/dist/es5/xlsx/xform/sheet/cf/icon-set-xform.js +43 -0
  223. package/dist/es5/xlsx/xform/sheet/cf/icon-set-xform.js.map +1 -0
  224. package/dist/es5/xlsx/xform/sheet/cf-ext/cf-icon-ext-xform.js +28 -0
  225. package/dist/es5/xlsx/xform/sheet/cf-ext/cf-icon-ext-xform.js.map +1 -0
  226. package/dist/es5/xlsx/xform/sheet/cf-ext/cf-rule-ext-xform.js +88 -0
  227. package/dist/es5/xlsx/xform/sheet/cf-ext/cf-rule-ext-xform.js.map +1 -0
  228. package/dist/es5/xlsx/xform/sheet/cf-ext/cfvo-ext-xform.js +38 -0
  229. package/dist/es5/xlsx/xform/sheet/cf-ext/cfvo-ext-xform.js.map +1 -0
  230. package/dist/es5/xlsx/xform/sheet/cf-ext/conditional-formatting-ext-xform.js +52 -0
  231. package/dist/es5/xlsx/xform/sheet/cf-ext/conditional-formatting-ext-xform.js.map +1 -0
  232. package/dist/es5/xlsx/xform/sheet/cf-ext/conditional-formattings-ext-xform.js +43 -0
  233. package/dist/es5/xlsx/xform/sheet/cf-ext/conditional-formattings-ext-xform.js.map +1 -0
  234. package/dist/es5/xlsx/xform/sheet/cf-ext/databar-ext-xform.js +82 -0
  235. package/dist/es5/xlsx/xform/sheet/cf-ext/databar-ext-xform.js.map +1 -0
  236. package/dist/es5/xlsx/xform/sheet/cf-ext/f-ext-xform.js +22 -0
  237. package/dist/es5/xlsx/xform/sheet/cf-ext/f-ext-xform.js.map +1 -0
  238. package/dist/es5/xlsx/xform/sheet/cf-ext/icon-set-ext-xform.js +66 -0
  239. package/dist/es5/xlsx/xform/sheet/cf-ext/icon-set-ext-xform.js.map +1 -0
  240. package/dist/es5/xlsx/xform/sheet/cf-ext/sqref-ext-xform.js +22 -0
  241. package/dist/es5/xlsx/xform/sheet/cf-ext/sqref-ext-xform.js.map +1 -0
  242. package/dist/es5/xlsx/xform/sheet/col-xform.js +78 -0
  243. package/dist/es5/xlsx/xform/sheet/col-xform.js.map +1 -0
  244. package/dist/es5/xlsx/xform/sheet/data-validations-xform.js +247 -0
  245. package/dist/es5/xlsx/xform/sheet/data-validations-xform.js.map +1 -0
  246. package/dist/es5/xlsx/xform/sheet/dimension-xform.js +28 -0
  247. package/dist/es5/xlsx/xform/sheet/dimension-xform.js.map +1 -0
  248. package/dist/es5/xlsx/xform/sheet/drawing-xform.js +32 -0
  249. package/dist/es5/xlsx/xform/sheet/drawing-xform.js.map +1 -0
  250. package/dist/es5/xlsx/xform/sheet/ext-lst-xform.js +69 -0
  251. package/dist/es5/xlsx/xform/sheet/ext-lst-xform.js.map +1 -0
  252. package/dist/es5/xlsx/xform/sheet/header-footer-xform.js +126 -0
  253. package/dist/es5/xlsx/xform/sheet/header-footer-xform.js.map +1 -0
  254. package/dist/es5/xlsx/xform/sheet/hyperlink-xform.js +50 -0
  255. package/dist/es5/xlsx/xform/sheet/hyperlink-xform.js.map +1 -0
  256. package/dist/es5/xlsx/xform/sheet/merge-cell-xform.js +26 -0
  257. package/dist/es5/xlsx/xform/sheet/merge-cell-xform.js.map +1 -0
  258. package/dist/es5/xlsx/xform/sheet/merges.js +52 -0
  259. package/dist/es5/xlsx/xform/sheet/merges.js.map +1 -0
  260. package/dist/es5/xlsx/xform/sheet/outline-properties-xform.js +35 -0
  261. package/dist/es5/xlsx/xform/sheet/outline-properties-xform.js.map +1 -0
  262. package/dist/es5/xlsx/xform/sheet/page-breaks-xform.js +24 -0
  263. package/dist/es5/xlsx/xform/sheet/page-breaks-xform.js.map +1 -0
  264. package/dist/es5/xlsx/xform/sheet/page-margins-xform.js +46 -0
  265. package/dist/es5/xlsx/xform/sheet/page-margins-xform.js.map +1 -0
  266. package/dist/es5/xlsx/xform/sheet/page-setup-properties-xform.js +32 -0
  267. package/dist/es5/xlsx/xform/sheet/page-setup-properties-xform.js.map +1 -0
  268. package/dist/es5/xlsx/xform/sheet/page-setup-xform.js +99 -0
  269. package/dist/es5/xlsx/xform/sheet/page-setup-xform.js.map +1 -0
  270. package/dist/es5/xlsx/xform/sheet/picture-xform.js +32 -0
  271. package/dist/es5/xlsx/xform/sheet/picture-xform.js.map +1 -0
  272. package/dist/es5/xlsx/xform/sheet/print-options-xform.js +45 -0
  273. package/dist/es5/xlsx/xform/sheet/print-options-xform.js.map +1 -0
  274. package/dist/es5/xlsx/xform/sheet/row-breaks-xform.js +37 -0
  275. package/dist/es5/xlsx/xform/sheet/row-breaks-xform.js.map +1 -0
  276. package/dist/es5/xlsx/xform/sheet/row-xform.js +131 -0
  277. package/dist/es5/xlsx/xform/sheet/row-xform.js.map +1 -0
  278. package/dist/es5/xlsx/xform/sheet/sheet-format-properties-xform.js +63 -0
  279. package/dist/es5/xlsx/xform/sheet/sheet-format-properties-xform.js.map +1 -0
  280. package/dist/es5/xlsx/xform/sheet/sheet-properties-xform.js +83 -0
  281. package/dist/es5/xlsx/xform/sheet/sheet-properties-xform.js.map +1 -0
  282. package/dist/es5/xlsx/xform/sheet/sheet-protection-xform.js +84 -0
  283. package/dist/es5/xlsx/xform/sheet/sheet-protection-xform.js.map +1 -0
  284. package/dist/es5/xlsx/xform/sheet/sheet-view-xform.js +190 -0
  285. package/dist/es5/xlsx/xform/sheet/sheet-view-xform.js.map +1 -0
  286. package/dist/es5/xlsx/xform/sheet/table-part-xform.js +32 -0
  287. package/dist/es5/xlsx/xform/sheet/table-part-xform.js.map +1 -0
  288. package/dist/es5/xlsx/xform/sheet/worksheet-xform.js +622 -0
  289. package/dist/es5/xlsx/xform/sheet/worksheet-xform.js.map +1 -0
  290. package/dist/es5/xlsx/xform/simple/boolean-xform.js +27 -0
  291. package/dist/es5/xlsx/xform/simple/boolean-xform.js.map +1 -0
  292. package/dist/es5/xlsx/xform/simple/date-xform.js +58 -0
  293. package/dist/es5/xlsx/xform/simple/date-xform.js.map +1 -0
  294. package/dist/es5/xlsx/xform/simple/float-xform.js +47 -0
  295. package/dist/es5/xlsx/xform/simple/float-xform.js.map +1 -0
  296. package/dist/es5/xlsx/xform/simple/integer-xform.js +53 -0
  297. package/dist/es5/xlsx/xform/simple/integer-xform.js.map +1 -0
  298. package/dist/es5/xlsx/xform/simple/string-xform.js +47 -0
  299. package/dist/es5/xlsx/xform/simple/string-xform.js.map +1 -0
  300. package/dist/es5/xlsx/xform/static-xform.js +61 -0
  301. package/dist/es5/xlsx/xform/static-xform.js.map +1 -0
  302. package/dist/es5/xlsx/xform/strings/phonetic-text-xform.js +98 -0
  303. package/dist/es5/xlsx/xform/strings/phonetic-text-xform.js.map +1 -0
  304. package/dist/es5/xlsx/xform/strings/rich-text-xform.js +92 -0
  305. package/dist/es5/xlsx/xform/strings/rich-text-xform.js.map +1 -0
  306. package/dist/es5/xlsx/xform/strings/shared-string-xform.js +99 -0
  307. package/dist/es5/xlsx/xform/strings/shared-string-xform.js.map +1 -0
  308. package/dist/es5/xlsx/xform/strings/shared-strings-xform.js +116 -0
  309. package/dist/es5/xlsx/xform/strings/shared-strings-xform.js.map +1 -0
  310. package/dist/es5/xlsx/xform/strings/text-xform.js +39 -0
  311. package/dist/es5/xlsx/xform/strings/text-xform.js.map +1 -0
  312. package/dist/es5/xlsx/xform/style/alignment-xform.js +139 -0
  313. package/dist/es5/xlsx/xform/style/alignment-xform.js.map +1 -0
  314. package/dist/es5/xlsx/xform/style/border-xform.js +185 -0
  315. package/dist/es5/xlsx/xform/style/border-xform.js.map +1 -0
  316. package/dist/es5/xlsx/xform/style/color-xform.js +66 -0
  317. package/dist/es5/xlsx/xform/style/color-xform.js.map +1 -0
  318. package/dist/es5/xlsx/xform/style/dxf-xform.js +106 -0
  319. package/dist/es5/xlsx/xform/style/dxf-xform.js.map +1 -0
  320. package/dist/es5/xlsx/xform/style/fill-xform.js +307 -0
  321. package/dist/es5/xlsx/xform/style/fill-xform.js.map +1 -0
  322. package/dist/es5/xlsx/xform/style/font-xform.js +175 -0
  323. package/dist/es5/xlsx/xform/style/font-xform.js.map +1 -0
  324. package/dist/es5/xlsx/xform/style/numfmt-xform.js +58 -0
  325. package/dist/es5/xlsx/xform/style/numfmt-xform.js.map +1 -0
  326. package/dist/es5/xlsx/xform/style/protection-xform.js +53 -0
  327. package/dist/es5/xlsx/xform/style/protection-xform.js.map +1 -0
  328. package/dist/es5/xlsx/xform/style/style-xform.js +118 -0
  329. package/dist/es5/xlsx/xform/style/style-xform.js.map +1 -0
  330. package/dist/es5/xlsx/xform/style/styles-xform.js +611 -0
  331. package/dist/es5/xlsx/xform/style/styles-xform.js.map +1 -0
  332. package/dist/es5/xlsx/xform/style/underline-xform.js +46 -0
  333. package/dist/es5/xlsx/xform/style/underline-xform.js.map +1 -0
  334. package/dist/es5/xlsx/xform/table/auto-filter-xform.js +75 -0
  335. package/dist/es5/xlsx/xform/table/auto-filter-xform.js.map +1 -0
  336. package/dist/es5/xlsx/xform/table/custom-filter-xform.js +30 -0
  337. package/dist/es5/xlsx/xform/table/custom-filter-xform.js.map +1 -0
  338. package/dist/es5/xlsx/xform/table/filter-column-xform.js +92 -0
  339. package/dist/es5/xlsx/xform/table/filter-column-xform.js.map +1 -0
  340. package/dist/es5/xlsx/xform/table/filter-xform.js +28 -0
  341. package/dist/es5/xlsx/xform/table/filter-xform.js.map +1 -0
  342. package/dist/es5/xlsx/xform/table/table-column-xform.js +42 -0
  343. package/dist/es5/xlsx/xform/table/table-column-xform.js.map +1 -0
  344. package/dist/es5/xlsx/xform/table/table-style-info-xform.js +40 -0
  345. package/dist/es5/xlsx/xform/table/table-style-info-xform.js.map +1 -0
  346. package/dist/es5/xlsx/xform/table/table-xform.js +125 -0
  347. package/dist/es5/xlsx/xform/table/table-xform.js.map +1 -0
  348. package/dist/es5/xlsx/xlsx.js +1109 -0
  349. package/dist/es5/xlsx/xlsx.js.map +1 -0
  350. package/dist/es5/xlsx/xml/theme1.js +5 -0
  351. package/dist/es5/xlsx/xml/theme1.js.map +1 -0
  352. package/dist/exceljs.bare.js +65234 -0
  353. package/dist/exceljs.bare.js.map +889 -0
  354. package/dist/exceljs.bare.min.js +45 -0
  355. package/dist/exceljs.bare.min.js.map +1 -0
  356. package/dist/exceljs.js +69987 -0
  357. package/dist/exceljs.js.map +1211 -0
  358. package/dist/exceljs.min.js +45 -0
  359. package/dist/exceljs.min.js.map +1 -0
  360. package/excel.js +13 -0
  361. package/index.d.ts +2041 -0
  362. package/index.ts +2 -0
  363. package/lib/csv/csv.js +191 -0
  364. package/lib/csv/line-buffer.js +74 -0
  365. package/lib/csv/stream-converter.js +135 -0
  366. package/lib/doc/anchor.js +91 -0
  367. package/lib/doc/cell.js +1124 -0
  368. package/lib/doc/column.js +320 -0
  369. package/lib/doc/data/theme1.json +234 -0
  370. package/lib/doc/data-validations.js +19 -0
  371. package/lib/doc/defined-names.js +196 -0
  372. package/lib/doc/enums.js +48 -0
  373. package/lib/doc/form-checkbox.js +336 -0
  374. package/lib/doc/image.js +59 -0
  375. package/lib/doc/modelcontainer.js +18 -0
  376. package/lib/doc/note.js +65 -0
  377. package/lib/doc/pivot-table.js +239 -0
  378. package/lib/doc/range.js +257 -0
  379. package/lib/doc/row.js +424 -0
  380. package/lib/doc/table.js +559 -0
  381. package/lib/doc/workbook.js +240 -0
  382. package/lib/doc/worksheet.js +1041 -0
  383. package/lib/exceljs.bare.js +13 -0
  384. package/lib/exceljs.browser.js +36 -0
  385. package/lib/exceljs.nodejs.js +14 -0
  386. package/lib/stream/xlsx/hyperlink-reader.js +83 -0
  387. package/lib/stream/xlsx/sheet-comments-writer.js +121 -0
  388. package/lib/stream/xlsx/sheet-rels-writer.js +119 -0
  389. package/lib/stream/xlsx/workbook-reader.js +336 -0
  390. package/lib/stream/xlsx/workbook-writer.js +347 -0
  391. package/lib/stream/xlsx/worksheet-reader.js +374 -0
  392. package/lib/stream/xlsx/worksheet-writer.js +717 -0
  393. package/lib/utils/auto-drain.js +15 -0
  394. package/lib/utils/browser-buffer-decode.js +14 -0
  395. package/lib/utils/browser-buffer-encode.js +15 -0
  396. package/lib/utils/cell-matrix.js +165 -0
  397. package/lib/utils/col-cache.js +287 -0
  398. package/lib/utils/copy-style.js +43 -0
  399. package/lib/utils/encryptor.js +55 -0
  400. package/lib/utils/iterate-stream.js +48 -0
  401. package/lib/utils/parse-sax.js +43 -0
  402. package/lib/utils/shared-formula.js +44 -0
  403. package/lib/utils/shared-strings.js +42 -0
  404. package/lib/utils/stream-base64.js +72 -0
  405. package/lib/utils/stream-buf.js +387 -0
  406. package/lib/utils/string-buf.js +82 -0
  407. package/lib/utils/string-builder.js +35 -0
  408. package/lib/utils/stuttered-pipe.js +67 -0
  409. package/lib/utils/typed-stack.js +24 -0
  410. package/lib/utils/under-dash.js +184 -0
  411. package/lib/utils/utils.js +206 -0
  412. package/lib/utils/xml-stream.js +169 -0
  413. package/lib/utils/zip-stream.js +87 -0
  414. package/lib/xlsx/.rels +11 -0
  415. package/lib/xlsx/calcChain.xml +6 -0
  416. package/lib/xlsx/core.xml +7 -0
  417. package/lib/xlsx/defaultnumformats.js +153 -0
  418. package/lib/xlsx/rel-type.js +27 -0
  419. package/lib/xlsx/styles.xml +41 -0
  420. package/lib/xlsx/workbook.xml +16 -0
  421. package/lib/xlsx/xform/base-xform.js +145 -0
  422. package/lib/xlsx/xform/book/defined-name-xform.js +91 -0
  423. package/lib/xlsx/xform/book/sheet-xform.js +34 -0
  424. package/lib/xlsx/xform/book/workbook-calc-properties-xform.js +26 -0
  425. package/lib/xlsx/xform/book/workbook-pivot-cache-xform.js +29 -0
  426. package/lib/xlsx/xform/book/workbook-properties-xform.js +29 -0
  427. package/lib/xlsx/xform/book/workbook-view-xform.js +53 -0
  428. package/lib/xlsx/xform/book/workbook-xform.js +265 -0
  429. package/lib/xlsx/xform/comment/comment-xform.js +105 -0
  430. package/lib/xlsx/xform/comment/comments-xform.js +82 -0
  431. package/lib/xlsx/xform/comment/style/vml-position-xform.js +39 -0
  432. package/lib/xlsx/xform/comment/style/vml-protection-xform.js +36 -0
  433. package/lib/xlsx/xform/comment/vml-anchor-xform.js +60 -0
  434. package/lib/xlsx/xform/comment/vml-client-data-xform.js +92 -0
  435. package/lib/xlsx/xform/comment/vml-notes-xform.js +217 -0
  436. package/lib/xlsx/xform/comment/vml-shape-xform.js +95 -0
  437. package/lib/xlsx/xform/comment/vml-textbox-xform.js +64 -0
  438. package/lib/xlsx/xform/composite-xform.js +56 -0
  439. package/lib/xlsx/xform/core/app-heading-pairs-xform.js +32 -0
  440. package/lib/xlsx/xform/core/app-titles-of-parts-xform.js +28 -0
  441. package/lib/xlsx/xform/core/app-xform.js +100 -0
  442. package/lib/xlsx/xform/core/content-types-xform.js +211 -0
  443. package/lib/xlsx/xform/core/core-xform.js +142 -0
  444. package/lib/xlsx/xform/core/relationship-xform.js +25 -0
  445. package/lib/xlsx/xform/core/relationships-xform.js +73 -0
  446. package/lib/xlsx/xform/drawing/base-cell-anchor-xform.js +48 -0
  447. package/lib/xlsx/xform/drawing/blip-fill-xform.js +71 -0
  448. package/lib/xlsx/xform/drawing/blip-xform.js +42 -0
  449. package/lib/xlsx/xform/drawing/c-nv-pic-pr-xform.js +38 -0
  450. package/lib/xlsx/xform/drawing/c-nv-pr-xform.js +68 -0
  451. package/lib/xlsx/xform/drawing/cell-position-xform.js +77 -0
  452. package/lib/xlsx/xform/drawing/ctrl-prop-xform.js +74 -0
  453. package/lib/xlsx/xform/drawing/drawing-xform.js +109 -0
  454. package/lib/xlsx/xform/drawing/ext-lst-xform.js +43 -0
  455. package/lib/xlsx/xform/drawing/ext-xform.js +44 -0
  456. package/lib/xlsx/xform/drawing/hlink-click-xform.js +41 -0
  457. package/lib/xlsx/xform/drawing/nv-pic-pr-xform.js +65 -0
  458. package/lib/xlsx/xform/drawing/one-cell-anchor-xform.js +63 -0
  459. package/lib/xlsx/xform/drawing/pic-xform.js +77 -0
  460. package/lib/xlsx/xform/drawing/sp-pr.js +17 -0
  461. package/lib/xlsx/xform/drawing/two-cell-anchor-xform.js +62 -0
  462. package/lib/xlsx/xform/list-xform.js +95 -0
  463. package/lib/xlsx/xform/pivot-table/cache-field.js +74 -0
  464. package/lib/xlsx/xform/pivot-table/pivot-cache-definition-xform.js +77 -0
  465. package/lib/xlsx/xform/pivot-table/pivot-cache-records-xform.js +107 -0
  466. package/lib/xlsx/xform/pivot-table/pivot-table-xform.js +265 -0
  467. package/lib/xlsx/xform/sheet/auto-filter-xform.js +38 -0
  468. package/lib/xlsx/xform/sheet/cell-xform.js +498 -0
  469. package/lib/xlsx/xform/sheet/cf/cf-rule-xform.js +308 -0
  470. package/lib/xlsx/xform/sheet/cf/cfvo-xform.js +27 -0
  471. package/lib/xlsx/xform/sheet/cf/color-scale-xform.js +45 -0
  472. package/lib/xlsx/xform/sheet/cf/conditional-formatting-xform.js +48 -0
  473. package/lib/xlsx/xform/sheet/cf/conditional-formattings-xform.js +92 -0
  474. package/lib/xlsx/xform/sheet/cf/databar-xform.js +56 -0
  475. package/lib/xlsx/xform/sheet/cf/ext-lst-ref-xform.js +87 -0
  476. package/lib/xlsx/xform/sheet/cf/formula-xform.js +25 -0
  477. package/lib/xlsx/xform/sheet/cf/icon-set-xform.js +47 -0
  478. package/lib/xlsx/xform/sheet/cf-ext/cf-icon-ext-xform.js +27 -0
  479. package/lib/xlsx/xform/sheet/cf-ext/cf-rule-ext-xform.js +98 -0
  480. package/lib/xlsx/xform/sheet/cf-ext/cfvo-ext-xform.js +43 -0
  481. package/lib/xlsx/xform/sheet/cf-ext/conditional-formatting-ext-xform.js +62 -0
  482. package/lib/xlsx/xform/sheet/cf-ext/conditional-formattings-ext-xform.js +50 -0
  483. package/lib/xlsx/xform/sheet/cf-ext/databar-ext-xform.js +102 -0
  484. package/lib/xlsx/xform/sheet/cf-ext/f-ext-xform.js +25 -0
  485. package/lib/xlsx/xform/sheet/cf-ext/icon-set-ext-xform.js +73 -0
  486. package/lib/xlsx/xform/sheet/cf-ext/sqref-ext-xform.js +25 -0
  487. package/lib/xlsx/xform/sheet/col-xform.js +86 -0
  488. package/lib/xlsx/xform/sheet/data-validations-xform.js +257 -0
  489. package/lib/xlsx/xform/sheet/dimension-xform.js +29 -0
  490. package/lib/xlsx/xform/sheet/drawing-xform.js +33 -0
  491. package/lib/xlsx/xform/sheet/ext-lst-xform.js +86 -0
  492. package/lib/xlsx/xform/sheet/header-footer-xform.js +146 -0
  493. package/lib/xlsx/xform/sheet/hyperlink-xform.js +54 -0
  494. package/lib/xlsx/xform/sheet/merge-cell-xform.js +27 -0
  495. package/lib/xlsx/xform/sheet/merges.js +56 -0
  496. package/lib/xlsx/xform/sheet/outline-properties-xform.js +43 -0
  497. package/lib/xlsx/xform/sheet/page-breaks-xform.js +27 -0
  498. package/lib/xlsx/xform/sheet/page-margins-xform.js +49 -0
  499. package/lib/xlsx/xform/sheet/page-setup-properties-xform.js +35 -0
  500. package/lib/xlsx/xform/sheet/page-setup-xform.js +103 -0
  501. package/lib/xlsx/xform/sheet/picture-xform.js +33 -0
  502. package/lib/xlsx/xform/sheet/print-options-xform.js +49 -0
  503. package/lib/xlsx/xform/sheet/row-breaks-xform.js +39 -0
  504. package/lib/xlsx/xform/sheet/row-xform.js +145 -0
  505. package/lib/xlsx/xform/sheet/sheet-format-properties-xform.js +67 -0
  506. package/lib/xlsx/xform/sheet/sheet-properties-xform.js +90 -0
  507. package/lib/xlsx/xform/sheet/sheet-protection-xform.js +89 -0
  508. package/lib/xlsx/xform/sheet/sheet-view-xform.js +202 -0
  509. package/lib/xlsx/xform/sheet/table-part-xform.js +33 -0
  510. package/lib/xlsx/xform/sheet/worksheet-xform.js +657 -0
  511. package/lib/xlsx/xform/simple/boolean-xform.js +31 -0
  512. package/lib/xlsx/xform/simple/date-xform.js +66 -0
  513. package/lib/xlsx/xform/simple/float-xform.js +51 -0
  514. package/lib/xlsx/xform/simple/integer-xform.js +57 -0
  515. package/lib/xlsx/xform/simple/string-xform.js +51 -0
  516. package/lib/xlsx/xform/static-xform.js +64 -0
  517. package/lib/xlsx/xform/strings/phonetic-text-xform.js +98 -0
  518. package/lib/xlsx/xform/strings/rich-text-xform.js +101 -0
  519. package/lib/xlsx/xform/strings/shared-string-xform.js +102 -0
  520. package/lib/xlsx/xform/strings/shared-strings-xform.js +132 -0
  521. package/lib/xlsx/xform/strings/text-xform.js +44 -0
  522. package/lib/xlsx/xform/style/alignment-xform.js +172 -0
  523. package/lib/xlsx/xform/style/border-xform.js +207 -0
  524. package/lib/xlsx/xform/style/color-xform.js +63 -0
  525. package/lib/xlsx/xform/style/dxf-xform.js +111 -0
  526. package/lib/xlsx/xform/style/fill-xform.js +364 -0
  527. package/lib/xlsx/xform/style/font-xform.js +102 -0
  528. package/lib/xlsx/xform/style/numfmt-xform.js +63 -0
  529. package/lib/xlsx/xform/style/protection-xform.js +60 -0
  530. package/lib/xlsx/xform/style/style-xform.js +125 -0
  531. package/lib/xlsx/xform/style/styles-xform.js +527 -0
  532. package/lib/xlsx/xform/style/underline-xform.js +47 -0
  533. package/lib/xlsx/xform/table/auto-filter-xform.js +81 -0
  534. package/lib/xlsx/xform/table/custom-filter-xform.js +33 -0
  535. package/lib/xlsx/xform/table/filter-column-xform.js +99 -0
  536. package/lib/xlsx/xform/table/filter-xform.js +31 -0
  537. package/lib/xlsx/xform/table/table-column-xform.js +44 -0
  538. package/lib/xlsx/xform/table/table-style-info-xform.js +41 -0
  539. package/lib/xlsx/xform/table/table-xform.js +134 -0
  540. package/lib/xlsx/xlsx.js +1160 -0
  541. package/lib/xlsx/xml/theme1.js +3 -0
  542. package/lib/xlsx/xml/theme1.xml +318 -0
  543. package/package.json +159 -0
@@ -0,0 +1,1160 @@
1
+ const fs = require('fs');
2
+ const JSZip = require('jszip');
3
+ const {PassThrough} = require('readable-stream');
4
+ const ZipStream = require('../utils/zip-stream');
5
+ const StreamBuf = require('../utils/stream-buf');
6
+
7
+ const utils = require('../utils/utils');
8
+ const XmlStream = require('../utils/xml-stream');
9
+ const {bufferToString} = require('../utils/browser-buffer-decode');
10
+
11
+ const StylesXform = require('./xform/style/styles-xform');
12
+
13
+ const CoreXform = require('./xform/core/core-xform');
14
+ const SharedStringsXform = require('./xform/strings/shared-strings-xform');
15
+ const RelationshipsXform = require('./xform/core/relationships-xform');
16
+ const ContentTypesXform = require('./xform/core/content-types-xform');
17
+ const AppXform = require('./xform/core/app-xform');
18
+ const WorkbookXform = require('./xform/book/workbook-xform');
19
+ const WorksheetXform = require('./xform/sheet/worksheet-xform');
20
+ const DrawingXform = require('./xform/drawing/drawing-xform');
21
+ const TableXform = require('./xform/table/table-xform');
22
+ const PivotCacheRecordsXform = require('./xform/pivot-table/pivot-cache-records-xform');
23
+ const PivotCacheDefinitionXform = require('./xform/pivot-table/pivot-cache-definition-xform');
24
+ const PivotTableXform = require('./xform/pivot-table/pivot-table-xform');
25
+ const CommentsXform = require('./xform/comment/comments-xform');
26
+ const VmlNotesXform = require('./xform/comment/vml-notes-xform');
27
+ const CtrlPropXform = require('./xform/drawing/ctrl-prop-xform');
28
+
29
+ const theme1Xml = require('./xml/theme1');
30
+ const RelType = require('./rel-type');
31
+
32
+ function fsReadFileAsync(filename, options) {
33
+ return new Promise((resolve, reject) => {
34
+ fs.readFile(filename, options, (error, data) => {
35
+ if (error) {
36
+ reject(error);
37
+ } else {
38
+ resolve(data);
39
+ }
40
+ });
41
+ });
42
+ }
43
+
44
+ class XLSX {
45
+ constructor(workbook) {
46
+ this.workbook = workbook;
47
+ }
48
+
49
+ // ===============================================================================
50
+ // Workbook
51
+ // =========================================================================
52
+ // Read
53
+
54
+ async readFile(filename, options) {
55
+ if (!(await utils.fs.exists(filename))) {
56
+ throw new Error(`File not found: ${filename}`);
57
+ }
58
+ const stream = fs.createReadStream(filename);
59
+ try {
60
+ const workbook = await this.read(stream, options);
61
+ stream.close();
62
+ return workbook;
63
+ } catch (error) {
64
+ stream.close();
65
+ throw error;
66
+ }
67
+ }
68
+
69
+ parseRels(stream) {
70
+ const xform = new RelationshipsXform();
71
+ return xform.parseStream(stream);
72
+ }
73
+
74
+ parseWorkbook(stream) {
75
+ const xform = new WorkbookXform();
76
+ return xform.parseStream(stream);
77
+ }
78
+
79
+ parseSharedStrings(stream) {
80
+ const xform = new SharedStringsXform();
81
+ return xform.parseStream(stream);
82
+ }
83
+
84
+ reconcile(model, options) {
85
+ const workbookXform = new WorkbookXform();
86
+ const worksheetXform = new WorksheetXform(options);
87
+ const drawingXform = new DrawingXform();
88
+ const tableXform = new TableXform();
89
+
90
+ workbookXform.reconcile(model);
91
+
92
+ // reconcile drawings with their rels
93
+ const drawingOptions = {
94
+ media: model.media,
95
+ mediaIndex: model.mediaIndex,
96
+ };
97
+ Object.keys(model.drawings).forEach(name => {
98
+ const drawing = model.drawings[name];
99
+ const drawingRel = model.drawingRels[name];
100
+ if (drawingRel) {
101
+ drawingOptions.rels = drawingRel.reduce((o, rel) => {
102
+ o[rel.Id] = rel;
103
+ return o;
104
+ }, {});
105
+ (drawing.anchors || []).forEach(anchor => {
106
+ const hyperlinks = anchor.picture && anchor.picture.hyperlinks;
107
+ if (hyperlinks && drawingOptions.rels[hyperlinks.rId]) {
108
+ hyperlinks.hyperlink = drawingOptions.rels[hyperlinks.rId].Target;
109
+ delete hyperlinks.rId;
110
+ }
111
+ });
112
+ drawingXform.reconcile(drawing, drawingOptions);
113
+ }
114
+ });
115
+
116
+ // reconcile tables with the default styles
117
+ const tableOptions = {
118
+ styles: model.styles,
119
+ };
120
+ Object.values(model.tables).forEach(table => {
121
+ tableXform.reconcile(table, tableOptions);
122
+ });
123
+
124
+ const sheetOptions = {
125
+ styles: model.styles,
126
+ sharedStrings: model.sharedStrings,
127
+ media: model.media,
128
+ mediaIndex: model.mediaIndex,
129
+ date1904: model.properties && model.properties.date1904,
130
+ drawings: model.drawings,
131
+ comments: model.comments,
132
+ tables: model.tables,
133
+ vmlDrawings: model.vmlDrawings,
134
+ preservedPivotTablesXml: model.preservedPivotTablesXml,
135
+ preservedPivotTablesRels: model.preservedPivotTablesRels,
136
+ preservedDrawingsXml: model.preservedDrawingsXml,
137
+ preservedDrawingsRels: model.preservedDrawingsRels,
138
+ };
139
+ model.worksheets.forEach(worksheet => {
140
+ worksheet.relationships = model.worksheetRels[worksheet.sheetNo];
141
+ worksheetXform.reconcile(worksheet, sheetOptions);
142
+ });
143
+
144
+ // Collect preserved pivot tables for write
145
+ model.preservedPivotTables = {
146
+ pivotTables: model.preservedPivotTablesXml,
147
+ pivotCacheDefinitions: model.preservedPivotCacheDefinitionsXml,
148
+ pivotCacheRecords: model.preservedPivotCacheRecordsXml,
149
+ };
150
+
151
+ // Extract cache IDs from preserved pivot tables and create pivot cache entries
152
+ // These will be used by workbook-xform to write the <pivotCaches> section
153
+ const preservedCaches = [];
154
+ const cacheIdToFilename = {}; // Map cacheId to actual filename
155
+
156
+ // First, build a map of cacheId to definition filename by checking the pivot table rels
157
+ model.worksheets.forEach(worksheet => {
158
+ if (worksheet.pivotTables && worksheet.pivotTables.length > 0) {
159
+ worksheet.pivotTables.forEach(pivotTable => {
160
+ if (pivotTable.xml && pivotTable.rels) {
161
+ // Extract cacheId from the pivot table XML
162
+ const cacheIdMatch = pivotTable.xml.match(/cacheId="(\d+)"/);
163
+ if (cacheIdMatch) {
164
+ const cacheId = cacheIdMatch[1];
165
+ // Find the pivot cache definition relationship
166
+ // pivotTable.rels should have a relationship to the cache definition
167
+ const cacheDefRel = pivotTable.rels.find(
168
+ rel => rel.Type === RelType.PivotCacheDefinition
169
+ );
170
+ if (cacheDefRel) {
171
+ // Extract filename from Target like "../pivotCache/pivotCacheDefinition1.xml"
172
+ const targetMatch = cacheDefRel.Target.match(/pivotCacheDefinition\d+\.xml/);
173
+ if (targetMatch) {
174
+ cacheIdToFilename[cacheId] = targetMatch[0];
175
+ }
176
+ }
177
+ }
178
+ }
179
+ });
180
+ }
181
+ });
182
+
183
+ // Now create the preserved cache entries with correct filenames
184
+ Object.keys(cacheIdToFilename).forEach(cacheId => {
185
+ preservedCaches.push({
186
+ cacheId,
187
+ definitionFilename: cacheIdToFilename[cacheId],
188
+ isPreserved: true,
189
+ });
190
+ });
191
+
192
+ model.preservedPivotCaches = preservedCaches;
193
+
194
+ // delete unnecessary parts
195
+ delete model.worksheetHash;
196
+ delete model.worksheetRels;
197
+ delete model.globalRels;
198
+ delete model.sharedStrings;
199
+ delete model.workbookRels;
200
+ delete model.sheetDefs;
201
+ delete model.styles;
202
+ delete model.mediaIndex;
203
+ delete model.drawings;
204
+ delete model.drawingRels;
205
+ delete model.vmlDrawings;
206
+ delete model.preservedPivotTablesRels;
207
+ delete model.preservedPivotCacheDefinitionsRels;
208
+ // Keep the XML dictionaries through preservedPivotTables
209
+ }
210
+
211
+ async _processWorksheetEntry(stream, model, sheetNo, options, path) {
212
+ const xform = new WorksheetXform(options);
213
+ const worksheet = await xform.parseStream(stream);
214
+ worksheet.sheetNo = sheetNo;
215
+ model.worksheetHash[path] = worksheet;
216
+ model.worksheets.push(worksheet);
217
+ }
218
+
219
+ async _processCommentEntry(stream, model, name) {
220
+ const xform = new CommentsXform();
221
+ const comments = await xform.parseStream(stream);
222
+ model.comments[`../${name}.xml`] = comments;
223
+ }
224
+
225
+ async _processTableEntry(stream, model, name) {
226
+ const xform = new TableXform();
227
+ const table = await xform.parseStream(stream);
228
+ model.tables[`../tables/${name}.xml`] = table;
229
+ }
230
+
231
+ async _processWorksheetRelsEntry(stream, model, sheetNo) {
232
+ const xform = new RelationshipsXform();
233
+ const relationships = await xform.parseStream(stream);
234
+ model.worksheetRels[sheetNo] = relationships;
235
+ }
236
+
237
+ async _processMediaEntry(entry, model, filename) {
238
+ const lastDot = filename.lastIndexOf('.');
239
+ // if we can't determine extension, ignore it
240
+ if (lastDot >= 1) {
241
+ const extension = filename.substr(lastDot + 1);
242
+ const name = filename.substr(0, lastDot);
243
+ await new Promise((resolve, reject) => {
244
+ const streamBuf = new StreamBuf();
245
+ streamBuf.on('finish', () => {
246
+ model.mediaIndex[filename] = model.media.length;
247
+ model.mediaIndex[name] = model.media.length;
248
+ const medium = {
249
+ type: 'image',
250
+ name,
251
+ extension,
252
+ buffer: streamBuf.toBuffer(),
253
+ };
254
+ model.media.push(medium);
255
+ resolve();
256
+ });
257
+ entry.on('error', error => {
258
+ reject(error);
259
+ });
260
+ entry.pipe(streamBuf);
261
+ });
262
+ }
263
+ }
264
+
265
+ async _processDrawingEntry(entry, model, name) {
266
+ // Check if drawing contains chart references
267
+ const xml = await entry.async('string');
268
+ const hasChart = xml.includes('drawingml/2006/chart');
269
+
270
+ if (hasChart) {
271
+ // Preserve as raw XML if it contains charts
272
+ model.preservedDrawingsXml[name] = xml;
273
+ } else {
274
+ // Parse normally for images and other content
275
+ // Re-create a stream from the XML we already read using StreamBuf
276
+ const stream = new StreamBuf();
277
+ stream.write(xml);
278
+ stream.end();
279
+ const xform = new DrawingXform();
280
+ const drawing = await xform.parseStream(stream);
281
+ model.drawings[name] = drawing;
282
+ }
283
+ }
284
+
285
+ async _processDrawingRelsEntry(entry, model, name) {
286
+ const xform = new RelationshipsXform();
287
+ const relationships = await xform.parseStream(entry);
288
+ model.drawingRels[name] = relationships;
289
+
290
+ // Also preserve raw relationships for preserved drawings
291
+ if (model.preservedDrawingsXml[name]) {
292
+ model.preservedDrawingsRels[name] = relationships;
293
+ }
294
+ }
295
+
296
+ async _processVmlDrawingEntry(entry, model, name) {
297
+ const xform = new VmlNotesXform();
298
+ const vmlDrawing = await xform.parseStream(entry);
299
+ model.vmlDrawings[`../drawings/${name}.vml`] = vmlDrawing;
300
+ }
301
+
302
+ async _processPivotTableEntry(zipEntry, model, name) {
303
+ // Read XML directly from zip entry
304
+ const xml = await zipEntry.async('string');
305
+ model.preservedPivotTablesXml[name] = xml;
306
+ }
307
+
308
+ async _processPivotTableRelsEntry(stream, model, name) {
309
+ const xform = new RelationshipsXform();
310
+ const relationships = await xform.parseStream(stream);
311
+ model.preservedPivotTablesRels[name] = relationships;
312
+ }
313
+
314
+ async _processPivotCacheDefinitionEntry(zipEntry, model, name) {
315
+ // Read XML directly from zip entry
316
+ const xml = await zipEntry.async('string');
317
+ model.preservedPivotCacheDefinitionsXml[name] = xml;
318
+ }
319
+
320
+ async _processPivotCacheDefinitionRelsEntry(stream, model, name) {
321
+ const xform = new RelationshipsXform();
322
+ const relationships = await xform.parseStream(stream);
323
+ model.preservedPivotCacheDefinitionsRels[name] = relationships;
324
+ }
325
+
326
+ async _processPivotCacheRecordsEntry(zipEntry, model, name) {
327
+ // Read XML directly from zip entry
328
+ const xml = await zipEntry.async('string');
329
+ model.preservedPivotCacheRecordsXml[name] = xml;
330
+ }
331
+
332
+ async _processChartEntry(zipEntry, model, name) {
333
+ // Read XML directly from zip entry
334
+ const xml = await zipEntry.async('string');
335
+ model.preservedChartsXml[name] = xml;
336
+ }
337
+
338
+ async _processChartRelsEntry(stream, model, name) {
339
+ const xform = new RelationshipsXform();
340
+ const relationships = await xform.parseStream(stream);
341
+ model.preservedChartsRels[name] = relationships;
342
+ }
343
+
344
+ async _processChartStyleEntry(zipEntry, model, name) {
345
+ // Read XML directly from zip entry
346
+ const xml = await zipEntry.async('string');
347
+ model.preservedChartStylesXml[name] = xml;
348
+ }
349
+
350
+ async _processChartColorsEntry(zipEntry, model, name) {
351
+ // Read XML directly from zip entry
352
+ const xml = await zipEntry.async('string');
353
+ model.preservedChartColorsXml[name] = xml;
354
+ }
355
+
356
+ async _processThemeEntry(entry, model, name) {
357
+ await new Promise((resolve, reject) => {
358
+ // TODO: stream entry into buffer and store the xml in the model.themes[]
359
+ const stream = new StreamBuf();
360
+ entry.on('error', reject);
361
+ stream.on('error', reject);
362
+ stream.on('finish', () => {
363
+ model.themes[name] = stream.read().toString();
364
+ resolve();
365
+ });
366
+ entry.pipe(stream);
367
+ });
368
+ }
369
+
370
+ /**
371
+ * @deprecated since version 4.0. You should use `#read` instead. Please follow upgrade instruction: https://github.com/exceljs/exceljs/blob/master/UPGRADE-4.0.md
372
+ */
373
+ createInputStream() {
374
+ throw new Error(
375
+ '`XLSX#createInputStream` is deprecated. You should use `XLSX#read` instead. This method will be removed in version 5.0. Please follow upgrade instruction: https://github.com/exceljs/exceljs/blob/master/UPGRADE-4.0.md'
376
+ );
377
+ }
378
+
379
+ async read(stream, options) {
380
+ // TODO: Remove once node v8 is deprecated
381
+ // Detect and upgrade old streams
382
+ if (!stream[Symbol.asyncIterator] && stream.pipe) {
383
+ stream = stream.pipe(new PassThrough());
384
+ }
385
+ const chunks = [];
386
+ for await (const chunk of stream) {
387
+ chunks.push(chunk);
388
+ }
389
+ return this.load(Buffer.concat(chunks), options);
390
+ }
391
+
392
+ async load(data, options) {
393
+ let buffer;
394
+ if (options && options.base64) {
395
+ buffer = Buffer.from(data.toString(), 'base64');
396
+ } else {
397
+ buffer = data;
398
+ }
399
+
400
+ const model = {
401
+ worksheets: [],
402
+ worksheetHash: {},
403
+ worksheetRels: [],
404
+ themes: {},
405
+ media: [],
406
+ mediaIndex: {},
407
+ drawings: {},
408
+ drawingRels: {},
409
+ comments: {},
410
+ tables: {},
411
+ vmlDrawings: {},
412
+ pivotTables: [], // Keep as array for programmatic pivots
413
+ preservedPivotTablesXml: {},
414
+ preservedPivotTablesRels: {},
415
+ preservedPivotCacheDefinitionsXml: {},
416
+ preservedPivotCacheDefinitionsRels: {},
417
+ preservedPivotCacheRecordsXml: {},
418
+ preservedChartsXml: {},
419
+ preservedChartsRels: {},
420
+ preservedChartStylesXml: {},
421
+ preservedChartColorsXml: {},
422
+ preservedDrawingsXml: {},
423
+ preservedDrawingsRels: {},
424
+ };
425
+
426
+ const zip = await JSZip.loadAsync(buffer);
427
+ for (const entry of Object.values(zip.files)) {
428
+ /* eslint-disable no-await-in-loop */
429
+ if (!entry.dir) {
430
+ let entryName = entry.name;
431
+ if (entryName[0] === '/') {
432
+ entryName = entryName.substr(1);
433
+ }
434
+ let stream;
435
+ if (
436
+ entryName.match(/xl\/media\//) ||
437
+ // themes are not parsed as stream
438
+ entryName.match(/xl\/theme\/([a-zA-Z0-9]+)[.]xml/)
439
+ ) {
440
+ stream = new PassThrough();
441
+ stream.write(await entry.async('nodebuffer'));
442
+ } else {
443
+ // use object mode to avoid buffer-string convention
444
+ stream = new PassThrough({
445
+ writableObjectMode: true,
446
+ readableObjectMode: true,
447
+ });
448
+ let content;
449
+ // https://www.npmjs.com/package/process
450
+ if (process.browser) {
451
+ // running in browser, use TextDecoder if possible
452
+ content = bufferToString(await entry.async('nodebuffer'));
453
+ } else {
454
+ // running in node.js
455
+ content = await entry.async('string');
456
+ }
457
+ const chunkSize = 16 * 1024;
458
+ for (let i = 0; i < content.length; i += chunkSize) {
459
+ stream.write(content.substring(i, i + chunkSize));
460
+ }
461
+ }
462
+ stream.end();
463
+ switch (entryName) {
464
+ case '_rels/.rels':
465
+ model.globalRels = await this.parseRels(stream);
466
+ break;
467
+
468
+ case 'xl/workbook.xml': {
469
+ const workbook = await this.parseWorkbook(stream);
470
+ if (workbook) {
471
+ model.sheets = workbook.sheets;
472
+ model.definedNames = workbook.definedNames;
473
+ model.views = workbook.views;
474
+ model.properties = workbook.properties;
475
+ model.calcProperties = workbook.calcProperties;
476
+ }
477
+ break;
478
+ }
479
+
480
+ case 'xl/_rels/workbook.xml.rels':
481
+ model.workbookRels = await this.parseRels(stream);
482
+ break;
483
+
484
+ case 'xl/sharedStrings.xml':
485
+ model.sharedStrings = new SharedStringsXform();
486
+ await model.sharedStrings.parseStream(stream);
487
+ break;
488
+
489
+ case 'xl/styles.xml':
490
+ model.styles = new StylesXform();
491
+ await model.styles.parseStream(stream);
492
+ break;
493
+
494
+ case 'docProps/app.xml': {
495
+ const appXform = new AppXform();
496
+ const appProperties = await appXform.parseStream(stream);
497
+ if (appProperties) {
498
+ model.company = appProperties.company;
499
+ model.manager = appProperties.manager;
500
+ }
501
+ break;
502
+ }
503
+
504
+ case 'docProps/core.xml': {
505
+ const coreXform = new CoreXform();
506
+ const coreProperties = await coreXform.parseStream(stream);
507
+ if (coreProperties) {
508
+ Object.assign(model, coreProperties);
509
+ }
510
+ break;
511
+ }
512
+
513
+ default: {
514
+ let match = entryName.match(/xl\/worksheets\/sheet(\d+)[.]xml/);
515
+ if (match) {
516
+ await this._processWorksheetEntry(stream, model, match[1], options, entryName);
517
+ break;
518
+ }
519
+ match = entryName.match(/xl\/worksheets\/_rels\/sheet(\d+)[.]xml.rels/);
520
+ if (match) {
521
+ await this._processWorksheetRelsEntry(stream, model, match[1]);
522
+ break;
523
+ }
524
+ match = entryName.match(/xl\/theme\/([a-zA-Z0-9]+)[.]xml/);
525
+ if (match) {
526
+ await this._processThemeEntry(stream, model, match[1]);
527
+ break;
528
+ }
529
+ match = entryName.match(/xl\/media\/([a-zA-Z0-9]+[.][a-zA-Z0-9]{3,4})$/);
530
+ if (match) {
531
+ await this._processMediaEntry(stream, model, match[1]);
532
+ break;
533
+ }
534
+ match = entryName.match(/xl\/drawings\/([a-zA-Z0-9]+)[.]xml/);
535
+ if (match) {
536
+ await this._processDrawingEntry(entry, model, match[1]);
537
+ break;
538
+ }
539
+ match = entryName.match(/xl\/(comments\d+)[.]xml/);
540
+ if (match) {
541
+ await this._processCommentEntry(stream, model, match[1]);
542
+ break;
543
+ }
544
+ match = entryName.match(/xl\/tables\/(table\d+)[.]xml/);
545
+ if (match) {
546
+ await this._processTableEntry(stream, model, match[1]);
547
+ break;
548
+ }
549
+ match = entryName.match(/xl\/drawings\/_rels\/([a-zA-Z0-9]+)[.]xml[.]rels/);
550
+ if (match) {
551
+ await this._processDrawingRelsEntry(stream, model, match[1]);
552
+ break;
553
+ }
554
+ match = entryName.match(/xl\/drawings\/(vmlDrawing\d+)[.]vml/);
555
+ if (match) {
556
+ await this._processVmlDrawingEntry(stream, model, match[1]);
557
+ break;
558
+ }
559
+ match = entryName.match(/xl\/pivotTables\/(pivotTable\d+)[.]xml/);
560
+ if (match) {
561
+ await this._processPivotTableEntry(entry, model, match[1]);
562
+ break;
563
+ }
564
+ match = entryName.match(/xl\/pivotTables\/_rels\/(pivotTable\d+)[.]xml[.]rels/);
565
+ if (match) {
566
+ await this._processPivotTableRelsEntry(stream, model, match[1]);
567
+ break;
568
+ }
569
+ match = entryName.match(/xl\/pivotCache\/(pivotCacheDefinition\d+)[.]xml/);
570
+ if (match) {
571
+ await this._processPivotCacheDefinitionEntry(entry, model, match[1]);
572
+ break;
573
+ }
574
+ match = entryName.match(/xl\/pivotCache\/_rels\/(pivotCacheDefinition\d+)[.]xml[.]rels/);
575
+ if (match) {
576
+ await this._processPivotCacheDefinitionRelsEntry(stream, model, match[1]);
577
+ break;
578
+ }
579
+ match = entryName.match(/xl\/pivotCache\/(pivotCacheRecords\d+)[.]xml/);
580
+ if (match) {
581
+ await this._processPivotCacheRecordsEntry(entry, model, match[1]);
582
+ break;
583
+ }
584
+ match = entryName.match(/xl\/charts\/(chart\d+)[.]xml/);
585
+ if (match) {
586
+ await this._processChartEntry(entry, model, match[1]);
587
+ break;
588
+ }
589
+ match = entryName.match(/xl\/charts\/_rels\/(chart\d+)[.]xml[.]rels/);
590
+ if (match) {
591
+ await this._processChartRelsEntry(stream, model, match[1]);
592
+ break;
593
+ }
594
+ match = entryName.match(/xl\/charts\/(style\d+)[.]xml/);
595
+ if (match) {
596
+ await this._processChartStyleEntry(entry, model, match[1]);
597
+ break;
598
+ }
599
+ match = entryName.match(/xl\/charts\/(colors\d+)[.]xml/);
600
+ if (match) {
601
+ await this._processChartColorsEntry(entry, model, match[1]);
602
+ break;
603
+ }
604
+ }
605
+ }
606
+ }
607
+ }
608
+
609
+ this.reconcile(model, options);
610
+
611
+ // apply model
612
+ this.workbook.model = model;
613
+ return this.workbook;
614
+ }
615
+
616
+ // =========================================================================
617
+ // Write
618
+
619
+ async addMedia(zip, model) {
620
+ await Promise.all(
621
+ model.media.map(async medium => {
622
+ if (medium.type === 'image') {
623
+ const filename = `xl/media/${medium.name}.${medium.extension}`;
624
+ if (medium.filename) {
625
+ const data = await fsReadFileAsync(medium.filename);
626
+ return zip.append(data, {name: filename});
627
+ }
628
+ if (medium.buffer) {
629
+ return zip.append(medium.buffer, {name: filename});
630
+ }
631
+ if (medium.base64) {
632
+ const dataimg64 = medium.base64;
633
+ const content = dataimg64.substring(dataimg64.indexOf(',') + 1);
634
+ return zip.append(content, {name: filename, base64: true});
635
+ }
636
+ }
637
+ throw new Error('Unsupported media');
638
+ })
639
+ );
640
+ }
641
+
642
+ addDrawings(zip, model) {
643
+ const drawingXform = new DrawingXform();
644
+ const relsXform = new RelationshipsXform();
645
+
646
+ // First add preserved drawings (with charts)
647
+ if (model.preservedDrawingsXml) {
648
+ Object.keys(model.preservedDrawingsXml).forEach(name => {
649
+ zip.append(model.preservedDrawingsXml[name], {
650
+ name: `xl/drawings/${name}.xml`,
651
+ });
652
+ });
653
+ }
654
+
655
+ if (model.preservedDrawingsRels) {
656
+ Object.keys(model.preservedDrawingsRels).forEach(name => {
657
+ const xml = relsXform.toXml(model.preservedDrawingsRels[name]);
658
+ zip.append(xml, {
659
+ name: `xl/drawings/_rels/${name}.xml.rels`,
660
+ });
661
+ });
662
+ }
663
+
664
+ // Then add programmatic drawings
665
+ model.worksheets.forEach(worksheet => {
666
+ const {drawing, preservedDrawing} = worksheet;
667
+ // Skip if this is a preserved drawing (already written above)
668
+ if (drawing && !preservedDrawing) {
669
+ drawingXform.prepare(drawing, {});
670
+ let xml = drawingXform.toXml(drawing);
671
+ zip.append(xml, {name: `xl/drawings/${drawing.name}.xml`});
672
+
673
+ xml = relsXform.toXml(drawing.rels);
674
+ zip.append(xml, {name: `xl/drawings/_rels/${drawing.name}.xml.rels`});
675
+ }
676
+ });
677
+ }
678
+
679
+ addTables(zip, model) {
680
+ const tableXform = new TableXform();
681
+
682
+ model.worksheets.forEach(worksheet => {
683
+ const {tables} = worksheet;
684
+ tables.forEach(table => {
685
+ tableXform.prepare(table, {});
686
+ const tableXml = tableXform.toXml(table);
687
+ zip.append(tableXml, {name: `xl/tables/${table.target}`});
688
+ });
689
+ });
690
+ }
691
+
692
+ addCtrlProps(zip, model) {
693
+ if (!model.formControlRefs || !model.formControlRefs.length) return;
694
+
695
+ const ctrlPropXform = new CtrlPropXform();
696
+
697
+ model.formControlRefs.forEach(ref => {
698
+ const ctrlPropXml = ctrlPropXform.toXml(ref.model);
699
+ zip.append(ctrlPropXml, {name: `xl/ctrlProps/ctrlProp${ref.id}.xml`});
700
+ });
701
+ }
702
+
703
+ addPivotTables(zip, model) {
704
+ const hasProgrammaticPivots = model.pivotTables && model.pivotTables.length > 0;
705
+ const hasPreservedPivots = model.preservedPivotTables &&
706
+ Object.keys(model.preservedPivotTables.pivotTables || {}).length > 0;
707
+
708
+ if (!hasProgrammaticPivots && !hasPreservedPivots) return;
709
+
710
+ const pivotCacheRecordsXform = new PivotCacheRecordsXform();
711
+ const pivotCacheDefinitionXform = new PivotCacheDefinitionXform();
712
+ const pivotTableXform = new PivotTableXform();
713
+ const relsXform = new RelationshipsXform();
714
+
715
+ // First, write preserved pivot tables (from round-trip)
716
+ if (hasPreservedPivots) {
717
+ const preserved = model.preservedPivotTables;
718
+
719
+ // Write pivot tables
720
+ Object.keys(preserved.pivotTables).forEach(name => {
721
+ zip.append(preserved.pivotTables[name], {
722
+ name: `xl/pivotTables/${name}.xml`,
723
+ });
724
+ });
725
+
726
+ // Write pivot cache definitions
727
+ Object.keys(preserved.pivotCacheDefinitions).forEach(name => {
728
+ zip.append(preserved.pivotCacheDefinitions[name], {
729
+ name: `xl/pivotCache/${name}.xml`,
730
+ });
731
+ });
732
+
733
+ // Write pivot cache records
734
+ Object.keys(preserved.pivotCacheRecords).forEach(name => {
735
+ zip.append(preserved.pivotCacheRecords[name], {
736
+ name: `xl/pivotCache/${name}.xml`,
737
+ });
738
+ });
739
+
740
+ // Write rels for pivot tables
741
+ Object.keys(preserved.pivotTables).forEach(name => {
742
+ const tableNum = name.match(/\d+/)[0];
743
+ const xml = relsXform.toXml([
744
+ {
745
+ Id: 'rId1',
746
+ Type: XLSX.RelType.PivotCacheDefinition,
747
+ Target: `../pivotCache/pivotCacheDefinition${tableNum}.xml`,
748
+ },
749
+ ]);
750
+ zip.append(xml, {
751
+ name: `xl/pivotTables/_rels/${name}.xml.rels`,
752
+ });
753
+ });
754
+
755
+ // Write rels for pivot cache definitions
756
+ Object.keys(preserved.pivotCacheDefinitions).forEach(name => {
757
+ const tableNum = name.match(/\d+/)[0];
758
+ const xml = relsXform.toXml([
759
+ {
760
+ Id: 'rId1',
761
+ Type: XLSX.RelType.PivotCacheRecords,
762
+ Target: `pivotCacheRecords${tableNum}.xml`,
763
+ },
764
+ ]);
765
+ zip.append(xml, {
766
+ name: `xl/pivotCache/_rels/${name}.xml.rels`,
767
+ });
768
+ });
769
+ }
770
+
771
+ // Then, process programmatic pivot tables
772
+ if (!hasProgrammaticPivots) return;
773
+
774
+ // Process each pivot table
775
+ model.pivotTables.forEach((pivotTable, index) => {
776
+ const tableNum = index + 1;
777
+
778
+ // pivot cache records
779
+ // --------------------------------------------------
780
+ // copy of the source data.
781
+ //
782
+ // Note: cells in the columns of the source data which are part
783
+ // of the "rows" or "columns" of the pivot table configuration are
784
+ // replaced by references to their __cache field__ identifiers.
785
+ // See "pivot cache definition" below.
786
+
787
+ let xml = pivotCacheRecordsXform.toXml(pivotTable);
788
+ zip.append(xml, {
789
+ name: `xl/pivotCache/pivotCacheRecords${tableNum}.xml`,
790
+ });
791
+
792
+ // pivot cache definition
793
+ // --------------------------------------------------
794
+ // cache source (source data):
795
+ // ref="A1:E7" on sheet="Sheet1"
796
+ // cache fields:
797
+ // - 0: "A" (a1, a2, a3)
798
+ // - 1: "B" (b1, b2)
799
+ // - ...
800
+
801
+ xml = pivotCacheDefinitionXform.toXml(pivotTable);
802
+ zip.append(xml, {
803
+ name: `xl/pivotCache/pivotCacheDefinition${tableNum}.xml`,
804
+ });
805
+
806
+ xml = relsXform.toXml([
807
+ {
808
+ Id: 'rId1',
809
+ Type: XLSX.RelType.PivotCacheRecords,
810
+ Target: `pivotCacheRecords${tableNum}.xml`,
811
+ },
812
+ ]);
813
+ zip.append(xml, {
814
+ name: `xl/pivotCache/_rels/pivotCacheDefinition${tableNum}.xml.rels`,
815
+ });
816
+
817
+ // pivot tables (on destination worksheet)
818
+ // --------------------------------------------------
819
+ // location: ref="A3:E15"
820
+ // pivotFields
821
+ // rowFields and rowItems
822
+ // colFields and colItems
823
+ // dataFields
824
+ // pivotTableStyleInfo
825
+
826
+ xml = pivotTableXform.toXml(pivotTable);
827
+ zip.append(xml, {name: `xl/pivotTables/pivotTable${tableNum}.xml`});
828
+
829
+ xml = relsXform.toXml([
830
+ {
831
+ Id: 'rId1',
832
+ Type: XLSX.RelType.PivotCacheDefinition,
833
+ Target: `../pivotCache/pivotCacheDefinition${tableNum}.xml`,
834
+ },
835
+ ]);
836
+ zip.append(xml, {
837
+ name: `xl/pivotTables/_rels/pivotTable${tableNum}.xml.rels`,
838
+ });
839
+ });
840
+ }
841
+
842
+ addCharts(zip, model) {
843
+ const hasPreservedCharts = model.preservedChartsXml &&
844
+ Object.keys(model.preservedChartsXml).length > 0;
845
+
846
+ if (!hasPreservedCharts) return;
847
+
848
+ const relsXform = new RelationshipsXform();
849
+
850
+ // Write chart XML files
851
+ Object.keys(model.preservedChartsXml).forEach(name => {
852
+ zip.append(model.preservedChartsXml[name], {
853
+ name: `xl/charts/${name}.xml`,
854
+ });
855
+ });
856
+
857
+ // Write chart relationship files
858
+ Object.keys(model.preservedChartsRels || {}).forEach(name => {
859
+ const xml = relsXform.toXml(model.preservedChartsRels[name]);
860
+ zip.append(xml, {
861
+ name: `xl/charts/_rels/${name}.xml.rels`,
862
+ });
863
+ });
864
+
865
+ // Write chart style files
866
+ Object.keys(model.preservedChartStylesXml || {}).forEach(name => {
867
+ zip.append(model.preservedChartStylesXml[name], {
868
+ name: `xl/charts/${name}.xml`,
869
+ });
870
+ });
871
+
872
+ // Write chart colors files
873
+ Object.keys(model.preservedChartColorsXml || {}).forEach(name => {
874
+ zip.append(model.preservedChartColorsXml[name], {
875
+ name: `xl/charts/${name}.xml`,
876
+ });
877
+ });
878
+ }
879
+
880
+ async addContentTypes(zip, model) {
881
+ const xform = new ContentTypesXform();
882
+ const xml = xform.toXml(model);
883
+ zip.append(xml, {name: '[Content_Types].xml'});
884
+ }
885
+
886
+ async addApp(zip, model) {
887
+ const xform = new AppXform();
888
+ const xml = xform.toXml(model);
889
+ zip.append(xml, {name: 'docProps/app.xml'});
890
+ }
891
+
892
+ async addCore(zip, model) {
893
+ const coreXform = new CoreXform();
894
+ zip.append(coreXform.toXml(model), {name: 'docProps/core.xml'});
895
+ }
896
+
897
+ async addThemes(zip, model) {
898
+ const themes = model.themes || {theme1: theme1Xml};
899
+ Object.keys(themes).forEach(name => {
900
+ const xml = themes[name];
901
+ const path = `xl/theme/${name}.xml`;
902
+ zip.append(xml, {name: path});
903
+ });
904
+ }
905
+
906
+ async addOfficeRels(zip) {
907
+ const xform = new RelationshipsXform();
908
+ const xml = xform.toXml([
909
+ {
910
+ Id: 'rId1',
911
+ Type: XLSX.RelType.OfficeDocument,
912
+ Target: 'xl/workbook.xml',
913
+ },
914
+ {
915
+ Id: 'rId2',
916
+ Type: XLSX.RelType.CoreProperties,
917
+ Target: 'docProps/core.xml',
918
+ },
919
+ {
920
+ Id: 'rId3',
921
+ Type: XLSX.RelType.ExtenderProperties,
922
+ Target: 'docProps/app.xml',
923
+ },
924
+ ]);
925
+ zip.append(xml, {name: '_rels/.rels'});
926
+ }
927
+
928
+ async addWorkbookRels(zip, model) {
929
+ let count = 1;
930
+ const relationships = [
931
+ {Id: `rId${count++}`, Type: XLSX.RelType.Styles, Target: 'styles.xml'},
932
+ {
933
+ Id: `rId${count++}`,
934
+ Type: XLSX.RelType.Theme,
935
+ Target: 'theme/theme1.xml',
936
+ },
937
+ ];
938
+ if (model.sharedStrings.count) {
939
+ relationships.push({
940
+ Id: `rId${count++}`,
941
+ Type: XLSX.RelType.SharedStrings,
942
+ Target: 'sharedStrings.xml',
943
+ });
944
+ }
945
+ // Add relationships for programmatic pivot tables
946
+ if ((model.pivotTables || []).length) {
947
+ model.pivotTables.forEach((pivotTable, index) => {
948
+ const tableNum = index + 1;
949
+ pivotTable.rId = `rId${count++}`;
950
+ relationships.push({
951
+ Id: pivotTable.rId,
952
+ Type: XLSX.RelType.PivotCacheDefinition,
953
+ Target: `pivotCache/pivotCacheDefinition${tableNum}.xml`,
954
+ });
955
+ });
956
+ }
957
+
958
+ // Add relationships for preserved pivot tables (from round-trip)
959
+ if (model.preservedPivotCaches && model.preservedPivotCaches.length) {
960
+ model.preservedPivotCaches.forEach(cache => {
961
+ cache.rId = `rId${count++}`;
962
+ relationships.push({
963
+ Id: cache.rId,
964
+ Type: XLSX.RelType.PivotCacheDefinition,
965
+ Target: `pivotCache/${cache.definitionFilename}`,
966
+ });
967
+ });
968
+ }
969
+ model.worksheets.forEach(worksheet => {
970
+ worksheet.rId = `rId${count++}`;
971
+ relationships.push({
972
+ Id: worksheet.rId,
973
+ Type: XLSX.RelType.Worksheet,
974
+ Target: `worksheets/sheet${worksheet.id}.xml`,
975
+ });
976
+ });
977
+ const xform = new RelationshipsXform();
978
+ const xml = xform.toXml(relationships);
979
+ zip.append(xml, {name: 'xl/_rels/workbook.xml.rels'});
980
+ }
981
+
982
+ async addSharedStrings(zip, model) {
983
+ if (model.sharedStrings && model.sharedStrings.count) {
984
+ zip.append(model.sharedStrings.xml, {name: 'xl/sharedStrings.xml'});
985
+ }
986
+ }
987
+
988
+ async addStyles(zip, model) {
989
+ const {xml} = model.styles;
990
+ if (xml) {
991
+ zip.append(xml, {name: 'xl/styles.xml'});
992
+ }
993
+ }
994
+
995
+ async addWorkbook(zip, model) {
996
+ const xform = new WorkbookXform();
997
+ zip.append(xform.toXml(model), {name: 'xl/workbook.xml'});
998
+ }
999
+
1000
+ async addWorksheets(zip, model) {
1001
+ // preparation phase
1002
+ const worksheetXform = new WorksheetXform();
1003
+ const relationshipsXform = new RelationshipsXform();
1004
+ const commentsXform = new CommentsXform();
1005
+ const vmlNotesXform = new VmlNotesXform();
1006
+
1007
+ // write sheets
1008
+ model.worksheets.forEach(worksheet => {
1009
+ let xmlStream = new XmlStream();
1010
+ worksheetXform.render(xmlStream, worksheet);
1011
+ zip.append(xmlStream.xml, {
1012
+ name: `xl/worksheets/sheet${worksheet.id}.xml`,
1013
+ });
1014
+
1015
+ if (worksheet.rels && worksheet.rels.length) {
1016
+ xmlStream = new XmlStream();
1017
+ relationshipsXform.render(xmlStream, worksheet.rels);
1018
+ zip.append(xmlStream.xml, {
1019
+ name: `xl/worksheets/_rels/sheet${worksheet.id}.xml.rels`,
1020
+ });
1021
+ }
1022
+
1023
+ if (worksheet.comments.length > 0) {
1024
+ xmlStream = new XmlStream();
1025
+ commentsXform.render(xmlStream, worksheet);
1026
+ zip.append(xmlStream.xml, {name: `xl/comments${worksheet.id}.xml`});
1027
+
1028
+ xmlStream = new XmlStream();
1029
+ vmlNotesXform.render(xmlStream, worksheet);
1030
+ zip.append(xmlStream.xml, {
1031
+ name: `xl/drawings/vmlDrawing${worksheet.id}.vml`,
1032
+ });
1033
+ } else if (worksheet.formControls && worksheet.formControls.length > 0) {
1034
+ // VML file for form controls (no comments)
1035
+ xmlStream = new XmlStream();
1036
+ vmlNotesXform.render(xmlStream, worksheet);
1037
+ zip.append(xmlStream.xml, {
1038
+ name: `xl/drawings/vmlDrawing${worksheet.id}.vml`,
1039
+ });
1040
+ }
1041
+ });
1042
+ }
1043
+
1044
+ _finalize(zip) {
1045
+ return new Promise((resolve, reject) => {
1046
+ zip.on('finish', () => {
1047
+ resolve(this);
1048
+ });
1049
+ zip.on('error', reject);
1050
+ zip.finalize();
1051
+ });
1052
+ }
1053
+
1054
+ prepareModel(model, options) {
1055
+ // ensure following properties have sane values
1056
+ model.creator = model.creator || 'ExcelJS';
1057
+ model.lastModifiedBy = model.lastModifiedBy || 'ExcelJS';
1058
+ model.created = model.created || new Date();
1059
+ model.modified = model.modified || new Date();
1060
+
1061
+ model.useSharedStrings =
1062
+ options.useSharedStrings !== undefined ? options.useSharedStrings : true;
1063
+ model.useStyles = options.useStyles !== undefined ? options.useStyles : true;
1064
+
1065
+ // Manage the shared strings
1066
+ model.sharedStrings = new SharedStringsXform();
1067
+
1068
+ // add a style manager to handle cell formats, fonts, etc.
1069
+ model.styles = model.useStyles ? new StylesXform(true) : new StylesXform.Mock();
1070
+
1071
+ // prepare all of the things before the render
1072
+ const workbookXform = new WorkbookXform();
1073
+ const worksheetXform = new WorksheetXform();
1074
+
1075
+ workbookXform.prepare(model);
1076
+
1077
+ const worksheetOptions = {
1078
+ sharedStrings: model.sharedStrings,
1079
+ styles: model.styles,
1080
+ date1904: model.properties.date1904,
1081
+ drawingsCount: 0,
1082
+ media: model.media,
1083
+ };
1084
+ worksheetOptions.drawings = model.drawings = [];
1085
+ worksheetOptions.commentRefs = model.commentRefs = [];
1086
+ worksheetOptions.formControlRefs = model.formControlRefs = [];
1087
+ let tableCount = 0;
1088
+ model.tables = [];
1089
+ model.worksheets.forEach(worksheet => {
1090
+ // assign unique filenames to tables
1091
+ worksheet.tables.forEach(table => {
1092
+ tableCount++;
1093
+ table.target = `table${tableCount}.xml`;
1094
+ table.id = tableCount;
1095
+ model.tables.push(table);
1096
+ });
1097
+
1098
+ worksheetXform.prepare(worksheet, worksheetOptions);
1099
+ });
1100
+
1101
+ // TODO: workbook drawing list
1102
+ }
1103
+
1104
+ async write(stream, options) {
1105
+ options = options || {};
1106
+ const {model} = this.workbook;
1107
+ const zip = new ZipStream.ZipWriter(options.zip);
1108
+ zip.pipe(stream);
1109
+
1110
+ this.prepareModel(model, options);
1111
+
1112
+ // render
1113
+ await this.addContentTypes(zip, model);
1114
+ await this.addOfficeRels(zip, model);
1115
+ await this.addWorkbookRels(zip, model);
1116
+ await this.addWorksheets(zip, model);
1117
+ await this.addSharedStrings(zip, model); // always after worksheets
1118
+ await this.addDrawings(zip, model);
1119
+ await this.addTables(zip, model);
1120
+ await this.addCtrlProps(zip, model);
1121
+ await this.addPivotTables(zip, model);
1122
+ await this.addCharts(zip, model);
1123
+ await Promise.all([this.addThemes(zip, model), this.addStyles(zip, model)]);
1124
+ await this.addMedia(zip, model);
1125
+ await Promise.all([this.addApp(zip, model), this.addCore(zip, model)]);
1126
+ await this.addWorkbook(zip, model);
1127
+ return this._finalize(zip);
1128
+ }
1129
+
1130
+ writeFile(filename, options) {
1131
+ const stream = fs.createWriteStream(filename);
1132
+
1133
+ return new Promise((resolve, reject) => {
1134
+ stream.on('finish', () => {
1135
+ resolve();
1136
+ });
1137
+ stream.on('error', error => {
1138
+ reject(error);
1139
+ });
1140
+
1141
+ this.write(stream, options)
1142
+ .then(() => {
1143
+ stream.end();
1144
+ })
1145
+ .catch(err => {
1146
+ reject(err);
1147
+ });
1148
+ });
1149
+ }
1150
+
1151
+ async writeBuffer(options) {
1152
+ const stream = new StreamBuf();
1153
+ await this.write(stream, options);
1154
+ return stream.read();
1155
+ }
1156
+ }
1157
+
1158
+ XLSX.RelType = require('./rel-type');
1159
+
1160
+ module.exports = XLSX;