@cj-tech-master/excelts 5.0.6 → 5.1.0

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 (273) hide show
  1. package/dist/browser/index.browser.d.ts +1 -1
  2. package/dist/browser/index.d.ts +1 -1
  3. package/dist/browser/modules/archive/unzip/stream.base.js +19 -19
  4. package/dist/browser/modules/archive/unzip/stream.browser.js +3 -3
  5. package/dist/browser/modules/csv/csv-core.js +6 -3
  6. package/dist/browser/modules/csv/csv.browser.js +2 -2
  7. package/dist/browser/modules/csv/csv.js +1 -1
  8. package/dist/browser/modules/excel/anchor.js +4 -4
  9. package/dist/browser/modules/excel/cell.js +5 -5
  10. package/dist/browser/modules/excel/column.js +4 -4
  11. package/dist/browser/modules/excel/defined-names.js +1 -1
  12. package/dist/browser/modules/excel/form-control.js +1 -1
  13. package/dist/browser/modules/excel/pivot-table.d.ts +168 -17
  14. package/dist/browser/modules/excel/pivot-table.js +278 -70
  15. package/dist/browser/modules/excel/row.js +4 -4
  16. package/dist/browser/modules/excel/stream/workbook-reader.browser.js +4 -4
  17. package/dist/browser/modules/excel/stream/workbook-writer.browser.js +4 -4
  18. package/dist/browser/modules/excel/stream/worksheet-reader.js +1 -1
  19. package/dist/browser/modules/excel/stream/worksheet-writer.js +4 -4
  20. package/dist/browser/modules/excel/table.js +2 -2
  21. package/dist/browser/modules/excel/types.d.ts +0 -4
  22. package/dist/browser/modules/excel/utils/cell-format.js +3 -3
  23. package/dist/browser/modules/excel/utils/shared-formula.js +1 -1
  24. package/dist/browser/modules/excel/utils/stream-buf.js +2 -2
  25. package/dist/browser/modules/excel/utils/string-buf.js +1 -1
  26. package/dist/browser/modules/excel/workbook.d.ts +0 -2
  27. package/dist/browser/modules/excel/workbook.js +4 -5
  28. package/dist/browser/modules/excel/worksheet.js +9 -9
  29. package/dist/browser/modules/excel/xlsx/xform/base-xform.d.ts +5 -5
  30. package/dist/browser/modules/excel/xlsx/xform/base-xform.js +1 -1
  31. package/dist/browser/modules/excel/xlsx/xform/book/defined-name-xform.js +2 -2
  32. package/dist/browser/modules/excel/xlsx/xform/book/workbook-view-xform.js +4 -4
  33. package/dist/browser/modules/excel/xlsx/xform/book/workbook-xform.js +16 -4
  34. package/dist/browser/modules/excel/xlsx/xform/comment/comment-xform.d.ts +1 -2
  35. package/dist/browser/modules/excel/xlsx/xform/comment/comments-xform.d.ts +1 -2
  36. package/dist/browser/modules/excel/xlsx/xform/comment/style/vml-position-xform.d.ts +3 -4
  37. package/dist/browser/modules/excel/xlsx/xform/comment/style/vml-position-xform.js +1 -1
  38. package/dist/browser/modules/excel/xlsx/xform/comment/style/vml-protection-xform.js +1 -1
  39. package/dist/browser/modules/excel/xlsx/xform/comment/vml-client-data-xform.d.ts +1 -2
  40. package/dist/browser/modules/excel/xlsx/xform/comment/vml-notes-xform.d.ts +1 -2
  41. package/dist/browser/modules/excel/xlsx/xform/comment/vml-shape-xform.js +1 -1
  42. package/dist/browser/modules/excel/xlsx/xform/comment/vml-textbox-xform.d.ts +1 -2
  43. package/dist/browser/modules/excel/xlsx/xform/comment/vml-textbox-xform.js +1 -1
  44. package/dist/browser/modules/excel/xlsx/xform/composite-xform.d.ts +1 -1
  45. package/dist/browser/modules/excel/xlsx/xform/core/app-xform.js +1 -1
  46. package/dist/browser/modules/excel/xlsx/xform/core/content-types-xform.js +24 -11
  47. package/dist/browser/modules/excel/xlsx/xform/drawing/base-cell-anchor-xform.js +1 -1
  48. package/dist/browser/modules/excel/xlsx/xform/drawing/blip-xform.d.ts +1 -2
  49. package/dist/browser/modules/excel/xlsx/xform/drawing/cell-position-xform.d.ts +1 -2
  50. package/dist/browser/modules/excel/xlsx/xform/drawing/ctrl-prop-xform.d.ts +1 -2
  51. package/dist/browser/modules/excel/xlsx/xform/drawing/drawing-xform.d.ts +1 -2
  52. package/dist/browser/modules/excel/xlsx/xform/drawing/ext-xform.d.ts +1 -2
  53. package/dist/browser/modules/excel/xlsx/xform/drawing/ext-xform.js +2 -2
  54. package/dist/browser/modules/excel/xlsx/xform/drawing/one-cell-anchor-xform.js +1 -1
  55. package/dist/browser/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.js +1 -1
  56. package/dist/browser/modules/excel/xlsx/xform/drawing/vml-drawing-xform.d.ts +1 -2
  57. package/dist/browser/modules/excel/xlsx/xform/list-xform.d.ts +1 -2
  58. package/dist/browser/modules/excel/xlsx/xform/list-xform.js +3 -3
  59. package/dist/browser/modules/excel/xlsx/xform/pivot-table/cache-field-xform.d.ts +5 -15
  60. package/dist/browser/modules/excel/xlsx/xform/pivot-table/cache-field-xform.js +134 -52
  61. package/dist/browser/modules/excel/xlsx/xform/pivot-table/cache-field.d.ts +14 -15
  62. package/dist/browser/modules/excel/xlsx/xform/pivot-table/cache-field.js +244 -70
  63. package/dist/browser/modules/excel/xlsx/xform/pivot-table/pivot-cache-definition-xform.d.ts +13 -29
  64. package/dist/browser/modules/excel/xlsx/xform/pivot-table/pivot-cache-definition-xform.js +213 -37
  65. package/dist/browser/modules/excel/xlsx/xform/pivot-table/pivot-cache-records-xform.d.ts +7 -34
  66. package/dist/browser/modules/excel/xlsx/xform/pivot-table/pivot-cache-records-xform.js +143 -41
  67. package/dist/browser/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.d.ts +101 -27
  68. package/dist/browser/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.js +793 -408
  69. package/dist/browser/modules/excel/xlsx/xform/pivot-table/raw-xml-collector.d.ts +78 -0
  70. package/dist/browser/modules/excel/xlsx/xform/pivot-table/raw-xml-collector.js +149 -0
  71. package/dist/browser/modules/excel/xlsx/xform/sheet/cell-xform.js +1 -1
  72. package/dist/browser/modules/excel/xlsx/xform/sheet/cf/cf-rule-xform.js +1 -1
  73. package/dist/browser/modules/excel/xlsx/xform/sheet/cf/conditional-formattings-xform.js +1 -1
  74. package/dist/browser/modules/excel/xlsx/xform/sheet/cf-ext/cf-rule-ext-xform.js +1 -1
  75. package/dist/browser/modules/excel/xlsx/xform/sheet/col-xform.js +3 -3
  76. package/dist/browser/modules/excel/xlsx/xform/sheet/data-validations-xform.js +3 -3
  77. package/dist/browser/modules/excel/xlsx/xform/sheet/header-footer-xform.js +6 -6
  78. package/dist/browser/modules/excel/xlsx/xform/sheet/page-setup-xform.js +11 -11
  79. package/dist/browser/modules/excel/xlsx/xform/sheet/row-xform.d.ts +1 -2
  80. package/dist/browser/modules/excel/xlsx/xform/sheet/sheet-format-properties-xform.js +3 -3
  81. package/dist/browser/modules/excel/xlsx/xform/sheet/sheet-view-xform.d.ts +1 -2
  82. package/dist/browser/modules/excel/xlsx/xform/sheet/sheet-view-xform.js +10 -10
  83. package/dist/browser/modules/excel/xlsx/xform/sheet/worksheet-xform.js +12 -12
  84. package/dist/browser/modules/excel/xlsx/xform/strings/phonetic-text-xform.js +2 -2
  85. package/dist/browser/modules/excel/xlsx/xform/style/color-xform.js +1 -1
  86. package/dist/browser/modules/excel/xlsx/xform/style/style-xform.js +5 -5
  87. package/dist/browser/modules/excel/xlsx/xform/table/auto-filter-xform.d.ts +1 -2
  88. package/dist/browser/modules/excel/xlsx/xform/table/custom-filter-xform.d.ts +1 -2
  89. package/dist/browser/modules/excel/xlsx/xform/table/filter-column-xform.d.ts +1 -2
  90. package/dist/browser/modules/excel/xlsx/xform/table/filter-xform.d.ts +1 -2
  91. package/dist/browser/modules/excel/xlsx/xform/table/table-column-xform.d.ts +1 -2
  92. package/dist/browser/modules/excel/xlsx/xform/table/table-style-info-xform.d.ts +1 -2
  93. package/dist/browser/modules/excel/xlsx/xform/table/table-xform.d.ts +1 -2
  94. package/dist/browser/modules/excel/xlsx/xlsx.browser.d.ts +5 -2
  95. package/dist/browser/modules/excel/xlsx/xlsx.browser.js +88 -54
  96. package/dist/browser/utils/env.d.ts +0 -5
  97. package/dist/browser/utils/env.js +0 -7
  98. package/dist/browser/utils/utils.base.d.ts +8 -13
  99. package/dist/browser/utils/utils.base.js +40 -47
  100. package/dist/browser/utils/utils.browser.d.ts +1 -1
  101. package/dist/browser/utils/utils.browser.js +1 -1
  102. package/dist/browser/utils/utils.d.ts +1 -1
  103. package/dist/browser/utils/utils.js +1 -1
  104. package/dist/cjs/modules/archive/unzip/stream.base.js +19 -19
  105. package/dist/cjs/modules/archive/unzip/stream.browser.js +3 -3
  106. package/dist/cjs/modules/csv/csv-core.js +6 -3
  107. package/dist/cjs/modules/csv/csv.browser.js +2 -2
  108. package/dist/cjs/modules/csv/csv.js +1 -1
  109. package/dist/cjs/modules/excel/anchor.js +4 -4
  110. package/dist/cjs/modules/excel/cell.js +5 -5
  111. package/dist/cjs/modules/excel/column.js +4 -4
  112. package/dist/cjs/modules/excel/defined-names.js +1 -1
  113. package/dist/cjs/modules/excel/form-control.js +1 -1
  114. package/dist/cjs/modules/excel/pivot-table.js +280 -70
  115. package/dist/cjs/modules/excel/row.js +4 -4
  116. package/dist/cjs/modules/excel/stream/workbook-reader.browser.js +4 -4
  117. package/dist/cjs/modules/excel/stream/workbook-writer.browser.js +4 -4
  118. package/dist/cjs/modules/excel/stream/worksheet-reader.js +1 -1
  119. package/dist/cjs/modules/excel/stream/worksheet-writer.js +4 -4
  120. package/dist/cjs/modules/excel/table.js +2 -2
  121. package/dist/cjs/modules/excel/utils/cell-format.js +3 -3
  122. package/dist/cjs/modules/excel/utils/shared-formula.js +1 -1
  123. package/dist/cjs/modules/excel/utils/stream-buf.js +2 -2
  124. package/dist/cjs/modules/excel/utils/string-buf.js +1 -1
  125. package/dist/cjs/modules/excel/workbook.js +4 -5
  126. package/dist/cjs/modules/excel/worksheet.js +9 -9
  127. package/dist/cjs/modules/excel/xlsx/xform/base-xform.js +1 -1
  128. package/dist/cjs/modules/excel/xlsx/xform/book/defined-name-xform.js +2 -2
  129. package/dist/cjs/modules/excel/xlsx/xform/book/workbook-view-xform.js +4 -4
  130. package/dist/cjs/modules/excel/xlsx/xform/book/workbook-xform.js +16 -4
  131. package/dist/cjs/modules/excel/xlsx/xform/comment/style/vml-position-xform.js +1 -1
  132. package/dist/cjs/modules/excel/xlsx/xform/comment/style/vml-protection-xform.js +1 -1
  133. package/dist/cjs/modules/excel/xlsx/xform/comment/vml-shape-xform.js +1 -1
  134. package/dist/cjs/modules/excel/xlsx/xform/comment/vml-textbox-xform.js +1 -1
  135. package/dist/cjs/modules/excel/xlsx/xform/core/app-xform.js +1 -1
  136. package/dist/cjs/modules/excel/xlsx/xform/core/content-types-xform.js +24 -11
  137. package/dist/cjs/modules/excel/xlsx/xform/drawing/base-cell-anchor-xform.js +1 -1
  138. package/dist/cjs/modules/excel/xlsx/xform/drawing/ext-xform.js +2 -2
  139. package/dist/cjs/modules/excel/xlsx/xform/drawing/one-cell-anchor-xform.js +1 -1
  140. package/dist/cjs/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.js +1 -1
  141. package/dist/cjs/modules/excel/xlsx/xform/list-xform.js +3 -3
  142. package/dist/cjs/modules/excel/xlsx/xform/pivot-table/cache-field-xform.js +133 -51
  143. package/dist/cjs/modules/excel/xlsx/xform/pivot-table/cache-field.js +245 -71
  144. package/dist/cjs/modules/excel/xlsx/xform/pivot-table/pivot-cache-definition-xform.js +212 -36
  145. package/dist/cjs/modules/excel/xlsx/xform/pivot-table/pivot-cache-records-xform.js +142 -40
  146. package/dist/cjs/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.js +793 -408
  147. package/dist/cjs/modules/excel/xlsx/xform/pivot-table/raw-xml-collector.js +153 -0
  148. package/dist/cjs/modules/excel/xlsx/xform/sheet/cell-xform.js +1 -1
  149. package/dist/cjs/modules/excel/xlsx/xform/sheet/cf/cf-rule-xform.js +1 -1
  150. package/dist/cjs/modules/excel/xlsx/xform/sheet/cf/conditional-formattings-xform.js +1 -1
  151. package/dist/cjs/modules/excel/xlsx/xform/sheet/cf-ext/cf-rule-ext-xform.js +1 -1
  152. package/dist/cjs/modules/excel/xlsx/xform/sheet/col-xform.js +3 -3
  153. package/dist/cjs/modules/excel/xlsx/xform/sheet/data-validations-xform.js +3 -3
  154. package/dist/cjs/modules/excel/xlsx/xform/sheet/header-footer-xform.js +6 -6
  155. package/dist/cjs/modules/excel/xlsx/xform/sheet/page-setup-xform.js +11 -11
  156. package/dist/cjs/modules/excel/xlsx/xform/sheet/sheet-format-properties-xform.js +3 -3
  157. package/dist/cjs/modules/excel/xlsx/xform/sheet/sheet-view-xform.js +10 -10
  158. package/dist/cjs/modules/excel/xlsx/xform/sheet/worksheet-xform.js +12 -12
  159. package/dist/cjs/modules/excel/xlsx/xform/strings/phonetic-text-xform.js +2 -2
  160. package/dist/cjs/modules/excel/xlsx/xform/style/color-xform.js +1 -1
  161. package/dist/cjs/modules/excel/xlsx/xform/style/style-xform.js +5 -5
  162. package/dist/cjs/modules/excel/xlsx/xlsx.browser.js +88 -54
  163. package/dist/cjs/utils/env.js +0 -8
  164. package/dist/cjs/utils/utils.base.js +41 -54
  165. package/dist/cjs/utils/utils.browser.js +2 -7
  166. package/dist/cjs/utils/utils.js +2 -7
  167. package/dist/esm/modules/archive/unzip/stream.base.js +19 -19
  168. package/dist/esm/modules/archive/unzip/stream.browser.js +3 -3
  169. package/dist/esm/modules/csv/csv-core.js +6 -3
  170. package/dist/esm/modules/csv/csv.browser.js +2 -2
  171. package/dist/esm/modules/csv/csv.js +1 -1
  172. package/dist/esm/modules/excel/anchor.js +4 -4
  173. package/dist/esm/modules/excel/cell.js +5 -5
  174. package/dist/esm/modules/excel/column.js +4 -4
  175. package/dist/esm/modules/excel/defined-names.js +1 -1
  176. package/dist/esm/modules/excel/form-control.js +1 -1
  177. package/dist/esm/modules/excel/pivot-table.js +278 -70
  178. package/dist/esm/modules/excel/row.js +4 -4
  179. package/dist/esm/modules/excel/stream/workbook-reader.browser.js +4 -4
  180. package/dist/esm/modules/excel/stream/workbook-writer.browser.js +4 -4
  181. package/dist/esm/modules/excel/stream/worksheet-reader.js +1 -1
  182. package/dist/esm/modules/excel/stream/worksheet-writer.js +4 -4
  183. package/dist/esm/modules/excel/table.js +2 -2
  184. package/dist/esm/modules/excel/utils/cell-format.js +3 -3
  185. package/dist/esm/modules/excel/utils/shared-formula.js +1 -1
  186. package/dist/esm/modules/excel/utils/stream-buf.js +2 -2
  187. package/dist/esm/modules/excel/utils/string-buf.js +1 -1
  188. package/dist/esm/modules/excel/workbook.js +4 -5
  189. package/dist/esm/modules/excel/worksheet.js +9 -9
  190. package/dist/esm/modules/excel/xlsx/xform/base-xform.js +1 -1
  191. package/dist/esm/modules/excel/xlsx/xform/book/defined-name-xform.js +2 -2
  192. package/dist/esm/modules/excel/xlsx/xform/book/workbook-view-xform.js +4 -4
  193. package/dist/esm/modules/excel/xlsx/xform/book/workbook-xform.js +16 -4
  194. package/dist/esm/modules/excel/xlsx/xform/comment/style/vml-position-xform.js +1 -1
  195. package/dist/esm/modules/excel/xlsx/xform/comment/style/vml-protection-xform.js +1 -1
  196. package/dist/esm/modules/excel/xlsx/xform/comment/vml-shape-xform.js +1 -1
  197. package/dist/esm/modules/excel/xlsx/xform/comment/vml-textbox-xform.js +1 -1
  198. package/dist/esm/modules/excel/xlsx/xform/core/app-xform.js +1 -1
  199. package/dist/esm/modules/excel/xlsx/xform/core/content-types-xform.js +24 -11
  200. package/dist/esm/modules/excel/xlsx/xform/drawing/base-cell-anchor-xform.js +1 -1
  201. package/dist/esm/modules/excel/xlsx/xform/drawing/ext-xform.js +2 -2
  202. package/dist/esm/modules/excel/xlsx/xform/drawing/one-cell-anchor-xform.js +1 -1
  203. package/dist/esm/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.js +1 -1
  204. package/dist/esm/modules/excel/xlsx/xform/list-xform.js +3 -3
  205. package/dist/esm/modules/excel/xlsx/xform/pivot-table/cache-field-xform.js +134 -52
  206. package/dist/esm/modules/excel/xlsx/xform/pivot-table/cache-field.js +244 -70
  207. package/dist/esm/modules/excel/xlsx/xform/pivot-table/pivot-cache-definition-xform.js +213 -37
  208. package/dist/esm/modules/excel/xlsx/xform/pivot-table/pivot-cache-records-xform.js +143 -41
  209. package/dist/esm/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.js +793 -408
  210. package/dist/esm/modules/excel/xlsx/xform/pivot-table/raw-xml-collector.js +149 -0
  211. package/dist/esm/modules/excel/xlsx/xform/sheet/cell-xform.js +1 -1
  212. package/dist/esm/modules/excel/xlsx/xform/sheet/cf/cf-rule-xform.js +1 -1
  213. package/dist/esm/modules/excel/xlsx/xform/sheet/cf/conditional-formattings-xform.js +1 -1
  214. package/dist/esm/modules/excel/xlsx/xform/sheet/cf-ext/cf-rule-ext-xform.js +1 -1
  215. package/dist/esm/modules/excel/xlsx/xform/sheet/col-xform.js +3 -3
  216. package/dist/esm/modules/excel/xlsx/xform/sheet/data-validations-xform.js +3 -3
  217. package/dist/esm/modules/excel/xlsx/xform/sheet/header-footer-xform.js +6 -6
  218. package/dist/esm/modules/excel/xlsx/xform/sheet/page-setup-xform.js +11 -11
  219. package/dist/esm/modules/excel/xlsx/xform/sheet/sheet-format-properties-xform.js +3 -3
  220. package/dist/esm/modules/excel/xlsx/xform/sheet/sheet-view-xform.js +10 -10
  221. package/dist/esm/modules/excel/xlsx/xform/sheet/worksheet-xform.js +12 -12
  222. package/dist/esm/modules/excel/xlsx/xform/strings/phonetic-text-xform.js +2 -2
  223. package/dist/esm/modules/excel/xlsx/xform/style/color-xform.js +1 -1
  224. package/dist/esm/modules/excel/xlsx/xform/style/style-xform.js +5 -5
  225. package/dist/esm/modules/excel/xlsx/xlsx.browser.js +88 -54
  226. package/dist/esm/utils/env.js +0 -7
  227. package/dist/esm/utils/utils.base.js +40 -47
  228. package/dist/esm/utils/utils.browser.js +1 -1
  229. package/dist/esm/utils/utils.js +1 -1
  230. package/dist/iife/excelts.iife.js +1553 -718
  231. package/dist/iife/excelts.iife.js.map +1 -1
  232. package/dist/iife/excelts.iife.min.js +36 -105
  233. package/dist/types/index.browser.d.ts +1 -1
  234. package/dist/types/index.d.ts +1 -1
  235. package/dist/types/modules/excel/pivot-table.d.ts +168 -17
  236. package/dist/types/modules/excel/types.d.ts +0 -4
  237. package/dist/types/modules/excel/workbook.d.ts +0 -2
  238. package/dist/types/modules/excel/xlsx/xform/base-xform.d.ts +5 -5
  239. package/dist/types/modules/excel/xlsx/xform/comment/comment-xform.d.ts +1 -2
  240. package/dist/types/modules/excel/xlsx/xform/comment/comments-xform.d.ts +1 -2
  241. package/dist/types/modules/excel/xlsx/xform/comment/style/vml-position-xform.d.ts +3 -4
  242. package/dist/types/modules/excel/xlsx/xform/comment/vml-client-data-xform.d.ts +1 -2
  243. package/dist/types/modules/excel/xlsx/xform/comment/vml-notes-xform.d.ts +1 -2
  244. package/dist/types/modules/excel/xlsx/xform/comment/vml-textbox-xform.d.ts +1 -2
  245. package/dist/types/modules/excel/xlsx/xform/composite-xform.d.ts +1 -1
  246. package/dist/types/modules/excel/xlsx/xform/drawing/blip-xform.d.ts +1 -2
  247. package/dist/types/modules/excel/xlsx/xform/drawing/cell-position-xform.d.ts +1 -2
  248. package/dist/types/modules/excel/xlsx/xform/drawing/ctrl-prop-xform.d.ts +1 -2
  249. package/dist/types/modules/excel/xlsx/xform/drawing/drawing-xform.d.ts +1 -2
  250. package/dist/types/modules/excel/xlsx/xform/drawing/ext-xform.d.ts +1 -2
  251. package/dist/types/modules/excel/xlsx/xform/drawing/vml-drawing-xform.d.ts +1 -2
  252. package/dist/types/modules/excel/xlsx/xform/list-xform.d.ts +1 -2
  253. package/dist/types/modules/excel/xlsx/xform/pivot-table/cache-field-xform.d.ts +5 -15
  254. package/dist/types/modules/excel/xlsx/xform/pivot-table/cache-field.d.ts +14 -15
  255. package/dist/types/modules/excel/xlsx/xform/pivot-table/pivot-cache-definition-xform.d.ts +13 -29
  256. package/dist/types/modules/excel/xlsx/xform/pivot-table/pivot-cache-records-xform.d.ts +7 -34
  257. package/dist/types/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.d.ts +101 -27
  258. package/dist/types/modules/excel/xlsx/xform/pivot-table/raw-xml-collector.d.ts +78 -0
  259. package/dist/types/modules/excel/xlsx/xform/sheet/row-xform.d.ts +1 -2
  260. package/dist/types/modules/excel/xlsx/xform/sheet/sheet-view-xform.d.ts +1 -2
  261. package/dist/types/modules/excel/xlsx/xform/table/auto-filter-xform.d.ts +1 -2
  262. package/dist/types/modules/excel/xlsx/xform/table/custom-filter-xform.d.ts +1 -2
  263. package/dist/types/modules/excel/xlsx/xform/table/filter-column-xform.d.ts +1 -2
  264. package/dist/types/modules/excel/xlsx/xform/table/filter-xform.d.ts +1 -2
  265. package/dist/types/modules/excel/xlsx/xform/table/table-column-xform.d.ts +1 -2
  266. package/dist/types/modules/excel/xlsx/xform/table/table-style-info-xform.d.ts +1 -2
  267. package/dist/types/modules/excel/xlsx/xform/table/table-xform.d.ts +1 -2
  268. package/dist/types/modules/excel/xlsx/xlsx.browser.d.ts +5 -2
  269. package/dist/types/utils/env.d.ts +0 -5
  270. package/dist/types/utils/utils.base.d.ts +8 -13
  271. package/dist/types/utils/utils.browser.d.ts +1 -1
  272. package/dist/types/utils/utils.d.ts +1 -1
  273. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @cj-tech-master/excelts v5.0.6
2
+ * @cj-tech-master/excelts v5.1.0
3
3
  * TypeScript Excel Workbook Manager - Read and Write xlsx and csv Files.
4
4
  * (c) 2026 cjnoname
5
5
  * Released under the MIT License
@@ -643,7 +643,7 @@ var ExcelTS = (function(exports) {
643
643
  let row = parseInt(rowStr, 10);
644
644
  if (!colDollar) col += to.col - offset.col;
645
645
  if (!rowDollar) row += to.row - offset.row;
646
- return (sheet || "") + (colDollar || "") + colCache.n2l(col) + (rowDollar || "") + row;
646
+ return (sheet ?? "") + (colDollar ?? "") + colCache.n2l(col) + (rowDollar ?? "") + row;
647
647
  }
648
648
  return refMatch;
649
649
  });
@@ -1079,8 +1079,8 @@ var ExcelTS = (function(exports) {
1079
1079
  }
1080
1080
  get value() {
1081
1081
  return {
1082
- text: this.model.text || "",
1083
- hyperlink: this.model.hyperlink || "",
1082
+ text: this.model.text ?? "",
1083
+ hyperlink: this.model.hyperlink ?? "",
1084
1084
  tooltip: this.model.tooltip
1085
1085
  };
1086
1086
  }
@@ -1114,11 +1114,11 @@ var ExcelTS = (function(exports) {
1114
1114
  this.model.address = value;
1115
1115
  }
1116
1116
  toCsvString() {
1117
- return this.model.hyperlink || "";
1117
+ return this.model.hyperlink ?? "";
1118
1118
  }
1119
1119
  release() {}
1120
1120
  toString() {
1121
- return this.model.text || "";
1121
+ return this.model.text ?? "";
1122
1122
  }
1123
1123
  };
1124
1124
  var MergeValue = class {
@@ -1262,7 +1262,7 @@ var ExcelTS = (function(exports) {
1262
1262
  return this._translatedFormula;
1263
1263
  }
1264
1264
  toCsvString() {
1265
- return `${this.model.result || ""}`;
1265
+ return `${this.model.result ?? ""}`;
1266
1266
  }
1267
1267
  release() {}
1268
1268
  toString() {
@@ -1647,8 +1647,8 @@ var ExcelTS = (function(exports) {
1647
1647
  }
1648
1648
  addPageBreak(lft, rght) {
1649
1649
  const ws = this._worksheet;
1650
- const left = Math.max(0, (lft || 0) - 1) || 0;
1651
- const right = Math.max(0, (rght || 0) - 1) || 16838;
1650
+ const left = Math.max(0, (lft ?? 0) - 1) || 0;
1651
+ const right = Math.max(0, (rght ?? 0) - 1) || 16838;
1652
1652
  const pb = {
1653
1653
  id: this._number,
1654
1654
  max: right,
@@ -1799,7 +1799,7 @@ var ExcelTS = (function(exports) {
1799
1799
  this._hidden = value;
1800
1800
  }
1801
1801
  get outlineLevel() {
1802
- return this._outlineLevel || 0;
1802
+ return this._outlineLevel ?? 0;
1803
1803
  }
1804
1804
  set outlineLevel(value) {
1805
1805
  this._outlineLevel = value;
@@ -1864,7 +1864,7 @@ var ExcelTS = (function(exports) {
1864
1864
  if (value.height) this.height = value.height;
1865
1865
  else delete this.height;
1866
1866
  this.hidden = value.hidden;
1867
- this.outlineLevel = value.outlineLevel || 0;
1867
+ this.outlineLevel = value.outlineLevel ?? 0;
1868
1868
  this.dyDescent = value.dyDescent;
1869
1869
  this.style = value.style && JSON.parse(JSON.stringify(value.style)) || {};
1870
1870
  }
@@ -1976,7 +1976,7 @@ var ExcelTS = (function(exports) {
1976
1976
  * Set an outline level for columns
1977
1977
  */
1978
1978
  get outlineLevel() {
1979
- return this._outlineLevel || 0;
1979
+ return this._outlineLevel ?? 0;
1980
1980
  }
1981
1981
  set outlineLevel(value) {
1982
1982
  this._outlineLevel = value;
@@ -2053,8 +2053,8 @@ var ExcelTS = (function(exports) {
2053
2053
  */
2054
2054
  addPageBreak(top, bottom) {
2055
2055
  const ws = this._worksheet;
2056
- const topRow = Math.max(0, (top || 0) - 1) || 0;
2057
- const bottomRow = Math.max(0, (bottom || 0) - 1) || 1048575;
2056
+ const topRow = Math.max(0, (top ?? 0) - 1) || 0;
2057
+ const bottomRow = Math.max(0, (bottom ?? 0) - 1) || 1048575;
2058
2058
  const pb = {
2059
2059
  id: this._number,
2060
2060
  max: bottomRow,
@@ -2143,7 +2143,7 @@ var ExcelTS = (function(exports) {
2143
2143
  static fromModel(worksheetOrCols, colsMaybe) {
2144
2144
  const worksheet = Array.isArray(worksheetOrCols) ? worksheetOrCols : worksheetOrCols;
2145
2145
  let cols = Array.isArray(worksheetOrCols) ? worksheetOrCols : colsMaybe ?? [];
2146
- cols = cols || [];
2146
+ cols = cols ?? [];
2147
2147
  const columns = [];
2148
2148
  let count = 1;
2149
2149
  let index = 0;
@@ -2186,10 +2186,10 @@ var ExcelTS = (function(exports) {
2186
2186
  this.nativeRow = decoded.row + offset;
2187
2187
  this.nativeRowOff = 0;
2188
2188
  } else if (isAnchorModel(address)) {
2189
- this.nativeCol = address.nativeCol || 0;
2190
- this.nativeColOff = address.nativeColOff || 0;
2191
- this.nativeRow = address.nativeRow || 0;
2192
- this.nativeRowOff = address.nativeRowOff || 0;
2189
+ this.nativeCol = address.nativeCol ?? 0;
2190
+ this.nativeColOff = address.nativeColOff ?? 0;
2191
+ this.nativeRow = address.nativeRow ?? 0;
2192
+ this.nativeRowOff = address.nativeRowOff ?? 0;
2193
2193
  } else if (isSimpleAddress(address)) {
2194
2194
  this.col = address.col + offset;
2195
2195
  this.row = address.row + offset;
@@ -2384,7 +2384,7 @@ var ExcelTS = (function(exports) {
2384
2384
  case "stdDev": return `SUBTOTAL(106,${this.table.name}[${column.name}])`;
2385
2385
  case "var": return `SUBTOTAL(107,${this.table.name}[${column.name}])`;
2386
2386
  case "sum": return `SUBTOTAL(109,${this.table.name}[${column.name}])`;
2387
- case "custom": return column.totalsRowFormula || null;
2387
+ case "custom": return column.totalsRowFormula ?? null;
2388
2388
  default: throw new Error(`Invalid Totals Row Function: ${column.totalsRowFunction}`);
2389
2389
  }
2390
2390
  }
@@ -2431,7 +2431,7 @@ var ExcelTS = (function(exports) {
2431
2431
  if (i === 0) assign(column, "totalsRowLabel", "Total");
2432
2432
  else {
2433
2433
  assign(column, "totalsRowFunction", "none");
2434
- column.totalsRowFormula = this.getFormula(column) || void 0;
2434
+ column.totalsRowFormula = this.getFormula(column) ?? void 0;
2435
2435
  }
2436
2436
  });
2437
2437
  }
@@ -2709,7 +2709,7 @@ var ExcelTS = (function(exports) {
2709
2709
  constructor(worksheet, range, options) {
2710
2710
  this.worksheet = worksheet;
2711
2711
  const { tl, br } = this._parseRange(range);
2712
- const shapeId = 1025 + (worksheet.formControls?.length || 0);
2712
+ const shapeId = 1025 + (worksheet.formControls?.length ?? 0);
2713
2713
  let link;
2714
2714
  if (options?.link) link = this._toAbsoluteRef(options.link);
2715
2715
  this.model = {
@@ -2976,6 +2976,14 @@ var ExcelTS = (function(exports) {
2976
2976
  const millisecondSinceEpoch = Math.round((v - 25569 + (date1904 ? 1462 : 0)) * 24 * 3600 * 1e3);
2977
2977
  return new Date(millisecondSinceEpoch);
2978
2978
  }
2979
+ /**
2980
+ * Parse an OOXML date string into a Date object.
2981
+ * OOXML dates like "2024-01-15T00:00:00" lack a timezone suffix,
2982
+ * which some JS engines parse as local time. Appending "Z" forces UTC.
2983
+ */
2984
+ function parseOoxmlDate(raw) {
2985
+ return new Date(raw.endsWith("Z") ? raw : raw + "Z");
2986
+ }
2979
2987
  const xmlDecodingMap = {
2980
2988
  lt: "<",
2981
2989
  gt: ">",
@@ -3060,8 +3068,23 @@ var ExcelTS = (function(exports) {
3060
3068
  }
3061
3069
  function toSortedArray(values) {
3062
3070
  const result = Array.from(values);
3071
+ if (result.length <= 1) return result;
3063
3072
  if (result.every((item) => Number.isFinite(item))) return result.sort((a, b) => a - b);
3064
- return result.sort();
3073
+ if (result.every((item) => item instanceof Date)) return result.sort((a, b) => a.getTime() - b.getTime());
3074
+ return result.sort((a, b) => {
3075
+ const ta = sortTypeRank(a);
3076
+ const tb = sortTypeRank(b);
3077
+ if (ta !== tb) return ta - tb;
3078
+ if (ta === 0) return a - b;
3079
+ if (ta === 1) return a.getTime() - b.getTime();
3080
+ return String(a).localeCompare(String(b));
3081
+ });
3082
+ }
3083
+ /** Rank for mixed-type sort: numbers=0, dates=1, everything else=2 */
3084
+ function sortTypeRank(v) {
3085
+ if (Number.isFinite(v)) return 0;
3086
+ if (v instanceof Date) return 1;
3087
+ return 2;
3065
3088
  }
3066
3089
  const textDecoder$2 = new TextDecoder("utf-8");
3067
3090
  let latin1Decoder;
@@ -5376,6 +5399,40 @@ var ExcelTS = (function(exports) {
5376
5399
  //#endregion
5377
5400
  //#region src/modules/excel/pivot-table.ts
5378
5401
  /**
5402
+ * Wrapper for OOXML error values in sharedItems (e.g. `<e v="REF!"/>`).
5403
+ * Distinguishes error strings from regular strings so they roundtrip as `<e>` not `<s>`.
5404
+ */
5405
+ var PivotErrorValue = class {
5406
+ constructor(code) {
5407
+ this.code = code;
5408
+ }
5409
+ /** Returns the display form with '#' prefix, e.g. "#REF!" */
5410
+ toString() {
5411
+ return `#${this.code}`;
5412
+ }
5413
+ };
5414
+ /** Map from PivotTableSubtotal to its Excel display name prefix */
5415
+ const METRIC_DISPLAY_NAMES = {
5416
+ sum: "Sum",
5417
+ count: "Count",
5418
+ average: "Average",
5419
+ max: "Max",
5420
+ min: "Min",
5421
+ product: "Product",
5422
+ countNums: "Count Numbers",
5423
+ stdDev: "StdDev",
5424
+ stdDevP: "StdDevP",
5425
+ var: "Var",
5426
+ varP: "VarP"
5427
+ };
5428
+ /** Set of all valid PivotTableSubtotal values (for runtime validation) */
5429
+ const VALID_SUBTOTALS = new Set(Object.keys(METRIC_DISPLAY_NAMES));
5430
+ /**
5431
+ * Data rows start at index 2 in ExcelJS sparse arrays:
5432
+ * index 0 = empty (ExcelJS convention), index 1 = header row.
5433
+ */
5434
+ const DATA_START_INDEX = 2;
5435
+ /**
5379
5436
  * Creates a PivotTableSource adapter from a Table object.
5380
5437
  * This allows Tables to be used as pivot table data sources with the same interface as Worksheets.
5381
5438
  */
@@ -5392,6 +5449,7 @@ var ExcelTS = (function(exports) {
5392
5449
  const headerRow = [void 0, ...columnNames];
5393
5450
  const dataRows = tableModel.rows.map((row) => [void 0, ...row]);
5394
5451
  const tl = tableModel.tl;
5452
+ if (!tl) throw new Error(`Table "${tableModel.name}" is missing top-left cell address (tl)`);
5395
5453
  const startRow = tl.row;
5396
5454
  const startCol = tl.col;
5397
5455
  const endRow = startRow + tableModel.rows.length;
@@ -5399,9 +5457,10 @@ var ExcelTS = (function(exports) {
5399
5457
  const shortRange = colCache.encode(startRow, startCol, endRow, endCol);
5400
5458
  return {
5401
5459
  name: table.worksheet.name,
5460
+ tableName: tableModel.name,
5402
5461
  getRow(rowNumber) {
5403
5462
  if (rowNumber === 1) return { values: headerRow };
5404
- const dataIndex = rowNumber - 2;
5463
+ const dataIndex = rowNumber - DATA_START_INDEX;
5405
5464
  if (dataIndex >= 0 && dataIndex < dataRows.length) return { values: dataRows[dataIndex] };
5406
5465
  return { values: [] };
5407
5466
  },
@@ -5421,54 +5480,154 @@ var ExcelTS = (function(exports) {
5421
5480
  dimensions: { shortRange }
5422
5481
  };
5423
5482
  }
5483
+ /** Base cache ID starts at 10 (Excel convention), each subsequent table increments */
5484
+ const BASE_CACHE_ID = 10;
5424
5485
  /**
5425
5486
  * Resolves the data source from the model, supporting both sourceSheet and sourceTable.
5487
+ * Validates that exactly one source is provided.
5426
5488
  */
5427
5489
  function resolveSource(model) {
5490
+ if (model.sourceSheet && model.sourceTable) throw new Error("Cannot specify both sourceSheet and sourceTable. Choose one.");
5428
5491
  if (model.sourceTable) return createTableSourceAdapter(model.sourceTable);
5492
+ if (!model.sourceSheet) throw new Error("Either sourceSheet or sourceTable must be provided.");
5429
5493
  return model.sourceSheet;
5430
5494
  }
5495
+ /** Resolve a value entry to its column name string */
5496
+ function resolveValueName(v) {
5497
+ return typeof v === "string" ? v : v.name;
5498
+ }
5499
+ /** Resolve a value entry's metric (or undefined if inheriting table-wide default) */
5500
+ function resolveValueMetric(v) {
5501
+ return typeof v === "string" ? void 0 : v.metric;
5502
+ }
5431
5503
  function makePivotTable(worksheet, model) {
5432
- if (!model.sourceSheet && !model.sourceTable) throw new Error("Either sourceSheet or sourceTable must be provided.");
5433
- if (model.sourceSheet && model.sourceTable) throw new Error("Cannot specify both sourceSheet and sourceTable. Choose one.");
5434
5504
  const source = resolveSource(model);
5435
- validate(worksheet, model, source);
5436
- const { rows, values } = model;
5505
+ validate(model, source);
5506
+ const { rows } = model;
5437
5507
  const columns = model.columns ?? [];
5438
- const cacheFields = makeCacheFields(source, [...rows, ...columns], values);
5439
- const nameToIndex = cacheFields.reduce((result, cacheField, index) => {
5440
- result[cacheField.name] = index;
5441
- return result;
5442
- }, {});
5443
- const rowIndices = rows.map((row) => nameToIndex[row]);
5444
- const columnIndices = columns.map((column) => nameToIndex[column]);
5445
- const valueIndices = values.map((value) => nameToIndex[value]);
5446
- const tableNumber = worksheet.workbook.pivotTables.length + 1;
5508
+ const pages = model.pages ?? [];
5509
+ const valueNames = model.values.map(resolveValueName);
5510
+ const defaultMetric = model.metric ?? "sum";
5511
+ const valueMetrics = model.values.map((v) => resolveValueMetric(v) ?? defaultMetric);
5512
+ const cacheFields = makeCacheFields(source, [
5513
+ ...rows,
5514
+ ...columns,
5515
+ ...pages
5516
+ ], valueNames);
5517
+ const nameToIndex = {};
5518
+ for (let i = 0; i < cacheFields.length; i++) nameToIndex[cacheFields[i].name] = i;
5519
+ const resolveIndex = (fieldName, role) => {
5520
+ const idx = nameToIndex[fieldName];
5521
+ if (idx === void 0) throw new Error(`${role} field "${fieldName}" not found in cache fields`);
5522
+ return idx;
5523
+ };
5524
+ const rowIndices = rows.map((row) => resolveIndex(row, "Row"));
5525
+ const columnIndices = columns.map((column) => resolveIndex(column, "Column"));
5526
+ const valueIndices = valueNames.map((value) => resolveIndex(value, "Value"));
5527
+ const pageIndices = pages.map((page) => resolveIndex(page, "Page"));
5528
+ const existingTableNumbers = worksheet.workbook.pivotTables.map((pt) => pt.tableNumber).filter((n) => Number.isFinite(n));
5529
+ const tableNumber = existingTableNumbers.length > 0 ? existingTableNumbers.reduce((a, b) => a > b ? a : b, -Infinity) + 1 : 1;
5530
+ const existingCacheIds = worksheet.workbook.pivotTables.map((pt) => parseInt(pt.cacheId, 10)).filter((id) => Number.isFinite(id));
5531
+ const nextCacheId = existingCacheIds.length > 0 ? existingCacheIds.reduce((a, b) => a > b ? a : b, -Infinity) + 1 : BASE_CACHE_ID + tableNumber - 1;
5447
5532
  return {
5448
5533
  source,
5449
5534
  rows: rowIndices,
5450
5535
  columns: columnIndices,
5451
5536
  values: valueIndices,
5452
- metric: model.metric ?? "sum",
5537
+ pages: pageIndices,
5538
+ metric: defaultMetric,
5539
+ valueMetrics,
5453
5540
  cacheFields,
5454
- cacheId: String(10 + tableNumber - 1),
5541
+ cacheId: String(nextCacheId),
5455
5542
  applyWidthHeightFormats: model.applyWidthHeightFormats ?? "1",
5456
5543
  tableNumber
5457
5544
  };
5458
5545
  }
5459
- function validate(_worksheet, model, source) {
5460
- if (model.metric && model.metric !== "sum" && model.metric !== "count") throw new Error("Only the \"sum\" and \"count\" metrics are supported at this time.");
5546
+ function validate(model, source) {
5461
5547
  const columns = model.columns ?? [];
5548
+ const pages = model.pages ?? [];
5549
+ const valueNames = model.values.map(resolveValueName);
5462
5550
  const headerNames = source.getRow(1).values.slice(1);
5463
- const headerNameSet = new Set(headerNames);
5464
- for (const name of [
5465
- ...model.rows,
5466
- ...columns,
5467
- ...model.values
5468
- ]) if (!headerNameSet.has(name)) throw new Error(`The header name "${name}" was not found in ${source.name}.`);
5551
+ for (let i = 0; i < headerNames.length; i++) {
5552
+ const h = headerNames[i];
5553
+ if (h === null || h === void 0 || h === "" || typeof h === "string" && h.trim() === "") throw new Error(`Empty or missing header name at column ${i + 1} in ${source.name}. Pivot tables require all columns to have non-empty headers.`);
5554
+ }
5555
+ const headerDupCheck = /* @__PURE__ */ new Set();
5556
+ for (const h of headerNames) {
5557
+ const name = String(h);
5558
+ if (headerDupCheck.has(name)) throw new Error(`Duplicate header name "${name}" found in ${source.name}. Pivot tables require unique column names.`);
5559
+ headerDupCheck.add(name);
5560
+ }
5561
+ const headerNameSet = new Set(headerNames.map(String));
5562
+ const validateFieldExists = (name) => {
5563
+ if (!headerNameSet.has(name)) throw new Error(`The header name "${name}" was not found in ${source.name}.`);
5564
+ };
5565
+ for (const name of model.rows) validateFieldExists(name);
5566
+ for (const name of columns) validateFieldExists(name);
5567
+ for (const name of valueNames) validateFieldExists(name);
5568
+ for (const name of pages) validateFieldExists(name);
5569
+ const fieldToAxis = /* @__PURE__ */ new Map();
5570
+ const axisAreas = [
5571
+ {
5572
+ name: "rows",
5573
+ fields: model.rows
5574
+ },
5575
+ {
5576
+ name: "columns",
5577
+ fields: columns
5578
+ },
5579
+ {
5580
+ name: "pages",
5581
+ fields: pages
5582
+ }
5583
+ ];
5584
+ for (const area of axisAreas) for (const field of area.fields) {
5585
+ const existing = fieldToAxis.get(field);
5586
+ if (existing === area.name) throw new Error(`Duplicate field "${field}" in ${area.name}. Each field can only appear once per axis area.`);
5587
+ else if (existing) throw new Error(`Field "${field}" cannot appear in both ${existing} and ${area.name}. Each field can only be assigned to one axis area.`);
5588
+ fieldToAxis.set(field, area.name);
5589
+ }
5469
5590
  if (!model.rows.length) throw new Error("No pivot table rows specified.");
5470
5591
  if (model.values.length < 1) throw new Error("Must have at least one value.");
5471
- if (model.values.length > 1 && columns.length > 0) throw new Error("It is currently not possible to have multiple values when columns are specified. Please either supply an empty array for columns or a single value.");
5592
+ if (model.metric !== void 0 && !VALID_SUBTOTALS.has(model.metric)) throw new Error(`Invalid metric "${model.metric}". Must be one of: ${[...VALID_SUBTOTALS].join(", ")}.`);
5593
+ for (const v of model.values) {
5594
+ const perMetric = resolveValueMetric(v);
5595
+ if (perMetric !== void 0 && !VALID_SUBTOTALS.has(perMetric)) throw new Error(`Invalid metric "${perMetric}" on value field "${resolveValueName(v)}". Must be one of: ${[...VALID_SUBTOTALS].join(", ")}.`);
5596
+ }
5597
+ const valueDupCheck = /* @__PURE__ */ new Set();
5598
+ for (const name of valueNames) {
5599
+ if (valueDupCheck.has(name)) throw new Error(`Duplicate value field "${name}". Each value field name must be unique.`);
5600
+ valueDupCheck.add(name);
5601
+ }
5602
+ }
5603
+ /**
5604
+ * R8-B2: Unwrap complex cell value types to a primitive suitable for pivot table shared items.
5605
+ * - CellErrorValue ({error:"#REF!"}) → PivotErrorValue
5606
+ * - CellRichTextValue ({richText:[...]}) → concatenated plain text
5607
+ * - CellFormulaValue / CellArrayFormulaValue / CellSharedFormulaValue → result value (recursive)
5608
+ * - CellHyperlinkValue ({text,hyperlink}) → text string
5609
+ * - CellCheckboxValue ({checkbox:bool}) → boolean
5610
+ * - Other objects → String(v)
5611
+ */
5612
+ function unwrapCellValue(v) {
5613
+ if (v === null || v === void 0) return null;
5614
+ if (typeof v !== "object") return v;
5615
+ if (v instanceof Date) return v;
5616
+ if (v instanceof PivotErrorValue) return v;
5617
+ const obj = v;
5618
+ if (typeof obj.error === "string") {
5619
+ const errorStr = obj.error;
5620
+ return new PivotErrorValue(errorStr.startsWith("#") ? errorStr.slice(1) : errorStr);
5621
+ }
5622
+ if ("formula" in obj || "sharedFormula" in obj) {
5623
+ const result = obj.result;
5624
+ if (result === void 0 || result === null) return null;
5625
+ return unwrapCellValue(result);
5626
+ }
5627
+ if (Array.isArray(obj.richText)) return obj.richText.map((rt) => rt.text ?? "").join("");
5628
+ if (typeof obj.text === "string" && typeof obj.hyperlink === "string") return obj.text;
5629
+ if (typeof obj.checkbox === "boolean") return obj.checkbox;
5630
+ return String(v);
5472
5631
  }
5473
5632
  function makeCacheFields(source, fieldNamesWithSharedItems, valueFieldNames) {
5474
5633
  const names = source.getRow(1).values;
@@ -5477,33 +5636,47 @@ var ExcelTS = (function(exports) {
5477
5636
  const aggregate = (columnIndex) => {
5478
5637
  const columnValues = source.getColumn(columnIndex).values;
5479
5638
  const uniqueValues = /* @__PURE__ */ new Set();
5480
- for (let i = 2; i < columnValues.length; i++) {
5481
- const v = columnValues[i];
5482
- if (v !== null && v !== void 0) uniqueValues.add(v);
5639
+ const seenErrors = /* @__PURE__ */ new Map();
5640
+ let hasNull = false;
5641
+ for (let i = DATA_START_INDEX; i < columnValues.length; i++) {
5642
+ const v = unwrapCellValue(columnValues[i]);
5643
+ if (v === null || typeof v === "number" && isNaN(v)) hasNull = true;
5644
+ else if (v instanceof PivotErrorValue) {
5645
+ if (!seenErrors.has(v.code)) {
5646
+ seenErrors.set(v.code, v);
5647
+ uniqueValues.add(v);
5648
+ }
5649
+ } else uniqueValues.add(v);
5483
5650
  }
5484
- return toSortedArray(uniqueValues);
5651
+ const sorted = toSortedArray(uniqueValues);
5652
+ if (hasNull) sorted.push(null);
5653
+ return sorted;
5485
5654
  };
5486
5655
  const getMinMax = (columnIndex) => {
5487
5656
  const columnValues = source.getColumn(columnIndex).values;
5488
5657
  let min = Infinity;
5489
5658
  let max = -Infinity;
5490
5659
  let hasNumeric = false;
5491
- for (let i = 2; i < columnValues.length; i++) {
5492
- const v = columnValues[i];
5493
- if (typeof v === "number" && !isNaN(v)) {
5660
+ let allInteger = true;
5661
+ for (let i = DATA_START_INDEX; i < columnValues.length; i++) {
5662
+ const unwrapped = unwrapCellValue(columnValues[i]);
5663
+ if (typeof unwrapped === "number" && !isNaN(unwrapped)) {
5494
5664
  hasNumeric = true;
5495
- if (v < min) min = v;
5496
- if (v > max) max = v;
5665
+ if (unwrapped < min) min = unwrapped;
5666
+ if (unwrapped > max) max = unwrapped;
5667
+ if (!Number.isInteger(unwrapped)) allInteger = false;
5497
5668
  }
5498
5669
  }
5499
5670
  return hasNumeric ? {
5500
5671
  minValue: min,
5501
- maxValue: max
5672
+ maxValue: max,
5673
+ allInteger
5502
5674
  } : null;
5503
5675
  };
5504
5676
  const result = [];
5505
5677
  for (const columnIndex of range(1, names.length)) {
5506
- const name = names[columnIndex];
5678
+ const rawName = names[columnIndex];
5679
+ const name = String(rawName);
5507
5680
  if (sharedItemsFields.has(name)) result.push({
5508
5681
  name,
5509
5682
  sharedItems: aggregate(columnIndex)
@@ -5513,8 +5686,10 @@ var ExcelTS = (function(exports) {
5513
5686
  result.push({
5514
5687
  name,
5515
5688
  sharedItems: null,
5689
+ containsNumber: minMax ? "1" : void 0,
5516
5690
  minValue: minMax?.minValue,
5517
- maxValue: minMax?.maxValue
5691
+ maxValue: minMax?.maxValue,
5692
+ containsInteger: minMax?.allInteger ? "1" : void 0
5518
5693
  });
5519
5694
  } else result.push({
5520
5695
  name,
@@ -5569,10 +5744,10 @@ var ExcelTS = (function(exports) {
5569
5744
  constructor(options) {
5570
5745
  options = options || {};
5571
5746
  this._workbook = options.workbook;
5572
- this.id = options.id || 0;
5573
- this.orderNo = options.orderNo || 0;
5747
+ this.id = options.id ?? 0;
5748
+ this.orderNo = options.orderNo ?? 0;
5574
5749
  this.name = options.name || `sheet${this.id}`;
5575
- this.state = options.state || "visible";
5750
+ this.state = options.state ?? "visible";
5576
5751
  this._rows = [];
5577
5752
  this._columns = null;
5578
5753
  this._keys = {};
@@ -5625,8 +5800,8 @@ var ExcelTS = (function(exports) {
5625
5800
  firstFooter: null
5626
5801
  }, options.headerFooter);
5627
5802
  this.dataValidations = new DataValidations();
5628
- this.views = options.views || [];
5629
- this.autoFilter = options.autoFilter || null;
5803
+ this.views = options.views ?? [];
5804
+ this.autoFilter = options.autoFilter ?? null;
5630
5805
  this._media = [];
5631
5806
  this.sheetProtection = null;
5632
5807
  this.tables = {};
@@ -5745,7 +5920,7 @@ var ExcelTS = (function(exports) {
5745
5920
  spliceColumns(start, count, ...inserts) {
5746
5921
  const nRows = this._rows.length;
5747
5922
  if (inserts.length > 0) for (let i = 0; i < nRows; i++) {
5748
- const insertValues = inserts.map((insert) => insert[i] || null);
5923
+ const insertValues = inserts.map((insert) => insert[i] ?? null);
5749
5924
  this.getRow(i + 1).splice(start, count, ...insertValues);
5750
5925
  }
5751
5926
  else this._rows.forEach((r) => {
@@ -6240,7 +6415,7 @@ var ExcelTS = (function(exports) {
6240
6415
  formControls: this.formControls.map((fc) => fc.model),
6241
6416
  drawing: this._drawing
6242
6417
  };
6243
- model.cols = Column.toModel(this.columns || []);
6418
+ model.cols = Column.toModel(this.columns ?? []);
6244
6419
  const rows = model.rows = [];
6245
6420
  const dimensions = model.dimensions = new Range();
6246
6421
  this._rows.forEach((row) => {
@@ -6278,8 +6453,8 @@ var ExcelTS = (function(exports) {
6278
6453
  this.properties = value.properties;
6279
6454
  this.pageSetup = value.pageSetup;
6280
6455
  this.headerFooter = value.headerFooter;
6281
- this.rowBreaks = value.rowBreaks || [];
6282
- this.colBreaks = value.colBreaks || [];
6456
+ this.rowBreaks = value.rowBreaks ?? [];
6457
+ this.colBreaks = value.colBreaks ?? [];
6283
6458
  this.views = value.views;
6284
6459
  this.autoFilter = value.autoFilter;
6285
6460
  this._media = value.media.map((medium) => new Image(this, medium));
@@ -6567,7 +6742,7 @@ var ExcelTS = (function(exports) {
6567
6742
  value.forEach((definedName) => {
6568
6743
  const matrix = matrixMap[definedName.name] = new CellMatrix();
6569
6744
  definedName.ranges.forEach((rangeStr) => {
6570
- if (rangeRegexp.test(rangeStr.split("!").pop() || "")) matrix.addCell(rangeStr);
6745
+ if (rangeRegexp.test(rangeStr.split("!").pop() ?? "")) matrix.addCell(rangeStr);
6571
6746
  });
6572
6747
  });
6573
6748
  }
@@ -7634,7 +7809,7 @@ var ExcelTS = (function(exports) {
7634
7809
  }
7635
7810
  reconcile(_model, _options) {}
7636
7811
  reset() {
7637
- this.model = null;
7812
+ this.model = void 0;
7638
7813
  if (this.map) Object.values(this.map).forEach((xform) => {
7639
7814
  if (xform instanceof BaseXform) xform.reset();
7640
7815
  else if (xform.xform) xform.xform.reset();
@@ -7774,7 +7949,7 @@ var ExcelTS = (function(exports) {
7774
7949
  this.always = !!options.always;
7775
7950
  this.count = options.count;
7776
7951
  this.empty = options.empty;
7777
- this.$count = options.$count || "count";
7952
+ this.$count = options.$count ?? "count";
7778
7953
  this.$ = options.$;
7779
7954
  this.childXform = options.childXform;
7780
7955
  this.maxItems = options.maxItems;
@@ -7789,9 +7964,9 @@ var ExcelTS = (function(exports) {
7789
7964
  render(xmlStream, model) {
7790
7965
  if (this.always || model && model.length) {
7791
7966
  xmlStream.openNode(this.tag, this.$);
7792
- if (this.count) xmlStream.addAttribute(this.$count, model && model.length || 0);
7967
+ if (this.count) xmlStream.addAttribute(this.$count, model?.length ?? 0);
7793
7968
  const { childXform } = this;
7794
- (model || []).forEach((childModel, index) => {
7969
+ (model ?? []).forEach((childModel, index) => {
7795
7970
  childXform.render(xmlStream, childModel, index);
7796
7971
  });
7797
7972
  xmlStream.closeNode();
@@ -7845,7 +8020,7 @@ var ExcelTS = (function(exports) {
7845
8020
  var ColorXform = class extends BaseXform {
7846
8021
  constructor(name) {
7847
8022
  super();
7848
- this.name = name || "color";
8023
+ this.name = name ?? "color";
7849
8024
  }
7850
8025
  get tag() {
7851
8026
  return this.name;
@@ -9021,12 +9196,12 @@ var ExcelTS = (function(exports) {
9021
9196
  }
9022
9197
  render(xmlStream, model) {
9023
9198
  xmlStream.openNode("xf", {
9024
- numFmtId: model.numFmtId || 0,
9025
- fontId: model.fontId || 0,
9026
- fillId: model.fillId || 0,
9027
- borderId: model.borderId || 0
9199
+ numFmtId: model.numFmtId ?? 0,
9200
+ fontId: model.fontId ?? 0,
9201
+ fillId: model.fillId ?? 0,
9202
+ borderId: model.borderId ?? 0
9028
9203
  });
9029
- if (this.xfId) xmlStream.addAttribute("xfId", model.xfId || 0);
9204
+ if (this.xfId) xmlStream.addAttribute("xfId", model.xfId ?? 0);
9030
9205
  if (model.applyNumberFormat || model.numFmtId) xmlStream.addAttribute("applyNumberFormat", "1");
9031
9206
  if (model.applyFont || model.fontId) xmlStream.addAttribute("applyFont", "1");
9032
9207
  if (model.applyFill || model.fillId) xmlStream.addAttribute("applyFill", "1");
@@ -9916,8 +10091,8 @@ var ExcelTS = (function(exports) {
9916
10091
  }
9917
10092
  render(xmlStream, model) {
9918
10093
  xmlStream.openNode(this.tag, {
9919
- sb: model.sb || 0,
9920
- eb: model.eb || 0
10094
+ sb: model.sb ?? 0,
10095
+ eb: model.eb ?? 0
9921
10096
  });
9922
10097
  if (model && Object.prototype.hasOwnProperty.call(model, "richText") && model.richText) {
9923
10098
  const { r } = this.map;
@@ -10424,7 +10599,7 @@ var ExcelTS = (function(exports) {
10424
10599
  xmlStream.openXml(XmlStream.StdDocAttributes);
10425
10600
  xmlStream.openNode("Types", ContentTypesXform.PROPERTY_ATTRIBUTES);
10426
10601
  const mediaHash = {};
10427
- (model.media || []).forEach((medium) => {
10602
+ (model.media ?? []).forEach((medium) => {
10428
10603
  if (medium.type === "image") {
10429
10604
  const imageType = medium.extension;
10430
10605
  if (!mediaHash[imageType]) {
@@ -10455,21 +10630,28 @@ var ExcelTS = (function(exports) {
10455
10630
  ContentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"
10456
10631
  });
10457
10632
  });
10458
- if ((model.pivotTables || []).length) (model.pivotTables || []).forEach((pivotTable) => {
10459
- const n = pivotTable.tableNumber;
10460
- xmlStream.leafNode("Override", {
10461
- PartName: toContentTypesPartName(pivotCacheDefinitionPath(n)),
10462
- ContentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml"
10463
- });
10464
- xmlStream.leafNode("Override", {
10465
- PartName: toContentTypesPartName(pivotCacheRecordsPath(n)),
10466
- ContentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheRecords+xml"
10467
- });
10468
- xmlStream.leafNode("Override", {
10469
- PartName: toContentTypesPartName(pivotTablePath(n)),
10470
- ContentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml"
10633
+ if ((model.pivotTables ?? []).length) {
10634
+ const writtenCacheIds = /* @__PURE__ */ new Set();
10635
+ (model.pivotTables ?? []).forEach((pivotTable) => {
10636
+ const n = pivotTable.tableNumber;
10637
+ const cacheId = pivotTable.cacheId;
10638
+ if (!writtenCacheIds.has(cacheId)) {
10639
+ writtenCacheIds.add(cacheId);
10640
+ xmlStream.leafNode("Override", {
10641
+ PartName: toContentTypesPartName(pivotCacheDefinitionPath(n)),
10642
+ ContentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml"
10643
+ });
10644
+ if (pivotTable.isLoaded ? !!pivotTable.cacheRecords : true) xmlStream.leafNode("Override", {
10645
+ PartName: toContentTypesPartName(pivotCacheRecordsPath(n)),
10646
+ ContentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheRecords+xml"
10647
+ });
10648
+ }
10649
+ xmlStream.leafNode("Override", {
10650
+ PartName: toContentTypesPartName(pivotTablePath(n)),
10651
+ ContentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml"
10652
+ });
10471
10653
  });
10472
- });
10654
+ }
10473
10655
  xmlStream.leafNode("Override", {
10474
10656
  PartName: toContentTypesPartName(OOXML_PATHS.xlTheme1),
10475
10657
  ContentType: "application/vnd.openxmlformats-officedocument.theme+xml"
@@ -10611,7 +10793,7 @@ var ExcelTS = (function(exports) {
10611
10793
  xmlStream.leafNode("ScaleCrop", void 0, "false");
10612
10794
  this.map.HeadingPairs.render(xmlStream, model.worksheets);
10613
10795
  this.map.TitlesOfParts.render(xmlStream, model.worksheets);
10614
- this.map.Company.render(xmlStream, model.company || "");
10796
+ this.map.Company.render(xmlStream, model.company ?? "");
10615
10797
  this.map.Manager.render(xmlStream, model.manager);
10616
10798
  xmlStream.leafNode("LinksUpToDate", void 0, "false");
10617
10799
  xmlStream.leafNode("SharedDoc", void 0, "false");
@@ -10712,7 +10894,7 @@ var ExcelTS = (function(exports) {
10712
10894
  const colRangeRegexp = /^[$]?[A-Za-z]{1,3}:[$]?[A-Za-z]{1,3}$/;
10713
10895
  function isValidRange(range) {
10714
10896
  if (range.startsWith("{") || range.endsWith("}")) return false;
10715
- const cellRef = range.split("!").pop() || "";
10897
+ const cellRef = range.split("!").pop() ?? "";
10716
10898
  if (!cellRangeRegexp.test(cellRef) && !rowRangeRegexp.test(cellRef) && !colRangeRegexp.test(cellRef)) return false;
10717
10899
  try {
10718
10900
  const decoded = colCache.decodeEx(range);
@@ -10730,7 +10912,7 @@ var ExcelTS = (function(exports) {
10730
10912
  let last = "";
10731
10913
  parsedText.split(",").forEach((item) => {
10732
10914
  if (!item) return;
10733
- const quotes = (item.match(/'/g) || []).length;
10915
+ const quotes = (item.match(/'/g) ?? []).length;
10734
10916
  if (!quotes) {
10735
10917
  if (quotesOpened) last += `${item},`;
10736
10918
  else if (isValidRange(item)) ranges.push(item);
@@ -10784,10 +10966,10 @@ var ExcelTS = (function(exports) {
10784
10966
  var WorkbookViewXform = class extends BaseXform {
10785
10967
  render(xmlStream, model) {
10786
10968
  const attributes = {
10787
- xWindow: model.x || 0,
10788
- yWindow: model.y || 0,
10789
- windowWidth: model.width || 12e3,
10790
- windowHeight: model.height || 24e3,
10969
+ xWindow: model.x ?? 0,
10970
+ yWindow: model.y ?? 0,
10971
+ windowWidth: model.width ?? 12e3,
10972
+ windowHeight: model.height ?? 24e3,
10791
10973
  firstSheet: model.firstSheet,
10792
10974
  activeTab: model.activeTab
10793
10975
  };
@@ -10955,7 +11137,7 @@ var ExcelTS = (function(exports) {
10955
11137
  index++;
10956
11138
  });
10957
11139
  if (printAreas.length) model.definedNames = model.definedNames.concat(printAreas);
10958
- (model.media || []).forEach((medium, i) => {
11140
+ (model.media ?? []).forEach((medium, i) => {
10959
11141
  medium.name = medium.type + (i + 1);
10960
11142
  });
10961
11143
  }
@@ -10968,7 +11150,14 @@ var ExcelTS = (function(exports) {
10968
11150
  this.map.sheets.render(xmlStream, model.sheets);
10969
11151
  this.map.definedNames.render(xmlStream, model.definedNames);
10970
11152
  this.map.calcPr.render(xmlStream, model.calcProperties);
10971
- this.map.pivotCaches.render(xmlStream, model.pivotTables);
11153
+ const pivotTables = model.pivotTables ?? [];
11154
+ const seenCacheIds = /* @__PURE__ */ new Set();
11155
+ const uniquePivotCaches = pivotTables.filter((pt) => {
11156
+ if (seenCacheIds.has(pt.cacheId)) return false;
11157
+ seenCacheIds.add(pt.cacheId);
11158
+ return true;
11159
+ });
11160
+ this.map.pivotCaches.render(xmlStream, uniquePivotCaches);
10972
11161
  xmlStream.closeNode();
10973
11162
  }
10974
11163
  parseOpen(node) {
@@ -11007,14 +11196,14 @@ var ExcelTS = (function(exports) {
11007
11196
  }
11008
11197
  }
11009
11198
  reconcile(model) {
11010
- const rels = (model.workbookRels || []).reduce((map, rel) => {
11199
+ const rels = (model.workbookRels ?? []).reduce((map, rel) => {
11011
11200
  map[rel.Id] = rel;
11012
11201
  return map;
11013
11202
  }, {});
11014
11203
  const worksheets = [];
11015
11204
  let worksheet;
11016
11205
  let index = 0;
11017
- (model.sheets || []).forEach((sheet) => {
11206
+ (model.sheets ?? []).forEach((sheet) => {
11018
11207
  const rel = rels[sheet.rId];
11019
11208
  if (!rel) return;
11020
11209
  worksheet = model.worksheetHash[`xl/${rel.Target.replace(/^(\s|\/xl\/)+/, "")}`];
@@ -11431,7 +11620,7 @@ var ExcelTS = (function(exports) {
11431
11620
  return true;
11432
11621
  case "r":
11433
11622
  this.model.value = this.model.value || {};
11434
- this.model.value.richText = this.model.value.richText || [];
11623
+ this.model.value.richText = this.model.value.richText ?? [];
11435
11624
  this.model.value.richText.push(this.parser.model);
11436
11625
  this.parser = void 0;
11437
11626
  this.currentNode = void 0;
@@ -11625,9 +11814,9 @@ var ExcelTS = (function(exports) {
11625
11814
  parseOpen(node) {
11626
11815
  if (node.name === "col") {
11627
11816
  const model = this.model = {
11628
- min: parseInt(node.attributes.min || "0", 10),
11629
- max: parseInt(node.attributes.max || "0", 10),
11630
- width: node.attributes.width === void 0 ? void 0 : parseFloat(node.attributes.width || "0")
11817
+ min: parseInt(node.attributes.min ?? "0", 10),
11818
+ max: parseInt(node.attributes.max ?? "0", 10),
11819
+ width: node.attributes.width === void 0 ? void 0 : parseFloat(node.attributes.width ?? "0")
11631
11820
  };
11632
11821
  if (node.attributes.style) model.styleId = parseInt(node.attributes.style, 10);
11633
11822
  if (parseBoolean(node.attributes.hidden)) model.hidden = true;
@@ -11834,7 +12023,7 @@ var ExcelTS = (function(exports) {
11834
12023
  if (value.errorTitle) xmlStream.addAttribute("errorTitle", value.errorTitle);
11835
12024
  if (value.error) xmlStream.addAttribute("error", value.error);
11836
12025
  xmlStream.addAttribute("sqref", value.sqref);
11837
- (value.formulae || []).forEach((formula, index) => {
12026
+ (value.formulae ?? []).forEach((formula, index) => {
11838
12027
  xmlStream.openNode(`formula${index + 1}`);
11839
12028
  if (value.type === "date") xmlStream.writeText(dateToExcel(new Date(formula)));
11840
12029
  else xmlStream.writeText(formula);
@@ -11853,7 +12042,7 @@ var ExcelTS = (function(exports) {
11853
12042
  case "dataValidation": {
11854
12043
  this._address = node.attributes.sqref;
11855
12044
  const dataValidation = {
11856
- type: node.attributes.type || "any",
12045
+ type: node.attributes.type ?? "any",
11857
12046
  formulae: []
11858
12047
  };
11859
12048
  if (node.attributes.type) assignBool(dataValidation, node.attributes, "allowBlank");
@@ -11893,7 +12082,7 @@ var ExcelTS = (function(exports) {
11893
12082
  delete this._dataValidation.formulae;
11894
12083
  delete this._dataValidation.operator;
11895
12084
  }
11896
- (this._address.split(/\s+/g) || []).forEach((addr) => {
12085
+ this._address.split(/\s+/g).forEach((addr) => {
11897
12086
  if (addr.includes(":")) this.model[`range:${addr}`] = this._dataValidation;
11898
12087
  else this.model[addr] = this._dataValidation;
11899
12088
  });
@@ -12070,10 +12259,10 @@ var ExcelTS = (function(exports) {
12070
12259
  parseOpen(node) {
12071
12260
  if (node.name === "sheetFormatPr") {
12072
12261
  this.model = {
12073
- defaultRowHeight: parseFloat(node.attributes.defaultRowHeight || "0"),
12262
+ defaultRowHeight: parseFloat(node.attributes.defaultRowHeight ?? "0"),
12074
12263
  dyDescent: node.attributes["x14ac:dyDescent"] !== void 0 ? parseFloat(node.attributes["x14ac:dyDescent"]) : void 0,
12075
- outlineLevelRow: parseInt(node.attributes.outlineLevelRow || "0", 10),
12076
- outlineLevelCol: parseInt(node.attributes.outlineLevelCol || "0", 10)
12264
+ outlineLevelRow: parseInt(node.attributes.outlineLevelRow ?? "0", 10),
12265
+ outlineLevelCol: parseInt(node.attributes.outlineLevelCol ?? "0", 10)
12077
12266
  };
12078
12267
  if (node.attributes.defaultColWidth) this.model.defaultColWidth = parseFloat(node.attributes.defaultColWidth);
12079
12268
  if (node.attributes.customHeight === "1") this.model.customHeight = true;
@@ -12110,7 +12299,7 @@ var ExcelTS = (function(exports) {
12110
12299
  render(xmlStream, model) {
12111
12300
  const initialAttrs = {};
12112
12301
  if (model.tabSelected) initialAttrs.tabSelected = "1";
12113
- initialAttrs.workbookViewId = model.workbookViewId || 0;
12302
+ initialAttrs.workbookViewId = model.workbookViewId ?? 0;
12114
12303
  xmlStream.openNode("sheetView", initialAttrs);
12115
12304
  const add = function(name, value, included) {
12116
12305
  if (included) xmlStream.addAttribute(name, value);
@@ -12128,8 +12317,8 @@ var ExcelTS = (function(exports) {
12128
12317
  let activePane;
12129
12318
  switch (model.state) {
12130
12319
  case "frozen":
12131
- xSplit = model.xSplit || 0;
12132
- ySplit = model.ySplit || 0;
12320
+ xSplit = model.xSplit ?? 0;
12321
+ ySplit = model.ySplit ?? 0;
12133
12322
  topLeftCell = model.topLeftCell || colCache.getAddress(ySplit + 1, xSplit + 1).address;
12134
12323
  activePane = model.xSplit && model.ySplit && "bottomRight" || model.xSplit && "topRight" || "bottomLeft";
12135
12324
  xmlStream.leafNode("pane", {
@@ -12179,8 +12368,8 @@ var ExcelTS = (function(exports) {
12179
12368
  showRuler: !(node.attributes.showRuler === "0"),
12180
12369
  showRowColHeaders: !(node.attributes.showRowColHeaders === "0"),
12181
12370
  showGridLines: !(node.attributes.showGridLines === "0"),
12182
- zoomScale: parseInt(node.attributes.zoomScale || "100", 10),
12183
- zoomScaleNormal: parseInt(node.attributes.zoomScaleNormal || "100", 10),
12371
+ zoomScale: parseInt(node.attributes.zoomScale ?? "100", 10),
12372
+ zoomScaleNormal: parseInt(node.attributes.zoomScaleNormal ?? "100", 10),
12184
12373
  style: node.attributes.view
12185
12374
  };
12186
12375
  this.pane = void 0;
@@ -12188,15 +12377,15 @@ var ExcelTS = (function(exports) {
12188
12377
  return true;
12189
12378
  case "pane":
12190
12379
  this.pane = {
12191
- xSplit: parseInt(node.attributes.xSplit || "0", 10),
12192
- ySplit: parseInt(node.attributes.ySplit || "0", 10),
12380
+ xSplit: parseInt(node.attributes.xSplit ?? "0", 10),
12381
+ ySplit: parseInt(node.attributes.ySplit ?? "0", 10),
12193
12382
  topLeftCell: node.attributes.topLeftCell,
12194
- activePane: node.attributes.activePane || "topLeft",
12383
+ activePane: node.attributes.activePane ?? "topLeft",
12195
12384
  state: node.attributes.state
12196
12385
  };
12197
12386
  return true;
12198
12387
  case "selection": {
12199
- const name = node.attributes.pane || "topLeft";
12388
+ const name = node.attributes.pane ?? "topLeft";
12200
12389
  this.selections[name] = {
12201
12390
  pane: name,
12202
12391
  activeCell: node.attributes.activeCell
@@ -12217,7 +12406,7 @@ var ExcelTS = (function(exports) {
12217
12406
  workbookViewId: this.sheetView.workbookViewId,
12218
12407
  rightToLeft: this.sheetView.rightToLeft,
12219
12408
  tabSelected: this.sheetView.tabSelected,
12220
- state: VIEW_STATES[this.pane.state] || "split",
12409
+ state: VIEW_STATES[this.pane.state] ?? "split",
12221
12410
  xSplit: this.pane.xSplit,
12222
12411
  ySplit: this.pane.ySplit,
12223
12412
  topLeftCell: this.pane.topLeftCell,
@@ -12439,21 +12628,21 @@ var ExcelTS = (function(exports) {
12439
12628
  case this.tag:
12440
12629
  this.model = {
12441
12630
  paperSize: pageSizeToModel(node.attributes.paperSize),
12442
- orientation: node.attributes.orientation || "portrait",
12443
- horizontalDpi: parseInt(node.attributes.horizontalDpi || "4294967295", 10),
12444
- verticalDpi: parseInt(node.attributes.verticalDpi || "4294967295", 10),
12445
- pageOrder: node.attributes.pageOrder || "downThenOver",
12631
+ orientation: node.attributes.orientation ?? "portrait",
12632
+ horizontalDpi: parseInt(node.attributes.horizontalDpi ?? "4294967295", 10),
12633
+ verticalDpi: parseInt(node.attributes.verticalDpi ?? "4294967295", 10),
12634
+ pageOrder: node.attributes.pageOrder ?? "downThenOver",
12446
12635
  blackAndWhite: node.attributes.blackAndWhite === "1",
12447
12636
  draft: node.attributes.draft === "1",
12448
- cellComments: node.attributes.cellComments || "None",
12449
- errors: node.attributes.errors || "displayed",
12450
- scale: parseInt(node.attributes.scale || "100", 10),
12451
- fitToWidth: parseInt(node.attributes.fitToWidth || "1", 10),
12452
- fitToHeight: parseInt(node.attributes.fitToHeight || "1", 10),
12453
- firstPageNumber: parseInt(node.attributes.firstPageNumber || "1", 10),
12637
+ cellComments: node.attributes.cellComments ?? "None",
12638
+ errors: node.attributes.errors ?? "displayed",
12639
+ scale: parseInt(node.attributes.scale ?? "100", 10),
12640
+ fitToWidth: parseInt(node.attributes.fitToWidth ?? "1", 10),
12641
+ fitToHeight: parseInt(node.attributes.fitToHeight ?? "1", 10),
12642
+ firstPageNumber: parseInt(node.attributes.firstPageNumber ?? "1", 10),
12454
12643
  useFirstPageNumber: node.attributes.useFirstPageNumber === "1",
12455
12644
  usePrinterDefaults: node.attributes.usePrinterDefaults === "1",
12456
- copies: parseInt(node.attributes.copies || "1", 10)
12645
+ copies: parseInt(node.attributes.copies ?? "1", 10)
12457
12646
  };
12458
12647
  return true;
12459
12648
  default: return false;
@@ -12766,22 +12955,22 @@ var ExcelTS = (function(exports) {
12766
12955
  parseText(text) {
12767
12956
  switch (this.currentNode) {
12768
12957
  case "oddHeader":
12769
- this.model.oddHeader = (this.model.oddHeader || "") + text;
12958
+ this.model.oddHeader = (this.model.oddHeader ?? "") + text;
12770
12959
  break;
12771
12960
  case "oddFooter":
12772
- this.model.oddFooter = (this.model.oddFooter || "") + text;
12961
+ this.model.oddFooter = (this.model.oddFooter ?? "") + text;
12773
12962
  break;
12774
12963
  case "evenHeader":
12775
- this.model.evenHeader = (this.model.evenHeader || "") + text;
12964
+ this.model.evenHeader = (this.model.evenHeader ?? "") + text;
12776
12965
  break;
12777
12966
  case "evenFooter":
12778
- this.model.evenFooter = (this.model.evenFooter || "") + text;
12967
+ this.model.evenFooter = (this.model.evenFooter ?? "") + text;
12779
12968
  break;
12780
12969
  case "firstHeader":
12781
- this.model.firstHeader = (this.model.firstHeader || "") + text;
12970
+ this.model.firstHeader = (this.model.firstHeader ?? "") + text;
12782
12971
  break;
12783
12972
  case "firstFooter":
12784
- this.model.firstFooter = (this.model.firstFooter || "") + text;
12973
+ this.model.firstFooter = (this.model.firstFooter ?? "") + text;
12785
12974
  break;
12786
12975
  default: break;
12787
12976
  }
@@ -13262,7 +13451,7 @@ var ExcelTS = (function(exports) {
13262
13451
  Object.assign(this.model, parser.model);
13263
13452
  break;
13264
13453
  case "formula":
13265
- this.model.formulae = this.model.formulae || [];
13454
+ this.model.formulae = this.model.formulae ?? [];
13266
13455
  this.model.formulae.push(parser.model);
13267
13456
  break;
13268
13457
  }
@@ -13315,7 +13504,7 @@ var ExcelTS = (function(exports) {
13315
13504
  this.model = [];
13316
13505
  }
13317
13506
  prepare(model, options) {
13318
- let nextPriority = model.reduce((p, cf) => Math.max(p, ...cf.rules.map((rule) => rule.priority || 0)), 1);
13507
+ let nextPriority = model.reduce((p, cf) => Math.max(p, ...cf.rules.map((rule) => rule.priority ?? 0)), 1);
13319
13508
  model.forEach((cf) => {
13320
13509
  cf.rules.forEach((rule) => {
13321
13510
  if (!rule.priority) rule.priority = nextPriority++;
@@ -13644,7 +13833,7 @@ var ExcelTS = (function(exports) {
13644
13833
  xmlStream.openNode(this.tag, {
13645
13834
  type: "iconSet",
13646
13835
  priority: model.priority,
13647
- id: model.x14Id || `{${uuidV4()}}`
13836
+ id: model.x14Id ?? `{${uuidV4()}}`
13648
13837
  });
13649
13838
  this.iconSetXform.render(xmlStream, model);
13650
13839
  xmlStream.closeNode();
@@ -13861,7 +14050,7 @@ var ExcelTS = (function(exports) {
13861
14050
  constructor(options) {
13862
14051
  super();
13863
14052
  const { maxRows, maxCols, ignoreNodes } = options || {};
13864
- this.ignoreNodes = ignoreNodes || [];
14053
+ this.ignoreNodes = ignoreNodes ?? [];
13865
14054
  this.map = {
13866
14055
  sheetPr: new SheetPropertiesXform(),
13867
14056
  dimension: new DimensionXform(),
@@ -14047,7 +14236,7 @@ var ExcelTS = (function(exports) {
14047
14236
  if (style) column.dxfId = options.styles.addDxfStyle(style);
14048
14237
  });
14049
14238
  });
14050
- (model.pivotTables || []).forEach((pivotTable) => {
14239
+ (model.pivotTables ?? []).forEach((pivotTable) => {
14051
14240
  rels.push({
14052
14241
  Id: nextRid(rels),
14053
14242
  Type: RelType.PivotTable,
@@ -14267,8 +14456,8 @@ var ExcelTS = (function(exports) {
14267
14456
  drawing: this.map.drawing.model,
14268
14457
  tables: this.map.tableParts.model,
14269
14458
  conditionalFormattings,
14270
- rowBreaks: this.map.rowBreaks.model || [],
14271
- colBreaks: this.map.colBreaks.model || []
14459
+ rowBreaks: this.map.rowBreaks.model ?? [],
14460
+ colBreaks: this.map.colBreaks.model ?? []
14272
14461
  };
14273
14462
  if (this.map.autoFilter.model) this.model.autoFilter = this.map.autoFilter.model;
14274
14463
  if (this.map.sheetProtection.model) this.model.sheetProtection = this.map.sheetProtection.model;
@@ -14278,7 +14467,7 @@ var ExcelTS = (function(exports) {
14278
14467
  }
14279
14468
  }
14280
14469
  reconcile(model, options) {
14281
- const rels = (model.relationships || []).reduce((h, rel) => {
14470
+ const rels = (model.relationships ?? []).reduce((h, rel) => {
14282
14471
  h[rel.Id] = rel;
14283
14472
  if (rel.Type === RelType.Comments) model.comments = options.comments[rel.Target].comments;
14284
14473
  if (rel.Type === RelType.VmlDrawing && model.comments && model.comments.length) {
@@ -14289,18 +14478,18 @@ var ExcelTS = (function(exports) {
14289
14478
  }
14290
14479
  return h;
14291
14480
  }, {});
14292
- options.commentsMap = (model.comments || []).reduce((h, comment) => {
14481
+ options.commentsMap = (model.comments ?? []).reduce((h, comment) => {
14293
14482
  if (comment.ref) h[comment.ref] = comment;
14294
14483
  return h;
14295
14484
  }, {});
14296
- options.hyperlinkMap = (model.hyperlinks || []).reduce((h, hyperlink) => {
14485
+ options.hyperlinkMap = (model.hyperlinks ?? []).reduce((h, hyperlink) => {
14297
14486
  if (hyperlink.rId) h[hyperlink.address] = rels[hyperlink.rId].Target;
14298
14487
  return h;
14299
14488
  }, {});
14300
14489
  options.formulae = {};
14301
- model.rows = model.rows && model.rows.filter(Boolean) || [];
14490
+ model.rows = model.rows?.filter(Boolean) ?? [];
14302
14491
  model.rows.forEach((row) => {
14303
- row.cells = row.cells && row.cells.filter(Boolean) || [];
14492
+ row.cells = row.cells?.filter(Boolean) ?? [];
14304
14493
  });
14305
14494
  this.map.cols.reconcile(model.cols, options);
14306
14495
  this.map.sheetData.reconcile(model.rows, options);
@@ -14315,7 +14504,7 @@ var ExcelTS = (function(exports) {
14315
14504
  model.drawing = {
14316
14505
  ...drawing,
14317
14506
  name: drawingName,
14318
- rels: options.drawingRels?.[drawingName] || drawing.rels || []
14507
+ rels: options.drawingRels?.[drawingName] ?? drawing.rels ?? []
14319
14508
  };
14320
14509
  drawing.anchors.forEach((anchor) => {
14321
14510
  if (anchor.medium) {
@@ -14340,12 +14529,12 @@ var ExcelTS = (function(exports) {
14340
14529
  imageId
14341
14530
  });
14342
14531
  }
14343
- model.tables = (model.tables || []).map((tablePart) => {
14532
+ model.tables = (model.tables ?? []).map((tablePart) => {
14344
14533
  const rel = rels[tablePart.rId];
14345
14534
  return options.tables[rel.Target];
14346
14535
  });
14347
14536
  model.pivotTables = [];
14348
- (model.relationships || []).forEach((rel) => {
14537
+ (model.relationships ?? []).forEach((rel) => {
14349
14538
  if (rel.Type === RelType.PivotTable && options.pivotTables) {
14350
14539
  const pivotTable = options.pivotTables[rel.Target];
14351
14540
  if (pivotTable) model.pivotTables.push(pivotTable);
@@ -14404,7 +14593,7 @@ var ExcelTS = (function(exports) {
14404
14593
  switch (node.name) {
14405
14594
  case this.tag:
14406
14595
  this.reset();
14407
- this.model = { range: { editAs: node.attributes.editAs || "oneCell" } };
14596
+ this.model = { range: { editAs: node.attributes.editAs ?? "oneCell" } };
14408
14597
  break;
14409
14598
  default:
14410
14599
  this.parser = this.map[node.name];
@@ -15021,7 +15210,7 @@ var ExcelTS = (function(exports) {
15021
15210
  ...model.alternateContent?.requires === "a14" ? { "xmlns:a14": "http://schemas.microsoft.com/office/drawing/2010/main" } : {}
15022
15211
  });
15023
15212
  }
15024
- xmlStream.openNode(this.tag, { editAs: model.range.editAs || "oneCell" });
15213
+ xmlStream.openNode(this.tag, { editAs: model.range.editAs ?? "oneCell" });
15025
15214
  this.map["xdr:from"].render(xmlStream, model.range.tl);
15026
15215
  this.map["xdr:to"].render(xmlStream, model.range.br);
15027
15216
  if (model.picture) this.map["xdr:pic"].render(xmlStream, model.picture);
@@ -15078,8 +15267,8 @@ var ExcelTS = (function(exports) {
15078
15267
  parseOpen(node) {
15079
15268
  if (node.name === this.tag) {
15080
15269
  this.model = {
15081
- width: parseInt(node.attributes.cx || "0", 10) / EMU_PER_PIXEL_AT_96_DPI,
15082
- height: parseInt(node.attributes.cy || "0", 10) / EMU_PER_PIXEL_AT_96_DPI
15270
+ width: parseInt(node.attributes.cx ?? "0", 10) / EMU_PER_PIXEL_AT_96_DPI,
15271
+ height: parseInt(node.attributes.cy ?? "0", 10) / EMU_PER_PIXEL_AT_96_DPI
15083
15272
  };
15084
15273
  return true;
15085
15274
  }
@@ -15110,7 +15299,7 @@ var ExcelTS = (function(exports) {
15110
15299
  this.map["xdr:pic"].prepare(model.picture, options);
15111
15300
  }
15112
15301
  render(xmlStream, model) {
15113
- xmlStream.openNode(this.tag, { editAs: model.range.editAs || "oneCell" });
15302
+ xmlStream.openNode(this.tag, { editAs: model.range.editAs ?? "oneCell" });
15114
15303
  this.map["xdr:from"].render(xmlStream, model.range.tl);
15115
15304
  this.map["xdr:ext"].render(xmlStream, model.range.ext);
15116
15305
  this.map["xdr:pic"].render(xmlStream, model.picture);
@@ -15604,16 +15793,145 @@ var ExcelTS = (function(exports) {
15604
15793
  }
15605
15794
  };
15606
15795
 
15796
+ //#endregion
15797
+ //#region src/modules/excel/xlsx/xform/pivot-table/cache-field.ts
15798
+ /**
15799
+ * Format a Date for OOXML pivot cache output.
15800
+ * Excel expects `"2024-01-15T00:00:00"` — no milliseconds, no trailing "Z".
15801
+ */
15802
+ function formatDateForExcel(date) {
15803
+ if (isNaN(date.getTime())) return "";
15804
+ return date.toISOString().replace(/\.\d{3}Z$/, "");
15805
+ }
15806
+ /**
15807
+ * Render a single `<cacheField>` element as an XML string.
15808
+ *
15809
+ * This is a pure data-in → string-out transformation with no state or lifecycle,
15810
+ * so it is a plain function rather than a class.
15811
+ */
15812
+ function renderCacheField(cf) {
15813
+ const escapedName = xmlEncode(cf.name);
15814
+ const fmtId = cf.numFmtId ?? "0";
15815
+ const extraStr = buildExtraAttrsStr(cf.extraAttrs);
15816
+ const fgXml = cf.fieldGroupXml ? `\n ${cf.fieldGroupXml}` : "";
15817
+ if (cf.sharedItems === null) {
15818
+ if (cf.isLoaded) {
15819
+ if (fgXml) return `<cacheField name="${escapedName}" numFmtId="${fmtId}"${extraStr}>${fgXml}\n </cacheField>`;
15820
+ return `<cacheField name="${escapedName}" numFmtId="${fmtId}"${extraStr} />`;
15821
+ }
15822
+ let attrStr;
15823
+ if (cf.minValue !== void 0 && cf.maxValue !== void 0) attrStr = ` containsSemiMixedTypes="0" containsString="0" containsNumber="1"${cf.containsInteger ? " containsInteger=\"1\"" : ""} minValue="${cf.minValue}" maxValue="${cf.maxValue}"`;
15824
+ else attrStr = "";
15825
+ return `<cacheField name="${escapedName}" numFmtId="${fmtId}"${extraStr}>
15826
+ <sharedItems${attrStr} />${fgXml}
15827
+ </cacheField>`;
15828
+ }
15829
+ if (cf.isLoaded && cf.sharedItems.length === 0) return `<cacheField name="${escapedName}" numFmtId="${fmtId}"${extraStr}>
15830
+ <sharedItems${buildLoadedSharedItemsAttrs(cf)} />${fgXml}
15831
+ </cacheField>`;
15832
+ if (cf.isLoaded) {
15833
+ const itemXmls = renderSharedItemElements(cf.sharedItems);
15834
+ return `<cacheField name="${escapedName}" numFmtId="${fmtId}"${extraStr}>
15835
+ <sharedItems${buildLoadedSharedItemsAttrs(cf)} count="${cf.sharedItems.length}">
15836
+ ${itemXmls}
15837
+ </sharedItems>${fgXml}
15838
+ </cacheField>`;
15839
+ }
15840
+ let hasString = false;
15841
+ let hasNumber = false;
15842
+ let hasBoolean = false;
15843
+ let hasDate = false;
15844
+ let hasNull = false;
15845
+ let hasError = false;
15846
+ let allInteger = true;
15847
+ let minValue = Infinity;
15848
+ let maxValue = -Infinity;
15849
+ for (const item of cf.sharedItems) if (item === null) hasNull = true;
15850
+ else if (item instanceof PivotErrorValue) hasError = true;
15851
+ else if (typeof item === "string") hasString = true;
15852
+ else if (typeof item === "number") if (Number.isFinite(item)) {
15853
+ hasNumber = true;
15854
+ if (item < minValue) minValue = item;
15855
+ if (item > maxValue) maxValue = item;
15856
+ if (!Number.isInteger(item)) allInteger = false;
15857
+ } else hasNull = true;
15858
+ else if (typeof item === "boolean") hasBoolean = true;
15859
+ else if (item instanceof Date) hasDate = true;
15860
+ const attrs = [];
15861
+ if (!hasString) {
15862
+ attrs.push("containsSemiMixedTypes=\"0\"");
15863
+ attrs.push("containsString=\"0\"");
15864
+ }
15865
+ if ((hasString ? 1 : 0) + (hasNumber ? 1 : 0) + (hasBoolean ? 1 : 0) + (hasDate ? 1 : 0) + (hasError ? 1 : 0) > 1) attrs.push("containsMixedTypes=\"1\"");
15866
+ if (hasNumber) {
15867
+ attrs.push("containsNumber=\"1\"");
15868
+ if (allInteger) attrs.push("containsInteger=\"1\"");
15869
+ attrs.push(`minValue="${minValue}"`);
15870
+ attrs.push(`maxValue="${maxValue}"`);
15871
+ }
15872
+ if (hasDate) attrs.push("containsDate=\"1\"");
15873
+ if (hasNull) attrs.push("containsBlank=\"1\"");
15874
+ const itemXmls = renderSharedItemElements(cf.sharedItems);
15875
+ return `<cacheField name="${escapedName}" numFmtId="${fmtId}"${extraStr}>
15876
+ <sharedItems${attrs.length > 0 ? ` ${attrs.join(" ")}` : ""} count="${cf.sharedItems.length}">
15877
+ ${itemXmls}
15878
+ </sharedItems>${fgXml}
15879
+ </cacheField>`;
15880
+ }
15881
+ /**
15882
+ * Render shared item elements as an XML string.
15883
+ */
15884
+ function renderSharedItemElements(sharedItems) {
15885
+ const itemXmls = [];
15886
+ for (const item of sharedItems) if (item === null) itemXmls.push("<m />");
15887
+ else if (item instanceof PivotErrorValue) itemXmls.push(`<e v="${xmlEncode(item.code)}" />`);
15888
+ else if (typeof item === "number") if (Number.isFinite(item)) itemXmls.push(`<n v="${item}" />`);
15889
+ else itemXmls.push("<m />");
15890
+ else if (typeof item === "boolean") itemXmls.push(`<b v="${item ? "1" : "0"}" />`);
15891
+ else if (item instanceof Date) itemXmls.push(`<d v="${formatDateForExcel(item)}" />`);
15892
+ else itemXmls.push(`<s v="${xmlEncode(item)}" />`);
15893
+ return itemXmls.join("");
15894
+ }
15895
+ /**
15896
+ * Build extra attributes string for cacheField element (roundtrip preservation).
15897
+ */
15898
+ function buildExtraAttrsStr(extraAttrs) {
15899
+ if (!extraAttrs) return "";
15900
+ return Object.entries(extraAttrs).map(([k, v]) => ` ${k}="${xmlEncode(v)}"`).join("");
15901
+ }
15902
+ /**
15903
+ * Build sharedItems attribute string from preserved loaded attributes.
15904
+ * Reconstructs the original attribute order for roundtrip fidelity.
15905
+ */
15906
+ function buildLoadedSharedItemsAttrs(cf) {
15907
+ const parts = [];
15908
+ if (cf.containsSemiMixedTypes !== void 0) parts.push(`containsSemiMixedTypes="${cf.containsSemiMixedTypes}"`);
15909
+ if (cf.containsNonDate !== void 0) parts.push(`containsNonDate="${cf.containsNonDate}"`);
15910
+ if (cf.containsString !== void 0) parts.push(`containsString="${cf.containsString}"`);
15911
+ if (cf.containsBlank !== void 0) parts.push(`containsBlank="${cf.containsBlank}"`);
15912
+ if (cf.containsMixedTypes !== void 0) parts.push(`containsMixedTypes="${cf.containsMixedTypes}"`);
15913
+ if (cf.containsNumber !== void 0) parts.push(`containsNumber="${cf.containsNumber}"`);
15914
+ if (cf.containsInteger !== void 0) parts.push(`containsInteger="${cf.containsInteger}"`);
15915
+ if (cf.minValue !== void 0) parts.push(`minValue="${cf.minValue}"`);
15916
+ if (cf.maxValue !== void 0) parts.push(`maxValue="${cf.maxValue}"`);
15917
+ if (cf.containsDate !== void 0) parts.push(`containsDate="${cf.containsDate}"`);
15918
+ return parts.length > 0 ? ` ${parts.join(" ")}` : "";
15919
+ }
15920
+
15607
15921
  //#endregion
15608
15922
  //#region src/modules/excel/xlsx/xform/pivot-table/pivot-cache-records-xform.ts
15923
+ /** Attribute keys on <pivotCacheRecords> that are individually parsed (not collected into extraRootAttrs). */
15924
+ const KNOWN_CACHE_RECORDS_ROOT_KEYS = new Set([
15925
+ "xmlns",
15926
+ "xmlns:r",
15927
+ "count"
15928
+ ]);
15609
15929
  var PivotCacheRecordsXform = class PivotCacheRecordsXform extends BaseXform {
15610
15930
  constructor() {
15611
15931
  super();
15612
- this.map = {};
15613
15932
  this.model = null;
15614
15933
  this.currentRecord = null;
15615
15934
  }
15616
- prepare(_model) {}
15617
15935
  get tag() {
15618
15936
  return "pivotCacheRecords";
15619
15937
  }
@@ -15626,7 +15944,7 @@ var ExcelTS = (function(exports) {
15626
15944
  * Supports both newly created models (with PivotTableSource) and loaded models.
15627
15945
  */
15628
15946
  render(xmlStream, model) {
15629
- if (model.isLoaded || !("source" in model)) this.renderLoaded(xmlStream, model);
15947
+ if ("isLoaded" in model && model.isLoaded || !("source" in model)) this.renderLoaded(xmlStream, model);
15630
15948
  else this.renderNew(xmlStream, model);
15631
15949
  }
15632
15950
  /**
@@ -15634,7 +15952,7 @@ var ExcelTS = (function(exports) {
15634
15952
  */
15635
15953
  renderNew(xmlStream, model) {
15636
15954
  const { source, cacheFields } = model;
15637
- const sourceBodyRows = source.getSheetValues().slice(2);
15955
+ const sourceBodyRows = source.getSheetValues().slice(2).filter(Array.isArray);
15638
15956
  xmlStream.openXml(XmlStream.StdDocAttributes);
15639
15957
  xmlStream.openNode(this.tag, {
15640
15958
  ...PivotCacheRecordsXform.PIVOT_CACHE_RECORDS_ATTRIBUTES,
@@ -15648,10 +15966,18 @@ var ExcelTS = (function(exports) {
15648
15966
  */
15649
15967
  renderLoaded(xmlStream, model) {
15650
15968
  xmlStream.openXml(XmlStream.StdDocAttributes);
15651
- xmlStream.openNode(this.tag, {
15652
- ...PivotCacheRecordsXform.PIVOT_CACHE_RECORDS_ATTRIBUTES,
15653
- count: model.count
15654
- });
15969
+ const rootAttrs = {
15970
+ xmlns: PivotCacheRecordsXform.PIVOT_CACHE_RECORDS_ATTRIBUTES.xmlns,
15971
+ "xmlns:r": PivotCacheRecordsXform.PIVOT_CACHE_RECORDS_ATTRIBUTES["xmlns:r"]
15972
+ };
15973
+ if (model.extraRootAttrs) for (const [k, v] of Object.entries(model.extraRootAttrs)) rootAttrs[k] = v;
15974
+ else {
15975
+ rootAttrs["xmlns:mc"] = PivotCacheRecordsXform.PIVOT_CACHE_RECORDS_ATTRIBUTES["xmlns:mc"];
15976
+ rootAttrs["mc:Ignorable"] = PivotCacheRecordsXform.PIVOT_CACHE_RECORDS_ATTRIBUTES["mc:Ignorable"];
15977
+ rootAttrs["xmlns:xr"] = PivotCacheRecordsXform.PIVOT_CACHE_RECORDS_ATTRIBUTES["xmlns:xr"];
15978
+ }
15979
+ rootAttrs.count = model.records.length;
15980
+ xmlStream.openNode(this.tag, rootAttrs);
15655
15981
  for (const record of model.records) {
15656
15982
  xmlStream.writeXml("\n <r>");
15657
15983
  for (const value of record) {
@@ -15668,13 +15994,18 @@ var ExcelTS = (function(exports) {
15668
15994
  renderRecordValue(value) {
15669
15995
  switch (value.type) {
15670
15996
  case "x": return `<x v="${value.value}" />`;
15671
- case "n": return `<n v="${value.value}" />`;
15672
- case "s": return `<s v="${xmlEncode(String(value.value))}" />`;
15997
+ case "n":
15998
+ if (!Number.isFinite(value.value)) return "<m />";
15999
+ return `<n v="${value.value}" />`;
16000
+ case "s": return `<s v="${xmlEncode(value.value)}" />`;
15673
16001
  case "b": return `<b v="${value.value ? "1" : "0"}" />`;
15674
16002
  case "m": return "<m />";
15675
- case "d": return `<d v="${value.value.toISOString()}" />`;
15676
- case "e": return `<e v="${value.value}" />`;
15677
- default: return "<m />";
16003
+ case "d": return `<d v="${formatDateForExcel(value.value)}" />`;
16004
+ case "e": return `<e v="${xmlEncode(value.value)}" />`;
16005
+ default: {
16006
+ const _exhaustive = value;
16007
+ throw new Error(`Unhandled record value type: ${_exhaustive.type}`);
16008
+ }
15678
16009
  }
15679
16010
  }
15680
16011
  renderTableNew(sourceBodyRows, cacheFields) {
@@ -15682,54 +16013,69 @@ var ExcelTS = (function(exports) {
15682
16013
  for (const row of sourceBodyRows) {
15683
16014
  const realRow = row.slice(1);
15684
16015
  parts.push("\n <r>");
15685
- for (let i = 0; i < realRow.length; i++) {
16016
+ const fieldCount = Math.min(realRow.length, cacheFields.length);
16017
+ for (let i = 0; i < fieldCount; i++) {
15686
16018
  parts.push("\n ");
15687
16019
  parts.push(this.renderCellNew(realRow[i], cacheFields[i].sharedItems));
15688
16020
  }
16021
+ for (let i = fieldCount; i < cacheFields.length; i++) parts.push("\n <m />");
15689
16022
  parts.push("\n </r>");
15690
16023
  }
15691
16024
  return parts.join("");
15692
16025
  }
15693
16026
  renderCellNew(value, sharedItems) {
15694
- if (value === null || value === void 0) return "<m />";
16027
+ if (value === null || value === void 0 || typeof value === "number" && !Number.isFinite(value)) {
16028
+ if (sharedItems === null) return "<m />";
16029
+ const idx = sharedItems.indexOf(null);
16030
+ if (idx >= 0) return `<x v="${idx}" />`;
16031
+ return "<m />";
16032
+ }
15695
16033
  if (sharedItems === null) {
16034
+ if (value instanceof PivotErrorValue) return `<e v="${xmlEncode(value.code)}" />`;
16035
+ if (typeof value === "boolean") return `<b v="${value ? "1" : "0"}" />`;
16036
+ if (value instanceof Date) return `<d v="${formatDateForExcel(value)}" />`;
15696
16037
  if (Number.isFinite(value)) return `<n v="${value}" />`;
15697
16038
  return `<s v="${xmlEncode(String(value))}" />`;
15698
16039
  }
15699
- const sharedItemsIndex = sharedItems.indexOf(value);
16040
+ const sharedItemsIndex = findSharedItemIndex(sharedItems, value);
15700
16041
  if (sharedItemsIndex < 0) throw new Error(`${JSON.stringify(value)} not in sharedItems ${JSON.stringify(sharedItems)}`);
15701
16042
  return `<x v="${sharedItemsIndex}" />`;
15702
16043
  }
15703
16044
  parseOpen(node) {
15704
16045
  const { name, attributes } = node;
15705
16046
  switch (name) {
15706
- case this.tag:
16047
+ case this.tag: {
15707
16048
  this.reset();
16049
+ const extraRootAttrs = {};
16050
+ for (const [k, v] of Object.entries(attributes)) if (!KNOWN_CACHE_RECORDS_ROOT_KEYS.has(k)) extraRootAttrs[k] = String(v);
15708
16051
  this.model = {
15709
16052
  records: [],
15710
- count: parseInt(attributes.count || "0", 10),
15711
- isLoaded: true
16053
+ count: parseInt(attributes.count ?? "0", 10),
16054
+ isLoaded: true,
16055
+ extraRootAttrs: Object.keys(extraRootAttrs).length > 0 ? extraRootAttrs : void 0
15712
16056
  };
15713
16057
  break;
16058
+ }
15714
16059
  case "r":
15715
16060
  this.currentRecord = [];
15716
16061
  break;
15717
16062
  case "x":
15718
16063
  if (this.currentRecord) this.currentRecord.push({
15719
16064
  type: "x",
15720
- value: parseInt(attributes.v || "0", 10)
16065
+ value: parseInt(attributes.v ?? "0", 10)
15721
16066
  });
15722
16067
  break;
15723
16068
  case "n":
15724
- if (this.currentRecord) this.currentRecord.push({
16069
+ if (this.currentRecord) if (attributes.v === void 0 || attributes.v === "") this.currentRecord.push({ type: "m" });
16070
+ else this.currentRecord.push({
15725
16071
  type: "n",
15726
- value: parseFloat(attributes.v || "0")
16072
+ value: parseFloat(attributes.v)
15727
16073
  });
15728
16074
  break;
15729
16075
  case "s":
15730
16076
  if (this.currentRecord) this.currentRecord.push({
15731
16077
  type: "s",
15732
- value: xmlDecode(attributes.v || "")
16078
+ value: attributes.v ?? ""
15733
16079
  });
15734
16080
  break;
15735
16081
  case "b":
@@ -15742,15 +16088,20 @@ var ExcelTS = (function(exports) {
15742
16088
  if (this.currentRecord) this.currentRecord.push({ type: "m" });
15743
16089
  break;
15744
16090
  case "d":
15745
- if (this.currentRecord) this.currentRecord.push({
15746
- type: "d",
15747
- value: new Date(attributes.v || "")
15748
- });
16091
+ if (this.currentRecord) if (!attributes.v) this.currentRecord.push({ type: "m" });
16092
+ else {
16093
+ const date = parseOoxmlDate(attributes.v);
16094
+ if (isNaN(date.getTime())) this.currentRecord.push({ type: "m" });
16095
+ else this.currentRecord.push({
16096
+ type: "d",
16097
+ value: date
16098
+ });
16099
+ }
15749
16100
  break;
15750
16101
  case "e":
15751
16102
  if (this.currentRecord) this.currentRecord.push({
15752
16103
  type: "e",
15753
- value: attributes.v || ""
16104
+ value: attributes.v ?? ""
15754
16105
  });
15755
16106
  break;
15756
16107
  }
@@ -15769,7 +16120,6 @@ var ExcelTS = (function(exports) {
15769
16120
  }
15770
16121
  return true;
15771
16122
  }
15772
- reconcile(_model, _options) {}
15773
16123
  static {
15774
16124
  this.PIVOT_CACHE_RECORDS_ATTRIBUTES = {
15775
16125
  xmlns: "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
@@ -15780,48 +16130,157 @@ var ExcelTS = (function(exports) {
15780
16130
  };
15781
16131
  }
15782
16132
  };
16133
+ /**
16134
+ * Find the index of `value` in `sharedItems`, using type-aware comparison.
16135
+ * - Date objects are compared by timestamp (getTime()) since === uses reference equality.
16136
+ * - PivotErrorValue objects are compared by their code string.
16137
+ * - All other types use strict equality (===) via indexOf.
16138
+ */
16139
+ function findSharedItemIndex(sharedItems, value) {
16140
+ if (value instanceof Date) {
16141
+ const ts = value.getTime();
16142
+ for (let i = 0; i < sharedItems.length; i++) {
16143
+ const item = sharedItems[i];
16144
+ if (item instanceof Date && item.getTime() === ts) return i;
16145
+ }
16146
+ return -1;
16147
+ }
16148
+ if (value instanceof PivotErrorValue) {
16149
+ for (let i = 0; i < sharedItems.length; i++) {
16150
+ const item = sharedItems[i];
16151
+ if (item instanceof PivotErrorValue && item.code === value.code) return i;
16152
+ }
16153
+ return -1;
16154
+ }
16155
+ return sharedItems.indexOf(value);
16156
+ }
15783
16157
 
15784
16158
  //#endregion
15785
- //#region src/modules/excel/xlsx/xform/pivot-table/cache-field.ts
15786
- var CacheField = class {
15787
- constructor({ name, sharedItems, minValue, maxValue }) {
15788
- this.name = name;
15789
- this.sharedItems = sharedItems;
15790
- this.minValue = minValue;
15791
- this.maxValue = maxValue;
15792
- }
15793
- render() {
15794
- const escapedName = xmlEncode(this.name);
15795
- if (this.sharedItems === null) {
15796
- if (this.minValue === void 0 || this.maxValue === void 0) return `<cacheField name="${escapedName}" numFmtId="0">
15797
- <sharedItems />
15798
- </cacheField>`;
15799
- return `<cacheField name="${escapedName}" numFmtId="0">
15800
- <sharedItems containsSemiMixedTypes="0" containsString="0" containsNumber="1" containsInteger="1" minValue="${this.minValue}" maxValue="${this.maxValue}" />
15801
- </cacheField>`;
16159
+ //#region src/modules/excel/xlsx/xform/pivot-table/raw-xml-collector.ts
16160
+ /**
16161
+ * Reusable utility for collecting raw XML fragments during SAX parsing.
16162
+ *
16163
+ * Many pivot-table xforms need to capture entire sub-trees (extLst, formats,
16164
+ * conditionalFormats, filters, fieldGroup, unknown elements, …) as raw strings
16165
+ * for roundtrip preservation. The pattern — `active` flag, `depth` counter,
16166
+ * `buffer` of string fragments, plus identical `feedOpen` / `feedClose` /
16167
+ * `feedText` logic — was previously copy-pasted across multiple files.
16168
+ *
16169
+ * Usage:
16170
+ * ```ts
16171
+ * const collector = new RawXmlCollector("extLst");
16172
+ * // In parseOpen, when you see <extLst>:
16173
+ * collector.start(); // opens with <extLst>
16174
+ * // For every child open tag while active:
16175
+ * collector.feedOpen(name, attributes);
16176
+ * // For every text node while active:
16177
+ * collector.feedText(text);
16178
+ * // For every close tag while active:
16179
+ * if (collector.feedClose(name)) { ... } // returns true when root tag closed
16180
+ * // Retrieve result:
16181
+ * collector.result; // joined XML string
16182
+ * ```
16183
+ */
16184
+ var RawXmlCollector = class {
16185
+ constructor(rootTag) {
16186
+ this.active = false;
16187
+ this.depth = 0;
16188
+ this.buffer = [];
16189
+ this.lastOpenIndex = -1;
16190
+ this.rootTag = rootTag;
16191
+ }
16192
+ /**
16193
+ * Begin collecting. Pushes the opening root tag (with optional attributes)
16194
+ * and resets depth.
16195
+ *
16196
+ * @param attributes - Attributes on the root element (may be undefined/null).
16197
+ */
16198
+ start(attributes) {
16199
+ this.active = true;
16200
+ this.depth = 0;
16201
+ const attrsStr = serializeAttributes(attributes);
16202
+ this.buffer = [`<${this.rootTag}${attrsStr ? " " + attrsStr : ""}>`];
16203
+ }
16204
+ /**
16205
+ * Begin collecting with a dynamically determined root tag.
16206
+ * Used for catch-all unknown element collectors where the tag name
16207
+ * is not known at construction time.
16208
+ */
16209
+ startAs(rootTag, attributes) {
16210
+ this.rootTag = rootTag;
16211
+ this.start(attributes);
16212
+ }
16213
+ /**
16214
+ * Reset the collector to its initial idle state.
16215
+ */
16216
+ reset() {
16217
+ this.active = false;
16218
+ this.depth = 0;
16219
+ this.buffer.length = 0;
16220
+ this.lastOpenIndex = -1;
16221
+ }
16222
+ /**
16223
+ * Feed an open-tag event. Must only be called while `active` is true.
16224
+ */
16225
+ feedOpen(name, attributes) {
16226
+ const attrsStr = serializeAttributes(attributes);
16227
+ this.buffer.push(`<${name}${attrsStr ? " " + attrsStr : ""}>`);
16228
+ this.depth++;
16229
+ this.lastOpenIndex = this.buffer.length - 1;
16230
+ }
16231
+ /**
16232
+ * Feed a text-node event. Must only be called while `active` is true.
16233
+ */
16234
+ feedText(text) {
16235
+ this.buffer.push(xmlEncode(text));
16236
+ this.lastOpenIndex = -1;
16237
+ }
16238
+ /**
16239
+ * Feed a close-tag event.
16240
+ *
16241
+ * @returns `true` when the **root** close tag has been received (collector
16242
+ * deactivates itself and the result is ready). `false` for any
16243
+ * nested close tag.
16244
+ */
16245
+ feedClose(name) {
16246
+ if (name === this.rootTag && this.depth === 0) {
16247
+ this.buffer.push(`</${name}>`);
16248
+ this.active = false;
16249
+ this.lastOpenIndex = -1;
16250
+ return true;
15802
16251
  }
15803
- const allNumeric = this.sharedItems.length > 0 && this.sharedItems.every((item) => typeof item === "number" && Number.isFinite(item));
15804
- const allInteger = allNumeric && this.sharedItems.every((item) => Number.isInteger(item));
15805
- if (allNumeric) {
15806
- const minValue = Math.min(...this.sharedItems);
15807
- const maxValue = Math.max(...this.sharedItems);
15808
- return `<cacheField name="${escapedName}" numFmtId="0">
15809
- <sharedItems containsSemiMixedTypes="0" containsString="0" containsNumber="1"${allInteger ? " containsInteger=\"1\"" : ""} minValue="${minValue}" maxValue="${maxValue}" count="${this.sharedItems.length}">
15810
- ${this.sharedItems.map((item) => `<n v="${item}" />`).join("")}
15811
- </sharedItems>
15812
- </cacheField>`;
16252
+ if (this.depth > 0) this.depth--;
16253
+ if (this.lastOpenIndex >= 0 && this.lastOpenIndex === this.buffer.length - 1) {
16254
+ const openTag = this.buffer[this.lastOpenIndex];
16255
+ this.buffer[this.lastOpenIndex] = openTag.slice(0, -1) + " />";
16256
+ this.lastOpenIndex = -1;
16257
+ return false;
15813
16258
  }
15814
- return `<cacheField name="${escapedName}" numFmtId="0">
15815
- <sharedItems count="${this.sharedItems.length}">
15816
- ${this.sharedItems.map((item) => `<s v="${xmlEncode(String(item))}" />`).join("")}
15817
- </sharedItems>
15818
- </cacheField>`;
16259
+ this.lastOpenIndex = -1;
16260
+ this.buffer.push(`</${name}>`);
16261
+ return false;
16262
+ }
16263
+ /** The collected XML string. Only meaningful after `feedClose` returns true. */
16264
+ get result() {
16265
+ return this.buffer.join("");
15819
16266
  }
15820
16267
  };
16268
+ /**
16269
+ * Serialize an attributes object to an XML attribute string.
16270
+ * `null`, `undefined`, and empty objects produce an empty string.
16271
+ */
16272
+ function serializeAttributes(attributes) {
16273
+ if (!attributes) return "";
16274
+ const entries = Object.entries(attributes);
16275
+ if (entries.length === 0) return "";
16276
+ return entries.filter(([, v]) => v != null).map(([k, v]) => `${k}="${xmlEncode(String(v))}"`).join(" ");
16277
+ }
15821
16278
 
15822
16279
  //#endregion
15823
16280
  //#region src/modules/excel/xlsx/xform/pivot-table/cache-field-xform.ts
15824
- /**
16281
+ /** Attribute keys on <cacheField> that are individually parsed (not collected into extraAttrs). */
16282
+ const KNOWN_CACHE_FIELD_KEYS = new Set(["name", "numFmtId"]);
16283
+ /**
15825
16284
  * Xform for parsing individual <cacheField> elements within a pivot cache definition.
15826
16285
  *
15827
16286
  * Example XML:
@@ -15843,8 +16302,9 @@ var ExcelTS = (function(exports) {
15843
16302
  var CacheFieldXform = class extends BaseXform {
15844
16303
  constructor() {
15845
16304
  super();
15846
- this.model = null;
15847
16305
  this.inSharedItems = false;
16306
+ this.fieldGroupCollector = new RawXmlCollector("fieldGroup");
16307
+ this.model = null;
15848
16308
  }
15849
16309
  get tag() {
15850
16310
  return "cacheField";
@@ -15852,65 +16312,74 @@ var ExcelTS = (function(exports) {
15852
16312
  reset() {
15853
16313
  this.model = null;
15854
16314
  this.inSharedItems = false;
16315
+ this.fieldGroupCollector.reset();
15855
16316
  }
15856
16317
  parseOpen(node) {
15857
16318
  const { name, attributes } = node;
16319
+ if (this.fieldGroupCollector.active) {
16320
+ this.fieldGroupCollector.feedOpen(name, attributes);
16321
+ return true;
16322
+ }
15858
16323
  switch (name) {
15859
- case "cacheField":
16324
+ case "cacheField": {
16325
+ const extraAttrs = {};
16326
+ for (const [k, v] of Object.entries(attributes)) if (!KNOWN_CACHE_FIELD_KEYS.has(k)) extraAttrs[k] = String(v);
15860
16327
  this.model = {
15861
- name: xmlDecode(attributes.name || ""),
15862
- sharedItems: null
16328
+ name: attributes.name ?? "",
16329
+ sharedItems: null,
16330
+ numFmtId: attributes.numFmtId,
16331
+ isLoaded: true,
16332
+ extraAttrs: Object.keys(extraAttrs).length > 0 ? extraAttrs : void 0
15863
16333
  };
15864
16334
  break;
16335
+ }
16336
+ case "fieldGroup":
16337
+ if (this.model) this.fieldGroupCollector.start(attributes);
16338
+ break;
15865
16339
  case "sharedItems":
15866
16340
  this.inSharedItems = true;
15867
16341
  if (this.model) {
15868
- this.model.containsNumber = attributes.containsNumber === "1";
15869
- this.model.containsInteger = attributes.containsInteger === "1";
15870
- if (attributes.minValue !== void 0) this.model.minValue = parseFloat(attributes.minValue);
15871
- if (attributes.maxValue !== void 0) this.model.maxValue = parseFloat(attributes.maxValue);
15872
- if (parseInt(attributes.count || "0", 10) > 0) this.model.sharedItems = [];
15873
- else this.model.sharedItems = null;
16342
+ if (attributes.containsNumber !== void 0) this.model.containsNumber = attributes.containsNumber;
16343
+ if (attributes.containsInteger !== void 0) this.model.containsInteger = attributes.containsInteger;
16344
+ if (attributes.minValue !== void 0) {
16345
+ const parsed = parseFloat(attributes.minValue);
16346
+ if (Number.isFinite(parsed)) this.model.minValue = parsed;
16347
+ }
16348
+ if (attributes.maxValue !== void 0) {
16349
+ const parsed = parseFloat(attributes.maxValue);
16350
+ if (Number.isFinite(parsed)) this.model.maxValue = parsed;
16351
+ }
16352
+ if (attributes.containsSemiMixedTypes !== void 0) this.model.containsSemiMixedTypes = attributes.containsSemiMixedTypes;
16353
+ if (attributes.containsNonDate !== void 0) this.model.containsNonDate = attributes.containsNonDate;
16354
+ if (attributes.containsString !== void 0) this.model.containsString = attributes.containsString;
16355
+ if (attributes.containsBlank !== void 0) this.model.containsBlank = attributes.containsBlank;
16356
+ if (attributes.containsDate !== void 0) this.model.containsDate = attributes.containsDate;
16357
+ if (attributes.containsMixedTypes !== void 0) this.model.containsMixedTypes = attributes.containsMixedTypes;
16358
+ this.model.sharedItems = [];
15874
16359
  }
15875
16360
  break;
15876
16361
  case "s":
15877
- if (this.inSharedItems && this.model?.sharedItems !== null) {
15878
- const value = xmlDecode(attributes.v || "");
15879
- this.model.sharedItems.push(value);
15880
- }
15881
- break;
15882
16362
  case "n":
15883
- if (this.inSharedItems && this.model?.sharedItems !== null) {
15884
- const value = parseFloat(attributes.v || "0");
15885
- this.model.sharedItems.push(value);
15886
- }
15887
- break;
15888
16363
  case "b":
15889
- if (this.inSharedItems && this.model?.sharedItems !== null) {
15890
- const value = attributes.v === "1";
15891
- this.model.sharedItems.push(value);
15892
- }
15893
- break;
15894
16364
  case "e":
15895
- if (this.inSharedItems && this.model?.sharedItems !== null) {
15896
- const value = `#${attributes.v || "ERROR!"}`;
15897
- this.model.sharedItems.push(value);
15898
- }
15899
- break;
15900
16365
  case "m":
15901
- if (this.inSharedItems && this.model?.sharedItems !== null) this.model.sharedItems.push(null);
15902
- break;
15903
16366
  case "d":
15904
- if (this.inSharedItems && this.model?.sharedItems !== null) {
15905
- const value = new Date(attributes.v || "");
15906
- this.model.sharedItems.push(value);
15907
- }
16367
+ if (this.inSharedItems && this.model && this.model.sharedItems !== null) this.model.sharedItems.push(parseSharedItemValue(name, attributes));
15908
16368
  break;
15909
16369
  }
15910
16370
  return true;
15911
16371
  }
15912
- parseText(_text) {}
16372
+ parseText(text) {
16373
+ if (this.fieldGroupCollector.active) this.fieldGroupCollector.feedText(text);
16374
+ }
15913
16375
  parseClose(name) {
16376
+ if (this.fieldGroupCollector.active) {
16377
+ if (this.fieldGroupCollector.feedClose(name)) {
16378
+ if (this.model) this.model.fieldGroupXml = this.fieldGroupCollector.result;
16379
+ this.fieldGroupCollector.reset();
16380
+ }
16381
+ return true;
16382
+ }
15914
16383
  switch (name) {
15915
16384
  case "cacheField": return false;
15916
16385
  case "sharedItems":
@@ -15920,19 +16389,64 @@ var ExcelTS = (function(exports) {
15920
16389
  return true;
15921
16390
  }
15922
16391
  };
16392
+ /**
16393
+ * Convert a SAX-parsed shared item element into its typed value.
16394
+ *
16395
+ * Tag mapping:
16396
+ * - `s` → string
16397
+ * - `n` → number
16398
+ * - `b` → boolean
16399
+ * - `e` → PivotErrorValue
16400
+ * - `m` → null (missing)
16401
+ * - `d` → Date (UTC)
16402
+ */
16403
+ function parseSharedItemValue(tag, attributes) {
16404
+ switch (tag) {
16405
+ case "s": return attributes.v ?? "";
16406
+ case "n":
16407
+ if (attributes.v === void 0 || attributes.v === "") return null;
16408
+ return parseFloat(attributes.v);
16409
+ case "b": return attributes.v === "1";
16410
+ case "e": return new PivotErrorValue(attributes.v ?? "");
16411
+ case "m": return null;
16412
+ case "d": {
16413
+ if (!attributes.v) return null;
16414
+ const date = parseOoxmlDate(attributes.v);
16415
+ return isNaN(date.getTime()) ? null : date;
16416
+ }
16417
+ default: return null;
16418
+ }
16419
+ }
15923
16420
 
15924
16421
  //#endregion
15925
16422
  //#region src/modules/excel/xlsx/xform/pivot-table/pivot-cache-definition-xform.ts
16423
+ /** Attribute keys on <pivotCacheDefinition> that are individually parsed (not collected into extraRootAttrs). */
16424
+ const KNOWN_CACHE_DEF_ROOT_KEYS = new Set([
16425
+ "xmlns",
16426
+ "xmlns:r",
16427
+ "r:id",
16428
+ "refreshOnLoad",
16429
+ "createdVersion",
16430
+ "refreshedVersion",
16431
+ "minRefreshableVersion",
16432
+ "recordCount",
16433
+ "backgroundQuery",
16434
+ "supportSubquery",
16435
+ "supportAdvancedDrill"
16436
+ ]);
15926
16437
  var PivotCacheDefinitionXform = class PivotCacheDefinitionXform extends BaseXform {
15927
16438
  constructor() {
15928
16439
  super();
15929
- this.map = {};
15930
- this.model = null;
15931
16440
  this.currentCacheField = null;
15932
16441
  this.inCacheFields = false;
15933
16442
  this.inCacheSource = false;
16443
+ this.extLstCollector = new RawXmlCollector("extLst");
16444
+ this.unknownCollector = new RawXmlCollector("");
16445
+ this.unknownElementsXmlParts = [];
16446
+ this.cacheSourceChildCollector = new RawXmlCollector("");
16447
+ this.cacheSourceXmlParts = [];
16448
+ this.model = null;
15934
16449
  }
15935
- prepare(_model) {}
15936
16450
  get tag() {
15937
16451
  return "pivotCacheDefinition";
15938
16452
  }
@@ -15941,13 +16455,18 @@ var ExcelTS = (function(exports) {
15941
16455
  this.currentCacheField = null;
15942
16456
  this.inCacheFields = false;
15943
16457
  this.inCacheSource = false;
16458
+ this.extLstCollector.reset();
16459
+ this.unknownCollector.reset();
16460
+ this.unknownElementsXmlParts = [];
16461
+ this.cacheSourceChildCollector.reset();
16462
+ this.cacheSourceXmlParts = [];
15944
16463
  }
15945
16464
  /**
15946
16465
  * Render pivot cache definition XML.
15947
16466
  * Supports both newly created models (with PivotTableSource) and loaded models.
15948
16467
  */
15949
16468
  render(xmlStream, model) {
15950
- if (model.isLoaded || !("source" in model)) this.renderLoaded(xmlStream, model);
16469
+ if ("isLoaded" in model && model.isLoaded || !("source" in model)) this.renderLoaded(xmlStream, model);
15951
16470
  else this.renderNew(xmlStream, model);
15952
16471
  }
15953
16472
  /**
@@ -15955,7 +16474,7 @@ var ExcelTS = (function(exports) {
15955
16474
  */
15956
16475
  renderNew(xmlStream, model) {
15957
16476
  const { source, cacheFields } = model;
15958
- const recordCount = source.getSheetValues().slice(2).length;
16477
+ const recordCount = source.getSheetValues().slice(2).filter(Array.isArray).length;
15959
16478
  xmlStream.openXml(XmlStream.StdDocAttributes);
15960
16479
  xmlStream.openNode(this.tag, {
15961
16480
  ...PivotCacheDefinitionXform.PIVOT_CACHE_DEFINITION_ATTRIBUTES,
@@ -15967,13 +16486,14 @@ var ExcelTS = (function(exports) {
15967
16486
  recordCount
15968
16487
  });
15969
16488
  xmlStream.openNode("cacheSource", { type: "worksheet" });
15970
- xmlStream.leafNode("worksheetSource", {
16489
+ const worksheetSourceAttrs = source.tableName ? { name: source.tableName } : {
15971
16490
  ref: source.dimensions.shortRange,
15972
16491
  sheet: source.name
15973
- });
16492
+ };
16493
+ xmlStream.leafNode("worksheetSource", worksheetSourceAttrs);
15974
16494
  xmlStream.closeNode();
15975
16495
  xmlStream.openNode("cacheFields", { count: cacheFields.length });
15976
- xmlStream.writeXml(cacheFields.map((cacheField) => new CacheField(cacheField).render()).join("\n "));
16496
+ xmlStream.writeXml(PivotCacheDefinitionXform.renderCacheFieldsXml(cacheFields));
15977
16497
  xmlStream.closeNode();
15978
16498
  xmlStream.closeNode();
15979
16499
  }
@@ -15983,36 +16503,61 @@ var ExcelTS = (function(exports) {
15983
16503
  renderLoaded(xmlStream, model) {
15984
16504
  const { cacheFields, sourceRef, sourceSheet, sourceTableName, recordCount } = model;
15985
16505
  xmlStream.openXml(XmlStream.StdDocAttributes);
15986
- xmlStream.openNode(this.tag, {
16506
+ const rootAttrs = {
15987
16507
  ...PivotCacheDefinitionXform.PIVOT_CACHE_DEFINITION_ATTRIBUTES,
15988
- "r:id": model.rId || "rId1",
15989
- refreshOnLoad: model.refreshOnLoad || "1",
15990
- createdVersion: model.createdVersion || "8",
15991
- refreshedVersion: model.refreshedVersion || "8",
15992
- minRefreshableVersion: model.minRefreshableVersion || "3",
15993
- recordCount: recordCount || cacheFields.length + 1
15994
- });
15995
- xmlStream.openNode("cacheSource", { type: "worksheet" });
15996
- const worksheetSourceAttrs = sourceTableName ? { name: sourceTableName } : {
15997
- ref: sourceRef,
15998
- sheet: sourceSheet
16508
+ "r:id": model.rId ?? "rId1"
15999
16509
  };
16000
- xmlStream.leafNode("worksheetSource", worksheetSourceAttrs);
16510
+ if (model.refreshOnLoad) rootAttrs.refreshOnLoad = model.refreshOnLoad;
16511
+ rootAttrs.createdVersion = model.createdVersion ?? "8";
16512
+ rootAttrs.refreshedVersion = model.refreshedVersion ?? "8";
16513
+ rootAttrs.minRefreshableVersion = model.minRefreshableVersion ?? "3";
16514
+ if (recordCount !== void 0) rootAttrs.recordCount = recordCount;
16515
+ if (model.backgroundQuery) rootAttrs.backgroundQuery = model.backgroundQuery;
16516
+ if (model.supportSubquery) rootAttrs.supportSubquery = model.supportSubquery;
16517
+ if (model.supportAdvancedDrill) rootAttrs.supportAdvancedDrill = model.supportAdvancedDrill;
16518
+ if (model.extraRootAttrs) for (const [k, v] of Object.entries(model.extraRootAttrs)) rootAttrs[k] = v;
16519
+ xmlStream.openNode(this.tag, rootAttrs);
16520
+ xmlStream.openNode("cacheSource", { type: model.cacheSourceType ?? "worksheet" });
16521
+ if (!model.cacheSourceType || model.cacheSourceType === "worksheet") {
16522
+ const worksheetSourceAttrs = sourceTableName ? { name: sourceTableName } : {
16523
+ ref: sourceRef,
16524
+ sheet: sourceSheet
16525
+ };
16526
+ if (model.worksheetSourceRId) worksheetSourceAttrs["r:id"] = model.worksheetSourceRId;
16527
+ if (Object.values(worksheetSourceAttrs).some((v) => v !== void 0)) xmlStream.leafNode("worksheetSource", worksheetSourceAttrs);
16528
+ }
16529
+ if (model.cacheSourceXml) xmlStream.writeXml(model.cacheSourceXml);
16001
16530
  xmlStream.closeNode();
16002
16531
  xmlStream.openNode("cacheFields", { count: cacheFields.length });
16003
- xmlStream.writeXml(cacheFields.map((cacheField) => new CacheField(cacheField).render()).join("\n "));
16532
+ xmlStream.writeXml(PivotCacheDefinitionXform.renderCacheFieldsXml(cacheFields));
16004
16533
  xmlStream.closeNode();
16534
+ if (model.unknownElementsXml) xmlStream.writeXml(model.unknownElementsXml);
16535
+ if (model.extLstXml) xmlStream.writeXml(model.extLstXml);
16005
16536
  xmlStream.closeNode();
16006
16537
  }
16007
16538
  parseOpen(node) {
16008
16539
  const { name, attributes } = node;
16540
+ if (this.extLstCollector.active) {
16541
+ this.extLstCollector.feedOpen(name, attributes);
16542
+ return true;
16543
+ }
16544
+ if (this.unknownCollector.active) {
16545
+ this.unknownCollector.feedOpen(name, attributes);
16546
+ return true;
16547
+ }
16548
+ if (this.cacheSourceChildCollector.active) {
16549
+ this.cacheSourceChildCollector.feedOpen(name, attributes);
16550
+ return true;
16551
+ }
16009
16552
  if (this.currentCacheField) {
16010
16553
  this.currentCacheField.parseOpen(node);
16011
16554
  return true;
16012
16555
  }
16013
16556
  switch (name) {
16014
- case this.tag:
16557
+ case this.tag: {
16015
16558
  this.reset();
16559
+ const extraRootAttrs = {};
16560
+ for (const [k, v] of Object.entries(attributes)) if (!KNOWN_CACHE_DEF_ROOT_KEYS.has(k)) extraRootAttrs[k] = String(v);
16016
16561
  this.model = {
16017
16562
  cacheFields: [],
16018
16563
  rId: attributes["r:id"],
@@ -16021,17 +16566,24 @@ var ExcelTS = (function(exports) {
16021
16566
  refreshedVersion: attributes.refreshedVersion,
16022
16567
  minRefreshableVersion: attributes.minRefreshableVersion,
16023
16568
  recordCount: attributes.recordCount ? parseInt(attributes.recordCount, 10) : void 0,
16569
+ backgroundQuery: attributes.backgroundQuery,
16570
+ supportSubquery: attributes.supportSubquery,
16571
+ supportAdvancedDrill: attributes.supportAdvancedDrill,
16572
+ extraRootAttrs: Object.keys(extraRootAttrs).length > 0 ? extraRootAttrs : void 0,
16024
16573
  isLoaded: true
16025
16574
  };
16026
16575
  break;
16576
+ }
16027
16577
  case "cacheSource":
16028
16578
  this.inCacheSource = true;
16579
+ if (this.model) this.model.cacheSourceType = attributes.type;
16029
16580
  break;
16030
16581
  case "worksheetSource":
16031
16582
  if (this.inCacheSource && this.model) {
16032
16583
  this.model.sourceRef = attributes.ref;
16033
16584
  this.model.sourceSheet = attributes.sheet;
16034
16585
  this.model.sourceTableName = attributes.name;
16586
+ if (attributes["r:id"]) this.model.worksheetSourceRId = attributes["r:id"];
16035
16587
  }
16036
16588
  break;
16037
16589
  case "cacheFields":
@@ -16043,13 +16595,56 @@ var ExcelTS = (function(exports) {
16043
16595
  this.currentCacheField.parseOpen(node);
16044
16596
  }
16045
16597
  break;
16598
+ case "extLst":
16599
+ if (this.model) this.extLstCollector.start(attributes);
16600
+ break;
16601
+ default:
16602
+ if (this.inCacheSource && this.model) {
16603
+ this.cacheSourceChildCollector.startAs(name, attributes);
16604
+ break;
16605
+ }
16606
+ if (this.model) this.unknownCollector.startAs(name, attributes);
16607
+ break;
16046
16608
  }
16047
16609
  return true;
16048
16610
  }
16049
16611
  parseText(text) {
16612
+ if (this.extLstCollector.active) {
16613
+ this.extLstCollector.feedText(text);
16614
+ return;
16615
+ }
16616
+ if (this.unknownCollector.active) {
16617
+ this.unknownCollector.feedText(text);
16618
+ return;
16619
+ }
16620
+ if (this.cacheSourceChildCollector.active) {
16621
+ this.cacheSourceChildCollector.feedText(text);
16622
+ return;
16623
+ }
16050
16624
  if (this.currentCacheField) this.currentCacheField.parseText(text);
16051
16625
  }
16052
16626
  parseClose(name) {
16627
+ if (this.extLstCollector.active) {
16628
+ if (this.extLstCollector.feedClose(name)) {
16629
+ if (this.model) this.model.extLstXml = this.extLstCollector.result;
16630
+ this.extLstCollector.reset();
16631
+ }
16632
+ return true;
16633
+ }
16634
+ if (this.unknownCollector.active) {
16635
+ if (this.unknownCollector.feedClose(name)) {
16636
+ this.unknownElementsXmlParts.push(this.unknownCollector.result);
16637
+ this.unknownCollector.reset();
16638
+ }
16639
+ return true;
16640
+ }
16641
+ if (this.cacheSourceChildCollector.active) {
16642
+ if (this.cacheSourceChildCollector.feedClose(name)) {
16643
+ this.cacheSourceXmlParts.push(this.cacheSourceChildCollector.result);
16644
+ this.cacheSourceChildCollector.reset();
16645
+ }
16646
+ return true;
16647
+ }
16053
16648
  if (this.currentCacheField) {
16054
16649
  if (!this.currentCacheField.parseClose(name)) {
16055
16650
  if (this.model && this.currentCacheField.model) this.model.cacheFields.push(this.currentCacheField.model);
@@ -16058,9 +16653,12 @@ var ExcelTS = (function(exports) {
16058
16653
  return true;
16059
16654
  }
16060
16655
  switch (name) {
16061
- case this.tag: return false;
16656
+ case this.tag:
16657
+ if (this.model && this.unknownElementsXmlParts.length > 0) this.model.unknownElementsXml = this.unknownElementsXmlParts.join("");
16658
+ return false;
16062
16659
  case "cacheSource":
16063
16660
  this.inCacheSource = false;
16661
+ if (this.model && this.cacheSourceXmlParts.length > 0) this.model.cacheSourceXml = this.cacheSourceXmlParts.join("");
16064
16662
  break;
16065
16663
  case "cacheFields":
16066
16664
  this.inCacheFields = false;
@@ -16068,7 +16666,9 @@ var ExcelTS = (function(exports) {
16068
16666
  }
16069
16667
  return true;
16070
16668
  }
16071
- reconcile(_model, _options) {}
16669
+ static renderCacheFieldsXml(cacheFields) {
16670
+ return "\n " + cacheFields.map((cf) => renderCacheField(cf)).join("\n ");
16671
+ }
16072
16672
  static {
16073
16673
  this.PIVOT_CACHE_DEFINITION_ATTRIBUTES = {
16074
16674
  xmlns: "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
@@ -16079,71 +16679,117 @@ var ExcelTS = (function(exports) {
16079
16679
 
16080
16680
  //#endregion
16081
16681
  //#region src/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.ts
16682
+ /** OOXML sentinel field index meaning "data values" pseudo-field (used in pivotArea references) */
16683
+ const FIELD_INDEX_DATA_VALUES = 4294967294;
16684
+ /**
16685
+ * Signed sentinel for the "Values" pseudo-field in colFields/rowFields.
16686
+ * OOXML represents this as x="-2" (signed int32 of 0xFFFFFFFE).
16687
+ */
16688
+ const VALUES_FIELD_INDEX = -2;
16689
+ /** Default pivot table style name */
16690
+ const DEFAULT_PIVOT_STYLE = "PivotStyleLight16";
16691
+ /** Valid OOXML axis values for pivot fields */
16692
+ const VALID_PIVOT_AXES = new Set([
16693
+ "axisRow",
16694
+ "axisCol",
16695
+ "axisPage",
16696
+ "axisValues"
16697
+ ]);
16698
+ /** PivotFieldItem attribute keys — used to build the attrs object for rendering */
16699
+ const PIVOT_FIELD_ITEM_KEYS = [
16700
+ "x",
16701
+ "t",
16702
+ "h",
16703
+ "sd",
16704
+ "f",
16705
+ "m",
16706
+ "c",
16707
+ "d"
16708
+ ];
16709
+ /** Factory for default ParserState values */
16710
+ function createDefaultParserState() {
16711
+ return {
16712
+ currentSection: null,
16713
+ inPivotArea: false,
16714
+ inAutoSortScope: false
16715
+ };
16716
+ }
16717
+ /** Known pivotField attributes that we parse individually (hoisted to module scope) */
16718
+ const KNOWN_PIVOT_FIELD_KEYS = new Set([
16719
+ "axis",
16720
+ "dataField",
16721
+ "compact",
16722
+ "outline",
16723
+ "showAll",
16724
+ "defaultSubtotal",
16725
+ "numFmtId",
16726
+ "sortType",
16727
+ "subtotalTop",
16728
+ "insertBlankRow",
16729
+ "multipleItemSelectionAllowed"
16730
+ ]);
16082
16731
  var PivotTableXform = class PivotTableXform extends BaseXform {
16083
16732
  constructor() {
16084
16733
  super();
16085
- this.state = {
16086
- inPivotFields: false,
16087
- inRowFields: false,
16088
- inColFields: false,
16089
- inDataFields: false,
16090
- inRowItems: false,
16091
- inColItems: false,
16092
- inLocation: false,
16093
- inItems: false,
16094
- inPivotTableStyleInfo: false,
16095
- inChartFormats: false,
16096
- inPivotArea: false
16097
- };
16734
+ this.state = createDefaultParserState();
16098
16735
  this.currentPivotField = null;
16099
16736
  this.currentRowItem = null;
16100
16737
  this.currentColItem = null;
16101
16738
  this.currentChartFormat = null;
16102
16739
  this.pivotAreaXmlBuffer = [];
16103
- this.pivotAreaDepth = 0;
16104
- this.map = {};
16740
+ this.autoSortScopeXmlBuffer = [];
16741
+ this.extLstCollector = new RawXmlCollector("extLst");
16742
+ this.formatsCollector = new RawXmlCollector("formats");
16743
+ this.conditionalFormatsCollector = new RawXmlCollector("conditionalFormats");
16744
+ this.filtersCollector = new RawXmlCollector("filters");
16745
+ this.unknownCollector = new RawXmlCollector("");
16746
+ this.unknownElementsXmlParts = [];
16105
16747
  this.model = null;
16106
16748
  }
16107
- prepare(_model) {}
16108
16749
  get tag() {
16109
16750
  return "pivotTableDefinition";
16110
16751
  }
16111
16752
  reset() {
16112
16753
  this.model = null;
16113
- Object.keys(this.state).forEach((key) => {
16114
- this.state[key] = false;
16115
- });
16754
+ this.state = createDefaultParserState();
16116
16755
  this.currentPivotField = null;
16117
16756
  this.currentRowItem = null;
16118
16757
  this.currentColItem = null;
16119
16758
  this.currentChartFormat = null;
16120
16759
  this.pivotAreaXmlBuffer = [];
16121
- this.pivotAreaDepth = 0;
16760
+ this.autoSortScopeXmlBuffer = [];
16761
+ this.extLstCollector.reset();
16762
+ this.formatsCollector.reset();
16763
+ this.conditionalFormatsCollector.reset();
16764
+ this.filtersCollector.reset();
16765
+ this.unknownCollector.reset();
16766
+ this.unknownElementsXmlParts = [];
16122
16767
  }
16123
16768
  /**
16124
16769
  * Render pivot table XML.
16125
16770
  * Supports both newly created models and loaded models.
16126
16771
  */
16127
16772
  render(xmlStream, model) {
16128
- if (model.isLoaded) this.renderLoaded(xmlStream, model);
16773
+ if ("isLoaded" in model && model.isLoaded) this.renderLoaded(xmlStream, model);
16129
16774
  else this.renderNew(xmlStream, model);
16130
16775
  }
16131
16776
  /**
16132
16777
  * Render newly created pivot table
16133
16778
  */
16134
16779
  renderNew(xmlStream, model) {
16135
- const { rows, columns, values, cacheFields, cacheId, applyWidthHeightFormats } = model;
16136
- const rowItems = buildRowItems(rows, cacheFields);
16137
- const colItems = buildColItems(columns, cacheFields, values.length);
16138
- const rowFieldItemCount = rows.length > 0 ? cacheFields[rows[0]]?.sharedItems?.length || 0 : 0;
16139
- const colFieldItemCount = columns.length > 0 ? cacheFields[columns[0]]?.sharedItems?.length || 0 : 0;
16140
- const endRow = 4 + rowFieldItemCount + 1;
16141
- const endCol = 1 + colFieldItemCount + 1;
16142
- const locationRef = `A3:${String.fromCharCode(64 + endCol)}${endRow}`;
16780
+ const { rows, columns, values, pages = [], cacheFields, cacheId, tableNumber, applyWidthHeightFormats } = model;
16781
+ const isMultiValueNoCol = columns.length === 0 && values.length > 1;
16782
+ const pageCount = pages.length;
16783
+ const pageOffset = pageCount > 0 ? pageCount + 1 : 0;
16784
+ const firstDataCol = rows.length;
16785
+ const startRow = 3 + pageOffset;
16786
+ const endRow = startRow + 1;
16787
+ const endCol = firstDataCol + (isMultiValueNoCol ? values.length : 1);
16788
+ const locationRef = `A${startRow}:${colCache.n2l(endCol)}${endRow}`;
16143
16789
  xmlStream.openXml(XmlStream.StdDocAttributes);
16144
16790
  xmlStream.openNode(this.tag, {
16145
16791
  ...PivotTableXform.PIVOT_TABLE_ATTRIBUTES,
16146
- name: "PivotTable2",
16792
+ name: `PivotTable${tableNumber}`,
16147
16793
  cacheId,
16148
16794
  applyNumberFormats: "0",
16149
16795
  applyBorderFormats: "0",
@@ -16162,93 +16808,91 @@ var ExcelTS = (function(exports) {
16162
16808
  compactData: "0",
16163
16809
  multipleFieldFilters: "0"
16164
16810
  });
16165
- xmlStream.writeXml(`
16166
- <location ref="${locationRef}" firstHeaderRow="1" firstDataRow="2" firstDataCol="1" />
16167
- <pivotFields count="${cacheFields.length}">
16168
- ${renderPivotFields(model)}
16169
- </pivotFields>
16170
- <rowFields count="${rows.length}">
16171
- ${rows.map((rowIndex) => `<field x="${rowIndex}" />`).join("\n ")}
16172
- </rowFields>
16173
- <rowItems count="${rowItems.count}">
16174
- ${rowItems.xml}
16175
- </rowItems>
16176
- <colFields count="${columns.length === 0 ? 1 : columns.length}">
16177
- ${columns.length === 0 ? "<field x=\"-2\" />" : columns.map((columnIndex) => `<field x="${columnIndex}" />`).join("\n ")}
16178
- </colFields>
16179
- <colItems count="${colItems.count}">
16180
- ${colItems.xml}
16181
- </colItems>
16182
- <dataFields count="${values.length}">
16183
- ${buildDataFields(cacheFields, values, model.metric)}
16184
- </dataFields>
16185
- <pivotTableStyleInfo
16186
- name="PivotStyleLight16"
16187
- showRowHeaders="1"
16188
- showColHeaders="1"
16189
- showRowStripes="0"
16190
- showColStripes="0"
16191
- showLastColumn="1"
16192
- />
16193
- <extLst>
16194
- <ext
16195
- uri="{962EF5D1-5CA2-4c93-8EF4-DBF5C05439D2}"
16196
- xmlns:x14="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"
16197
- >
16198
- <x14:pivotTableDefinition
16199
- hideValuesRow="1"
16200
- xmlns:xm="http://schemas.microsoft.com/office/excel/2006/main"
16201
- />
16202
- </ext>
16203
- <ext
16204
- uri="{747A6164-185A-40DC-8AA5-F01512510D54}"
16205
- xmlns:xpdl="http://schemas.microsoft.com/office/spreadsheetml/2016/pivotdefaultlayout"
16206
- >
16207
- <xpdl:pivotTableDefinition16
16208
- EnabledSubtotalsDefault="0"
16209
- SubtotalsOnTopDefault="0"
16210
- />
16211
- </ext>
16212
- </extLst>
16213
- `);
16811
+ const locAttrs = {
16812
+ ref: locationRef,
16813
+ firstHeaderRow: 1,
16814
+ firstDataRow: 1,
16815
+ firstDataCol
16816
+ };
16817
+ if (pageCount > 0) {
16818
+ locAttrs.rowPageCount = pageCount;
16819
+ locAttrs.colPageCount = 1;
16820
+ }
16821
+ xmlStream.leafNode("location", locAttrs);
16822
+ renderPivotFields(xmlStream, model);
16823
+ xmlStream.openNode("rowFields", { count: rows.length });
16824
+ for (const rowIndex of rows) xmlStream.leafNode("field", { x: rowIndex });
16825
+ xmlStream.closeNode();
16826
+ xmlStream.openNode("rowItems", { count: 1 });
16827
+ xmlStream.openNode("i", { t: "grand" });
16828
+ xmlStream.leafNode("x");
16829
+ xmlStream.closeNode();
16830
+ xmlStream.closeNode();
16831
+ if (columns.length > 0) {
16832
+ const fieldCount = values.length > 1 ? columns.length + 1 : columns.length;
16833
+ xmlStream.openNode("colFields", { count: fieldCount });
16834
+ for (const colIndex of columns) xmlStream.leafNode("field", { x: colIndex });
16835
+ if (values.length > 1) xmlStream.leafNode("field", { x: VALUES_FIELD_INDEX });
16836
+ xmlStream.closeNode();
16837
+ } else if (isMultiValueNoCol) {
16838
+ xmlStream.openNode("colFields", { count: 1 });
16839
+ xmlStream.leafNode("field", { x: VALUES_FIELD_INDEX });
16840
+ xmlStream.closeNode();
16841
+ }
16842
+ if (isMultiValueNoCol) {
16843
+ xmlStream.openNode("colItems", { count: values.length + 1 });
16844
+ for (let idx = 0; idx < values.length; idx++) {
16845
+ xmlStream.openNode("i");
16846
+ xmlStream.leafNode("x", idx === 0 ? void 0 : { v: idx });
16847
+ xmlStream.closeNode();
16848
+ }
16849
+ xmlStream.openNode("i", { t: "grand" });
16850
+ xmlStream.leafNode("x");
16851
+ xmlStream.closeNode();
16852
+ xmlStream.closeNode();
16853
+ } else {
16854
+ xmlStream.openNode("colItems", { count: 1 });
16855
+ xmlStream.leafNode("i");
16856
+ xmlStream.closeNode();
16857
+ }
16858
+ if (pageCount > 0) {
16859
+ xmlStream.openNode("pageFields", { count: pageCount });
16860
+ for (const fld of pages) xmlStream.leafNode("pageField", {
16861
+ fld,
16862
+ hier: -1
16863
+ });
16864
+ xmlStream.closeNode();
16865
+ }
16866
+ renderDataFields(xmlStream, cacheFields, values, model.valueMetrics);
16867
+ xmlStream.leafNode("pivotTableStyleInfo", {
16868
+ name: DEFAULT_PIVOT_STYLE,
16869
+ showRowHeaders: "1",
16870
+ showColHeaders: "1",
16871
+ showRowStripes: "0",
16872
+ showColStripes: "0",
16873
+ showLastColumn: "1"
16874
+ });
16875
+ xmlStream.writeXml(PivotTableXform.EXTLST_XML);
16214
16876
  xmlStream.closeNode();
16215
16877
  }
16216
16878
  /**
16217
16879
  * Render loaded pivot table (preserving original structure)
16218
16880
  */
16219
16881
  renderLoaded(xmlStream, model) {
16220
- const attrs = {
16221
- ...PivotTableXform.PIVOT_TABLE_ATTRIBUTES,
16222
- name: model.name || "PivotTable1",
16223
- cacheId: model.cacheId,
16224
- applyNumberFormats: model.applyNumberFormats || "0",
16225
- applyBorderFormats: model.applyBorderFormats || "0",
16226
- applyFontFormats: model.applyFontFormats || "0",
16227
- applyPatternFormats: model.applyPatternFormats || "0",
16228
- applyAlignmentFormats: model.applyAlignmentFormats || "0",
16229
- applyWidthHeightFormats: model.applyWidthHeightFormats ?? "0",
16230
- dataCaption: model.dataCaption || "Values",
16231
- updatedVersion: model.updatedVersion || "8",
16232
- minRefreshableVersion: model.minRefreshableVersion || "3",
16233
- useAutoFormatting: model.useAutoFormatting ? "1" : "0",
16234
- itemPrintTitles: model.itemPrintTitles ? "1" : "0",
16235
- createdVersion: model.createdVersion || "8",
16236
- indent: model.indent !== void 0 ? String(model.indent) : "0",
16237
- multipleFieldFilters: model.multipleFieldFilters ? "1" : "0"
16238
- };
16239
- if (model.outline) attrs.outline = "1";
16240
- if (model.outlineData) attrs.outlineData = "1";
16241
- if (model.chartFormat !== void 0) attrs.chartFormat = String(model.chartFormat);
16242
- if (model.compact) attrs.compact = "1";
16243
- if (model.compactData) attrs.compactData = "1";
16882
+ const attrs = this.buildLoadedRootAttributes(model);
16244
16883
  xmlStream.openXml(XmlStream.StdDocAttributes);
16245
16884
  xmlStream.openNode(this.tag, attrs);
16246
- if (model.location) xmlStream.leafNode("location", {
16247
- ref: model.location.ref,
16248
- firstHeaderRow: model.location.firstHeaderRow,
16249
- firstDataRow: model.location.firstDataRow,
16250
- firstDataCol: model.location.firstDataCol
16251
- });
16885
+ if (model.location) {
16886
+ const locAttrs = {
16887
+ ref: model.location.ref,
16888
+ firstHeaderRow: model.location.firstHeaderRow,
16889
+ firstDataRow: model.location.firstDataRow,
16890
+ firstDataCol: model.location.firstDataCol
16891
+ };
16892
+ if (model.location.rowPageCount !== void 0) locAttrs.rowPageCount = model.location.rowPageCount;
16893
+ if (model.location.colPageCount !== void 0) locAttrs.colPageCount = model.location.colPageCount;
16894
+ xmlStream.leafNode("location", locAttrs);
16895
+ }
16252
16896
  if (model.pivotFields.length > 0) {
16253
16897
  xmlStream.openNode("pivotFields", { count: model.pivotFields.length });
16254
16898
  for (const pivotField of model.pivotFields) this.renderPivotFieldLoaded(xmlStream, pivotField);
@@ -16263,11 +16907,12 @@ var ExcelTS = (function(exports) {
16263
16907
  xmlStream.openNode("rowItems", { count: model.rowItems.length });
16264
16908
  for (const item of model.rowItems) this.renderRowColItem(xmlStream, item);
16265
16909
  xmlStream.closeNode();
16266
- } else xmlStream.writeXml("<rowItems count=\"1\"><i t=\"grand\"><x/></i></rowItems>");
16267
- if (model.hasColFields || model.colFields.length > 0) {
16910
+ } else if (model.hasRowItems) xmlStream.writeXml("<rowItems count=\"1\"><i t=\"grand\"><x/></i></rowItems>");
16911
+ if (model.hasColFields || model.colFields.length > 0) if (model.colFields.length === 0 && model.dataFields.length <= 1) xmlStream.leafNode("colFields", { count: 0 });
16912
+ else {
16268
16913
  const colFieldCount = model.colFields.length === 0 ? 1 : model.colFields.length;
16269
16914
  xmlStream.openNode("colFields", { count: colFieldCount });
16270
- if (model.colFields.length === 0) xmlStream.leafNode("field", { x: -2 });
16915
+ if (model.colFields.length === 0) xmlStream.leafNode("field", { x: VALUES_FIELD_INDEX });
16271
16916
  else for (const fieldIndex of model.colFields) xmlStream.leafNode("field", { x: fieldIndex });
16272
16917
  xmlStream.closeNode();
16273
16918
  }
@@ -16275,44 +16920,108 @@ var ExcelTS = (function(exports) {
16275
16920
  xmlStream.openNode("colItems", { count: model.colItems.length });
16276
16921
  for (const item of model.colItems) this.renderRowColItem(xmlStream, item);
16277
16922
  xmlStream.closeNode();
16278
- } else xmlStream.writeXml("<colItems count=\"1\"><i t=\"grand\"><x/></i></colItems>");
16923
+ } else if (model.hasColItems) xmlStream.writeXml("<colItems count=\"1\"><i t=\"grand\"><x/></i></colItems>");
16924
+ if (model.pageFields && model.pageFields.length > 0) {
16925
+ xmlStream.openNode("pageFields", { count: model.pageFields.length });
16926
+ for (const pf of model.pageFields) {
16927
+ const pfAttrs = { fld: pf.fld };
16928
+ if (pf.item !== void 0) pfAttrs.item = pf.item;
16929
+ if (pf.hier !== void 0) pfAttrs.hier = pf.hier;
16930
+ if (pf.name !== void 0) pfAttrs.name = pf.name;
16931
+ xmlStream.leafNode("pageField", pfAttrs);
16932
+ }
16933
+ xmlStream.closeNode();
16934
+ }
16279
16935
  if (model.dataFields.length > 0) {
16280
16936
  xmlStream.openNode("dataFields", { count: model.dataFields.length });
16281
16937
  for (const dataField of model.dataFields) {
16282
16938
  const dfAttrs = {
16283
16939
  name: dataField.name,
16284
- fld: dataField.fld,
16285
- baseField: dataField.baseField ?? 0,
16286
- baseItem: dataField.baseItem ?? 0
16940
+ fld: dataField.fld
16287
16941
  };
16288
- if (dataField.subtotal && dataField.subtotal !== "sum") dfAttrs.subtotal = dataField.subtotal;
16942
+ if (dataField.baseField !== void 0) dfAttrs.baseField = dataField.baseField;
16943
+ if (dataField.baseItem !== void 0) dfAttrs.baseItem = dataField.baseItem;
16944
+ if (dataField.subtotal !== void 0 && dataField.subtotal !== "sum") dfAttrs.subtotal = dataField.subtotal;
16945
+ if (dataField.numFmtId !== void 0) dfAttrs.numFmtId = dataField.numFmtId;
16289
16946
  xmlStream.leafNode("dataField", dfAttrs);
16290
16947
  }
16291
16948
  xmlStream.closeNode();
16292
16949
  }
16293
- if (model.chartFormats && model.chartFormats.length > 0) {
16294
- xmlStream.openNode("chartFormats", { count: model.chartFormats.length });
16295
- for (const cf of model.chartFormats) {
16296
- xmlStream.openNode("chartFormat", {
16297
- chart: cf.chart,
16298
- format: cf.format,
16299
- series: cf.series ? "1" : void 0
16300
- });
16301
- if (cf.pivotAreaXml) xmlStream.writeXml(cf.pivotAreaXml);
16302
- else xmlStream.writeXml(`<pivotArea type="data" outline="0" fieldPosition="0"><references count="1"><reference field="4294967294" count="1" selected="0"><x v="0"/></reference></references></pivotArea>`);
16303
- xmlStream.closeNode();
16304
- }
16950
+ if (model.formatsXml) xmlStream.writeXml(model.formatsXml);
16951
+ if (model.conditionalFormatsXml) xmlStream.writeXml(model.conditionalFormatsXml);
16952
+ if (model.chartFormats && model.chartFormats.length > 0) this.renderChartFormats(xmlStream, model.chartFormats);
16953
+ const si = model.styleInfo;
16954
+ xmlStream.leafNode("pivotTableStyleInfo", {
16955
+ name: si?.name ?? model.styleName ?? DEFAULT_PIVOT_STYLE,
16956
+ showRowHeaders: si?.showRowHeaders ?? "1",
16957
+ showColHeaders: si?.showColHeaders ?? "1",
16958
+ showRowStripes: si?.showRowStripes ?? "0",
16959
+ showColStripes: si?.showColStripes ?? "0",
16960
+ showLastColumn: si?.showLastColumn ?? "1"
16961
+ });
16962
+ if (model.filtersXml) xmlStream.writeXml(model.filtersXml);
16963
+ if (model.unknownElementsXml) xmlStream.writeXml(model.unknownElementsXml);
16964
+ const extLstXml = model.extLstXml ?? (model.isLoaded ? "" : PivotTableXform.EXTLST_XML);
16965
+ if (extLstXml) xmlStream.writeXml(extLstXml);
16966
+ xmlStream.closeNode();
16967
+ }
16968
+ /**
16969
+ * Build the root `<pivotTableDefinition>` attributes for a loaded (roundtrip) model.
16970
+ * Extracted from renderLoaded to keep the render method focused on element structure.
16971
+ */
16972
+ buildLoadedRootAttributes(model) {
16973
+ const attrs = {
16974
+ ...PivotTableXform.PIVOT_TABLE_ATTRIBUTES,
16975
+ name: model.name ?? "PivotTable1",
16976
+ cacheId: String(model.cacheId),
16977
+ applyNumberFormats: model.applyNumberFormats ?? "0",
16978
+ applyBorderFormats: model.applyBorderFormats ?? "0",
16979
+ applyFontFormats: model.applyFontFormats ?? "0",
16980
+ applyPatternFormats: model.applyPatternFormats ?? "0",
16981
+ applyAlignmentFormats: model.applyAlignmentFormats ?? "0",
16982
+ applyWidthHeightFormats: model.applyWidthHeightFormats ?? "0",
16983
+ dataCaption: model.dataCaption ?? "Values",
16984
+ updatedVersion: model.updatedVersion ?? "8",
16985
+ minRefreshableVersion: model.minRefreshableVersion ?? "3"
16986
+ };
16987
+ if (model.useAutoFormatting !== void 0) attrs.useAutoFormatting = model.useAutoFormatting;
16988
+ if (model.itemPrintTitles !== void 0) attrs.itemPrintTitles = model.itemPrintTitles;
16989
+ if (model.multipleFieldFilters !== void 0) attrs.multipleFieldFilters = model.multipleFieldFilters;
16990
+ attrs.createdVersion = model.createdVersion ?? "8";
16991
+ if (model.indent !== void 0) attrs.indent = String(model.indent);
16992
+ if (model.uid) {
16993
+ attrs["xmlns:xr"] = "http://schemas.microsoft.com/office/spreadsheetml/2014/revision";
16994
+ attrs["xr:uid"] = model.uid;
16995
+ }
16996
+ if (model.outline) attrs.outline = "1";
16997
+ if (model.outlineData) attrs.outlineData = "1";
16998
+ if (model.chartFormat !== void 0) attrs.chartFormat = String(model.chartFormat);
16999
+ if (model.colGrandTotals !== void 0) attrs.colGrandTotals = model.colGrandTotals;
17000
+ if (model.rowGrandTotals !== void 0) attrs.rowGrandTotals = model.rowGrandTotals;
17001
+ if (model.showError !== void 0) attrs.showError = model.showError;
17002
+ if (model.errorCaption !== void 0) attrs.errorCaption = model.errorCaption;
17003
+ if (model.showMissing !== void 0) attrs.showMissing = model.showMissing;
17004
+ if (model.missingCaption !== void 0) attrs.missingCaption = model.missingCaption;
17005
+ if (model.grandTotalCaption !== void 0) attrs.grandTotalCaption = model.grandTotalCaption;
17006
+ if (model.compact === false) attrs.compact = "0";
17007
+ if (model.compactData === false) attrs.compactData = "0";
17008
+ return attrs;
17009
+ }
17010
+ /**
17011
+ * Render `<chartFormats>` with preserved pivotArea XML for pivot chart roundtrip.
17012
+ */
17013
+ renderChartFormats(xmlStream, chartFormats) {
17014
+ xmlStream.openNode("chartFormats", { count: chartFormats.length });
17015
+ for (const cf of chartFormats) {
17016
+ xmlStream.openNode("chartFormat", {
17017
+ chart: cf.chart,
17018
+ format: cf.format,
17019
+ series: cf.series === true ? "1" : cf.series === false ? "0" : void 0
17020
+ });
17021
+ if (cf.pivotAreaXml) xmlStream.writeXml(cf.pivotAreaXml);
17022
+ else xmlStream.writeXml(`<pivotArea type="data" outline="0" fieldPosition="0"><references count="1"><reference field="${FIELD_INDEX_DATA_VALUES}" count="1" selected="0"><x v="0"/></reference></references></pivotArea>`);
16305
17023
  xmlStream.closeNode();
16306
17024
  }
16307
- xmlStream.leafNode("pivotTableStyleInfo", {
16308
- name: model.styleName || "PivotStyleLight16",
16309
- showRowHeaders: "1",
16310
- showColHeaders: "1",
16311
- showRowStripes: "0",
16312
- showColStripes: "0",
16313
- showLastColumn: "1"
16314
- });
16315
- xmlStream.writeXml(`<extLst><ext uri="{962EF5D1-5CA2-4c93-8EF4-DBF5C05439D2}" xmlns:x14="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"><x14:pivotTableDefinition hideValuesRow="1" xmlns:xm="http://schemas.microsoft.com/office/excel/2006/main"/></ext><ext uri="{747A6164-185A-40DC-8AA5-F01512510D54}" xmlns:xpdl="http://schemas.microsoft.com/office/spreadsheetml/2016/pivotdefaultlayout"><xpdl:pivotTableDefinition16/></ext></extLst>`);
16316
17025
  xmlStream.closeNode();
16317
17026
  }
16318
17027
  /**
@@ -16320,10 +17029,12 @@ var ExcelTS = (function(exports) {
16320
17029
  */
16321
17030
  renderRowColItem(xmlStream, item) {
16322
17031
  const attrs = {};
16323
- if (item.t) attrs.t = item.t;
16324
- if (item.x && item.x.length > 0) {
17032
+ if (item.t !== void 0) attrs.t = item.t;
17033
+ if (item.r !== void 0) attrs.r = item.r;
17034
+ if (item.i !== void 0) attrs.i = item.i;
17035
+ if (item.x.length > 0) {
16325
17036
  xmlStream.openNode("i", attrs);
16326
- for (const x of item.x) if (x.v && x.v !== 0) xmlStream.leafNode("x", { v: x.v });
17037
+ for (const x of item.x) if (x.v !== 0) xmlStream.leafNode("x", { v: x.v });
16327
17038
  else xmlStream.leafNode("x");
16328
17039
  xmlStream.closeNode();
16329
17040
  } else xmlStream.leafNode("i", attrs);
@@ -16335,28 +17046,64 @@ var ExcelTS = (function(exports) {
16335
17046
  const attrs = {};
16336
17047
  if (field.axis) attrs.axis = field.axis;
16337
17048
  if (field.dataField) attrs.dataField = "1";
17049
+ if (field.numFmtId !== void 0) attrs.numFmtId = String(field.numFmtId);
17050
+ if (field.sortType) attrs.sortType = field.sortType;
17051
+ if (field.compact === false) attrs.compact = "0";
17052
+ if (field.outline === false) attrs.outline = "0";
16338
17053
  attrs.showAll = field.showAll ? "1" : "0";
16339
- if (field.items && field.items.length > 0) {
17054
+ if (field.defaultSubtotal === false) attrs.defaultSubtotal = "0";
17055
+ if (field.subtotalTop === false) attrs.subtotalTop = "0";
17056
+ if (field.insertBlankRow === true) attrs.insertBlankRow = "1";
17057
+ if (field.multipleItemSelectionAllowed === true) attrs.multipleItemSelectionAllowed = "1";
17058
+ if (field.extraAttrs) for (const [k, v] of Object.entries(field.extraAttrs)) attrs[k] = v;
17059
+ if (field.items !== void 0 && field.items.length > 0 || field.autoSortScopeXml !== void 0) {
16340
17060
  xmlStream.openNode("pivotField", attrs);
16341
- xmlStream.openNode("items", { count: field.items.length + 1 });
16342
- for (const itemIndex of field.items) xmlStream.leafNode("item", { x: itemIndex });
16343
- xmlStream.writeXml("<item t=\"default\"/>");
16344
- xmlStream.closeNode();
17061
+ if (field.items !== void 0 && field.items.length > 0) {
17062
+ xmlStream.openNode("items", { count: field.items.length });
17063
+ for (const item of field.items) {
17064
+ const itemAttrs = {};
17065
+ for (const key of PIVOT_FIELD_ITEM_KEYS) if (item[key] !== void 0) itemAttrs[key] = item[key];
17066
+ xmlStream.leafNode("item", itemAttrs);
17067
+ }
17068
+ xmlStream.closeNode();
17069
+ }
17070
+ if (field.autoSortScopeXml) xmlStream.writeXml(field.autoSortScopeXml);
16345
17071
  xmlStream.closeNode();
16346
17072
  } else xmlStream.leafNode("pivotField", attrs);
16347
17073
  }
16348
17074
  parseOpen(node) {
16349
17075
  const { name, attributes } = node;
17076
+ if (this.extLstCollector.active) {
17077
+ this.extLstCollector.feedOpen(name, attributes);
17078
+ return true;
17079
+ }
17080
+ if (this.formatsCollector.active) {
17081
+ this.formatsCollector.feedOpen(name, attributes);
17082
+ return true;
17083
+ }
17084
+ if (this.conditionalFormatsCollector.active) {
17085
+ this.conditionalFormatsCollector.feedOpen(name, attributes);
17086
+ return true;
17087
+ }
17088
+ if (this.filtersCollector.active) {
17089
+ this.filtersCollector.feedOpen(name, attributes);
17090
+ return true;
17091
+ }
17092
+ if (this.unknownCollector.active) {
17093
+ this.unknownCollector.feedOpen(name, attributes);
17094
+ return true;
17095
+ }
16350
17096
  switch (name) {
16351
17097
  case this.tag:
16352
17098
  this.reset();
16353
17099
  this.model = {
16354
17100
  name: attributes.name,
16355
- cacheId: parseInt(attributes.cacheId || "0", 10),
17101
+ cacheId: parseInt(attributes.cacheId ?? "0", 10),
16356
17102
  uid: attributes["xr:uid"],
16357
17103
  pivotFields: [],
16358
17104
  rowFields: [],
16359
17105
  colFields: [],
17106
+ pageFields: [],
16360
17107
  dataFields: [],
16361
17108
  applyNumberFormats: attributes.applyNumberFormats,
16362
17109
  applyBorderFormats: attributes.applyBorderFormats,
@@ -16368,15 +17115,22 @@ var ExcelTS = (function(exports) {
16368
17115
  updatedVersion: attributes.updatedVersion,
16369
17116
  minRefreshableVersion: attributes.minRefreshableVersion,
16370
17117
  createdVersion: attributes.createdVersion,
16371
- useAutoFormatting: attributes.useAutoFormatting === "1",
16372
- itemPrintTitles: attributes.itemPrintTitles === "1",
16373
- indent: attributes.indent ? parseInt(attributes.indent, 10) : 0,
16374
- compact: attributes.compact === "1",
16375
- compactData: attributes.compactData === "1",
16376
- multipleFieldFilters: attributes.multipleFieldFilters === "1",
17118
+ useAutoFormatting: attributes.useAutoFormatting,
17119
+ itemPrintTitles: attributes.itemPrintTitles,
17120
+ indent: attributes.indent !== void 0 ? parseInt(attributes.indent, 10) : void 0,
17121
+ compact: attributes.compact !== "0",
17122
+ compactData: attributes.compactData !== "0",
17123
+ multipleFieldFilters: attributes.multipleFieldFilters,
16377
17124
  outline: attributes.outline === "1",
16378
17125
  outlineData: attributes.outlineData === "1",
16379
- chartFormat: attributes.chartFormat ? parseInt(attributes.chartFormat, 10) : void 0,
17126
+ chartFormat: attributes.chartFormat !== void 0 ? parseInt(attributes.chartFormat, 10) : void 0,
17127
+ colGrandTotals: attributes.colGrandTotals,
17128
+ rowGrandTotals: attributes.rowGrandTotals,
17129
+ showError: attributes.showError,
17130
+ errorCaption: attributes.errorCaption,
17131
+ showMissing: attributes.showMissing,
17132
+ missingCaption: attributes.missingCaption,
17133
+ grandTotalCaption: attributes.grandTotalCaption,
16380
17134
  rowItems: [],
16381
17135
  colItems: [],
16382
17136
  chartFormats: [],
@@ -16386,132 +17140,241 @@ var ExcelTS = (function(exports) {
16386
17140
  case "location":
16387
17141
  if (this.model) this.model.location = {
16388
17142
  ref: attributes.ref,
16389
- firstHeaderRow: attributes.firstHeaderRow ? parseInt(attributes.firstHeaderRow, 10) : void 0,
16390
- firstDataRow: attributes.firstDataRow ? parseInt(attributes.firstDataRow, 10) : void 0,
16391
- firstDataCol: attributes.firstDataCol ? parseInt(attributes.firstDataCol, 10) : void 0
17143
+ firstHeaderRow: attributes.firstHeaderRow !== void 0 ? parseInt(attributes.firstHeaderRow, 10) : void 0,
17144
+ firstDataRow: attributes.firstDataRow !== void 0 ? parseInt(attributes.firstDataRow, 10) : void 0,
17145
+ firstDataCol: attributes.firstDataCol !== void 0 ? parseInt(attributes.firstDataCol, 10) : void 0,
17146
+ rowPageCount: attributes.rowPageCount !== void 0 ? parseInt(attributes.rowPageCount, 10) : void 0,
17147
+ colPageCount: attributes.colPageCount !== void 0 ? parseInt(attributes.colPageCount, 10) : void 0
16392
17148
  };
16393
17149
  break;
16394
17150
  case "pivotFields":
16395
- this.state.inPivotFields = true;
17151
+ this.state.currentSection = "pivotFields";
16396
17152
  break;
16397
17153
  case "pivotField":
16398
- if (this.state.inPivotFields) this.currentPivotField = {
16399
- axis: attributes.axis,
16400
- dataField: attributes.dataField === "1",
16401
- items: [],
16402
- compact: attributes.compact === "1",
16403
- outline: attributes.outline === "1",
16404
- showAll: attributes.showAll === "1",
16405
- defaultSubtotal: attributes.defaultSubtotal === "1"
16406
- };
16407
- break;
16408
- case "items":
16409
- if (this.currentPivotField) this.state.inItems = true;
17154
+ if (this.state.currentSection === "pivotFields") {
17155
+ const extraAttrs = {};
17156
+ for (const [k, v] of Object.entries(attributes)) if (!KNOWN_PIVOT_FIELD_KEYS.has(k)) extraAttrs[k] = String(v);
17157
+ this.currentPivotField = {
17158
+ axis: VALID_PIVOT_AXES.has(attributes.axis) ? attributes.axis : void 0,
17159
+ dataField: attributes.dataField === "1",
17160
+ items: [],
17161
+ compact: attributes.compact !== "0",
17162
+ outline: attributes.outline !== "0",
17163
+ showAll: attributes.showAll !== "0",
17164
+ defaultSubtotal: attributes.defaultSubtotal !== "0",
17165
+ numFmtId: attributes.numFmtId !== void 0 ? parseInt(attributes.numFmtId, 10) : void 0,
17166
+ sortType: attributes.sortType,
17167
+ subtotalTop: attributes.subtotalTop !== void 0 ? attributes.subtotalTop === "1" : void 0,
17168
+ insertBlankRow: attributes.insertBlankRow === "1" ? true : void 0,
17169
+ multipleItemSelectionAllowed: attributes.multipleItemSelectionAllowed === "1" ? true : void 0,
17170
+ extraAttrs: Object.keys(extraAttrs).length > 0 ? extraAttrs : void 0
17171
+ };
17172
+ }
16410
17173
  break;
17174
+ case "items": break;
16411
17175
  case "item":
16412
- if (this.state.inItems && this.currentPivotField && attributes.x !== void 0) this.currentPivotField.items.push(parseInt(attributes.x, 10));
17176
+ if (this.currentPivotField) {
17177
+ const item = {};
17178
+ if (attributes.x !== void 0) item.x = parseInt(attributes.x, 10);
17179
+ for (const key of PIVOT_FIELD_ITEM_KEYS) if (key !== "x" && attributes[key] !== void 0) item[key] = attributes[key];
17180
+ this.currentPivotField.items.push(item);
17181
+ }
17182
+ break;
17183
+ case "autoSortScope":
17184
+ if (this.currentPivotField) {
17185
+ this.state.inAutoSortScope = true;
17186
+ this.autoSortScopeXmlBuffer = ["<autoSortScope>"];
17187
+ }
16413
17188
  break;
16414
17189
  case "rowFields":
16415
- this.state.inRowFields = true;
17190
+ this.state.currentSection = "rowFields";
16416
17191
  break;
16417
17192
  case "colFields":
16418
- this.state.inColFields = true;
17193
+ this.state.currentSection = "colFields";
16419
17194
  if (this.model) this.model.hasColFields = true;
16420
17195
  break;
16421
17196
  case "dataFields":
16422
- this.state.inDataFields = true;
17197
+ this.state.currentSection = "dataFields";
17198
+ break;
17199
+ case "pageFields":
17200
+ this.state.currentSection = "pageFields";
17201
+ break;
17202
+ case "pageField":
17203
+ if (this.state.currentSection === "pageFields" && this.model) this.model.pageFields.push({
17204
+ fld: parseInt(attributes.fld ?? "0", 10),
17205
+ item: attributes.item !== void 0 ? parseInt(attributes.item, 10) : void 0,
17206
+ hier: attributes.hier !== void 0 ? parseInt(attributes.hier, 10) : void 0,
17207
+ name: attributes.name
17208
+ });
16423
17209
  break;
16424
17210
  case "rowItems":
16425
- this.state.inRowItems = true;
17211
+ this.state.currentSection = "rowItems";
17212
+ if (this.model) this.model.hasRowItems = true;
16426
17213
  break;
16427
17214
  case "colItems":
16428
- this.state.inColItems = true;
17215
+ this.state.currentSection = "colItems";
17216
+ if (this.model) this.model.hasColItems = true;
16429
17217
  break;
16430
17218
  case "i":
16431
- if (this.state.inRowItems && this.model) this.currentRowItem = {
16432
- t: attributes.t,
16433
- x: []
16434
- };
16435
- else if (this.state.inColItems && this.model) this.currentColItem = {
16436
- t: attributes.t,
16437
- x: []
16438
- };
17219
+ if (this.model) {
17220
+ const rowColItem = this.state.currentSection === "rowItems" || this.state.currentSection === "colItems" ? parseRowColItem(attributes) : null;
17221
+ if (this.state.currentSection === "rowItems") this.currentRowItem = rowColItem;
17222
+ else if (this.state.currentSection === "colItems") this.currentColItem = rowColItem;
17223
+ }
16439
17224
  break;
16440
17225
  case "x":
16441
17226
  if (this.state.inPivotArea) {
16442
- const xAttrs = Object.entries(attributes).map(([k, v]) => `${k}="${v}"`).join(" ");
16443
- this.pivotAreaXmlBuffer.push(xAttrs ? `<x ${xAttrs}/>` : "<x/>");
16444
- } else if (this.currentRowItem) this.currentRowItem.x.push({ v: attributes.v ? parseInt(attributes.v, 10) : 0 });
16445
- else if (this.currentColItem) this.currentColItem.x.push({ v: attributes.v ? parseInt(attributes.v, 10) : 0 });
17227
+ const xAttrs = serializeAttributes(attributes);
17228
+ if (this.state.inAutoSortScope) this.autoSortScopeXmlBuffer.push(xAttrs ? `<x ${xAttrs}/>` : "<x/>");
17229
+ else this.pivotAreaXmlBuffer.push(xAttrs ? `<x ${xAttrs}/>` : "<x/>");
17230
+ } else if (this.currentRowItem) this.currentRowItem.x.push({ v: parseInt(attributes.v ?? "0", 10) });
17231
+ else if (this.currentColItem) this.currentColItem.x.push({ v: parseInt(attributes.v ?? "0", 10) });
16446
17232
  break;
16447
17233
  case "chartFormats":
16448
- this.state.inChartFormats = true;
17234
+ this.state.currentSection = "chartFormats";
16449
17235
  break;
16450
17236
  case "chartFormat":
16451
- if (this.state.inChartFormats && this.model) this.currentChartFormat = {
16452
- chart: attributes.chart ? parseInt(attributes.chart, 10) : 0,
16453
- format: attributes.format ? parseInt(attributes.format, 10) : 0,
16454
- series: attributes.series === "1"
17237
+ if (this.state.currentSection === "chartFormats" && this.model) this.currentChartFormat = {
17238
+ chart: parseInt(attributes.chart ?? "0", 10),
17239
+ format: parseInt(attributes.format ?? "0", 10),
17240
+ series: attributes.series !== void 0 ? attributes.series === "1" : void 0
16455
17241
  };
16456
17242
  break;
16457
17243
  case "pivotArea":
16458
17244
  if (this.currentChartFormat) {
16459
17245
  this.state.inPivotArea = true;
16460
- const attrsStr = Object.entries(attributes).map(([k, v]) => `${k}="${v}"`).join(" ");
17246
+ const attrsStr = serializeAttributes(attributes);
16461
17247
  this.pivotAreaXmlBuffer = [attrsStr ? `<pivotArea ${attrsStr}>` : "<pivotArea>"];
17248
+ } else if (this.state.inAutoSortScope) {
17249
+ this.state.inPivotArea = true;
17250
+ const attrsStr = serializeAttributes(attributes);
17251
+ this.autoSortScopeXmlBuffer.push(attrsStr ? `<pivotArea ${attrsStr}>` : "<pivotArea>");
16462
17252
  }
16463
17253
  break;
16464
17254
  case "references":
16465
17255
  case "reference":
16466
17256
  if (this.state.inPivotArea) {
16467
- this.pivotAreaDepth++;
16468
- const attrsStr = Object.entries(attributes).map(([k, v]) => `${k}="${v}"`).join(" ");
16469
- this.pivotAreaXmlBuffer.push(`<${name}${attrsStr ? " " + attrsStr : ""}>`);
17257
+ const attrsStr = serializeAttributes(attributes);
17258
+ if (this.state.inAutoSortScope) this.autoSortScopeXmlBuffer.push(`<${name}${attrsStr ? " " + attrsStr : ""}>`);
17259
+ else this.pivotAreaXmlBuffer.push(`<${name}${attrsStr ? " " + attrsStr : ""}>`);
16470
17260
  }
16471
17261
  break;
16472
17262
  case "field":
16473
17263
  if (this.model) {
16474
- const fieldIndex = parseInt(attributes.x || "0", 10);
16475
- if (this.state.inRowFields) this.model.rowFields.push(fieldIndex);
16476
- else if (this.state.inColFields) this.model.colFields.push(fieldIndex);
17264
+ const fieldIndex = parseInt(attributes.x ?? "0", 10);
17265
+ if (this.state.currentSection === "rowFields") this.model.rowFields.push(fieldIndex);
17266
+ else if (this.state.currentSection === "colFields") this.model.colFields.push(fieldIndex);
16477
17267
  }
16478
17268
  break;
16479
17269
  case "dataField":
16480
- if (this.state.inDataFields && this.model) this.model.dataFields.push({
16481
- name: xmlDecode(attributes.name || ""),
16482
- fld: parseInt(attributes.fld || "0", 10),
16483
- baseField: attributes.baseField ? parseInt(attributes.baseField, 10) : 0,
16484
- baseItem: attributes.baseItem ? parseInt(attributes.baseItem, 10) : 0,
16485
- subtotal: attributes.subtotal
17270
+ if (this.state.currentSection === "dataFields" && this.model) this.model.dataFields.push({
17271
+ name: attributes.name ?? "",
17272
+ fld: parseInt(attributes.fld ?? "0", 10),
17273
+ baseField: attributes.baseField !== void 0 ? parseInt(attributes.baseField, 10) : void 0,
17274
+ baseItem: attributes.baseItem !== void 0 ? parseInt(attributes.baseItem, 10) : void 0,
17275
+ subtotal: VALID_SUBTOTALS.has(attributes.subtotal) ? attributes.subtotal : void 0,
17276
+ numFmtId: attributes.numFmtId !== void 0 ? parseInt(attributes.numFmtId, 10) : void 0
16486
17277
  });
16487
17278
  break;
16488
17279
  case "pivotTableStyleInfo":
16489
- if (this.model) this.model.styleName = attributes.name;
17280
+ if (this.model) {
17281
+ this.model.styleName = attributes.name;
17282
+ this.model.styleInfo = {
17283
+ name: attributes.name,
17284
+ showRowHeaders: attributes.showRowHeaders,
17285
+ showColHeaders: attributes.showColHeaders,
17286
+ showRowStripes: attributes.showRowStripes,
17287
+ showColStripes: attributes.showColStripes,
17288
+ showLastColumn: attributes.showLastColumn
17289
+ };
17290
+ }
17291
+ break;
17292
+ case "extLst":
17293
+ if (this.model) this.extLstCollector.start(attributes);
17294
+ break;
17295
+ case "formats":
17296
+ if (this.model) this.formatsCollector.start(attributes);
17297
+ break;
17298
+ case "conditionalFormats":
17299
+ if (this.model) this.conditionalFormatsCollector.start(attributes);
17300
+ break;
17301
+ case "filters":
17302
+ if (this.model) this.filtersCollector.start(attributes);
17303
+ break;
17304
+ default:
17305
+ if (this.model && this.state.currentSection === null && !this.state.inPivotArea && !this.state.inAutoSortScope) this.unknownCollector.startAs(name, attributes);
16490
17306
  break;
16491
17307
  }
16492
17308
  return true;
16493
17309
  }
16494
- parseText(_text) {}
17310
+ parseText(text) {
17311
+ if (this.extLstCollector.active) this.extLstCollector.feedText(text);
17312
+ else if (this.formatsCollector.active) this.formatsCollector.feedText(text);
17313
+ else if (this.conditionalFormatsCollector.active) this.conditionalFormatsCollector.feedText(text);
17314
+ else if (this.filtersCollector.active) this.filtersCollector.feedText(text);
17315
+ else if (this.unknownCollector.active) this.unknownCollector.feedText(text);
17316
+ }
17317
+ /** Feed a close-tag to a collector; if it completes, store the result on the model. */
17318
+ tryCloseCollector(collector, name, modelKey) {
17319
+ if (collector.feedClose(name)) {
17320
+ if (this.model) this.model[modelKey] = collector.result;
17321
+ collector.reset();
17322
+ }
17323
+ }
16495
17324
  parseClose(name) {
17325
+ if (this.extLstCollector.active) {
17326
+ this.tryCloseCollector(this.extLstCollector, name, "extLstXml");
17327
+ return true;
17328
+ }
17329
+ if (this.formatsCollector.active) {
17330
+ this.tryCloseCollector(this.formatsCollector, name, "formatsXml");
17331
+ return true;
17332
+ }
17333
+ if (this.conditionalFormatsCollector.active) {
17334
+ this.tryCloseCollector(this.conditionalFormatsCollector, name, "conditionalFormatsXml");
17335
+ return true;
17336
+ }
17337
+ if (this.filtersCollector.active) {
17338
+ this.tryCloseCollector(this.filtersCollector, name, "filtersXml");
17339
+ return true;
17340
+ }
17341
+ if (this.unknownCollector.active) {
17342
+ if (this.unknownCollector.feedClose(name)) {
17343
+ this.unknownElementsXmlParts.push(this.unknownCollector.result);
17344
+ this.unknownCollector.reset();
17345
+ }
17346
+ return true;
17347
+ }
16496
17348
  if (this.state.inPivotArea) {
16497
17349
  if (name === "pivotArea") {
16498
- this.pivotAreaXmlBuffer.push("</pivotArea>");
16499
- if (this.currentChartFormat) this.currentChartFormat.pivotAreaXml = this.pivotAreaXmlBuffer.join("");
17350
+ if (this.state.inAutoSortScope) this.autoSortScopeXmlBuffer.push("</pivotArea>");
17351
+ else {
17352
+ this.pivotAreaXmlBuffer.push("</pivotArea>");
17353
+ if (this.currentChartFormat) this.currentChartFormat.pivotAreaXml = this.pivotAreaXmlBuffer.join("");
17354
+ this.pivotAreaXmlBuffer = [];
17355
+ }
16500
17356
  this.state.inPivotArea = false;
16501
- this.pivotAreaXmlBuffer = [];
16502
- this.pivotAreaDepth = 0;
16503
17357
  return true;
16504
17358
  } else if (name === "references" || name === "reference") {
16505
- this.pivotAreaXmlBuffer.push(`</${name}>`);
16506
- this.pivotAreaDepth--;
17359
+ if (this.state.inAutoSortScope) this.autoSortScopeXmlBuffer.push(`</${name}>`);
17360
+ else this.pivotAreaXmlBuffer.push(`</${name}>`);
16507
17361
  return true;
16508
17362
  }
16509
17363
  return true;
16510
17364
  }
16511
17365
  switch (name) {
16512
- case this.tag: return false;
17366
+ case this.tag:
17367
+ if (this.model && this.unknownElementsXmlParts.length > 0) this.model.unknownElementsXml = this.unknownElementsXmlParts.join("");
17368
+ return false;
16513
17369
  case "pivotFields":
16514
- this.state.inPivotFields = false;
17370
+ case "rowFields":
17371
+ case "colFields":
17372
+ case "dataFields":
17373
+ case "pageFields":
17374
+ case "rowItems":
17375
+ case "colItems":
17376
+ case "chartFormats":
17377
+ this.state.currentSection = null;
16515
17378
  break;
16516
17379
  case "pivotField":
16517
17380
  if (this.currentPivotField && this.model) {
@@ -16519,146 +17382,107 @@ var ExcelTS = (function(exports) {
16519
17382
  this.currentPivotField = null;
16520
17383
  }
16521
17384
  break;
16522
- case "items":
16523
- this.state.inItems = false;
16524
- break;
16525
- case "rowFields":
16526
- this.state.inRowFields = false;
16527
- break;
16528
- case "colFields":
16529
- this.state.inColFields = false;
16530
- break;
16531
- case "dataFields":
16532
- this.state.inDataFields = false;
16533
- break;
16534
- case "rowItems":
16535
- this.state.inRowItems = false;
16536
- break;
16537
- case "colItems":
16538
- this.state.inColItems = false;
17385
+ case "items": break;
17386
+ case "autoSortScope":
17387
+ if (this.state.inAutoSortScope && this.currentPivotField) {
17388
+ this.autoSortScopeXmlBuffer.push("</autoSortScope>");
17389
+ this.currentPivotField.autoSortScopeXml = this.autoSortScopeXmlBuffer.join("");
17390
+ this.autoSortScopeXmlBuffer = [];
17391
+ this.state.inAutoSortScope = false;
17392
+ }
16539
17393
  break;
16540
17394
  case "i":
16541
17395
  if (this.currentRowItem && this.model) {
16542
- this.model.rowItems.push(this.currentRowItem);
17396
+ this.model.rowItems?.push(this.currentRowItem);
16543
17397
  this.currentRowItem = null;
16544
17398
  } else if (this.currentColItem && this.model) {
16545
- this.model.colItems.push(this.currentColItem);
17399
+ this.model.colItems?.push(this.currentColItem);
16546
17400
  this.currentColItem = null;
16547
17401
  }
16548
17402
  break;
16549
- case "chartFormats":
16550
- this.state.inChartFormats = false;
16551
- break;
16552
17403
  case "chartFormat":
16553
17404
  if (this.currentChartFormat && this.model) {
16554
- this.model.chartFormats.push(this.currentChartFormat);
17405
+ this.model.chartFormats?.push(this.currentChartFormat);
16555
17406
  this.currentChartFormat = null;
16556
17407
  }
16557
17408
  break;
16558
17409
  }
16559
17410
  return true;
16560
17411
  }
16561
- reconcile(_model, _options) {}
16562
17412
  static {
16563
17413
  this.PIVOT_TABLE_ATTRIBUTES = { xmlns: "http://schemas.openxmlformats.org/spreadsheetml/2006/main" };
16564
17414
  }
17415
+ static {
17416
+ this.EXTLST_XML = "<extLst><ext uri=\"{962EF5D1-5CA2-4c93-8EF4-DBF5C05439D2}\" xmlns:x14=\"http://schemas.microsoft.com/office/spreadsheetml/2009/9/main\"><x14:pivotTableDefinition hideValuesRow=\"1\" xmlns:xm=\"http://schemas.microsoft.com/office/excel/2006/main\"/></ext><ext uri=\"{747A6164-185A-40DC-8AA5-F01512510D54}\" xmlns:xpdl=\"http://schemas.microsoft.com/office/spreadsheetml/2016/pivotdefaultlayout\"><xpdl:pivotTableDefinition16 EnabledSubtotalsDefault=\"0\" SubtotalsOnTopDefault=\"0\"/></ext></extLst>";
17417
+ }
16565
17418
  };
16566
- /**
16567
- * Build rowItems XML - one item for each unique value in row fields, plus grand total.
16568
- * Each <i> represents a row in the pivot table.
16569
- * - Regular items: <i><x/></i> for index 0, <i><x v="index"/></i> for index > 0
16570
- * - Grand total: <i t="grand"><x/></i>
16571
- * Note: When v=0, the v attribute should be omitted (Excel convention)
16572
- */
16573
- function buildRowItems(rows, cacheFields) {
16574
- if (rows.length === 0) return {
16575
- count: 1,
16576
- xml: "<i t=\"grand\"><x /></i>"
16577
- };
16578
- const itemCount = (cacheFields[rows[0]]?.sharedItems || []).length;
16579
- const items = [];
16580
- for (let i = 0; i < itemCount; i++) if (i === 0) items.push("<i><x /></i>");
16581
- else items.push(`<i><x v="${i}" /></i>`);
16582
- items.push("<i t=\"grand\"><x /></i>");
17419
+ /** Parse attributes of a row/col `<i>` element into a RowColItem. */
17420
+ function parseRowColItem(attributes) {
16583
17421
  return {
16584
- count: items.length,
16585
- xml: items.join("\n ")
17422
+ t: attributes.t,
17423
+ r: attributes.r !== void 0 ? parseInt(attributes.r, 10) : void 0,
17424
+ i: attributes.i !== void 0 ? parseInt(attributes.i, 10) : void 0,
17425
+ x: []
16586
17426
  };
16587
17427
  }
16588
17428
  /**
16589
- * Build colItems XML - one item for each unique value in column fields, plus grand total.
16590
- * When there are multiple data fields (values), each column value may have sub-columns.
16591
- * Note: When v=0, the v attribute should be omitted (Excel convention)
17429
+ * Render dataField XML elements for all values in the pivot table.
17430
+ * Each value field gets its own metric from the `valueMetrics` array.
16592
17431
  */
16593
- function buildColItems(columns, cacheFields, valueCount) {
16594
- if (columns.length === 0) {
16595
- if (valueCount > 1) {
16596
- const items = [];
16597
- for (let i = 0; i < valueCount; i++) if (i === 0) items.push("<i><x /></i>");
16598
- else items.push(`<i><x v="${i}" /></i>`);
16599
- items.push("<i t=\"grand\"><x /></i>");
16600
- return {
16601
- count: items.length,
16602
- xml: items.join("\n ")
16603
- };
16604
- }
16605
- return {
16606
- count: 1,
16607
- xml: "<i t=\"grand\"><x /></i>"
17432
+ function renderDataFields(xmlStream, cacheFields, values, valueMetrics) {
17433
+ xmlStream.openNode("dataFields", { count: values.length });
17434
+ for (let i = 0; i < values.length; i++) {
17435
+ const valueIndex = values[i];
17436
+ const metric = valueMetrics[i] ?? "sum";
17437
+ const metricName = METRIC_DISPLAY_NAMES[metric];
17438
+ const field = cacheFields[valueIndex];
17439
+ if (!field) throw new Error(`Value field index ${valueIndex} is out of bounds (cacheFields has ${cacheFields.length} entries)`);
17440
+ const attrs = {
17441
+ name: `${metricName} of ${field.name}`,
17442
+ fld: valueIndex,
17443
+ baseField: 0,
17444
+ baseItem: 0
16608
17445
  };
17446
+ if (metric !== "sum") attrs.subtotal = metric;
17447
+ xmlStream.leafNode("dataField", attrs);
16609
17448
  }
16610
- const itemCount = (cacheFields[columns[0]]?.sharedItems || []).length;
16611
- const items = [];
16612
- for (let i = 0; i < itemCount; i++) if (i === 0) items.push("<i><x /></i>");
16613
- else items.push(`<i><x v="${i}" /></i>`);
16614
- items.push("<i t=\"grand\"><x /></i>");
16615
- return {
16616
- count: items.length,
16617
- xml: items.join("\n ")
16618
- };
17449
+ xmlStream.closeNode();
16619
17450
  }
16620
- /**
16621
- * Build dataField XML elements for all values in the pivot table.
16622
- * Supports multiple values when columns is empty.
16623
- */
16624
- function buildDataFields(cacheFields, values, metric) {
16625
- const metricName = metric === "count" ? "Count" : "Sum";
16626
- const subtotalAttr = metric === "count" ? " subtotal=\"count\"" : "";
16627
- return values.map((valueIndex) => `<dataField
16628
- name="${metricName} of ${xmlEncode(cacheFields[valueIndex].name)}"
16629
- fld="${valueIndex}"
16630
- baseField="0"
16631
- baseItem="0"${subtotalAttr}
16632
- />`).join("");
16633
- }
16634
- function renderPivotFields(pivotTable) {
17451
+ function renderPivotFields(xmlStream, pivotTable) {
16635
17452
  const rowSet = new Set(pivotTable.rows);
16636
17453
  const colSet = new Set(pivotTable.columns);
16637
17454
  const valueSet = new Set(pivotTable.values);
16638
- return pivotTable.cacheFields.map((cacheField, fieldIndex) => {
16639
- return renderPivotField(rowSet.has(fieldIndex), colSet.has(fieldIndex), valueSet.has(fieldIndex), cacheField.sharedItems);
16640
- }).join("");
16641
- }
16642
- function renderPivotField(isRow, isCol, isValue, sharedItems) {
16643
- if (isRow || isCol) {
16644
- const axis = isRow ? "axisRow" : "axisCol";
16645
- let axisAttributes = "compact=\"0\" outline=\"0\" showAll=\"0\"";
16646
- if (isValue) axisAttributes = `dataField="1" ${axisAttributes}`;
16647
- const itemsXml = [...sharedItems.map((_item, index) => `<item x="${index}" />`), "<item t=\"default\" />"].join("\n ");
16648
- return `
16649
- <pivotField axis="${axis}" ${axisAttributes}>
16650
- <items count="${sharedItems.length + 1}">
16651
- ${itemsXml}
16652
- </items>
16653
- </pivotField>
16654
- `;
16655
- }
16656
- return `
16657
- <pivotField
16658
- ${isValue ? "dataField=\"1\"" : ""}
16659
- compact="0" outline="0" showAll="0" defaultSubtotal="0"
16660
- />
16661
- `;
17455
+ const pageSet = new Set(pivotTable.pages ?? []);
17456
+ xmlStream.openNode("pivotFields", { count: pivotTable.cacheFields.length });
17457
+ for (let fieldIndex = 0; fieldIndex < pivotTable.cacheFields.length; fieldIndex++) {
17458
+ const cacheField = pivotTable.cacheFields[fieldIndex];
17459
+ renderPivotField(xmlStream, rowSet.has(fieldIndex), colSet.has(fieldIndex), valueSet.has(fieldIndex), pageSet.has(fieldIndex), cacheField.sharedItems);
17460
+ }
17461
+ xmlStream.closeNode();
17462
+ }
17463
+ function renderPivotField(xmlStream, isRow, isCol, isValue, isPage, sharedItems) {
17464
+ if (isRow || isCol || isPage) {
17465
+ if (!sharedItems) throw new Error("sharedItems is required for axis field (row/column/page)");
17466
+ const attrs = { axis: isRow ? "axisRow" : isCol ? "axisCol" : "axisPage" };
17467
+ if (isValue) attrs.dataField = "1";
17468
+ attrs.compact = "0";
17469
+ attrs.outline = "0";
17470
+ attrs.showAll = "0";
17471
+ xmlStream.openNode("pivotField", attrs);
17472
+ xmlStream.openNode("items", { count: sharedItems.length + 1 });
17473
+ for (let i = 0; i < sharedItems.length; i++) xmlStream.leafNode("item", { x: i });
17474
+ xmlStream.leafNode("item", { t: "default" });
17475
+ xmlStream.closeNode();
17476
+ xmlStream.closeNode();
17477
+ return;
17478
+ }
17479
+ const attrs = {};
17480
+ if (isValue) attrs.dataField = "1";
17481
+ attrs.compact = "0";
17482
+ attrs.outline = "0";
17483
+ attrs.showAll = "0";
17484
+ attrs.defaultSubtotal = "0";
17485
+ xmlStream.leafNode("pivotField", attrs);
16662
17486
  }
16663
17487
 
16664
17488
  //#endregion
@@ -16801,7 +17625,7 @@ var ExcelTS = (function(exports) {
16801
17625
  return `${(parseFloat(value.toString()) * multiple).toFixed(2)}${unit}`;
16802
17626
  }
16803
17627
  reverseConversionUnit(inset) {
16804
- return (inset || "").split(",").map((margin) => {
17628
+ return (inset ?? "").split(",").map((margin) => {
16805
17629
  return Number(parseFloat(this.conversionUnit(parseFloat(margin), .1, "")).toFixed(2));
16806
17630
  });
16807
17631
  }
@@ -16908,7 +17732,7 @@ var ExcelTS = (function(exports) {
16908
17732
  this.text = "";
16909
17733
  }
16910
17734
  get tag() {
16911
- return this._model && this._model.tag || "";
17735
+ return this._model?.tag ?? "";
16912
17736
  }
16913
17737
  render(xmlStream, model) {
16914
17738
  xmlStream.leafNode(this.tag, null, model);
@@ -16938,7 +17762,7 @@ var ExcelTS = (function(exports) {
16938
17762
  this.model = {};
16939
17763
  }
16940
17764
  get tag() {
16941
- return this._model && this._model.tag || "";
17765
+ return this._model?.tag ?? "";
16942
17766
  }
16943
17767
  render(xmlStream, model, type) {
16944
17768
  if (type && model === type[2]) xmlStream.leafNode(this.tag);
@@ -17054,7 +17878,7 @@ var ExcelTS = (function(exports) {
17054
17878
  return "v:shape";
17055
17879
  }
17056
17880
  render(xmlStream, model, index) {
17057
- xmlStream.openNode("v:shape", VmlShapeXform.V_SHAPE_ATTRIBUTES(model, index || 0));
17881
+ xmlStream.openNode("v:shape", VmlShapeXform.V_SHAPE_ATTRIBUTES(model, index ?? 0));
17058
17882
  xmlStream.leafNode("v:fill", { color2: "infoBackground [80]" });
17059
17883
  xmlStream.leafNode("v:shadow", {
17060
17884
  color: "none [81]",
@@ -17376,7 +18200,7 @@ var ExcelTS = (function(exports) {
17376
18200
  return this._buffer;
17377
18201
  }
17378
18202
  reset(position) {
17379
- position = position || 0;
18203
+ position = position ?? 0;
17380
18204
  this._buffer = void 0;
17381
18205
  this._inPos = position;
17382
18206
  }
@@ -17526,7 +18350,7 @@ var ExcelTS = (function(exports) {
17526
18350
  this._asyncWriteQueue = Promise.resolve();
17527
18351
  this.bufSize = options?.bufSize || 1024 * 1024;
17528
18352
  this.buffers = [];
17529
- this.batch = options?.batch || false;
18353
+ this.batch = options?.batch ?? false;
17530
18354
  this.corked = false;
17531
18355
  this.paused = false;
17532
18356
  this.encoding = null;
@@ -17694,7 +18518,7 @@ var ExcelTS = (function(exports) {
17694
18518
  * Cross-platform compatible - works identically in Node.js and Browser.
17695
18519
  */
17696
18520
  readString(encoding) {
17697
- const enc = encoding || this.encoding || "utf-8";
18521
+ const enc = encoding ?? this.encoding ?? "utf-8";
17698
18522
  const buf = this.read();
17699
18523
  if (typeof Buffer !== "undefined" && buf instanceof Buffer) return buf.toString(enc);
17700
18524
  return new TextDecoder(enc).decode(buf);
@@ -20779,7 +21603,6 @@ var ExcelTS = (function(exports) {
20779
21603
  pivotTables: {},
20780
21604
  pivotTableRels: {},
20781
21605
  pivotCacheDefinitions: {},
20782
- pivotCacheDefinitionRels: {},
20783
21606
  pivotCacheRecords: {},
20784
21607
  passthrough: {}
20785
21608
  };
@@ -20961,7 +21784,7 @@ var ExcelTS = (function(exports) {
20961
21784
  o[rel.Id] = rel;
20962
21785
  return o;
20963
21786
  }, {});
20964
- (drawing.anchors || []).forEach((anchor) => {
21787
+ (drawing.anchors ?? []).forEach((anchor) => {
20965
21788
  const hyperlinks = anchor.picture && anchor.picture.hyperlinks;
20966
21789
  if (hyperlinks && drawingOptions.rels[hyperlinks.rId]) {
20967
21790
  hyperlinks.hyperlink = drawingOptions.rels[hyperlinks.rId].Target;
@@ -21010,7 +21833,6 @@ var ExcelTS = (function(exports) {
21010
21833
  delete model.drawingRels;
21011
21834
  delete model.vmlDrawings;
21012
21835
  delete model.pivotTableRels;
21013
- delete model.pivotCacheDefinitionRels;
21014
21836
  }
21015
21837
  /**
21016
21838
  * Reconcile pivot tables by linking them to worksheets and their cache data.
@@ -21037,21 +21859,24 @@ var ExcelTS = (function(exports) {
21037
21859
  });
21038
21860
  const loadedPivotTables = [];
21039
21861
  const pivotTablesIndexed = {};
21040
- Object.entries(rawPivotTables).forEach(([pivotName, pivotTable]) => {
21041
- const pt = pivotTable;
21862
+ Object.entries(rawPivotTables).forEach(([pivotName, pt]) => {
21042
21863
  const tableNumber = this._extractTableNumber(pivotName);
21043
21864
  const cacheData = cacheMap.get(pt.cacheId);
21865
+ const defaultMetric = this._determineMetric(pt.dataFields);
21044
21866
  const completePivotTable = {
21045
21867
  ...pt,
21046
21868
  tableNumber,
21869
+ cacheId: String(pt.cacheId),
21047
21870
  cacheDefinition: cacheData?.definition,
21048
21871
  cacheRecords: cacheData?.records,
21049
- cacheFields: cacheData?.definition?.cacheFields || [],
21872
+ cacheFields: cacheData?.definition?.cacheFields ?? [],
21050
21873
  rows: pt.rowFields.filter((f) => f >= 0),
21051
21874
  columns: pt.colFields.filter((f) => f >= 0 && f !== -2),
21052
21875
  values: pt.dataFields.map((df) => df.fld),
21053
- metric: this._determineMetric(pt.dataFields),
21054
- applyWidthHeightFormats: pt.applyWidthHeightFormats || "0"
21876
+ pages: pt.pageFields.map((pf) => pf.fld),
21877
+ metric: defaultMetric,
21878
+ valueMetrics: this._determineValueMetrics(pt.dataFields, defaultMetric),
21879
+ applyWidthHeightFormats: pt.applyWidthHeightFormats === "1" ? "1" : "0"
21055
21880
  };
21056
21881
  loadedPivotTables.push(completePivotTable);
21057
21882
  pivotTablesIndexed[pivotTableRelTargetFromWorksheetName(pivotName)] = completePivotTable;
@@ -21059,7 +21884,6 @@ var ExcelTS = (function(exports) {
21059
21884
  loadedPivotTables.sort((a, b) => a.tableNumber - b.tableNumber);
21060
21885
  model.pivotTables = loadedPivotTables;
21061
21886
  model.pivotTablesIndexed = pivotTablesIndexed;
21062
- model.loadedPivotTables = loadedPivotTables;
21063
21887
  }
21064
21888
  _extractTableNumber(name) {
21065
21889
  const match = name.match(/pivotTable(\d+)/);
@@ -21067,14 +21891,14 @@ var ExcelTS = (function(exports) {
21067
21891
  }
21068
21892
  _buildCacheIdMap(model) {
21069
21893
  const rIdToCacheId = /* @__PURE__ */ new Map();
21070
- const pivotCaches = model.pivotCaches || [];
21894
+ const pivotCaches = model.pivotCaches ?? [];
21071
21895
  for (const cache of pivotCaches) if (cache.cacheId && cache.rId) rIdToCacheId.set(cache.rId, parseInt(cache.cacheId, 10));
21072
21896
  return rIdToCacheId;
21073
21897
  }
21074
21898
  _buildDefinitionToCacheIdMap(model) {
21075
21899
  const definitionToCacheId = /* @__PURE__ */ new Map();
21076
21900
  const rIdToCacheId = this._buildCacheIdMap(model);
21077
- const workbookRels = model.workbookRels || [];
21901
+ const workbookRels = model.workbookRels ?? [];
21078
21902
  for (const rel of workbookRels) if (rel.Type === XLSX.RelType.PivotCacheDefinition && rel.Target) {
21079
21903
  const match = rel.Target.match(/pivotCacheDefinition(\d+)\.xml/);
21080
21904
  if (match) {
@@ -21086,9 +21910,12 @@ var ExcelTS = (function(exports) {
21086
21910
  return definitionToCacheId;
21087
21911
  }
21088
21912
  _determineMetric(dataFields) {
21089
- if (dataFields.length > 0 && dataFields[0].subtotal === "count") return "count";
21913
+ if (dataFields.length > 0 && dataFields[0].subtotal) return dataFields[0].subtotal;
21090
21914
  return "sum";
21091
21915
  }
21916
+ _determineValueMetrics(dataFields, defaultMetric) {
21917
+ return dataFields.map((df) => df.subtotal || defaultMetric);
21918
+ }
21092
21919
  async _processWorksheetEntry(stream, model, sheetNo, options, path) {
21093
21920
  const worksheet = await new WorkSheetXform(options).parseStream(stream);
21094
21921
  if (!worksheet) throw new Error(`Failed to parse worksheet ${path}`);
@@ -21204,10 +22031,6 @@ var ExcelTS = (function(exports) {
21204
22031
  const cacheDefinition = await new PivotCacheDefinitionXform().parseStream(stream);
21205
22032
  if (cacheDefinition) model.pivotCacheDefinitions[name] = cacheDefinition;
21206
22033
  }
21207
- async _processPivotCacheDefinitionRelsEntry(stream, model, name) {
21208
- const relationships = await new RelationshipsXform().parseStream(stream);
21209
- model.pivotCacheDefinitionRels[name] = relationships;
21210
- }
21211
22034
  async _processPivotCacheRecordsEntry(stream, model, name) {
21212
22035
  const cacheRecords = await new PivotCacheRecordsXform().parseStream(stream);
21213
22036
  if (cacheRecords) model.pivotCacheRecords[name] = cacheRecords;
@@ -21288,11 +22111,7 @@ var ExcelTS = (function(exports) {
21288
22111
  await this._processPivotCacheDefinitionEntry(stream, model, pivotCacheDefinitionName);
21289
22112
  return true;
21290
22113
  }
21291
- const pivotCacheDefinitionRelsName = getPivotCacheDefinitionNameFromRelsPath(entryName);
21292
- if (pivotCacheDefinitionRelsName) {
21293
- await this._processPivotCacheDefinitionRelsEntry(stream, model, pivotCacheDefinitionRelsName);
21294
- return true;
21295
- }
22114
+ if (getPivotCacheDefinitionNameFromRelsPath(entryName)) return true;
21296
22115
  const pivotCacheRecordsName = getPivotCacheRecordsNameFromPath(entryName);
21297
22116
  if (pivotCacheRecordsName) {
21298
22117
  await this._processPivotCacheRecordsEntry(stream, model, pivotCacheRecordsName);
@@ -21373,13 +22192,19 @@ var ExcelTS = (function(exports) {
21373
22192
  Type: XLSX.RelType.FeaturePropertyBag,
21374
22193
  Target: OOXML_REL_TARGETS.workbookFeaturePropertyBag
21375
22194
  });
21376
- (model.pivotTables || []).forEach((pivotTable) => {
21377
- pivotTable.rId = `rId${count++}`;
21378
- relationships.push({
21379
- Id: pivotTable.rId,
21380
- Type: XLSX.RelType.PivotCacheDefinition,
21381
- Target: pivotCacheDefinitionRelTargetFromWorkbook(pivotTable.tableNumber)
21382
- });
22195
+ const seenCacheIds = /* @__PURE__ */ new Map();
22196
+ (model.pivotTables ?? []).forEach((pivotTable) => {
22197
+ const existing = seenCacheIds.get(pivotTable.cacheId);
22198
+ if (existing) pivotTable.rId = existing;
22199
+ else {
22200
+ pivotTable.rId = `rId${count++}`;
22201
+ seenCacheIds.set(pivotTable.cacheId, pivotTable.rId);
22202
+ relationships.push({
22203
+ Id: pivotTable.rId,
22204
+ Type: XLSX.RelType.PivotCacheDefinition,
22205
+ Target: pivotCacheDefinitionRelTargetFromWorkbook(pivotTable.tableNumber)
22206
+ });
22207
+ }
21383
22208
  });
21384
22209
  model.worksheets.forEach((worksheet, index) => {
21385
22210
  worksheet.rId = `rId${count++}`;
@@ -21455,7 +22280,7 @@ var ExcelTS = (function(exports) {
21455
22280
  if (drawing) {
21456
22281
  if (this.drawingHasChartReference(drawing) && rawDrawings[drawing.name]) zip.append(rawDrawings[drawing.name], { name: drawingPath(drawing.name) });
21457
22282
  else {
21458
- const filteredAnchors = (drawing.anchors || []).filter((a) => {
22283
+ const filteredAnchors = (drawing.anchors ?? []).filter((a) => {
21459
22284
  if (a == null) return false;
21460
22285
  if (a.range?.br && a.shape) return true;
21461
22286
  if (!a.br && !a.picture) return false;
@@ -21501,35 +22326,45 @@ var ExcelTS = (function(exports) {
21501
22326
  const pivotCacheDefinitionXform = new PivotCacheDefinitionXform();
21502
22327
  const pivotTableXform = new PivotTableXform();
21503
22328
  const relsXform = new RelationshipsXform();
22329
+ const writtenCaches = /* @__PURE__ */ new Map();
21504
22330
  model.pivotTables.forEach((pivotTable) => {
21505
22331
  const n = pivotTable.tableNumber;
21506
- if (pivotTable.isLoaded) {
21507
- if (pivotTable.cacheDefinition) {
21508
- const xml = pivotCacheDefinitionXform.toXml(pivotTable.cacheDefinition);
22332
+ const isLoaded = pivotTable.isLoaded;
22333
+ const cacheId = pivotTable.cacheId;
22334
+ if (!writtenCaches.has(cacheId)) {
22335
+ writtenCaches.set(cacheId, n);
22336
+ if (isLoaded) {
22337
+ if (pivotTable.cacheDefinition) {
22338
+ const xml = pivotCacheDefinitionXform.toXml(pivotTable.cacheDefinition);
22339
+ zip.append(xml, { name: pivotCacheDefinitionPath(n) });
22340
+ }
22341
+ if (pivotTable.cacheRecords) {
22342
+ const xml = pivotCacheRecordsXform.toXml(pivotTable.cacheRecords);
22343
+ zip.append(xml, { name: pivotCacheRecordsPath(n) });
22344
+ }
22345
+ } else {
22346
+ let xml = pivotCacheRecordsXform.toXml(pivotTable);
22347
+ zip.append(xml, { name: pivotCacheRecordsPath(n) });
22348
+ xml = pivotCacheDefinitionXform.toXml(pivotTable);
21509
22349
  zip.append(xml, { name: pivotCacheDefinitionPath(n) });
21510
22350
  }
21511
- if (pivotTable.cacheRecords) {
21512
- const xml = pivotCacheRecordsXform.toXml(pivotTable.cacheRecords);
21513
- zip.append(xml, { name: pivotCacheRecordsPath(n) });
22351
+ if (isLoaded ? !!pivotTable.cacheRecords : true) {
22352
+ const cacheRecordsRId = (isLoaded ? pivotTable.cacheDefinition?.rId : void 0) ?? "rId1";
22353
+ const xml = relsXform.toXml([{
22354
+ Id: cacheRecordsRId,
22355
+ Type: XLSX.RelType.PivotCacheRecords,
22356
+ Target: pivotCacheRecordsRelTarget(n)
22357
+ }]);
22358
+ zip.append(xml, { name: pivotCacheDefinitionRelsPath(n) });
21514
22359
  }
21515
- } else {
21516
- let xml = pivotCacheRecordsXform.toXml(pivotTable);
21517
- zip.append(xml, { name: pivotCacheRecordsPath(n) });
21518
- xml = pivotCacheDefinitionXform.toXml(pivotTable);
21519
- zip.append(xml, { name: pivotCacheDefinitionPath(n) });
21520
22360
  }
21521
- let xml = relsXform.toXml([{
21522
- Id: "rId1",
21523
- Type: XLSX.RelType.PivotCacheRecords,
21524
- Target: pivotCacheRecordsRelTarget(n)
21525
- }]);
21526
- zip.append(xml, { name: pivotCacheDefinitionRelsPath(n) });
21527
- xml = pivotTableXform.toXml(pivotTable);
22361
+ let xml = pivotTableXform.toXml(pivotTable);
21528
22362
  zip.append(xml, { name: pivotTablePath(n) });
22363
+ const cacheTableNumber = writtenCaches.get(cacheId);
21529
22364
  xml = relsXform.toXml([{
21530
22365
  Id: "rId1",
21531
22366
  Type: XLSX.RelType.PivotCacheDefinition,
21532
- Target: pivotCacheDefinitionRelTargetFromPivotTable(n)
22367
+ Target: pivotCacheDefinitionRelTargetFromPivotTable(cacheTableNumber)
21533
22368
  }]);
21534
22369
  zip.append(xml, { name: pivotTableRelsPath(n) });
21535
22370
  });
@@ -21544,10 +22379,10 @@ var ExcelTS = (function(exports) {
21544
22379
  });
21545
22380
  }
21546
22381
  prepareModel(model, options) {
21547
- model.creator = model.creator || "ExcelTS";
21548
- model.lastModifiedBy = model.lastModifiedBy || "ExcelTS";
21549
- model.created = model.created || /* @__PURE__ */ new Date();
21550
- model.modified = model.modified || /* @__PURE__ */ new Date();
22382
+ model.creator = model.creator ?? "ExcelTS";
22383
+ model.lastModifiedBy = model.lastModifiedBy ?? "ExcelTS";
22384
+ model.created = model.created ?? /* @__PURE__ */ new Date();
22385
+ model.modified = model.modified ?? /* @__PURE__ */ new Date();
21551
22386
  model.useSharedStrings = options.useSharedStrings !== void 0 ? options.useSharedStrings : true;
21552
22387
  model.useStyles = options.useStyles !== void 0 ? options.useStyles : true;
21553
22388
  model.sharedStrings = new SharedStringsXform();
@@ -22124,7 +22959,7 @@ var ExcelTS = (function(exports) {
22124
22959
  else if (result.isValid) validatedRows.push(row);
22125
22960
  else invalidRows.push({
22126
22961
  row: Object.values(row),
22127
- reason: result.reason || "Validation failed"
22962
+ reason: result.reason ?? "Validation failed"
22128
22963
  });
22129
22964
  }
22130
22965
  dataRows = validatedRows;
@@ -22154,7 +22989,7 @@ var ExcelTS = (function(exports) {
22154
22989
  else if (result.isValid) validatedRows.push(row);
22155
22990
  else arrayInvalidRows.push({
22156
22991
  row,
22157
- reason: result.reason || "Validation failed"
22992
+ reason: result.reason ?? "Validation failed"
22158
22993
  });
22159
22994
  }
22160
22995
  resultRows = validatedRows;
@@ -22764,8 +23599,8 @@ var ExcelTS = (function(exports) {
22764
23599
  const formatter = dateFormat ? DateFormatter.create(dateFormat, { utc: dateUTC }) : DateFormatter.iso(dateUTC);
22765
23600
  return function mapValue(value) {
22766
23601
  if (value) {
22767
- if (value.text || value.hyperlink) return value.hyperlink || value.text || "";
22768
- if (value.formula || value.result) return value.result || "";
23602
+ if (value.text || value.hyperlink) return value.hyperlink ?? value.text ?? "";
23603
+ if (value.formula || value.result) return value.result ?? "";
22769
23604
  if (value instanceof Date) return formatter.format(value);
22770
23605
  if (value.error) return value.error;
22771
23606
  if (typeof value === "object") return JSON.stringify(value);
@@ -23096,7 +23931,7 @@ var ExcelTS = (function(exports) {
23096
23931
  constructor(options) {
23097
23932
  this.id = options.id;
23098
23933
  this.name = options.name || `Sheet${this.id}`;
23099
- this.state = options.state || "visible";
23934
+ this.state = options.state ?? "visible";
23100
23935
  this._rows = [];
23101
23936
  this._columns = null;
23102
23937
  this._keys = {};
@@ -23158,11 +23993,11 @@ var ExcelTS = (function(exports) {
23158
23993
  rowBreaks: null,
23159
23994
  colBreaks: null
23160
23995
  }, options.pageSetup);
23161
- this.useSharedStrings = options.useSharedStrings || false;
23996
+ this.useSharedStrings = options.useSharedStrings ?? false;
23162
23997
  this._workbook = options.workbook;
23163
23998
  this.hasComments = false;
23164
- this._views = options.views || [];
23165
- this.autoFilter = options.autoFilter || null;
23999
+ this._views = options.views ?? [];
24000
+ this.autoFilter = options.autoFilter ?? null;
23166
24001
  this._media = [];
23167
24002
  this.sheetProtection = null;
23168
24003
  this._writeOpenWorksheet();
@@ -23525,10 +24360,10 @@ var ExcelTS = (function(exports) {
23525
24360
  this.WorksheetWriterClass = WorksheetWriterClass;
23526
24361
  this.created = options.created || /* @__PURE__ */ new Date();
23527
24362
  this.modified = options.modified || this.created;
23528
- this.creator = options.creator || "ExcelTS";
23529
- this.lastModifiedBy = options.lastModifiedBy || "ExcelTS";
24363
+ this.creator = options.creator ?? "ExcelTS";
24364
+ this.lastModifiedBy = options.lastModifiedBy ?? "ExcelTS";
23530
24365
  this.lastPrinted = options.lastPrinted;
23531
- this.useSharedStrings = options.useSharedStrings || false;
24366
+ this.useSharedStrings = options.useSharedStrings ?? false;
23532
24367
  this.sharedStrings = new SharedStrings();
23533
24368
  this.styles = options.useStyles ? new StylesXform(true) : new StylesXform.Mock(true);
23534
24369
  this._definedNames = new DefinedNames();
@@ -23640,7 +24475,7 @@ var ExcelTS = (function(exports) {
23640
24475
  };
23641
24476
  }
23642
24477
  const id = this.nextId;
23643
- name = name || `sheet${id}`;
24478
+ name = name ?? `sheet${id}`;
23644
24479
  const worksheet = new this.WorksheetWriterClass({
23645
24480
  id,
23646
24481
  name,
@@ -23971,7 +24806,7 @@ var ExcelTS = (function(exports) {
23971
24806
  return textDecoder.decode(pathBuffer);
23972
24807
  }
23973
24808
  function isZipUnicodeFlag(flags) {
23974
- return ((flags || 0) & 2048) !== 0;
24809
+ return ((flags ?? 0) & 2048) !== 0;
23975
24810
  }
23976
24811
  function isZipDirectoryPath(path) {
23977
24812
  if (path.length === 0) return false;
@@ -23989,8 +24824,8 @@ var ExcelTS = (function(exports) {
23989
24824
  };
23990
24825
  }
23991
24826
  function resolveZipEntryLastModifiedDateTime(vars, extraFields) {
23992
- const dosDate = vars.lastModifiedDate || 0;
23993
- const dosTime = vars.lastModifiedTime || 0;
24827
+ const dosDate = vars.lastModifiedDate ?? 0;
24828
+ const dosTime = vars.lastModifiedTime ?? 0;
23994
24829
  const dosDateTime = parseDosDateTimeUTC(dosDate, dosTime);
23995
24830
  const unixSecondsMtime = extraFields.mtimeUnixSeconds;
23996
24831
  if (unixSecondsMtime === void 0) return dosDateTime;
@@ -23998,10 +24833,10 @@ var ExcelTS = (function(exports) {
23998
24833
  }
23999
24834
  const parseExtraField = parseZipExtraFields;
24000
24835
  function hasDataDescriptorFlag(flags) {
24001
- return ((flags || 0) & 8) !== 0;
24836
+ return ((flags ?? 0) & 8) !== 0;
24002
24837
  }
24003
24838
  function isFileSizeKnown(flags, compressedSize) {
24004
- return !hasDataDescriptorFlag(flags) || (compressedSize || 0) > 0;
24839
+ return !hasDataDescriptorFlag(flags) || (compressedSize ?? 0) > 0;
24005
24840
  }
24006
24841
  function autodrain(stream) {
24007
24842
  const draining = stream.pipe(new Transform({ transform(_chunk, _encoding, callback) {
@@ -24033,8 +24868,8 @@ var ExcelTS = (function(exports) {
24033
24868
  async function readCrxHeader(pull) {
24034
24869
  const data = await pull(12);
24035
24870
  const header = data.length >= 12 ? parseCrxHeaderFast(data) : parseTyped(data, CRX_HEADER_FORMAT);
24036
- const pubKeyLength = header.pubKeyLength || 0;
24037
- const keyAndSig = await pull(pubKeyLength + (header.signatureLength || 0));
24871
+ const pubKeyLength = header.pubKeyLength ?? 0;
24872
+ const keyAndSig = await pull(pubKeyLength + (header.signatureLength ?? 0));
24038
24873
  header.publicKey = keyAndSig.subarray(0, pubKeyLength);
24039
24874
  header.signature = keyAndSig.subarray(pubKeyLength);
24040
24875
  return header;
@@ -24044,8 +24879,8 @@ var ExcelTS = (function(exports) {
24044
24879
  const vars = data.length >= 26 ? parseLocalFileHeaderVarsFast(data) : parseTyped(data, LOCAL_FILE_HEADER_FORMAT);
24045
24880
  return {
24046
24881
  vars,
24047
- fileNameBuffer: await pull(vars.fileNameLength || 0),
24048
- extraFieldData: await pull(vars.extraFieldLength || 0)
24882
+ fileNameBuffer: await pull(vars.fileNameLength ?? 0),
24883
+ extraFieldData: await pull(vars.extraFieldLength ?? 0)
24049
24884
  };
24050
24885
  }
24051
24886
  async function readDataDescriptor(pull) {
@@ -24054,12 +24889,12 @@ var ExcelTS = (function(exports) {
24054
24889
  }
24055
24890
  async function consumeCentralDirectoryFileHeader(pull) {
24056
24891
  const vars = parseTyped(await pull(42), CENTRAL_DIRECTORY_FILE_HEADER_FORMAT);
24057
- await pull(vars.fileNameLength || 0);
24058
- await pull(vars.extraFieldLength || 0);
24059
- await pull(vars.fileCommentLength || 0);
24892
+ await pull(vars.fileNameLength ?? 0);
24893
+ await pull(vars.extraFieldLength ?? 0);
24894
+ await pull(vars.fileCommentLength ?? 0);
24060
24895
  }
24061
24896
  async function consumeEndOfCentralDirectoryRecord(pull) {
24062
- await pull(parseTyped(await pull(18), END_OF_CENTRAL_DIRECTORY_FORMAT).commentLength || 0);
24897
+ await pull(parseTyped(await pull(18), END_OF_CENTRAL_DIRECTORY_FORMAT).commentLength ?? 0);
24063
24898
  }
24064
24899
  function isValidZipRecordSignature(sig) {
24065
24900
  switch (sig) {
@@ -24384,7 +25219,7 @@ var ExcelTS = (function(exports) {
24384
25219
  };
24385
25220
  entry.path = fileName;
24386
25221
  entry.props = buildZipEntryProps(fileName, fileNameBuffer, vars.flags);
24387
- entry.type = getZipEntryType(fileName, vars.uncompressedSize || 0);
25222
+ entry.type = getZipEntryType(fileName, vars.uncompressedSize ?? 0);
24388
25223
  if (opts.verbose) {
24389
25224
  if (entry.type === "Directory") console.log(" creating:", fileName);
24390
25225
  else if (entry.type === "File") if (vars.compressionMethod === 0) console.log(" extracting:", fileName);
@@ -24396,7 +25231,7 @@ var ExcelTS = (function(exports) {
24396
25231
  entry.extraFields = extra;
24397
25232
  entry.__autodraining = autodraining;
24398
25233
  const fileSizeKnown = isFileSizeKnown(vars.flags, vars.compressedSize);
24399
- if (fileSizeKnown) entry.size = vars.uncompressedSize || 0;
25234
+ if (fileSizeKnown) entry.size = vars.uncompressedSize ?? 0;
24400
25235
  if (opts.forceStream) emitter.pushEntry(entry);
24401
25236
  else {
24402
25237
  emitter.emitEntry(entry);
@@ -24408,8 +25243,8 @@ var ExcelTS = (function(exports) {
24408
25243
  extraFields: entry.extraFields
24409
25244
  });
24410
25245
  const sizesTrusted = !hasDataDescriptorFlag(vars.flags);
24411
- const compressedSize = vars.compressedSize || 0;
24412
- const uncompressedSize = vars.uncompressedSize || 0;
25246
+ const compressedSize = vars.compressedSize ?? 0;
25247
+ const uncompressedSize = vars.uncompressedSize ?? 0;
24413
25248
  if (sizesTrusted && fileSizeKnown && inflateRawSync && vars.compressionMethod !== 0 && !autodraining && compressedSize <= thresholdBytes && uncompressedSize <= thresholdBytes) {
24414
25249
  const decompressedData = inflateRawSync(await io.pull(compressedSize));
24415
25250
  entry.end(decompressedData);
@@ -24418,11 +25253,11 @@ var ExcelTS = (function(exports) {
24418
25253
  }
24419
25254
  const inflater = vars.compressionMethod && !autodraining ? inflateFactory() : new PassThrough({ highWaterMark: DEFAULT_UNZIP_STREAM_HIGH_WATER_MARK$1 });
24420
25255
  if (fileSizeKnown) {
24421
- await pumpKnownCompressedSizeToEntry(io, inflater, entry, vars.compressedSize || 0);
25256
+ await pumpKnownCompressedSizeToEntry(io, inflater, entry, vars.compressedSize ?? 0);
24422
25257
  return;
24423
25258
  }
24424
25259
  await pipeline(io.streamUntilDataDescriptor(), inflater, entry);
24425
- entry.size = (await readDataDescriptor(async (l) => io.pull(l))).uncompressedSize || 0;
25260
+ entry.size = (await readDataDescriptor(async (l) => io.pull(l))).uncompressedSize ?? 0;
24426
25261
  }
24427
25262
 
24428
25263
  //#endregion
@@ -24536,8 +25371,8 @@ var ExcelTS = (function(exports) {
24536
25371
  });
24537
25372
  }
24538
25373
  destroy(error) {
24539
- if (!this.writeClosed) this.writer.abort(error || void 0).catch(() => {});
24540
- this.reader.cancel(error || void 0).catch(() => {});
25374
+ if (!this.writeClosed) this.writer.abort(error ?? void 0).catch(() => {});
25375
+ this.reader.cancel(error ?? void 0).catch(() => {});
24541
25376
  return super.destroy(error);
24542
25377
  }
24543
25378
  };
@@ -24683,7 +25518,7 @@ onmessage = async (ev) => {
24683
25518
  }
24684
25519
  };
24685
25520
  this.worker.onerror = (e) => {
24686
- const err = new Error(e.message || "Worker error");
25521
+ const err = new Error(e.message ?? "Worker error");
24687
25522
  for (const cb of this._pendingAcks.values()) cb(err);
24688
25523
  this._pendingAcks.clear();
24689
25524
  this.emit("error", err);
@@ -25264,7 +26099,7 @@ onmessage = async (ev) => {
25264
26099
  min: parseInt(node.attributes.min, 10),
25265
26100
  max: parseInt(node.attributes.max, 10),
25266
26101
  width: parseFloat(node.attributes.width),
25267
- styleId: parseInt(node.attributes.style || "0", 10)
26102
+ styleId: parseInt(node.attributes.style ?? "0", 10)
25268
26103
  });
25269
26104
  break;
25270
26105
  case "row":
@@ -25592,7 +26427,7 @@ onmessage = async (ev) => {
25592
26427
  async _parseRels(entry) {
25593
26428
  this.workbookRels = await new RelationshipsXform().parseStream(iterateStream(entry));
25594
26429
  this._workbookRelIdByTarget = Object.create(null);
25595
- for (const rel of this.workbookRels || []) if (rel?.Target && rel?.Id) this._workbookRelIdByTarget[rel.Target] = rel.Id;
26430
+ for (const rel of this.workbookRels ?? []) if (rel?.Target && rel?.Id) this._workbookRelIdByTarget[rel.Target] = rel.Id;
25596
26431
  }
25597
26432
  async _parseWorkbook(entry) {
25598
26433
  this._emitEntry({ type: "workbook" });
@@ -25600,7 +26435,7 @@ onmessage = async (ev) => {
25600
26435
  this.model = await workbook.parseStream(iterateStream(entry));
25601
26436
  this.properties = workbook.map?.workbookPr;
25602
26437
  this._sheetByRelId = Object.create(null);
25603
- for (const sheet of this.model?.sheets || []) this._sheetByRelId[sheet.rId] = sheet;
26438
+ for (const sheet of this.model?.sheets ?? []) this._sheetByRelId[sheet.rId] = sheet;
25604
26439
  }
25605
26440
  async *_parseSharedStrings(entry) {
25606
26441
  this._emitEntry({ type: "shared-strings" });
@@ -25692,10 +26527,10 @@ onmessage = async (ev) => {
25692
26527
  }
25693
26528
  break;
25694
26529
  case "si":
25695
- if (this.options.sharedStrings === "cache") this.sharedStrings.push(richText.length ? { richText } : text || "");
26530
+ if (this.options.sharedStrings === "cache") this.sharedStrings.push(richText.length ? { richText } : text ?? "");
25696
26531
  else if (this.options.sharedStrings === "emit") yield {
25697
26532
  index: index++,
25698
- text: richText.length ? { richText } : text || ""
26533
+ text: richText.length ? { richText } : text ?? ""
25699
26534
  };
25700
26535
  richText = [];
25701
26536
  font = null;
@@ -26016,8 +26851,8 @@ onmessage = async (ev) => {
26016
26851
  }
26017
26852
  get model() {
26018
26853
  return {
26019
- creator: this.creator || "Unknown",
26020
- lastModifiedBy: this.lastModifiedBy || "Unknown",
26854
+ creator: this.creator ?? "Unknown",
26855
+ lastModifiedBy: this.lastModifiedBy ?? "Unknown",
26021
26856
  lastPrinted: this.lastPrinted,
26022
26857
  created: this.created,
26023
26858
  modified: this.modified,
@@ -26079,8 +26914,8 @@ onmessage = async (ev) => {
26079
26914
  this._definedNames.model = value.definedNames;
26080
26915
  this.views = value.views;
26081
26916
  this._themes = value.themes;
26082
- this.media = value.media || [];
26083
- this.pivotTables = value.pivotTables || value.loadedPivotTables || [];
26917
+ this.media = value.media ?? [];
26918
+ this.pivotTables = value.pivotTables ?? [];
26084
26919
  this._passthrough = value.passthrough || {};
26085
26920
  this._rawDrawings = value.rawDrawings || {};
26086
26921
  this._defaultFont = value.defaultFont;
@@ -26287,7 +27122,7 @@ onmessage = async (ev) => {
26287
27122
  * @param fmt The format string containing %
26288
27123
  */
26289
27124
  function formatPercentage(val, fmt) {
26290
- const percentCount = (fmt.match(/%/g) || []).length;
27125
+ const percentCount = (fmt.match(/%/g) ?? []).length;
26291
27126
  return formatNumberPattern(val * Math.pow(100, percentCount), fmt.replace(/%/g, "") || "0") + "%".repeat(percentCount);
26292
27127
  }
26293
27128
  /**
@@ -26442,7 +27277,7 @@ onmessage = async (ev) => {
26442
27277
  } else {
26443
27278
  formattedInt = intPart;
26444
27279
  if (intFmt.includes(",")) formattedInt = commaify(intPart);
26445
- const minIntDigits = (intFmt.match(/0/g) || []).length;
27280
+ const minIntDigits = (intFmt.match(/0/g) ?? []).length;
26446
27281
  if (formattedInt.length < minIntDigits) formattedInt = "0".repeat(minIntDigits - formattedInt.length) + formattedInt;
26447
27282
  }
26448
27283
  let formattedDec = "";