@trebco/treb 36.1.4 → 37.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (552) hide show
  1. package/api-config.json +1 -1
  2. package/build/package.json +119 -0
  3. package/build/treb-base-types/src/api_types.d.ts +11 -0
  4. package/build/treb-base-types/src/api_types.js +22 -0
  5. package/build/treb-base-types/src/api_types.js.map +1 -0
  6. package/build/treb-base-types/src/area-utils.d.ts +9 -0
  7. package/build/treb-base-types/src/area-utils.js +50 -0
  8. package/build/treb-base-types/src/area-utils.js.map +1 -0
  9. package/build/treb-base-types/src/area.d.ts +182 -0
  10. package/build/treb-base-types/src/area.js +715 -0
  11. package/build/treb-base-types/src/area.js.map +1 -0
  12. package/build/treb-base-types/src/basic_types.d.ts +20 -0
  13. package/build/treb-base-types/src/basic_types.js +22 -0
  14. package/build/treb-base-types/src/basic_types.js.map +1 -0
  15. package/build/treb-base-types/src/cell.d.ts +167 -0
  16. package/build/treb-base-types/src/cell.js +432 -0
  17. package/build/treb-base-types/src/cell.js.map +1 -0
  18. package/build/treb-base-types/src/cells.d.ts +251 -0
  19. package/build/treb-base-types/src/cells.js +1136 -0
  20. package/build/treb-base-types/src/cells.js.map +1 -0
  21. package/build/treb-base-types/src/color.d.ts +35 -0
  22. package/build/treb-base-types/src/color.js +162 -0
  23. package/build/treb-base-types/src/color.js.map +1 -0
  24. package/build/treb-base-types/src/dom-utilities.d.ts +70 -0
  25. package/build/treb-base-types/src/dom-utilities.js +144 -0
  26. package/build/treb-base-types/src/dom-utilities.js.map +1 -0
  27. package/build/treb-base-types/src/evaluate-options.d.ts +35 -0
  28. package/build/treb-base-types/src/evaluate-options.js +22 -0
  29. package/build/treb-base-types/src/evaluate-options.js.map +1 -0
  30. package/build/treb-base-types/src/font-stack.d.ts +37 -0
  31. package/build/treb-base-types/src/font-stack.js +93 -0
  32. package/build/treb-base-types/src/font-stack.js.map +1 -0
  33. package/build/treb-base-types/src/gradient.d.ts +18 -0
  34. package/build/treb-base-types/src/gradient.js +86 -0
  35. package/build/treb-base-types/src/gradient.js.map +1 -0
  36. package/build/treb-base-types/src/import.d.ts +48 -0
  37. package/build/treb-base-types/src/import.js +22 -0
  38. package/build/treb-base-types/src/import.js.map +1 -0
  39. package/build/treb-base-types/src/index-standalone.d.ts +6 -0
  40. package/build/treb-base-types/src/index-standalone.js +27 -0
  41. package/build/treb-base-types/src/index-standalone.js.map +1 -0
  42. package/build/treb-base-types/src/index.d.ts +22 -0
  43. package/build/treb-base-types/src/index.js +45 -0
  44. package/build/treb-base-types/src/index.js.map +1 -0
  45. package/build/treb-base-types/src/layout.d.ts +22 -0
  46. package/build/treb-base-types/src/layout.js +22 -0
  47. package/build/treb-base-types/src/layout.js.map +1 -0
  48. package/build/treb-base-types/src/localization.d.ts +37 -0
  49. package/build/treb-base-types/src/localization.js +157 -0
  50. package/build/treb-base-types/src/localization.js.map +1 -0
  51. package/build/treb-base-types/src/rectangle.d.ts +51 -0
  52. package/build/treb-base-types/src/rectangle.js +123 -0
  53. package/build/treb-base-types/src/rectangle.js.map +1 -0
  54. package/build/treb-base-types/src/render_text.d.ts +34 -0
  55. package/build/treb-base-types/src/render_text.js +22 -0
  56. package/build/treb-base-types/src/render_text.js.map +1 -0
  57. package/build/treb-base-types/src/style.d.ts +214 -0
  58. package/build/treb-base-types/src/style.js +373 -0
  59. package/build/treb-base-types/src/style.js.map +1 -0
  60. package/build/treb-base-types/src/table.d.ts +58 -0
  61. package/build/treb-base-types/src/table.js +27 -0
  62. package/build/treb-base-types/src/table.js.map +1 -0
  63. package/build/treb-base-types/src/text_part.d.ts +26 -0
  64. package/build/treb-base-types/src/text_part.js +47 -0
  65. package/build/treb-base-types/src/text_part.js.map +1 -0
  66. package/build/treb-base-types/src/theme.d.ts +120 -0
  67. package/build/treb-base-types/src/theme.js +460 -0
  68. package/build/treb-base-types/src/theme.js.map +1 -0
  69. package/build/treb-base-types/src/union.d.ts +73 -0
  70. package/build/treb-base-types/src/union.js +61 -0
  71. package/build/treb-base-types/src/union.js.map +1 -0
  72. package/build/treb-base-types/src/value-type.d.ts +86 -0
  73. package/build/treb-base-types/src/value-type.js +168 -0
  74. package/build/treb-base-types/src/value-type.js.map +1 -0
  75. package/build/treb-base-types/src/worker-proxy.d.ts +95 -0
  76. package/build/treb-base-types/src/worker-proxy.js +221 -0
  77. package/build/treb-base-types/src/worker-proxy.js.map +1 -0
  78. package/build/treb-calculator/src/calculator.d.ts +249 -0
  79. package/build/treb-calculator/src/calculator.js +2755 -0
  80. package/build/treb-calculator/src/calculator.js.map +1 -0
  81. package/build/treb-calculator/src/complex-math.d.ts +75 -0
  82. package/build/treb-calculator/src/complex-math.js +559 -0
  83. package/build/treb-calculator/src/complex-math.js.map +1 -0
  84. package/build/treb-calculator/src/dag/array-vertex.d.ts +71 -0
  85. package/build/treb-calculator/src/dag/array-vertex.js +156 -0
  86. package/build/treb-calculator/src/dag/array-vertex.js.map +1 -0
  87. package/build/treb-calculator/src/dag/calculation_leaf_vertex.d.ts +48 -0
  88. package/build/treb-calculator/src/dag/calculation_leaf_vertex.js +84 -0
  89. package/build/treb-calculator/src/dag/calculation_leaf_vertex.js.map +1 -0
  90. package/build/treb-calculator/src/dag/graph.d.ts +134 -0
  91. package/build/treb-calculator/src/dag/graph.js +842 -0
  92. package/build/treb-calculator/src/dag/graph.js.map +1 -0
  93. package/build/treb-calculator/src/dag/spreadsheet_vertex.d.ts +58 -0
  94. package/build/treb-calculator/src/dag/spreadsheet_vertex.js +232 -0
  95. package/build/treb-calculator/src/dag/spreadsheet_vertex.js.map +1 -0
  96. package/build/treb-calculator/src/dag/spreadsheet_vertex_base.d.ts +20 -0
  97. package/build/treb-calculator/src/dag/spreadsheet_vertex_base.js +25 -0
  98. package/build/treb-calculator/src/dag/spreadsheet_vertex_base.js.map +1 -0
  99. package/build/treb-calculator/src/dag/state_leaf_vertex.d.ts +43 -0
  100. package/build/treb-calculator/src/dag/state_leaf_vertex.js +81 -0
  101. package/build/treb-calculator/src/dag/state_leaf_vertex.js.map +1 -0
  102. package/build/treb-calculator/src/dag/vertex.d.ts +71 -0
  103. package/build/treb-calculator/src/dag/vertex.js +274 -0
  104. package/build/treb-calculator/src/dag/vertex.js.map +1 -0
  105. package/build/treb-calculator/src/descriptors.d.ts +189 -0
  106. package/build/treb-calculator/src/descriptors.js +22 -0
  107. package/build/treb-calculator/src/descriptors.js.map +1 -0
  108. package/build/treb-calculator/src/expression-calculator.d.ts +127 -0
  109. package/build/treb-calculator/src/expression-calculator.js +1033 -0
  110. package/build/treb-calculator/src/expression-calculator.js.map +1 -0
  111. package/build/treb-calculator/src/function-error.d.ts +35 -0
  112. package/build/treb-calculator/src/function-error.js +85 -0
  113. package/build/treb-calculator/src/function-error.js.map +1 -0
  114. package/build/treb-calculator/src/function-library.d.ts +22 -0
  115. package/build/treb-calculator/src/function-library.js +96 -0
  116. package/build/treb-calculator/src/function-library.js.map +1 -0
  117. package/build/treb-calculator/src/functions/base-functions.d.ts +7 -0
  118. package/build/treb-calculator/src/functions/base-functions.js +2611 -0
  119. package/build/treb-calculator/src/functions/base-functions.js.map +1 -0
  120. package/build/treb-calculator/src/functions/beta.d.ts +17 -0
  121. package/build/treb-calculator/src/functions/beta.js +201 -0
  122. package/build/treb-calculator/src/functions/beta.js.map +1 -0
  123. package/build/treb-calculator/src/functions/checkbox.d.ts +3 -0
  124. package/build/treb-calculator/src/functions/checkbox.js +128 -0
  125. package/build/treb-calculator/src/functions/checkbox.js.map +1 -0
  126. package/build/treb-calculator/src/functions/complex-functions.d.ts +2 -0
  127. package/build/treb-calculator/src/functions/complex-functions.js +217 -0
  128. package/build/treb-calculator/src/functions/complex-functions.js.map +1 -0
  129. package/build/treb-calculator/src/functions/date-utils.d.ts +3 -0
  130. package/build/treb-calculator/src/functions/date-utils.js +59 -0
  131. package/build/treb-calculator/src/functions/date-utils.js.map +1 -0
  132. package/build/treb-calculator/src/functions/finance-functions.d.ts +2 -0
  133. package/build/treb-calculator/src/functions/finance-functions.js +547 -0
  134. package/build/treb-calculator/src/functions/finance-functions.js.map +1 -0
  135. package/build/treb-calculator/src/functions/fp.d.ts +2 -0
  136. package/build/treb-calculator/src/functions/fp.js +463 -0
  137. package/build/treb-calculator/src/functions/fp.js.map +1 -0
  138. package/build/treb-calculator/src/functions/function-utilities.d.ts +2 -0
  139. package/build/treb-calculator/src/functions/function-utilities.js +36 -0
  140. package/build/treb-calculator/src/functions/function-utilities.js.map +1 -0
  141. package/build/treb-calculator/src/functions/gamma.d.ts +20 -0
  142. package/build/treb-calculator/src/functions/gamma.js +142 -0
  143. package/build/treb-calculator/src/functions/gamma.js.map +1 -0
  144. package/build/treb-calculator/src/functions/information-functions.d.ts +2 -0
  145. package/build/treb-calculator/src/functions/information-functions.js +71 -0
  146. package/build/treb-calculator/src/functions/information-functions.js.map +1 -0
  147. package/build/treb-calculator/src/functions/lambda-functions.d.ts +2 -0
  148. package/build/treb-calculator/src/functions/lambda-functions.js +85 -0
  149. package/build/treb-calculator/src/functions/lambda-functions.js.map +1 -0
  150. package/build/treb-calculator/src/functions/matrix-functions.d.ts +2 -0
  151. package/build/treb-calculator/src/functions/matrix-functions.js +144 -0
  152. package/build/treb-calculator/src/functions/matrix-functions.js.map +1 -0
  153. package/build/treb-calculator/src/functions/normal.d.ts +2 -0
  154. package/build/treb-calculator/src/functions/normal.js +32 -0
  155. package/build/treb-calculator/src/functions/normal.js.map +1 -0
  156. package/build/treb-calculator/src/functions/regex-functions.d.ts +2 -0
  157. package/build/treb-calculator/src/functions/regex-functions.js +188 -0
  158. package/build/treb-calculator/src/functions/regex-functions.js.map +1 -0
  159. package/build/treb-calculator/src/functions/sparkline.d.ts +37 -0
  160. package/build/treb-calculator/src/functions/sparkline.js +264 -0
  161. package/build/treb-calculator/src/functions/sparkline.js.map +1 -0
  162. package/build/treb-calculator/src/functions/statistics-functions.d.ts +6 -0
  163. package/build/treb-calculator/src/functions/statistics-functions.js +989 -0
  164. package/build/treb-calculator/src/functions/statistics-functions.js.map +1 -0
  165. package/build/treb-calculator/src/functions/students-t.d.ts +3 -0
  166. package/build/treb-calculator/src/functions/students-t.js +64 -0
  167. package/build/treb-calculator/src/functions/students-t.js.map +1 -0
  168. package/build/treb-calculator/src/functions/text-functions.d.ts +3 -0
  169. package/build/treb-calculator/src/functions/text-functions.js +320 -0
  170. package/build/treb-calculator/src/functions/text-functions.js.map +1 -0
  171. package/build/treb-calculator/src/index.d.ts +2 -0
  172. package/build/treb-calculator/src/index.js +22 -0
  173. package/build/treb-calculator/src/index.js.map +1 -0
  174. package/build/treb-calculator/src/notifier-types.d.ts +26 -0
  175. package/build/treb-calculator/src/notifier-types.js +22 -0
  176. package/build/treb-calculator/src/notifier-types.js.map +1 -0
  177. package/build/treb-calculator/src/primitives.d.ts +15 -0
  178. package/build/treb-calculator/src/primitives.js +398 -0
  179. package/build/treb-calculator/src/primitives.js.map +1 -0
  180. package/build/treb-calculator/src/utilities.d.ts +68 -0
  181. package/build/treb-calculator/src/utilities.js +324 -0
  182. package/build/treb-calculator/src/utilities.js.map +1 -0
  183. package/build/treb-charts/src/chart-functions.d.ts +8 -0
  184. package/build/treb-charts/src/chart-functions.js +209 -0
  185. package/build/treb-charts/src/chart-functions.js.map +1 -0
  186. package/build/treb-charts/src/chart-types.d.ts +233 -0
  187. package/build/treb-charts/src/chart-types.js +57 -0
  188. package/build/treb-charts/src/chart-types.js.map +1 -0
  189. package/build/treb-charts/src/chart-utils.d.ts +106 -0
  190. package/build/treb-charts/src/chart-utils.js +1060 -0
  191. package/build/treb-charts/src/chart-utils.js.map +1 -0
  192. package/build/treb-charts/src/chart.d.ts +23 -0
  193. package/build/treb-charts/src/chart.js +94 -0
  194. package/build/treb-charts/src/chart.js.map +1 -0
  195. package/build/treb-charts/src/default-chart-renderer.d.ts +16 -0
  196. package/build/treb-charts/src/default-chart-renderer.js +533 -0
  197. package/build/treb-charts/src/default-chart-renderer.js.map +1 -0
  198. package/build/treb-charts/src/index.d.ts +5 -0
  199. package/build/treb-charts/src/index.js +24 -0
  200. package/build/treb-charts/src/index.js.map +1 -0
  201. package/build/treb-charts/src/main.d.ts +1 -0
  202. package/build/treb-charts/src/main.js +34 -0
  203. package/build/treb-charts/src/main.js.map +1 -0
  204. package/build/treb-charts/src/quicksort.d.ts +1 -0
  205. package/build/treb-charts/src/quicksort.js +49 -0
  206. package/build/treb-charts/src/quicksort.js.map +1 -0
  207. package/build/treb-charts/src/rectangle.d.ts +18 -0
  208. package/build/treb-charts/src/rectangle.js +41 -0
  209. package/build/treb-charts/src/rectangle.js.map +1 -0
  210. package/build/treb-charts/src/renderer-type.d.ts +24 -0
  211. package/build/treb-charts/src/renderer-type.js +22 -0
  212. package/build/treb-charts/src/renderer-type.js.map +1 -0
  213. package/build/treb-charts/src/renderer.d.ts +127 -0
  214. package/build/treb-charts/src/renderer.js +1518 -0
  215. package/build/treb-charts/src/renderer.js.map +1 -0
  216. package/build/treb-charts/src/util.d.ts +18 -0
  217. package/build/treb-charts/src/util.js +71 -0
  218. package/build/treb-charts/src/util.js.map +1 -0
  219. package/build/treb-data-model/src/annotation.d.ts +167 -0
  220. package/build/treb-data-model/src/annotation.js +120 -0
  221. package/build/treb-data-model/src/annotation.js.map +1 -0
  222. package/build/treb-data-model/src/conditional_format.d.ts +155 -0
  223. package/build/treb-data-model/src/conditional_format.js +62 -0
  224. package/build/treb-data-model/src/conditional_format.js.map +1 -0
  225. package/build/treb-data-model/src/data-validation.d.ts +28 -0
  226. package/build/treb-data-model/src/data-validation.js +22 -0
  227. package/build/treb-data-model/src/data-validation.js.map +1 -0
  228. package/build/treb-data-model/src/data_model.d.ts +173 -0
  229. package/build/treb-data-model/src/data_model.js +637 -0
  230. package/build/treb-data-model/src/data_model.js.map +1 -0
  231. package/build/treb-data-model/src/index.d.ts +13 -0
  232. package/build/treb-data-model/src/index.js +28 -0
  233. package/build/treb-data-model/src/index.js.map +1 -0
  234. package/build/treb-data-model/src/language-model.d.ts +22 -0
  235. package/build/treb-data-model/src/language-model.js +22 -0
  236. package/build/treb-data-model/src/language-model.js.map +1 -0
  237. package/build/treb-data-model/src/named.d.ts +124 -0
  238. package/build/treb-data-model/src/named.js +372 -0
  239. package/build/treb-data-model/src/named.js.map +1 -0
  240. package/build/treb-data-model/src/serialize_options.d.ts +49 -0
  241. package/build/treb-data-model/src/serialize_options.js +22 -0
  242. package/build/treb-data-model/src/serialize_options.js.map +1 -0
  243. package/build/treb-data-model/src/sheet.d.ts +499 -0
  244. package/build/treb-data-model/src/sheet.js +2904 -0
  245. package/build/treb-data-model/src/sheet.js.map +1 -0
  246. package/build/treb-data-model/src/sheet_collection.d.ts +58 -0
  247. package/build/treb-data-model/src/sheet_collection.js +112 -0
  248. package/build/treb-data-model/src/sheet_collection.js.map +1 -0
  249. package/build/treb-data-model/src/sheet_selection.d.ts +42 -0
  250. package/build/treb-data-model/src/sheet_selection.js +39 -0
  251. package/build/treb-data-model/src/sheet_selection.js.map +1 -0
  252. package/build/treb-data-model/src/sheet_types.d.ts +104 -0
  253. package/build/treb-data-model/src/sheet_types.js +22 -0
  254. package/build/treb-data-model/src/sheet_types.js.map +1 -0
  255. package/build/treb-data-model/src/types.d.ts +59 -0
  256. package/build/treb-data-model/src/types.js +22 -0
  257. package/build/treb-data-model/src/types.js.map +1 -0
  258. package/build/treb-embed/src/custom-element/spreadsheet-constructor.d.ts +75 -0
  259. package/build/treb-embed/src/custom-element/spreadsheet-constructor.js +1144 -0
  260. package/build/treb-embed/src/custom-element/spreadsheet-constructor.js.map +1 -0
  261. package/build/treb-embed/src/custom-element/treb-global.d.ts +36 -0
  262. package/build/treb-embed/src/custom-element/treb-global.js +64 -0
  263. package/build/treb-embed/src/custom-element/treb-global.js.map +1 -0
  264. package/build/treb-embed/src/custom-element/treb-spreadsheet-element.d.ts +1 -0
  265. package/build/treb-embed/src/custom-element/treb-spreadsheet-element.js +61 -0
  266. package/build/treb-embed/src/custom-element/treb-spreadsheet-element.js.map +1 -0
  267. package/build/treb-embed/src/embedded-spreadsheet.d.ts +1358 -0
  268. package/build/treb-embed/src/embedded-spreadsheet.js +5205 -0
  269. package/build/treb-embed/src/embedded-spreadsheet.js.map +1 -0
  270. package/build/treb-embed/src/index.d.ts +12 -0
  271. package/build/treb-embed/src/index.js +34 -0
  272. package/build/treb-embed/src/index.js.map +1 -0
  273. package/build/treb-embed/src/options.d.ts +266 -0
  274. package/build/treb-embed/src/options.js +56 -0
  275. package/build/treb-embed/src/options.js.map +1 -0
  276. package/build/treb-embed/src/plugin.d.ts +9 -0
  277. package/build/treb-embed/src/plugin.js +22 -0
  278. package/build/treb-embed/src/plugin.js.map +1 -0
  279. package/build/treb-embed/src/progress-dialog.d.ts +49 -0
  280. package/build/treb-embed/src/progress-dialog.js +178 -0
  281. package/build/treb-embed/src/progress-dialog.js.map +1 -0
  282. package/build/treb-embed/src/selection-state.d.ts +15 -0
  283. package/build/treb-embed/src/selection-state.js +22 -0
  284. package/build/treb-embed/src/selection-state.js.map +1 -0
  285. package/build/treb-embed/src/spinner.d.ts +8 -0
  286. package/build/treb-embed/src/spinner.js +40 -0
  287. package/build/treb-embed/src/spinner.js.map +1 -0
  288. package/build/treb-embed/src/toolbar-message.d.ts +72 -0
  289. package/build/treb-embed/src/toolbar-message.js +22 -0
  290. package/build/treb-embed/src/toolbar-message.js.map +1 -0
  291. package/build/treb-embed/src/types.d.ts +185 -0
  292. package/build/treb-embed/src/types.js +45 -0
  293. package/build/treb-embed/src/types.js.map +1 -0
  294. package/build/treb-embed/tsconfig.tsbuildinfo +1 -0
  295. package/build/treb-export/src/address-type.d.ts +34 -0
  296. package/build/treb-export/src/address-type.js +53 -0
  297. package/build/treb-export/src/address-type.js.map +1 -0
  298. package/build/treb-export/src/base-template.d.ts +1 -0
  299. package/build/treb-export/src/base-template.js +22 -0
  300. package/build/treb-export/src/base-template.js.map +1 -0
  301. package/build/treb-export/src/column-width.d.ts +2 -0
  302. package/build/treb-export/src/column-width.js +80 -0
  303. package/build/treb-export/src/column-width.js.map +1 -0
  304. package/build/treb-export/src/drawing/bubble-chart-template.d.ts +514 -0
  305. package/build/treb-export/src/drawing/bubble-chart-template.js +544 -0
  306. package/build/treb-export/src/drawing/bubble-chart-template.js.map +1 -0
  307. package/build/treb-export/src/drawing/chart-template-components2.d.ts +365 -0
  308. package/build/treb-export/src/drawing/chart-template-components2.js +386 -0
  309. package/build/treb-export/src/drawing/chart-template-components2.js.map +1 -0
  310. package/build/treb-export/src/drawing/chart.d.ts +26 -0
  311. package/build/treb-export/src/drawing/chart.js +247 -0
  312. package/build/treb-export/src/drawing/chart.js.map +1 -0
  313. package/build/treb-export/src/drawing/column-chart-template2.d.ts +490 -0
  314. package/build/treb-export/src/drawing/column-chart-template2.js +518 -0
  315. package/build/treb-export/src/drawing/column-chart-template2.js.map +1 -0
  316. package/build/treb-export/src/drawing/donut-chart-template2.d.ts +272 -0
  317. package/build/treb-export/src/drawing/donut-chart-template2.js +293 -0
  318. package/build/treb-export/src/drawing/donut-chart-template2.js.map +1 -0
  319. package/build/treb-export/src/drawing/drawing.d.ts +49 -0
  320. package/build/treb-export/src/drawing/drawing.js +193 -0
  321. package/build/treb-export/src/drawing/drawing.js.map +1 -0
  322. package/build/treb-export/src/drawing/embedded-image.d.ts +12 -0
  323. package/build/treb-export/src/drawing/embedded-image.js +54 -0
  324. package/build/treb-export/src/drawing/embedded-image.js.map +1 -0
  325. package/build/treb-export/src/drawing/scatter-chart-template2.d.ts +520 -0
  326. package/build/treb-export/src/drawing/scatter-chart-template2.js +551 -0
  327. package/build/treb-export/src/drawing/scatter-chart-template2.js.map +1 -0
  328. package/build/treb-export/src/export.d.ts +72 -0
  329. package/build/treb-export/src/export.js +2039 -0
  330. package/build/treb-export/src/export.js.map +1 -0
  331. package/build/treb-export/src/import-export-messages.d.ts +31 -0
  332. package/build/treb-export/src/import-export-messages.js +22 -0
  333. package/build/treb-export/src/import-export-messages.js.map +1 -0
  334. package/build/treb-export/src/import.d.ts +33 -0
  335. package/build/treb-export/src/import.js +1258 -0
  336. package/build/treb-export/src/import.js.map +1 -0
  337. package/build/treb-export/src/index.worker.d.ts +1 -0
  338. package/build/treb-export/src/index.worker.js +93 -0
  339. package/build/treb-export/src/index.worker.js.map +1 -0
  340. package/build/treb-export/src/metadata.d.ts +51 -0
  341. package/build/treb-export/src/metadata.js +153 -0
  342. package/build/treb-export/src/metadata.js.map +1 -0
  343. package/build/treb-export/src/ooxml.d.ts +7 -0
  344. package/build/treb-export/src/ooxml.js +41 -0
  345. package/build/treb-export/src/ooxml.js.map +1 -0
  346. package/build/treb-export/src/relationship.d.ts +8 -0
  347. package/build/treb-export/src/relationship.js +27 -0
  348. package/build/treb-export/src/relationship.js.map +1 -0
  349. package/build/treb-export/src/shared-strings.d.ts +11 -0
  350. package/build/treb-export/src/shared-strings.js +105 -0
  351. package/build/treb-export/src/shared-strings.js.map +1 -0
  352. package/build/treb-export/src/template-2.d.ts +1 -0
  353. package/build/treb-export/src/template-2.js +22 -0
  354. package/build/treb-export/src/template-2.js.map +1 -0
  355. package/build/treb-export/src/unescape_xml.d.ts +1 -0
  356. package/build/treb-export/src/unescape_xml.js +61 -0
  357. package/build/treb-export/src/unescape_xml.js.map +1 -0
  358. package/build/treb-export/src/workbook-sheet.d.ts +75 -0
  359. package/build/treb-export/src/workbook-sheet.js +128 -0
  360. package/build/treb-export/src/workbook-sheet.js.map +1 -0
  361. package/build/treb-export/src/workbook-style.d.ts +110 -0
  362. package/build/treb-export/src/workbook-style.js +1134 -0
  363. package/build/treb-export/src/workbook-style.js.map +1 -0
  364. package/build/treb-export/src/workbook-theme.d.ts +13 -0
  365. package/build/treb-export/src/workbook-theme.js +85 -0
  366. package/build/treb-export/src/workbook-theme.js.map +1 -0
  367. package/build/treb-export/src/workbook.d.ts +123 -0
  368. package/build/treb-export/src/workbook.js +644 -0
  369. package/build/treb-export/src/workbook.js.map +1 -0
  370. package/build/treb-export/src/xml-test.d.ts +9 -0
  371. package/build/treb-export/src/xml-test.js +52 -0
  372. package/build/treb-export/src/xml-test.js.map +1 -0
  373. package/build/treb-export/src/xml-utils.d.ts +76 -0
  374. package/build/treb-export/src/xml-utils.js +223 -0
  375. package/build/treb-export/src/xml-utils.js.map +1 -0
  376. package/build/treb-export/src/zip-wrapper.d.ts +22 -0
  377. package/build/treb-export/src/zip-wrapper.js +93 -0
  378. package/build/treb-export/src/zip-wrapper.js.map +1 -0
  379. package/build/treb-format/src/format.d.ts +130 -0
  380. package/build/treb-format/src/format.js +805 -0
  381. package/build/treb-format/src/format.js.map +1 -0
  382. package/build/treb-format/src/format_cache.d.ts +55 -0
  383. package/build/treb-format/src/format_cache.js +166 -0
  384. package/build/treb-format/src/format_cache.js.map +1 -0
  385. package/build/treb-format/src/format_parser.d.ts +70 -0
  386. package/build/treb-format/src/format_parser.js +618 -0
  387. package/build/treb-format/src/format_parser.js.map +1 -0
  388. package/build/treb-format/src/index.d.ts +4 -0
  389. package/build/treb-format/src/index.js +25 -0
  390. package/build/treb-format/src/index.js.map +1 -0
  391. package/build/treb-format/src/number_format_section.d.ts +58 -0
  392. package/build/treb-format/src/number_format_section.js +78 -0
  393. package/build/treb-format/src/number_format_section.js.map +1 -0
  394. package/build/treb-format/src/value_parser.d.ts +48 -0
  395. package/build/treb-format/src/value_parser.js +244 -0
  396. package/build/treb-format/src/value_parser.js.map +1 -0
  397. package/build/treb-grid/src/editors/autocomplete.d.ts +39 -0
  398. package/build/treb-grid/src/editors/autocomplete.js +316 -0
  399. package/build/treb-grid/src/editors/autocomplete.js.map +1 -0
  400. package/build/treb-grid/src/editors/autocomplete_matcher.d.ts +74 -0
  401. package/build/treb-grid/src/editors/autocomplete_matcher.js +212 -0
  402. package/build/treb-grid/src/editors/autocomplete_matcher.js.map +1 -0
  403. package/build/treb-grid/src/editors/editor.d.ts +214 -0
  404. package/build/treb-grid/src/editors/editor.js +879 -0
  405. package/build/treb-grid/src/editors/editor.js.map +1 -0
  406. package/build/treb-grid/src/editors/external_editor.d.ts +11 -0
  407. package/build/treb-grid/src/editors/external_editor.js +118 -0
  408. package/build/treb-grid/src/editors/external_editor.js.map +1 -0
  409. package/build/treb-grid/src/editors/formula_bar.d.ts +85 -0
  410. package/build/treb-grid/src/editors/formula_bar.js +444 -0
  411. package/build/treb-grid/src/editors/formula_bar.js.map +1 -0
  412. package/build/treb-grid/src/editors/overlay_editor.d.ts +85 -0
  413. package/build/treb-grid/src/editors/overlay_editor.js +353 -0
  414. package/build/treb-grid/src/editors/overlay_editor.js.map +1 -0
  415. package/build/treb-grid/src/index.d.ts +12 -0
  416. package/build/treb-grid/src/index.js +28 -0
  417. package/build/treb-grid/src/index.js.map +1 -0
  418. package/build/treb-grid/src/layout/base_layout.d.ts +346 -0
  419. package/build/treb-grid/src/layout/base_layout.js +2050 -0
  420. package/build/treb-grid/src/layout/base_layout.js.map +1 -0
  421. package/build/treb-grid/src/layout/grid_layout.d.ts +19 -0
  422. package/build/treb-grid/src/layout/grid_layout.js +235 -0
  423. package/build/treb-grid/src/layout/grid_layout.js.map +1 -0
  424. package/build/treb-grid/src/layout/mock-layout.d.ts +10 -0
  425. package/build/treb-grid/src/layout/mock-layout.js +37 -0
  426. package/build/treb-grid/src/layout/mock-layout.js.map +1 -0
  427. package/build/treb-grid/src/render/selection-renderer.d.ts +97 -0
  428. package/build/treb-grid/src/render/selection-renderer.js +315 -0
  429. package/build/treb-grid/src/render/selection-renderer.js.map +1 -0
  430. package/build/treb-grid/src/render/svg_header_overlay.d.ts +20 -0
  431. package/build/treb-grid/src/render/svg_header_overlay.js +76 -0
  432. package/build/treb-grid/src/render/svg_header_overlay.js.map +1 -0
  433. package/build/treb-grid/src/render/svg_selection_block.d.ts +27 -0
  434. package/build/treb-grid/src/render/svg_selection_block.js +106 -0
  435. package/build/treb-grid/src/render/svg_selection_block.js.map +1 -0
  436. package/build/treb-grid/src/render/tile_renderer.d.ts +121 -0
  437. package/build/treb-grid/src/render/tile_renderer.js +1609 -0
  438. package/build/treb-grid/src/render/tile_renderer.js.map +1 -0
  439. package/build/treb-grid/src/types/border_constants.d.ts +9 -0
  440. package/build/treb-grid/src/types/border_constants.js +34 -0
  441. package/build/treb-grid/src/types/border_constants.js.map +1 -0
  442. package/build/treb-grid/src/types/clipboard_data.d.ts +11 -0
  443. package/build/treb-grid/src/types/clipboard_data.js +22 -0
  444. package/build/treb-grid/src/types/clipboard_data.js.map +1 -0
  445. package/build/treb-grid/src/types/clipboard_data2.d.ts +46 -0
  446. package/build/treb-grid/src/types/clipboard_data2.js +22 -0
  447. package/build/treb-grid/src/types/clipboard_data2.js.map +1 -0
  448. package/build/treb-grid/src/types/drag_mask.d.ts +10 -0
  449. package/build/treb-grid/src/types/drag_mask.js +78 -0
  450. package/build/treb-grid/src/types/drag_mask.js.map +1 -0
  451. package/build/treb-grid/src/types/external_editor_config.d.ts +33 -0
  452. package/build/treb-grid/src/types/external_editor_config.js +22 -0
  453. package/build/treb-grid/src/types/external_editor_config.js.map +1 -0
  454. package/build/treb-grid/src/types/grid.d.ts +806 -0
  455. package/build/treb-grid/src/types/grid.js +6410 -0
  456. package/build/treb-grid/src/types/grid.js.map +1 -0
  457. package/build/treb-grid/src/types/grid_base.d.ts +442 -0
  458. package/build/treb-grid/src/types/grid_base.js +3523 -0
  459. package/build/treb-grid/src/types/grid_base.js.map +1 -0
  460. package/build/treb-grid/src/types/grid_command.d.ts +408 -0
  461. package/build/treb-grid/src/types/grid_command.js +75 -0
  462. package/build/treb-grid/src/types/grid_command.js.map +1 -0
  463. package/build/treb-grid/src/types/grid_events.d.ts +93 -0
  464. package/build/treb-grid/src/types/grid_events.js +36 -0
  465. package/build/treb-grid/src/types/grid_events.js.map +1 -0
  466. package/build/treb-grid/src/types/grid_options.d.ts +50 -0
  467. package/build/treb-grid/src/types/grid_options.js +34 -0
  468. package/build/treb-grid/src/types/grid_options.js.map +1 -0
  469. package/build/treb-grid/src/types/scale-control.d.ts +21 -0
  470. package/build/treb-grid/src/types/scale-control.js +148 -0
  471. package/build/treb-grid/src/types/scale-control.js.map +1 -0
  472. package/build/treb-grid/src/types/set_range_options.d.ts +24 -0
  473. package/build/treb-grid/src/types/set_range_options.js +22 -0
  474. package/build/treb-grid/src/types/set_range_options.js.map +1 -0
  475. package/build/treb-grid/src/types/tab_bar.d.ts +84 -0
  476. package/build/treb-grid/src/types/tab_bar.js +426 -0
  477. package/build/treb-grid/src/types/tab_bar.js.map +1 -0
  478. package/build/treb-grid/src/types/tile.d.ts +29 -0
  479. package/build/treb-grid/src/types/tile.js +22 -0
  480. package/build/treb-grid/src/types/tile.js.map +1 -0
  481. package/build/treb-grid/src/types/update_flags.d.ts +48 -0
  482. package/build/treb-grid/src/types/update_flags.js +22 -0
  483. package/build/treb-grid/src/types/update_flags.js.map +1 -0
  484. package/build/treb-grid/src/util/fontmetrics.d.ts +21 -0
  485. package/build/treb-grid/src/util/fontmetrics.js +82 -0
  486. package/build/treb-grid/src/util/fontmetrics.js.map +1 -0
  487. package/build/treb-grid/src/util/ua.d.ts +33 -0
  488. package/build/treb-grid/src/util/ua.js +86 -0
  489. package/build/treb-grid/src/util/ua.js.map +1 -0
  490. package/build/treb-parser/src/csv-parser.d.ts +13 -0
  491. package/build/treb-parser/src/csv-parser.js +107 -0
  492. package/build/treb-parser/src/csv-parser.js.map +1 -0
  493. package/build/treb-parser/src/index.d.ts +4 -0
  494. package/build/treb-parser/src/index.js +25 -0
  495. package/build/treb-parser/src/index.js.map +1 -0
  496. package/build/treb-parser/src/md-parser.d.ts +97 -0
  497. package/build/treb-parser/src/md-parser.js +403 -0
  498. package/build/treb-parser/src/md-parser.js.map +1 -0
  499. package/build/treb-parser/src/parser-types.d.ts +345 -0
  500. package/build/treb-parser/src/parser-types.js +53 -0
  501. package/build/treb-parser/src/parser-types.js.map +1 -0
  502. package/build/treb-parser/src/parser.d.ts +422 -0
  503. package/build/treb-parser/src/parser.js +2418 -0
  504. package/build/treb-parser/src/parser.js.map +1 -0
  505. package/build/treb-utils/src/event_source.d.ts +34 -0
  506. package/build/treb-utils/src/event_source.js +110 -0
  507. package/build/treb-utils/src/event_source.js.map +1 -0
  508. package/build/treb-utils/src/ievent_source.d.ts +9 -0
  509. package/build/treb-utils/src/ievent_source.js +22 -0
  510. package/build/treb-utils/src/ievent_source.js.map +1 -0
  511. package/build/treb-utils/src/index.d.ts +6 -0
  512. package/build/treb-utils/src/index.js +30 -0
  513. package/build/treb-utils/src/index.js.map +1 -0
  514. package/build/treb-utils/src/measurement.d.ts +42 -0
  515. package/build/treb-utils/src/measurement.js +145 -0
  516. package/build/treb-utils/src/measurement.js.map +1 -0
  517. package/build/treb-utils/src/scale.d.ts +16 -0
  518. package/build/treb-utils/src/scale.js +106 -0
  519. package/build/treb-utils/src/scale.js.map +1 -0
  520. package/build/treb-utils/src/serialize_html.d.ts +5 -0
  521. package/build/treb-utils/src/serialize_html.js +128 -0
  522. package/build/treb-utils/src/serialize_html.js.map +1 -0
  523. package/build/treb-utils/src/validate_uri.d.ts +20 -0
  524. package/build/treb-utils/src/validate_uri.js +55 -0
  525. package/build/treb-utils/src/validate_uri.js.map +1 -0
  526. package/dist/{chunk-Z4XFMZ2X.mjs → chunk-E35ONJUS.mjs} +1 -1
  527. package/dist/treb-export-worker.mjs +2 -2
  528. package/dist/treb-spreadsheet.mjs +4 -4
  529. package/dist/treb.d.ts +1 -1
  530. package/esbuild-composite.mjs +5 -1
  531. package/package.json +67 -3
  532. package/treb-embed/src/custom-element/spreadsheet-constructor.ts +7 -3
  533. package/treb-embed/src/embedded-spreadsheet.ts +1 -1
  534. package/treb-grid/src/types/grid_options.ts +1 -1
  535. package/tsproject.json +1 -2
  536. package/dist/chunk-43DLP2OX.mjs +0 -11
  537. package/dist/chunk-4CKS56PE.mjs +0 -11
  538. package/dist/chunk-75PARUQE.mjs +0 -11
  539. package/dist/chunk-7QD63AZS.mjs +0 -24601
  540. package/dist/chunk-A55ARVRD.mjs +0 -11
  541. package/dist/chunk-DESAKYW4.mjs +0 -11
  542. package/dist/chunk-EQ2R5W6P.mjs +0 -24565
  543. package/dist/chunk-IYJU2J6D.mjs +0 -24601
  544. package/dist/chunk-KSJFPGXT.mjs +0 -11
  545. package/dist/chunk-MQK4DNXI.mjs +0 -11
  546. package/dist/chunk-ORQFKLXM.mjs +0 -24601
  547. package/dist/chunk-SFDNNDHY.mjs +0 -11
  548. package/dist/chunk-T47DX5MI.mjs +0 -11
  549. package/dist/chunk-T6ILBVEX.mjs +0 -11
  550. package/dist/chunk-TPRCDYYG.mjs +0 -11
  551. package/dist/chunk-YAHNOOHO.mjs +0 -11
  552. package/dist/chunk-YLCFKX2G.mjs +0 -24601
@@ -0,0 +1,2039 @@
1
+ /*
2
+ * This file is part of TREB.
3
+ *
4
+ * TREB is free software: you can redistribute it and/or modify it under the
5
+ * terms of the GNU General Public License as published by the Free Software
6
+ * Foundation, either version 3 of the License, or (at your option) any
7
+ * later version.
8
+ *
9
+ * TREB is distributed in the hope that it will be useful, but WITHOUT ANY
10
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
+ * details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License along
15
+ * with TREB. If not, see <https://www.gnu.org/licenses/>.
16
+ *
17
+ * Copyright 2022-2026 trebco, llc.
18
+ * info@treb.app
19
+ *
20
+ */
21
+ /**
22
+ * rewrite of export. we'll still use a template, but do more direct
23
+ * writing and less DOM manipulation. this should be cleaner in the long
24
+ * run, but it will take a bit more work.
25
+ */
26
+ // import JSZip from 'jszip';
27
+ import * as Base64JS from 'base64-js';
28
+ import { PixelsToColumnWidth } from './column-width';
29
+ const XMLDeclaration = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n`;
30
+ import { template } from './template-2';
31
+ import { Area, Cells, ValueType, Style, IsHTMLColor, IsThemeColor, ThemeColorIndex } from 'treb-base-types';
32
+ import { SharedStrings } from './shared-strings';
33
+ import { StyleCache } from './workbook-style';
34
+ import { Theme } from './workbook-theme';
35
+ import { AddRel } from './relationship';
36
+ import { PatchXMLBuilder } from './xml-utils';
37
+ import { Parser } from 'treb-parser';
38
+ import { Chart } from './drawing/chart';
39
+ import { Drawing } from './drawing/drawing';
40
+ import { ConditionalFormatOperators } from './workbook';
41
+ import { ZipWrapper } from './zip-wrapper';
42
+ import { ooxml_parser } from './ooxml';
43
+ /*
44
+ interface NestedDOMType {
45
+ [index: string]: string|number|NestedDOMType|NestedDOMType[];
46
+ }
47
+ */
48
+ /**
49
+ * utility function. given a Color object (our Color, from Style) returns
50
+ * an XML structure like
51
+ *
52
+ * { a$: { rgb: '123456 }}
53
+ *
54
+ * or
55
+ *
56
+ * { a$: { theme: 1, tint: .5 }}
57
+ *
58
+ */
59
+ const ColorAttrs = (color) => {
60
+ if (IsHTMLColor(color)) {
61
+ return {
62
+ a$: {
63
+ rgb: `FF` + color.text.substring(1),
64
+ },
65
+ };
66
+ }
67
+ if (IsThemeColor(color)) {
68
+ return {
69
+ a$: {
70
+ theme: ThemeColorIndex(color),
71
+ tint: color.tint,
72
+ },
73
+ };
74
+ }
75
+ return undefined;
76
+ };
77
+ export class Exporter {
78
+ // public zip?: JSZip;
79
+ zip;
80
+ xmloptions = {
81
+ format: true,
82
+ attributesGroupName: 'a$',
83
+ textNodeName: 't$',
84
+ ignoreAttributes: false,
85
+ suppressEmptyNode: true,
86
+ // OK so now I am turning this off altogether. not sure why we
87
+ // were using it in the first place -- which is a problem, since
88
+ // there's probably something I don't know.
89
+ /*
90
+ tagValueProcessor: (name: string, a: string) => {
91
+
92
+ // we were including unsafe symbols here, but that was
93
+ // resulting in double-encoding. not sure why this is
94
+ // here at all, unless we need it for unicode? in any
95
+ // event (atm) allowing unsafe symbols is sufficient
96
+
97
+ return a; // ?
98
+
99
+ return (typeof a === 'string') ? he.encode(a, { useNamedReferences: true, allowUnsafeSymbols: true }) : a;
100
+ },
101
+ */
102
+ // there's a "isAttributeValue" for decode, but no option for encode?
103
+ // we only want to encode ' and "
104
+ // attrValueProcessor: a => (typeof a === 'string') ? he.encode(a, { useNamedReferences: true }) : a,
105
+ // why is this double-encoding? is there arlready implicit encoding? (...)
106
+ // there must have been a reason we used it in the first place... but I don't know what that was.
107
+ // do we need to encode apostrophes?
108
+ // attributeValueProcessor: (name: string, a: string) => (typeof a === 'string') ?
109
+ // a.replace(/"/g, '&quot;').replace(/'/g, '&apos;') : a,
110
+ };
111
+ // public xmlparser = new xmlparser.j2xParser(this.xmloptions);
112
+ xmlbuilder1 = PatchXMLBuilder(this.xmloptions);
113
+ // public xmlparser2 = new XMLParser(XMLOptions2);
114
+ // FIXME: need a way to share/pass parser flags
115
+ parser = new Parser();
116
+ decorated_functions = {};
117
+ /*
118
+ constructor() {
119
+
120
+ }
121
+ */
122
+ /**
123
+ * init used to load the template file. we added a parameter to
124
+ * pass in the list of functions that need decoration (_xlfn).
125
+ *
126
+ * @param decorated_functions
127
+ */
128
+ Init(decorated_functions = {}) {
129
+ for (const key of Object.keys(decorated_functions)) {
130
+ this.decorated_functions[key.toLowerCase()] = decorated_functions[key]; // normalized
131
+ }
132
+ const parsed = Base64JS.toByteArray(template);
133
+ this.zip = new ZipWrapper(parsed.buffer);
134
+ }
135
+ WriteRels(rels, path, dump = false) {
136
+ if (!this.zip) {
137
+ throw new Error('missing zip');
138
+ }
139
+ const keys = Object.keys(rels);
140
+ const dom = {
141
+ Relationships: {
142
+ a$: {
143
+ xmlns: 'http://schemas.openxmlformats.org/package/2006/relationships',
144
+ },
145
+ Relationship: keys.map(key => {
146
+ const rel = rels[key];
147
+ const a$ = {
148
+ Id: rel.id,
149
+ Target: rel.target,
150
+ Type: rel.type,
151
+ };
152
+ if (rel.mode) {
153
+ a$.TargetMode = rel.mode;
154
+ }
155
+ return { a$ };
156
+ }),
157
+ },
158
+ };
159
+ const xml = XMLDeclaration + this.xmlbuilder1.build(dom);
160
+ // console.info({dom, xml});
161
+ if (dump) {
162
+ console.info(xml);
163
+ }
164
+ this.zip.Set(path, xml);
165
+ }
166
+ /**
167
+ * format and write styles
168
+ */
169
+ WriteStyleCache(style_cache) {
170
+ if (!this.zip) {
171
+ throw new Error('missing zip');
172
+ }
173
+ const ColorAttributes = (color) => {
174
+ // we could just pass through except that we have argb and excel has rgb
175
+ const attrs = {};
176
+ if (color.indexed !== undefined) {
177
+ attrs.indexed = color.indexed;
178
+ }
179
+ if (color.theme !== undefined) {
180
+ attrs.theme = color.theme;
181
+ }
182
+ if (color.tint !== undefined) {
183
+ attrs.tint = color.tint;
184
+ }
185
+ if (color.argb !== undefined) {
186
+ attrs.rgb = color.argb;
187
+ }
188
+ return attrs;
189
+ };
190
+ const xfs = style_cache.cell_xfs.map(xf => {
191
+ const block = {
192
+ a$: {
193
+ numFmtId: xf.number_format,
194
+ fontId: xf.font,
195
+ fillId: xf.fill,
196
+ borderId: xf.border,
197
+ },
198
+ };
199
+ if (xf.horizontal_alignment || xf.vertical_alignment || xf.wrap_text || xf.indent) {
200
+ const attrs = {};
201
+ if (xf.horizontal_alignment) {
202
+ attrs.horizontal = xf.horizontal_alignment;
203
+ }
204
+ if (xf.vertical_alignment) {
205
+ attrs.vertical = xf.vertical_alignment;
206
+ }
207
+ if (xf.wrap_text) {
208
+ attrs.wrapText = 1;
209
+ }
210
+ if (xf.indent && xf.horizontal_alignment !== 'center') {
211
+ attrs.indent = xf.indent;
212
+ }
213
+ block.alignment = { a$: attrs };
214
+ }
215
+ return block;
216
+ });
217
+ const BorderColorAttributes = (edge) => {
218
+ if (edge.color) {
219
+ return { indexed: edge.color };
220
+ }
221
+ if (edge.rgba) {
222
+ return { rgb: edge.rgba };
223
+ }
224
+ if (typeof edge.theme !== 'undefined') {
225
+ return {
226
+ theme: edge.theme,
227
+ tint: edge.tint,
228
+ };
229
+ }
230
+ return undefined;
231
+ };
232
+ const borders = style_cache.borders.map(border => {
233
+ const top = {};
234
+ const left = {};
235
+ const right = {};
236
+ const bottom = {};
237
+ const diagonal = {};
238
+ if (border.top.style) {
239
+ top.a$ = {
240
+ style: border.top.style,
241
+ };
242
+ const attrs = BorderColorAttributes(border.top);
243
+ if (attrs) {
244
+ top.color = { a$: attrs };
245
+ }
246
+ }
247
+ if (border.left.style) {
248
+ left.a$ = {
249
+ style: border.left.style,
250
+ };
251
+ const attrs = BorderColorAttributes(border.left);
252
+ if (attrs) {
253
+ left.color = { a$: attrs };
254
+ }
255
+ }
256
+ if (border.bottom.style) {
257
+ bottom.a$ = {
258
+ style: border.bottom.style,
259
+ };
260
+ const attrs = BorderColorAttributes(border.bottom);
261
+ if (attrs) {
262
+ bottom.color = { a$: attrs };
263
+ }
264
+ }
265
+ if (border.right.style) {
266
+ right.a$ = {
267
+ style: border.right.style,
268
+ };
269
+ const attrs = BorderColorAttributes(border.right);
270
+ if (attrs) {
271
+ right.color = { a$: attrs };
272
+ }
273
+ }
274
+ if (border.diagonal.style) {
275
+ diagonal.a$ = {
276
+ style: border.diagonal.style,
277
+ };
278
+ const attrs = BorderColorAttributes(border.diagonal);
279
+ if (attrs) {
280
+ diagonal.color = { a$: attrs };
281
+ }
282
+ }
283
+ return {
284
+ left,
285
+ right,
286
+ top,
287
+ bottom,
288
+ diagonal,
289
+ };
290
+ });
291
+ const fills = style_cache.fills.map(fill => ({
292
+ patternFill: {
293
+ a$: {
294
+ patternType: (fill.pattern_gray !== undefined) ? `gray${fill.pattern_gray}` : fill.pattern_type,
295
+ },
296
+ bgColor: fill.bg_color ? {
297
+ a$: ColorAttributes(fill.bg_color),
298
+ } : undefined,
299
+ fgColor: fill.fg_color ? {
300
+ a$: ColorAttributes(fill.fg_color),
301
+ } : undefined,
302
+ },
303
+ }));
304
+ const ValProp = (prop) => {
305
+ if (typeof prop === 'undefined') {
306
+ return undefined;
307
+ }
308
+ return {
309
+ a$: {
310
+ val: prop,
311
+ },
312
+ };
313
+ };
314
+ // console.info({style_cache});
315
+ const fonts = style_cache.fonts.map(font => {
316
+ return {
317
+ // flags
318
+ b: font.bold ? '' : undefined,
319
+ i: font.italic ? '' : undefined,
320
+ u: font.underline ? '' : undefined,
321
+ strike: font.strike ? '' : undefined,
322
+ // 'val' props
323
+ sz: ValProp(font.size),
324
+ family: ValProp(font.family),
325
+ name: ValProp(font.name),
326
+ scheme: ValProp(font.scheme),
327
+ color: font.color_argb ? {
328
+ a$: { rgb: font.color_argb },
329
+ } : (typeof font.color_theme !== 'undefined') ? {
330
+ a$: {
331
+ theme: font.color_theme,
332
+ tint: font.color_tint,
333
+ },
334
+ } : undefined,
335
+ };
336
+ });
337
+ const WithCount = (key, source) => {
338
+ if (source.length) {
339
+ return {
340
+ a$: { count: source.length },
341
+ [key]: source,
342
+ };
343
+ }
344
+ return undefined;
345
+ };
346
+ const dxf = style_cache.dxf_styles.map(style => {
347
+ const entry = {};
348
+ if (style.text || style.bold || style.italic || style.underline) {
349
+ entry.font = {
350
+ b: style.bold ? {} : undefined,
351
+ i: style.italic ? {} : undefined,
352
+ u: style.underline ? {} : undefined,
353
+ strike: style.strike ? {} : undefined,
354
+ color: ColorAttrs(style.text),
355
+ };
356
+ }
357
+ if (style.fill) {
358
+ entry.fill = {
359
+ patternFill: {
360
+ bgColor: ColorAttrs(style.fill),
361
+ }
362
+ };
363
+ }
364
+ ;
365
+ return entry;
366
+ });
367
+ // console.info({dxf});
368
+ const dom = {
369
+ styleSheet: {
370
+ a$: {
371
+ 'xmlns': 'http://schemas.openxmlformats.org/spreadsheetml/2006/main',
372
+ 'xmlns:mc': 'http://schemas.openxmlformats.org/markup-compatibility/2006',
373
+ 'mc:Ignorable': 'x14ac x16r2 xr',
374
+ 'xmlns:x14ac': 'http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac',
375
+ 'xmlns:x16r2': 'http://schemas.microsoft.com/office/spreadsheetml/2015/02/main',
376
+ 'xmlns:xr': 'http://schemas.microsoft.com/office/spreadsheetml/2014/revision',
377
+ },
378
+ // we're only adding elements here if they are not empty, but in
379
+ // practice only numFmts can be empty (because there are implicit
380
+ // formats); everything else has a default 0 entry
381
+ numFmts: style_cache.number_formats.length ? {
382
+ a$: { count: style_cache.number_formats.length },
383
+ numFmt: style_cache.number_formats.map(format => {
384
+ return {
385
+ a$: {
386
+ numFmtId: format.id,
387
+ formatCode: format.format,
388
+ },
389
+ };
390
+ }),
391
+ } : undefined,
392
+ fonts: WithCount('font', fonts),
393
+ fills: WithCount('fill', fills),
394
+ borders: WithCount('border', borders),
395
+ cellXfs: WithCount('xf', xfs),
396
+ dxfs: WithCount('dxf', dxf),
397
+ },
398
+ };
399
+ const xml = XMLDeclaration + this.xmlbuilder1.build(dom);
400
+ // console.info(xml);
401
+ this.zip?.Set('xl/styles.xml', xml);
402
+ }
403
+ /**
404
+ * format and write shared strings file to the zip archive. this will
405
+ * replace any existing shared strings file.
406
+ */
407
+ WriteSharedStrings(shared_strings) {
408
+ // console.info({shared_strings});
409
+ if (!this.zip) {
410
+ throw new Error('missing zip');
411
+ }
412
+ const dom = {
413
+ sst: {
414
+ a$: {
415
+ 'xmlns': 'http://schemas.openxmlformats.org/spreadsheetml/2006/main',
416
+ count: shared_strings.strings.length,
417
+ uniqueCount: shared_strings.strings.length,
418
+ },
419
+ si: [
420
+ ...shared_strings.strings.map(t => { return { t }; }),
421
+ ],
422
+ },
423
+ };
424
+ const xml = XMLDeclaration + this.xmlbuilder1.build(dom);
425
+ // console.info(xml);
426
+ this.zip.Set('xl/sharedStrings.xml', xml);
427
+ }
428
+ /**
429
+ * FIXME: we might not always need this.
430
+ */
431
+ SheetStyle(sheet, style_cache) {
432
+ if (!sheet.sheet_style) {
433
+ return 0;
434
+ }
435
+ const options = style_cache.StyleOptionsFromProperties(sheet.sheet_style);
436
+ return style_cache.EnsureStyle(options);
437
+ }
438
+ RowStyle(sheet, style_cache, row) {
439
+ const cell_style_refs = sheet.styles || sheet.cell_style_refs || [];
440
+ const list = [sheet.sheet_style];
441
+ if (sheet.row_style) {
442
+ let style = sheet.row_style[row];
443
+ if (typeof style === 'number') {
444
+ style = cell_style_refs[style];
445
+ if (style) {
446
+ list.push(style);
447
+ }
448
+ }
449
+ else if (style) {
450
+ list.push(style);
451
+ }
452
+ }
453
+ const options = style_cache.StyleOptionsFromProperties(Style.Composite(list));
454
+ return style_cache.EnsureStyle(options);
455
+ }
456
+ ColumnStyle(sheet, style_cache, column) {
457
+ const cell_style_refs = sheet.styles || sheet.cell_style_refs || [];
458
+ const list = [sheet.sheet_style];
459
+ if (sheet.column_style) {
460
+ let style = sheet.column_style[column];
461
+ if (typeof style === 'number') {
462
+ style = cell_style_refs[style];
463
+ if (style) {
464
+ list.push(style);
465
+ }
466
+ }
467
+ else if (style) {
468
+ list.push(style);
469
+ }
470
+ }
471
+ const options = style_cache.StyleOptionsFromProperties(Style.Composite(list));
472
+ return style_cache.EnsureStyle(options);
473
+ }
474
+ StyleFromCell(sheet, style_cache, row, column, style = {}) {
475
+ //if (row === 2 && column === 5)
476
+ // console.info("SFC", JSON.stringify(style, undefined, 2));
477
+ const cell_style_refs = sheet.styles || sheet.cell_style_refs || [];
478
+ const list = [sheet.sheet_style];
479
+ /*
480
+ // should apply to rows, not cells
481
+
482
+ if (sheet.row_pattern && sheet.row_pattern.length) {
483
+ list.push(sheet.row_pattern[row % sheet.row_pattern.length]);
484
+ }
485
+ */
486
+ // is this backwards, vis a vis our rendering? I think it might be...
487
+ // YES: should be row pattern -> row -> column -> cell [corrected]
488
+ // FIXME: can't we just ask the sheet? (A: no, because we don't have
489
+ // an actual sheet, although we could?)
490
+ // if (sheet.row_style && sheet.row_style[row]) {
491
+ // list.push(sheet.row_style[row]);
492
+ // }
493
+ if (sheet.row_style) {
494
+ let style = sheet.row_style[row];
495
+ if (typeof style === 'number') {
496
+ style = cell_style_refs[style];
497
+ if (style) {
498
+ list.push(style);
499
+ }
500
+ }
501
+ else if (style) {
502
+ list.push(style);
503
+ }
504
+ }
505
+ // this can now be a number, and possibly 0 (?)
506
+ // actually 0 is by default a null style, although that's more of
507
+ // a convention than a hard rule, not sure we should rely on it
508
+ if (sheet.column_style) {
509
+ let style = sheet.column_style[column];
510
+ if (typeof style === 'number') {
511
+ style = cell_style_refs[style];
512
+ if (style) {
513
+ list.push(style);
514
+ }
515
+ }
516
+ else if (style) {
517
+ list.push(style);
518
+ }
519
+ }
520
+ //if (sheet.column_style && sheet.column_style[column]) {
521
+ // list.push(sheet.column_style[column]);
522
+ //}
523
+ /*
524
+ if (cell.ref) {
525
+ list.push(sheet_source.cell_style_refs[cell.ref]);
526
+ }
527
+ else if (cell.style_ref) {
528
+ list.push(sheet_source.cell_style_refs[cell.style_ref]);
529
+ }
530
+ else if (style_map[cell.column] && style_map[cell.column][cell.row]) {
531
+ list.push(style_map[cell.column][cell.row]);
532
+ }
533
+ */
534
+ list.push(style);
535
+ const options = style_cache.StyleOptionsFromProperties(Style.Composite(list));
536
+ return style_cache.EnsureStyle(options);
537
+ }
538
+ /**
539
+ * for charts we need addresses to be absolute ($) and ensure there's
540
+ * a sheet name -- use the active sheet if it's not explicitly referenced
541
+ */
542
+ NormalizeAddress(unit, sheet) {
543
+ const addresses = (unit.type === 'address') ? [unit] : [unit.start, unit.end];
544
+ for (const address of addresses) {
545
+ address.absolute_row = true;
546
+ address.absolute_column = true;
547
+ if (!address.sheet) {
548
+ address.sheet = sheet.name;
549
+ }
550
+ }
551
+ if (unit.type === 'range') {
552
+ unit.end.sheet = undefined;
553
+ }
554
+ unit.label = this.parser.Render(unit);
555
+ return unit; // fluent
556
+ }
557
+ EnsureRange(unit) {
558
+ if (unit.type === 'range') {
559
+ return unit;
560
+ }
561
+ return {
562
+ type: 'range',
563
+ start: unit,
564
+ end: unit,
565
+ label: unit.label,
566
+ id: unit.id,
567
+ position: unit.position,
568
+ };
569
+ }
570
+ /**
571
+ * new-style annotation layout (kind of a two-cell anchor) to two-cell anchor
572
+ */
573
+ AnnotationLayoutToAnchor(layout, sheet) {
574
+ // our offsets are % of cell. their offsets are in excel units,
575
+ // but when the chart is added our method will convert from pixels.
576
+ const address_to_anchor = (corner) => {
577
+ const width = (sheet.column_width && sheet.column_width[corner.address.column]) ?
578
+ sheet.column_width[corner.address.column] : (sheet.default_column_width || 100);
579
+ const height = (sheet.row_height && sheet.row_height[corner.address.row]) ?
580
+ sheet.row_height[corner.address.row] : (sheet.default_row_height || 20);
581
+ return {
582
+ ...corner.address,
583
+ row_offset: Math.round(corner.offset.y * height),
584
+ column_offset: Math.round(corner.offset.x * width),
585
+ };
586
+ };
587
+ return {
588
+ from: address_to_anchor(layout.tl),
589
+ to: address_to_anchor(layout.br),
590
+ };
591
+ }
592
+ /**
593
+ * convert a rectangle (pixels) to a two-cell anchor. note that
594
+ * our offsets are in pixels, they'll need to be changed to whatever
595
+ * the target units are.
596
+ */
597
+ AnnotationRectToAnchor(src_rect, sheet) {
598
+ const anchor = {
599
+ from: { row: -1, column: -1 },
600
+ to: { row: -1, column: -1 },
601
+ };
602
+ const annotation_rect = {
603
+ top: 0, left: 0, width: 301, height: 301,
604
+ ...src_rect,
605
+ };
606
+ const rect = {
607
+ ...annotation_rect, // {top, left, width, height}
608
+ right: annotation_rect.left + annotation_rect.width,
609
+ bottom: annotation_rect.top + annotation_rect.height,
610
+ };
611
+ for (let x = 0, column = 0; column < 1000; column++) {
612
+ const width = (sheet.column_width && sheet.column_width[column]) ? sheet.column_width[column] : (sheet.default_column_width || 100);
613
+ if (anchor.from.column < 0 && rect.left <= x + width) {
614
+ anchor.from.column = column;
615
+ anchor.from.column_offset = (rect.left - x);
616
+ }
617
+ if (anchor.to.column < 0 && rect.right <= x + width) {
618
+ anchor.to.column = column;
619
+ anchor.to.column_offset = (rect.right - x);
620
+ break;
621
+ }
622
+ x += width;
623
+ }
624
+ for (let y = 0, row = 0; row < 1000; row++) {
625
+ const height = (sheet.row_height && sheet.row_height[row]) ? sheet.row_height[row] : (sheet.default_row_height || 20);
626
+ if (anchor.from.row < 0 && rect.top <= y + height) {
627
+ anchor.from.row = row;
628
+ anchor.from.row_offset = (rect.top - y);
629
+ }
630
+ if (anchor.to.row < 0 && rect.bottom <= y + height) {
631
+ anchor.to.row = row;
632
+ anchor.to.row_offset = (rect.bottom - y);
633
+ break;
634
+ }
635
+ y += height;
636
+ }
637
+ return anchor;
638
+ }
639
+ ParseImages(sheet_source) {
640
+ const images = [];
641
+ for (const annotation of sheet_source.annotations || []) {
642
+ if (annotation.type === 'image' && annotation.data?.src) {
643
+ // this is (should be) a data URI in base64. at least (atm)
644
+ // that's all we support for exporting.
645
+ const src = annotation.data.src;
646
+ const match = src.match(/^data:image\/([^;]*?);base64,/);
647
+ if (match) {
648
+ const data = src.substr(match[0].length);
649
+ const mimetype = match[1];
650
+ const options = {
651
+ data,
652
+ mimetype,
653
+ encoding: 'base64',
654
+ };
655
+ switch (mimetype) {
656
+ case 'svg+xml':
657
+ case 'webp':
658
+ case 'jpeg':
659
+ case 'jpg':
660
+ case 'image/png':
661
+ case 'png':
662
+ case 'gif':
663
+ if (annotation.layout) {
664
+ images.push({
665
+ anchor: this.AnnotationLayoutToAnchor(annotation.layout, sheet_source), options
666
+ });
667
+ }
668
+ else if (annotation.rect) {
669
+ images.push({
670
+ anchor: this.AnnotationRectToAnchor(annotation.rect, sheet_source), options
671
+ });
672
+ }
673
+ else {
674
+ console.warn('annotation missing layout');
675
+ }
676
+ break;
677
+ default:
678
+ console.info('unhandled image type', mimetype);
679
+ break;
680
+ }
681
+ }
682
+ }
683
+ }
684
+ return images;
685
+ }
686
+ ParseCharts(sheet_source) {
687
+ const charts = [];
688
+ const parse_series = (arg, options, ref) => {
689
+ if (arg.type === 'range') {
690
+ options.data.push(this.NormalizeAddress(arg, sheet_source));
691
+ }
692
+ else if (arg.type === 'call') {
693
+ if (/group/i.test(arg.name)) {
694
+ // recurse
695
+ for (const value of (arg.args || [])) {
696
+ parse_series(value, options, ref ? ref + ` (recurse)` : undefined);
697
+ }
698
+ }
699
+ else if (/series/i.test(arg.name)) {
700
+ const [label, x, y, z] = arg.args; // y is required
701
+ // FIXME: could be address also [x, y]
702
+ if (y && (y.type === 'range' || y.type === 'address')) {
703
+ options.data.push(this.EnsureRange(this.NormalizeAddress(y, sheet_source)));
704
+ if (label) {
705
+ if (!options.names) {
706
+ options.names = [];
707
+ }
708
+ if (label.type === 'address') {
709
+ this.NormalizeAddress(label, sheet_source);
710
+ }
711
+ if (label.type === 'range') {
712
+ this.NormalizeAddress(label.start, sheet_source);
713
+ options.names[options.data.length - 1] = label.start;
714
+ }
715
+ else {
716
+ options.names[options.data.length - 1] = label;
717
+ }
718
+ }
719
+ if (!options.labels2) {
720
+ options.labels2 = [];
721
+ }
722
+ if (x && (x.type === 'range' || x.type === 'address')) {
723
+ options.labels2[options.data.length - 1] = this.EnsureRange(this.NormalizeAddress(x, sheet_source));
724
+ }
725
+ if (z && (z.type === 'range' || z.type === 'address')) {
726
+ if (!options.labels3) {
727
+ options.labels3 = [];
728
+ }
729
+ options.labels3[options.data.length - 1] = this.EnsureRange(this.NormalizeAddress(z, sheet_source));
730
+ }
731
+ }
732
+ else {
733
+ console.info('invalid series missing Y', { y, arg, ref });
734
+ }
735
+ }
736
+ }
737
+ };
738
+ for (const annotation of sheet_source.annotations || []) {
739
+ const parse_result = this.parser.Parse(annotation.formula || '');
740
+ if (parse_result.expression && parse_result.expression.type === 'call') {
741
+ let type = ''; // FIXME
742
+ switch (parse_result.expression.name.toLowerCase()) {
743
+ case 'line.chart':
744
+ type = 'scatter';
745
+ break;
746
+ case 'bubble.chart':
747
+ type = 'bubble';
748
+ break;
749
+ case 'scatter.line':
750
+ type = 'scatter2';
751
+ break;
752
+ case 'donut.chart':
753
+ type = 'donut';
754
+ break;
755
+ case 'bar.chart':
756
+ type = 'bar';
757
+ break;
758
+ case 'column.chart':
759
+ type = 'column';
760
+ break;
761
+ }
762
+ if (type === 'column' || type === 'donut' || type === 'bar' || type === 'scatter' || type === 'scatter2' || type === 'bubble') {
763
+ const options = { type, data: [] };
764
+ const title_index = (type === 'scatter2' || type === 'bubble') ? 1 : 2;
765
+ const title_arg = parse_result.expression.args[title_index];
766
+ if (title_arg && title_arg.type === 'literal') {
767
+ options.title = title_arg;
768
+ }
769
+ else if (title_arg && title_arg.type === 'address') {
770
+ options.title = this.NormalizeAddress(title_arg, sheet_source);
771
+ }
772
+ else {
773
+ // FIXME: formula here will not work. we need to bring
774
+ // a calculator into this class? (!) or somehow cache the value...
775
+ // console.info('chart title arg', title_arg)
776
+ }
777
+ // we changed our Series() to Group(), and then added a new Series()
778
+ // function which adds data labels and per-series X values... will
779
+ // need to incorporate somehow. for now, just s/series/group to get
780
+ // the data in the chart
781
+ // oh we already did that... duh
782
+ if (parse_result.expression.args[0]) {
783
+ const arg0 = parse_result.expression.args[0];
784
+ if (type === 'scatter2' || type === 'bar' || type === 'column' || type === 'scatter' || type === 'bubble') {
785
+ parse_series(arg0, options, sheet_source.name);
786
+ }
787
+ else if (arg0.type === 'range') {
788
+ options.data.push(this.NormalizeAddress(arg0, sheet_source));
789
+ }
790
+ // so the next cases cannot happen? (...) donut? (...)
791
+ else if (arg0.type === 'call' && /group/i.test(arg0.name)) {
792
+ for (const series of arg0.args) {
793
+ // in group, could be a range or a Series()
794
+ if (series.type === 'range') {
795
+ options.data.push(this.NormalizeAddress(series, sheet_source));
796
+ }
797
+ else if (series.type === 'call' && /series/i.test(series.name)) {
798
+ // in Series(), args are (name, X, range of data)
799
+ if (series.args[2] && series.args[2].type === 'range') {
800
+ options.data.push(this.NormalizeAddress(series.args[2], sheet_source));
801
+ }
802
+ }
803
+ }
804
+ }
805
+ else if (arg0.type === 'call' && /series/i.test(arg0.name)) {
806
+ // another case, single Series()
807
+ if (arg0.args[2] && arg0.args[2].type === 'range') {
808
+ options.data.push(this.NormalizeAddress(arg0.args[2], sheet_source));
809
+ }
810
+ }
811
+ /*
812
+ else if (arg0.type === 'call' && /series/i.test(arg0.name)) {
813
+ for (const series of arg0.args) {
814
+ if (series.type === 'range') {
815
+ options.data.push(this.NormalizeAddress(series, sheet_source));
816
+ }
817
+ }
818
+ }
819
+ */
820
+ }
821
+ if (type !== 'scatter2' && type !== 'bubble') {
822
+ if (parse_result.expression.args[1] && parse_result.expression.args[1].type === 'range') {
823
+ options.labels = this.NormalizeAddress(parse_result.expression.args[1], sheet_source);
824
+ }
825
+ }
826
+ if (type === 'scatter'
827
+ && parse_result.expression.args[4]
828
+ && parse_result.expression.args[4].type === 'literal'
829
+ && parse_result.expression.args[4].value.toString().toLowerCase() === 'smooth') {
830
+ options.smooth = true;
831
+ }
832
+ else if (type === 'scatter2' && parse_result.expression.args[2]) {
833
+ if (parse_result.expression.args[2].type === 'literal'
834
+ && /smooth/i.test(parse_result.expression.args[2].value.toString())) {
835
+ options.smooth = true;
836
+ }
837
+ }
838
+ else if (type === 'bubble') {
839
+ // ...
840
+ // console.info({parse_result});
841
+ }
842
+ // FIXME: fix this type (this happened when we switched from annotation
843
+ // class to a data interface)
844
+ const rect = annotation.rect;
845
+ if (annotation.layout) {
846
+ charts.push({
847
+ anchor: this.AnnotationLayoutToAnchor(annotation.layout, sheet_source), options
848
+ });
849
+ // sheet.AddChart(this.AnnotationLayoutToAnchor(annotation.layout, sheet_source), options);
850
+ }
851
+ else if (rect) {
852
+ charts.push({
853
+ anchor: this.AnnotationRectToAnchor(rect, sheet_source), options
854
+ });
855
+ // sheet.AddChart(this.AnnotationRectToAnchor(annotation.rect, sheet_source), options);
856
+ }
857
+ else {
858
+ console.warn('annotation missing layout');
859
+ }
860
+ }
861
+ }
862
+ }
863
+ return charts;
864
+ }
865
+ FormulaText(text, context) {
866
+ // let mared = false;
867
+ if (text[0] !== '=') {
868
+ return text;
869
+ }
870
+ const parse_result = this.parser.Parse(text);
871
+ if (!parse_result.expression) {
872
+ console.warn('parsing function failed');
873
+ console.warn(text);
874
+ return text.substring(1);
875
+ }
876
+ else {
877
+ // if (this.decorated_functions.length) {
878
+ {
879
+ this.parser.Walk(parse_result.expression, (unit) => {
880
+ if (unit.type === 'call') {
881
+ // unit.name = unit.name.toUpperCase();
882
+ const lc = unit.name.toLowerCase();
883
+ /*
884
+ for (const test of this.decorated_functions) {
885
+ if (test === lc) {
886
+ unit.name = '_xlfn.' + unit.name;
887
+ break;
888
+ }
889
+ }
890
+ */
891
+ if (this.decorated_functions[lc]) {
892
+ // mared = true;
893
+ unit.name = this.decorated_functions[lc] + '.' + unit.name;
894
+ }
895
+ }
896
+ return true;
897
+ });
898
+ }
899
+ //if (mared) {
900
+ // console.info("MARED", this.parser.Render(parse_result.expression, undefined, ''));
901
+ //}
902
+ // const x = this.parser.Render(parse_result.expression, undefined, '');
903
+ // console.info("T", text, x);
904
+ const table_name = context.table?.name || '';
905
+ /*
906
+ console.info('tn', table_name);
907
+ const temp = this.parser.Render(parse_result.expression, undefined, '', undefined, undefined, undefined, true, table_name);
908
+ console.info({temp});
909
+ */
910
+ return this.parser.Render(parse_result.expression, {
911
+ missing: '',
912
+ long_structured_references: true,
913
+ table_name
914
+ });
915
+ }
916
+ }
917
+ Export(source) {
918
+ // --- create a map --------------------------------------------------------
919
+ // active_sheet, in source, is a sheet ID. we need to map
920
+ // that to an index. luckily we preserve index order. we can
921
+ // do that as a side effect of creating the map, although we
922
+ // will need a loop index.
923
+ let active_sheet = 0;
924
+ const sheet_name_map = [];
925
+ for (let index = 0; index < source.sheet_data.length; index++) {
926
+ const sheet = source.sheet_data[index];
927
+ const id = sheet.id || 0;
928
+ if (id) {
929
+ sheet_name_map[id] = sheet.name || '';
930
+ }
931
+ if (id === source.active_sheet) {
932
+ active_sheet = index;
933
+ }
934
+ }
935
+ // console.info("active sheet", source.active_sheet, active_sheet);
936
+ // --- init workbook globals -----------------------------------------------
937
+ // shared strings, start empty
938
+ const shared_strings = new SharedStrings();
939
+ // style and theme: use the template so we have the base values
940
+ const style_cache = new StyleCache();
941
+ const theme = new Theme();
942
+ let data = this.zip?.Get('xl/theme/theme1.xml');
943
+ theme.FromXML(ooxml_parser.parse(data || '')?.theme);
944
+ // theme.FromXML(this.xmlparser2.parse(data || ''));
945
+ // console.info({data, xml: this.xmlparser2.parse(data)})
946
+ data = this.zip?.Get('xl/styles.xml');
947
+ //style_cache.FromXML(this.xmlparser2.parse(data || ''), theme);
948
+ style_cache.FromXML(ooxml_parser.parse(data || '')?.styleSheet, theme);
949
+ // new flag: we need metadata for dynamic arrays
950
+ let dynamic_array_metadata = false;
951
+ // reset counters
952
+ Drawing.next_drawing_index = 1;
953
+ Chart.next_chart_index = 1;
954
+ const drawings = [];
955
+ // we need to keep track of tables in all sheets
956
+ const global_tables = [];
957
+ // --- now sheets ----------------------------------------------------------
958
+ for (let sheet_index = 0; sheet_index < source.sheet_data.length; sheet_index++) {
959
+ const sheet = source.sheet_data[sheet_index];
960
+ const sheet_rels = {};
961
+ // FIXME: we could, in theory, type this thing...
962
+ const sheet_attributes = {
963
+ 'xmlns': 'http://schemas.openxmlformats.org/spreadsheetml/2006/main',
964
+ 'xmlns:r': 'http://schemas.openxmlformats.org/officeDocument/2006/relationships',
965
+ 'xmlns:mc': 'http://schemas.openxmlformats.org/markup-compatibility/2006',
966
+ 'mc:Ignorable': 'x14ac xr xr2 xr3',
967
+ 'xmlns:x14ac': 'http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac',
968
+ 'xmlns:xr': 'http://schemas.microsoft.com/office/spreadsheetml/2014/revision',
969
+ 'xmlns:xr2': 'http://schemas.microsoft.com/office/spreadsheetml/2015/revision2',
970
+ 'xmlns:xr3': 'http://schemas.microsoft.com/office/spreadsheetml/2016/revision3',
971
+ 'xr:uid': '{D37933E2-499F-4789-8D13-194E11B743FC}',
972
+ };
973
+ const default_row_height = sheet.default_row_height ? (sheet.default_row_height / 20 * 15) : 15;
974
+ // data has different representations. it is either blocked into rows or
975
+ // columns, or a set of individual cells. we could theoretically guarantee
976
+ // a particular encoding if we wanted to (by row would be optimal for excel).
977
+ // but we don't do that at the moment, so let's just unwind it using the
978
+ // standard class (adding support for cell styles)
979
+ const cell_style_refs = sheet.styles || sheet.cell_style_refs || [];
980
+ const cells = new Cells();
981
+ cells.FromJSON(sheet.data, cell_style_refs);
982
+ // console.info({ss: sheet.sheet_style, sheet});
983
+ // these are cells with style but no contents
984
+ for (const entry of sheet.cell_styles) {
985
+ const cell = cells.EnsureCell(entry); // cheating
986
+ if (!cell.style) {
987
+ cell.style = cell_style_refs[entry.ref];
988
+ }
989
+ }
990
+ // start with an extent from (0, 0). we can shift this as necessary.
991
+ const extent = {
992
+ start: { row: cells.rows + 1, column: cells.columns + 1, },
993
+ end: { row: cells.rows + 1, column: cells.columns + 1, }
994
+ };
995
+ // const FormulaText = (text: string) => (text[0] === '=') ? TranslateFormula(text.substr(1)) : text;
996
+ // cells data is row-major, and sparse.
997
+ // const sheet_data: any = { row: [] };
998
+ const sheet_rows = [];
999
+ const hyperlinks = [];
1000
+ const sparklines = [];
1001
+ const merges = [];
1002
+ const tables = [];
1003
+ // --
1004
+ //
1005
+ // this is a map of column number -> column style. we need this
1006
+ // for two things: (1) so we can skip cells that are empty, but
1007
+ // have a style from the column; and (2) so we can create the list
1008
+ // of columns, including styles.
1009
+ //
1010
+ const column_style_map = [];
1011
+ const sheet_style = this.SheetStyle(sheet, style_cache);
1012
+ for (let r = 0; r < cells.data.length; r++) {
1013
+ const row_style = this.RowStyle(sheet, style_cache, r);
1014
+ if (cells.data[r] && cells.data[r].length) {
1015
+ // push out the extent (reversed)
1016
+ if (r < extent.start.row) {
1017
+ extent.start.row = r;
1018
+ }
1019
+ // row span
1020
+ const span = { start: -1, end: -1 };
1021
+ const row = [];
1022
+ for (let c = 0; c < cells.data[r].length; c++) {
1023
+ if (!column_style_map[c]) {
1024
+ column_style_map[c] = this.ColumnStyle(sheet, style_cache, c);
1025
+ }
1026
+ const cell = cells.data[r][c];
1027
+ if (cell) {
1028
+ // create a table reference at the table head, we can ignore the rest
1029
+ if (cell.table &&
1030
+ cell.table.area.start.row === r &&
1031
+ cell.table.area.start.column === c) {
1032
+ const area = new Area(cell.table.area.start, cell.table.area.end);
1033
+ const global_count = global_tables.length + 1;
1034
+ const path = `../tables/table${global_count}.xml`;
1035
+ // column names must match the text in the column. AND, they
1036
+ // have to be unique. case-insensitive unique! we are not (atm)
1037
+ // enforcing those rules, so we need to enforce them on export.
1038
+ // also, values (and column headers) MUST BE STRINGS.
1039
+ const columns = [];
1040
+ for (let i = 0; i < area.columns; i++) {
1041
+ const header = cells.data[r][c + i];
1042
+ let value = '';
1043
+ if (header.type !== ValueType.string) {
1044
+ if (typeof header.calculated !== 'undefined') {
1045
+ value = (header.calculated).toString();
1046
+ }
1047
+ else if (typeof header.value !== 'undefined') {
1048
+ value = (header.value).toString();
1049
+ }
1050
+ header.type = ValueType.string;
1051
+ header.value = value;
1052
+ }
1053
+ else {
1054
+ value = header.value || '';
1055
+ }
1056
+ if (!value) {
1057
+ value = `Column${i + 1}`;
1058
+ }
1059
+ let proposed = value;
1060
+ let success = false;
1061
+ let index = 1;
1062
+ while (!success) {
1063
+ success = true;
1064
+ inner_loop: for (const check of columns) {
1065
+ if (check.toLowerCase() === proposed.toLowerCase()) {
1066
+ success = false;
1067
+ proposed = `${value}${++index}`;
1068
+ break inner_loop;
1069
+ }
1070
+ }
1071
+ }
1072
+ header.value = proposed;
1073
+ columns.push(proposed);
1074
+ }
1075
+ let footers = undefined;
1076
+ if (cell.table.totals_row) {
1077
+ footers = [];
1078
+ for (let i = 0; i < area.columns; i++) {
1079
+ const footer = cells.data[area.end.row][area.start.column + i];
1080
+ if (footer.type) {
1081
+ if (footer.type === ValueType.formula) {
1082
+ footers[i] = {
1083
+ type: 'formula',
1084
+ value: (footer.value || '').toString().substring(1),
1085
+ };
1086
+ }
1087
+ else {
1088
+ if (footer.type !== ValueType.string) {
1089
+ footer.type = ValueType.string;
1090
+ footer.value = footer.value?.toString() || '';
1091
+ }
1092
+ footers[i] = {
1093
+ type: 'label',
1094
+ value: footer.value,
1095
+ };
1096
+ }
1097
+ }
1098
+ // console.info({footer});
1099
+ }
1100
+ }
1101
+ // console.info({columns});
1102
+ const description = {
1103
+ rel: AddRel(sheet_rels, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/table', path),
1104
+ index: global_count,
1105
+ ref: area.spreadsheet_label,
1106
+ name: `Table${global_count}`,
1107
+ display_name: `Table${global_count}`,
1108
+ totals_row_shown: 0,
1109
+ totals_row_count: cell.table?.totals_row ? 1 : 0,
1110
+ columns,
1111
+ footers,
1112
+ };
1113
+ if (cell.table.totals_row) {
1114
+ const filter_area = new Area(area.start, {
1115
+ row: area.end.row - 1,
1116
+ column: area.end.column,
1117
+ });
1118
+ description.filterRef = filter_area.spreadsheet_label;
1119
+ }
1120
+ // console.info({description});
1121
+ // this list is used to add tables on this sheet
1122
+ tables.push(description);
1123
+ // but we also need global references to create the files
1124
+ global_tables.push(description);
1125
+ }
1126
+ // merges
1127
+ if (cell.merge_area &&
1128
+ cell.merge_area.start.row === r &&
1129
+ cell.merge_area.start.column === c) {
1130
+ merges.push(new Area(cell.merge_area.start, cell.merge_area.end));
1131
+ }
1132
+ // links
1133
+ if (cell.hyperlink) {
1134
+ const rel = AddRel(sheet_rels, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink', cell.hyperlink, 'External');
1135
+ hyperlinks.push({
1136
+ rel, target: cell.hyperlink, address: { row: r, column: c },
1137
+ });
1138
+ }
1139
+ // short-circuit here
1140
+ if (cell.type === ValueType.formula && /^=?sparkline\./i.test(cell.value)) {
1141
+ sparklines.push({
1142
+ address: { row: r, column: c },
1143
+ formula: cell.value,
1144
+ style: cell.style,
1145
+ });
1146
+ continue;
1147
+ }
1148
+ // push out the extent (reversed)
1149
+ if (c < extent.start.column) {
1150
+ extent.start.column = c;
1151
+ }
1152
+ // update span: end is implicit
1153
+ if (span.start < 0) {
1154
+ span.start = c;
1155
+ }
1156
+ span.end = c;
1157
+ // we have to stack the styles? what if there's no cell style?
1158
+ // there are definitely column styles...
1159
+ // s is style, index into the style table
1160
+ const s = this.StyleFromCell(sheet, style_cache, r, c, cell.style);
1161
+ if (cell.type === ValueType.undefined) {
1162
+ // you can skip if (1) there's a row style, and style === row style;
1163
+ // (2) there's a column style, no row style, and style === column style
1164
+ if ((row_style && s === row_style) ||
1165
+ (!row_style && (column_style_map[c] && s === column_style_map[c]))) {
1166
+ continue; // can skip
1167
+ }
1168
+ }
1169
+ // v (child element) is the value
1170
+ let v;
1171
+ let t;
1172
+ let f; // string|undefined;
1173
+ switch (cell.type) {
1174
+ case ValueType.formula:
1175
+ f = this.FormulaText(cell.value, cell);
1176
+ switch (cell.calculated_type) {
1177
+ case ValueType.string:
1178
+ v = cell.calculated;
1179
+ t = 'str';
1180
+ break;
1181
+ case ValueType.number:
1182
+ v = cell.calculated;
1183
+ break;
1184
+ case ValueType.boolean:
1185
+ v = (cell.calculated ? 1 : 0);
1186
+ t = 'b';
1187
+ break;
1188
+ }
1189
+ break;
1190
+ case ValueType.string:
1191
+ v = shared_strings.Ensure(cell.value);
1192
+ t = 's'; // shared string
1193
+ break;
1194
+ case ValueType.number:
1195
+ v = cell.value;
1196
+ break;
1197
+ case ValueType.boolean:
1198
+ v = (cell.value ? 1 : 0);
1199
+ t = 'b';
1200
+ break;
1201
+ //default:
1202
+ // v = 0;
1203
+ }
1204
+ if (cell.area && cell.area.start.row === r && cell.area.start.column === c) {
1205
+ if (typeof f === 'string') {
1206
+ f = {
1207
+ t$: f,
1208
+ a$: {
1209
+ t: 'array',
1210
+ ref: cell.area.spreadsheet_label,
1211
+ },
1212
+ };
1213
+ }
1214
+ }
1215
+ let cm = undefined;
1216
+ if (cell.spill && cell.spill.start.row === r && cell.spill.start.column === c) {
1217
+ cm = 1;
1218
+ dynamic_array_metadata = true;
1219
+ if (typeof f === 'string') {
1220
+ f = {
1221
+ t$: f,
1222
+ a$: {
1223
+ t: 'array',
1224
+ ref: cell.spill.spreadsheet_label,
1225
+ },
1226
+ };
1227
+ }
1228
+ }
1229
+ row.push({
1230
+ a$: {
1231
+ r: Area.CellAddressToLabel({ row: r, column: c }),
1232
+ t,
1233
+ // old comment regarding `s`:
1234
+ // we could skip this if it's equal to row style,
1235
+ // or there is no row style and it's equal to column style
1236
+ // or there is no column style and it's equal to sheet style
1237
+ s,
1238
+ cm,
1239
+ },
1240
+ f,
1241
+ v,
1242
+ });
1243
+ }
1244
+ }
1245
+ if (row.length || (row_style && row_style !== sheet_style)) {
1246
+ let customHeight = undefined;
1247
+ let ht = undefined;
1248
+ let s = undefined;
1249
+ let customFormat = undefined;
1250
+ if (sheet.row_height
1251
+ && (typeof sheet.row_height[r] === 'number')
1252
+ && sheet.row_height[r] !== sheet.default_row_height) {
1253
+ customHeight = 1;
1254
+ ht = sheet.row_height[r] * 3 / 4;
1255
+ }
1256
+ if (row_style && row_style !== sheet_style) {
1257
+ s = row_style;
1258
+ customFormat = 1;
1259
+ }
1260
+ // sheet_data.row.
1261
+ sheet_rows.push({
1262
+ a$: {
1263
+ r: r + 1,
1264
+ spans: `${span.start + 1}:${span.end + 1}`, // this works out to 0:0 for an empty row, will that work?
1265
+ customHeight,
1266
+ ht,
1267
+ s,
1268
+ customFormat,
1269
+ },
1270
+ c: row,
1271
+ });
1272
+ }
1273
+ }
1274
+ }
1275
+ // --- cols ----------------------------------------------------------------
1276
+ // the "cols" element represents column styles and nonstandard column
1277
+ // widths. FIXME: should we put sheet style in here as well? I think so...
1278
+ const column_entries = [];
1279
+ // we only need to include column style if it's !== sheet style,
1280
+ // because we'll have a default entry for columns that have the
1281
+ // sheet style. this is only for columns that are different.
1282
+ for (let c = 0; c < sheet.columns; c++) {
1283
+ const entry = { index: c };
1284
+ if (sheet.column_width
1285
+ && sheet.default_column_width
1286
+ && (typeof sheet.column_width[c] === 'number')
1287
+ && sheet.column_width[c] !== sheet.default_column_width) {
1288
+ entry.width = PixelsToColumnWidth(sheet.column_width[c]);
1289
+ }
1290
+ const style = column_style_map[c];
1291
+ if (style && style !== sheet_style) {
1292
+ entry.style = style;
1293
+ }
1294
+ if (entry.style !== undefined || entry.width !== undefined) {
1295
+ column_entries[c] = entry;
1296
+ }
1297
+ }
1298
+ // we're short-cutting here, these should be arranged in blocks if
1299
+ // there's overlap. not sure how much of an issue that is though.
1300
+ let dom_cols;
1301
+ if (column_entries.length || sheet_style) {
1302
+ const filled = [];
1303
+ const default_column_width = PixelsToColumnWidth(sheet.default_column_width || 90);
1304
+ // FIXME: can merge these two branches
1305
+ { // if (sheet_style) {
1306
+ let start_index = 0;
1307
+ for (const entry of column_entries) {
1308
+ if (!entry) {
1309
+ continue;
1310
+ }
1311
+ // fill with defaults
1312
+ if (sheet_style && (entry.index > start_index + 1)) {
1313
+ filled.push({
1314
+ a$: {
1315
+ min: start_index + 1,
1316
+ max: entry.index,
1317
+ style: sheet_style,
1318
+ width: default_column_width,
1319
+ },
1320
+ });
1321
+ }
1322
+ filled.push({ a$: {
1323
+ min: entry.index + 1,
1324
+ max: entry.index + 1,
1325
+ style: entry.style === undefined ? sheet_style : entry.style,
1326
+ width: entry.width === undefined ? default_column_width : entry.width,
1327
+ customWidth: entry.width === undefined ? undefined : 1,
1328
+ } });
1329
+ start_index = entry.index;
1330
+ }
1331
+ if (sheet_style && (start_index < 16384)) { // OK, sure why not
1332
+ filled.push({
1333
+ a$: {
1334
+ min: start_index + 1,
1335
+ max: 16384,
1336
+ style: sheet_style,
1337
+ width: default_column_width,
1338
+ },
1339
+ });
1340
+ }
1341
+ dom_cols = { col: filled };
1342
+ }
1343
+ }
1344
+ // --- validation ----------------------------------------------------------
1345
+ let dataValidations;
1346
+ if (sheet.data_validations?.length) {
1347
+ dataValidations = {
1348
+ a$: { count: sheet.data_validations.length },
1349
+ dataValidation: sheet.data_validations.map(validation => {
1350
+ const sqref = validation.target.map(target => {
1351
+ return new Area(target.start, target.end).spreadsheet_label;
1352
+ }).join(' ');
1353
+ let formula1 = undefined;
1354
+ if (validation.type === 'range') {
1355
+ const range = {
1356
+ id: 0,
1357
+ type: 'range',
1358
+ label: '', position: 0,
1359
+ start: { ...validation.area.start, absolute_column: true, absolute_row: true, id: 0, label: '', position: 0, type: 'address', },
1360
+ end: { ...validation.area.end, absolute_column: true, absolute_row: true, id: 0, label: '', position: 0, type: 'address', },
1361
+ };
1362
+ if (typeof validation.area.start.sheet_id !== 'undefined') {
1363
+ range.start.sheet = sheet_name_map[validation.area.start.sheet_id];
1364
+ }
1365
+ formula1 = this.parser.Render(range);
1366
+ }
1367
+ else if (validation.type === 'list') {
1368
+ formula1 = `"${validation.list.join(',')}"`;
1369
+ }
1370
+ return {
1371
+ a$: {
1372
+ type: 'list',
1373
+ allowBlank: 1,
1374
+ showInputMessage: 1,
1375
+ showErrorMessage: 1,
1376
+ sqref, // : new Area(validation.address).spreadsheet_label,
1377
+ },
1378
+ formula1,
1379
+ };
1380
+ }),
1381
+ };
1382
+ }
1383
+ // --- tables ------------------------------------------------------------
1384
+ let tableParts;
1385
+ if (tables.length) {
1386
+ tableParts = {
1387
+ a$: {
1388
+ count: tables.length,
1389
+ },
1390
+ tablePart: tables.map(table => {
1391
+ return {
1392
+ a$: {
1393
+ 'r:id': table.rel || '',
1394
+ }
1395
+ };
1396
+ }),
1397
+ };
1398
+ }
1399
+ for (const table of tables) {
1400
+ const totals_attributes = {};
1401
+ if (table.totals_row_count) {
1402
+ totals_attributes.totalsRowCount = 1;
1403
+ }
1404
+ const tableColumns = {
1405
+ a$: {
1406
+ count: (table.columns || []).length,
1407
+ },
1408
+ tableColumn: (table.columns || []).map((column, i) => {
1409
+ const footer = (table.footers || [])[i];
1410
+ return {
1411
+ a$: {
1412
+ id: i + 1,
1413
+ name: column || `Column${i + 1}`,
1414
+ totalsRowLabel: footer?.type === 'label' ? footer.value : undefined,
1415
+ totalsRowFunction: footer?.type === 'formula' ? 'custom' : undefined,
1416
+ },
1417
+ totalsRowFormula: footer?.type === 'formula' ? footer.value : undefined,
1418
+ };
1419
+ }),
1420
+ };
1421
+ const table_dom = {
1422
+ table: {
1423
+ a$: {
1424
+ xmlns: 'http://schemas.openxmlformats.org/spreadsheetml/2006/main',
1425
+ 'xmlns:mc': 'http://schemas.openxmlformats.org/markup-compatibility/2006',
1426
+ 'mc:Ignorable': 'xr xr3',
1427
+ 'xmlns:xr': 'http://schemas.microsoft.com/office/spreadsheetml/2014/revision',
1428
+ 'xmlns:xr3': 'http://schemas.microsoft.com/office/spreadsheetml/2016/revision3',
1429
+ id: table.index || 0,
1430
+ name: table.name,
1431
+ displayName: table.display_name,
1432
+ ...totals_attributes,
1433
+ ref: table.ref,
1434
+ },
1435
+ autoFilter: {
1436
+ a$: {
1437
+ ref: table.filterRef || table.ref,
1438
+ },
1439
+ },
1440
+ tableColumns,
1441
+ tableStyleInfo: {
1442
+ a$: {
1443
+ name: 'TableStyleMedium2',
1444
+ showFirstColumn: 0,
1445
+ showLastColumn: 0,
1446
+ showRowStripes: 1,
1447
+ showColumnStripes: 0,
1448
+ },
1449
+ },
1450
+ },
1451
+ };
1452
+ const xml = XMLDeclaration + this.xmlbuilder1.build(table_dom);
1453
+ // console.info(xml);
1454
+ this.zip?.Set(`xl/tables/table${table.index}.xml`, xml);
1455
+ }
1456
+ // --- conditional formats -----------------------------------------------
1457
+ let conditionalFormatting;
1458
+ if (sheet.conditional_formats?.length) {
1459
+ const format_list = [];
1460
+ let priority_index = 1;
1461
+ const reverse_operator_map = {};
1462
+ const operator_list = Object.entries(ConditionalFormatOperators).map(entry => {
1463
+ reverse_operator_map[entry[1]] = entry[0];
1464
+ return entry[1];
1465
+ });
1466
+ operator_list.sort((a, b) => b.length - a.length);
1467
+ for (const format of sheet.conditional_formats) {
1468
+ let dxf_index = 0;
1469
+ if (format.type !== 'gradient' && format.type !== 'data-bar') {
1470
+ // these are zero-based? I thought everything in there
1471
+ // was 1-based. [A: yes, these are indexed from 0].
1472
+ dxf_index = style_cache.dxf_styles.length;
1473
+ style_cache.dxf_styles.push(format.style);
1474
+ }
1475
+ switch (format.type) {
1476
+ case 'cell-match':
1477
+ {
1478
+ let operator = '';
1479
+ let formula = '';
1480
+ for (const test of operator_list) {
1481
+ if (new RegExp('^' + test + '\\s').test(format.expression)) {
1482
+ operator = reverse_operator_map[test];
1483
+ formula = format.expression.substring(test.length).trim();
1484
+ break;
1485
+ }
1486
+ }
1487
+ if (operator) {
1488
+ format_list.push({
1489
+ a$: { sqref: new Area(format.area.start, format.area.end).spreadsheet_label },
1490
+ cfRule: {
1491
+ a$: { type: 'cellIs', dxfId: dxf_index, operator, priority: priority_index++ },
1492
+ formula,
1493
+ }
1494
+ });
1495
+ }
1496
+ }
1497
+ break;
1498
+ case 'expression':
1499
+ format_list.push({
1500
+ a$: { sqref: new Area(format.area.start, format.area.end).spreadsheet_label },
1501
+ cfRule: {
1502
+ a$: { type: 'expression', dxfId: dxf_index, priority: priority_index++ },
1503
+ formula: format.expression,
1504
+ }
1505
+ });
1506
+ break;
1507
+ case 'duplicate-values':
1508
+ format_list.push({
1509
+ a$: { sqref: new Area(format.area.start, format.area.end).spreadsheet_label },
1510
+ cfRule: {
1511
+ a$: { type: format.unique ? 'uniqueValues' : 'duplicateValues', dxfId: dxf_index, priority: priority_index++ },
1512
+ }
1513
+ });
1514
+ break;
1515
+ case 'gradient':
1516
+ {
1517
+ const cfvo = [];
1518
+ const color = [];
1519
+ for (const stop of format.stops) {
1520
+ if (stop.value === 0) {
1521
+ cfvo.push({ a$: { type: 'min' } });
1522
+ }
1523
+ else if (stop.value === 1) {
1524
+ cfvo.push({ a$: { type: 'max' } });
1525
+ }
1526
+ else {
1527
+ cfvo.push({ a$: { type: 'percentile', val: stop.value * 100 } });
1528
+ }
1529
+ const attrs = ColorAttrs(stop.color);
1530
+ if (attrs) {
1531
+ color.push(attrs);
1532
+ }
1533
+ }
1534
+ const generated = {
1535
+ a$: { sqref: new Area(format.area.start, format.area.end).spreadsheet_label },
1536
+ cfRule: {
1537
+ a$: { type: 'colorScale', priority: priority_index++ },
1538
+ colorScale: {
1539
+ cfvo,
1540
+ color,
1541
+ }
1542
+ }
1543
+ };
1544
+ format_list.push(generated);
1545
+ }
1546
+ break;
1547
+ }
1548
+ }
1549
+ if (format_list.length) {
1550
+ conditionalFormatting = (format_list.length > 1) ? format_list : format_list[0];
1551
+ }
1552
+ }
1553
+ // --- merges ------------------------------------------------------------
1554
+ let mergeCells;
1555
+ if (merges.length) {
1556
+ mergeCells = {
1557
+ a$: { count: merges.length },
1558
+ mergeCell: merges.map(merge => {
1559
+ return {
1560
+ a$: { ref: merge.spreadsheet_label }
1561
+ };
1562
+ }),
1563
+ };
1564
+ }
1565
+ // --- hyperlinks --------------------------------------------------------
1566
+ let dom_hyperlinks;
1567
+ if (hyperlinks.length) {
1568
+ dom_hyperlinks = {
1569
+ hyperlink: hyperlinks.map(link => {
1570
+ return {
1571
+ a$: {
1572
+ 'r:id': link.rel,
1573
+ ref: new Area(link.address).spreadsheet_label,
1574
+ 'xr:uid': '{0C6B7792-7EA0-4932-BF15-D49C453C565D}',
1575
+ },
1576
+ };
1577
+ }),
1578
+ };
1579
+ }
1580
+ // --- sparklines --------------------------------------------------------
1581
+ let extLst;
1582
+ if (sparklines.length) {
1583
+ const groups = {
1584
+ a$: {
1585
+ 'xmlns:xm': 'http://schemas.microsoft.com/office/excel/2006/main',
1586
+ },
1587
+ 'x14:sparklineGroup': sparklines.map(sparkline => {
1588
+ const result = this.parser.Parse(sparkline.formula);
1589
+ let source = '';
1590
+ if (result.expression
1591
+ && result.expression.type === 'call'
1592
+ && result.expression.args.length > 0) {
1593
+ const arg = result.expression.args[0];
1594
+ if (arg.type === 'range' || arg.type === 'address') {
1595
+ const start = (arg.type === 'range') ? arg.start : arg;
1596
+ if (!start.sheet) {
1597
+ if (typeof start.sheet_id !== 'undefined') {
1598
+ start.sheet = sheet_name_map[start.sheet_id];
1599
+ }
1600
+ else {
1601
+ start.sheet = sheet.name;
1602
+ }
1603
+ }
1604
+ source = this.parser.Render(arg);
1605
+ }
1606
+ }
1607
+ const color_series = {
1608
+ rgb: 'FF376092' // default
1609
+ };
1610
+ if (sparkline.style?.text) {
1611
+ if (IsHTMLColor(sparkline.style.text)) {
1612
+ color_series.rgb = sparkline.style.text.text;
1613
+ }
1614
+ else if (IsThemeColor(sparkline.style.text)) {
1615
+ color_series.rgb = undefined;
1616
+ color_series.theme = sparkline.style.text.theme.toString();
1617
+ color_series.tint = typeof sparkline.style.text.tint === 'number' ?
1618
+ sparkline.style.text.tint.toString() : undefined;
1619
+ }
1620
+ }
1621
+ return {
1622
+ a$: {
1623
+ displayEmptyCellsAs: 'gap',
1624
+ displayHidden: '1',
1625
+ type: /column/i.test(sparkline.formula) ? 'column' : undefined,
1626
+ },
1627
+ 'x14:colorSeries': { a$: { ...color_series } },
1628
+ 'x14:sparklines': {
1629
+ 'x14:sparkline': {
1630
+ 'xm:f': source,
1631
+ 'xm:sqref': new Area(sparkline.address).spreadsheet_label,
1632
+ },
1633
+ },
1634
+ };
1635
+ }),
1636
+ };
1637
+ extLst = {
1638
+ ext: {
1639
+ a$: {
1640
+ uri: '{05C60535-1F16-4fd2-B633-F4F36F0B64E0}',
1641
+ 'xmlns:x14': 'http://schemas.microsoft.com/office/spreadsheetml/2009/9/main',
1642
+ },
1643
+ 'x14:sparklineGroups': groups
1644
+ }
1645
+ };
1646
+ }
1647
+ // --- charts ------------------------------------------------------------
1648
+ let dom_drawing;
1649
+ const charts = this.ParseCharts(sheet);
1650
+ const images = this.ParseImages(sheet);
1651
+ // if a sheet has one or more charts, it has a single drawing. for a
1652
+ // drawing, we need
1653
+ //
1654
+ // (1) entry in sheet xml
1655
+ // (2) drawing xml file
1656
+ // (3) relationship sheet -> drawing
1657
+ // (4) drawing rels file (for charts, later)
1658
+ // (5) entry in [ContentTypes]
1659
+ //
1660
+ // each chart in the drawing then needs
1661
+ //
1662
+ // (1) entry in drawing file
1663
+ // (2) chart xml file
1664
+ // (3) relationship drawing -> chart
1665
+ // (4) chart/colors xml file
1666
+ // (5) chart/style xml file
1667
+ // (6) chart rels file
1668
+ // (7) relationship chart -> colors
1669
+ // (8) relationship chart -> style
1670
+ // (9) entry in [ContentTypes]
1671
+ //
1672
+ // check: we can get away with not including colors or style, which
1673
+ // will revert to defaults -- let's do that for the time being if we can
1674
+ //
1675
+ // merging in images, which use the same drawing (and in a single
1676
+ // sheet, a single drawing holds both charts and images).
1677
+ if (charts.length || images.length) {
1678
+ const drawing = new Drawing();
1679
+ for (const chart of charts) {
1680
+ drawing.AddChart(chart.options, chart.anchor);
1681
+ }
1682
+ for (const image of images) {
1683
+ drawing.AddImage(image.options, image.anchor);
1684
+ }
1685
+ for (const { image } of drawing.images) {
1686
+ if (image.options.data) {
1687
+ this.zip?.SetBinary(`xl/media/image${image.index}.${image.extension}`, image.options.data, image.options.encoding);
1688
+ }
1689
+ // no media rels!
1690
+ }
1691
+ for (const { chart } of drawing.charts) {
1692
+ const dom = chart.toJSON();
1693
+ const xml = XMLDeclaration + this.xmlbuilder1.build(dom);
1694
+ this.zip?.Set(`xl/charts/chart${chart.index}.xml`, xml);
1695
+ this.WriteRels(chart.relationships, `xl/charts/_rels/chart${chart.index}.xml.rels`);
1696
+ }
1697
+ this.WriteRels(drawing.relationships, `xl/drawings/_rels/drawing${drawing.index}.xml.rels`);
1698
+ const xml = XMLDeclaration + this.xmlbuilder1.build(drawing.toJSON());
1699
+ this.zip?.Set(`xl/drawings/drawing${drawing.index}.xml`, xml);
1700
+ drawings.push(drawing); // for [ContentTypes]
1701
+ const drawing_rel = AddRel(sheet_rels, `http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing`, `../drawings/drawing${drawing.index}.xml`);
1702
+ // dom.worksheet.drawing = {
1703
+ dom_drawing = {
1704
+ a$: {
1705
+ 'r:id': drawing_rel,
1706
+ },
1707
+ };
1708
+ }
1709
+ else {
1710
+ // delete dom.worksheet.drawing;
1711
+ }
1712
+ // --- tab color ---------------------------------------------------------
1713
+ const tab_color_block = {};
1714
+ if (sheet.tab_color) {
1715
+ if (IsThemeColor(sheet.tab_color)) {
1716
+ tab_color_block.sheetPr = {
1717
+ tabColor: {
1718
+ a$: {
1719
+ theme: sheet.tab_color.theme,
1720
+ tint: sheet.tab_color.tint,
1721
+ }
1722
+ }
1723
+ };
1724
+ }
1725
+ else if (IsHTMLColor(sheet.tab_color)) {
1726
+ const color = sheet.tab_color.text || '';
1727
+ if (/^#[0-9a-fA-F]*$/.test(color)) {
1728
+ tab_color_block.sheetPr = {
1729
+ tabColor: {
1730
+ a$: {
1731
+ rgb: `FF` + color.substring(1)
1732
+ }
1733
+ }
1734
+ };
1735
+ }
1736
+ }
1737
+ }
1738
+ // --- move page margins -------------------------------------------------
1739
+ // const margins = dom.worksheet.pageMargins;
1740
+ // delete dom.worksheet.pageMargins;
1741
+ // dom.worksheet.pageMargins = margins;
1742
+ // --- end? --------------------------------------------------------------
1743
+ const sheetFormatPr = {
1744
+ a$: {
1745
+ 'x14ac:dyDescent': 0.25,
1746
+ defaultRowHeight: default_row_height === 15 ? undefined : default_row_height,
1747
+ customHeight: default_row_height === 15 ? undefined : 1,
1748
+ defaultColWidth: sheet.default_column_width ? PixelsToColumnWidth(sheet.default_column_width) : undefined,
1749
+ },
1750
+ };
1751
+ //------------------------------------------------------------------------
1752
+ //
1753
+ // NOTE: order matters. that's why we define the layout here. we
1754
+ // can't just append entries to the worksheet object.
1755
+ //
1756
+ //------------------------------------------------------------------------
1757
+ const dom = {
1758
+ worksheet: {
1759
+ a$: { ...sheet_attributes },
1760
+ ...tab_color_block,
1761
+ dimension: {
1762
+ a$: {
1763
+ ref: new Area(extent.start, extent.end).spreadsheet_label,
1764
+ },
1765
+ },
1766
+ sheetViews: {
1767
+ sheetView: {
1768
+ a$: {
1769
+ workbookViewId: 0,
1770
+ },
1771
+ },
1772
+ },
1773
+ sheetFormatPr,
1774
+ cols: dom_cols,
1775
+ sheetData: { row: sheet_rows },
1776
+ mergeCells,
1777
+ conditionalFormatting,
1778
+ dataValidations,
1779
+ hyperlinks: dom_hyperlinks,
1780
+ pageMargins: {
1781
+ a$: {
1782
+ left: 0.7,
1783
+ right: 0.7,
1784
+ top: 0.75,
1785
+ bottom: 0.75,
1786
+ header: 0.3,
1787
+ footer: 0.3,
1788
+ },
1789
+ },
1790
+ drawing: dom_drawing,
1791
+ tableParts,
1792
+ extLst,
1793
+ },
1794
+ };
1795
+ // -----------------------------------------------------------------------
1796
+ // it seems like chrome, at least, will maintain order. but this is
1797
+ // not gauranteed and we can't rely on it. the best thing to do might
1798
+ // be to use the renderer on blocks and then assemble the blocks ourselves.
1799
+ const xml = XMLDeclaration + this.xmlbuilder1.build(dom);
1800
+ // console.info(xml);
1801
+ // write this into the file
1802
+ this.zip?.Set(`xl/worksheets/sheet${sheet_index + 1}.xml`, xml);
1803
+ if (Object.keys(sheet_rels).length) {
1804
+ this.WriteRels(sheet_rels, `xl/worksheets/_rels/sheet${sheet_index + 1}.xml.rels`);
1805
+ }
1806
+ }
1807
+ // these are workbook global so after all sheets are done
1808
+ this.WriteSharedStrings(shared_strings);
1809
+ this.WriteStyleCache(style_cache);
1810
+ // now have to write/update
1811
+ //
1812
+ // (1) contentTypes
1813
+ // (2) workbook.xml
1814
+ // (3) workbook.xml.rels
1815
+ //
1816
+ const workbook_rels = {};
1817
+ AddRel(workbook_rels, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles', 'styles.xml');
1818
+ AddRel(workbook_rels, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme', 'theme/theme1.xml');
1819
+ AddRel(workbook_rels, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings', 'sharedStrings.xml');
1820
+ const worksheet_rels_map = source.sheet_data.map((sheet, index) => AddRel(workbook_rels, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet', `worksheets/sheet${index + 1}.xml`));
1821
+ if (dynamic_array_metadata) {
1822
+ const metadata_dom = {
1823
+ metadata: {
1824
+ a$: {
1825
+ xmlns: 'http://schemas.openxmlformats.org/spreadsheetml/2006/main',
1826
+ 'xmlns:xda': 'http://schemas.microsoft.com/office/spreadsheetml/2017/dynamicarray',
1827
+ },
1828
+ metadataTypes: {
1829
+ a$: {
1830
+ count: 1,
1831
+ },
1832
+ metadataType: {
1833
+ a$: {
1834
+ name: 'XLDAPR',
1835
+ minSupportedVersion: '120000',
1836
+ copy: 1,
1837
+ pasteAll: 1,
1838
+ pasteValues: 1,
1839
+ merge: 1,
1840
+ splitFirst: 1,
1841
+ rowColShift: 1,
1842
+ clearFormats: 1,
1843
+ clearComments: 1,
1844
+ assign: 1,
1845
+ coerce: 1,
1846
+ cellMeta: 1,
1847
+ },
1848
+ },
1849
+ },
1850
+ futureMetadata: {
1851
+ a$: {
1852
+ name: 'XLDAPR',
1853
+ count: 1,
1854
+ },
1855
+ bk: {
1856
+ extLst: {
1857
+ ext: {
1858
+ a$: {
1859
+ uri: '{bdbb8cdc-fa1e-496e-a857-3c3f30c029c3}',
1860
+ },
1861
+ 'xda:dynamicArrayProperties': {
1862
+ a$: {
1863
+ fDynamic: 1,
1864
+ fCollapsed: `0`,
1865
+ },
1866
+ },
1867
+ },
1868
+ },
1869
+ },
1870
+ },
1871
+ cellMetadata: {
1872
+ a$: { count: 1 },
1873
+ bk: {
1874
+ rc: {
1875
+ a$: {
1876
+ t: 1,
1877
+ v: `0`,
1878
+ }
1879
+ },
1880
+ },
1881
+ },
1882
+ },
1883
+ };
1884
+ const metadata_xml = XMLDeclaration + this.xmlbuilder1.build(metadata_dom);
1885
+ // console.info(metadata_xml);
1886
+ this.zip?.Set(`xl/metadata.xml`, metadata_xml);
1887
+ // add rel
1888
+ AddRel(workbook_rels, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/sheetMetadata', 'metadata.xml');
1889
+ }
1890
+ this.WriteRels(workbook_rels, `xl/_rels/workbook.xml.rels`);
1891
+ const definedNames = source.named?.length ? {
1892
+ definedName: (source.named || []).map(entry => {
1893
+ let scope = undefined;
1894
+ if (entry.scope) {
1895
+ const test = entry.scope.toLowerCase();
1896
+ for (const [index, sheet] of source.sheet_data.entries()) {
1897
+ if (sheet.name?.toLowerCase() === test) {
1898
+ scope = index.toString();
1899
+ break;
1900
+ }
1901
+ }
1902
+ }
1903
+ return {
1904
+ a$: { name: entry.name, localSheetId: scope },
1905
+ t$: entry.expression,
1906
+ };
1907
+ }),
1908
+ } : undefined;
1909
+ const workbook_dom = {
1910
+ workbook: {
1911
+ a$: {
1912
+ 'xmlns': 'http://schemas.openxmlformats.org/spreadsheetml/2006/main',
1913
+ 'xmlns:r': 'http://schemas.openxmlformats.org/officeDocument/2006/relationships',
1914
+ 'xmlns:mc': 'http://schemas.openxmlformats.org/markup-compatibility/2006',
1915
+ 'mc:Ignorable': 'x15 xr xr6 xr10 xr2',
1916
+ 'xmlns:x15': 'http://schemas.microsoft.com/office/spreadsheetml/2010/11/main',
1917
+ 'xmlns:xr': 'http://schemas.microsoft.com/office/spreadsheetml/2014/revision',
1918
+ 'xmlns:xr6': 'http://schemas.microsoft.com/office/spreadsheetml/2016/revision6',
1919
+ 'xmlns:xr10': 'http://schemas.microsoft.com/office/spreadsheetml/2016/revision10',
1920
+ 'xmlns:xr2': 'http://schemas.microsoft.com/office/spreadsheetml/2015/revision2',
1921
+ },
1922
+ workbookPr: {
1923
+ a$: {
1924
+ defaultThemeVersion: '166925',
1925
+ },
1926
+ },
1927
+ bookViews: {
1928
+ workbookView: {
1929
+ a$: {
1930
+ activeTab: (active_sheet || 0),
1931
+ },
1932
+ },
1933
+ },
1934
+ sheets: {
1935
+ sheet: source.sheet_data.map((sheet, index) => ({
1936
+ a$: {
1937
+ name: sheet.name || `Sheet${index + 1}`,
1938
+ sheetId: index + 1,
1939
+ 'r:id': worksheet_rels_map[index],
1940
+ state: (sheet.visible === false) ? 'hidden' : undefined,
1941
+ }
1942
+ })),
1943
+ },
1944
+ definedNames,
1945
+ },
1946
+ };
1947
+ const workbook_xml = XMLDeclaration + this.xmlbuilder1.build(workbook_dom);
1948
+ // console.info(workbook_xml);
1949
+ this.zip?.Set(`xl/workbook.xml`, workbook_xml);
1950
+ // const extensions: Array<{ Extension: string, ContentType: string }> = [];
1951
+ const extensions = {};
1952
+ for (const drawing of drawings) {
1953
+ for (const image of drawing.images) {
1954
+ switch (image.image.extension) {
1955
+ case 'gif':
1956
+ case 'png':
1957
+ case 'jpeg':
1958
+ extensions[image.image.extension] = 'image/' + image.image.extension;
1959
+ break;
1960
+ case 'svg':
1961
+ extensions['svg'] = 'image/svg+xml';
1962
+ break;
1963
+ }
1964
+ }
1965
+ }
1966
+ const content_types_dom = {
1967
+ Types: {
1968
+ a$: {
1969
+ 'xmlns': 'http://schemas.openxmlformats.org/package/2006/content-types',
1970
+ },
1971
+ Default: [
1972
+ { a$: { Extension: 'rels', ContentType: 'application/vnd.openxmlformats-package.relationships+xml' } },
1973
+ { a$: { Extension: 'xml', ContentType: 'application/xml' } },
1974
+ ...Object.keys(extensions).map(key => ({
1975
+ a$: { Extension: key, ContentType: extensions[key] },
1976
+ })),
1977
+ ],
1978
+ Override: [
1979
+ { a$: { PartName: '/xl/workbook.xml', ContentType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml' } },
1980
+ // sheets
1981
+ ...source.sheet_data.map((sheet, index) => {
1982
+ return { a$: {
1983
+ ContentType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml',
1984
+ PartName: `/xl/worksheets/sheet${index + 1}.xml`,
1985
+ } };
1986
+ }),
1987
+ // charts and drawings
1988
+ ...drawings.reduce((a, drawing) => {
1989
+ return a.concat([
1990
+ ...drawing.charts.map(chart => {
1991
+ return { a$: {
1992
+ ContentType: 'application/vnd.openxmlformats-officedocument.drawingml.chart+xml',
1993
+ PartName: `/xl/charts/chart${chart.chart.index}.xml`,
1994
+ } };
1995
+ }),
1996
+ { a$: {
1997
+ ContentType: 'application/vnd.openxmlformats-officedocument.drawing+xml',
1998
+ PartName: `/xl/drawings/drawing${drawing.index}.xml`,
1999
+ } },
2000
+ ]);
2001
+ }, []),
2002
+ { a$: { PartName: '/xl/theme/theme1.xml', ContentType: 'application/vnd.openxmlformats-officedocument.theme+xml' } },
2003
+ { a$: { PartName: '/xl/styles.xml', ContentType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml' } },
2004
+ { a$: { PartName: '/xl/sharedStrings.xml', ContentType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml' } },
2005
+ // metadata
2006
+ ...(dynamic_array_metadata ? [
2007
+ { a$: { PartName: '/xl/metadata.xml', ContentType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheetMetadata+xml' } },
2008
+ ] : []),
2009
+ // tables
2010
+ ...global_tables.map(table => {
2011
+ return { a$: {
2012
+ ContentType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml',
2013
+ PartName: `/xl/tables/table${table.index || 0}.xml`,
2014
+ } };
2015
+ }),
2016
+ { a$: { PartName: '/docProps/core.xml', ContentType: 'application/vnd.openxmlformats-package.core-properties+xml' } },
2017
+ { a$: { PartName: '/docProps/app.xml', ContentType: 'application/vnd.openxmlformats-officedocument.extended-properties+xml' } },
2018
+ ],
2019
+ },
2020
+ };
2021
+ const content_types_xml = XMLDeclaration + this.xmlbuilder1.build(content_types_dom);
2022
+ // console.info(content_types_xml);
2023
+ this.zip?.Set(`[Content_Types].xml`, content_types_xml);
2024
+ }
2025
+ ArrayBuffer() {
2026
+ if (!this.zip) {
2027
+ throw new Error('missing zip');
2028
+ }
2029
+ return this.zip.ArrayBuffer();
2030
+ }
2031
+ Blob() {
2032
+ if (!this.zip) {
2033
+ throw new Error('missing zip');
2034
+ }
2035
+ const buffer = this.zip.ArrayBuffer();
2036
+ return new Blob([buffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
2037
+ }
2038
+ }
2039
+ //# sourceMappingURL=export.js.map