react-native-nitro-xlsx 0.2.5 → 0.2.6

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 (395) hide show
  1. package/NitroXlsx.podspec +26 -27
  2. package/Package.swift +31 -10
  3. package/README.md +1 -1
  4. package/android/CMakeLists.txt +20 -27
  5. package/package.json +2 -2
  6. package/scripts/run-cpp-tests.sh +1 -1
  7. package/thirdparty/OpenXLSX/.clang-format +118 -0
  8. package/thirdparty/OpenXLSX/.clang-tidy +28 -0
  9. package/thirdparty/OpenXLSX/.gitignore +130 -0
  10. package/thirdparty/OpenXLSX/Benchmarks/2024-07-29-benchmarks_before_XMLNode_wrappers +46 -0
  11. package/thirdparty/OpenXLSX/Benchmarks/2024-07-29-benchmarks_with_XMLNode_wrappers_and_namespace_and_stripping +49 -0
  12. package/thirdparty/OpenXLSX/Benchmarks/2024-07-29-benchmarks_with_XMLNode_wrappers_and_namespace_char_support +49 -0
  13. package/thirdparty/OpenXLSX/Benchmarks/2024-07-29-benchmarks_with_XMLNode_wrappers_and_namespace_support +49 -0
  14. package/thirdparty/OpenXLSX/Benchmarks/2024-07-29-benchmarks_with_XMLNode_wrappers_and_namespaced_name_disabled +49 -0
  15. package/thirdparty/OpenXLSX/Benchmarks/2024-08-11-benchmarks_post-XLCellIterator-Rework +46 -0
  16. package/thirdparty/OpenXLSX/Benchmarks/2024-08-14-benchmarks_post-default-row-column-style-support +46 -0
  17. package/thirdparty/OpenXLSX/Benchmarks/2024-09-02-benchmarks +46 -0
  18. package/thirdparty/OpenXLSX/Benchmarks/2024-12-19-benchmarks +46 -0
  19. package/thirdparty/OpenXLSX/Benchmarks/2024-12-30-benchmarks-post-XLSharedStrings-by-ref +46 -0
  20. package/thirdparty/OpenXLSX/Benchmarks/2025-01-09-benchmarks-post-conditionalFormatsAndSheetProtection +46 -0
  21. package/thirdparty/OpenXLSX/Benchmarks/2025-01-10-benchmarks-post-XLCellValue-bugfix +46 -0
  22. package/thirdparty/OpenXLSX/Benchmarks/2025-01-31-benchmarks-post-XLComments-implementation +46 -0
  23. package/thirdparty/OpenXLSX/Benchmarks/2025-02-02-benchmarks-post-XLRowIterator-Rework +46 -0
  24. package/thirdparty/OpenXLSX/Benchmarks/2025-07-20-benchmarks-after-hiding-pugixml-internals +46 -0
  25. package/thirdparty/OpenXLSX/Benchmarks/2025-08-29-benchmarks-after-code-review-with-libzip +46 -0
  26. package/thirdparty/OpenXLSX/Benchmarks/Benchmark.cpp +249 -0
  27. package/thirdparty/OpenXLSX/Benchmarks/CMakeLists.txt +19 -0
  28. package/thirdparty/OpenXLSX/CMakeLists.txt +466 -0
  29. package/thirdparty/OpenXLSX/Documentation/CMakeLists.txt +31 -0
  30. package/thirdparty/OpenXLSX/Documentation/Doxyfile.in +2471 -0
  31. package/thirdparty/OpenXLSX/Documentation/DoxygenLayout.xml +194 -0
  32. package/thirdparty/OpenXLSX/Documentation/customdoxygen.css +1355 -0
  33. package/thirdparty/OpenXLSX/Examples/CMakeLists.txt +103 -0
  34. package/thirdparty/OpenXLSX/Examples/Demo1.cpp +279 -0
  35. package/thirdparty/OpenXLSX/Examples/Demo10.cpp +545 -0
  36. package/thirdparty/OpenXLSX/Examples/Demo1A.cpp +137 -0
  37. package/thirdparty/OpenXLSX/Examples/Demo2.cpp +65 -0
  38. package/thirdparty/OpenXLSX/Examples/Demo3.cpp +89 -0
  39. package/thirdparty/OpenXLSX/Examples/Demo4.cpp +86 -0
  40. package/thirdparty/OpenXLSX/Examples/Demo5.cpp +77 -0
  41. package/thirdparty/OpenXLSX/Examples/Demo6.cpp +103 -0
  42. package/thirdparty/OpenXLSX/Examples/Demo7.cpp +79 -0
  43. package/thirdparty/OpenXLSX/Examples/Demo8.cpp +117 -0
  44. package/thirdparty/OpenXLSX/Examples/Demo9.cpp +363 -0
  45. package/thirdparty/OpenXLSX/Examples/cmake/FindLIBZIP.cmake +61 -0
  46. package/thirdparty/OpenXLSX/Examples/external/CustomZip/CustomZip.hpp +256 -0
  47. package/thirdparty/OpenXLSX/LICENSE.md +29 -0
  48. package/thirdparty/OpenXLSX/Makefile.GNU +530 -0
  49. package/thirdparty/OpenXLSX/Notes/TBDs.txt +16 -0
  50. package/thirdparty/OpenXLSX/Notes/confirmed-TBCs.txt +8 -0
  51. package/thirdparty/OpenXLSX/Notes/styles-missing-support.xml +12 -0
  52. package/thirdparty/OpenXLSX/Notes/todo-list.txt +108 -0
  53. package/thirdparty/OpenXLSX/OpenXLSX/CMakeLists.txt +631 -0
  54. package/thirdparty/OpenXLSX/OpenXLSX/OpenXLSX.hpp +63 -0
  55. package/thirdparty/OpenXLSX/OpenXLSX/OpenXLSXConfig.cmake +11 -0
  56. package/thirdparty/OpenXLSX/OpenXLSX/cmake/bundle_static_library.cmake +198 -0
  57. package/thirdparty/OpenXLSX/OpenXLSX/cmake/patch_pkg_config.cmake +69 -0
  58. package/thirdparty/OpenXLSX/OpenXLSX/headers/IZipArchive.hpp +361 -0
  59. package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX-Exports.hpp +12 -0
  60. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLCell.hpp +367 -0
  61. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLCellIterator.hpp +252 -0
  62. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLCellRange.hpp +223 -0
  63. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLCellReference.hpp +317 -0
  64. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLCellValue.hpp +793 -0
  65. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLColor.hpp +232 -0
  66. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLColumn.hpp +159 -0
  67. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLCommandQuery.hpp +228 -0
  68. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLComments.hpp +270 -0
  69. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLConstants.hpp +18 -0
  70. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLContentTypes.hpp +264 -0
  71. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLDateTime.hpp +175 -0
  72. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLDocument.hpp +505 -0
  73. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLDrawing.hpp +452 -0
  74. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLException.hpp +161 -0
  75. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLFormula.hpp +375 -0
  76. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLIterator.hpp +40 -0
  77. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLMergeCells.hpp +216 -0
  78. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLProperties.hpp +348 -0
  79. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLRelationships.hpp +348 -0
  80. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLRow.hpp +721 -0
  81. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLRowData.hpp +488 -0
  82. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLSharedStrings.hpp +204 -0
  83. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLSheet.hpp +1640 -0
  84. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLStyles.hpp +2390 -0
  85. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLTables.hpp +132 -0
  86. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLWorkbook.hpp +404 -0
  87. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLXmlData.hpp +283 -0
  88. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLXmlFile.hpp +194 -0
  89. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLXmlParser.hpp +282 -0
  90. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLXmlParserForwardDeclarations.hpp +85 -0
  91. package/thirdparty/OpenXLSX/OpenXLSX/headers/XLZipArchive.hpp +232 -0
  92. package/thirdparty/OpenXLSX/OpenXLSX/headers/detail/LibZip.hpp +447 -0
  93. package/thirdparty/OpenXLSX/OpenXLSX/headers/detail/OpenXLSXFileSystemTools.hpp +207 -0
  94. package/thirdparty/OpenXLSX/OpenXLSX/headers/detail/Zippy.hpp +1375 -0
  95. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLCell.cpp +340 -0
  96. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLCellIterator.cpp +427 -0
  97. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLCellRange.cpp +221 -0
  98. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLCellReference.cpp +408 -0
  99. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLCellValue.cpp +519 -0
  100. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLColor.cpp +202 -0
  101. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLColumn.cpp +141 -0
  102. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLComments.cpp +637 -0
  103. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLContentTypes.cpp +329 -0
  104. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLDateTime.cpp +269 -0
  105. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLDocument.cpp +1678 -0
  106. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLDrawing.cpp +784 -0
  107. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLFormula.cpp +201 -0
  108. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLMergeCells.cpp +357 -0
  109. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLProperties.cpp +810 -0
  110. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLRelationships.cpp +529 -0
  111. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLRow.cpp +918 -0
  112. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLRowData.cpp +508 -0
  113. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLSharedStrings.cpp +220 -0
  114. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLSheet.cpp +1970 -0
  115. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLStyles.cpp +3014 -0
  116. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLTables.cpp +125 -0
  117. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLWorkbook.cpp +784 -0
  118. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLXmlData.cpp +247 -0
  119. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLXmlFile.cpp +160 -0
  120. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLXmlParser.cpp +261 -0
  121. package/thirdparty/OpenXLSX/OpenXLSX/sources/XLZipArchive.cpp +266 -0
  122. package/thirdparty/OpenXLSX/OpenXLSX/sources/utilities/XLUtilities.hpp +478 -0
  123. package/thirdparty/OpenXLSX/README.md +1279 -0
  124. package/thirdparty/OpenXLSX/Scripts/cmake-cleanup.sh +102 -0
  125. package/thirdparty/OpenXLSX/Scripts/compile.sh +23 -0
  126. package/thirdparty/OpenXLSX/Scripts/demos-cleanup.sh +25 -0
  127. package/thirdparty/OpenXLSX/Scripts/demos-run-all.sh +60 -0
  128. package/thirdparty/OpenXLSX/Scripts/guarded-xml-format.sh +47 -0
  129. package/thirdparty/OpenXLSX/Scripts/make-gnu.sh +11 -0
  130. package/thirdparty/OpenXLSX/Scripts/uninstall-manifest.sh +48 -0
  131. package/thirdparty/OpenXLSX/Scripts/xml-format-all.sh +19 -0
  132. package/thirdparty/OpenXLSX/Scripts/xml-format.sh +38 -0
  133. package/thirdparty/OpenXLSX/Tests/CMakeLists.txt +37 -0
  134. package/thirdparty/OpenXLSX/Tests/catch/catch.hpp +17799 -0
  135. package/thirdparty/OpenXLSX/Tests/catch/catch_reporter_automake.hpp +68 -0
  136. package/thirdparty/OpenXLSX/Tests/catch/catch_reporter_sonarqube.hpp +182 -0
  137. package/thirdparty/OpenXLSX/Tests/catch/catch_reporter_tap.hpp +278 -0
  138. package/thirdparty/OpenXLSX/Tests/catch/catch_reporter_teamcity.hpp +212 -0
  139. package/thirdparty/OpenXLSX/Tests/main.cpp +55 -0
  140. package/thirdparty/OpenXLSX/Tests/testXLCell.cpp +176 -0
  141. package/thirdparty/OpenXLSX/Tests/testXLCellRange.cpp +180 -0
  142. package/thirdparty/OpenXLSX/Tests/testXLCellReference.cpp +160 -0
  143. package/thirdparty/OpenXLSX/Tests/testXLCellValue.cpp +366 -0
  144. package/thirdparty/OpenXLSX/Tests/testXLCellValueProxy.cpp +255 -0
  145. package/thirdparty/OpenXLSX/Tests/testXLColor.cpp +75 -0
  146. package/thirdparty/OpenXLSX/Tests/testXLDateTime.cpp +229 -0
  147. package/thirdparty/OpenXLSX/Tests/testXLDocument.cpp +197 -0
  148. package/thirdparty/OpenXLSX/Tests/testXLFormula.cpp +131 -0
  149. package/thirdparty/OpenXLSX/Tests/testXLRow.cpp +597 -0
  150. package/thirdparty/OpenXLSX/Tests/testXLSheet.cpp +77 -0
  151. package/thirdparty/OpenXLSX/Tests/ziptest-with-libs.cpp +88 -0
  152. package/thirdparty/OpenXLSX/Tests/ziptest.cpp +735 -0
  153. package/thirdparty/OpenXLSX/cmake/get-git-HEAD-ID.cmake +45 -0
  154. package/thirdparty/OpenXLSX/cmake/libopenxlsxCPackOptions.cmake.in +20 -0
  155. package/thirdparty/OpenXLSX/cmake/manage_dependency.cmake +813 -0
  156. package/thirdparty/OpenXLSX/cmake/recursive_library_type_test.cmake +52 -0
  157. package/thirdparty/OpenXLSX/gnu-make-crutch/OpenXLSX-Exports-shared.hpp +42 -0
  158. package/thirdparty/OpenXLSX/gnu-make-crutch/OpenXLSX-Exports-static.hpp +42 -0
  159. package/thirdparty/OpenXLSX/vcpkg.json +24 -0
  160. package/thirdparty/README.md +42 -0
  161. package/thirdparty/miniz/.clang-format +47 -0
  162. package/thirdparty/miniz/.travis.yml +2 -0
  163. package/thirdparty/miniz/CMakeLists.txt +333 -0
  164. package/thirdparty/miniz/CMakePresets.json +31 -0
  165. package/thirdparty/miniz/ChangeLog.md +272 -0
  166. package/thirdparty/miniz/Config.cmake.in +1 -0
  167. package/thirdparty/miniz/LICENSE +22 -0
  168. package/thirdparty/miniz/amalgamate.sh +57 -0
  169. package/thirdparty/miniz/examples/example1.c +105 -0
  170. package/thirdparty/miniz/examples/example2.c +164 -0
  171. package/thirdparty/miniz/examples/example3.c +269 -0
  172. package/thirdparty/miniz/examples/example4.c +102 -0
  173. package/thirdparty/miniz/examples/example5.c +327 -0
  174. package/thirdparty/miniz/examples/example6.c +189 -0
  175. package/thirdparty/miniz/meson.build +21 -0
  176. package/thirdparty/miniz/miniz.c +646 -0
  177. package/thirdparty/miniz/miniz.h +615 -0
  178. package/thirdparty/miniz/miniz.pc.in +13 -0
  179. package/thirdparty/miniz/miniz_common.h +89 -0
  180. package/thirdparty/miniz/miniz_export.h +20 -0
  181. package/thirdparty/miniz/miniz_tdef.c +1602 -0
  182. package/thirdparty/miniz/miniz_tdef.h +199 -0
  183. package/thirdparty/miniz/miniz_tinfl.c +778 -0
  184. package/thirdparty/miniz/miniz_tinfl.h +150 -0
  185. package/thirdparty/miniz/miniz_zip.c +4895 -0
  186. package/thirdparty/miniz/miniz_zip.h +454 -0
  187. package/thirdparty/miniz/readme.md +46 -0
  188. package/thirdparty/miniz/test.sh +36 -0
  189. package/thirdparty/miniz/tests/add_in_place_fuzzer.c +87 -0
  190. package/thirdparty/miniz/tests/catch_amalgamated.cpp +10795 -0
  191. package/thirdparty/miniz/tests/catch_amalgamated.hpp +13143 -0
  192. package/thirdparty/miniz/tests/checksum_fuzzer.c +26 -0
  193. package/thirdparty/miniz/tests/compress_fuzzer.c +91 -0
  194. package/thirdparty/miniz/tests/flush_fuzzer.c +88 -0
  195. package/thirdparty/miniz/tests/fuzz_main.c +55 -0
  196. package/thirdparty/miniz/tests/large_fuzzer.c +133 -0
  197. package/thirdparty/miniz/tests/main.cpp +185 -0
  198. package/thirdparty/miniz/tests/miniz_tdefl_fuzzer.cc +115 -0
  199. package/thirdparty/miniz/tests/miniz_tester.cpp +1881 -0
  200. package/thirdparty/miniz/tests/miniz_zip_validate_fuzzer.cc +71 -0
  201. package/thirdparty/miniz/tests/miniz_zip_writer_fuzzer.cc +96 -0
  202. package/thirdparty/miniz/tests/ossfuzz.sh +48 -0
  203. package/thirdparty/miniz/tests/small_fuzzer.c +126 -0
  204. package/thirdparty/miniz/tests/timer.cpp +152 -0
  205. package/thirdparty/miniz/tests/timer.h +40 -0
  206. package/thirdparty/miniz/tests/uncompress2_fuzzer.c +21 -0
  207. package/thirdparty/miniz/tests/uncompress_fuzzer.c +30 -0
  208. package/thirdparty/miniz/tests/zip.dict +9 -0
  209. package/thirdparty/miniz/tests/zip_fuzzer.c +63 -0
  210. package/thirdparty/pugixml/.codecov.yml +7 -0
  211. package/thirdparty/pugixml/.gitattributes +1 -0
  212. package/thirdparty/pugixml/CMakeLists.txt +330 -0
  213. package/thirdparty/pugixml/LICENSE.md +24 -0
  214. package/thirdparty/pugixml/Makefile +98 -0
  215. package/thirdparty/pugixml/README.md +81 -0
  216. package/thirdparty/pugixml/SECURITY.md +9 -0
  217. package/thirdparty/pugixml/appveyor.yml +50 -0
  218. package/thirdparty/pugixml/docs/config.adoc +7 -0
  219. package/thirdparty/pugixml/docs/images/dom_tree.png +0 -0
  220. package/thirdparty/pugixml/docs/images/vs2005_link1.png +0 -0
  221. package/thirdparty/pugixml/docs/images/vs2005_link2.png +0 -0
  222. package/thirdparty/pugixml/docs/images/vs2005_pch1.png +0 -0
  223. package/thirdparty/pugixml/docs/images/vs2005_pch2.png +0 -0
  224. package/thirdparty/pugixml/docs/images/vs2005_pch3.png +0 -0
  225. package/thirdparty/pugixml/docs/images/vs2005_pch4.png +0 -0
  226. package/thirdparty/pugixml/docs/images/vs2010_link1.png +0 -0
  227. package/thirdparty/pugixml/docs/images/vs2010_link2.png +0 -0
  228. package/thirdparty/pugixml/docs/manual.adoc +3326 -0
  229. package/thirdparty/pugixml/docs/manual.html +6395 -0
  230. package/thirdparty/pugixml/docs/quickstart.adoc +287 -0
  231. package/thirdparty/pugixml/docs/quickstart.html +1107 -0
  232. package/thirdparty/pugixml/docs/samples/character.xml +8 -0
  233. package/thirdparty/pugixml/docs/samples/custom_memory_management.cpp +27 -0
  234. package/thirdparty/pugixml/docs/samples/include.cpp +64 -0
  235. package/thirdparty/pugixml/docs/samples/load_error_handling.cpp +33 -0
  236. package/thirdparty/pugixml/docs/samples/load_file.cpp +16 -0
  237. package/thirdparty/pugixml/docs/samples/load_memory.cpp +66 -0
  238. package/thirdparty/pugixml/docs/samples/load_options.cpp +30 -0
  239. package/thirdparty/pugixml/docs/samples/load_stream.cpp +97 -0
  240. package/thirdparty/pugixml/docs/samples/modify_add.cpp +29 -0
  241. package/thirdparty/pugixml/docs/samples/modify_base.cpp +43 -0
  242. package/thirdparty/pugixml/docs/samples/modify_remove.cpp +27 -0
  243. package/thirdparty/pugixml/docs/samples/save_custom_writer.cpp +116 -0
  244. package/thirdparty/pugixml/docs/samples/save_declaration.cpp +27 -0
  245. package/thirdparty/pugixml/docs/samples/save_file.cpp +17 -0
  246. package/thirdparty/pugixml/docs/samples/save_options.cpp +48 -0
  247. package/thirdparty/pugixml/docs/samples/save_stream.cpp +18 -0
  248. package/thirdparty/pugixml/docs/samples/save_subtree.cpp +26 -0
  249. package/thirdparty/pugixml/docs/samples/text.cpp +35 -0
  250. package/thirdparty/pugixml/docs/samples/transitions.xml +7 -0
  251. package/thirdparty/pugixml/docs/samples/traverse_base.cpp +51 -0
  252. package/thirdparty/pugixml/docs/samples/traverse_iter.cpp +27 -0
  253. package/thirdparty/pugixml/docs/samples/traverse_predicate.cpp +48 -0
  254. package/thirdparty/pugixml/docs/samples/traverse_rangefor.cpp +32 -0
  255. package/thirdparty/pugixml/docs/samples/traverse_walker.cpp +35 -0
  256. package/thirdparty/pugixml/docs/samples/tree.xml +12 -0
  257. package/thirdparty/pugixml/docs/samples/weekly-shift_jis.xml +78 -0
  258. package/thirdparty/pugixml/docs/samples/weekly-utf-16.xml +0 -0
  259. package/thirdparty/pugixml/docs/samples/weekly-utf-8.xml +78 -0
  260. package/thirdparty/pugixml/docs/samples/xgconsole.xml +12 -0
  261. package/thirdparty/pugixml/docs/samples/xpath_error.cpp +43 -0
  262. package/thirdparty/pugixml/docs/samples/xpath_query.cpp +36 -0
  263. package/thirdparty/pugixml/docs/samples/xpath_select.cpp +28 -0
  264. package/thirdparty/pugixml/docs/samples/xpath_variables.cpp +38 -0
  265. package/thirdparty/pugixml/readme.txt +50 -0
  266. package/thirdparty/pugixml/scripts/archive.py +54 -0
  267. package/thirdparty/pugixml/scripts/cocoapods_push.sh +4 -0
  268. package/thirdparty/pugixml/scripts/natvis/pugixml.natvis +77 -0
  269. package/thirdparty/pugixml/scripts/natvis/pugixml_compact.natvis +506 -0
  270. package/thirdparty/pugixml/scripts/nuget/build/native/pugixml-propertiesui.xml +17 -0
  271. package/thirdparty/pugixml/scripts/nuget/build/native/pugixml.targets +28 -0
  272. package/thirdparty/pugixml/scripts/nuget/pugixml.nuspec +20 -0
  273. package/thirdparty/pugixml/scripts/nuget_build.ps1 +60 -0
  274. package/thirdparty/pugixml/scripts/premake4.lua +92 -0
  275. package/thirdparty/pugixml/scripts/pugixml-config.cmake.in +12 -0
  276. package/thirdparty/pugixml/scripts/pugixml.pc.in +11 -0
  277. package/thirdparty/pugixml/scripts/pugixml.podspec +14 -0
  278. package/thirdparty/pugixml/scripts/pugixml.xcodeproj/project.pbxproj +212 -0
  279. package/thirdparty/pugixml/scripts/pugixml_airplay.mkf +13 -0
  280. package/thirdparty/pugixml/scripts/pugixml_codeblocks.cbp +44 -0
  281. package/thirdparty/pugixml/scripts/pugixml_codelite.project +56 -0
  282. package/thirdparty/pugixml/scripts/pugixml_dll.rc +45 -0
  283. package/thirdparty/pugixml/scripts/pugixml_vs2005.vcproj +343 -0
  284. package/thirdparty/pugixml/scripts/pugixml_vs2005_static.vcproj +343 -0
  285. package/thirdparty/pugixml/scripts/pugixml_vs2008.vcproj +339 -0
  286. package/thirdparty/pugixml/scripts/pugixml_vs2008_static.vcproj +339 -0
  287. package/thirdparty/pugixml/scripts/pugixml_vs2010.vcxproj +191 -0
  288. package/thirdparty/pugixml/scripts/pugixml_vs2010_static.vcxproj +191 -0
  289. package/thirdparty/pugixml/scripts/pugixml_vs2013.vcxproj +199 -0
  290. package/thirdparty/pugixml/scripts/pugixml_vs2013_static.vcxproj +199 -0
  291. package/thirdparty/pugixml/scripts/pugixml_vs2015.vcxproj +172 -0
  292. package/thirdparty/pugixml/scripts/pugixml_vs2015_static.vcxproj +176 -0
  293. package/thirdparty/pugixml/scripts/pugixml_vs2017.vcxproj +172 -0
  294. package/thirdparty/pugixml/scripts/pugixml_vs2017_static.vcxproj +176 -0
  295. package/thirdparty/pugixml/scripts/pugixml_vs2019.vcxproj +176 -0
  296. package/thirdparty/pugixml/scripts/pugixml_vs2019_static.vcxproj +180 -0
  297. package/thirdparty/pugixml/scripts/pugixml_vs2022.vcxproj +176 -0
  298. package/thirdparty/pugixml/scripts/pugixml_vs2022_static.vcxproj +180 -0
  299. package/thirdparty/pugixml/scripts/pugixml_vs2026.vcxproj +176 -0
  300. package/thirdparty/pugixml/scripts/pugixml_vs2026_static.vcxproj +180 -0
  301. package/thirdparty/pugixml/scripts/sbom.cdx.json +47 -0
  302. package/thirdparty/pugixml/src/pugiconfig.hpp +81 -0
  303. package/thirdparty/pugixml/src/pugixml.cpp +13776 -0
  304. package/thirdparty/pugixml/src/pugixml.hpp +1604 -0
  305. package/thirdparty/pugixml/tests/allocator.cpp +175 -0
  306. package/thirdparty/pugixml/tests/allocator.hpp +10 -0
  307. package/thirdparty/pugixml/tests/autotest-appveyor.ps1 +93 -0
  308. package/thirdparty/pugixml/tests/cmake-appveyor.ps1 +57 -0
  309. package/thirdparty/pugixml/tests/data/empty.xml +0 -0
  310. package/thirdparty/pugixml/tests/data/large.xml +1 -0
  311. package/thirdparty/pugixml/tests/data/latintest_latin1.xml +1 -0
  312. package/thirdparty/pugixml/tests/data/latintest_utf8.xml +1 -0
  313. package/thirdparty/pugixml/tests/data/multiline.xml +3 -0
  314. package/thirdparty/pugixml/tests/data/small.xml +1 -0
  315. package/thirdparty/pugixml/tests/data/truncation.xml +19 -0
  316. package/thirdparty/pugixml/tests/data/utftest_utf16_be.xml +0 -0
  317. package/thirdparty/pugixml/tests/data/utftest_utf16_be_bom.xml +0 -0
  318. package/thirdparty/pugixml/tests/data/utftest_utf16_be_clean.xml +0 -0
  319. package/thirdparty/pugixml/tests/data/utftest_utf16_be_nodecl.xml +0 -0
  320. package/thirdparty/pugixml/tests/data/utftest_utf16_le.xml +0 -0
  321. package/thirdparty/pugixml/tests/data/utftest_utf16_le_bom.xml +0 -0
  322. package/thirdparty/pugixml/tests/data/utftest_utf16_le_clean.xml +0 -0
  323. package/thirdparty/pugixml/tests/data/utftest_utf16_le_nodecl.xml +0 -0
  324. package/thirdparty/pugixml/tests/data/utftest_utf32_be.xml +0 -0
  325. package/thirdparty/pugixml/tests/data/utftest_utf32_be_bom.xml +0 -0
  326. package/thirdparty/pugixml/tests/data/utftest_utf32_be_clean.xml +0 -0
  327. package/thirdparty/pugixml/tests/data/utftest_utf32_be_nodecl.xml +0 -0
  328. package/thirdparty/pugixml/tests/data/utftest_utf32_le.xml +0 -0
  329. package/thirdparty/pugixml/tests/data/utftest_utf32_le_bom.xml +0 -0
  330. package/thirdparty/pugixml/tests/data/utftest_utf32_le_clean.xml +0 -0
  331. package/thirdparty/pugixml/tests/data/utftest_utf32_le_nodecl.xml +0 -0
  332. package/thirdparty/pugixml/tests/data/utftest_utf8.xml +87 -0
  333. package/thirdparty/pugixml/tests/data/utftest_utf8_bom.xml +87 -0
  334. package/thirdparty/pugixml/tests/data/utftest_utf8_clean.xml +84 -0
  335. package/thirdparty/pugixml/tests/data/utftest_utf8_nodecl.xml +86 -0
  336. package/thirdparty/pugixml/tests/data//321/202/320/265/321/201/321/202.xml +1 -0
  337. package/thirdparty/pugixml/tests/data_fuzz_parse/basic.xml +1 -0
  338. package/thirdparty/pugixml/tests/data_fuzz_parse/doctype.xml +1 -0
  339. package/thirdparty/pugixml/tests/data_fuzz_parse/refs.xml +1 -0
  340. package/thirdparty/pugixml/tests/data_fuzz_parse/types.xml +1 -0
  341. package/thirdparty/pugixml/tests/data_fuzz_parse/utf16.xml +0 -0
  342. package/thirdparty/pugixml/tests/data_fuzz_parse/utf32.xml +0 -0
  343. package/thirdparty/pugixml/tests/data_fuzz_xpath/basic.xpath +1 -0
  344. package/thirdparty/pugixml/tests/data_fuzz_xpath/functions.xpath +1 -0
  345. package/thirdparty/pugixml/tests/data_fuzz_xpath/math.xpath +1 -0
  346. package/thirdparty/pugixml/tests/data_fuzz_xpath/path.xpath +1 -0
  347. package/thirdparty/pugixml/tests/data_fuzz_xpath/predicate.xpath +1 -0
  348. package/thirdparty/pugixml/tests/fuzz_parse.cpp +14 -0
  349. package/thirdparty/pugixml/tests/fuzz_parse.dict +72 -0
  350. package/thirdparty/pugixml/tests/fuzz_setup.sh +11 -0
  351. package/thirdparty/pugixml/tests/fuzz_xpath.cpp +46 -0
  352. package/thirdparty/pugixml/tests/fuzz_xpath.dict +72 -0
  353. package/thirdparty/pugixml/tests/helpers.hpp +114 -0
  354. package/thirdparty/pugixml/tests/main.cpp +218 -0
  355. package/thirdparty/pugixml/tests/test.cpp +220 -0
  356. package/thirdparty/pugixml/tests/test.hpp +175 -0
  357. package/thirdparty/pugixml/tests/test_compact.cpp +150 -0
  358. package/thirdparty/pugixml/tests/test_deprecated.cpp +25 -0
  359. package/thirdparty/pugixml/tests/test_document.cpp +1910 -0
  360. package/thirdparty/pugixml/tests/test_dom_modify.cpp +2122 -0
  361. package/thirdparty/pugixml/tests/test_dom_text.cpp +601 -0
  362. package/thirdparty/pugixml/tests/test_dom_traverse.cpp +1481 -0
  363. package/thirdparty/pugixml/tests/test_header_guard.cpp +3 -0
  364. package/thirdparty/pugixml/tests/test_header_iosfwd_1.cpp +3 -0
  365. package/thirdparty/pugixml/tests/test_header_iosfwd_2.cpp +3 -0
  366. package/thirdparty/pugixml/tests/test_header_iostream_1.cpp +3 -0
  367. package/thirdparty/pugixml/tests/test_header_iostream_2.cpp +3 -0
  368. package/thirdparty/pugixml/tests/test_header_only_1.cpp +21 -0
  369. package/thirdparty/pugixml/tests/test_header_only_2.cpp +21 -0
  370. package/thirdparty/pugixml/tests/test_header_string_1.cpp +3 -0
  371. package/thirdparty/pugixml/tests/test_header_string_2.cpp +3 -0
  372. package/thirdparty/pugixml/tests/test_header_string_iostream.cpp +5 -0
  373. package/thirdparty/pugixml/tests/test_memory.cpp +303 -0
  374. package/thirdparty/pugixml/tests/test_parse.cpp +1463 -0
  375. package/thirdparty/pugixml/tests/test_parse_doctype.cpp +366 -0
  376. package/thirdparty/pugixml/tests/test_unicode.cpp +152 -0
  377. package/thirdparty/pugixml/tests/test_version.cpp +5 -0
  378. package/thirdparty/pugixml/tests/test_write.cpp +757 -0
  379. package/thirdparty/pugixml/tests/test_xpath.cpp +833 -0
  380. package/thirdparty/pugixml/tests/test_xpath_api.cpp +646 -0
  381. package/thirdparty/pugixml/tests/test_xpath_functions.cpp +844 -0
  382. package/thirdparty/pugixml/tests/test_xpath_operators.cpp +566 -0
  383. package/thirdparty/pugixml/tests/test_xpath_parse.cpp +428 -0
  384. package/thirdparty/pugixml/tests/test_xpath_paths.cpp +787 -0
  385. package/thirdparty/pugixml/tests/test_xpath_paths_abbrev_w3c.cpp +219 -0
  386. package/thirdparty/pugixml/tests/test_xpath_paths_w3c.cpp +312 -0
  387. package/thirdparty/pugixml/tests/test_xpath_variables.cpp +683 -0
  388. package/thirdparty/pugixml/tests/test_xpath_xalan_1.cpp +411 -0
  389. package/thirdparty/pugixml/tests/test_xpath_xalan_2.cpp +417 -0
  390. package/thirdparty/pugixml/tests/test_xpath_xalan_3.cpp +321 -0
  391. package/thirdparty/pugixml/tests/test_xpath_xalan_4.cpp +300 -0
  392. package/thirdparty/pugixml/tests/test_xpath_xalan_5.cpp +295 -0
  393. package/thirdparty/pugixml/tests/writer_string.cpp +79 -0
  394. package/thirdparty/pugixml/tests/writer_string.hpp +27 -0
  395. package/scripts/prepare-openxlsx.js +0 -126
@@ -0,0 +1,784 @@
1
+ /*
2
+
3
+ ____ ____ ___ ____ ____ ____ ___
4
+ 6MMMMb `MM( )M' `MM' 6MMMMb\`MM( )M'
5
+ 8P Y8 `MM. d' MM 6M' ` `MM. d'
6
+ 6M Mb __ ____ ____ ___ __ `MM. d' MM MM `MM. d'
7
+ MM MM `M6MMMMb 6MMMMb `MM 6MMb `MM. d' MM YM. `MM. d'
8
+ MM MM MM' `Mb 6M' `Mb MMM9 `Mb `MMd MM YMMMMb `MMd
9
+ MM MM MM MM MM MM MM' MM dMM. MM `Mb dMM.
10
+ MM MM MM MM MMMMMMMM MM MM d'`MM. MM MM d'`MM.
11
+ YM M9 MM MM MM MM MM d' `MM. MM MM d' `MM.
12
+ 8b d8 MM. ,M9 YM d9 MM MM d' `MM. MM / L ,M9 d' `MM.
13
+ YMMMM9 MMYMMM9 YMMMM9 _MM_ _MM_M(_ _)MM_ _MMMMMMM MYMMMM9 _M(_ _)MM_
14
+ MM
15
+ MM
16
+ _MM_
17
+
18
+ Copyright (c) 2018, Kenneth Troldal Balslev
19
+
20
+ All rights reserved.
21
+
22
+ Redistribution and use in source and binary forms, with or without
23
+ modification, are permitted provided that the following conditions are met:
24
+ - Redistributions of source code must retain the above copyright
25
+ notice, this list of conditions and the following disclaimer.
26
+ - Redistributions in binary form must reproduce the above copyright
27
+ notice, this list of conditions and the following disclaimer in the
28
+ documentation and/or other materials provided with the distribution.
29
+ - Neither the name of the author nor the
30
+ names of any contributors may be used to endorse or promote products
31
+ derived from this software without specific prior written permission.
32
+
33
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
34
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
35
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
36
+ DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
37
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
38
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
39
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
40
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
41
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
42
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43
+
44
+ */
45
+
46
+ // ===== External Includes ===== //
47
+ #include <algorithm>
48
+ #include <iterator>
49
+ #include <vector>
50
+
51
+ // ===== OpenXLSX Includes ===== //
52
+ #include "XLDocument.hpp"
53
+ #include "XLSheet.hpp"
54
+ #include "XLWorkbook.hpp"
55
+ #include "XLXmlParser.hpp" // pugixml wrapper
56
+ #include "utilities/XLUtilities.hpp" // appendAndGetAttribute
57
+
58
+ using namespace OpenXLSX;
59
+
60
+ namespace
61
+ {
62
+ /**
63
+ * @brief
64
+ * @param doc
65
+ * @return
66
+ */
67
+ XMLNode sheetsNode(const XMLDocument& doc) { return doc.document_element().child("sheets"); }
68
+ } // namespace
69
+
70
+ /**
71
+ * @details Default constructor
72
+ */
73
+ XLWorkbook::XLWorkbook() = default;
74
+
75
+ /**
76
+ * @details The constructor initializes the member variables and calls the loadXMLData from the
77
+ * XLAbstractXMLFile base class.
78
+ */
79
+ XLWorkbook::XLWorkbook(XLXmlData* xmlData) : XLXmlFile(xmlData)
80
+ {
81
+ // 2026-06-10: ensure that XML namespaces are defined in existing documents, too
82
+ XMLNode rootNode = xmlDocument().document_element();
83
+ appendAndGetAttribute(rootNode, "xmlns", "http://schemas.openxmlformats.org/spreadsheetml/2006/main");
84
+ appendAndGetAttribute(rootNode, "xmlns:r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships");
85
+ appendAndGetAttribute(rootNode, "xmlns:mc", "http://schemas.openxmlformats.org/markup-compatibility/2006");
86
+ appendAndGetAttribute(rootNode, "xmlns:x15", "http://schemas.microsoft.com/office/spreadsheetml/2010/11/main");
87
+ appendAndGetAttribute(rootNode, "xmlns:xr", "http://schemas.microsoft.com/office/spreadsheetml/2014/revision");
88
+ appendAndGetAttribute(rootNode, "xmlns:xr6", "http://schemas.microsoft.com/office/spreadsheetml/2016/revision6");
89
+ appendAndGetAttribute(rootNode, "xmlns:xr10", "http://schemas.microsoft.com/office/spreadsheetml/2016/revision10");
90
+ appendAndGetAttribute(rootNode, "xmlns:xr2", "http://schemas.microsoft.com/office/spreadsheetml/2015/revision2");
91
+ }
92
+
93
+ /**
94
+ * @details Copy constructor
95
+ */
96
+ XLWorkbook::XLWorkbook(const XLWorkbook& other) = default;
97
+
98
+ /**
99
+ * @details Move constructor
100
+ */
101
+ XLWorkbook::XLWorkbook(XLWorkbook&& other) = default;
102
+
103
+ /**
104
+ * @details
105
+ */
106
+ XLWorkbook::~XLWorkbook() = default;
107
+
108
+ /**
109
+ * @brief Copy assignment operator
110
+ */
111
+ XLWorkbook& XLWorkbook::operator=(const XLWorkbook& other) = default;
112
+
113
+ /**
114
+ * @brief Move assignment operator
115
+ */
116
+ XLWorkbook& XLWorkbook::operator=(XLWorkbook&& other) = default;
117
+
118
+ /**
119
+ * @details
120
+ */
121
+ XLSheet XLWorkbook::sheet(const std::string& sheetName)
122
+ {
123
+ // ===== First determine if the sheet exists.
124
+ if (xmlDocument().document_element().child("sheets").find_child_by_attribute("name", sheetName.c_str()) == nullptr)
125
+ throw XLInputError("Sheet \"" + sheetName + "\" does not exist");
126
+
127
+ // ===== Find the sheet data corresponding to the sheet with the requested name
128
+ const std::string xmlID =
129
+ xmlDocument().document_element().child("sheets").find_child_by_attribute("name", sheetName.c_str()).attribute("r:id").value();
130
+
131
+ XLQuery pathQuery(XLQueryType::QuerySheetRelsTarget);
132
+ pathQuery.setParam("sheetID", xmlID);
133
+ auto xmlPath = parentDoc().execQuery(pathQuery).result<std::string>();
134
+
135
+ // Some spreadsheets use absolute rather than relative paths in relationship items.
136
+ if (xmlPath.substr(0, 4) == "/xl/") xmlPath = xmlPath.substr(4);
137
+
138
+ XLQuery xmlQuery(XLQueryType::QueryXmlData);
139
+ xmlQuery.setParam("xmlPath", "xl/" + xmlPath);
140
+ return XLSheet(parentDoc().execQuery(xmlQuery).result<XLXmlData*>());
141
+ }
142
+
143
+ /**
144
+ * @details iterate over sheetsNode and count element nodes until index, get sheet name and return the corresponding sheet object
145
+ *
146
+ * @old-details Create a vector with sheet nodes, retrieve the node at the requested index, get sheet name and return the
147
+ * corresponding sheet object.
148
+ */
149
+ XLSheet XLWorkbook::sheet(uint16_t index) // 2024-04-30: whitespace support
150
+ {
151
+ if (index < 1 || index > sheetCount()) throw XLInputError("Sheet index is out of bounds");
152
+
153
+ // ===== Find the n-th node_element that corresponds to index
154
+ uint16_t curIndex = 0;
155
+ for (XMLNode node = sheetsNode(xmlDocument()).first_child_of_type(pugi::node_element);
156
+ not node.empty();
157
+ node = node.next_sibling_of_type(pugi::node_element))
158
+ {
159
+ if (++curIndex == index) return sheet(node.attribute("name").as_string());
160
+ }
161
+
162
+ // ===== If execution gets here, there are less element nodes than index in sheetsNode, this should never happen
163
+ using namespace std::literals::string_literals;
164
+ throw XLInternalError("Sheet index "s + std::to_string(index) + " is out of bounds"s);
165
+ }
166
+
167
+ /**
168
+ * @details
169
+ */
170
+ XLWorksheet XLWorkbook::worksheet(const std::string& sheetName) { return sheet(sheetName).get<XLWorksheet>(); }
171
+
172
+ /**
173
+ * @details
174
+ */
175
+ XLWorksheet XLWorkbook::worksheet(uint16_t index) { return sheet(index).get<XLWorksheet>(); }
176
+
177
+ /**
178
+ * @details
179
+ */
180
+ XLChartsheet XLWorkbook::chartsheet(const std::string& sheetName) { return sheet(sheetName).get<XLChartsheet>(); }
181
+
182
+ /**
183
+ * @details
184
+ */
185
+ XLChartsheet XLWorkbook::chartsheet(uint16_t index) { return sheet(index).get<XLChartsheet>(); }
186
+
187
+ // /**
188
+ // * @details
189
+ // */
190
+ // bool XLWorkbook::hasSharedStrings() const
191
+ // {
192
+ // return true; // always true
193
+ // }
194
+ //
195
+ // /**
196
+ // * @details
197
+ // */
198
+ // XLSharedStrings XLWorkbook::sharedStrings()
199
+ // {
200
+ // const XLQuery query(XLQueryType::QuerySharedStrings);
201
+ // return parentDoc().execQuery(query).result<XLSharedStrings>();
202
+ // }
203
+ //
204
+ /**
205
+ * @details
206
+ */
207
+ void XLWorkbook::deleteNamedRanges()
208
+ {
209
+ xmlDocument()
210
+ .document_element()
211
+ .child("definedNames")
212
+ .remove_children(); // 2024-05-02: why loop if pugixml has a function for "delete all children"?
213
+ // for (auto& child : xmlDocument().document_element().child("definedNames").children()) child.parent().remove_child(child);
214
+ }
215
+
216
+ /**
217
+ * @details
218
+ */
219
+ void XLWorkbook::deleteSheet(const std::string& sheetName) // 2024-05-02: whitespace support
220
+ // CAUTION: execCommand on underlying XML with whitespaces not verified
221
+ {
222
+ // ===== Determine ID and type of sheet, as well as current worksheet count.
223
+ std::string sheetID = sheetsNode(xmlDocument()).find_child_by_attribute("name", sheetName.c_str()).attribute("r:id").value(); // NOLINT
224
+ if (sheetID.length() == 0) { // 2025-01-12 BUGFIX: prevent segfault by throwing
225
+ using namespace std::literals::string_literals;
226
+ throw XLException("XLWorkbook::deleteSheet: workbook has no sheet with name \""s + sheetName + "\""s);
227
+ }
228
+ XLQuery sheetTypeQuery(XLQueryType::QuerySheetType);
229
+ sheetTypeQuery.setParam("sheetID", std::string(sheetID)); // BUGFIX 2024-05-02: was using relationshipID() instead of sheetID,
230
+ // leading to a bad sheetType & a failed check to not delete last worksheet
231
+ const auto sheetType = parentDoc().execQuery(sheetTypeQuery).result<XLContentType>();
232
+
233
+ // 2024-04-30: this should be whitespace-safe due to lambda expression checking for an attribute that non element nodes can not have
234
+ const auto worksheetCount =
235
+ std::count_if(sheetsNode(xmlDocument()).children().begin(), sheetsNode(xmlDocument()).children().end(), [&](const XMLNode& item) {
236
+ if (item.type() != pugi::node_element) return false; // 2024-05-02 this avoids the unnecessary query below
237
+ XLQuery query(XLQueryType::QuerySheetType);
238
+ query.setParam("sheetID", std::string(item.attribute("r:id").value()));
239
+ return parentDoc().execQuery(query).result<XLContentType>() == XLContentType::Worksheet;
240
+ });
241
+
242
+ // ===== If this is the last worksheet in the workbook, throw an exception.
243
+ if (worksheetCount == 1 && sheetType == XLContentType::Worksheet)
244
+ throw XLInputError("Invalid operation. There must be at least one worksheet in the workbook.");
245
+
246
+ // ===== Delete the sheet data as well as the sheet node from Workbook.xml
247
+ parentDoc().execCommand(
248
+ XLCommand(XLCommandType::DeleteSheet).setParam("sheetID", std::string(sheetID)).setParam("sheetName", sheetName));
249
+ XMLNode sheet = sheetsNode(xmlDocument()).find_child_by_attribute("name", sheetName.c_str());
250
+ if (not sheet.empty()) {
251
+ // ===== Delete all non element nodes (comments, whitespaces) following the sheet being deleted from workbook.xml <sheets> node
252
+ XMLNode nonElementNode = sheet.next_sibling();
253
+ while (not nonElementNode.empty() && nonElementNode.type() != pugi::node_element) {
254
+ sheetsNode(xmlDocument()).remove_child(nonElementNode);
255
+ nonElementNode = nonElementNode.next_sibling();
256
+ }
257
+ sheetsNode(xmlDocument()).remove_child(sheet); // delete the actual sheet entry
258
+ }
259
+
260
+ if (sheetIsActive(sheetID))
261
+ xmlDocument().document_element().child("bookViews").first_child_of_type(pugi::node_element).remove_attribute("activeTab");
262
+ }
263
+
264
+ /**
265
+ * @details
266
+ */
267
+ void XLWorkbook::addWorksheet(const std::string& sheetName)
268
+ {
269
+ // ===== If a sheet with the given name already exists, throw an exception.
270
+ if (xmlDocument().document_element().child("sheets").find_child_by_attribute("name", sheetName.c_str()))
271
+ throw XLInputError("Sheet named \"" + sheetName + "\" already exists.");
272
+
273
+ // ===== Create new internal (workbook) ID for the sheet
274
+ auto internalID = createInternalSheetID();
275
+
276
+ // ===== Create xml file for new worksheet and add metadata to the workbook file.
277
+ parentDoc().execCommand(XLCommand(XLCommandType::AddWorksheet)
278
+ .setParam("sheetName", sheetName)
279
+ .setParam("sheetPath", "/xl/worksheets/sheet" + std::to_string(internalID) + ".xml"));
280
+ prepareSheetMetadata(sheetName, internalID);
281
+ }
282
+
283
+ /**
284
+ * @details
285
+ * @todo If the original sheet's tabSelected attribute is set, ensure it is un-set in the clone.
286
+ * TBD: See comment in XLWorkbook::setSheetActive - should the tabSelected actually be un-set? It's not the same as the active tab,
287
+ * which does not need to be selected
288
+ */
289
+ void XLWorkbook::cloneSheet(const std::string& existingName, const std::string& newName)
290
+ {
291
+ parentDoc().execCommand(XLCommand(XLCommandType::CloneSheet).setParam("sheetID", sheetID(existingName)).setParam("cloneName", newName));
292
+ }
293
+
294
+ /**
295
+ * @details
296
+ */
297
+ uint16_t XLWorkbook::createInternalSheetID() // 2024-04-30: whitespace support
298
+ {
299
+ XMLNode sheet = xmlDocument().document_element().child("sheets").first_child_of_type(pugi::node_element);
300
+ uint32_t maxSheetIdFound = 0;
301
+ while (not sheet.empty()) {
302
+ uint32_t thisSheetId = sheet.attribute("sheetId").as_uint();
303
+ if (thisSheetId > maxSheetIdFound) maxSheetIdFound = thisSheetId;
304
+ sheet = sheet.next_sibling_of_type(pugi::node_element);
305
+ }
306
+ return maxSheetIdFound + 1;
307
+ }
308
+
309
+ /**
310
+ * @details
311
+ */
312
+ std::string XLWorkbook::sheetID(const std::string& sheetName)
313
+ {
314
+ return xmlDocument().document_element().child("sheets").find_child_by_attribute("name", sheetName.c_str()).attribute("r:id").value();
315
+ }
316
+
317
+ /**
318
+ * @details
319
+ */
320
+ std::string XLWorkbook::sheetName(const std::string& sheetID) const
321
+ {
322
+ return xmlDocument().document_element().child("sheets").find_child_by_attribute("r:id", sheetID.c_str()).attribute("name").value();
323
+ }
324
+
325
+ /**
326
+ * @details
327
+ */
328
+ std::string XLWorkbook::sheetVisibility(const std::string& sheetID) const
329
+ {
330
+ return xmlDocument().document_element().child("sheets").find_child_by_attribute("r:id", sheetID.c_str()).attribute("state").value();
331
+ }
332
+
333
+ /**
334
+ * @details
335
+ */
336
+ void XLWorkbook::prepareSheetMetadata(const std::string& sheetName, uint16_t internalID)
337
+ {
338
+ // ===== Add new child node to the "sheets" node.
339
+ auto node = sheetsNode(xmlDocument()).append_child("sheet");
340
+
341
+ // ===== append the required attributes to the newly created sheet node.
342
+ std::string sheetPath = "/xl/worksheets/sheet" + std::to_string(internalID) + ".xml";
343
+ node.append_attribute("name") = sheetName.c_str();
344
+ node.append_attribute("sheetId") = std::to_string(internalID).c_str();
345
+
346
+ XLQuery query(XLQueryType::QuerySheetRelsID);
347
+ query.setParam("sheetPath", sheetPath);
348
+ node.append_attribute("r:id") = parentDoc().execQuery(query).result<std::string>().c_str();
349
+ }
350
+
351
+ /**
352
+ * @details
353
+ */
354
+ void XLWorkbook::setSheetName(const std::string& sheetRID, const std::string& newName)
355
+ {
356
+ auto sheetName = xmlDocument().document_element().child("sheets").find_child_by_attribute("r:id", sheetRID.c_str()).attribute("name");
357
+
358
+ updateSheetReferences(sheetName.value(), newName);
359
+ sheetName.set_value(newName.c_str());
360
+ }
361
+
362
+ /**
363
+ * @details
364
+ */
365
+ void XLWorkbook::setSheetVisibility(const std::string& sheetRID, const std::string& state) // 2024-04-30: whitespace support
366
+ {
367
+ // ===== First, determine if there are other sheets that are visible
368
+ int visibleSheets = 0;
369
+ // for (const auto& item : xmlDocument().document_element().child("sheets").children()) {
370
+ XMLNode item = xmlDocument().document_element().child("sheets").first_child_of_type(pugi::node_element);
371
+ while (not item.empty()) {
372
+ if (std::string(item.attribute("r:id").value()) != sheetRID) {
373
+ if (isVisible(item)) ++visibleSheets;
374
+ }
375
+ item = item.next_sibling_of_type(pugi::node_element);
376
+ }
377
+
378
+ bool hideSheet = not isVisibleState(state); // 2024-04-30: save for later use on activating another sheet if needed
379
+
380
+ // ===== If there are no other visible sheets, and the current sheet is to be made hidden, throw an exception.
381
+ if (hideSheet && visibleSheets == 0) throw XLSheetError("At least one sheet must be visible.");
382
+
383
+ // ===== Then, retrieve or create the visibility ("state") attribute for the sheet, and set it to the "state" value
384
+ auto stateAttribute =
385
+ xmlDocument().document_element().child("sheets").find_child_by_attribute("r:id", sheetRID.c_str()).attribute("state");
386
+ if (stateAttribute.empty()) {
387
+ stateAttribute =
388
+ xmlDocument().document_element().child("sheets").find_child_by_attribute("r:id", sheetRID.c_str()).prepend_attribute("state");
389
+ }
390
+ stateAttribute.set_value(state.c_str());
391
+
392
+ // Next, find the index of the sheet...
393
+ std::string name =
394
+ xmlDocument().document_element().child("sheets").find_child_by_attribute("r:id", sheetRID.c_str()).attribute("name").value();
395
+ auto index = indexOfSheet(name) - 1; // 2024-05-01: activeTab property stores an array index, NOT the value of r_ID?
396
+
397
+ // ...and determine the index of the active sheet
398
+ XMLNode workbookView = xmlDocument().document_element().child("bookViews").first_child_of_type(pugi::node_element);
399
+ auto activeTabAttribute = workbookView.attribute("activeTab");
400
+ if (activeTabAttribute.empty()) {
401
+ activeTabAttribute = workbookView.append_attribute("activeTab");
402
+ activeTabAttribute.set_value(0);
403
+ }
404
+ const auto activeTabIndex = activeTabAttribute.as_uint();
405
+
406
+ // Finally, if the current sheet is the active one, set the "activeTab" attribute to the first visible sheet in the workbook
407
+ if (hideSheet && activeTabIndex == index) { // BUGFIX 2024-04-30: previously, the active tab was re-set even if the current sheet was
408
+ // being set to "visible" (when already being visible)
409
+ XMLNode item = xmlDocument().document_element().child("sheets").first_child_of_type(pugi::node_element);
410
+ while (not item.empty()) {
411
+ if (isVisible(item))
412
+ { // BUGFIX 2024-05-01: old check was testing state != "hidden" || != "veryHidden", which was always true
413
+ activeTabAttribute.set_value(indexOfSheet(item.attribute("name").value()) - 1);
414
+ break;
415
+ }
416
+ item = item.next_sibling_of_type(pugi::node_element);
417
+ }
418
+ }
419
+ }
420
+
421
+ /**
422
+ * @details
423
+ * @done In some cases (eg. if a sheet is moved to the position before the selected sheet), multiple sheets are selected when opened
424
+ * in Excel.
425
+ */
426
+ void XLWorkbook::setSheetIndex(const std::string& sheetName, unsigned int index) // 2024-05-01: whitespace support
427
+ {
428
+ // ===== Determine the index of the active tab, if any
429
+ const XMLNode workbookView = xmlDocument().document_element().child("bookViews").first_child_of_type(pugi::node_element);
430
+ const uint32_t activeSheetIndex = 1 + workbookView.attribute("activeTab").as_uint(0); // use index in the 1.. range
431
+
432
+ // ===== Attempt to locate the sheet with sheetName, and look out for the sheet @index, and the sheet @activeIndex while iterating over
433
+ // the sheets
434
+ XMLNode sheetToMove {}; // determine the sheet matching sheetName, if any
435
+ unsigned int sheetToMoveIndex = 0;
436
+ XMLNode existingSheet {}; // determine the sheet at index, if any
437
+ std::string activeSheet_rId {}; // determine the r:id of the sheet at activeIndex, if any
438
+
439
+ unsigned int sheetIndex = 1;
440
+ XMLNode curSheet = sheetsNode(xmlDocument()).first_child_of_type(pugi::node_element);
441
+ int thingsToFind = (activeSheetIndex > 0) ? 3 : 2; // if there is no active tab configured, no need to search for its name
442
+
443
+ while (not curSheet.empty() && thingsToFind > 0) { // permit early loop exit when all sheets are located
444
+ if (sheetToMove.empty() && (curSheet.attribute("name").value() == sheetName)) {
445
+ sheetToMoveIndex = sheetIndex;
446
+ sheetToMove = curSheet;
447
+ --thingsToFind;
448
+ }
449
+ if (existingSheet.empty() && (sheetIndex == index)) {
450
+ existingSheet = curSheet;
451
+ --thingsToFind;
452
+ }
453
+ if (activeSheet_rId.empty() && (sheetIndex == activeSheetIndex)) { // if no active sheet: activeSheetIndex 0 never matches
454
+ activeSheet_rId = curSheet.attribute("r:id").value();
455
+ --thingsToFind;
456
+ }
457
+ ++sheetIndex;
458
+ curSheet = curSheet.next_sibling_of_type(pugi::node_element);
459
+ }
460
+
461
+ // ===== If a sheet with sheetName was not found
462
+ if (sheetToMove.empty()) throw XLInputError(std::string(__func__) + std::string(": no worksheet exists with name ") + sheetName);
463
+
464
+ // ==== name was matched
465
+
466
+ // ===== If the new index is equal to the current, don't do anything
467
+ if (index == sheetToMoveIndex) return;
468
+
469
+ // ===== Modify the node in the XML file
470
+ if (existingSheet.empty()) // new index is beyond last sheet
471
+ sheetsNode(xmlDocument()).append_move(sheetToMove);
472
+ else { // existingSheet was found
473
+ if (sheetToMoveIndex < index)
474
+ sheetsNode(xmlDocument()).insert_move_after(sheetToMove, existingSheet);
475
+ else // sheetToMoveIndex > index, because if equal, function never gets here
476
+ sheetsNode(xmlDocument()).insert_move_before(sheetToMove, existingSheet);
477
+ }
478
+
479
+ // ===== Updated defined names with worksheet scopes. TBD what this does
480
+ XMLNode definedName = xmlDocument().document_element().child("definedNames").first_child_of_type(pugi::node_element);
481
+ while (not definedName.empty()) {
482
+ // TBD: is the current definedName actually associated with the sheet that was moved?
483
+ definedName.attribute("localSheetId").set_value(sheetToMoveIndex - 1);
484
+ definedName = definedName.next_sibling_of_type(pugi::node_element);
485
+ }
486
+
487
+ // ===== Update the activeTab attribute.
488
+ if ((activeSheetIndex < std::min(index, sheetToMoveIndex)) ||
489
+ (activeSheetIndex > std::max(index, sheetToMoveIndex))) // if active sheet was not within the set of sheets affected by the move
490
+ return; // nothing to do
491
+
492
+ if (activeSheet_rId.length() > 0) setSheetActive(activeSheet_rId);
493
+ }
494
+
495
+ /**
496
+ * @details
497
+ */
498
+ unsigned int XLWorkbook::indexOfSheet(const std::string& sheetName) const // 2024-05-01: whitespace support
499
+ {
500
+ // ===== Iterate through sheet nodes. When a match is found, return the index;
501
+ unsigned int index = 1;
502
+ for (XMLNode sheet = sheetsNode(xmlDocument()).first_child_of_type(pugi::node_element);
503
+ not sheet.empty();
504
+ sheet = sheet.next_sibling_of_type(pugi::node_element))
505
+ {
506
+ if (sheetName == sheet.attribute("name").value()) return index;
507
+ index++;
508
+ }
509
+
510
+ // ===== If a match is not found, throw an exception.
511
+ throw XLInputError("Sheet does not exist");
512
+ }
513
+
514
+ /**
515
+ * @details
516
+ */
517
+ XLSheetType XLWorkbook::typeOfSheet(const std::string& sheetName) const
518
+ {
519
+ if (!sheetExists(sheetName)) throw XLInputError("Sheet with name \"" + sheetName + "\" doesn't exist.");
520
+
521
+ if (worksheetExists(sheetName)) return XLSheetType::Worksheet;
522
+ return XLSheetType::Chartsheet;
523
+ }
524
+
525
+ /**
526
+ * @details
527
+ */
528
+ XLSheetType XLWorkbook::typeOfSheet(unsigned int index) const // 2024-05-01: whitespace support
529
+ {
530
+ unsigned int thisIndex = 1;
531
+ for (XMLNode sheet = sheetsNode(xmlDocument()).first_child_of_type(pugi::node_element);
532
+ not sheet.empty();
533
+ sheet = sheet.next_sibling_of_type(pugi::node_element))
534
+ {
535
+ if (thisIndex == index) return typeOfSheet(sheet.attribute("name").as_string());
536
+ ++thisIndex;
537
+ }
538
+
539
+ using namespace std::literals::string_literals;
540
+ throw XLInputError(std::string(__func__) + ": index "s + std::to_string(index) + " is out of range"s);
541
+ }
542
+
543
+ /**
544
+ * @details
545
+ */
546
+ unsigned int XLWorkbook::sheetCount() const // 2024-04-30: whitespace support
547
+ {
548
+ unsigned int count = 0;
549
+ for (XMLNode node = sheetsNode(xmlDocument()).first_child_of_type(pugi::node_element);
550
+ not node.empty();
551
+ node = node.next_sibling_of_type(pugi::node_element))
552
+ ++count;
553
+ return count;
554
+ }
555
+
556
+ /**
557
+ * @details
558
+ */
559
+ unsigned int XLWorkbook::worksheetCount() const { return static_cast<unsigned int>(worksheetNames().size()); }
560
+
561
+ /**
562
+ * @details
563
+ */
564
+ unsigned int XLWorkbook::chartsheetCount() const { return static_cast<unsigned int>(chartsheetNames().size()); }
565
+
566
+ /**
567
+ * @details
568
+ */
569
+ std::vector<std::string> XLWorkbook::sheetNames() const // 2024-05-01: whitespace support
570
+ {
571
+ std::vector<std::string> results;
572
+
573
+ for (XMLNode item = sheetsNode(xmlDocument()).first_child_of_type(pugi::node_element);
574
+ not item.empty();
575
+ item = item.next_sibling_of_type(pugi::node_element))
576
+ results.emplace_back(item.attribute("name").value());
577
+
578
+ return results;
579
+ }
580
+
581
+ /**
582
+ * @details
583
+ */
584
+ std::vector<std::string> XLWorkbook::worksheetNames() const // 2024-05-01: whitespace support
585
+ {
586
+ std::vector<std::string> results;
587
+
588
+ for (XMLNode item = sheetsNode(xmlDocument()).first_child_of_type(pugi::node_element);
589
+ not item.empty();
590
+ item = item.next_sibling_of_type(pugi::node_element))
591
+ {
592
+ XLQuery query(XLQueryType::QuerySheetType);
593
+ query.setParam("sheetID", std::string(item.attribute("r:id").value()));
594
+ if (parentDoc().execQuery(query).result<XLContentType>() == XLContentType::Worksheet)
595
+ results.emplace_back(item.attribute("name").value());
596
+ }
597
+
598
+ return results;
599
+ }
600
+
601
+ /**
602
+ * @details
603
+ */
604
+ std::vector<std::string> XLWorkbook::chartsheetNames() const // 2024-05-01: whitespace support
605
+ {
606
+ std::vector<std::string> results;
607
+
608
+ for (XMLNode item = sheetsNode(xmlDocument()).first_child_of_type(pugi::node_element);
609
+ not item.empty();
610
+ item = item.next_sibling_of_type(pugi::node_element))
611
+ {
612
+ XLQuery query(XLQueryType::QuerySheetType);
613
+ query.setParam("sheetID", std::string(item.attribute("r:id").value()));
614
+ if (parentDoc().execQuery(query).result<XLContentType>() == XLContentType::Chartsheet)
615
+ results.emplace_back(item.attribute("name").value());
616
+ }
617
+
618
+ return results;
619
+ }
620
+
621
+ /**
622
+ * @details
623
+ */
624
+ bool XLWorkbook::sheetExists(const std::string& sheetName) const { return chartsheetExists(sheetName) || worksheetExists(sheetName); }
625
+
626
+ /**
627
+ * @details
628
+ */
629
+ bool XLWorkbook::worksheetExists(const std::string& sheetName) const
630
+ {
631
+ auto wksNames = worksheetNames();
632
+ return std::find(wksNames.begin(), wksNames.end(), sheetName) != wksNames.end();
633
+ }
634
+
635
+ /**
636
+ * @details
637
+ */
638
+ bool XLWorkbook::chartsheetExists(const std::string& sheetName) const
639
+ {
640
+ auto chsNames = chartsheetNames();
641
+ return std::find(chsNames.begin(), chsNames.end(), sheetName) != chsNames.end();
642
+ }
643
+
644
+ /**
645
+ * @details The UpdateSheetName member function searches throug the usages of the old name and replaces with the
646
+ * new sheet name.
647
+ * @todo Currently, this function only searches through defined names. Consider using this function to update the
648
+ * actual sheet name as well.
649
+ */
650
+ void XLWorkbook::updateSheetReferences(
651
+ const std::string& oldName,
652
+ const std::string& newName) // 2024-05-01: whitespace support with TBD to verify definedNames logic
653
+ {
654
+ // for (auto& sheet : m_sheets) {
655
+ // if (sheet.sheetType == XLSheetType::WorkSheet)
656
+ // Worksheet(sheet.sheetNode.attribute("name").getValue())->UpdateSheetName(oldName, newName);
657
+ // }
658
+
659
+ // ===== Set up temporary variables
660
+ std::string oldNameTemp = oldName;
661
+ std::string newNameTemp = newName;
662
+ std::string formula;
663
+
664
+ // ===== If the sheet name contains spaces, it should be enclosed in single quotes (')
665
+ if (oldName.find(' ') != std::string::npos) oldNameTemp = "\'" + oldName + "\'";
666
+ if (newName.find(' ') != std::string::npos) newNameTemp = "\'" + newName + "\'";
667
+
668
+ // ===== Ensure only sheet names are replaced (references to sheets always ends with a '!')
669
+ oldNameTemp += '!';
670
+ newNameTemp += '!';
671
+
672
+ // ===== Iterate through all defined names // TODO 2024-05-01: verify definedNames logic
673
+ XMLNode definedName = xmlDocument().document_element().child("definedNames").first_child_of_type(pugi::node_element);
674
+ for (; not definedName.empty(); definedName = definedName.next_sibling_of_type(pugi::node_element)) {
675
+ formula = definedName.text().get();
676
+
677
+ // ===== Skip if formula contains a '[' and ']' (means that the defined refers to external workbook)
678
+ if (formula.find('[') == std::string::npos && formula.find(']') == std::string::npos) {
679
+ // ===== For all instances of the old sheet name in the formula, replace with the new name.
680
+ while (formula.find(oldNameTemp) != std::string::npos) { // NOLINT
681
+ formula.replace(formula.find(oldNameTemp), oldNameTemp.length(), newNameTemp);
682
+ }
683
+ definedName.text().set(formula.c_str());
684
+ }
685
+ }
686
+ }
687
+
688
+ /**
689
+ * @details
690
+ */
691
+ void XLWorkbook::setFullCalculationOnLoad()
692
+ {
693
+ XMLNode calcPr = xmlDocument().document_element().child("calcPr");
694
+
695
+ auto getOrCreateAttribute = [&calcPr](const char* attributeName) {
696
+ XMLAttribute attr = calcPr.attribute(attributeName);
697
+ if (attr.empty()) attr = calcPr.append_attribute(attributeName);
698
+ return attr;
699
+ };
700
+
701
+ getOrCreateAttribute("forceFullCalc").set_value(true);
702
+ getOrCreateAttribute("fullCalcOnLoad").set_value(true);
703
+ }
704
+
705
+ /**
706
+ * @details
707
+ */
708
+ void XLWorkbook::print(std::basic_ostream<char>& ostr) const { xmlDocument().document_element().print (ostr); }
709
+
710
+ /**
711
+ * @details
712
+ */
713
+ bool XLWorkbook::sheetIsActive(const std::string& sheetRID) const // 2024-04-30: whitespace support
714
+ {
715
+ const XMLNode workbookView = xmlDocument().document_element().child("bookViews").first_child_of_type(pugi::node_element);
716
+ const XMLAttribute activeTabAttribute = workbookView.attribute("activeTab");
717
+ const int32_t activeTabIndex = (not activeTabAttribute.empty() ? activeTabAttribute.as_int() : -1); // 2024-05-29 BUGFIX: activeTabAttribute was being read as_uint
718
+ if (activeTabIndex == -1) return false; // 2024-05-29 early exit: no need to try and match sheetRID if there *is* no active tab
719
+
720
+ int32_t index = 0; // 2024-06-04 BUGFIX: index should support -1 as 2024-05-29 change below sets it to -1 for preventing a match with activeTabIndex
721
+ XMLNode item = sheetsNode(xmlDocument()).first_child_of_type(pugi::node_element);
722
+ while (not item.empty()) {
723
+ if (std::string(item.attribute("r:id").value()) == sheetRID) break;
724
+ ++index;
725
+ item = item.next_sibling_of_type(pugi::node_element);
726
+ }
727
+ if (item.empty()) index = -1; // 2024-05-29: prevent a match if activeTabIndex invalidly points to a non-existing sheet
728
+
729
+ return index == activeTabIndex;
730
+ }
731
+
732
+ /**
733
+ * @details
734
+ * @done: no exception if setSheetActive fails, instead return false
735
+ * @done: fail by returning false if sheetRID is either not found or belongs to a sheet that is not visible
736
+ * @note: this makes some bug fixes from 2024-05-29 obsolete
737
+ * @note: changed behavior: attempting to setSheetActive on a non-existing or non-visible sheet will no longer unselect the active sheet
738
+ */
739
+ bool XLWorkbook::setSheetActive(const std::string& sheetRID) // 2024-04-30: whitespace support
740
+ {
741
+ XMLNode workbookView = xmlDocument().document_element().child("bookViews").first_child_of_type(pugi::node_element);
742
+ const XMLAttribute activeTabAttribute = workbookView.attribute("activeTab");
743
+ int32_t activeTabIndex = -1; // negative == no active tab identified
744
+ if (not activeTabAttribute.empty()) activeTabIndex = activeTabAttribute.as_int();
745
+
746
+ int32_t index = 0; // index should have the same data type as activeTabIndex for comparisons
747
+ XMLNode item = sheetsNode(xmlDocument()).first_child_of_type(pugi::node_element);
748
+ while (not item.empty() && (std::string(item.attribute("r:id").value()) != sheetRID)) {
749
+ ++index;
750
+ item = item.next_sibling_of_type(pugi::node_element);
751
+ }
752
+ // ===== 2024-06-19: Fail without action if sheet is not found or sheet is not visible
753
+ if (item.empty() || !isVisible(item)) return false;
754
+
755
+ // NOTE: XLSheet XLWorkbook::sheet(uint16_t index) is using a 1-based index, while the workbookView attribute activeTab is using a
756
+ // 0-based index
757
+
758
+ // ===== If an active sheet was found, but sheetRID is not the same sheet: attempt to unselect the old active sheet.
759
+ if ((activeTabIndex != -1) && (index != activeTabIndex)) sheet(activeTabIndex + 1).setSelected(false); // see NOTE above
760
+
761
+ // ===== Set the activeTab property for the workbook.xml sheets node
762
+ if (workbookView.attribute("activeTab").empty()) workbookView.append_attribute("activeTab");
763
+ workbookView.attribute("activeTab").set_value(index);
764
+ // sheet(index + 1).setSelected(true); // it appears that an active sheet does not have to be selected
765
+ return true; // success
766
+ }
767
+
768
+ /**
769
+ * @details evaluate a sheet node state attribute where "hidden" or "veryHidden" means not visible
770
+ * @note 2024-05-01 BUGFIX: veryHidden was not checked (in setSheetActive)
771
+ */
772
+ bool XLWorkbook::isVisibleState(std::string const& state) const { return (state != "hidden" && state != "veryHidden"); }
773
+
774
+ /**
775
+ * @details function only returns meaningful information when used with a sheet node
776
+ * (or nodes with state attribute allowing values visible, hidden, veryHidden)
777
+ */
778
+ bool XLWorkbook::isVisible(XMLNode const& sheetNode) const
779
+ {
780
+ if (sheetNode.empty()) return false; // empty nodes can't be visible
781
+ if (sheetNode.attribute("state").empty()) return true; // no state attribute means no hidden-ness can be flagged
782
+ // ===== Attribute exists and value must be checked
783
+ return isVisibleState(sheetNode.attribute("state").value());
784
+ }