react-native-nitro-xlsx 0.1.4 → 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.
- package/NitroXlsx.podspec +27 -27
- package/Package.swift +35 -10
- package/README.md +220 -58
- package/android/CMakeLists.txt +24 -27
- package/android/cpp-adapter.cpp +12 -0
- package/android/src/main/java/com/margelo/nitro/xlsx/NitroXlsxPackage.kt +9 -0
- package/cpp/HybridNitroXlsx.cpp +25 -179
- package/cpp/HybridNitroXlsx.hpp +2 -2
- package/cpp/HybridXlsxConditionalFormat.cpp +252 -0
- package/cpp/HybridXlsxConditionalFormat.hpp +62 -0
- package/cpp/HybridXlsxConditionalFormats.cpp +46 -0
- package/cpp/HybridXlsxConditionalFormats.hpp +28 -0
- package/cpp/HybridXlsxWorkbook.cpp +159 -196
- package/cpp/HybridXlsxWorkbook.hpp +7 -2
- package/cpp/HybridXlsxWorksheet.cpp +433 -62
- package/cpp/HybridXlsxWorksheet.hpp +73 -26
- package/cpp/XlsxCacheDir.cpp +76 -0
- package/cpp/XlsxCacheDir.hpp +27 -0
- package/cpp/XlsxError.hpp +68 -0
- package/cpp/XlsxJson.cpp +185 -0
- package/cpp/XlsxJson.hpp +36 -0
- package/ios/XlsxCacheDir.mm +60 -0
- package/nitrogen/generated/android/NitroXlsx+autolinking.cmake +2 -0
- package/nitrogen/generated/shared/c++/HybridNitroXlsxSpec.hpp +5 -3
- package/nitrogen/generated/shared/c++/HybridXlsxConditionalFormatSpec.cpp +54 -0
- package/nitrogen/generated/shared/c++/HybridXlsxConditionalFormatSpec.hpp +95 -0
- package/nitrogen/generated/shared/c++/HybridXlsxConditionalFormatsSpec.cpp +24 -0
- package/nitrogen/generated/shared/c++/HybridXlsxConditionalFormatsSpec.hpp +68 -0
- package/nitrogen/generated/shared/c++/HybridXlsxWorkbookSpec.cpp +3 -0
- package/nitrogen/generated/shared/c++/HybridXlsxWorkbookSpec.hpp +6 -1
- package/nitrogen/generated/shared/c++/HybridXlsxWorksheetSpec.cpp +47 -19
- package/nitrogen/generated/shared/c++/HybridXlsxWorksheetSpec.hpp +52 -20
- package/package.json +3 -3
- package/scripts/run-cpp-tests.sh +14 -0
- package/src/__mocks__/react-native-nitro-modules.ts +1 -0
- package/src/__tests__/index.test.ts +76 -7
- package/src/index.ts +107 -18
- package/src/specs/NitroXlsx.nitro.ts +141 -44
- package/thirdparty/OpenXLSX/.clang-format +118 -0
- package/thirdparty/OpenXLSX/.clang-tidy +28 -0
- package/thirdparty/OpenXLSX/.gitignore +130 -0
- package/thirdparty/OpenXLSX/Benchmarks/2024-07-29-benchmarks_before_XMLNode_wrappers +46 -0
- package/thirdparty/OpenXLSX/Benchmarks/2024-07-29-benchmarks_with_XMLNode_wrappers_and_namespace_and_stripping +49 -0
- package/thirdparty/OpenXLSX/Benchmarks/2024-07-29-benchmarks_with_XMLNode_wrappers_and_namespace_char_support +49 -0
- package/thirdparty/OpenXLSX/Benchmarks/2024-07-29-benchmarks_with_XMLNode_wrappers_and_namespace_support +49 -0
- package/thirdparty/OpenXLSX/Benchmarks/2024-07-29-benchmarks_with_XMLNode_wrappers_and_namespaced_name_disabled +49 -0
- package/thirdparty/OpenXLSX/Benchmarks/2024-08-11-benchmarks_post-XLCellIterator-Rework +46 -0
- package/thirdparty/OpenXLSX/Benchmarks/2024-08-14-benchmarks_post-default-row-column-style-support +46 -0
- package/thirdparty/OpenXLSX/Benchmarks/2024-09-02-benchmarks +46 -0
- package/thirdparty/OpenXLSX/Benchmarks/2024-12-19-benchmarks +46 -0
- package/thirdparty/OpenXLSX/Benchmarks/2024-12-30-benchmarks-post-XLSharedStrings-by-ref +46 -0
- package/thirdparty/OpenXLSX/Benchmarks/2025-01-09-benchmarks-post-conditionalFormatsAndSheetProtection +46 -0
- package/thirdparty/OpenXLSX/Benchmarks/2025-01-10-benchmarks-post-XLCellValue-bugfix +46 -0
- package/thirdparty/OpenXLSX/Benchmarks/2025-01-31-benchmarks-post-XLComments-implementation +46 -0
- package/thirdparty/OpenXLSX/Benchmarks/2025-02-02-benchmarks-post-XLRowIterator-Rework +46 -0
- package/thirdparty/OpenXLSX/Benchmarks/2025-07-20-benchmarks-after-hiding-pugixml-internals +46 -0
- package/thirdparty/OpenXLSX/Benchmarks/2025-08-29-benchmarks-after-code-review-with-libzip +46 -0
- package/thirdparty/OpenXLSX/Benchmarks/Benchmark.cpp +249 -0
- package/thirdparty/OpenXLSX/Benchmarks/CMakeLists.txt +19 -0
- package/thirdparty/OpenXLSX/CMakeLists.txt +466 -0
- package/thirdparty/OpenXLSX/Documentation/CMakeLists.txt +31 -0
- package/thirdparty/OpenXLSX/Documentation/Doxyfile.in +2471 -0
- package/thirdparty/OpenXLSX/Documentation/DoxygenLayout.xml +194 -0
- package/thirdparty/OpenXLSX/Documentation/customdoxygen.css +1355 -0
- package/thirdparty/OpenXLSX/Examples/CMakeLists.txt +103 -0
- package/thirdparty/OpenXLSX/Examples/Demo1.cpp +279 -0
- package/thirdparty/OpenXLSX/Examples/Demo10.cpp +545 -0
- package/thirdparty/OpenXLSX/Examples/Demo1A.cpp +137 -0
- package/thirdparty/OpenXLSX/Examples/Demo2.cpp +65 -0
- package/thirdparty/OpenXLSX/Examples/Demo3.cpp +89 -0
- package/thirdparty/OpenXLSX/Examples/Demo4.cpp +86 -0
- package/thirdparty/OpenXLSX/Examples/Demo5.cpp +77 -0
- package/thirdparty/OpenXLSX/Examples/Demo6.cpp +103 -0
- package/thirdparty/OpenXLSX/Examples/Demo7.cpp +79 -0
- package/thirdparty/OpenXLSX/Examples/Demo8.cpp +117 -0
- package/thirdparty/OpenXLSX/Examples/Demo9.cpp +363 -0
- package/thirdparty/OpenXLSX/Examples/cmake/FindLIBZIP.cmake +61 -0
- package/thirdparty/OpenXLSX/Examples/external/CustomZip/CustomZip.hpp +256 -0
- package/thirdparty/OpenXLSX/LICENSE.md +29 -0
- package/thirdparty/OpenXLSX/Makefile.GNU +530 -0
- package/thirdparty/OpenXLSX/Notes/TBDs.txt +16 -0
- package/thirdparty/OpenXLSX/Notes/confirmed-TBCs.txt +8 -0
- package/thirdparty/OpenXLSX/Notes/styles-missing-support.xml +12 -0
- package/thirdparty/OpenXLSX/Notes/todo-list.txt +108 -0
- package/thirdparty/OpenXLSX/OpenXLSX/CMakeLists.txt +631 -0
- package/thirdparty/OpenXLSX/OpenXLSX/OpenXLSX.hpp +63 -0
- package/thirdparty/OpenXLSX/OpenXLSX/OpenXLSXConfig.cmake +11 -0
- package/thirdparty/OpenXLSX/OpenXLSX/cmake/bundle_static_library.cmake +198 -0
- package/thirdparty/OpenXLSX/OpenXLSX/cmake/patch_pkg_config.cmake +69 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/IZipArchive.hpp +361 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/OpenXLSX-Exports.hpp +12 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/XLCell.hpp +367 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/XLCellIterator.hpp +252 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/XLCellRange.hpp +223 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/XLCellReference.hpp +317 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/XLCellValue.hpp +793 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/XLColor.hpp +232 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/XLColumn.hpp +159 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/XLCommandQuery.hpp +228 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/XLComments.hpp +270 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/XLConstants.hpp +18 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/XLContentTypes.hpp +264 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/XLDateTime.hpp +175 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/XLDocument.hpp +505 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/XLDrawing.hpp +452 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/XLException.hpp +161 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/XLFormula.hpp +375 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/XLIterator.hpp +40 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/XLMergeCells.hpp +216 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/XLProperties.hpp +348 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/XLRelationships.hpp +348 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/XLRow.hpp +721 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/XLRowData.hpp +488 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/XLSharedStrings.hpp +204 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/XLSheet.hpp +1640 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/XLStyles.hpp +2390 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/XLTables.hpp +132 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/XLWorkbook.hpp +404 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/XLXmlData.hpp +283 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/XLXmlFile.hpp +194 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/XLXmlParser.hpp +282 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/XLXmlParserForwardDeclarations.hpp +85 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/XLZipArchive.hpp +232 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/detail/LibZip.hpp +447 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/detail/OpenXLSXFileSystemTools.hpp +207 -0
- package/thirdparty/OpenXLSX/OpenXLSX/headers/detail/Zippy.hpp +1375 -0
- package/thirdparty/OpenXLSX/OpenXLSX/sources/XLCell.cpp +340 -0
- package/thirdparty/OpenXLSX/OpenXLSX/sources/XLCellIterator.cpp +427 -0
- package/thirdparty/OpenXLSX/OpenXLSX/sources/XLCellRange.cpp +221 -0
- package/thirdparty/OpenXLSX/OpenXLSX/sources/XLCellReference.cpp +408 -0
- package/thirdparty/OpenXLSX/OpenXLSX/sources/XLCellValue.cpp +519 -0
- package/thirdparty/OpenXLSX/OpenXLSX/sources/XLColor.cpp +202 -0
- package/thirdparty/OpenXLSX/OpenXLSX/sources/XLColumn.cpp +141 -0
- package/thirdparty/OpenXLSX/OpenXLSX/sources/XLComments.cpp +637 -0
- package/thirdparty/OpenXLSX/OpenXLSX/sources/XLContentTypes.cpp +329 -0
- package/thirdparty/OpenXLSX/OpenXLSX/sources/XLDateTime.cpp +269 -0
- package/thirdparty/OpenXLSX/OpenXLSX/sources/XLDocument.cpp +1678 -0
- package/thirdparty/OpenXLSX/OpenXLSX/sources/XLDrawing.cpp +784 -0
- package/thirdparty/OpenXLSX/OpenXLSX/sources/XLFormula.cpp +201 -0
- package/thirdparty/OpenXLSX/OpenXLSX/sources/XLMergeCells.cpp +357 -0
- package/thirdparty/OpenXLSX/OpenXLSX/sources/XLProperties.cpp +810 -0
- package/thirdparty/OpenXLSX/OpenXLSX/sources/XLRelationships.cpp +529 -0
- package/thirdparty/OpenXLSX/OpenXLSX/sources/XLRow.cpp +918 -0
- package/thirdparty/OpenXLSX/OpenXLSX/sources/XLRowData.cpp +508 -0
- package/thirdparty/OpenXLSX/OpenXLSX/sources/XLSharedStrings.cpp +220 -0
- package/thirdparty/OpenXLSX/OpenXLSX/sources/XLSheet.cpp +1970 -0
- package/thirdparty/OpenXLSX/OpenXLSX/sources/XLStyles.cpp +3014 -0
- package/thirdparty/OpenXLSX/OpenXLSX/sources/XLTables.cpp +125 -0
- package/thirdparty/OpenXLSX/OpenXLSX/sources/XLWorkbook.cpp +784 -0
- package/thirdparty/OpenXLSX/OpenXLSX/sources/XLXmlData.cpp +247 -0
- package/thirdparty/OpenXLSX/OpenXLSX/sources/XLXmlFile.cpp +160 -0
- package/thirdparty/OpenXLSX/OpenXLSX/sources/XLXmlParser.cpp +261 -0
- package/thirdparty/OpenXLSX/OpenXLSX/sources/XLZipArchive.cpp +266 -0
- package/thirdparty/OpenXLSX/OpenXLSX/sources/utilities/XLUtilities.hpp +478 -0
- package/thirdparty/OpenXLSX/README.md +1279 -0
- package/thirdparty/OpenXLSX/Scripts/cmake-cleanup.sh +102 -0
- package/thirdparty/OpenXLSX/Scripts/compile.sh +23 -0
- package/thirdparty/OpenXLSX/Scripts/demos-cleanup.sh +25 -0
- package/thirdparty/OpenXLSX/Scripts/demos-run-all.sh +60 -0
- package/thirdparty/OpenXLSX/Scripts/guarded-xml-format.sh +47 -0
- package/thirdparty/OpenXLSX/Scripts/make-gnu.sh +11 -0
- package/thirdparty/OpenXLSX/Scripts/uninstall-manifest.sh +48 -0
- package/thirdparty/OpenXLSX/Scripts/xml-format-all.sh +19 -0
- package/thirdparty/OpenXLSX/Scripts/xml-format.sh +38 -0
- package/thirdparty/OpenXLSX/Tests/CMakeLists.txt +37 -0
- package/thirdparty/OpenXLSX/Tests/catch/catch.hpp +17799 -0
- package/thirdparty/OpenXLSX/Tests/catch/catch_reporter_automake.hpp +68 -0
- package/thirdparty/OpenXLSX/Tests/catch/catch_reporter_sonarqube.hpp +182 -0
- package/thirdparty/OpenXLSX/Tests/catch/catch_reporter_tap.hpp +278 -0
- package/thirdparty/OpenXLSX/Tests/catch/catch_reporter_teamcity.hpp +212 -0
- package/thirdparty/OpenXLSX/Tests/main.cpp +55 -0
- package/thirdparty/OpenXLSX/Tests/testXLCell.cpp +176 -0
- package/thirdparty/OpenXLSX/Tests/testXLCellRange.cpp +180 -0
- package/thirdparty/OpenXLSX/Tests/testXLCellReference.cpp +160 -0
- package/thirdparty/OpenXLSX/Tests/testXLCellValue.cpp +366 -0
- package/thirdparty/OpenXLSX/Tests/testXLCellValueProxy.cpp +255 -0
- package/thirdparty/OpenXLSX/Tests/testXLColor.cpp +75 -0
- package/thirdparty/OpenXLSX/Tests/testXLDateTime.cpp +229 -0
- package/thirdparty/OpenXLSX/Tests/testXLDocument.cpp +197 -0
- package/thirdparty/OpenXLSX/Tests/testXLFormula.cpp +131 -0
- package/thirdparty/OpenXLSX/Tests/testXLRow.cpp +597 -0
- package/thirdparty/OpenXLSX/Tests/testXLSheet.cpp +77 -0
- package/thirdparty/OpenXLSX/Tests/ziptest-with-libs.cpp +88 -0
- package/thirdparty/OpenXLSX/Tests/ziptest.cpp +735 -0
- package/thirdparty/OpenXLSX/cmake/get-git-HEAD-ID.cmake +45 -0
- package/thirdparty/OpenXLSX/cmake/libopenxlsxCPackOptions.cmake.in +20 -0
- package/thirdparty/OpenXLSX/cmake/manage_dependency.cmake +813 -0
- package/thirdparty/OpenXLSX/cmake/recursive_library_type_test.cmake +52 -0
- package/thirdparty/OpenXLSX/gnu-make-crutch/OpenXLSX-Exports-shared.hpp +42 -0
- package/thirdparty/OpenXLSX/gnu-make-crutch/OpenXLSX-Exports-static.hpp +42 -0
- package/thirdparty/OpenXLSX/vcpkg.json +24 -0
- package/thirdparty/README.md +42 -0
- package/thirdparty/miniz/.clang-format +47 -0
- package/thirdparty/miniz/.travis.yml +2 -0
- package/thirdparty/miniz/CMakeLists.txt +333 -0
- package/thirdparty/miniz/CMakePresets.json +31 -0
- package/thirdparty/miniz/ChangeLog.md +272 -0
- package/thirdparty/miniz/Config.cmake.in +1 -0
- package/thirdparty/miniz/LICENSE +22 -0
- package/thirdparty/miniz/amalgamate.sh +57 -0
- package/thirdparty/miniz/examples/example1.c +105 -0
- package/thirdparty/miniz/examples/example2.c +164 -0
- package/thirdparty/miniz/examples/example3.c +269 -0
- package/thirdparty/miniz/examples/example4.c +102 -0
- package/thirdparty/miniz/examples/example5.c +327 -0
- package/thirdparty/miniz/examples/example6.c +189 -0
- package/thirdparty/miniz/meson.build +21 -0
- package/thirdparty/miniz/miniz.c +646 -0
- package/thirdparty/miniz/miniz.h +615 -0
- package/thirdparty/miniz/miniz.pc.in +13 -0
- package/thirdparty/miniz/miniz_common.h +89 -0
- package/thirdparty/miniz/miniz_export.h +20 -0
- package/thirdparty/miniz/miniz_tdef.c +1602 -0
- package/thirdparty/miniz/miniz_tdef.h +199 -0
- package/thirdparty/miniz/miniz_tinfl.c +778 -0
- package/thirdparty/miniz/miniz_tinfl.h +150 -0
- package/thirdparty/miniz/miniz_zip.c +4895 -0
- package/thirdparty/miniz/miniz_zip.h +454 -0
- package/thirdparty/miniz/readme.md +46 -0
- package/thirdparty/miniz/test.sh +36 -0
- package/thirdparty/miniz/tests/add_in_place_fuzzer.c +87 -0
- package/thirdparty/miniz/tests/catch_amalgamated.cpp +10795 -0
- package/thirdparty/miniz/tests/catch_amalgamated.hpp +13143 -0
- package/thirdparty/miniz/tests/checksum_fuzzer.c +26 -0
- package/thirdparty/miniz/tests/compress_fuzzer.c +91 -0
- package/thirdparty/miniz/tests/flush_fuzzer.c +88 -0
- package/thirdparty/miniz/tests/fuzz_main.c +55 -0
- package/thirdparty/miniz/tests/large_fuzzer.c +133 -0
- package/thirdparty/miniz/tests/main.cpp +185 -0
- package/thirdparty/miniz/tests/miniz_tdefl_fuzzer.cc +115 -0
- package/thirdparty/miniz/tests/miniz_tester.cpp +1881 -0
- package/thirdparty/miniz/tests/miniz_zip_validate_fuzzer.cc +71 -0
- package/thirdparty/miniz/tests/miniz_zip_writer_fuzzer.cc +96 -0
- package/thirdparty/miniz/tests/ossfuzz.sh +48 -0
- package/thirdparty/miniz/tests/small_fuzzer.c +126 -0
- package/thirdparty/miniz/tests/timer.cpp +152 -0
- package/thirdparty/miniz/tests/timer.h +40 -0
- package/thirdparty/miniz/tests/uncompress2_fuzzer.c +21 -0
- package/thirdparty/miniz/tests/uncompress_fuzzer.c +30 -0
- package/thirdparty/miniz/tests/zip.dict +9 -0
- package/thirdparty/miniz/tests/zip_fuzzer.c +63 -0
- package/thirdparty/pugixml/.codecov.yml +7 -0
- package/thirdparty/pugixml/.gitattributes +1 -0
- package/thirdparty/pugixml/CMakeLists.txt +330 -0
- package/thirdparty/pugixml/LICENSE.md +24 -0
- package/thirdparty/pugixml/Makefile +98 -0
- package/thirdparty/pugixml/README.md +81 -0
- package/thirdparty/pugixml/SECURITY.md +9 -0
- package/thirdparty/pugixml/appveyor.yml +50 -0
- package/thirdparty/pugixml/docs/config.adoc +7 -0
- package/thirdparty/pugixml/docs/images/dom_tree.png +0 -0
- package/thirdparty/pugixml/docs/images/vs2005_link1.png +0 -0
- package/thirdparty/pugixml/docs/images/vs2005_link2.png +0 -0
- package/thirdparty/pugixml/docs/images/vs2005_pch1.png +0 -0
- package/thirdparty/pugixml/docs/images/vs2005_pch2.png +0 -0
- package/thirdparty/pugixml/docs/images/vs2005_pch3.png +0 -0
- package/thirdparty/pugixml/docs/images/vs2005_pch4.png +0 -0
- package/thirdparty/pugixml/docs/images/vs2010_link1.png +0 -0
- package/thirdparty/pugixml/docs/images/vs2010_link2.png +0 -0
- package/thirdparty/pugixml/docs/manual.adoc +3326 -0
- package/thirdparty/pugixml/docs/manual.html +6395 -0
- package/thirdparty/pugixml/docs/quickstart.adoc +287 -0
- package/thirdparty/pugixml/docs/quickstart.html +1107 -0
- package/thirdparty/pugixml/docs/samples/character.xml +8 -0
- package/thirdparty/pugixml/docs/samples/custom_memory_management.cpp +27 -0
- package/thirdparty/pugixml/docs/samples/include.cpp +64 -0
- package/thirdparty/pugixml/docs/samples/load_error_handling.cpp +33 -0
- package/thirdparty/pugixml/docs/samples/load_file.cpp +16 -0
- package/thirdparty/pugixml/docs/samples/load_memory.cpp +66 -0
- package/thirdparty/pugixml/docs/samples/load_options.cpp +30 -0
- package/thirdparty/pugixml/docs/samples/load_stream.cpp +97 -0
- package/thirdparty/pugixml/docs/samples/modify_add.cpp +29 -0
- package/thirdparty/pugixml/docs/samples/modify_base.cpp +43 -0
- package/thirdparty/pugixml/docs/samples/modify_remove.cpp +27 -0
- package/thirdparty/pugixml/docs/samples/save_custom_writer.cpp +116 -0
- package/thirdparty/pugixml/docs/samples/save_declaration.cpp +27 -0
- package/thirdparty/pugixml/docs/samples/save_file.cpp +17 -0
- package/thirdparty/pugixml/docs/samples/save_options.cpp +48 -0
- package/thirdparty/pugixml/docs/samples/save_stream.cpp +18 -0
- package/thirdparty/pugixml/docs/samples/save_subtree.cpp +26 -0
- package/thirdparty/pugixml/docs/samples/text.cpp +35 -0
- package/thirdparty/pugixml/docs/samples/transitions.xml +7 -0
- package/thirdparty/pugixml/docs/samples/traverse_base.cpp +51 -0
- package/thirdparty/pugixml/docs/samples/traverse_iter.cpp +27 -0
- package/thirdparty/pugixml/docs/samples/traverse_predicate.cpp +48 -0
- package/thirdparty/pugixml/docs/samples/traverse_rangefor.cpp +32 -0
- package/thirdparty/pugixml/docs/samples/traverse_walker.cpp +35 -0
- package/thirdparty/pugixml/docs/samples/tree.xml +12 -0
- package/thirdparty/pugixml/docs/samples/weekly-shift_jis.xml +78 -0
- package/thirdparty/pugixml/docs/samples/weekly-utf-16.xml +0 -0
- package/thirdparty/pugixml/docs/samples/weekly-utf-8.xml +78 -0
- package/thirdparty/pugixml/docs/samples/xgconsole.xml +12 -0
- package/thirdparty/pugixml/docs/samples/xpath_error.cpp +43 -0
- package/thirdparty/pugixml/docs/samples/xpath_query.cpp +36 -0
- package/thirdparty/pugixml/docs/samples/xpath_select.cpp +28 -0
- package/thirdparty/pugixml/docs/samples/xpath_variables.cpp +38 -0
- package/thirdparty/pugixml/readme.txt +50 -0
- package/thirdparty/pugixml/scripts/archive.py +54 -0
- package/thirdparty/pugixml/scripts/cocoapods_push.sh +4 -0
- package/thirdparty/pugixml/scripts/natvis/pugixml.natvis +77 -0
- package/thirdparty/pugixml/scripts/natvis/pugixml_compact.natvis +506 -0
- package/thirdparty/pugixml/scripts/nuget/build/native/pugixml-propertiesui.xml +17 -0
- package/thirdparty/pugixml/scripts/nuget/build/native/pugixml.targets +28 -0
- package/thirdparty/pugixml/scripts/nuget/pugixml.nuspec +20 -0
- package/thirdparty/pugixml/scripts/nuget_build.ps1 +60 -0
- package/thirdparty/pugixml/scripts/premake4.lua +92 -0
- package/thirdparty/pugixml/scripts/pugixml-config.cmake.in +12 -0
- package/thirdparty/pugixml/scripts/pugixml.pc.in +11 -0
- package/thirdparty/pugixml/scripts/pugixml.podspec +14 -0
- package/thirdparty/pugixml/scripts/pugixml.xcodeproj/project.pbxproj +212 -0
- package/thirdparty/pugixml/scripts/pugixml_airplay.mkf +13 -0
- package/thirdparty/pugixml/scripts/pugixml_codeblocks.cbp +44 -0
- package/thirdparty/pugixml/scripts/pugixml_codelite.project +56 -0
- package/thirdparty/pugixml/scripts/pugixml_dll.rc +45 -0
- package/thirdparty/pugixml/scripts/pugixml_vs2005.vcproj +343 -0
- package/thirdparty/pugixml/scripts/pugixml_vs2005_static.vcproj +343 -0
- package/thirdparty/pugixml/scripts/pugixml_vs2008.vcproj +339 -0
- package/thirdparty/pugixml/scripts/pugixml_vs2008_static.vcproj +339 -0
- package/thirdparty/pugixml/scripts/pugixml_vs2010.vcxproj +191 -0
- package/thirdparty/pugixml/scripts/pugixml_vs2010_static.vcxproj +191 -0
- package/thirdparty/pugixml/scripts/pugixml_vs2013.vcxproj +199 -0
- package/thirdparty/pugixml/scripts/pugixml_vs2013_static.vcxproj +199 -0
- package/thirdparty/pugixml/scripts/pugixml_vs2015.vcxproj +172 -0
- package/thirdparty/pugixml/scripts/pugixml_vs2015_static.vcxproj +176 -0
- package/thirdparty/pugixml/scripts/pugixml_vs2017.vcxproj +172 -0
- package/thirdparty/pugixml/scripts/pugixml_vs2017_static.vcxproj +176 -0
- package/thirdparty/pugixml/scripts/pugixml_vs2019.vcxproj +176 -0
- package/thirdparty/pugixml/scripts/pugixml_vs2019_static.vcxproj +180 -0
- package/thirdparty/pugixml/scripts/pugixml_vs2022.vcxproj +176 -0
- package/thirdparty/pugixml/scripts/pugixml_vs2022_static.vcxproj +180 -0
- package/thirdparty/pugixml/scripts/pugixml_vs2026.vcxproj +176 -0
- package/thirdparty/pugixml/scripts/pugixml_vs2026_static.vcxproj +180 -0
- package/thirdparty/pugixml/scripts/sbom.cdx.json +47 -0
- package/thirdparty/pugixml/src/pugiconfig.hpp +81 -0
- package/thirdparty/pugixml/src/pugixml.cpp +13776 -0
- package/thirdparty/pugixml/src/pugixml.hpp +1604 -0
- package/thirdparty/pugixml/tests/allocator.cpp +175 -0
- package/thirdparty/pugixml/tests/allocator.hpp +10 -0
- package/thirdparty/pugixml/tests/autotest-appveyor.ps1 +93 -0
- package/thirdparty/pugixml/tests/cmake-appveyor.ps1 +57 -0
- package/thirdparty/pugixml/tests/data/empty.xml +0 -0
- package/thirdparty/pugixml/tests/data/large.xml +1 -0
- package/thirdparty/pugixml/tests/data/latintest_latin1.xml +1 -0
- package/thirdparty/pugixml/tests/data/latintest_utf8.xml +1 -0
- package/thirdparty/pugixml/tests/data/multiline.xml +3 -0
- package/thirdparty/pugixml/tests/data/small.xml +1 -0
- package/thirdparty/pugixml/tests/data/truncation.xml +19 -0
- package/thirdparty/pugixml/tests/data/utftest_utf16_be.xml +0 -0
- package/thirdparty/pugixml/tests/data/utftest_utf16_be_bom.xml +0 -0
- package/thirdparty/pugixml/tests/data/utftest_utf16_be_clean.xml +0 -0
- package/thirdparty/pugixml/tests/data/utftest_utf16_be_nodecl.xml +0 -0
- package/thirdparty/pugixml/tests/data/utftest_utf16_le.xml +0 -0
- package/thirdparty/pugixml/tests/data/utftest_utf16_le_bom.xml +0 -0
- package/thirdparty/pugixml/tests/data/utftest_utf16_le_clean.xml +0 -0
- package/thirdparty/pugixml/tests/data/utftest_utf16_le_nodecl.xml +0 -0
- package/thirdparty/pugixml/tests/data/utftest_utf32_be.xml +0 -0
- package/thirdparty/pugixml/tests/data/utftest_utf32_be_bom.xml +0 -0
- package/thirdparty/pugixml/tests/data/utftest_utf32_be_clean.xml +0 -0
- package/thirdparty/pugixml/tests/data/utftest_utf32_be_nodecl.xml +0 -0
- package/thirdparty/pugixml/tests/data/utftest_utf32_le.xml +0 -0
- package/thirdparty/pugixml/tests/data/utftest_utf32_le_bom.xml +0 -0
- package/thirdparty/pugixml/tests/data/utftest_utf32_le_clean.xml +0 -0
- package/thirdparty/pugixml/tests/data/utftest_utf32_le_nodecl.xml +0 -0
- package/thirdparty/pugixml/tests/data/utftest_utf8.xml +87 -0
- package/thirdparty/pugixml/tests/data/utftest_utf8_bom.xml +87 -0
- package/thirdparty/pugixml/tests/data/utftest_utf8_clean.xml +84 -0
- package/thirdparty/pugixml/tests/data/utftest_utf8_nodecl.xml +86 -0
- package/thirdparty/pugixml/tests/data//321/202/320/265/321/201/321/202.xml +1 -0
- package/thirdparty/pugixml/tests/data_fuzz_parse/basic.xml +1 -0
- package/thirdparty/pugixml/tests/data_fuzz_parse/doctype.xml +1 -0
- package/thirdparty/pugixml/tests/data_fuzz_parse/refs.xml +1 -0
- package/thirdparty/pugixml/tests/data_fuzz_parse/types.xml +1 -0
- package/thirdparty/pugixml/tests/data_fuzz_parse/utf16.xml +0 -0
- package/thirdparty/pugixml/tests/data_fuzz_parse/utf32.xml +0 -0
- package/thirdparty/pugixml/tests/data_fuzz_xpath/basic.xpath +1 -0
- package/thirdparty/pugixml/tests/data_fuzz_xpath/functions.xpath +1 -0
- package/thirdparty/pugixml/tests/data_fuzz_xpath/math.xpath +1 -0
- package/thirdparty/pugixml/tests/data_fuzz_xpath/path.xpath +1 -0
- package/thirdparty/pugixml/tests/data_fuzz_xpath/predicate.xpath +1 -0
- package/thirdparty/pugixml/tests/fuzz_parse.cpp +14 -0
- package/thirdparty/pugixml/tests/fuzz_parse.dict +72 -0
- package/thirdparty/pugixml/tests/fuzz_setup.sh +11 -0
- package/thirdparty/pugixml/tests/fuzz_xpath.cpp +46 -0
- package/thirdparty/pugixml/tests/fuzz_xpath.dict +72 -0
- package/thirdparty/pugixml/tests/helpers.hpp +114 -0
- package/thirdparty/pugixml/tests/main.cpp +218 -0
- package/thirdparty/pugixml/tests/test.cpp +220 -0
- package/thirdparty/pugixml/tests/test.hpp +175 -0
- package/thirdparty/pugixml/tests/test_compact.cpp +150 -0
- package/thirdparty/pugixml/tests/test_deprecated.cpp +25 -0
- package/thirdparty/pugixml/tests/test_document.cpp +1910 -0
- package/thirdparty/pugixml/tests/test_dom_modify.cpp +2122 -0
- package/thirdparty/pugixml/tests/test_dom_text.cpp +601 -0
- package/thirdparty/pugixml/tests/test_dom_traverse.cpp +1481 -0
- package/thirdparty/pugixml/tests/test_header_guard.cpp +3 -0
- package/thirdparty/pugixml/tests/test_header_iosfwd_1.cpp +3 -0
- package/thirdparty/pugixml/tests/test_header_iosfwd_2.cpp +3 -0
- package/thirdparty/pugixml/tests/test_header_iostream_1.cpp +3 -0
- package/thirdparty/pugixml/tests/test_header_iostream_2.cpp +3 -0
- package/thirdparty/pugixml/tests/test_header_only_1.cpp +21 -0
- package/thirdparty/pugixml/tests/test_header_only_2.cpp +21 -0
- package/thirdparty/pugixml/tests/test_header_string_1.cpp +3 -0
- package/thirdparty/pugixml/tests/test_header_string_2.cpp +3 -0
- package/thirdparty/pugixml/tests/test_header_string_iostream.cpp +5 -0
- package/thirdparty/pugixml/tests/test_memory.cpp +303 -0
- package/thirdparty/pugixml/tests/test_parse.cpp +1463 -0
- package/thirdparty/pugixml/tests/test_parse_doctype.cpp +366 -0
- package/thirdparty/pugixml/tests/test_unicode.cpp +152 -0
- package/thirdparty/pugixml/tests/test_version.cpp +5 -0
- package/thirdparty/pugixml/tests/test_write.cpp +757 -0
- package/thirdparty/pugixml/tests/test_xpath.cpp +833 -0
- package/thirdparty/pugixml/tests/test_xpath_api.cpp +646 -0
- package/thirdparty/pugixml/tests/test_xpath_functions.cpp +844 -0
- package/thirdparty/pugixml/tests/test_xpath_operators.cpp +566 -0
- package/thirdparty/pugixml/tests/test_xpath_parse.cpp +428 -0
- package/thirdparty/pugixml/tests/test_xpath_paths.cpp +787 -0
- package/thirdparty/pugixml/tests/test_xpath_paths_abbrev_w3c.cpp +219 -0
- package/thirdparty/pugixml/tests/test_xpath_paths_w3c.cpp +312 -0
- package/thirdparty/pugixml/tests/test_xpath_variables.cpp +683 -0
- package/thirdparty/pugixml/tests/test_xpath_xalan_1.cpp +411 -0
- package/thirdparty/pugixml/tests/test_xpath_xalan_2.cpp +417 -0
- package/thirdparty/pugixml/tests/test_xpath_xalan_3.cpp +321 -0
- package/thirdparty/pugixml/tests/test_xpath_xalan_4.cpp +300 -0
- package/thirdparty/pugixml/tests/test_xpath_xalan_5.cpp +295 -0
- package/thirdparty/pugixml/tests/writer_string.cpp +79 -0
- package/thirdparty/pugixml/tests/writer_string.hpp +27 -0
- package/ios/dummy.swift +0 -2
- package/scripts/prepare-openxlsx.js +0 -109
|
@@ -0,0 +1,3014 @@
|
|
|
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 <cstdint> // uint32_t
|
|
48
|
+
#include <iostream> // std::cout, std::cerr
|
|
49
|
+
#include <memory> // std::make_unique
|
|
50
|
+
#include <stdexcept> // std::invalid_argument
|
|
51
|
+
#include <string> // std::stoi, std::literals::string_literals
|
|
52
|
+
#include <vector> // std::vector
|
|
53
|
+
|
|
54
|
+
// ===== OpenXLSX Includes ===== //
|
|
55
|
+
#include "XLColor.hpp"
|
|
56
|
+
#include "XLDocument.hpp"
|
|
57
|
+
#include "XLException.hpp"
|
|
58
|
+
#include "XLStyles.hpp"
|
|
59
|
+
#include "XLXmlParser.hpp" // pugixml wrapper
|
|
60
|
+
#include "utilities/XLUtilities.hpp" // OpenXLSX::ignore, ::XL(Keep|Remove)Attributes, appendAndGetNode, appendAnd(G|S)etAttribute, appendAnd(G|S)etNodeAttribute
|
|
61
|
+
|
|
62
|
+
using namespace OpenXLSX;
|
|
63
|
+
|
|
64
|
+
namespace // anonymous namespace for module local functions
|
|
65
|
+
{
|
|
66
|
+
enum XLStylesEntryType : uint8_t {
|
|
67
|
+
XLStylesNumberFormats = 0,
|
|
68
|
+
XLStylesFonts = 1,
|
|
69
|
+
XLStylesFills = 2,
|
|
70
|
+
XLStylesBorders = 3,
|
|
71
|
+
XLStylesCellStyleFormats = 4,
|
|
72
|
+
XLStylesCellFormats = 5,
|
|
73
|
+
XLStylesCellStyles = 6,
|
|
74
|
+
XLStylesColors = 7,
|
|
75
|
+
XLStylesDiffCellFormats = 8,
|
|
76
|
+
XLStylesTableStyles = 9,
|
|
77
|
+
XLStylesExtLst = 10,
|
|
78
|
+
XLStylesInvalid = 255
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
XLStylesEntryType XLStylesEntryTypeFromString(std::string name)
|
|
82
|
+
{
|
|
83
|
+
if (name == "numFmts") return XLStylesNumberFormats;
|
|
84
|
+
if (name == "fonts") return XLStylesFonts;
|
|
85
|
+
if (name == "fills") return XLStylesFills;
|
|
86
|
+
if (name == "borders") return XLStylesBorders;
|
|
87
|
+
if (name == "cellStyleXfs") return XLStylesCellStyleFormats;
|
|
88
|
+
if (name == "cellXfs") return XLStylesCellFormats;
|
|
89
|
+
if (name == "cellStyles") return XLStylesCellStyles;
|
|
90
|
+
if (name == "colors") return XLStylesColors;
|
|
91
|
+
if (name == "dxfs") return XLStylesDiffCellFormats;
|
|
92
|
+
if (name == "tableStyles") return XLStylesTableStyles;
|
|
93
|
+
if (name == "extLst") return XLStylesExtLst;
|
|
94
|
+
return XLStylesEntryType::XLStylesInvalid;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
std::string XLStylesEntryTypeToString(XLStylesEntryType entryType)
|
|
98
|
+
{
|
|
99
|
+
switch (entryType) {
|
|
100
|
+
case XLStylesNumberFormats: return "numFmts";
|
|
101
|
+
case XLStylesFonts: return "fonts";
|
|
102
|
+
case XLStylesFills: return "fills";
|
|
103
|
+
case XLStylesBorders: return "borders";
|
|
104
|
+
case XLStylesCellStyleFormats: return "cellStyleXfs";
|
|
105
|
+
case XLStylesCellFormats: return "cellXfs";
|
|
106
|
+
case XLStylesCellStyles: return "cellStyles";
|
|
107
|
+
case XLStylesColors: return "colors";
|
|
108
|
+
case XLStylesDiffCellFormats: return "dxfs";
|
|
109
|
+
case XLStylesTableStyles: return "tableStyles";
|
|
110
|
+
case XLStylesExtLst: return "extLst";
|
|
111
|
+
case XLStylesInvalid: [[fallthrough]];
|
|
112
|
+
default: return "(invalid)";
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
XLUnderlineStyle XLUnderlineStyleFromString(std::string underline)
|
|
117
|
+
{
|
|
118
|
+
if (underline == ""
|
|
119
|
+
|| underline == "none") return XLUnderlineNone;
|
|
120
|
+
if (underline == "single") return XLUnderlineSingle;
|
|
121
|
+
if (underline == "double") return XLUnderlineDouble;
|
|
122
|
+
std::cerr << __func__ << ": invalid underline style " << underline << std::endl;
|
|
123
|
+
return XLUnderlineInvalid;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
std::string XLUnderlineStyleToString(XLUnderlineStyle underline)
|
|
127
|
+
{
|
|
128
|
+
switch (underline) {
|
|
129
|
+
case XLUnderlineNone : return "none";
|
|
130
|
+
case XLUnderlineSingle : return "single";
|
|
131
|
+
case XLUnderlineDouble : return "double";
|
|
132
|
+
case XLUnderlineInvalid: [[fallthrough]];
|
|
133
|
+
default: return "(invalid)";
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
XLFontSchemeStyle XLFontSchemeStyleFromString(std::string fontScheme)
|
|
138
|
+
{
|
|
139
|
+
if (fontScheme == ""
|
|
140
|
+
|| fontScheme == "none") return XLFontSchemeNone;
|
|
141
|
+
if (fontScheme == "major") return XLFontSchemeMajor;
|
|
142
|
+
if (fontScheme == "minor") return XLFontSchemeMinor;
|
|
143
|
+
std::cerr << __func__ << ": invalid font scheme " << fontScheme << std::endl;
|
|
144
|
+
return XLFontSchemeInvalid;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
std::string XLFontSchemeStyleToString(XLFontSchemeStyle fontScheme)
|
|
148
|
+
{
|
|
149
|
+
switch (fontScheme) {
|
|
150
|
+
case XLFontSchemeNone : return "none";
|
|
151
|
+
case XLFontSchemeMajor : return "major";
|
|
152
|
+
case XLFontSchemeMinor : return "minor";
|
|
153
|
+
case XLFontSchemeInvalid: [[fallthrough]];
|
|
154
|
+
default : return "(invalid)";
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
XLVerticalAlignRunStyle XLVerticalAlignRunStyleFromString(std::string vertAlign)
|
|
159
|
+
{
|
|
160
|
+
if (vertAlign == ""
|
|
161
|
+
|| vertAlign == "baseline") return XLBaseline;
|
|
162
|
+
if (vertAlign == "subscript") return XLSubscript;
|
|
163
|
+
if (vertAlign == "superscript") return XLSuperscript;
|
|
164
|
+
std::cerr << __func__ << ": invalid font vertical align run style " << vertAlign << std::endl;
|
|
165
|
+
return XLVerticalAlignRunInvalid;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
std::string XLVerticalAlignRunStyleToString(XLVerticalAlignRunStyle vertAlign)
|
|
169
|
+
{
|
|
170
|
+
switch (vertAlign) {
|
|
171
|
+
case XLBaseline : return "baseline";
|
|
172
|
+
case XLSubscript : return "subscript";
|
|
173
|
+
case XLSuperscript : return "superscript";
|
|
174
|
+
case XLVerticalAlignRunInvalid: [[fallthrough]];
|
|
175
|
+
default : return "(invalid)";
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
XLFillType XLFillTypeFromString(std::string fillType)
|
|
180
|
+
{
|
|
181
|
+
if (fillType == "gradientFill") return XLGradientFill;
|
|
182
|
+
if (fillType == "patternFill" ) return XLPatternFill;
|
|
183
|
+
if (fillType != "") // suppress error message for empty fillType (= no node exists yet)
|
|
184
|
+
std::cerr << __func__ << ": invalid fillType \"" << fillType << "\"" << std::endl;
|
|
185
|
+
return XLFillTypeInvalid;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
std::string XLFillTypeToString(XLFillType fillType)
|
|
189
|
+
{
|
|
190
|
+
switch (fillType) {
|
|
191
|
+
case XLGradientFill : return "gradientFill";
|
|
192
|
+
case XLPatternFill : return "patternFill";
|
|
193
|
+
case XLFillTypeInvalid: [[fallthrough]];
|
|
194
|
+
default: return "(invalid)";
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
XLGradientType XLGradientTypeFromString(std::string gradientType)
|
|
199
|
+
{
|
|
200
|
+
if (gradientType == "linear") return XLGradientLinear;
|
|
201
|
+
if (gradientType == "path") return XLGradientPath;
|
|
202
|
+
std::cerr << __func__ << ": invalid gradient type " << gradientType << std::endl;
|
|
203
|
+
return XLGradientTypeInvalid;
|
|
204
|
+
}
|
|
205
|
+
std::string XLGradientTypeToString(XLGradientType gradientType)
|
|
206
|
+
{
|
|
207
|
+
switch (gradientType) {
|
|
208
|
+
case XLGradientLinear : return "linear";
|
|
209
|
+
case XLGradientPath : return "path";
|
|
210
|
+
case XLGradientTypeInvalid: [[fallthrough]];
|
|
211
|
+
default: return "(invalid)";
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
XLPatternType XLPatternTypeFromString(std::string patternType)
|
|
216
|
+
{
|
|
217
|
+
if (patternType == ""
|
|
218
|
+
|| patternType == "none") return XLPatternNone;
|
|
219
|
+
if (patternType == "solid") return XLPatternSolid;
|
|
220
|
+
if (patternType == "mediumGray") return XLPatternMediumGray;
|
|
221
|
+
if (patternType == "darkGray") return XLPatternDarkGray;
|
|
222
|
+
if (patternType == "lightGray") return XLPatternLightGray;
|
|
223
|
+
if (patternType == "darkHorizontal") return XLPatternDarkHorizontal;
|
|
224
|
+
if (patternType == "darkVertical") return XLPatternDarkVertical;
|
|
225
|
+
if (patternType == "darkDown") return XLPatternDarkDown;
|
|
226
|
+
if (patternType == "darkUp") return XLPatternDarkUp;
|
|
227
|
+
if (patternType == "darkGrid") return XLPatternDarkGrid;
|
|
228
|
+
if (patternType == "darkTrellis") return XLPatternDarkTrellis;
|
|
229
|
+
if (patternType == "lightHorizontal") return XLPatternLightHorizontal;
|
|
230
|
+
if (patternType == "lightVertical") return XLPatternLightVertical;
|
|
231
|
+
if (patternType == "lightDown") return XLPatternLightDown;
|
|
232
|
+
if (patternType == "lightUp") return XLPatternLightUp;
|
|
233
|
+
if (patternType == "lightGrid") return XLPatternLightGrid;
|
|
234
|
+
if (patternType == "lightTrellis") return XLPatternLightTrellis;
|
|
235
|
+
if (patternType == "gray125") return XLPatternGray125;
|
|
236
|
+
if (patternType == "gray0625") return XLPatternGray0625;
|
|
237
|
+
std::cerr << __func__ << ": invalid patternType " << patternType << std::endl;
|
|
238
|
+
return XLPatternTypeInvalid;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
std::string XLPatternTypeToString(XLPatternType patternType)
|
|
242
|
+
{
|
|
243
|
+
switch (patternType) {
|
|
244
|
+
case XLPatternNone : return "none";
|
|
245
|
+
case XLPatternSolid : return "solid";
|
|
246
|
+
case XLPatternMediumGray : return "mediumGray";
|
|
247
|
+
case XLPatternDarkGray : return "darkGray";
|
|
248
|
+
case XLPatternLightGray : return "lightGray";
|
|
249
|
+
case XLPatternDarkHorizontal : return "darkHorizontal";
|
|
250
|
+
case XLPatternDarkVertical : return "darkVertical";
|
|
251
|
+
case XLPatternDarkDown : return "darkDown";
|
|
252
|
+
case XLPatternDarkUp : return "darkUp";
|
|
253
|
+
case XLPatternDarkGrid : return "darkGrid";
|
|
254
|
+
case XLPatternDarkTrellis : return "darkTrellis";
|
|
255
|
+
case XLPatternLightHorizontal: return "lightHorizontal";
|
|
256
|
+
case XLPatternLightVertical : return "lightVertical";
|
|
257
|
+
case XLPatternLightDown : return "lightDown";
|
|
258
|
+
case XLPatternLightUp : return "lightUp";
|
|
259
|
+
case XLPatternLightGrid : return "lightGrid";
|
|
260
|
+
case XLPatternLightTrellis : return "lightTrellis";
|
|
261
|
+
case XLPatternGray125 : return "gray125";
|
|
262
|
+
case XLPatternGray0625 : return "gray0625";
|
|
263
|
+
case XLPatternTypeInvalid : [[fallthrough]];
|
|
264
|
+
default: return "(invalid)";
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
#ifdef __GNUC__ // conditionally enable GCC specific pragmas to suppress unused function warning
|
|
269
|
+
# pragma GCC diagnostic push
|
|
270
|
+
# pragma GCC diagnostic ignored "-Wunused-function"
|
|
271
|
+
#endif // __GNUC__
|
|
272
|
+
XLLineType XLLineTypeFromString(std::string lineType)
|
|
273
|
+
{
|
|
274
|
+
if (lineType == "left") return XLLineLeft;
|
|
275
|
+
if (lineType == "right") return XLLineRight;
|
|
276
|
+
if (lineType == "top") return XLLineTop;
|
|
277
|
+
if (lineType == "bottom") return XLLineBottom;
|
|
278
|
+
if (lineType == "diagonal") return XLLineDiagonal;
|
|
279
|
+
if (lineType == "vertical") return XLLineVertical;
|
|
280
|
+
if (lineType == "horizontal") return XLLineHorizontal;
|
|
281
|
+
std::cerr << __func__ << ": invalid line type" << lineType << std::endl;
|
|
282
|
+
return XLLineInvalid;
|
|
283
|
+
}
|
|
284
|
+
#ifdef __GNUC__ // conditionally enable GCC specific pragmas to suppress unused function warning
|
|
285
|
+
# pragma GCC diagnostic pop
|
|
286
|
+
#endif // __GNUC__
|
|
287
|
+
|
|
288
|
+
std::string XLLineTypeToString(XLLineType lineType)
|
|
289
|
+
{
|
|
290
|
+
switch (lineType) {
|
|
291
|
+
case XLLineLeft: return "left";
|
|
292
|
+
case XLLineRight: return "right";
|
|
293
|
+
case XLLineTop: return "top";
|
|
294
|
+
case XLLineBottom: return "bottom";
|
|
295
|
+
case XLLineDiagonal: return "diagonal";
|
|
296
|
+
case XLLineVertical: return "vertical";
|
|
297
|
+
case XLLineHorizontal: return "horizontal";
|
|
298
|
+
case XLLineInvalid: [[fallthrough]];
|
|
299
|
+
default: return "(invalid)";
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
XLLineStyle XLLineStyleFromString(std::string style)
|
|
304
|
+
{
|
|
305
|
+
if (style == "") return XLLineStyleNone;
|
|
306
|
+
if (style == "thin") return XLLineStyleThin;
|
|
307
|
+
if (style == "medium") return XLLineStyleMedium;
|
|
308
|
+
if (style == "dashed") return XLLineStyleDashed;
|
|
309
|
+
if (style == "dotted") return XLLineStyleDotted;
|
|
310
|
+
if (style == "thick") return XLLineStyleThick;
|
|
311
|
+
if (style == "double") return XLLineStyleDouble;
|
|
312
|
+
if (style == "hair") return XLLineStyleHair;
|
|
313
|
+
if (style == "mediumDashed") return XLLineStyleMediumDashed;
|
|
314
|
+
if (style == "dashDot") return XLLineStyleDashDot;
|
|
315
|
+
if (style == "mediumDashDot") return XLLineStyleMediumDashDot;
|
|
316
|
+
if (style == "dashDotDot") return XLLineStyleDashDotDot;
|
|
317
|
+
if (style == "mediumDashDotDot") return XLLineStyleMediumDashDotDot;
|
|
318
|
+
if (style == "slantDashDot") return XLLineStyleSlantDashDot;
|
|
319
|
+
std::cerr << __func__ << ": invalid line style " << style << std::endl;
|
|
320
|
+
return XLLineStyleInvalid;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
std::string XLLineStyleToString(XLLineStyle style)
|
|
324
|
+
{
|
|
325
|
+
switch (style) {
|
|
326
|
+
case XLLineStyleNone : return "";
|
|
327
|
+
case XLLineStyleThin : return "thin";
|
|
328
|
+
case XLLineStyleMedium : return "medium";
|
|
329
|
+
case XLLineStyleDashed : return "dashed";
|
|
330
|
+
case XLLineStyleDotted : return "dotted";
|
|
331
|
+
case XLLineStyleThick : return "thick";
|
|
332
|
+
case XLLineStyleDouble : return "double";
|
|
333
|
+
case XLLineStyleHair : return "hair";
|
|
334
|
+
case XLLineStyleMediumDashed : return "mediumDashed";
|
|
335
|
+
case XLLineStyleDashDot : return "dashDot";
|
|
336
|
+
case XLLineStyleMediumDashDot : return "mediumDashDot";
|
|
337
|
+
case XLLineStyleDashDotDot : return "dashDotDot";
|
|
338
|
+
case XLLineStyleMediumDashDotDot: return "mediumDashDotDot";
|
|
339
|
+
case XLLineStyleSlantDashDot : return "slantDashDot";
|
|
340
|
+
case XLLineStyleInvalid : [[fallthrough]];
|
|
341
|
+
default : return "(invalid)";
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
XLAlignmentStyle XLAlignmentStyleFromString(std::string alignment)
|
|
346
|
+
{
|
|
347
|
+
if (alignment == ""
|
|
348
|
+
|| alignment == "general") return XLAlignGeneral;
|
|
349
|
+
if (alignment == "left") return XLAlignLeft;
|
|
350
|
+
if (alignment == "right") return XLAlignRight;
|
|
351
|
+
if (alignment == "center") return XLAlignCenter;
|
|
352
|
+
if (alignment == "top") return XLAlignTop;
|
|
353
|
+
if (alignment == "bottom") return XLAlignBottom;
|
|
354
|
+
if (alignment == "fill") return XLAlignFill;
|
|
355
|
+
if (alignment == "justify") return XLAlignJustify;
|
|
356
|
+
if (alignment == "centerContinuous") return XLAlignCenterContinuous;
|
|
357
|
+
if (alignment == "distributed") return XLAlignDistributed;
|
|
358
|
+
std::cerr << __func__ << ": invalid alignment style " << alignment << std::endl;
|
|
359
|
+
return XLAlignInvalid;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
std::string XLAlignmentStyleToString(XLAlignmentStyle alignment)
|
|
363
|
+
{
|
|
364
|
+
switch (alignment) {
|
|
365
|
+
case XLAlignGeneral : return "";
|
|
366
|
+
case XLAlignLeft : return "left";
|
|
367
|
+
case XLAlignRight : return "right";
|
|
368
|
+
case XLAlignCenter : return "center";
|
|
369
|
+
case XLAlignTop : return "top";
|
|
370
|
+
case XLAlignBottom : return "bottom";
|
|
371
|
+
case XLAlignFill : return "fill";
|
|
372
|
+
case XLAlignJustify : return "justify";
|
|
373
|
+
case XLAlignCenterContinuous : return "centerContinuous";
|
|
374
|
+
case XLAlignDistributed : return "distributed";
|
|
375
|
+
case XLAlignInvalid: [[fallthrough]];
|
|
376
|
+
default: return "(unknown)";
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
std::string XLReadingOrderToString(uint32_t readingOrder)
|
|
381
|
+
{
|
|
382
|
+
switch (readingOrder) {
|
|
383
|
+
case XLReadingOrderContextual : return "contextual";
|
|
384
|
+
case XLReadingOrderLeftToRight: return "left-to-right";
|
|
385
|
+
case XLReadingOrderRightToLeft: return "right-to-left";
|
|
386
|
+
default: return "(unknown)";
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
void copyXMLNode(XMLNode & destination, XMLNode & source)
|
|
391
|
+
{
|
|
392
|
+
if (not source.empty()) {
|
|
393
|
+
// ===== Copy all XML child nodes
|
|
394
|
+
for (XMLNode child = source.first_child(); not child.empty(); child = child.next_sibling())
|
|
395
|
+
destination.append_copy(child);
|
|
396
|
+
// ===== Copy all XML attributes
|
|
397
|
+
for (XMLAttribute attr = source.first_attribute(); not attr.empty(); attr = attr.next_attribute())
|
|
398
|
+
destination.append_copy(attr);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* @brief remove trailing unwanted_chars from input
|
|
404
|
+
* @param input the string to trim
|
|
405
|
+
* @param unwanted_chars all characters to consider trimmable
|
|
406
|
+
* @return input minus any trailing characters that are part of unwanted_chars
|
|
407
|
+
*/
|
|
408
|
+
std::string rtrim(const std::string & input, const std::string & unwanted_chars)
|
|
409
|
+
{
|
|
410
|
+
size_t end = input.find_last_not_of( unwanted_chars );
|
|
411
|
+
if( end == std::string::npos )
|
|
412
|
+
return "";
|
|
413
|
+
else
|
|
414
|
+
return input.substr( 0, end + 1 );
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
void wrapNode(XMLNode parentNode, XMLNode & node, std::string const & prefix)
|
|
418
|
+
{
|
|
419
|
+
if (not node.empty() && prefix.length() > 0) {
|
|
420
|
+
XMLNode prev = node.previous_sibling();
|
|
421
|
+
// 2026-06-10 beauty fix: ensure that inserted prefix is not combined with other blankspaces
|
|
422
|
+
if (prev.type() == pugi::node_pcdata) { // if node is already preceeded by a text node
|
|
423
|
+
std::string trimmedVal = rtrim(prev.value(), " \t"); // trim from end of preceeding text node all spaces & tabs
|
|
424
|
+
prev.set_value((trimmedVal + prefix).c_str()); // and set the value to any remaining characters + prefix
|
|
425
|
+
}
|
|
426
|
+
else // else: node is not (yet) preceeded by a text node
|
|
427
|
+
parentNode.insert_child_before(pugi::node_pcdata, node).set_value(prefix.c_str()); // insert prefix before node opening tag
|
|
428
|
+
|
|
429
|
+
node.append_child(pugi::node_pcdata).set_value(prefix.c_str()); // always: insert prefix before node closing tag (within node)
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
/**
|
|
434
|
+
* @brief Format val as a string with decimalPlaces
|
|
435
|
+
* @param val The value to format
|
|
436
|
+
* @param decimalPlaces The amount of digits following the decimal separator that shall be included in the formatted string
|
|
437
|
+
* @return The value formatted as a string with the desired amount of decimal places
|
|
438
|
+
*/
|
|
439
|
+
std::string formatDoubleAsString(double val, int decimalPlaces = 2)
|
|
440
|
+
{
|
|
441
|
+
std::string result = std::to_string(val);
|
|
442
|
+
size_t decimalPos = result.find_first_of('.');
|
|
443
|
+
if (decimalPos >= result.length())
|
|
444
|
+
throw XLException("formatDoubleAsString: return value of std::to_string(double val) contains no decimal separator - this should never happen");
|
|
445
|
+
|
|
446
|
+
// ===== Return the string representation of val with the decimal separator and decimalPlaces digits following
|
|
447
|
+
return result.substr(0, decimalPos + 1 + decimalPlaces);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* @brief Check that a double value is within range, and format it as a string with decimalPlaces
|
|
452
|
+
* @param val The value to check & format
|
|
453
|
+
* @param min The lower bound of the valid value range
|
|
454
|
+
* @param max The upper bound of the valid value range 0 must be larger than min
|
|
455
|
+
* @param absTolerance The tolerance for rounding errors when checking the valid range - must be positive
|
|
456
|
+
* @param decimalPlaces The amount of digits following the decimal separator that shall be included in the formatted string
|
|
457
|
+
* @return The value formatted as a string with the desired amount of decimal places
|
|
458
|
+
* @return An empty string ""s if the value falls outside the valid range
|
|
459
|
+
* @note values that fall outside the range but within the tolerance will be rounded to the nearest range bound
|
|
460
|
+
*/
|
|
461
|
+
std::string checkAndFormatDoubleAsString(double val, double min, double max, double absTolerance, int decimalPlaces = 2)
|
|
462
|
+
{
|
|
463
|
+
if (max <= min || absTolerance < 0.0) throw XLException("checkAndFormatDoubleAsString: max must be greater than min and absTolerance must be >= 0.0");
|
|
464
|
+
if (val < min - absTolerance || val > max + absTolerance) return ""; // range check
|
|
465
|
+
if (val < min) val = min; else if (val > max) val = max; // fix rounding errors within tolerance
|
|
466
|
+
return formatDoubleAsString(val, decimalPlaces);
|
|
467
|
+
}
|
|
468
|
+
} // anonymous namespace
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
* @details Default constructor. Initializes an empty XLNumberFormat object
|
|
474
|
+
*/
|
|
475
|
+
XLNumberFormat::XLNumberFormat() : m_numberFormatNode(std::make_unique<XMLNode>()) {}
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* @details Constructor. Initializes the member variables for the new XLNumberFormat object.
|
|
479
|
+
*/
|
|
480
|
+
XLNumberFormat::XLNumberFormat(const XMLNode& node) : m_numberFormatNode(std::make_unique<XMLNode>(node)) {}
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* @details Copy constructor
|
|
484
|
+
*/
|
|
485
|
+
XLNumberFormat::XLNumberFormat(const XLNumberFormat& other)
|
|
486
|
+
: m_numberFormatNode(std::make_unique<XMLNode>(*other.m_numberFormatNode))
|
|
487
|
+
{}
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* @details Move constructor
|
|
491
|
+
*/
|
|
492
|
+
XLNumberFormat::XLNumberFormat(XLNumberFormat&& other) noexcept = default;
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* @details
|
|
496
|
+
*/
|
|
497
|
+
XLNumberFormat::~XLNumberFormat() = default;
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* @details Copy assignment operator
|
|
501
|
+
*/
|
|
502
|
+
XLNumberFormat& XLNumberFormat::operator=(const XLNumberFormat& other)
|
|
503
|
+
{
|
|
504
|
+
if (&other != this) *m_numberFormatNode = *other.m_numberFormatNode;
|
|
505
|
+
return *this;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* @details Move assignment operator
|
|
510
|
+
*/
|
|
511
|
+
XLNumberFormat& XLNumberFormat::operator=(XLNumberFormat&& other) noexcept = default;
|
|
512
|
+
|
|
513
|
+
/**
|
|
514
|
+
* @details Returns the numFmtId value
|
|
515
|
+
*/
|
|
516
|
+
uint32_t XLNumberFormat::numberFormatId() const { return m_numberFormatNode->attribute("numFmtId").as_uint(XLInvalidUInt32); }
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* @details Returns the formatCode value
|
|
520
|
+
*/
|
|
521
|
+
std::string XLNumberFormat::formatCode() const { return m_numberFormatNode->attribute("formatCode").value(); }
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* @details Setter functions
|
|
525
|
+
*/
|
|
526
|
+
bool XLNumberFormat::setNumberFormatId(uint32_t newNumberFormatId)
|
|
527
|
+
{ return appendAndSetAttribute(*m_numberFormatNode, "numFmtId", std::to_string(newNumberFormatId)).empty() == false; }
|
|
528
|
+
bool XLNumberFormat::setFormatCode (std::string newFormatCode)
|
|
529
|
+
{ return appendAndSetAttribute(*m_numberFormatNode, "formatCode", newFormatCode.c_str() ).empty() == false; }
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
/**
|
|
533
|
+
* @details assemble a string summary about the number format
|
|
534
|
+
*/
|
|
535
|
+
std::string XLNumberFormat::summary() const
|
|
536
|
+
{
|
|
537
|
+
using namespace std::literals::string_literals;
|
|
538
|
+
return "numFmtId="s + std::to_string(numberFormatId())
|
|
539
|
+
+ ", formatCode="s + formatCode();
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
|
|
543
|
+
// ===== XLNumberFormats, parent of XLNumberFormat
|
|
544
|
+
|
|
545
|
+
/**
|
|
546
|
+
* @details Constructor. Initializes an empty XLNumberFormats object
|
|
547
|
+
*/
|
|
548
|
+
XLNumberFormats::XLNumberFormats() : m_numberFormatsNode(std::make_unique<XMLNode>()) {}
|
|
549
|
+
|
|
550
|
+
/**
|
|
551
|
+
* @details Constructor. Initializes the member variables for the new XLNumberFormats object.
|
|
552
|
+
*/
|
|
553
|
+
XLNumberFormats::XLNumberFormats(const XMLNode& numberFormats)
|
|
554
|
+
: m_numberFormatsNode(std::make_unique<XMLNode>(numberFormats))
|
|
555
|
+
{
|
|
556
|
+
// initialize XLNumberFormat entries and m_numberFormats here
|
|
557
|
+
XMLNode node = numberFormats.first_child_of_type(pugi::node_element);
|
|
558
|
+
while (not node.empty()) {
|
|
559
|
+
std::string nodeName = node.name();
|
|
560
|
+
if (nodeName == "numFmt")
|
|
561
|
+
m_numberFormats.push_back(XLNumberFormat(node));
|
|
562
|
+
else
|
|
563
|
+
std::cerr << "WARNING: XLNumberFormats constructor: unknown subnode " << nodeName << std::endl;
|
|
564
|
+
node = node.next_sibling_of_type(pugi::node_element);
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
/**
|
|
569
|
+
* @details Copy constructor
|
|
570
|
+
*/
|
|
571
|
+
XLNumberFormats::XLNumberFormats(const XLNumberFormats& other)
|
|
572
|
+
: m_numberFormatsNode(std::make_unique<XMLNode>(*other.m_numberFormatsNode)),
|
|
573
|
+
m_numberFormats(other.m_numberFormats)
|
|
574
|
+
{}
|
|
575
|
+
|
|
576
|
+
/**
|
|
577
|
+
* @details Move constructor
|
|
578
|
+
*/
|
|
579
|
+
XLNumberFormats::XLNumberFormats(XLNumberFormats&& other)
|
|
580
|
+
: m_numberFormatsNode(std::move(other.m_numberFormatsNode)),
|
|
581
|
+
m_numberFormats(std::move(other.m_numberFormats))
|
|
582
|
+
{}
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* @details
|
|
586
|
+
*/
|
|
587
|
+
XLNumberFormats::~XLNumberFormats()
|
|
588
|
+
{
|
|
589
|
+
m_numberFormats.clear(); // delete vector with all children
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
/**
|
|
593
|
+
* @details Copy assignment operator
|
|
594
|
+
*/
|
|
595
|
+
XLNumberFormats& XLNumberFormats::operator=(const XLNumberFormats& other)
|
|
596
|
+
{
|
|
597
|
+
if (&other != this) {
|
|
598
|
+
*m_numberFormatsNode = *other.m_numberFormatsNode;
|
|
599
|
+
m_numberFormats.clear();
|
|
600
|
+
m_numberFormats = other.m_numberFormats;
|
|
601
|
+
}
|
|
602
|
+
return *this;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
/**
|
|
606
|
+
* @details Move assignment operator.
|
|
607
|
+
*/
|
|
608
|
+
XLNumberFormats& XLNumberFormats::operator=(XLNumberFormats&& other) noexcept = default;
|
|
609
|
+
|
|
610
|
+
/**
|
|
611
|
+
* @details Returns the amount of numberFormats held by the class
|
|
612
|
+
*/
|
|
613
|
+
size_t XLNumberFormats::count() const { return m_numberFormats.size(); }
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* @details fetch XLNumberFormat from m_numberFormats by index
|
|
617
|
+
*/
|
|
618
|
+
XLNumberFormat XLNumberFormats::numberFormatByIndex(XLStyleIndex index) const
|
|
619
|
+
{
|
|
620
|
+
if (index >= m_numberFormats.size()) {
|
|
621
|
+
using namespace std::literals::string_literals;
|
|
622
|
+
throw XLException("XLNumberFormats::"s + __func__ + ": index "s + std::to_string(index) + " is out of range"s);
|
|
623
|
+
}
|
|
624
|
+
return m_numberFormats.at(index);
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
/**
|
|
628
|
+
* @details fetch XLNumberFormat from m_numberFormats by its numberFormatId
|
|
629
|
+
*/
|
|
630
|
+
XLNumberFormat XLNumberFormats::numberFormatById(uint32_t numberFormatId) const
|
|
631
|
+
{
|
|
632
|
+
for (XLNumberFormat fmt : m_numberFormats)
|
|
633
|
+
if (fmt.numberFormatId() == numberFormatId)
|
|
634
|
+
return fmt;
|
|
635
|
+
using namespace std::literals::string_literals;
|
|
636
|
+
throw XLException("XLNumberFormats::"s + __func__ + ": numberFormatId "s + std::to_string(numberFormatId) + " not found"s);
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
/**
|
|
640
|
+
* @details fetch a numFmtId from m_numberFormats by index
|
|
641
|
+
*/
|
|
642
|
+
uint32_t XLNumberFormats::numberFormatIdFromIndex(XLStyleIndex index) const
|
|
643
|
+
{
|
|
644
|
+
if (index >= m_numberFormats.size()) {
|
|
645
|
+
using namespace std::literals::string_literals;
|
|
646
|
+
throw XLException("XLNumberFormats::"s + __func__ + ": index "s + std::to_string(index) + " is out of range"s);
|
|
647
|
+
}
|
|
648
|
+
return m_numberFormats[ index ].numberFormatId();
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
/**
|
|
652
|
+
* @details append a new XLNumberFormat to m_numberFormats and m_numberFormatsNode, based on copyFrom
|
|
653
|
+
*/
|
|
654
|
+
XLStyleIndex XLNumberFormats::create(XLNumberFormat copyFrom, std::string styleEntriesPrefix)
|
|
655
|
+
{
|
|
656
|
+
XLStyleIndex index = count(); // index for the number format to be created
|
|
657
|
+
XMLNode newNode{}; // scope declaration
|
|
658
|
+
|
|
659
|
+
// ===== Append new node prior to final whitespaces, if any
|
|
660
|
+
XMLNode lastStyle = m_numberFormatsNode->last_child_of_type(pugi::node_element);
|
|
661
|
+
if (lastStyle.empty()) newNode = m_numberFormatsNode->prepend_child("numFmt");
|
|
662
|
+
else newNode = m_numberFormatsNode->insert_child_after("numFmt", lastStyle);
|
|
663
|
+
if (newNode.empty()) {
|
|
664
|
+
using namespace std::literals::string_literals;
|
|
665
|
+
throw XLException("XLNumberFormats::"s + __func__ + ": failed to append a new numFmt node"s);
|
|
666
|
+
}
|
|
667
|
+
if (styleEntriesPrefix.length() > 0) // if a whitespace prefix is configured
|
|
668
|
+
m_numberFormatsNode->insert_child_before(pugi::node_pcdata, newNode).set_value(styleEntriesPrefix.c_str()); // prefix the new node with styleEntriesPrefix
|
|
669
|
+
|
|
670
|
+
XLNumberFormat newNumberFormat(newNode);
|
|
671
|
+
if (copyFrom.m_numberFormatNode->empty()) { // if no template is given
|
|
672
|
+
// ===== Create a number format with default values
|
|
673
|
+
newNumberFormat.setNumberFormatId(0);
|
|
674
|
+
newNumberFormat.setFormatCode("General");
|
|
675
|
+
}
|
|
676
|
+
else
|
|
677
|
+
copyXMLNode(newNode, *copyFrom.m_numberFormatNode); // will use copyFrom as template, does nothing if copyFrom is empty
|
|
678
|
+
|
|
679
|
+
m_numberFormats.push_back(newNumberFormat);
|
|
680
|
+
appendAndSetAttribute(*m_numberFormatsNode, "count", std::to_string(m_numberFormats.size())); // update array count in XML
|
|
681
|
+
return index;
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
|
|
685
|
+
/**
|
|
686
|
+
* @details Constructor. Initializes an empty XLFont object
|
|
687
|
+
*/
|
|
688
|
+
XLFont::XLFont() : m_fontNode(std::make_unique<XMLNode>()) {}
|
|
689
|
+
|
|
690
|
+
/**
|
|
691
|
+
* @details Constructor. Initializes the member variables for the new XLFont object.
|
|
692
|
+
*/
|
|
693
|
+
XLFont::XLFont(const XMLNode& node) : m_fontNode(std::make_unique<XMLNode>(node)) {}
|
|
694
|
+
|
|
695
|
+
/**
|
|
696
|
+
* @details Copy constructor
|
|
697
|
+
*/
|
|
698
|
+
XLFont::XLFont(const XLFont& other)
|
|
699
|
+
: m_fontNode(std::make_unique<XMLNode>(*other.m_fontNode))
|
|
700
|
+
{}
|
|
701
|
+
|
|
702
|
+
/**
|
|
703
|
+
* @details Move constructor
|
|
704
|
+
*/
|
|
705
|
+
XLFont::XLFont(XLFont&& other) noexcept = default;
|
|
706
|
+
|
|
707
|
+
/**
|
|
708
|
+
* @details
|
|
709
|
+
*/
|
|
710
|
+
XLFont::~XLFont() = default;
|
|
711
|
+
|
|
712
|
+
/**
|
|
713
|
+
* @details Copy assignment operator
|
|
714
|
+
*/
|
|
715
|
+
XLFont& XLFont::operator=(const XLFont& other)
|
|
716
|
+
{
|
|
717
|
+
if (&other != this) *m_fontNode = *other.m_fontNode;
|
|
718
|
+
return *this;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
/**
|
|
722
|
+
* @details Move assignment operator
|
|
723
|
+
*/
|
|
724
|
+
XLFont& XLFont::operator=(XLFont&& other) noexcept = default;
|
|
725
|
+
|
|
726
|
+
/**
|
|
727
|
+
* @details Returns the font name property
|
|
728
|
+
*/
|
|
729
|
+
std::string XLFont::fontName() const
|
|
730
|
+
{
|
|
731
|
+
XMLAttribute attr = appendAndGetNodeAttribute(*m_fontNode, "name", "val", OpenXLSX::XLDefaultFontName);
|
|
732
|
+
return attr.value();
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
/**
|
|
736
|
+
* @details Returns the font charset property
|
|
737
|
+
*/
|
|
738
|
+
size_t XLFont::fontCharset() const
|
|
739
|
+
{
|
|
740
|
+
XMLAttribute attr = appendAndGetNodeAttribute(*m_fontNode, "charset", "val", std::to_string(OpenXLSX::XLDefaultFontCharset));
|
|
741
|
+
return attr.as_uint();
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
/**
|
|
745
|
+
* @details Returns the font family property
|
|
746
|
+
*/
|
|
747
|
+
size_t XLFont::fontFamily() const
|
|
748
|
+
{
|
|
749
|
+
XMLAttribute attr = appendAndGetNodeAttribute(*m_fontNode, "family", "val", std::to_string(OpenXLSX::XLDefaultFontFamily));
|
|
750
|
+
return attr.as_uint();
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
/**
|
|
754
|
+
* @details Returns the font size property
|
|
755
|
+
*/
|
|
756
|
+
size_t XLFont::fontSize() const
|
|
757
|
+
{
|
|
758
|
+
XMLAttribute attr = appendAndGetNodeAttribute(*m_fontNode, "sz", "val", std::to_string(OpenXLSX::XLDefaultFontSize));
|
|
759
|
+
return attr.as_uint();
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
/**
|
|
763
|
+
* @details Returns the font color property
|
|
764
|
+
*/
|
|
765
|
+
XLColor XLFont::fontColor() const
|
|
766
|
+
{
|
|
767
|
+
using namespace std::literals::string_literals;
|
|
768
|
+
// XMLAttribute attr = appendAndGetNodeAttribute(*m_fontNode, "color", "theme", OpenXLSX::XLDefaultFontColorTheme);
|
|
769
|
+
// TBD what "theme" is and whether it should be supported at all
|
|
770
|
+
XMLAttribute attr = appendAndGetNodeAttribute(*m_fontNode, "color", "rgb", XLDefaultFontColor);
|
|
771
|
+
return XLColor(attr.value());
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
/**
|
|
775
|
+
* @details getter functions: return the font's bold, italic, underline, strikethrough status
|
|
776
|
+
*/
|
|
777
|
+
bool XLFont::bold() const { return getBoolAttributeWhenOmittedMeansTrue(*m_fontNode, "b", "val"); }
|
|
778
|
+
bool XLFont::italic() const { return getBoolAttributeWhenOmittedMeansTrue(*m_fontNode, "i", "val"); }
|
|
779
|
+
bool XLFont::strikethrough() const { return getBoolAttributeWhenOmittedMeansTrue(*m_fontNode, "strike", "val"); }
|
|
780
|
+
XLUnderlineStyle XLFont::underline() const { return XLUnderlineStyleFromString (appendAndGetNodeAttribute(*m_fontNode, "u", "val", "none" ).value() ); }
|
|
781
|
+
XLFontSchemeStyle XLFont::scheme() const { return XLFontSchemeStyleFromString (appendAndGetNodeAttribute(*m_fontNode, "scheme", "val", "none" ).value() ); }
|
|
782
|
+
XLVerticalAlignRunStyle XLFont::vertAlign() const { return XLVerticalAlignRunStyleFromString(appendAndGetNodeAttribute(*m_fontNode, "vertAlign", "val", "baseline").value() ); }
|
|
783
|
+
bool XLFont::outline() const { return getBoolAttributeWhenOmittedMeansTrue(*m_fontNode, "outline", "val"); }
|
|
784
|
+
bool XLFont::shadow() const { return getBoolAttributeWhenOmittedMeansTrue(*m_fontNode, "shadow", "val"); }
|
|
785
|
+
bool XLFont::condense() const { return getBoolAttributeWhenOmittedMeansTrue(*m_fontNode, "condense", "val"); }
|
|
786
|
+
bool XLFont::extend() const { return getBoolAttributeWhenOmittedMeansTrue(*m_fontNode, "extend", "val"); }
|
|
787
|
+
|
|
788
|
+
/**
|
|
789
|
+
* @details Setter functions
|
|
790
|
+
*/
|
|
791
|
+
bool XLFont::setFontName (std::string newName) { return appendAndSetNodeAttribute(*m_fontNode, "name", "val", newName.c_str() ).empty() == false; }
|
|
792
|
+
bool XLFont::setFontCharset (size_t newCharset) { return appendAndSetNodeAttribute(*m_fontNode, "charset", "val", std::to_string(newCharset) ).empty() == false; }
|
|
793
|
+
bool XLFont::setFontFamily (size_t newFamily) { return appendAndSetNodeAttribute(*m_fontNode, "family", "val", std::to_string(newFamily) ).empty() == false; }
|
|
794
|
+
bool XLFont::setFontSize (size_t newSize) { return appendAndSetNodeAttribute(*m_fontNode, "sz", "val", std::to_string(newSize) ).empty() == false; }
|
|
795
|
+
bool XLFont::setFontColor (XLColor newColor) { return appendAndSetNodeAttribute(*m_fontNode, "color", "rgb", newColor.hex(), XLRemoveAttributes ).empty() == false; }
|
|
796
|
+
bool XLFont::setBold (bool set) { return appendAndSetNodeAttribute(*m_fontNode, "b", "val", (set ? "true" : "false") ).empty() == false; }
|
|
797
|
+
bool XLFont::setItalic (bool set) { return appendAndSetNodeAttribute(*m_fontNode, "i", "val", (set ? "true" : "false") ).empty() == false; }
|
|
798
|
+
bool XLFont::setStrikethrough(bool set) { return appendAndSetNodeAttribute(*m_fontNode, "strike", "val", (set ? "true" : "false") ).empty() == false; }
|
|
799
|
+
bool XLFont::setUnderline (XLUnderlineStyle style)
|
|
800
|
+
{ return appendAndSetNodeAttribute(*m_fontNode, "u", "val", XLUnderlineStyleToString (style ).c_str()).empty() == false; }
|
|
801
|
+
bool XLFont::setScheme (XLFontSchemeStyle newScheme)
|
|
802
|
+
{ return appendAndSetNodeAttribute(*m_fontNode, "scheme", "val", XLFontSchemeStyleToString (newScheme ).c_str()).empty() == false; }
|
|
803
|
+
bool XLFont::setVertAlign (XLVerticalAlignRunStyle newVertAlign)
|
|
804
|
+
{ return appendAndSetNodeAttribute(*m_fontNode, "vertAlign", "val", XLVerticalAlignRunStyleToString(newVertAlign).c_str()).empty() == false; }
|
|
805
|
+
bool XLFont::setOutline (bool set) { return appendAndSetNodeAttribute(*m_fontNode, "outline", "val", (set ? "true" : "false") ).empty() == false; }
|
|
806
|
+
bool XLFont::setShadow (bool set) { return appendAndSetNodeAttribute(*m_fontNode, "shadow", "val", (set ? "true" : "false") ).empty() == false; }
|
|
807
|
+
bool XLFont::setCondense(bool set) { return appendAndSetNodeAttribute(*m_fontNode, "condense", "val", (set ? "true" : "false") ).empty() == false; }
|
|
808
|
+
bool XLFont::setExtend (bool set) { return appendAndSetNodeAttribute(*m_fontNode, "extend", "val", (set ? "true" : "false") ).empty() == false; }
|
|
809
|
+
|
|
810
|
+
|
|
811
|
+
/**
|
|
812
|
+
* @details assemble a string summary about the font
|
|
813
|
+
*/
|
|
814
|
+
std::string XLFont::summary() const
|
|
815
|
+
{
|
|
816
|
+
using namespace std::literals::string_literals;
|
|
817
|
+
return "font name is "s + fontName()
|
|
818
|
+
+ ", charset: "s + std::to_string(fontCharset())
|
|
819
|
+
+ ", font family: "s + std::to_string(fontFamily())
|
|
820
|
+
+ ", size: "s + std::to_string(fontSize())
|
|
821
|
+
+ ", color: "s + fontColor().hex()
|
|
822
|
+
+ (bold() ? ", +bold"s : ""s)
|
|
823
|
+
+ (italic() ? ", +italic"s : ""s)
|
|
824
|
+
+ (strikethrough() ? ", +strikethrough"s : ""s)
|
|
825
|
+
+ (underline() != XLUnderlineNone ? ", underline: "s + XLUnderlineStyleToString(underline()) : ""s)
|
|
826
|
+
+ (scheme() != XLFontSchemeNone ? ", scheme: "s + XLFontSchemeStyleToString(scheme()) : ""s)
|
|
827
|
+
+ (vertAlign() != XLBaseline ? ", vertAlign: "s + XLVerticalAlignRunStyleToString(vertAlign()) : ""s)
|
|
828
|
+
+ (outline() ? ", +outline"s : ""s)
|
|
829
|
+
+ (shadow() ? ", +shadow"s : ""s)
|
|
830
|
+
+ (condense() ? ", +condense"s : ""s)
|
|
831
|
+
+ (extend() ? ", +extend"s : ""s);
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
|
|
835
|
+
// ===== XLFonts, parent of XLFont
|
|
836
|
+
|
|
837
|
+
/**
|
|
838
|
+
* @details Constructor. Initializes an empty XLFonts object
|
|
839
|
+
*/
|
|
840
|
+
XLFonts::XLFonts() : m_fontsNode(std::make_unique<XMLNode>()) {}
|
|
841
|
+
|
|
842
|
+
/**
|
|
843
|
+
* @details Constructor. Initializes the member variables for the new XLFonts object.
|
|
844
|
+
*/
|
|
845
|
+
XLFonts::XLFonts(const XMLNode& fonts)
|
|
846
|
+
: m_fontsNode(std::make_unique<XMLNode>(fonts))
|
|
847
|
+
{
|
|
848
|
+
// initialize XLFonts entries and m_fonts here
|
|
849
|
+
XMLNode node = m_fontsNode->first_child_of_type(pugi::node_element);
|
|
850
|
+
while (not node.empty()) {
|
|
851
|
+
std::string nodeName = node.name();
|
|
852
|
+
if (nodeName == "font")
|
|
853
|
+
m_fonts.push_back(XLFont(node));
|
|
854
|
+
else
|
|
855
|
+
std::cerr << "WARNING: XLFonts constructor: unknown subnode " << nodeName << std::endl;
|
|
856
|
+
node = node.next_sibling_of_type(pugi::node_element);
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
/**
|
|
861
|
+
* @details Copy constructor
|
|
862
|
+
*/
|
|
863
|
+
XLFonts::XLFonts(const XLFonts& other)
|
|
864
|
+
: m_fontsNode(std::make_unique<XMLNode>(*other.m_fontsNode)),
|
|
865
|
+
m_fonts(other.m_fonts)
|
|
866
|
+
{}
|
|
867
|
+
|
|
868
|
+
/**
|
|
869
|
+
* @details Move constructor
|
|
870
|
+
*/
|
|
871
|
+
XLFonts::XLFonts(XLFonts&& other)
|
|
872
|
+
: m_fontsNode(std::move(other.m_fontsNode)),
|
|
873
|
+
m_fonts(std::move(other.m_fonts))
|
|
874
|
+
{}
|
|
875
|
+
|
|
876
|
+
/**
|
|
877
|
+
* @details
|
|
878
|
+
*/
|
|
879
|
+
XLFonts::~XLFonts()
|
|
880
|
+
{
|
|
881
|
+
m_fonts.clear(); // delete vector with all children
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
/**
|
|
885
|
+
* @details Copy assignment operator
|
|
886
|
+
*/
|
|
887
|
+
XLFonts& XLFonts::operator=(const XLFonts& other)
|
|
888
|
+
{
|
|
889
|
+
if (&other != this) {
|
|
890
|
+
*m_fontsNode = *other.m_fontsNode;
|
|
891
|
+
m_fonts.clear();
|
|
892
|
+
m_fonts = other.m_fonts;
|
|
893
|
+
}
|
|
894
|
+
return *this;
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
/**
|
|
898
|
+
* @details Move assignment operator
|
|
899
|
+
*/
|
|
900
|
+
XLFonts& XLFonts::operator=(XLFonts&& other) noexcept = default;
|
|
901
|
+
|
|
902
|
+
/**
|
|
903
|
+
* @details Returns the amount of fonts held by the class
|
|
904
|
+
*/
|
|
905
|
+
size_t XLFonts::count() const { return m_fonts.size(); }
|
|
906
|
+
|
|
907
|
+
/**
|
|
908
|
+
* @details fetch XLFont from m_Fonts by index
|
|
909
|
+
*/
|
|
910
|
+
XLFont XLFonts::fontByIndex(XLStyleIndex index) const
|
|
911
|
+
{
|
|
912
|
+
if (index >= m_fonts.size()) {
|
|
913
|
+
using namespace std::literals::string_literals;
|
|
914
|
+
throw XLException("XLFonts::"s + __func__ + ": attempted to access index "s + std::to_string(index) + " with count "s + std::to_string(m_fonts.size()));
|
|
915
|
+
}
|
|
916
|
+
return m_fonts.at(index);
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
/**
|
|
920
|
+
* @details append a new XLFont to m_fonts and m_fontsNode, based on copyFrom
|
|
921
|
+
*/
|
|
922
|
+
XLStyleIndex XLFonts::create(XLFont copyFrom, std::string styleEntriesPrefix)
|
|
923
|
+
{
|
|
924
|
+
XLStyleIndex index = count(); // index for the font to be created
|
|
925
|
+
XMLNode newNode{}; // scope declaration
|
|
926
|
+
|
|
927
|
+
// ===== Append new node prior to final whitespaces, if any
|
|
928
|
+
XMLNode lastStyle = m_fontsNode->last_child_of_type(pugi::node_element);
|
|
929
|
+
if (lastStyle.empty()) newNode = m_fontsNode->prepend_child("font");
|
|
930
|
+
else newNode = m_fontsNode->insert_child_after("font", lastStyle);
|
|
931
|
+
if (newNode.empty()) {
|
|
932
|
+
using namespace std::literals::string_literals;
|
|
933
|
+
throw XLException("XLFonts::"s + __func__ + ": failed to append a new fonts node"s);
|
|
934
|
+
}
|
|
935
|
+
if (styleEntriesPrefix.length() > 0) // if a whitespace prefix is configured
|
|
936
|
+
m_fontsNode->insert_child_before(pugi::node_pcdata, newNode).set_value(styleEntriesPrefix.c_str()); // prefix the new node with styleEntriesPrefix
|
|
937
|
+
|
|
938
|
+
XLFont newFont(newNode);
|
|
939
|
+
if (copyFrom.m_fontNode->empty()) { // if no template is given
|
|
940
|
+
// ===== Create a font with default values
|
|
941
|
+
// TODO: implement font defaults
|
|
942
|
+
// newFont.setProperty(defaultValue);
|
|
943
|
+
// ...
|
|
944
|
+
}
|
|
945
|
+
else
|
|
946
|
+
copyXMLNode(newNode, *copyFrom.m_fontNode); // will use copyFrom as template, does nothing if copyFrom is empty
|
|
947
|
+
|
|
948
|
+
m_fonts.push_back(newFont);
|
|
949
|
+
appendAndSetAttribute(*m_fontsNode, "count", std::to_string(m_fonts.size())); // update array count in XML
|
|
950
|
+
return index;
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
|
|
954
|
+
// ===== XLDataBarColor, used by XLFills gradientFill and by XLLine (to be implemented)
|
|
955
|
+
|
|
956
|
+
/**
|
|
957
|
+
* @details Constructor. Initializes an empty XLDataBarColor object
|
|
958
|
+
*/
|
|
959
|
+
XLDataBarColor::XLDataBarColor() : m_colorNode(std::make_unique<XMLNode>()) {}
|
|
960
|
+
|
|
961
|
+
/**
|
|
962
|
+
* @details Constructor. Initializes the member variables for the new XLDataBarColor object.
|
|
963
|
+
*/
|
|
964
|
+
XLDataBarColor::XLDataBarColor(const XMLNode& node) : m_colorNode(std::make_unique<XMLNode>(node)) {}
|
|
965
|
+
|
|
966
|
+
/**
|
|
967
|
+
* @details Copy constructor - initializes the member variables from other
|
|
968
|
+
*/
|
|
969
|
+
XLDataBarColor::XLDataBarColor(const XLDataBarColor& other)
|
|
970
|
+
: m_colorNode(std::make_unique<XMLNode>(*other.m_colorNode))
|
|
971
|
+
{}
|
|
972
|
+
|
|
973
|
+
/**
|
|
974
|
+
* @details Move Constructor
|
|
975
|
+
*/
|
|
976
|
+
XLDataBarColor::XLDataBarColor(XLDataBarColor&& other) noexcept = default;
|
|
977
|
+
|
|
978
|
+
/**
|
|
979
|
+
* @details
|
|
980
|
+
*/
|
|
981
|
+
XLDataBarColor::~XLDataBarColor() = default;
|
|
982
|
+
|
|
983
|
+
/**
|
|
984
|
+
* @details Copy assignment operator
|
|
985
|
+
*/
|
|
986
|
+
XLDataBarColor& XLDataBarColor::operator=(const XLDataBarColor& other)
|
|
987
|
+
{
|
|
988
|
+
if (&other != this) *m_colorNode = *other.m_colorNode;
|
|
989
|
+
return *this;
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
/**
|
|
993
|
+
* @details Move assignment operator
|
|
994
|
+
*/
|
|
995
|
+
XLDataBarColor& XLDataBarColor::operator=(XLDataBarColor&& other) noexcept = default;
|
|
996
|
+
|
|
997
|
+
/**
|
|
998
|
+
* @details Getter functions
|
|
999
|
+
*/
|
|
1000
|
+
XLColor XLDataBarColor::rgb() const { return XLColor(m_colorNode->attribute("rgb" ).as_string("ffffffff")); }
|
|
1001
|
+
double XLDataBarColor::tint() const { return m_colorNode->attribute("tint" ).as_double(0.0) ; }
|
|
1002
|
+
bool XLDataBarColor::automatic() const { return m_colorNode->attribute("auto" ).as_bool() ; }
|
|
1003
|
+
uint32_t XLDataBarColor::indexed() const { return m_colorNode->attribute("indexed").as_uint() ; }
|
|
1004
|
+
uint32_t XLDataBarColor::theme() const { return m_colorNode->attribute("theme" ).as_uint() ; }
|
|
1005
|
+
/**
|
|
1006
|
+
* @details Setter functions
|
|
1007
|
+
*/
|
|
1008
|
+
bool XLDataBarColor::setRgb (XLColor newColor) { return appendAndSetAttribute(*m_colorNode, "rgb", newColor.hex() ).empty() == false; }
|
|
1009
|
+
bool XLDataBarColor::setTint(double newTint)
|
|
1010
|
+
{
|
|
1011
|
+
std::string tintString = "";
|
|
1012
|
+
if (newTint != 0.0) {
|
|
1013
|
+
tintString = checkAndFormatDoubleAsString(newTint, -1.0, +1.0, 0.01);
|
|
1014
|
+
if (tintString.length() == 0) {
|
|
1015
|
+
using namespace std::literals::string_literals;
|
|
1016
|
+
throw XLException("XLDataBarColor::setTint: color tint "s + std::to_string(newTint) + " is not in range [-1.0;+1.0]"s);
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
if (tintString.length() == 0) return m_colorNode->remove_attribute("tint"); // remove tint attribute for a value 0
|
|
1020
|
+
|
|
1021
|
+
return (appendAndSetAttribute(*m_colorNode, "tint", tintString).empty() == false); // else: set tint attribute
|
|
1022
|
+
}
|
|
1023
|
+
bool XLDataBarColor::setAutomatic(bool set) { return appendAndSetAttribute(*m_colorNode, "auto", (set ? "true" : "false") ).empty() == false; }
|
|
1024
|
+
bool XLDataBarColor::setIndexed(uint32_t newIndex) { return appendAndSetAttribute(*m_colorNode, "indexed", std::to_string(newIndex) ).empty() == false; }
|
|
1025
|
+
bool XLDataBarColor::setTheme(uint32_t newTheme) {
|
|
1026
|
+
if( newTheme == XLDeleteProperty ) return m_colorNode->remove_attribute("theme");
|
|
1027
|
+
return appendAndSetAttribute(*m_colorNode, "theme", std::to_string(newTheme) ).empty() == false;
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
/**
|
|
1031
|
+
* @details assemble a string summary about the color
|
|
1032
|
+
*/
|
|
1033
|
+
std::string XLDataBarColor::summary() const
|
|
1034
|
+
{
|
|
1035
|
+
using namespace std::literals::string_literals;
|
|
1036
|
+
return "rgb is "s + rgb().hex()
|
|
1037
|
+
+ ", tint is "s + formatDoubleAsString(tint())
|
|
1038
|
+
+ (automatic() ? ", +automatic"s : ""s)
|
|
1039
|
+
+ (indexed() ? (", index is "s + std::to_string(indexed())) : "")
|
|
1040
|
+
+ (theme() ? (", theme is "s + std::to_string(theme() )) : "")
|
|
1041
|
+
;
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
|
|
1045
|
+
/**
|
|
1046
|
+
* @details Constructor. Initializes an empty XLGradientStop object
|
|
1047
|
+
*/
|
|
1048
|
+
XLGradientStop::XLGradientStop() : m_stopNode(std::make_unique<XMLNode>()) {}
|
|
1049
|
+
|
|
1050
|
+
/**
|
|
1051
|
+
* @details Constructor. Initializes the member variables for the new XLGradientStop object.
|
|
1052
|
+
*/
|
|
1053
|
+
XLGradientStop::XLGradientStop(const XMLNode& node) : m_stopNode(std::make_unique<XMLNode>(node)) {}
|
|
1054
|
+
|
|
1055
|
+
/**
|
|
1056
|
+
* @details Copy constructor - initializes the member variables from other
|
|
1057
|
+
*/
|
|
1058
|
+
XLGradientStop::XLGradientStop(const XLGradientStop& other)
|
|
1059
|
+
: m_stopNode(std::make_unique<XMLNode>(*other.m_stopNode))
|
|
1060
|
+
{}
|
|
1061
|
+
|
|
1062
|
+
/**
|
|
1063
|
+
* @details Move Constructor
|
|
1064
|
+
*/
|
|
1065
|
+
XLGradientStop::XLGradientStop(XLGradientStop&& other) noexcept = default;
|
|
1066
|
+
|
|
1067
|
+
/**
|
|
1068
|
+
* @details
|
|
1069
|
+
*/
|
|
1070
|
+
XLGradientStop::~XLGradientStop() = default;
|
|
1071
|
+
|
|
1072
|
+
/**
|
|
1073
|
+
* @details Copy assignment operator
|
|
1074
|
+
*/
|
|
1075
|
+
XLGradientStop& XLGradientStop::operator=(const XLGradientStop& other)
|
|
1076
|
+
{
|
|
1077
|
+
if (&other != this) *m_stopNode = *other.m_stopNode;
|
|
1078
|
+
return *this;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
/**
|
|
1082
|
+
* @details Move assignment operator
|
|
1083
|
+
*/
|
|
1084
|
+
XLGradientStop& XLGradientStop::operator=(XLGradientStop&& other) noexcept = default;
|
|
1085
|
+
|
|
1086
|
+
/**
|
|
1087
|
+
* @details Getter functions
|
|
1088
|
+
*/
|
|
1089
|
+
XLDataBarColor XLGradientStop::color() const
|
|
1090
|
+
{
|
|
1091
|
+
XMLNode color = appendAndGetNode(*m_stopNode, "color");
|
|
1092
|
+
if (color.empty()) return XLDataBarColor{};
|
|
1093
|
+
return XLDataBarColor(color);
|
|
1094
|
+
}
|
|
1095
|
+
double XLGradientStop::position() const
|
|
1096
|
+
{
|
|
1097
|
+
XMLAttribute attr = m_stopNode->attribute("position");
|
|
1098
|
+
return attr.as_double(0.0);
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
/**
|
|
1102
|
+
* @details Setter functions
|
|
1103
|
+
*/
|
|
1104
|
+
bool XLGradientStop::setPosition(double newPosition) { return appendAndSetAttribute(*m_stopNode, "position", formatDoubleAsString(newPosition)).empty() == false; }
|
|
1105
|
+
|
|
1106
|
+
|
|
1107
|
+
/**
|
|
1108
|
+
* @details assemble a string summary about the stop
|
|
1109
|
+
*/
|
|
1110
|
+
std::string XLGradientStop::summary() const
|
|
1111
|
+
{
|
|
1112
|
+
using namespace std::literals::string_literals;
|
|
1113
|
+
return "stop position is "s + formatDoubleAsString(position())
|
|
1114
|
+
+ ", " + color().summary();
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
|
|
1118
|
+
// ===== XLGradientStops, parent of XLGradientStop
|
|
1119
|
+
|
|
1120
|
+
/**
|
|
1121
|
+
* @details Constructor. Initializes an empty XLGradientStops object
|
|
1122
|
+
*/
|
|
1123
|
+
XLGradientStops::XLGradientStops() : m_gradientNode(std::make_unique<XMLNode>()) {}
|
|
1124
|
+
|
|
1125
|
+
/**
|
|
1126
|
+
* @details Constructor. Initializes the member variables for the new XLGradientStops object.
|
|
1127
|
+
*/
|
|
1128
|
+
XLGradientStops::XLGradientStops(const XMLNode& gradient)
|
|
1129
|
+
: m_gradientNode(std::make_unique<XMLNode>(gradient))
|
|
1130
|
+
{
|
|
1131
|
+
// initialize XLGradientStops entries and m_gradientStops here
|
|
1132
|
+
XMLNode node = m_gradientNode->first_child_of_type(pugi::node_element);
|
|
1133
|
+
while (not node.empty()) {
|
|
1134
|
+
std::string nodeName = node.name();
|
|
1135
|
+
if (nodeName == "stop")
|
|
1136
|
+
m_gradientStops.push_back(XLGradientStop(node));
|
|
1137
|
+
else
|
|
1138
|
+
std::cerr << "WARNING: XLGradientStops constructor: unknown subnode " << nodeName << std::endl;
|
|
1139
|
+
node = node.next_sibling_of_type(pugi::node_element);
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
/**
|
|
1144
|
+
* @details Copy constructor
|
|
1145
|
+
*/
|
|
1146
|
+
XLGradientStops::XLGradientStops(const XLGradientStops& other)
|
|
1147
|
+
: m_gradientNode(std::make_unique<XMLNode>(*other.m_gradientNode)),
|
|
1148
|
+
m_gradientStops(other.m_gradientStops)
|
|
1149
|
+
{}
|
|
1150
|
+
|
|
1151
|
+
/**
|
|
1152
|
+
* @details Move constructor
|
|
1153
|
+
*/
|
|
1154
|
+
XLGradientStops::XLGradientStops(XLGradientStops&& other)
|
|
1155
|
+
: m_gradientNode(std::move(other.m_gradientNode)),
|
|
1156
|
+
m_gradientStops(std::move(other.m_gradientStops))
|
|
1157
|
+
{}
|
|
1158
|
+
|
|
1159
|
+
/**
|
|
1160
|
+
* @details
|
|
1161
|
+
*/
|
|
1162
|
+
XLGradientStops::~XLGradientStops()
|
|
1163
|
+
{
|
|
1164
|
+
m_gradientStops.clear(); // delete vector with all children
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
/**
|
|
1168
|
+
* @details Copy assignment operator
|
|
1169
|
+
*/
|
|
1170
|
+
XLGradientStops& XLGradientStops::operator=(const XLGradientStops& other)
|
|
1171
|
+
{
|
|
1172
|
+
if (&other != this) {
|
|
1173
|
+
*m_gradientNode = *other.m_gradientNode;
|
|
1174
|
+
m_gradientStops.clear();
|
|
1175
|
+
m_gradientStops = other.m_gradientStops;
|
|
1176
|
+
}
|
|
1177
|
+
return *this;
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
/**
|
|
1181
|
+
* @details Move assignment operator.
|
|
1182
|
+
*/
|
|
1183
|
+
XLGradientStops& XLGradientStops::operator=(XLGradientStops&& other) noexcept = default;
|
|
1184
|
+
|
|
1185
|
+
/**
|
|
1186
|
+
* @details Returns the amount of gradient stops held by the class
|
|
1187
|
+
*/
|
|
1188
|
+
size_t XLGradientStops::count() const { return m_gradientStops.size(); }
|
|
1189
|
+
|
|
1190
|
+
/**
|
|
1191
|
+
* @details fetch XLGradientStop from m_gradientStops by index
|
|
1192
|
+
*/
|
|
1193
|
+
XLGradientStop XLGradientStops::stopByIndex(XLStyleIndex index) const
|
|
1194
|
+
{
|
|
1195
|
+
if (index >= m_gradientStops.size()) {
|
|
1196
|
+
using namespace std::literals::string_literals;
|
|
1197
|
+
throw XLException("XLGradientStops::"s + __func__ + ": attempted to access index "s + std::to_string(index) + " with count "s + std::to_string(m_gradientStops.size()));
|
|
1198
|
+
}
|
|
1199
|
+
return m_gradientStops.at(index);
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
/**
|
|
1203
|
+
* @details append a new XLGradientStop to m_gradientStops m_gradientNode, based on copyFrom
|
|
1204
|
+
*/
|
|
1205
|
+
XLStyleIndex XLGradientStops::create(XLGradientStop copyFrom, std::string styleEntriesPrefix)
|
|
1206
|
+
{
|
|
1207
|
+
XLStyleIndex index = count(); // index for the gradient stop to be created
|
|
1208
|
+
XMLNode newNode{}; // scope declaration
|
|
1209
|
+
|
|
1210
|
+
// ===== Append new node prior to final whitespaces, if any
|
|
1211
|
+
XMLNode lastStyle = m_gradientNode->last_child_of_type(pugi::node_element);
|
|
1212
|
+
if (lastStyle.empty()) newNode = m_gradientNode->prepend_child("stop");
|
|
1213
|
+
else newNode = m_gradientNode->insert_child_after("stop", lastStyle);
|
|
1214
|
+
if (newNode.empty()) {
|
|
1215
|
+
using namespace std::literals::string_literals;
|
|
1216
|
+
throw XLException("XLGradientStops::"s + __func__ + ": failed to append a new stop node"s);
|
|
1217
|
+
}
|
|
1218
|
+
if (styleEntriesPrefix.length() > 0) // if a whitespace prefix is configured
|
|
1219
|
+
m_gradientNode->insert_child_before(pugi::node_pcdata, newNode).set_value(styleEntriesPrefix.c_str()); // prefix the new node with styleEntriesPrefix
|
|
1220
|
+
|
|
1221
|
+
XLGradientStop newStop(newNode);
|
|
1222
|
+
if (copyFrom.m_stopNode->empty()) { // if no template is given
|
|
1223
|
+
// ===== Create a stop node with default values
|
|
1224
|
+
// TODO: implement stop defaults
|
|
1225
|
+
// newStop.setProperty(defaultValue);
|
|
1226
|
+
// ...
|
|
1227
|
+
}
|
|
1228
|
+
else
|
|
1229
|
+
copyXMLNode(newNode, *copyFrom.m_stopNode); // will use copyFrom as template, does nothing if copyFrom is empty
|
|
1230
|
+
|
|
1231
|
+
m_gradientStops.push_back(newStop);
|
|
1232
|
+
appendAndSetAttribute(*m_gradientNode, "count", std::to_string(m_gradientStops.size())); // update array count in XML
|
|
1233
|
+
return index;
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1236
|
+
std::string XLGradientStops::summary() const
|
|
1237
|
+
{
|
|
1238
|
+
std::string result{};
|
|
1239
|
+
for(XLGradientStop stop : m_gradientStops)
|
|
1240
|
+
result += stop.summary() + ", ";
|
|
1241
|
+
if (result.length() < 2) return ""; // if no stop summary was created - return empty string
|
|
1242
|
+
return result.substr(0, result.length() - 2);
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
/**
|
|
1246
|
+
* @details Constructor. Initializes an empty XLFill object
|
|
1247
|
+
*/
|
|
1248
|
+
XLFill::XLFill() : m_fillNode(std::make_unique<XMLNode>()) {}
|
|
1249
|
+
|
|
1250
|
+
/**
|
|
1251
|
+
* @details Constructor. Initializes the member variables for the new XLFill object.
|
|
1252
|
+
*/
|
|
1253
|
+
XLFill::XLFill(const XMLNode& node) : m_fillNode(std::make_unique<XMLNode>(node)) {}
|
|
1254
|
+
|
|
1255
|
+
/**
|
|
1256
|
+
* @details Copy constructor
|
|
1257
|
+
*/
|
|
1258
|
+
XLFill::XLFill(const XLFill& other)
|
|
1259
|
+
: m_fillNode(std::make_unique<XMLNode>(*other.m_fillNode))
|
|
1260
|
+
{}
|
|
1261
|
+
|
|
1262
|
+
/**
|
|
1263
|
+
* @details Move constructor
|
|
1264
|
+
*/
|
|
1265
|
+
XLFill::XLFill(XLFill&& other) noexcept = default;
|
|
1266
|
+
|
|
1267
|
+
/**
|
|
1268
|
+
* @details
|
|
1269
|
+
*/
|
|
1270
|
+
XLFill::~XLFill() = default;
|
|
1271
|
+
|
|
1272
|
+
/**
|
|
1273
|
+
* @details Copy assignment operator
|
|
1274
|
+
*/
|
|
1275
|
+
XLFill& XLFill::operator=(const XLFill& other)
|
|
1276
|
+
{
|
|
1277
|
+
if (&other != this) *m_fillNode = *other.m_fillNode;
|
|
1278
|
+
return *this;
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
/**
|
|
1282
|
+
* @details Move assignment operator
|
|
1283
|
+
*/
|
|
1284
|
+
XLFill& XLFill::operator=(XLFill&& other) noexcept = default;
|
|
1285
|
+
|
|
1286
|
+
/**
|
|
1287
|
+
* @details Returns the name of the first element child of fill
|
|
1288
|
+
* @note an empty node ::name() returns an empty string "", leading to XLFillTypeInvalid
|
|
1289
|
+
*/
|
|
1290
|
+
XLFillType XLFill::fillType() const { return XLFillTypeFromString(m_fillNode->first_child_of_type(pugi::node_element).name()); }
|
|
1291
|
+
|
|
1292
|
+
/**
|
|
1293
|
+
* @details set the fill type for a fill node - if force is true, delete any existing fill properties
|
|
1294
|
+
*/
|
|
1295
|
+
bool XLFill::setFillType(XLFillType newFillType, bool force)
|
|
1296
|
+
{
|
|
1297
|
+
XLFillType ft = fillType(); // determine once, use twice
|
|
1298
|
+
|
|
1299
|
+
// ===== If desired filltype is already set
|
|
1300
|
+
if (ft == newFillType) return true; // nothing to do
|
|
1301
|
+
|
|
1302
|
+
// ===== If force == true or fillType is just not set at all, delete existing child nodes, otherwise throw
|
|
1303
|
+
if (!force && ft != XLFillTypeInvalid) {
|
|
1304
|
+
using namespace std::literals::string_literals;
|
|
1305
|
+
throw XLException("XLFill::setFillType: can not change the fillType from "s + XLFillTypeToString(fillType())
|
|
1306
|
+
+ " to "s + XLFillTypeToString(newFillType) + " - invoke with force == true if override is desired"s);
|
|
1307
|
+
}
|
|
1308
|
+
// ===== At this point, m_fillNode needs to be emptied for a setting / force-change of the fill type
|
|
1309
|
+
|
|
1310
|
+
// ===== Delete all fill node children and insert a new node for the newFillType
|
|
1311
|
+
m_fillNode->remove_children();
|
|
1312
|
+
return (m_fillNode->append_child(XLFillTypeToString(newFillType).c_str()).empty() == false);
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
/**
|
|
1316
|
+
* @details Throw an XLException on a fill of typeToThrowOn
|
|
1317
|
+
*/
|
|
1318
|
+
void XLFill::throwOnFillType(XLFillType typeToThrowOn, const char *functionName) const
|
|
1319
|
+
{
|
|
1320
|
+
using namespace std::literals::string_literals;
|
|
1321
|
+
if (fillType() == typeToThrowOn)
|
|
1322
|
+
throw XLException("XLFill::"s + functionName + " must not be invoked for a "s + XLFillTypeToString(typeToThrowOn));
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
/**
|
|
1326
|
+
* @details get the fill element XML, create element with default XLFillType if none exists
|
|
1327
|
+
*/
|
|
1328
|
+
XMLNode XLFill::getValidFillDescription(XLFillType fillTypeIfEmpty, const char *functionName)
|
|
1329
|
+
{
|
|
1330
|
+
XLFillType throwOnThis = XLFillTypeInvalid;
|
|
1331
|
+
switch (fillTypeIfEmpty) {
|
|
1332
|
+
case XLGradientFill: throwOnThis = XLPatternFill; break; // throw on non-matching fill type
|
|
1333
|
+
case XLPatternFill : throwOnThis = XLGradientFill; break; // "
|
|
1334
|
+
default: throw XLException("XLFill::getValidFillDescription was not invoked with XLPatternFill or XLGradientFill");
|
|
1335
|
+
}
|
|
1336
|
+
throwOnFillType(throwOnThis, functionName);
|
|
1337
|
+
XMLNode fillDescription = m_fillNode->first_child_of_type(pugi::node_element); // fetch an existing fill description
|
|
1338
|
+
if (fillDescription.empty() && setFillType(fillTypeIfEmpty)) // if none exists, attempt to create a description
|
|
1339
|
+
fillDescription = m_fillNode->first_child_of_type(pugi::node_element); // fetch newly inserted description
|
|
1340
|
+
return fillDescription;
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
|
|
1344
|
+
/**
|
|
1345
|
+
* @details Getter functions for gradientFill
|
|
1346
|
+
*/
|
|
1347
|
+
XLGradientType XLFill::gradientType() { return XLGradientTypeFromString(getValidFillDescription(XLGradientFill, __func__).attribute("type" ).value() ); }
|
|
1348
|
+
double XLFill::degree() { return getValidFillDescription(XLGradientFill, __func__).attribute("degree").as_double(0) ; }
|
|
1349
|
+
double XLFill::left() { return getValidFillDescription(XLGradientFill, __func__).attribute("left" ).as_double(0) ; }
|
|
1350
|
+
double XLFill::right() { return getValidFillDescription(XLGradientFill, __func__).attribute("right" ).as_double(0) ; }
|
|
1351
|
+
double XLFill::top() { return getValidFillDescription(XLGradientFill, __func__).attribute("top" ).as_double(0) ; }
|
|
1352
|
+
double XLFill::bottom() { return getValidFillDescription(XLGradientFill, __func__).attribute("bottom").as_double(0) ; }
|
|
1353
|
+
XLGradientStops XLFill::stops() { return XLGradientStops( getValidFillDescription(XLGradientFill, __func__) ); }
|
|
1354
|
+
|
|
1355
|
+
/**
|
|
1356
|
+
* @details Getter functions for patternFill
|
|
1357
|
+
*/
|
|
1358
|
+
XLPatternType XLFill::patternType()
|
|
1359
|
+
{
|
|
1360
|
+
XMLNode fillDescription = getValidFillDescription(XLPatternFill, __func__);
|
|
1361
|
+
if (fillDescription.empty()) return XLDefaultPatternType; // if no description could be fetched: fail
|
|
1362
|
+
XMLAttribute attr = appendAndGetNodeAttribute(*m_fillNode, XLFillTypeToString(XLPatternFill), "patternType", XLPatternTypeToString(XLDefaultPatternType));
|
|
1363
|
+
return XLPatternTypeFromString(attr.value());
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
XLColor XLFill::color()
|
|
1367
|
+
{
|
|
1368
|
+
XMLNode fillDescription = getValidFillDescription(XLPatternFill, __func__);
|
|
1369
|
+
if (fillDescription.empty()) return XLColor{}; // if no description could be fetched: fail
|
|
1370
|
+
XMLAttribute fgColorRGB = appendAndGetNodeAttribute(fillDescription, "fgColor", "rgb", XLDefaultPatternFgColor);
|
|
1371
|
+
return XLColor(fgColorRGB.value());
|
|
1372
|
+
}
|
|
1373
|
+
XLColor XLFill::backgroundColor()
|
|
1374
|
+
{
|
|
1375
|
+
XMLNode fillDescription = getValidFillDescription(XLPatternFill, __func__);
|
|
1376
|
+
if (fillDescription.empty()) return XLColor{}; // if no description could be fetched: fail
|
|
1377
|
+
XMLAttribute bgColorRGB = appendAndGetNodeAttribute(fillDescription, "bgColor", "rgb", XLDefaultPatternBgColor);
|
|
1378
|
+
return XLColor(bgColorRGB.value());
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
/**
|
|
1382
|
+
* @details Setter functions for gradientFill
|
|
1383
|
+
*/
|
|
1384
|
+
bool XLFill::setGradientType(XLGradientType newType)
|
|
1385
|
+
{
|
|
1386
|
+
XMLNode fillDescription = getValidFillDescription(XLGradientFill, __func__);
|
|
1387
|
+
return appendAndSetAttribute(fillDescription, "type", XLGradientTypeToString(newType)).empty() == false;
|
|
1388
|
+
}
|
|
1389
|
+
bool XLFill::setDegree(double newDegree)
|
|
1390
|
+
{
|
|
1391
|
+
std::string degreeString = checkAndFormatDoubleAsString(newDegree, 0.0, 360.0, 0.01);
|
|
1392
|
+
if (degreeString.length() == 0) {
|
|
1393
|
+
using namespace std::literals::string_literals;
|
|
1394
|
+
throw XLException("XLFill::setDegree: gradientFill degree value "s + std::to_string(newDegree) + " is not in range [0.0;360.0]"s);
|
|
1395
|
+
}
|
|
1396
|
+
XMLNode fillDescription = getValidFillDescription(XLGradientFill, __func__);
|
|
1397
|
+
return appendAndSetAttribute(fillDescription, "degree", degreeString ).empty() == false;
|
|
1398
|
+
}
|
|
1399
|
+
bool XLFill::setLeft(double newLeft)
|
|
1400
|
+
{
|
|
1401
|
+
XMLNode fillDescription = getValidFillDescription(XLGradientFill, __func__);
|
|
1402
|
+
return appendAndSetAttribute(fillDescription, "left", formatDoubleAsString(newLeft ).c_str()).empty() == false;
|
|
1403
|
+
}
|
|
1404
|
+
bool XLFill::setRight(double newRight)
|
|
1405
|
+
{
|
|
1406
|
+
XMLNode fillDescription = getValidFillDescription(XLGradientFill, __func__);
|
|
1407
|
+
return appendAndSetAttribute(fillDescription, "right", formatDoubleAsString(newRight ).c_str()).empty() == false;
|
|
1408
|
+
}
|
|
1409
|
+
bool XLFill::setTop(double newTop)
|
|
1410
|
+
{
|
|
1411
|
+
XMLNode fillDescription = getValidFillDescription(XLGradientFill, __func__);
|
|
1412
|
+
return appendAndSetAttribute(fillDescription, "top", formatDoubleAsString(newTop ).c_str()).empty() == false;
|
|
1413
|
+
}
|
|
1414
|
+
bool XLFill::setBottom(double newBottom)
|
|
1415
|
+
{
|
|
1416
|
+
XMLNode fillDescription = getValidFillDescription(XLGradientFill, __func__);
|
|
1417
|
+
return appendAndSetAttribute(fillDescription, "bottom", formatDoubleAsString(newBottom).c_str()).empty() == false;
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
/**
|
|
1421
|
+
* @details Setter functions for patternFill
|
|
1422
|
+
*/
|
|
1423
|
+
bool XLFill::setPatternType(XLPatternType newFillPattern)
|
|
1424
|
+
{
|
|
1425
|
+
XMLNode fillDescription = getValidFillDescription(XLPatternFill, __func__);
|
|
1426
|
+
if (fillDescription.empty()) return false; // if no description could be fetched: fail
|
|
1427
|
+
return appendAndSetAttribute(fillDescription, "patternType", XLPatternTypeToString(newFillPattern)).empty() == false;
|
|
1428
|
+
}
|
|
1429
|
+
bool XLFill::setColor(XLColor newColor)
|
|
1430
|
+
{
|
|
1431
|
+
XMLNode fillDescription = getValidFillDescription(XLPatternFill, __func__);
|
|
1432
|
+
if (fillDescription.empty()) return false; // if no description could be fetched: fail
|
|
1433
|
+
return appendAndSetNodeAttribute(fillDescription, "fgColor", "rgb", newColor.hex(), XLRemoveAttributes).empty() == false;
|
|
1434
|
+
}
|
|
1435
|
+
bool XLFill::setBackgroundColor(XLColor newBgColor)
|
|
1436
|
+
{
|
|
1437
|
+
XMLNode fillDescription = getValidFillDescription(XLPatternFill, __func__);
|
|
1438
|
+
if (fillDescription.empty()) return false; // if no description could be fetched: fail
|
|
1439
|
+
return appendAndSetNodeAttribute(fillDescription, "bgColor", "rgb", newBgColor.hex(), XLRemoveAttributes).empty() == false;
|
|
1440
|
+
}
|
|
1441
|
+
|
|
1442
|
+
|
|
1443
|
+
/**
|
|
1444
|
+
* @details assemble a string summary about the fill
|
|
1445
|
+
*/
|
|
1446
|
+
std::string XLFill::summary()
|
|
1447
|
+
{
|
|
1448
|
+
using namespace std::literals::string_literals;
|
|
1449
|
+
switch (fillType()) {
|
|
1450
|
+
case XLGradientFill:
|
|
1451
|
+
return "fill type is "s + XLFillTypeToString(fillType())
|
|
1452
|
+
+ ", gradient type is "s + XLGradientTypeToString(gradientType())
|
|
1453
|
+
+ ", degree is: "s + formatDoubleAsString(degree())
|
|
1454
|
+
+ ", left is: "s + formatDoubleAsString(left())
|
|
1455
|
+
+ ", right is: "s + formatDoubleAsString(right())
|
|
1456
|
+
+ ", top is: "s + formatDoubleAsString(top())
|
|
1457
|
+
+ ", bottom is: "s + formatDoubleAsString(bottom())
|
|
1458
|
+
+ ", stops: "s + stops().summary();
|
|
1459
|
+
case XLPatternFill :
|
|
1460
|
+
return "fill type is "s + XLFillTypeToString(fillType())
|
|
1461
|
+
+ ", pattern type is "s + XLPatternTypeToString(patternType())
|
|
1462
|
+
+ ", fgcolor is: "s + color().hex() + ", bgcolor: "s + backgroundColor().hex();
|
|
1463
|
+
case XLFillTypeInvalid: [[fallthrough]];
|
|
1464
|
+
default :
|
|
1465
|
+
return "fill type is invalid!"s;
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1468
|
+
|
|
1469
|
+
// ===== XLFills, parent of XLFill
|
|
1470
|
+
|
|
1471
|
+
/**
|
|
1472
|
+
* @details Constructor. Initializes an empty XLFills object
|
|
1473
|
+
*/
|
|
1474
|
+
XLFills::XLFills() : m_fillsNode(std::make_unique<XMLNode>()) {}
|
|
1475
|
+
|
|
1476
|
+
/**
|
|
1477
|
+
* @details Constructor. Initializes the member variables for the new XLFills object.
|
|
1478
|
+
*/
|
|
1479
|
+
XLFills::XLFills(const XMLNode& fills)
|
|
1480
|
+
: m_fillsNode(std::make_unique<XMLNode>(fills))
|
|
1481
|
+
{
|
|
1482
|
+
// initialize XLFills entries and m_fills here
|
|
1483
|
+
XMLNode node = fills.first_child_of_type(pugi::node_element);
|
|
1484
|
+
while (not node.empty()) {
|
|
1485
|
+
std::string nodeName = node.name();
|
|
1486
|
+
if (nodeName == "fill")
|
|
1487
|
+
m_fills.push_back(XLFill(node));
|
|
1488
|
+
else
|
|
1489
|
+
std::cerr << "WARNING: XLFills constructor: unknown subnode " << nodeName << std::endl;
|
|
1490
|
+
node = node.next_sibling_of_type(pugi::node_element);
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
/**
|
|
1495
|
+
* @details Copy constructor
|
|
1496
|
+
*/
|
|
1497
|
+
XLFills::XLFills(const XLFills& other)
|
|
1498
|
+
: m_fillsNode(std::make_unique<XMLNode>(*other.m_fillsNode)),
|
|
1499
|
+
m_fills(other.m_fills)
|
|
1500
|
+
{}
|
|
1501
|
+
|
|
1502
|
+
/**
|
|
1503
|
+
* @details Move constructor
|
|
1504
|
+
*/
|
|
1505
|
+
XLFills::XLFills(XLFills&& other)
|
|
1506
|
+
: m_fillsNode(std::move(other.m_fillsNode)),
|
|
1507
|
+
m_fills(std::move(other.m_fills))
|
|
1508
|
+
{}
|
|
1509
|
+
|
|
1510
|
+
/**
|
|
1511
|
+
* @details
|
|
1512
|
+
*/
|
|
1513
|
+
XLFills::~XLFills()
|
|
1514
|
+
{
|
|
1515
|
+
m_fills.clear(); // delete vector with all children
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1518
|
+
/**
|
|
1519
|
+
* @details Copy assignment operator
|
|
1520
|
+
*/
|
|
1521
|
+
XLFills& XLFills::operator=(const XLFills& other)
|
|
1522
|
+
{
|
|
1523
|
+
if (&other != this) {
|
|
1524
|
+
*m_fillsNode = *other.m_fillsNode;
|
|
1525
|
+
m_fills.clear();
|
|
1526
|
+
m_fills = other.m_fills;
|
|
1527
|
+
}
|
|
1528
|
+
return *this;
|
|
1529
|
+
}
|
|
1530
|
+
|
|
1531
|
+
/**
|
|
1532
|
+
* @details Move assignment operator
|
|
1533
|
+
*/
|
|
1534
|
+
XLFills& XLFills::operator=(XLFills&& other) noexcept = default;
|
|
1535
|
+
|
|
1536
|
+
/**
|
|
1537
|
+
* @details Returns the amount of fills held by the class
|
|
1538
|
+
*/
|
|
1539
|
+
size_t XLFills::count() const { return m_fills.size(); }
|
|
1540
|
+
|
|
1541
|
+
/**
|
|
1542
|
+
* @details fetch XLFill from m_fills by index
|
|
1543
|
+
*/
|
|
1544
|
+
XLFill XLFills::fillByIndex(XLStyleIndex index) const
|
|
1545
|
+
{
|
|
1546
|
+
if (index >= m_fills.size()) {
|
|
1547
|
+
using namespace std::literals::string_literals;
|
|
1548
|
+
throw XLException("XLFills::"s + __func__ + ": attempted to access index "s + std::to_string(index) + " with count "s + std::to_string(m_fills.size()));
|
|
1549
|
+
}
|
|
1550
|
+
return m_fills.at(index);
|
|
1551
|
+
}
|
|
1552
|
+
|
|
1553
|
+
/**
|
|
1554
|
+
* @details append a new XLFill to m_fills and m_fillsNode, based on copyFrom
|
|
1555
|
+
*/
|
|
1556
|
+
XLStyleIndex XLFills::create(XLFill copyFrom, std::string styleEntriesPrefix)
|
|
1557
|
+
{
|
|
1558
|
+
XLStyleIndex index = count(); // index for the fill to be created
|
|
1559
|
+
XMLNode newNode{}; // scope declaration
|
|
1560
|
+
|
|
1561
|
+
// ===== Append new node prior to final whitespaces, if any
|
|
1562
|
+
XMLNode lastStyle = m_fillsNode->last_child_of_type(pugi::node_element);
|
|
1563
|
+
if (lastStyle.empty()) newNode = m_fillsNode->prepend_child("fill");
|
|
1564
|
+
else newNode = m_fillsNode->insert_child_after("fill", lastStyle);
|
|
1565
|
+
if (newNode.empty()) {
|
|
1566
|
+
using namespace std::literals::string_literals;
|
|
1567
|
+
throw XLException("XLFills::"s + __func__ + ": failed to append a new fill node"s);
|
|
1568
|
+
}
|
|
1569
|
+
if (styleEntriesPrefix.length() > 0) // if a whitespace prefix is configured
|
|
1570
|
+
m_fillsNode->insert_child_before(pugi::node_pcdata, newNode).set_value(styleEntriesPrefix.c_str()); // prefix the new node with styleEntriesPrefix
|
|
1571
|
+
|
|
1572
|
+
XLFill newFill(newNode);
|
|
1573
|
+
if (copyFrom.m_fillNode->empty()) { // if no template is given
|
|
1574
|
+
// ===== Create a fill with default values
|
|
1575
|
+
// TODO: implement fill defaults
|
|
1576
|
+
// newFill.setProperty(defaultValue);
|
|
1577
|
+
// ...
|
|
1578
|
+
}
|
|
1579
|
+
else
|
|
1580
|
+
copyXMLNode(newNode, *copyFrom.m_fillNode); // will use copyFrom as template, does nothing if copyFrom is empty
|
|
1581
|
+
|
|
1582
|
+
m_fills.push_back(newFill);
|
|
1583
|
+
appendAndSetAttribute(*m_fillsNode, "count", std::to_string(m_fills.size())); // update array count in XML
|
|
1584
|
+
return index;
|
|
1585
|
+
}
|
|
1586
|
+
|
|
1587
|
+
|
|
1588
|
+
/**
|
|
1589
|
+
* @details Constructor. Initializes an empty XLLine object
|
|
1590
|
+
*/
|
|
1591
|
+
XLLine::XLLine() : m_lineNode(std::make_unique<XMLNode>()) {}
|
|
1592
|
+
|
|
1593
|
+
/**
|
|
1594
|
+
* @details Constructor. Initializes the member variables for the new XLLine object.
|
|
1595
|
+
*/
|
|
1596
|
+
XLLine::XLLine(const XMLNode& node) : m_lineNode(std::make_unique<XMLNode>(node)) {}
|
|
1597
|
+
|
|
1598
|
+
/**
|
|
1599
|
+
* @details Copy constructor
|
|
1600
|
+
*/
|
|
1601
|
+
XLLine::XLLine(const XLLine& other)
|
|
1602
|
+
: m_lineNode(std::make_unique<XMLNode>(*other.m_lineNode))
|
|
1603
|
+
{}
|
|
1604
|
+
|
|
1605
|
+
/**
|
|
1606
|
+
* @details Move constructor
|
|
1607
|
+
*/
|
|
1608
|
+
XLLine::XLLine(XLLine&& other) noexcept = default;
|
|
1609
|
+
|
|
1610
|
+
/**
|
|
1611
|
+
* @details
|
|
1612
|
+
*/
|
|
1613
|
+
XLLine::~XLLine() = default;
|
|
1614
|
+
|
|
1615
|
+
/**
|
|
1616
|
+
* @details Copy assignment operator
|
|
1617
|
+
*/
|
|
1618
|
+
XLLine& XLLine::operator=(const XLLine& other)
|
|
1619
|
+
{
|
|
1620
|
+
if (&other != this) *m_lineNode = *other.m_lineNode;
|
|
1621
|
+
return *this;
|
|
1622
|
+
}
|
|
1623
|
+
|
|
1624
|
+
/**
|
|
1625
|
+
* @details Move assignment operator
|
|
1626
|
+
*/
|
|
1627
|
+
XLLine& XLLine::operator=(XLLine&& other) noexcept = default;
|
|
1628
|
+
|
|
1629
|
+
/**
|
|
1630
|
+
* @details Returns the line style (XLLineStyleNone if line is not set)
|
|
1631
|
+
*/
|
|
1632
|
+
XLLineStyle XLLine::style() const
|
|
1633
|
+
{
|
|
1634
|
+
if (m_lineNode->empty()) return XLLineStyleNone;
|
|
1635
|
+
XMLAttribute attr = appendAndGetAttribute(*m_lineNode, "style", OpenXLSX::XLDefaultLineStyle);
|
|
1636
|
+
return XLLineStyleFromString(attr.value());
|
|
1637
|
+
}
|
|
1638
|
+
|
|
1639
|
+
/**
|
|
1640
|
+
* @details check if line is used (set) or not
|
|
1641
|
+
*/
|
|
1642
|
+
XLLine::operator bool() const { return (style() != XLLineStyleNone); }
|
|
1643
|
+
|
|
1644
|
+
/**
|
|
1645
|
+
* @details Returns the line data bar color object
|
|
1646
|
+
*/
|
|
1647
|
+
XLDataBarColor XLLine::color() const
|
|
1648
|
+
{
|
|
1649
|
+
XMLNode color = appendAndGetNode(*m_lineNode, "color");
|
|
1650
|
+
if (color.empty()) return XLDataBarColor{};
|
|
1651
|
+
return XLDataBarColor(color);
|
|
1652
|
+
}
|
|
1653
|
+
// XLColor XLLine::color() const
|
|
1654
|
+
// {
|
|
1655
|
+
// XMLNode colorDetails = m_lineNode->child("color");
|
|
1656
|
+
// if (colorDetails.empty()) return XLColor("ffffffff");
|
|
1657
|
+
// XMLAttribute colorRGB = colorDetails.attribute("rgb");
|
|
1658
|
+
// if (colorRGB.empty()) return XLColor("ffffffff");
|
|
1659
|
+
// return XLColor(colorRGB.value());
|
|
1660
|
+
// }
|
|
1661
|
+
//
|
|
1662
|
+
// /**
|
|
1663
|
+
// * @details Returns the line color tint
|
|
1664
|
+
// */
|
|
1665
|
+
// double XLLine::colorTint() const
|
|
1666
|
+
// {
|
|
1667
|
+
// XMLNode colorDetails = m_lineNode->child("color");
|
|
1668
|
+
// if (not colorDetails.empty()) {
|
|
1669
|
+
// XMLAttribute colorTint = colorDetails.attribute("tint");
|
|
1670
|
+
// if (not colorTint.empty())
|
|
1671
|
+
// return colorTint.as_double();
|
|
1672
|
+
// }
|
|
1673
|
+
// return 0.0;
|
|
1674
|
+
// }
|
|
1675
|
+
|
|
1676
|
+
/**
|
|
1677
|
+
* @details assemble a string summary about the fill
|
|
1678
|
+
*/
|
|
1679
|
+
std::string XLLine::summary() const
|
|
1680
|
+
{
|
|
1681
|
+
using namespace std::literals::string_literals;
|
|
1682
|
+
return "line style is "s + XLLineStyleToString(style()) + ", "s + color().summary();
|
|
1683
|
+
// double tint = colorTint();
|
|
1684
|
+
// std::string tintSummary = "colorTint is "s + (tint == 0.0 ? "(none)"s : std::to_string(tint));
|
|
1685
|
+
// size_t tintDecimalPos = tintSummary.find_last_of('.');
|
|
1686
|
+
// if (tintDecimalPos != std::string::npos) tintSummary = tintSummary.substr(0, tintDecimalPos + 3); // truncate colorTint double output 2 digits after the decimal separator
|
|
1687
|
+
// return "line style is "s + XLLineStyleToString(style()) + ", color is "s + color().hex() + ", "s + tintSummary;
|
|
1688
|
+
}
|
|
1689
|
+
|
|
1690
|
+
|
|
1691
|
+
/**
|
|
1692
|
+
* @details Constructor. Initializes an empty XLBorder object
|
|
1693
|
+
*/
|
|
1694
|
+
XLBorder::XLBorder() : m_borderNode(std::make_unique<XMLNode>()) {}
|
|
1695
|
+
|
|
1696
|
+
/**
|
|
1697
|
+
* @details Constructor. Initializes the member variables for the new XLBorder object.
|
|
1698
|
+
*/
|
|
1699
|
+
XLBorder::XLBorder(const XMLNode& node) : m_borderNode(std::make_unique<XMLNode>(node)) {}
|
|
1700
|
+
|
|
1701
|
+
/**
|
|
1702
|
+
* @details Copy constructor
|
|
1703
|
+
*/
|
|
1704
|
+
XLBorder::XLBorder(const XLBorder& other)
|
|
1705
|
+
: m_borderNode(std::make_unique<XMLNode>(*other.m_borderNode))
|
|
1706
|
+
{}
|
|
1707
|
+
|
|
1708
|
+
/**
|
|
1709
|
+
* @details Move constructor
|
|
1710
|
+
*/
|
|
1711
|
+
XLBorder::XLBorder(XLBorder&& other) noexcept = default;
|
|
1712
|
+
|
|
1713
|
+
/**
|
|
1714
|
+
* @details
|
|
1715
|
+
*/
|
|
1716
|
+
XLBorder::~XLBorder() = default;
|
|
1717
|
+
|
|
1718
|
+
/**
|
|
1719
|
+
* @details Copy assignment operator
|
|
1720
|
+
*/
|
|
1721
|
+
XLBorder& XLBorder::operator=(const XLBorder& other)
|
|
1722
|
+
{
|
|
1723
|
+
if (&other != this) *m_borderNode = *other.m_borderNode;
|
|
1724
|
+
return *this;
|
|
1725
|
+
}
|
|
1726
|
+
|
|
1727
|
+
/**
|
|
1728
|
+
* @details Move assignment operator
|
|
1729
|
+
*/
|
|
1730
|
+
XLBorder& XLBorder::operator=(XLBorder&& other) noexcept = default;
|
|
1731
|
+
|
|
1732
|
+
/**
|
|
1733
|
+
* @details determines whether the diagonalUp property is set
|
|
1734
|
+
*/
|
|
1735
|
+
bool XLBorder::diagonalUp() const { return m_borderNode->attribute("diagonalUp").as_bool(); }
|
|
1736
|
+
|
|
1737
|
+
/**
|
|
1738
|
+
* @details determines whether the diagonalDown property is set
|
|
1739
|
+
*/
|
|
1740
|
+
bool XLBorder::diagonalDown() const { return m_borderNode->attribute("diagonalDown").as_bool(); }
|
|
1741
|
+
|
|
1742
|
+
/**
|
|
1743
|
+
* @details determines whether the outline property is set
|
|
1744
|
+
*/
|
|
1745
|
+
bool XLBorder::outline() const { return m_borderNode->attribute("outline").as_bool(); }
|
|
1746
|
+
|
|
1747
|
+
/**
|
|
1748
|
+
* @details fetch lines
|
|
1749
|
+
*/
|
|
1750
|
+
XLLine XLBorder::left() const { return XLLine(m_borderNode->child("left") ); }
|
|
1751
|
+
XLLine XLBorder::right() const { return XLLine(m_borderNode->child("right") ); }
|
|
1752
|
+
XLLine XLBorder::top() const { return XLLine(m_borderNode->child("top") ); }
|
|
1753
|
+
XLLine XLBorder::bottom() const { return XLLine(m_borderNode->child("bottom") ); }
|
|
1754
|
+
XLLine XLBorder::diagonal() const { return XLLine(m_borderNode->child("diagonal") ); }
|
|
1755
|
+
XLLine XLBorder::vertical() const { return XLLine(m_borderNode->child("vertical") ); }
|
|
1756
|
+
XLLine XLBorder::horizontal() const { return XLLine(m_borderNode->child("horizontal")); }
|
|
1757
|
+
|
|
1758
|
+
/**
|
|
1759
|
+
* @details Setter functions
|
|
1760
|
+
*/
|
|
1761
|
+
bool XLBorder::setDiagonalUp (bool set) { return appendAndSetAttribute(*m_borderNode, "diagonalUp", (set ? "true" : "false")).empty() == false; }
|
|
1762
|
+
bool XLBorder::setDiagonalDown(bool set) { return appendAndSetAttribute(*m_borderNode, "diagonalDown", (set ? "true" : "false")).empty() == false; }
|
|
1763
|
+
bool XLBorder::setOutline (bool set) { return appendAndSetAttribute(*m_borderNode, "outline", (set ? "true" : "false")).empty() == false; }
|
|
1764
|
+
bool XLBorder::setLine(XLLineType lineType, XLLineStyle lineStyle, XLColor lineColor, double lineTint)
|
|
1765
|
+
{
|
|
1766
|
+
XMLNode lineNode = appendAndGetNode(*m_borderNode, XLLineTypeToString(lineType), m_nodeOrder); // generate line node if not present
|
|
1767
|
+
// 2024-12-19: non-existing lines are added using an ordered insert to address issue #304
|
|
1768
|
+
bool success = (lineNode.empty() == false);
|
|
1769
|
+
if (success) success = (appendAndSetAttribute(lineNode, "style", XLLineStyleToString(lineStyle)).empty() == false); // set style attribute
|
|
1770
|
+
XMLNode colorNode{}; // empty node
|
|
1771
|
+
if (success) colorNode = appendAndGetNode(lineNode, "color"); // generate color node if not present
|
|
1772
|
+
XLDataBarColor colorObject{colorNode};
|
|
1773
|
+
success = (colorNode.empty() == false);
|
|
1774
|
+
if (success) success = colorObject.setRgb(lineColor);
|
|
1775
|
+
if (success) success = colorObject.setTint(lineTint);
|
|
1776
|
+
return success;
|
|
1777
|
+
}
|
|
1778
|
+
bool XLBorder::setLeft (XLLineStyle lineStyle, XLColor lineColor, double lineTint) { return setLine(XLLineLeft, lineStyle, lineColor, lineTint); }
|
|
1779
|
+
bool XLBorder::setRight (XLLineStyle lineStyle, XLColor lineColor, double lineTint) { return setLine(XLLineRight, lineStyle, lineColor, lineTint); }
|
|
1780
|
+
bool XLBorder::setTop (XLLineStyle lineStyle, XLColor lineColor, double lineTint) { return setLine(XLLineTop, lineStyle, lineColor, lineTint); }
|
|
1781
|
+
bool XLBorder::setBottom (XLLineStyle lineStyle, XLColor lineColor, double lineTint) { return setLine(XLLineBottom, lineStyle, lineColor, lineTint); }
|
|
1782
|
+
bool XLBorder::setDiagonal (XLLineStyle lineStyle, XLColor lineColor, double lineTint) { return setLine(XLLineDiagonal, lineStyle, lineColor, lineTint); }
|
|
1783
|
+
bool XLBorder::setVertical (XLLineStyle lineStyle, XLColor lineColor, double lineTint) { return setLine(XLLineVertical, lineStyle, lineColor, lineTint); }
|
|
1784
|
+
bool XLBorder::setHorizontal(XLLineStyle lineStyle, XLColor lineColor, double lineTint) { return setLine(XLLineHorizontal, lineStyle, lineColor, lineTint); }
|
|
1785
|
+
|
|
1786
|
+
|
|
1787
|
+
/**
|
|
1788
|
+
* @details assemble a string summary about the fill
|
|
1789
|
+
*/
|
|
1790
|
+
std::string XLBorder::summary() const
|
|
1791
|
+
{
|
|
1792
|
+
using namespace std::literals::string_literals;
|
|
1793
|
+
std::string lineInfo{};
|
|
1794
|
+
lineInfo += ", left: "s + left().summary() + ", right: " + right().summary()
|
|
1795
|
+
+ ", top: "s + top().summary() + ", bottom: " + bottom().summary()
|
|
1796
|
+
+ ", diagonal: "s + diagonal().summary()
|
|
1797
|
+
+ ", vertical: "s + vertical().summary()
|
|
1798
|
+
+ ", horizontal: "s + horizontal().summary();
|
|
1799
|
+
return "diagonalUp: "s + (diagonalUp() ? "true"s : "false"s)
|
|
1800
|
+
+ ", diagonalDown: "s + (diagonalDown() ? "true"s : "false"s)
|
|
1801
|
+
+ ", outline: "s + (outline() ? "true"s : "false"s)
|
|
1802
|
+
+ lineInfo;
|
|
1803
|
+
}
|
|
1804
|
+
|
|
1805
|
+
|
|
1806
|
+
// ===== XLBorders, parent of XLBorder
|
|
1807
|
+
|
|
1808
|
+
/**
|
|
1809
|
+
* @details Constructor. Initializes an empty XLBorders object
|
|
1810
|
+
*/
|
|
1811
|
+
XLBorders::XLBorders() : m_bordersNode(std::make_unique<XMLNode>()) {}
|
|
1812
|
+
|
|
1813
|
+
/**
|
|
1814
|
+
* @details Constructor. Initializes the member variables for the new XLBorders object.
|
|
1815
|
+
*/
|
|
1816
|
+
XLBorders::XLBorders(const XMLNode& borders)
|
|
1817
|
+
: m_bordersNode(std::make_unique<XMLNode>(borders))
|
|
1818
|
+
{
|
|
1819
|
+
// initialize XLBorders entries and m_borders here
|
|
1820
|
+
XMLNode node = borders.first_child_of_type(pugi::node_element);
|
|
1821
|
+
while (not node.empty()) {
|
|
1822
|
+
std::string nodeName = node.name();
|
|
1823
|
+
if (nodeName == "border")
|
|
1824
|
+
m_borders.push_back(XLBorder(node));
|
|
1825
|
+
else
|
|
1826
|
+
std::cerr << "WARNING: XLBorders constructor: unknown subnode " << nodeName << std::endl;
|
|
1827
|
+
node = node.next_sibling_of_type(pugi::node_element);
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1830
|
+
|
|
1831
|
+
/**
|
|
1832
|
+
* @details Copy constructor
|
|
1833
|
+
*/
|
|
1834
|
+
XLBorders::XLBorders(const XLBorders& other)
|
|
1835
|
+
: m_bordersNode(std::make_unique<XMLNode>(*other.m_bordersNode)),
|
|
1836
|
+
m_borders(other.m_borders)
|
|
1837
|
+
{}
|
|
1838
|
+
|
|
1839
|
+
/**
|
|
1840
|
+
* @details Move constructor
|
|
1841
|
+
*/
|
|
1842
|
+
XLBorders::XLBorders(XLBorders&& other)
|
|
1843
|
+
: m_bordersNode(std::move(other.m_bordersNode)),
|
|
1844
|
+
m_borders(std::move(other.m_borders))
|
|
1845
|
+
{}
|
|
1846
|
+
|
|
1847
|
+
/**
|
|
1848
|
+
* @details
|
|
1849
|
+
*/
|
|
1850
|
+
XLBorders::~XLBorders()
|
|
1851
|
+
{
|
|
1852
|
+
m_borders.clear(); // delete vector with all children
|
|
1853
|
+
}
|
|
1854
|
+
|
|
1855
|
+
/**
|
|
1856
|
+
* @details Copy assignment operator
|
|
1857
|
+
*/
|
|
1858
|
+
XLBorders& XLBorders::operator=(const XLBorders& other)
|
|
1859
|
+
{
|
|
1860
|
+
if (&other != this) {
|
|
1861
|
+
*m_bordersNode = *other.m_bordersNode;
|
|
1862
|
+
m_borders.clear();
|
|
1863
|
+
m_borders = other.m_borders;
|
|
1864
|
+
}
|
|
1865
|
+
return *this;
|
|
1866
|
+
}
|
|
1867
|
+
|
|
1868
|
+
/**
|
|
1869
|
+
* @details Move assignment operator
|
|
1870
|
+
*/
|
|
1871
|
+
XLBorders& XLBorders::operator=(XLBorders&& other) noexcept = default;
|
|
1872
|
+
|
|
1873
|
+
/**
|
|
1874
|
+
* @details Returns the amount of border descriptions held by the class
|
|
1875
|
+
*/
|
|
1876
|
+
size_t XLBorders::count() const { return m_borders.size(); }
|
|
1877
|
+
|
|
1878
|
+
/**
|
|
1879
|
+
* @details fetch XLBorder from m_borders by index
|
|
1880
|
+
*/
|
|
1881
|
+
XLBorder XLBorders::borderByIndex(XLStyleIndex index) const
|
|
1882
|
+
{
|
|
1883
|
+
if (index >= m_borders.size()) {
|
|
1884
|
+
using namespace std::literals::string_literals;
|
|
1885
|
+
throw XLException("XLBorders::"s + __func__ + ": attempted to access index "s + std::to_string(index) + " with count "s + std::to_string(m_borders.size()));
|
|
1886
|
+
}
|
|
1887
|
+
return m_borders.at(index);
|
|
1888
|
+
}
|
|
1889
|
+
|
|
1890
|
+
/**
|
|
1891
|
+
* @details append a new XLBorder to m_borders and m_bordersNode, based on copyFrom
|
|
1892
|
+
*/
|
|
1893
|
+
XLStyleIndex XLBorders::create(XLBorder copyFrom, std::string styleEntriesPrefix)
|
|
1894
|
+
{
|
|
1895
|
+
XLStyleIndex index = count(); // index for the border to be created
|
|
1896
|
+
XMLNode newNode{}; // scope declaration
|
|
1897
|
+
|
|
1898
|
+
// ===== Append new node prior to final whitespaces, if any
|
|
1899
|
+
XMLNode lastStyle = m_bordersNode->last_child_of_type(pugi::node_element);
|
|
1900
|
+
if (lastStyle.empty()) newNode = m_bordersNode->prepend_child("border");
|
|
1901
|
+
else newNode = m_bordersNode->insert_child_after("border", lastStyle);
|
|
1902
|
+
if (newNode.empty()) {
|
|
1903
|
+
using namespace std::literals::string_literals;
|
|
1904
|
+
throw XLException("XLBorders::"s + __func__ + ": failed to append a new border node"s);
|
|
1905
|
+
}
|
|
1906
|
+
if (styleEntriesPrefix.length() > 0) // if a whitespace prefix is configured
|
|
1907
|
+
m_bordersNode->insert_child_before(pugi::node_pcdata, newNode).set_value(styleEntriesPrefix.c_str()); // prefix the new node with styleEntriesPrefix
|
|
1908
|
+
|
|
1909
|
+
XLBorder newBorder(newNode);
|
|
1910
|
+
if (copyFrom.m_borderNode->empty()) { // if no template is given
|
|
1911
|
+
// ===== Create a border with default values
|
|
1912
|
+
// TODO: implement border defaults
|
|
1913
|
+
// newBorder.setProperty(defaultValue);
|
|
1914
|
+
// ...
|
|
1915
|
+
}
|
|
1916
|
+
else
|
|
1917
|
+
copyXMLNode(newNode, *copyFrom.m_borderNode); // will use copyFrom as template, does nothing if copyFrom is empty
|
|
1918
|
+
|
|
1919
|
+
m_borders.push_back(newBorder);
|
|
1920
|
+
appendAndSetAttribute(*m_bordersNode, "count", std::to_string(m_borders.size())); // update array count in XML
|
|
1921
|
+
return index;
|
|
1922
|
+
}
|
|
1923
|
+
|
|
1924
|
+
|
|
1925
|
+
/**
|
|
1926
|
+
* @details Constructor. Initializes an empty XLAlignment object
|
|
1927
|
+
*/
|
|
1928
|
+
XLAlignment::XLAlignment() : m_alignmentNode(std::make_unique<XMLNode>()) {}
|
|
1929
|
+
|
|
1930
|
+
/**
|
|
1931
|
+
* @details Constructor. Initializes the member variables for the new XLAlignment object.
|
|
1932
|
+
*/
|
|
1933
|
+
XLAlignment::XLAlignment(const XMLNode& node) : m_alignmentNode(std::make_unique<XMLNode>(node)) {}
|
|
1934
|
+
|
|
1935
|
+
/**
|
|
1936
|
+
* @details Copy constructor
|
|
1937
|
+
*/
|
|
1938
|
+
XLAlignment::XLAlignment(const XLAlignment& other)
|
|
1939
|
+
: m_alignmentNode(std::make_unique<XMLNode>(*other.m_alignmentNode))
|
|
1940
|
+
{}
|
|
1941
|
+
|
|
1942
|
+
/**
|
|
1943
|
+
* @details Move constructor
|
|
1944
|
+
*/
|
|
1945
|
+
XLAlignment::XLAlignment(XLAlignment&& other) noexcept = default;
|
|
1946
|
+
|
|
1947
|
+
/**
|
|
1948
|
+
* @details
|
|
1949
|
+
*/
|
|
1950
|
+
XLAlignment::~XLAlignment() = default;
|
|
1951
|
+
|
|
1952
|
+
/**
|
|
1953
|
+
* @details Copy assignment operator.
|
|
1954
|
+
*/
|
|
1955
|
+
XLAlignment& XLAlignment::operator=(const XLAlignment& other)
|
|
1956
|
+
{
|
|
1957
|
+
if (&other != this) *m_alignmentNode = *other.m_alignmentNode;
|
|
1958
|
+
return *this;
|
|
1959
|
+
}
|
|
1960
|
+
|
|
1961
|
+
/**
|
|
1962
|
+
* @details Move assignment operator.
|
|
1963
|
+
*/
|
|
1964
|
+
XLAlignment& XLAlignment::operator=(XLAlignment&& other) noexcept = default;
|
|
1965
|
+
|
|
1966
|
+
/**
|
|
1967
|
+
* @details Returns the horizontal alignment style
|
|
1968
|
+
*/
|
|
1969
|
+
XLAlignmentStyle XLAlignment::horizontal() const { return XLAlignmentStyleFromString(m_alignmentNode->attribute("horizontal").value()); }
|
|
1970
|
+
|
|
1971
|
+
/**
|
|
1972
|
+
* @details Returns the vertical alignment style
|
|
1973
|
+
*/
|
|
1974
|
+
XLAlignmentStyle XLAlignment::vertical() const { return XLAlignmentStyleFromString(m_alignmentNode->attribute("vertical").value()); }
|
|
1975
|
+
|
|
1976
|
+
/**
|
|
1977
|
+
* @details Returns the text rotation
|
|
1978
|
+
*/
|
|
1979
|
+
uint16_t XLAlignment::textRotation() const { return m_alignmentNode->attribute("textRotation").as_uint(); }
|
|
1980
|
+
|
|
1981
|
+
/**
|
|
1982
|
+
* @details check if text wrapping is enabled
|
|
1983
|
+
*/
|
|
1984
|
+
bool XLAlignment::wrapText() const { return m_alignmentNode->attribute("wrapText").as_bool(); }
|
|
1985
|
+
|
|
1986
|
+
/**
|
|
1987
|
+
* @details Returns the indent setting
|
|
1988
|
+
*/
|
|
1989
|
+
uint32_t XLAlignment::indent() const { return m_alignmentNode->attribute("indent").as_uint(); }
|
|
1990
|
+
|
|
1991
|
+
/**
|
|
1992
|
+
* @details Returns the relative indent setting
|
|
1993
|
+
*/
|
|
1994
|
+
int32_t XLAlignment::relativeIndent() const { return m_alignmentNode->attribute("relativeIndent").as_int(); }
|
|
1995
|
+
|
|
1996
|
+
/**
|
|
1997
|
+
* @details check if justification of last line is enabled
|
|
1998
|
+
*/
|
|
1999
|
+
bool XLAlignment::justifyLastLine() const { return m_alignmentNode->attribute("justifyLastLine").as_bool(); }
|
|
2000
|
+
|
|
2001
|
+
/**
|
|
2002
|
+
* @details check if shrink to fit is enabled
|
|
2003
|
+
*/
|
|
2004
|
+
bool XLAlignment::shrinkToFit() const { return m_alignmentNode->attribute("shrinkToFit").as_bool(); }
|
|
2005
|
+
|
|
2006
|
+
/**
|
|
2007
|
+
* @details Returns the reading order setting
|
|
2008
|
+
*/
|
|
2009
|
+
uint32_t XLAlignment::readingOrder() const { return m_alignmentNode->attribute("readingOrder").as_uint(); }
|
|
2010
|
+
|
|
2011
|
+
/**
|
|
2012
|
+
* @details Setter functions
|
|
2013
|
+
*/
|
|
2014
|
+
bool XLAlignment::setHorizontal (XLAlignmentStyle newStyle) { return appendAndSetAttribute(*m_alignmentNode, "horizontal", XLAlignmentStyleToString(newStyle).c_str()).empty() == false; }
|
|
2015
|
+
bool XLAlignment::setVertical (XLAlignmentStyle newStyle) { return appendAndSetAttribute(*m_alignmentNode, "vertical", XLAlignmentStyleToString(newStyle).c_str()).empty() == false; }
|
|
2016
|
+
bool XLAlignment::setTextRotation (uint16_t newRotation) { return appendAndSetAttribute(*m_alignmentNode, "textRotation", std::to_string(newRotation) ).empty() == false; }
|
|
2017
|
+
bool XLAlignment::setWrapText (bool set) { return appendAndSetAttribute(*m_alignmentNode, "wrapText", (set ? "true" : "false") ).empty() == false; }
|
|
2018
|
+
bool XLAlignment::setIndent (uint32_t newIndent) { return appendAndSetAttribute(*m_alignmentNode, "indent", std::to_string(newIndent) ).empty() == false; }
|
|
2019
|
+
bool XLAlignment::setRelativeIndent (int32_t newRelativeIndent) { return appendAndSetAttribute(*m_alignmentNode, "relativeIndent", std::to_string(newRelativeIndent) ).empty() == false; }
|
|
2020
|
+
bool XLAlignment::setJustifyLastLine(bool set) { return appendAndSetAttribute(*m_alignmentNode, "justifyLastLine", (set ? "true" : "false") ).empty() == false; }
|
|
2021
|
+
bool XLAlignment::setShrinkToFit (bool set) { return appendAndSetAttribute(*m_alignmentNode, "shrinkToFit", (set ? "true" : "false") ).empty() == false; }
|
|
2022
|
+
bool XLAlignment::setReadingOrder (uint32_t newReadingOrder) { return appendAndSetAttribute(*m_alignmentNode, "readingOrder", std::to_string(newReadingOrder) ).empty() == false; }
|
|
2023
|
+
|
|
2024
|
+
/**
|
|
2025
|
+
* @details assemble a string summary about the fill
|
|
2026
|
+
*/
|
|
2027
|
+
std::string XLAlignment::summary() const
|
|
2028
|
+
{
|
|
2029
|
+
using namespace std::literals::string_literals;
|
|
2030
|
+
return "alignment horizontal="s + XLAlignmentStyleToString(horizontal()) + ", vertical="s + XLAlignmentStyleToString(vertical())
|
|
2031
|
+
+ ", textRotation="s + std::to_string(textRotation())
|
|
2032
|
+
+ ", wrapText="s + (wrapText() ? "true" : "false")
|
|
2033
|
+
+ ", indent="s + std::to_string(indent())
|
|
2034
|
+
+ ", relativeIndent="s + std::to_string(relativeIndent())
|
|
2035
|
+
+ ", justifyLastLine="s + (justifyLastLine() ? "true" : "false")
|
|
2036
|
+
+ ", shrinkToFit="s + (shrinkToFit() ? "true" : "false")
|
|
2037
|
+
+ ", readingOrder="s + XLReadingOrderToString(readingOrder());
|
|
2038
|
+
}
|
|
2039
|
+
|
|
2040
|
+
|
|
2041
|
+
/**
|
|
2042
|
+
* @details Constructor. Initializes an empty XLCellFormat object
|
|
2043
|
+
*/
|
|
2044
|
+
XLCellFormat::XLCellFormat() : m_cellFormatNode(std::make_unique<XMLNode>()) {}
|
|
2045
|
+
|
|
2046
|
+
/**
|
|
2047
|
+
* @details Constructor. Initializes the member variables for the new XLCellFormat object.
|
|
2048
|
+
*/
|
|
2049
|
+
XLCellFormat::XLCellFormat(const XMLNode& node, bool permitXfId)
|
|
2050
|
+
: m_cellFormatNode(std::make_unique<XMLNode>(node)),
|
|
2051
|
+
m_permitXfId(permitXfId)
|
|
2052
|
+
{}
|
|
2053
|
+
|
|
2054
|
+
/**
|
|
2055
|
+
* @details Copy constructor
|
|
2056
|
+
*/
|
|
2057
|
+
XLCellFormat::XLCellFormat(const XLCellFormat& other)
|
|
2058
|
+
: m_cellFormatNode(std::make_unique<XMLNode>(*other.m_cellFormatNode)),
|
|
2059
|
+
m_permitXfId(other.m_permitXfId)
|
|
2060
|
+
{}
|
|
2061
|
+
|
|
2062
|
+
/**
|
|
2063
|
+
* @details Move constructor
|
|
2064
|
+
*/
|
|
2065
|
+
XLCellFormat::XLCellFormat(XLCellFormat&& other) noexcept = default;
|
|
2066
|
+
|
|
2067
|
+
/**
|
|
2068
|
+
* @details
|
|
2069
|
+
*/
|
|
2070
|
+
XLCellFormat::~XLCellFormat() = default;
|
|
2071
|
+
|
|
2072
|
+
/*
|
|
2073
|
+
* @details Copy assignment operator
|
|
2074
|
+
*/
|
|
2075
|
+
XLCellFormat& XLCellFormat::operator=(const XLCellFormat& other)
|
|
2076
|
+
{
|
|
2077
|
+
if (&other != this) {
|
|
2078
|
+
*m_cellFormatNode = *other.m_cellFormatNode;
|
|
2079
|
+
m_permitXfId = other.m_permitXfId;
|
|
2080
|
+
}
|
|
2081
|
+
return *this;
|
|
2082
|
+
}
|
|
2083
|
+
|
|
2084
|
+
/**
|
|
2085
|
+
* @details Move assignment operator
|
|
2086
|
+
*/
|
|
2087
|
+
XLCellFormat& XLCellFormat::operator=(XLCellFormat&& other) noexcept = default;
|
|
2088
|
+
|
|
2089
|
+
/**
|
|
2090
|
+
* @details determines the numberFormatId
|
|
2091
|
+
* @note returns XLInvalidUInt32 if attribute is not defined / set / empty
|
|
2092
|
+
*/
|
|
2093
|
+
uint32_t XLCellFormat::numberFormatId() const { return m_cellFormatNode->attribute("numFmtId").as_uint(XLInvalidUInt32); }
|
|
2094
|
+
|
|
2095
|
+
/**
|
|
2096
|
+
* @details determines the fontIndex
|
|
2097
|
+
* @note returns XLInvalidStyleIndex if attribute is not defined / set / empty
|
|
2098
|
+
*/
|
|
2099
|
+
XLStyleIndex XLCellFormat::fontIndex() const { return m_cellFormatNode->attribute("fontId").as_uint(XLInvalidStyleIndex); }
|
|
2100
|
+
|
|
2101
|
+
/**
|
|
2102
|
+
* @details determines the fillIndex
|
|
2103
|
+
* @note returns XLInvalidStyleIndex if attribute is not defined / set / empty
|
|
2104
|
+
*/
|
|
2105
|
+
XLStyleIndex XLCellFormat::fillIndex() const { return m_cellFormatNode->attribute("fillId").as_uint(XLInvalidStyleIndex); }
|
|
2106
|
+
|
|
2107
|
+
/**
|
|
2108
|
+
* @details determines the borderIndex
|
|
2109
|
+
* @note returns XLInvalidStyleIndex if attribute is not defined / set / empty
|
|
2110
|
+
*/
|
|
2111
|
+
XLStyleIndex XLCellFormat::borderIndex() const { return m_cellFormatNode->attribute("borderId").as_uint(XLInvalidStyleIndex); }
|
|
2112
|
+
|
|
2113
|
+
/**
|
|
2114
|
+
* @details Returns the xfId value
|
|
2115
|
+
*/
|
|
2116
|
+
XLStyleIndex XLCellFormat::xfId() const
|
|
2117
|
+
{
|
|
2118
|
+
if (m_permitXfId) return m_cellFormatNode->attribute("xfId").as_uint(XLInvalidStyleIndex);
|
|
2119
|
+
throw XLException("XLCellFormat::xfId not permitted when m_permitXfId is false");
|
|
2120
|
+
}
|
|
2121
|
+
|
|
2122
|
+
/**
|
|
2123
|
+
* @details determine the applyNumberFormat,applyFont,applyFill,applyBorder,applyAlignment,applyProtection status
|
|
2124
|
+
*/
|
|
2125
|
+
bool XLCellFormat::applyNumberFormat() const { return m_cellFormatNode->attribute("applyNumberFormat").as_bool(); }
|
|
2126
|
+
bool XLCellFormat::applyFont() const { return m_cellFormatNode->attribute("applyFont").as_bool(); }
|
|
2127
|
+
bool XLCellFormat::applyFill() const { return m_cellFormatNode->attribute("applyFill").as_bool(); }
|
|
2128
|
+
bool XLCellFormat::applyBorder() const { return m_cellFormatNode->attribute("applyBorder").as_bool(); }
|
|
2129
|
+
bool XLCellFormat::applyAlignment() const { return m_cellFormatNode->attribute("applyAlignment").as_bool(); }
|
|
2130
|
+
bool XLCellFormat::applyProtection() const { return m_cellFormatNode->attribute("applyProtection").as_bool(); }
|
|
2131
|
+
|
|
2132
|
+
/**
|
|
2133
|
+
* @details determine the quotePrefix, pivotButton status
|
|
2134
|
+
*/
|
|
2135
|
+
bool XLCellFormat::quotePrefix() const { return m_cellFormatNode->attribute("quotePrefix").as_bool(); }
|
|
2136
|
+
bool XLCellFormat::pivotButton() const { return m_cellFormatNode->attribute("pivotButton").as_bool(); }
|
|
2137
|
+
|
|
2138
|
+
/**
|
|
2139
|
+
* @details determine the protection:locked,protection:hidden status
|
|
2140
|
+
*/
|
|
2141
|
+
bool XLCellFormat::locked() const { return m_cellFormatNode->child("protection").attribute("locked").as_bool(); }
|
|
2142
|
+
bool XLCellFormat::hidden() const { return m_cellFormatNode->child("protection").attribute("hidden").as_bool(); }
|
|
2143
|
+
|
|
2144
|
+
/**
|
|
2145
|
+
* @details fetch alignment object
|
|
2146
|
+
*/
|
|
2147
|
+
XLAlignment XLCellFormat::alignment(bool createIfMissing) const
|
|
2148
|
+
{
|
|
2149
|
+
XMLNode nodeAlignment = m_cellFormatNode->child("alignment");
|
|
2150
|
+
if (nodeAlignment.empty() && createIfMissing)
|
|
2151
|
+
nodeAlignment = appendAndGetNode(*m_cellFormatNode, "alignment", m_nodeOrder); // 2024-12-19: ordered insert to address issue #305
|
|
2152
|
+
return XLAlignment(nodeAlignment);
|
|
2153
|
+
}
|
|
2154
|
+
|
|
2155
|
+
/**
|
|
2156
|
+
* @details Setter functions
|
|
2157
|
+
*/
|
|
2158
|
+
bool XLCellFormat::setNumberFormatId (uint32_t newNumFmtId) { return appendAndSetAttribute(*m_cellFormatNode, "numFmtId", std::to_string(newNumFmtId )).empty() == false; }
|
|
2159
|
+
bool XLCellFormat::setFontIndex (XLStyleIndex newXfIndex) { return appendAndSetAttribute(*m_cellFormatNode, "fontId", std::to_string(newXfIndex )).empty() == false; }
|
|
2160
|
+
bool XLCellFormat::setFillIndex (XLStyleIndex newFillIndex) { return appendAndSetAttribute(*m_cellFormatNode, "fillId", std::to_string(newFillIndex )).empty() == false; }
|
|
2161
|
+
bool XLCellFormat::setBorderIndex (XLStyleIndex newBorderIndex) { return appendAndSetAttribute(*m_cellFormatNode, "borderId", std::to_string(newBorderIndex)).empty() == false; }
|
|
2162
|
+
bool XLCellFormat::setXfId (XLStyleIndex newXfId)
|
|
2163
|
+
{
|
|
2164
|
+
if (m_permitXfId) return appendAndSetAttribute(*m_cellFormatNode, "xfId", std::to_string(newXfId )).empty() == false;
|
|
2165
|
+
throw XLException("XLCellFormat::setXfId not permitted when m_permitXfId is false");
|
|
2166
|
+
}
|
|
2167
|
+
bool XLCellFormat::setApplyNumberFormat(bool set) { return appendAndSetAttribute (*m_cellFormatNode, "applyNumberFormat", (set ? "true" : "false")).empty() == false; }
|
|
2168
|
+
bool XLCellFormat::setApplyFont (bool set) { return appendAndSetAttribute (*m_cellFormatNode, "applyFont", (set ? "true" : "false")).empty() == false; }
|
|
2169
|
+
bool XLCellFormat::setApplyFill (bool set) { return appendAndSetAttribute (*m_cellFormatNode, "applyFill", (set ? "true" : "false")).empty() == false; }
|
|
2170
|
+
bool XLCellFormat::setApplyBorder (bool set) { return appendAndSetAttribute (*m_cellFormatNode, "applyBorder", (set ? "true" : "false")).empty() == false; }
|
|
2171
|
+
bool XLCellFormat::setApplyAlignment (bool set) { return appendAndSetAttribute (*m_cellFormatNode, "applyAlignment", (set ? "true" : "false")).empty() == false; }
|
|
2172
|
+
bool XLCellFormat::setApplyProtection (bool set) { return appendAndSetAttribute (*m_cellFormatNode, "applyProtection", (set ? "true" : "false")).empty() == false; }
|
|
2173
|
+
bool XLCellFormat::setQuotePrefix (bool set) { return appendAndSetAttribute (*m_cellFormatNode, "quotePrefix", (set ? "true" : "false")).empty() == false; }
|
|
2174
|
+
bool XLCellFormat::setPivotButton (bool set) { return appendAndSetAttribute (*m_cellFormatNode, "pivotButton", (set ? "true" : "false")).empty() == false; }
|
|
2175
|
+
bool XLCellFormat::setLocked(bool set)
|
|
2176
|
+
{
|
|
2177
|
+
return appendAndSetNodeAttribute(*m_cellFormatNode, "protection", "locked", (set ? "true" : "false"),
|
|
2178
|
+
/**/ XLKeepAttributes, m_nodeOrder).empty() == false; // 2024-12-19: ordered insert to address issue #305
|
|
2179
|
+
}
|
|
2180
|
+
bool XLCellFormat::setHidden(bool set)
|
|
2181
|
+
{
|
|
2182
|
+
return appendAndSetNodeAttribute(*m_cellFormatNode, "protection", "hidden", (set ? "true" : "false"),
|
|
2183
|
+
/**/ XLKeepAttributes, m_nodeOrder).empty() == false; // 2024-12-19: ordered insert to address issue #305
|
|
2184
|
+
}
|
|
2185
|
+
|
|
2186
|
+
/**
|
|
2187
|
+
* @details Unsupported setter function
|
|
2188
|
+
*/
|
|
2189
|
+
bool XLCellFormat::setExtLst(XLUnsupportedElement const& newExtLst) { OpenXLSX::ignore(newExtLst); return false; }
|
|
2190
|
+
|
|
2191
|
+
|
|
2192
|
+
/**
|
|
2193
|
+
* @details assemble a string summary about the cell format
|
|
2194
|
+
*/
|
|
2195
|
+
std::string XLCellFormat::summary() const
|
|
2196
|
+
{
|
|
2197
|
+
using namespace std::literals::string_literals;
|
|
2198
|
+
return "numberFormatId="s + std::to_string(numberFormatId())
|
|
2199
|
+
+ ", fontIndex="s + std::to_string(fontIndex())
|
|
2200
|
+
+ ", fillIndex="s + std::to_string(fillIndex())
|
|
2201
|
+
+ ", borderIndex="s + std::to_string(borderIndex())
|
|
2202
|
+
+ ( m_permitXfId ? (", xfId: "s + std::to_string(xfId())) : ""s)
|
|
2203
|
+
+ ", applyNumberFormat: "s + (applyNumberFormat() ? "true"s : "false"s)
|
|
2204
|
+
+ ", applyFont: "s + (applyFont() ? "true"s : "false"s)
|
|
2205
|
+
+ ", applyFill: "s + (applyFill() ? "true"s : "false"s)
|
|
2206
|
+
+ ", applyBorder: "s + (applyBorder() ? "true"s : "false"s)
|
|
2207
|
+
+ ", applyAlignment: "s + (applyAlignment() ? "true"s : "false"s)
|
|
2208
|
+
+ ", applyProtection: "s + (applyProtection() ? "true"s : "false"s)
|
|
2209
|
+
+ ", quotePrefix: "s + (quotePrefix() ? "true"s : "false"s)
|
|
2210
|
+
+ ", pivotButton: "s + (pivotButton() ? "true"s : "false"s)
|
|
2211
|
+
+ ", locked: "s + (locked() ? "true"s : "false"s)
|
|
2212
|
+
+ ", hidden: "s + (hidden() ? "true"s : "false"s)
|
|
2213
|
+
+ ", " + alignment().summary();
|
|
2214
|
+
}
|
|
2215
|
+
|
|
2216
|
+
|
|
2217
|
+
// ===== XLCellFormats, one parent of XLCellFormat (the other being XLCellFormats)
|
|
2218
|
+
|
|
2219
|
+
/**
|
|
2220
|
+
* @details Constructor. Initializes an empty XLCellFormats object
|
|
2221
|
+
*/
|
|
2222
|
+
XLCellFormats::XLCellFormats() : m_cellFormatsNode(std::make_unique<XMLNode>()) {}
|
|
2223
|
+
|
|
2224
|
+
/**
|
|
2225
|
+
* @details Constructor. Initializes the member variables for the new XLCellFormats object.
|
|
2226
|
+
*/
|
|
2227
|
+
XLCellFormats::XLCellFormats(const XMLNode& cellStyleFormats, bool permitXfId)
|
|
2228
|
+
: m_cellFormatsNode(std::make_unique<XMLNode>(cellStyleFormats)),
|
|
2229
|
+
m_permitXfId(permitXfId)
|
|
2230
|
+
{
|
|
2231
|
+
// initialize XLCellFormats entries and m_cellFormats here
|
|
2232
|
+
XMLNode node = cellStyleFormats.first_child_of_type(pugi::node_element);
|
|
2233
|
+
while (not node.empty()) {
|
|
2234
|
+
std::string nodeName = node.name();
|
|
2235
|
+
if (nodeName == "xf")
|
|
2236
|
+
m_cellFormats.push_back(XLCellFormat(node, m_permitXfId));
|
|
2237
|
+
else
|
|
2238
|
+
std::cerr << "WARNING: XLCellFormats constructor: unknown subnode " << nodeName << std::endl;
|
|
2239
|
+
node = node.next_sibling_of_type(pugi::node_element);
|
|
2240
|
+
}
|
|
2241
|
+
}
|
|
2242
|
+
|
|
2243
|
+
/**
|
|
2244
|
+
* @details Copy constructor
|
|
2245
|
+
*/
|
|
2246
|
+
XLCellFormats::XLCellFormats(const XLCellFormats& other)
|
|
2247
|
+
: m_cellFormatsNode(std::make_unique<XMLNode>(*other.m_cellFormatsNode)),
|
|
2248
|
+
m_cellFormats(other.m_cellFormats),
|
|
2249
|
+
m_permitXfId(other.m_permitXfId)
|
|
2250
|
+
{}
|
|
2251
|
+
|
|
2252
|
+
/**
|
|
2253
|
+
* @details Move constructor
|
|
2254
|
+
*/
|
|
2255
|
+
XLCellFormats::XLCellFormats(XLCellFormats&& other)
|
|
2256
|
+
: m_cellFormatsNode(std::move(other.m_cellFormatsNode)),
|
|
2257
|
+
m_cellFormats(std::move(other.m_cellFormats)),
|
|
2258
|
+
m_permitXfId(other.m_permitXfId)
|
|
2259
|
+
{}
|
|
2260
|
+
|
|
2261
|
+
/**
|
|
2262
|
+
* @details
|
|
2263
|
+
*/
|
|
2264
|
+
XLCellFormats::~XLCellFormats()
|
|
2265
|
+
{
|
|
2266
|
+
m_cellFormats.clear(); // delete vector with all children
|
|
2267
|
+
}
|
|
2268
|
+
|
|
2269
|
+
/**
|
|
2270
|
+
* @details Copy assignment operator
|
|
2271
|
+
*/
|
|
2272
|
+
XLCellFormats& XLCellFormats::operator=(const XLCellFormats& other)
|
|
2273
|
+
{
|
|
2274
|
+
if (&other != this) {
|
|
2275
|
+
*m_cellFormatsNode = *other.m_cellFormatsNode;
|
|
2276
|
+
m_cellFormats.clear();
|
|
2277
|
+
m_cellFormats = other.m_cellFormats;
|
|
2278
|
+
m_permitXfId = other.m_permitXfId;
|
|
2279
|
+
}
|
|
2280
|
+
return *this;
|
|
2281
|
+
}
|
|
2282
|
+
|
|
2283
|
+
/**
|
|
2284
|
+
* @details Move assignment operator
|
|
2285
|
+
*/
|
|
2286
|
+
XLCellFormats& XLCellFormats::operator=(XLCellFormats&& other) noexcept = default;
|
|
2287
|
+
|
|
2288
|
+
/**
|
|
2289
|
+
* @details Returns the amount of cell format descriptions held by the class
|
|
2290
|
+
*/
|
|
2291
|
+
size_t XLCellFormats::count() const { return m_cellFormats.size(); }
|
|
2292
|
+
|
|
2293
|
+
/**
|
|
2294
|
+
* @details fetch XLCellFormat from m_cellFormats by index
|
|
2295
|
+
*/
|
|
2296
|
+
XLCellFormat XLCellFormats::cellFormatByIndex(XLStyleIndex index) const
|
|
2297
|
+
{
|
|
2298
|
+
if (index >= m_cellFormats.size()) {
|
|
2299
|
+
using namespace std::literals::string_literals;
|
|
2300
|
+
throw XLException("XLCellFormats::"s + __func__ + ": attempted to access index "s + std::to_string(index)
|
|
2301
|
+
+ " with count "s + std::to_string(m_cellFormats.size()));
|
|
2302
|
+
}
|
|
2303
|
+
return m_cellFormats.at(index);
|
|
2304
|
+
}
|
|
2305
|
+
|
|
2306
|
+
/**
|
|
2307
|
+
* @details append a new XLCellFormat to m_cellFormats and m_cellFormatsNode, based on copyFrom
|
|
2308
|
+
*/
|
|
2309
|
+
XLStyleIndex XLCellFormats::create(XLCellFormat copyFrom, std::string styleEntriesPrefix)
|
|
2310
|
+
{
|
|
2311
|
+
XLStyleIndex index = count(); // index for the cell format to be created
|
|
2312
|
+
XMLNode newNode{}; // scope declaration
|
|
2313
|
+
|
|
2314
|
+
// ===== Append new node prior to final whitespaces, if any
|
|
2315
|
+
XMLNode lastStyle = m_cellFormatsNode->last_child_of_type(pugi::node_element);
|
|
2316
|
+
if (lastStyle.empty()) newNode = m_cellFormatsNode->prepend_child("xf");
|
|
2317
|
+
else newNode = m_cellFormatsNode->insert_child_after("xf", lastStyle);
|
|
2318
|
+
if (newNode.empty()) {
|
|
2319
|
+
using namespace std::literals::string_literals;
|
|
2320
|
+
throw XLException("XLCellFormats::"s + __func__ + ": failed to append a new xf node"s);
|
|
2321
|
+
}
|
|
2322
|
+
if (styleEntriesPrefix.length() > 0) // if a whitespace prefix is configured
|
|
2323
|
+
m_cellFormatsNode->insert_child_before(pugi::node_pcdata, newNode).set_value(styleEntriesPrefix.c_str()); // prefix the new node with styleEntriesPrefix
|
|
2324
|
+
|
|
2325
|
+
XLCellFormat newCellFormat(newNode, m_permitXfId);
|
|
2326
|
+
if (copyFrom.m_cellFormatNode->empty()) { // if no template is given
|
|
2327
|
+
// ===== Create a cell format with default values
|
|
2328
|
+
// default index 0 for other style elements should protect from exceptions
|
|
2329
|
+
newCellFormat.setNumberFormatId (0);
|
|
2330
|
+
newCellFormat.setFontIndex (0);
|
|
2331
|
+
newCellFormat.setFillIndex (0);
|
|
2332
|
+
newCellFormat.setBorderIndex (0);
|
|
2333
|
+
newCellFormat.setXfId (0);
|
|
2334
|
+
newCellFormat.setApplyNumberFormat(false);
|
|
2335
|
+
newCellFormat.setApplyFont (false);
|
|
2336
|
+
newCellFormat.setApplyFill (false);
|
|
2337
|
+
newCellFormat.setApplyBorder (false);
|
|
2338
|
+
newCellFormat.setApplyAlignment (false);
|
|
2339
|
+
newCellFormat.setApplyProtection (false);
|
|
2340
|
+
newCellFormat.setQuotePrefix (false);
|
|
2341
|
+
newCellFormat.setPivotButton (false);
|
|
2342
|
+
newCellFormat.setLocked (false);
|
|
2343
|
+
newCellFormat.setHidden (false);
|
|
2344
|
+
// Unsupported setter
|
|
2345
|
+
newCellFormat.setExtLst (XLUnsupportedElement {});
|
|
2346
|
+
}
|
|
2347
|
+
else
|
|
2348
|
+
copyXMLNode(newNode, *copyFrom.m_cellFormatNode); // will use copyFrom as template, does nothing if copyFrom is empty
|
|
2349
|
+
|
|
2350
|
+
m_cellFormats.push_back(newCellFormat);
|
|
2351
|
+
appendAndSetAttribute(*m_cellFormatsNode, "count", std::to_string(m_cellFormats.size())); // update array count in XML
|
|
2352
|
+
return index;
|
|
2353
|
+
}
|
|
2354
|
+
|
|
2355
|
+
|
|
2356
|
+
/**
|
|
2357
|
+
* @details Constructor. Initializes an empty XLCellStyle object
|
|
2358
|
+
*/
|
|
2359
|
+
XLCellStyle::XLCellStyle() : m_cellStyleNode(std::make_unique<XMLNode>()) {}
|
|
2360
|
+
|
|
2361
|
+
/**
|
|
2362
|
+
* @details Constructor. Initializes the member variables for the new XLCellStyle object.
|
|
2363
|
+
*/
|
|
2364
|
+
XLCellStyle::XLCellStyle(const XMLNode& node) : m_cellStyleNode(std::make_unique<XMLNode>(node)) {}
|
|
2365
|
+
|
|
2366
|
+
/**
|
|
2367
|
+
* @details Copy constructor
|
|
2368
|
+
*/
|
|
2369
|
+
XLCellStyle::XLCellStyle(const XLCellStyle& other)
|
|
2370
|
+
: m_cellStyleNode(std::make_unique<XMLNode>(*other.m_cellStyleNode))
|
|
2371
|
+
{}
|
|
2372
|
+
|
|
2373
|
+
/**
|
|
2374
|
+
* @details Move constructor
|
|
2375
|
+
*/
|
|
2376
|
+
XLCellStyle::XLCellStyle(XLCellStyle&& other) noexcept = default;
|
|
2377
|
+
|
|
2378
|
+
/**
|
|
2379
|
+
* @details
|
|
2380
|
+
*/
|
|
2381
|
+
XLCellStyle::~XLCellStyle() = default;
|
|
2382
|
+
|
|
2383
|
+
/**
|
|
2384
|
+
* @details Copy assignment operator
|
|
2385
|
+
*/
|
|
2386
|
+
XLCellStyle& XLCellStyle::operator=(const XLCellStyle& other)
|
|
2387
|
+
{
|
|
2388
|
+
if (&other != this) *m_cellStyleNode = *other.m_cellStyleNode;
|
|
2389
|
+
return *this;
|
|
2390
|
+
}
|
|
2391
|
+
|
|
2392
|
+
/**
|
|
2393
|
+
* @details Move assignment operator
|
|
2394
|
+
*/
|
|
2395
|
+
XLCellStyle& XLCellStyle::operator=(XLCellStyle&& other) noexcept = default;
|
|
2396
|
+
|
|
2397
|
+
/**
|
|
2398
|
+
* @details Returns the style empty status
|
|
2399
|
+
*/
|
|
2400
|
+
bool XLCellStyle::empty() const { return m_cellStyleNode->empty(); }
|
|
2401
|
+
|
|
2402
|
+
/**
|
|
2403
|
+
* @details Getter functions
|
|
2404
|
+
*/
|
|
2405
|
+
std::string XLCellStyle::name () const { return m_cellStyleNode->attribute("name" ).value(); }
|
|
2406
|
+
XLStyleIndex XLCellStyle::xfId () const { return m_cellStyleNode->attribute("xfId" ).as_uint(XLInvalidStyleIndex); }
|
|
2407
|
+
uint32_t XLCellStyle::builtinId () const { return m_cellStyleNode->attribute("builtinId" ).as_uint(XLInvalidUInt32); }
|
|
2408
|
+
uint32_t XLCellStyle::outlineStyle () const { return m_cellStyleNode->attribute("iLevel" ).as_uint(XLInvalidUInt32); }
|
|
2409
|
+
bool XLCellStyle::hidden () const { return m_cellStyleNode->attribute("hidden" ).as_bool(); }
|
|
2410
|
+
bool XLCellStyle::customBuiltin() const { return m_cellStyleNode->attribute("customBuiltin").as_bool(); }
|
|
2411
|
+
|
|
2412
|
+
/**
|
|
2413
|
+
* @details Setter functions
|
|
2414
|
+
*/
|
|
2415
|
+
bool XLCellStyle::setName (std::string newName) { return appendAndSetAttribute(*m_cellStyleNode, "name", newName).empty() == false; }
|
|
2416
|
+
bool XLCellStyle::setXfId (XLStyleIndex newXfId) { return appendAndSetAttribute(*m_cellStyleNode, "xfId", std::to_string(newXfId)).empty() == false; }
|
|
2417
|
+
bool XLCellStyle::setBuiltinId (uint32_t newBuiltinId) { return appendAndSetAttribute(*m_cellStyleNode, "builtinId", std::to_string(newBuiltinId)).empty() == false; }
|
|
2418
|
+
bool XLCellStyle::setOutlineStyle (uint32_t newOutlineStyle) { return appendAndSetAttribute(*m_cellStyleNode, "iLevel", std::to_string(newOutlineStyle)).empty() == false; }
|
|
2419
|
+
bool XLCellStyle::setHidden (bool set) { return appendAndSetAttribute(*m_cellStyleNode, "hidden", (set ? "true" : "false")).empty() == false; }
|
|
2420
|
+
bool XLCellStyle::setCustomBuiltin(bool set) { return appendAndSetAttribute(*m_cellStyleNode, "customBuiltin", (set ? "true" : "false")).empty() == false; }
|
|
2421
|
+
|
|
2422
|
+
/**
|
|
2423
|
+
* @details Unsupported setter function
|
|
2424
|
+
*/
|
|
2425
|
+
bool XLCellStyle::setExtLst(XLUnsupportedElement const& newExtLst) { OpenXLSX::ignore(newExtLst); return false; }
|
|
2426
|
+
|
|
2427
|
+
/**
|
|
2428
|
+
* @details assemble a string summary about the cell style
|
|
2429
|
+
*/
|
|
2430
|
+
std::string XLCellStyle::summary() const
|
|
2431
|
+
{
|
|
2432
|
+
using namespace std::literals::string_literals;
|
|
2433
|
+
uint32_t iLevel = outlineStyle();
|
|
2434
|
+
return "name="s + name()
|
|
2435
|
+
+ ", xfId="s + std::to_string(xfId())
|
|
2436
|
+
+ ", builtinId="s + std::to_string(builtinId())
|
|
2437
|
+
+ (iLevel != XLInvalidUInt32 ? ", iLevel="s + std::to_string(outlineStyle()) : ""s)
|
|
2438
|
+
+ (hidden() ? ", hidden=true"s : ""s)
|
|
2439
|
+
+ (customBuiltin() ? ", customBuiltin=true"s : ""s);
|
|
2440
|
+
}
|
|
2441
|
+
|
|
2442
|
+
// ===== XLCellStyles, parent of XLCellStyle
|
|
2443
|
+
|
|
2444
|
+
/**
|
|
2445
|
+
* @details Constructor. Initializes an empty XLCellStyles object
|
|
2446
|
+
*/
|
|
2447
|
+
XLCellStyles::XLCellStyles() : m_cellStylesNode(std::make_unique<XMLNode>()) {}
|
|
2448
|
+
|
|
2449
|
+
/**
|
|
2450
|
+
* @details Constructor. Initializes the member variables for the new XLCellStyles object.
|
|
2451
|
+
*/
|
|
2452
|
+
XLCellStyles::XLCellStyles(const XMLNode& cellStyles)
|
|
2453
|
+
: m_cellStylesNode(std::make_unique<XMLNode>(cellStyles))
|
|
2454
|
+
{
|
|
2455
|
+
// initialize XLCellStyles entries and m_cellStyles here
|
|
2456
|
+
XMLNode node = cellStyles.first_child_of_type(pugi::node_element);
|
|
2457
|
+
while (not node.empty()) {
|
|
2458
|
+
std::string nodeName = node.name();
|
|
2459
|
+
if (nodeName == "cellStyle")
|
|
2460
|
+
m_cellStyles.push_back(XLCellStyle(node));
|
|
2461
|
+
else
|
|
2462
|
+
std::cerr << "WARNING: XLCellStyles constructor: unknown subnode " << nodeName << std::endl;
|
|
2463
|
+
node = node.next_sibling_of_type(pugi::node_element);
|
|
2464
|
+
}
|
|
2465
|
+
}
|
|
2466
|
+
|
|
2467
|
+
/**
|
|
2468
|
+
* @details Copy constructor
|
|
2469
|
+
*/
|
|
2470
|
+
XLCellStyles::XLCellStyles(const XLCellStyles& other)
|
|
2471
|
+
: m_cellStylesNode(std::make_unique<XMLNode>(*other.m_cellStylesNode)),
|
|
2472
|
+
m_cellStyles(other.m_cellStyles)
|
|
2473
|
+
{}
|
|
2474
|
+
|
|
2475
|
+
/**
|
|
2476
|
+
* @details Move constructor
|
|
2477
|
+
*/
|
|
2478
|
+
XLCellStyles::XLCellStyles(XLCellStyles&& other)
|
|
2479
|
+
: m_cellStylesNode(std::move(other.m_cellStylesNode)),
|
|
2480
|
+
m_cellStyles(std::move(other.m_cellStyles))
|
|
2481
|
+
{}
|
|
2482
|
+
|
|
2483
|
+
/**
|
|
2484
|
+
* @details
|
|
2485
|
+
*/
|
|
2486
|
+
XLCellStyles::~XLCellStyles()
|
|
2487
|
+
{
|
|
2488
|
+
m_cellStyles.clear(); // delete vector with all children
|
|
2489
|
+
}
|
|
2490
|
+
|
|
2491
|
+
/**
|
|
2492
|
+
* @details Copy assignment operator
|
|
2493
|
+
*/
|
|
2494
|
+
XLCellStyles& XLCellStyles::operator=(const XLCellStyles& other)
|
|
2495
|
+
{
|
|
2496
|
+
if (&other != this) {
|
|
2497
|
+
*m_cellStylesNode = *other.m_cellStylesNode;
|
|
2498
|
+
m_cellStyles.clear();
|
|
2499
|
+
m_cellStyles = other.m_cellStyles;
|
|
2500
|
+
}
|
|
2501
|
+
return *this;
|
|
2502
|
+
}
|
|
2503
|
+
|
|
2504
|
+
/**
|
|
2505
|
+
* @details Move assignment operator
|
|
2506
|
+
*/
|
|
2507
|
+
XLCellStyles& XLCellStyles::operator=(XLCellStyles&& other) noexcept = default;
|
|
2508
|
+
|
|
2509
|
+
/**
|
|
2510
|
+
* @details Returns the amount of numberFormats held by the class
|
|
2511
|
+
*/
|
|
2512
|
+
size_t XLCellStyles::count() const { return m_cellStyles.size(); }
|
|
2513
|
+
|
|
2514
|
+
/**
|
|
2515
|
+
* @details fetch XLCellStyle from m_cellStyles by index
|
|
2516
|
+
*/
|
|
2517
|
+
XLCellStyle XLCellStyles::cellStyleByIndex(XLStyleIndex index) const
|
|
2518
|
+
{
|
|
2519
|
+
if (index >= m_cellStyles.size()) {
|
|
2520
|
+
using namespace std::literals::string_literals;
|
|
2521
|
+
throw XLException("XLCellStyles::"s + __func__ + ": attempted to access index "s + std::to_string(index)
|
|
2522
|
+
+ " with count "s + std::to_string(m_cellStyles.size()));
|
|
2523
|
+
}
|
|
2524
|
+
return m_cellStyles.at(index);
|
|
2525
|
+
}
|
|
2526
|
+
|
|
2527
|
+
/**
|
|
2528
|
+
* @details append a new XLCellStyle to m_cellStyles and m_cellStyleNode, based on copyFrom
|
|
2529
|
+
*/
|
|
2530
|
+
XLStyleIndex XLCellStyles::create(XLCellStyle copyFrom, std::string styleEntriesPrefix)
|
|
2531
|
+
{
|
|
2532
|
+
XLStyleIndex index = count(); // index for the cell style to be created
|
|
2533
|
+
XMLNode newNode{}; // scope declaration
|
|
2534
|
+
|
|
2535
|
+
// ===== Append new node prior to final whitespaces, if any
|
|
2536
|
+
XMLNode lastStyle = m_cellStylesNode->last_child_of_type(pugi::node_element);
|
|
2537
|
+
if (lastStyle.empty()) newNode = m_cellStylesNode->prepend_child("cellStyle");
|
|
2538
|
+
else newNode = m_cellStylesNode->insert_child_after("cellStyle", lastStyle);
|
|
2539
|
+
if (newNode.empty()) {
|
|
2540
|
+
using namespace std::literals::string_literals;
|
|
2541
|
+
throw XLException("XLCellStyles::"s + __func__ + ": failed to append a new cellStyle node"s);
|
|
2542
|
+
}
|
|
2543
|
+
if (styleEntriesPrefix.length() > 0) // if a whitespace prefix is configured
|
|
2544
|
+
m_cellStylesNode->insert_child_before(pugi::node_pcdata, newNode).set_value(styleEntriesPrefix.c_str()); // prefix the new node with styleEntriesPrefix
|
|
2545
|
+
|
|
2546
|
+
XLCellStyle newCellStyle(newNode);
|
|
2547
|
+
if (copyFrom.m_cellStyleNode->empty()) { // if no template is given
|
|
2548
|
+
// ===== Create a cell style with default values
|
|
2549
|
+
// TODO: implement cell style defaults
|
|
2550
|
+
// newCellStyle.setProperty(defaultValue);
|
|
2551
|
+
// ...
|
|
2552
|
+
}
|
|
2553
|
+
else
|
|
2554
|
+
copyXMLNode(newNode, *copyFrom.m_cellStyleNode); // will use copyFrom as template, does nothing if copyFrom is empty
|
|
2555
|
+
|
|
2556
|
+
m_cellStyles.push_back(newCellStyle);
|
|
2557
|
+
appendAndSetAttribute(*m_cellStylesNode, "count", std::to_string(m_cellStyles.size())); // update array count in XML
|
|
2558
|
+
return index;
|
|
2559
|
+
}
|
|
2560
|
+
|
|
2561
|
+
|
|
2562
|
+
/**
|
|
2563
|
+
* @details Constructor. Initializes an empty XLDiffCellFormat object
|
|
2564
|
+
*/
|
|
2565
|
+
XLDiffCellFormat::XLDiffCellFormat() : m_diffCellFormatNode(std::make_unique<XMLNode>()) {}
|
|
2566
|
+
|
|
2567
|
+
/**
|
|
2568
|
+
* @details Constructor. Initializes the member variables for the new XLDiffCellFormat object.
|
|
2569
|
+
*/
|
|
2570
|
+
XLDiffCellFormat::XLDiffCellFormat(const XMLNode& node) : m_diffCellFormatNode(std::make_unique<XMLNode>(node)) {}
|
|
2571
|
+
|
|
2572
|
+
/**
|
|
2573
|
+
* @details Copy constructor
|
|
2574
|
+
*/
|
|
2575
|
+
XLDiffCellFormat::XLDiffCellFormat(const XLDiffCellFormat& other)
|
|
2576
|
+
: m_diffCellFormatNode(std::make_unique<XMLNode>(*other.m_diffCellFormatNode))
|
|
2577
|
+
{}
|
|
2578
|
+
|
|
2579
|
+
/**
|
|
2580
|
+
* @details Move constructor
|
|
2581
|
+
*/
|
|
2582
|
+
XLDiffCellFormat::XLDiffCellFormat(XLDiffCellFormat&& other) noexcept = default;
|
|
2583
|
+
|
|
2584
|
+
/**
|
|
2585
|
+
* @details
|
|
2586
|
+
*/
|
|
2587
|
+
XLDiffCellFormat::~XLDiffCellFormat() = default;
|
|
2588
|
+
|
|
2589
|
+
/**
|
|
2590
|
+
* @details Copy assignment operator
|
|
2591
|
+
*/
|
|
2592
|
+
XLDiffCellFormat& XLDiffCellFormat::operator=(const XLDiffCellFormat& other)
|
|
2593
|
+
{
|
|
2594
|
+
if (&other != this) *m_diffCellFormatNode = *other.m_diffCellFormatNode;
|
|
2595
|
+
return *this;
|
|
2596
|
+
}
|
|
2597
|
+
|
|
2598
|
+
/**
|
|
2599
|
+
* @details Move assignment operator
|
|
2600
|
+
*/
|
|
2601
|
+
XLDiffCellFormat& XLDiffCellFormat::operator=(XLDiffCellFormat&& other) noexcept = default;
|
|
2602
|
+
|
|
2603
|
+
|
|
2604
|
+
/**
|
|
2605
|
+
* @details Returns the differential cell format empty status
|
|
2606
|
+
*/
|
|
2607
|
+
bool XLDiffCellFormat::empty() const { return m_diffCellFormatNode->empty(); }
|
|
2608
|
+
|
|
2609
|
+
/**
|
|
2610
|
+
* @details Getter functions
|
|
2611
|
+
*/
|
|
2612
|
+
XLFont XLDiffCellFormat::font() const
|
|
2613
|
+
{
|
|
2614
|
+
XMLNode fontNode = appendAndGetNode(*m_diffCellFormatNode, "font");
|
|
2615
|
+
if (fontNode.empty()) return XLFont{};
|
|
2616
|
+
return XLFont(fontNode);
|
|
2617
|
+
}
|
|
2618
|
+
XLNumberFormat XLDiffCellFormat::numFmt() const
|
|
2619
|
+
{
|
|
2620
|
+
XMLNode numFmtNode = appendAndGetNode(*m_diffCellFormatNode, "numFmt");
|
|
2621
|
+
if (numFmtNode.empty()) return XLNumberFormat{};
|
|
2622
|
+
return XLNumberFormat(numFmtNode);
|
|
2623
|
+
}
|
|
2624
|
+
XLFill XLDiffCellFormat::fill() const
|
|
2625
|
+
{
|
|
2626
|
+
XMLNode fillNode = appendAndGetNode(*m_diffCellFormatNode, "fill");
|
|
2627
|
+
if (fillNode.empty()) return XLFill{};
|
|
2628
|
+
return XLFill(fillNode);
|
|
2629
|
+
}
|
|
2630
|
+
XLAlignment XLDiffCellFormat::alignment() const
|
|
2631
|
+
{
|
|
2632
|
+
XMLNode alignmentNode = appendAndGetNode(*m_diffCellFormatNode, "alignment");
|
|
2633
|
+
if (alignmentNode.empty()) return XLAlignment{};
|
|
2634
|
+
return XLAlignment(alignmentNode);
|
|
2635
|
+
}
|
|
2636
|
+
XLBorder XLDiffCellFormat::border() const
|
|
2637
|
+
{
|
|
2638
|
+
XMLNode borderNode = appendAndGetNode(*m_diffCellFormatNode, "border");
|
|
2639
|
+
if (borderNode.empty()) return XLBorder{};
|
|
2640
|
+
return XLBorder(borderNode);
|
|
2641
|
+
}
|
|
2642
|
+
|
|
2643
|
+
/**
|
|
2644
|
+
* @details Setter functions
|
|
2645
|
+
*/
|
|
2646
|
+
// bool XLDiffCellFormat::setName (std::string newName) { return appendAndSetAttribute(*m_diffCellFormatNode, "name", newName).empty() == false; }
|
|
2647
|
+
|
|
2648
|
+
/**
|
|
2649
|
+
* @details Unsupported setter function
|
|
2650
|
+
*/
|
|
2651
|
+
bool XLDiffCellFormat::setExtLst(XLUnsupportedElement const& newExtLst) { OpenXLSX::ignore(newExtLst); return false; }
|
|
2652
|
+
|
|
2653
|
+
/**
|
|
2654
|
+
* @details assemble a string summary about the differential cell format
|
|
2655
|
+
*/
|
|
2656
|
+
std::string XLDiffCellFormat::summary() const
|
|
2657
|
+
{
|
|
2658
|
+
using namespace std::literals::string_literals;
|
|
2659
|
+
return ""; // TODO: write this
|
|
2660
|
+
}
|
|
2661
|
+
|
|
2662
|
+
// ===== XLDiffCellFormats, parent of XLDiffCellFormat
|
|
2663
|
+
|
|
2664
|
+
/**
|
|
2665
|
+
* @details Constructor. Initializes an empty XLCellStyles object
|
|
2666
|
+
*/
|
|
2667
|
+
XLDiffCellFormats::XLDiffCellFormats() : m_diffCellFormatsNode(std::make_unique<XMLNode>()) {}
|
|
2668
|
+
|
|
2669
|
+
/**
|
|
2670
|
+
* @details Constructor. Initializes the member variables for the new XLCellStyles object.
|
|
2671
|
+
*/
|
|
2672
|
+
XLDiffCellFormats::XLDiffCellFormats(const XMLNode& diffCellFormats)
|
|
2673
|
+
: m_diffCellFormatsNode(std::make_unique<XMLNode>(diffCellFormats))
|
|
2674
|
+
{
|
|
2675
|
+
// initialize XLCellStyles entries and m_cellStyles here
|
|
2676
|
+
XMLNode node = m_diffCellFormatsNode->first_child_of_type(pugi::node_element);
|
|
2677
|
+
while (not node.empty()) {
|
|
2678
|
+
std::string nodeName = node.name();
|
|
2679
|
+
if (nodeName == "dxf")
|
|
2680
|
+
m_diffCellFormats.push_back(XLDiffCellFormat(node));
|
|
2681
|
+
else
|
|
2682
|
+
std::cerr << "WARNING: XLDiffCellFormats constructor: unknown subnode " << nodeName << std::endl;
|
|
2683
|
+
node = node.next_sibling_of_type(pugi::node_element);
|
|
2684
|
+
}
|
|
2685
|
+
}
|
|
2686
|
+
|
|
2687
|
+
/**
|
|
2688
|
+
* @details Copy constructor
|
|
2689
|
+
*/
|
|
2690
|
+
XLDiffCellFormats::XLDiffCellFormats(const XLDiffCellFormats& other)
|
|
2691
|
+
: m_diffCellFormatsNode(std::make_unique<XMLNode>(*other.m_diffCellFormatsNode)),
|
|
2692
|
+
m_diffCellFormats(other.m_diffCellFormats)
|
|
2693
|
+
{}
|
|
2694
|
+
|
|
2695
|
+
/**
|
|
2696
|
+
* @details Move constructor
|
|
2697
|
+
*/
|
|
2698
|
+
XLDiffCellFormats::XLDiffCellFormats(XLDiffCellFormats&& other)
|
|
2699
|
+
: m_diffCellFormatsNode(std::move(other.m_diffCellFormatsNode)),
|
|
2700
|
+
m_diffCellFormats(std::move(other.m_diffCellFormats))
|
|
2701
|
+
{}
|
|
2702
|
+
|
|
2703
|
+
/**
|
|
2704
|
+
* @details
|
|
2705
|
+
*/
|
|
2706
|
+
XLDiffCellFormats::~XLDiffCellFormats()
|
|
2707
|
+
{
|
|
2708
|
+
m_diffCellFormats.clear(); // delete vector with all children
|
|
2709
|
+
}
|
|
2710
|
+
|
|
2711
|
+
/**
|
|
2712
|
+
* @details Copy assignment operator
|
|
2713
|
+
*/
|
|
2714
|
+
XLDiffCellFormats& XLDiffCellFormats::operator=(const XLDiffCellFormats& other)
|
|
2715
|
+
{
|
|
2716
|
+
if (&other != this) {
|
|
2717
|
+
*m_diffCellFormatsNode = *other.m_diffCellFormatsNode;
|
|
2718
|
+
m_diffCellFormats.clear();
|
|
2719
|
+
m_diffCellFormats = other.m_diffCellFormats;
|
|
2720
|
+
}
|
|
2721
|
+
return *this;
|
|
2722
|
+
}
|
|
2723
|
+
|
|
2724
|
+
/**
|
|
2725
|
+
* @details Move assignment operator
|
|
2726
|
+
*/
|
|
2727
|
+
XLDiffCellFormats& XLDiffCellFormats::operator=(XLDiffCellFormats&& other) noexcept = default;
|
|
2728
|
+
|
|
2729
|
+
/**
|
|
2730
|
+
* @details Returns the amount of differential cell formats held by the class
|
|
2731
|
+
*/
|
|
2732
|
+
size_t XLDiffCellFormats::count() const { return m_diffCellFormats.size(); }
|
|
2733
|
+
|
|
2734
|
+
/**
|
|
2735
|
+
* @details fetch XLDiffCellFormat from m_diffCellFormats by index
|
|
2736
|
+
*/
|
|
2737
|
+
XLDiffCellFormat XLDiffCellFormats::diffCellFormatByIndex(XLStyleIndex index) const
|
|
2738
|
+
{
|
|
2739
|
+
if (index >= m_diffCellFormats.size()) {
|
|
2740
|
+
using namespace std::literals::string_literals;
|
|
2741
|
+
throw XLException("XLDiffCellFormats::"s + __func__ + ": attempted to access index "s + std::to_string(index)
|
|
2742
|
+
+ " with count "s + std::to_string(m_diffCellFormats.size()));
|
|
2743
|
+
}
|
|
2744
|
+
return m_diffCellFormats.at(index);
|
|
2745
|
+
}
|
|
2746
|
+
|
|
2747
|
+
/**
|
|
2748
|
+
* @details append a new XLDiffCellFormat to m_diffCellFormats and m_diffCellFormatsNode, based on copyFrom
|
|
2749
|
+
*/
|
|
2750
|
+
XLStyleIndex XLDiffCellFormats::create(XLDiffCellFormat copyFrom, std::string styleEntriesPrefix)
|
|
2751
|
+
{
|
|
2752
|
+
XLStyleIndex index = count(); // index for the cell style to be created
|
|
2753
|
+
XMLNode newNode{}; // scope declaration
|
|
2754
|
+
|
|
2755
|
+
// ===== Append new node prior to final whitespaces, if any
|
|
2756
|
+
XMLNode lastDiffCellFormat = m_diffCellFormatsNode->last_child_of_type(pugi::node_element);
|
|
2757
|
+
if (lastDiffCellFormat.empty()) newNode = m_diffCellFormatsNode->prepend_child("dxf");
|
|
2758
|
+
else newNode = m_diffCellFormatsNode->insert_child_after("dxf", lastDiffCellFormat);
|
|
2759
|
+
if (newNode.empty()) {
|
|
2760
|
+
using namespace std::literals::string_literals;
|
|
2761
|
+
throw XLException("XLDiffCellFormats::"s + __func__ + ": failed to append a new dxf node"s);
|
|
2762
|
+
}
|
|
2763
|
+
if (styleEntriesPrefix.length() > 0) // if a whitespace prefix is configured
|
|
2764
|
+
m_diffCellFormatsNode->insert_child_before(pugi::node_pcdata, newNode).set_value(styleEntriesPrefix.c_str()); // prefix the new node with styleEntriesPrefix
|
|
2765
|
+
|
|
2766
|
+
XLDiffCellFormat newDiffCellFormat(newNode);
|
|
2767
|
+
if (copyFrom.m_diffCellFormatNode->empty()) { // if no template is given
|
|
2768
|
+
// no-op: differential cell format entries have NO default values
|
|
2769
|
+
}
|
|
2770
|
+
else
|
|
2771
|
+
copyXMLNode(newNode, *copyFrom.m_diffCellFormatNode); // will use copyFrom as template, does nothing if copyFrom is empty
|
|
2772
|
+
|
|
2773
|
+
m_diffCellFormats.push_back(newDiffCellFormat);
|
|
2774
|
+
appendAndSetAttribute(*m_diffCellFormatsNode, "count", std::to_string(m_diffCellFormats.size())); // update array count in XML
|
|
2775
|
+
return index;
|
|
2776
|
+
}
|
|
2777
|
+
|
|
2778
|
+
|
|
2779
|
+
// ===== XLStyles, master class
|
|
2780
|
+
|
|
2781
|
+
/**
|
|
2782
|
+
* @details Default constructor
|
|
2783
|
+
*/
|
|
2784
|
+
XLStyles::XLStyles() {} // TBD if defaulting this constructor again would reintroduce issue #310
|
|
2785
|
+
|
|
2786
|
+
/**
|
|
2787
|
+
* @details Creates an XLStyles object, which will initialize from the given xmlData
|
|
2788
|
+
*/
|
|
2789
|
+
XLStyles::XLStyles(XLXmlData* xmlData, bool suppressWarnings, std::string stylesPrefix)
|
|
2790
|
+
: XLXmlFile(xmlData),
|
|
2791
|
+
m_suppressWarnings( suppressWarnings )
|
|
2792
|
+
{
|
|
2793
|
+
XMLDocument & doc = xmlDocument();
|
|
2794
|
+
if (doc.document_element().empty()) // handle a bad (no document element) xl/styles.xml
|
|
2795
|
+
doc.load_string(
|
|
2796
|
+
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
|
2797
|
+
"<styleSheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\">\n"
|
|
2798
|
+
"</styleSheet>",
|
|
2799
|
+
pugi_parse_settings
|
|
2800
|
+
);
|
|
2801
|
+
|
|
2802
|
+
XMLNode node = doc.document_element().first_child_of_type(pugi::node_element);
|
|
2803
|
+
while (not node.empty()) {
|
|
2804
|
+
XLStylesEntryType e = XLStylesEntryTypeFromString (node.name());
|
|
2805
|
+
// std::cout << "node.name() is " << node.name() << ", resulting XLStylesEntryType is " << std::to_string(e) << std::endl;
|
|
2806
|
+
switch (e) {
|
|
2807
|
+
case XLStylesNumberFormats:
|
|
2808
|
+
// std::cout << "found XLStylesNumberFormats, node name is " << node.name() << std::endl;
|
|
2809
|
+
m_numberFormats = std::make_unique<XLNumberFormats>(node);
|
|
2810
|
+
break;
|
|
2811
|
+
case XLStylesFonts:
|
|
2812
|
+
// std::cout << "found XLStylesFonts, node name is " << node.name() << std::endl;
|
|
2813
|
+
m_fonts = std::make_unique<XLFonts>(node);
|
|
2814
|
+
break;
|
|
2815
|
+
case XLStylesFills:
|
|
2816
|
+
// std::cout << "found XLStylesFills, node name is " << node.name() << std::endl;
|
|
2817
|
+
m_fills = std::make_unique<XLFills>(node);
|
|
2818
|
+
break;
|
|
2819
|
+
case XLStylesBorders:
|
|
2820
|
+
// std::cout << "found XLStylesBorders, node name is " << node.name() << std::endl;
|
|
2821
|
+
m_borders = std::make_unique<XLBorders>(node);
|
|
2822
|
+
break;
|
|
2823
|
+
case XLStylesCellStyleFormats:
|
|
2824
|
+
// std::cout << "found XLStylesCellStyleFormats, node name is " << node.name() << std::endl;
|
|
2825
|
+
m_cellStyleFormats = std::make_unique<XLCellFormats>(node);
|
|
2826
|
+
break;
|
|
2827
|
+
case XLStylesCellFormats:
|
|
2828
|
+
// std::cout << "found XLStylesCellFormats, node name is " << node.name() << std::endl;
|
|
2829
|
+
m_cellFormats = std::make_unique<XLCellFormats>(node, XLPermitXfID);
|
|
2830
|
+
break;
|
|
2831
|
+
case XLStylesCellStyles:
|
|
2832
|
+
// std::cout << "found XLStylesCellStyles, node name is " << node.name() << std::endl;
|
|
2833
|
+
m_cellStyles = std::make_unique<XLCellStyles>(node);
|
|
2834
|
+
break;
|
|
2835
|
+
case XLStylesDiffCellFormats:
|
|
2836
|
+
// std::cout << "found XLStylesDiffCellFormats, node name is " << node.name() << std::endl;
|
|
2837
|
+
m_diffCellFormats = std::make_unique<XLDiffCellFormats>(node);
|
|
2838
|
+
break;
|
|
2839
|
+
case XLStylesColors: [[fallthrough]];
|
|
2840
|
+
case XLStylesTableStyles: [[fallthrough]];
|
|
2841
|
+
case XLStylesExtLst:
|
|
2842
|
+
if( !m_suppressWarnings )
|
|
2843
|
+
std::cout << "XLStyles: Ignoring currently unsupported <" << XLStylesEntryTypeToString(e) + "> node" << std::endl;
|
|
2844
|
+
break;
|
|
2845
|
+
case XLStylesInvalid: [[fallthrough]];
|
|
2846
|
+
default:
|
|
2847
|
+
if( !m_suppressWarnings )
|
|
2848
|
+
std::cerr << "WARNING: XLStyles constructor: invalid styles subnode \"" << node.name() << "\"" << std::endl;
|
|
2849
|
+
break;
|
|
2850
|
+
}
|
|
2851
|
+
node = node.next_sibling_of_type(pugi::node_element);
|
|
2852
|
+
}
|
|
2853
|
+
|
|
2854
|
+
// ===== Fallbacks: create root style nodes (sorted insertions using m_nodeOrder)
|
|
2855
|
+
XMLNode docNode = doc.document_element(); // need an rvalue to pass as reference to appendAndGetNode
|
|
2856
|
+
if (!m_diffCellFormats) {
|
|
2857
|
+
node = appendAndGetNode(docNode, XLStylesEntryTypeToString(XLStylesDiffCellFormats).c_str(), m_nodeOrder );
|
|
2858
|
+
wrapNode (doc.document_element(), node, stylesPrefix);
|
|
2859
|
+
m_diffCellFormats = std::make_unique<XLDiffCellFormats>(node);
|
|
2860
|
+
}
|
|
2861
|
+
if (!m_cellStyles) {
|
|
2862
|
+
node = appendAndGetNode(docNode, XLStylesEntryTypeToString(XLStylesCellStyles).c_str(), m_nodeOrder );
|
|
2863
|
+
wrapNode (doc.document_element(), node, stylesPrefix);
|
|
2864
|
+
m_cellStyles = std::make_unique<XLCellStyles>(node);
|
|
2865
|
+
}
|
|
2866
|
+
if (!m_cellFormats) {
|
|
2867
|
+
node = appendAndGetNode(docNode, XLStylesEntryTypeToString(XLStylesCellFormats).c_str(), m_nodeOrder );
|
|
2868
|
+
wrapNode (doc.document_element(), node, stylesPrefix);
|
|
2869
|
+
m_cellFormats = std::make_unique<XLCellFormats>(node, XLPermitXfID);
|
|
2870
|
+
}
|
|
2871
|
+
if (m_cellFormats->count() == 0) { // if the cell formats array is empty
|
|
2872
|
+
// ===== Create a default empty cell format with ID 0 (== XLDefaultCellFormat) because when XLDefaultCellFormat
|
|
2873
|
+
// is assigned to an XLRow, the intention is interpreted as "set the cell back to default formatting",
|
|
2874
|
+
// which does not trigger setting the attribute customFormat="true".
|
|
2875
|
+
// To avoid confusing the user when the first style created does not work for rows, and setting a cell's
|
|
2876
|
+
// format back to XLDefaultCellFormat would cause an actual formatting (if assigned format ID 0), this
|
|
2877
|
+
// initial entry with no properties is created and henceforth ignored
|
|
2878
|
+
m_cellFormats->create();
|
|
2879
|
+
}
|
|
2880
|
+
|
|
2881
|
+
if (!m_cellStyleFormats) {
|
|
2882
|
+
node = appendAndGetNode(docNode, XLStylesEntryTypeToString(XLStylesCellStyleFormats).c_str(), m_nodeOrder );
|
|
2883
|
+
wrapNode (doc.document_element(), node, stylesPrefix);
|
|
2884
|
+
m_cellStyleFormats = std::make_unique<XLCellFormats>(node);
|
|
2885
|
+
}
|
|
2886
|
+
if (!m_borders) {
|
|
2887
|
+
node = appendAndGetNode(docNode, XLStylesEntryTypeToString(XLStylesBorders).c_str(), m_nodeOrder );
|
|
2888
|
+
wrapNode (doc.document_element(), node, stylesPrefix);
|
|
2889
|
+
m_borders = std::make_unique<XLBorders>(node);
|
|
2890
|
+
}
|
|
2891
|
+
if (!m_fills) {
|
|
2892
|
+
node = appendAndGetNode(docNode, XLStylesEntryTypeToString(XLStylesFills).c_str(), m_nodeOrder );
|
|
2893
|
+
wrapNode (doc.document_element(), node, stylesPrefix);
|
|
2894
|
+
m_fills = std::make_unique<XLFills>(node);
|
|
2895
|
+
}
|
|
2896
|
+
if (!m_fonts) {
|
|
2897
|
+
node = appendAndGetNode(docNode, XLStylesEntryTypeToString(XLStylesFonts).c_str(), m_nodeOrder );
|
|
2898
|
+
wrapNode (doc.document_element(), node, stylesPrefix);
|
|
2899
|
+
m_fonts = std::make_unique<XLFonts>(node);
|
|
2900
|
+
}
|
|
2901
|
+
if (!m_numberFormats) {
|
|
2902
|
+
node = appendAndGetNode(docNode, XLStylesEntryTypeToString(XLStylesNumberFormats).c_str(), m_nodeOrder );
|
|
2903
|
+
wrapNode (doc.document_element(), node, stylesPrefix);
|
|
2904
|
+
m_numberFormats = std::make_unique<XLNumberFormats>(node);
|
|
2905
|
+
}
|
|
2906
|
+
}
|
|
2907
|
+
|
|
2908
|
+
XLStyles::~XLStyles()
|
|
2909
|
+
{
|
|
2910
|
+
}
|
|
2911
|
+
|
|
2912
|
+
/**
|
|
2913
|
+
* @details move-construct an XLStyles object
|
|
2914
|
+
*/
|
|
2915
|
+
XLStyles::XLStyles(XLStyles&& other) noexcept
|
|
2916
|
+
: XLXmlFile(other),
|
|
2917
|
+
m_suppressWarnings(other.m_suppressWarnings),
|
|
2918
|
+
m_numberFormats (std::move(other.m_numberFormats) ),
|
|
2919
|
+
m_fonts (std::move(other.m_fonts) ),
|
|
2920
|
+
m_fills (std::move(other.m_fills) ),
|
|
2921
|
+
m_borders (std::move(other.m_borders) ),
|
|
2922
|
+
m_cellStyleFormats(std::move(other.m_cellStyleFormats)),
|
|
2923
|
+
m_cellFormats (std::move(other.m_cellFormats) ),
|
|
2924
|
+
m_cellStyles (std::move(other.m_cellStyles) ),
|
|
2925
|
+
m_diffCellFormats (std::move(other.m_diffCellFormats) )
|
|
2926
|
+
{}
|
|
2927
|
+
|
|
2928
|
+
/**
|
|
2929
|
+
* @details copy-construct an XLStyles object
|
|
2930
|
+
*/
|
|
2931
|
+
XLStyles::XLStyles(const XLStyles& other)
|
|
2932
|
+
: XLXmlFile(other),
|
|
2933
|
+
m_suppressWarnings(other.m_suppressWarnings),
|
|
2934
|
+
m_numberFormats (std::make_unique<XLNumberFormats >(*other.m_numberFormats) ),
|
|
2935
|
+
m_fonts (std::make_unique<XLFonts >(*other.m_fonts) ),
|
|
2936
|
+
m_fills (std::make_unique<XLFills >(*other.m_fills) ),
|
|
2937
|
+
m_borders (std::make_unique<XLBorders >(*other.m_borders) ),
|
|
2938
|
+
m_cellStyleFormats(std::make_unique<XLCellFormats >(*other.m_cellStyleFormats)),
|
|
2939
|
+
m_cellFormats (std::make_unique<XLCellFormats >(*other.m_cellFormats) ),
|
|
2940
|
+
m_cellStyles (std::make_unique<XLCellStyles >(*other.m_cellStyles) ),
|
|
2941
|
+
m_diffCellFormats (std::make_unique<XLDiffCellFormats>(*other.m_diffCellFormats) )
|
|
2942
|
+
{}
|
|
2943
|
+
|
|
2944
|
+
/**
|
|
2945
|
+
* @details move-assign an XLStyles object
|
|
2946
|
+
*/
|
|
2947
|
+
XLStyles& XLStyles::operator=(XLStyles&& other) noexcept
|
|
2948
|
+
{
|
|
2949
|
+
if (&other != this) {
|
|
2950
|
+
XLXmlFile::operator=(std::move(other));
|
|
2951
|
+
m_suppressWarnings = other.m_suppressWarnings;
|
|
2952
|
+
m_numberFormats = std::move(other.m_numberFormats );
|
|
2953
|
+
m_fonts = std::move(other.m_fonts );
|
|
2954
|
+
m_fills = std::move(other.m_fills );
|
|
2955
|
+
m_borders = std::move(other.m_borders );
|
|
2956
|
+
m_cellStyleFormats = std::move(other.m_cellStyleFormats);
|
|
2957
|
+
m_cellFormats = std::move(other.m_cellFormats );
|
|
2958
|
+
m_cellStyles = std::move(other.m_cellStyles );
|
|
2959
|
+
m_diffCellFormats = std::move(other.m_diffCellFormats );
|
|
2960
|
+
}
|
|
2961
|
+
return *this;
|
|
2962
|
+
}
|
|
2963
|
+
|
|
2964
|
+
/**
|
|
2965
|
+
* @details copy-assign an XLStyles object
|
|
2966
|
+
*/
|
|
2967
|
+
XLStyles& XLStyles::operator=(const XLStyles& other)
|
|
2968
|
+
{
|
|
2969
|
+
if (&other != this) {
|
|
2970
|
+
XLStyles temp = other; // copy-construct
|
|
2971
|
+
*this = std::move(temp); // move-assign & invalidate temp
|
|
2972
|
+
}
|
|
2973
|
+
return *this;
|
|
2974
|
+
}
|
|
2975
|
+
|
|
2976
|
+
/**
|
|
2977
|
+
* @details return a handle to the underlying number formats
|
|
2978
|
+
*/
|
|
2979
|
+
XLNumberFormats& XLStyles::numberFormats() const { return *m_numberFormats; }
|
|
2980
|
+
|
|
2981
|
+
/**
|
|
2982
|
+
* @details return a handle to the underlying fonts
|
|
2983
|
+
*/
|
|
2984
|
+
XLFonts& XLStyles::fonts() const { return *m_fonts; }
|
|
2985
|
+
|
|
2986
|
+
/**
|
|
2987
|
+
* @details return a handle to the underlying fills
|
|
2988
|
+
*/
|
|
2989
|
+
XLFills& XLStyles::fills() const { return *m_fills; }
|
|
2990
|
+
|
|
2991
|
+
/**
|
|
2992
|
+
* @details return a handle to the underlying borders
|
|
2993
|
+
*/
|
|
2994
|
+
XLBorders& XLStyles::borders() const { return *m_borders; }
|
|
2995
|
+
|
|
2996
|
+
/**
|
|
2997
|
+
* @details return a handle to the underlying cell style formats
|
|
2998
|
+
*/
|
|
2999
|
+
XLCellFormats& XLStyles::cellStyleFormats() const { return *m_cellStyleFormats; }
|
|
3000
|
+
|
|
3001
|
+
/**
|
|
3002
|
+
* @details return a handle to the underlying cell formats
|
|
3003
|
+
*/
|
|
3004
|
+
XLCellFormats& XLStyles::cellFormats() const { return *m_cellFormats; }
|
|
3005
|
+
|
|
3006
|
+
/**
|
|
3007
|
+
* @details return a handle to the underlying cell styles
|
|
3008
|
+
*/
|
|
3009
|
+
XLCellStyles& XLStyles::cellStyles() const { return *m_cellStyles; }
|
|
3010
|
+
|
|
3011
|
+
/**
|
|
3012
|
+
* @details return a handle to the underlying differential cell formats
|
|
3013
|
+
*/
|
|
3014
|
+
XLDiffCellFormats& XLStyles::diffCellFormats() const { return *m_diffCellFormats; }
|