├── .gitattributes ├── docs ├── advanced │ ├── Views.md │ ├── Printing.md │ ├── Encryption.md │ ├── README.md │ ├── Formatting.md │ └── Properties.md ├── basics │ ├── Iteration.md │ ├── README.md │ ├── Cell.md │ ├── Workbook.md │ ├── Worksheet.md │ └── MemoryModel.md ├── introduction │ ├── Motivation.md │ └── README.md ├── template.ejs └── README.md ├── samples ├── disabled │ ├── image.cpp │ ├── copy_style.cpp │ ├── page_setup.cpp │ ├── add_comments.cpp │ ├── comment_error.cpp │ ├── default_styles.cpp │ ├── group_columns.cpp │ ├── header_footer.cpp │ ├── merge_unmerge.cpp │ ├── parse_formulae.cpp │ ├── print_options.cpp │ ├── using_formulae.cpp │ ├── validate_cells.cpp │ ├── font_rgb_colors.cpp │ ├── row_column_style.cpp │ ├── font_legacy_colors.cpp │ ├── style_application.cpp │ ├── style_side_effects.cpp │ ├── using_number_formats.cpp │ ├── worksheet_properties.cpp │ ├── basic_conditional_formatting.cpp │ ├── create.cpp │ ├── read.cpp │ └── write.cpp ├── data │ ├── cafe.jpg │ ├── penguin.jpg │ ├── sample1.xlsx │ ├── encrypted.xlsx │ └── documentation-print.xlsx ├── decrypt.cpp └── CMakeLists.txt ├── logo └── logo.png ├── .gitbook.yaml ├── tests ├── data │ ├── 17_xlsm.xlsm │ ├── 14_images.xlsx │ ├── 2_minimal.xlsx │ ├── 3_default.xlsx │ ├── 15_phonetics.xlsx │ ├── 18_formulae.xlsx │ ├── 4_every_style.xlsx │ ├── 16_hidden_sheet.xlsx │ ├── 20_active_sheet.xlsx │ ├── 9_unicode_Λ_😇.xlsx │ ├── 11_print_settings.xlsx │ ├── 19_defined_names.xlsx │ ├── 5_encrypted_agile.xlsx │ ├── 6_encrypted_libre.xlsx │ ├── Issue492_empty_row.xlsx │ ├── excel_test_sheet.xlsx │ ├── 7_encrypted_standard.xlsx │ ├── 8_encrypted_numbers.xlsx │ ├── Issue445_inline_str.xlsx │ ├── Issue735_wrong_count.xlsx │ ├── 12_advanced_properties.xlsx │ ├── Issue494_shared_string.xlsx │ ├── Issue503_external_link.xlsx │ ├── Issue714_locale_comma.xlsx │ ├── issue90_debug_test_file.xlsx │ ├── 13_custom_heights_widths.xlsx │ ├── 1_powerpoint_presentation.xlsx │ ├── 10_comments_hyperlinks_formulae.xlsx │ ├── Issue279_workbook_delete_rename.xlsx │ ├── issue109_noncompliant_relations.xlsx │ ├── Issue6_google_missing_workbookView.xlsx │ ├── Issue353_first_row_empty_w_properties.xlsx │ └── Issue18_defined_name_with_workbook_scope.xlsx ├── helpers │ ├── temporary_file.hpp │ ├── test_suite.hpp │ ├── temporary_directory.hpp │ ├── test_suite.cpp │ └── timing.hpp ├── styles │ ├── alignment_test_suite.cpp │ ├── protection_test_suite.cpp │ ├── conditional_format_test_suite.cpp │ ├── style_test_suite.cpp │ └── color_test_suite.cpp ├── runner.cpp ├── drawing │ └── drawing_test_suite.cpp ├── worksheet │ └── page_setup_test_suite.cpp ├── internal │ └── locale_helpers.hpp └── utils │ └── path_test_suite.cpp ├── benchmarks ├── data │ ├── large.xlsx │ └── very_large.xlsx ├── disabled │ ├── bufzip.cpp │ ├── speed.cpp │ ├── memory.cpp │ └── reader.cpp ├── spreadsheet-load.cpp ├── microbenchmarks │ └── CMakeLists.txt └── CMakeLists.txt ├── book.json ├── CHANGELOG.md ├── cmake ├── pkg-config.pc.cmake ├── XlntConfig.cmake.in └── cmake_uninstall.cmake.in ├── .circleci ├── config_pr.yml ├── gcc7_cmake3.9.5_doxygen.Dockerfile ├── config.yml ├── gcc7_cmake3.2.Dockerfile ├── gcc7_cmake3.9.5.Dockerfile ├── gcc_cmake_latest.Dockerfile ├── post_coverage_comment.sh └── setup.sh ├── ubsan.supp ├── .gitignore ├── AUTHORS.md ├── .release-it.json ├── source ├── packaging │ ├── uri.cpp │ └── relationship.cpp ├── detail │ ├── implementations │ │ ├── formatting_record.hpp │ │ ├── conditional_format_impl.hpp │ │ ├── hyperlink_impl.hpp │ │ └── style_impl.hpp │ ├── serialization │ │ ├── serialisation_helpers.cpp │ │ ├── defined_name.hpp │ │ └── open_stream.hpp │ ├── xlnt_config_impl.hpp │ ├── default_case.hpp │ ├── cryptography │ │ ├── base64.hpp │ │ ├── sha.hpp │ │ ├── cipher.hpp │ │ ├── hash.hpp │ │ ├── xlsx_crypto_consumer.hpp │ │ ├── xlsx_crypto_producer.hpp │ │ ├── hash.cpp │ │ └── aes.hpp │ ├── header_footer │ │ └── header_footer_code.hpp │ ├── external │ │ ├── include_windows.hpp │ │ └── include_libstudxml.hpp │ ├── utils │ │ └── string_helpers.cpp │ ├── limits.hpp │ └── unicode.hpp ├── cell │ ├── rich_text_run.cpp │ ├── phonetic_run.cpp │ └── comment.cpp ├── worksheet │ ├── selection.cpp │ ├── sheet_protection.cpp │ └── page_margins.cpp └── styles │ └── protection.cpp ├── .gitmodules ├── package.json ├── .appveyor.yml ├── third-party ├── miniz │ └── LICENSE └── libstudxml.build │ └── CMakeLists.txt ├── python └── CMakeLists.txt ├── include └── xlnt │ ├── worksheet │ ├── major_order.hpp │ ├── sheet_protection.hpp │ ├── sheet_format_properties.hpp │ ├── print_options.hpp │ └── column_properties.hpp │ ├── xlnt_config.hpp │ ├── workbook │ ├── external_book.hpp │ ├── theme.hpp │ ├── calculation_properties.hpp │ └── metadata_property.hpp │ ├── utils │ ├── calendar.hpp │ ├── hash_combine.hpp │ ├── scoped_enum_hash.hpp │ └── timedelta.hpp │ ├── cell │ ├── phonetic_run.hpp │ ├── rich_text_run.hpp │ ├── cell_type.hpp │ └── hyperlink.hpp │ ├── drawing │ └── spreadsheet_drawing.hpp │ ├── internal │ └── format_impl_ptr.hpp │ └── packaging │ └── ext_list.hpp ├── .clang-format ├── CONTRIBUTING.md └── CODE_OF_CONDUCT.md /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto -------------------------------------------------------------------------------- /docs/advanced/Views.md: -------------------------------------------------------------------------------- 1 | ## Views 2 | -------------------------------------------------------------------------------- /samples/disabled/image.cpp: -------------------------------------------------------------------------------- 1 | image.cpp -------------------------------------------------------------------------------- /docs/advanced/Printing.md: -------------------------------------------------------------------------------- 1 | ## Printing 2 | -------------------------------------------------------------------------------- /docs/basics/Iteration.md: -------------------------------------------------------------------------------- 1 | ## Iteration 2 | -------------------------------------------------------------------------------- /docs/advanced/Encryption.md: -------------------------------------------------------------------------------- 1 | ## Encryption 2 | -------------------------------------------------------------------------------- /samples/disabled/copy_style.cpp: -------------------------------------------------------------------------------- 1 | copy_style.cpp -------------------------------------------------------------------------------- /samples/disabled/page_setup.cpp: -------------------------------------------------------------------------------- 1 | page_setup.cpp -------------------------------------------------------------------------------- /docs/introduction/Motivation.md: -------------------------------------------------------------------------------- 1 | ## Motivation 2 | -------------------------------------------------------------------------------- /samples/disabled/add_comments.cpp: -------------------------------------------------------------------------------- 1 | add_comments.cpp -------------------------------------------------------------------------------- /samples/disabled/comment_error.cpp: -------------------------------------------------------------------------------- 1 | comment_error.cpp -------------------------------------------------------------------------------- /samples/disabled/default_styles.cpp: -------------------------------------------------------------------------------- 1 | default_styles.cpp -------------------------------------------------------------------------------- /samples/disabled/group_columns.cpp: -------------------------------------------------------------------------------- 1 | group_columns.cpp -------------------------------------------------------------------------------- /samples/disabled/header_footer.cpp: -------------------------------------------------------------------------------- 1 | header_footer.cpp -------------------------------------------------------------------------------- /samples/disabled/merge_unmerge.cpp: -------------------------------------------------------------------------------- 1 | merge_unmerge.cpp -------------------------------------------------------------------------------- /samples/disabled/parse_formulae.cpp: -------------------------------------------------------------------------------- 1 | parse_formulae.cpp -------------------------------------------------------------------------------- /samples/disabled/print_options.cpp: -------------------------------------------------------------------------------- 1 | print_options.cpp -------------------------------------------------------------------------------- /samples/disabled/using_formulae.cpp: -------------------------------------------------------------------------------- 1 | using_formulae.cpp -------------------------------------------------------------------------------- /samples/disabled/validate_cells.cpp: -------------------------------------------------------------------------------- 1 | validate_cells.cpp -------------------------------------------------------------------------------- /samples/disabled/font_rgb_colors.cpp: -------------------------------------------------------------------------------- 1 | font_rgb_colors.cpp -------------------------------------------------------------------------------- /samples/disabled/row_column_style.cpp: -------------------------------------------------------------------------------- 1 | row_column_style.cpp -------------------------------------------------------------------------------- /samples/disabled/font_legacy_colors.cpp: -------------------------------------------------------------------------------- 1 | font_legacy_colors.cpp -------------------------------------------------------------------------------- /samples/disabled/style_application.cpp: -------------------------------------------------------------------------------- 1 | style_application.cpp -------------------------------------------------------------------------------- /samples/disabled/style_side_effects.cpp: -------------------------------------------------------------------------------- 1 | style_side_effects.cpp -------------------------------------------------------------------------------- /samples/disabled/using_number_formats.cpp: -------------------------------------------------------------------------------- 1 | using_number_formats.cpp -------------------------------------------------------------------------------- /samples/disabled/worksheet_properties.cpp: -------------------------------------------------------------------------------- 1 | worksheet_properties.cpp -------------------------------------------------------------------------------- /logo/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/logo/logo.png -------------------------------------------------------------------------------- /samples/disabled/basic_conditional_formatting.cpp: -------------------------------------------------------------------------------- 1 | basic_conditional_formatting.cpp -------------------------------------------------------------------------------- /samples/data/cafe.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/samples/data/cafe.jpg -------------------------------------------------------------------------------- /.gitbook.yaml: -------------------------------------------------------------------------------- 1 | root: ./ 2 | 3 | structure: 4 | readme: README.md 5 | summary: docs/README.md 6 | -------------------------------------------------------------------------------- /samples/data/penguin.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/samples/data/penguin.jpg -------------------------------------------------------------------------------- /tests/data/17_xlsm.xlsm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/tests/data/17_xlsm.xlsm -------------------------------------------------------------------------------- /benchmarks/data/large.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/benchmarks/data/large.xlsx -------------------------------------------------------------------------------- /samples/data/sample1.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/samples/data/sample1.xlsx -------------------------------------------------------------------------------- /tests/data/14_images.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/tests/data/14_images.xlsx -------------------------------------------------------------------------------- /tests/data/2_minimal.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/tests/data/2_minimal.xlsx -------------------------------------------------------------------------------- /tests/data/3_default.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/tests/data/3_default.xlsx -------------------------------------------------------------------------------- /docs/template.ejs: -------------------------------------------------------------------------------- 1 | <% for(var i = 0; i < summary.length; i++) {%> 2 | <%- summary[i].content %> 3 | <% } %> 4 | -------------------------------------------------------------------------------- /samples/data/encrypted.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/samples/data/encrypted.xlsx -------------------------------------------------------------------------------- /tests/data/15_phonetics.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/tests/data/15_phonetics.xlsx -------------------------------------------------------------------------------- /tests/data/18_formulae.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/tests/data/18_formulae.xlsx -------------------------------------------------------------------------------- /tests/data/4_every_style.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/tests/data/4_every_style.xlsx -------------------------------------------------------------------------------- /benchmarks/data/very_large.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/benchmarks/data/very_large.xlsx -------------------------------------------------------------------------------- /tests/data/16_hidden_sheet.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/tests/data/16_hidden_sheet.xlsx -------------------------------------------------------------------------------- /tests/data/20_active_sheet.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/tests/data/20_active_sheet.xlsx -------------------------------------------------------------------------------- /tests/data/9_unicode_Λ_😇.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/tests/data/9_unicode_Λ_😇.xlsx -------------------------------------------------------------------------------- /tests/data/11_print_settings.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/tests/data/11_print_settings.xlsx -------------------------------------------------------------------------------- /tests/data/19_defined_names.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/tests/data/19_defined_names.xlsx -------------------------------------------------------------------------------- /tests/data/5_encrypted_agile.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/tests/data/5_encrypted_agile.xlsx -------------------------------------------------------------------------------- /tests/data/6_encrypted_libre.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/tests/data/6_encrypted_libre.xlsx -------------------------------------------------------------------------------- /tests/data/Issue492_empty_row.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/tests/data/Issue492_empty_row.xlsx -------------------------------------------------------------------------------- /tests/data/excel_test_sheet.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/tests/data/excel_test_sheet.xlsx -------------------------------------------------------------------------------- /tests/data/7_encrypted_standard.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/tests/data/7_encrypted_standard.xlsx -------------------------------------------------------------------------------- /tests/data/8_encrypted_numbers.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/tests/data/8_encrypted_numbers.xlsx -------------------------------------------------------------------------------- /tests/data/Issue445_inline_str.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/tests/data/Issue445_inline_str.xlsx -------------------------------------------------------------------------------- /tests/data/Issue735_wrong_count.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/tests/data/Issue735_wrong_count.xlsx -------------------------------------------------------------------------------- /samples/data/documentation-print.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/samples/data/documentation-print.xlsx -------------------------------------------------------------------------------- /tests/data/12_advanced_properties.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/tests/data/12_advanced_properties.xlsx -------------------------------------------------------------------------------- /tests/data/Issue494_shared_string.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/tests/data/Issue494_shared_string.xlsx -------------------------------------------------------------------------------- /tests/data/Issue503_external_link.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/tests/data/Issue503_external_link.xlsx -------------------------------------------------------------------------------- /tests/data/Issue714_locale_comma.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/tests/data/Issue714_locale_comma.xlsx -------------------------------------------------------------------------------- /tests/data/issue90_debug_test_file.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/tests/data/issue90_debug_test_file.xlsx -------------------------------------------------------------------------------- /tests/data/13_custom_heights_widths.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/tests/data/13_custom_heights_widths.xlsx -------------------------------------------------------------------------------- /tests/data/1_powerpoint_presentation.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/tests/data/1_powerpoint_presentation.xlsx -------------------------------------------------------------------------------- /tests/data/10_comments_hyperlinks_formulae.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/tests/data/10_comments_hyperlinks_formulae.xlsx -------------------------------------------------------------------------------- /tests/data/Issue279_workbook_delete_rename.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/tests/data/Issue279_workbook_delete_rename.xlsx -------------------------------------------------------------------------------- /tests/data/issue109_noncompliant_relations.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/tests/data/issue109_noncompliant_relations.xlsx -------------------------------------------------------------------------------- /tests/data/Issue6_google_missing_workbookView.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/tests/data/Issue6_google_missing_workbookView.xlsx -------------------------------------------------------------------------------- /tests/data/Issue353_first_row_empty_w_properties.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/tests/data/Issue353_first_row_empty_w_properties.xlsx -------------------------------------------------------------------------------- /tests/data/Issue18_defined_name_with_workbook_scope.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xlnt-community/xlnt/HEAD/tests/data/Issue18_defined_name_with_workbook_scope.xlsx -------------------------------------------------------------------------------- /docs/introduction/README.md: -------------------------------------------------------------------------------- 1 | ## Introduction 2 | 3 | * [Motivation](Motivation.md) 4 | * [Examples](Examples.md) 5 | * [Features](Features.md) 6 | * [Installation](Installation.md) -------------------------------------------------------------------------------- /docs/advanced/README.md: -------------------------------------------------------------------------------- 1 | ## Advanced 2 | 3 | * [Formatting](Formatting.md) 4 | * [Properties](Properties.md) 5 | * [Printing](Printing.md) 6 | * [Encryption](Encryption.md) 7 | * [Views](Views.md) -------------------------------------------------------------------------------- /book.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["build"], 3 | "pluginsConfig": { 4 | "build": { 5 | "template": "docs/template.ejs", 6 | "format": "man", 7 | "output": "docs/xlnt.3" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /docs/basics/README.md: -------------------------------------------------------------------------------- 1 | ## Basics 2 | 3 | * [Workbook](/docs/basics/Workbook.md) 4 | * [Worksheet](/docs/basics/Worksheet.md) 5 | * [Cell](/docs/basics/Cell.md) 6 | * [Iteration](/docs/basics/Iteration.md) 7 | * [Memory model](/docs/basics/MemoryModel.md) 8 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | This project adheres to [Semantic Versioning](http://semver.org/). 4 | Every release is documented on the Github: 5 | - New releases: see [Releases page](https://github.com/xlnt-community/xlnt/releases). 6 | - Up to version 1.5.0: see [tfussells's Releases page](https://github.com/tfussell/xlnt/releases). 7 | -------------------------------------------------------------------------------- /cmake/pkg-config.pc.cmake: -------------------------------------------------------------------------------- 1 | Name: ${PROJECT_NAME} 2 | Description: ${PROJECT_DESCRIPTION} 3 | Version: ${PROJECT_VERSION} 4 | URL: ${PROJECT_URL} 5 | prefix=${CMAKE_INSTALL_PREFIX} 6 | includedir=${PKG_CONFIG_INCLUDEDIR} 7 | libdir=${PKG_CONFIG_LIBDIR} 8 | exec_prefix=${PKG_CONFIG_EXEC_PREFIX} 9 | Libs: ${PKG_CONFIG_LIBS} 10 | Cflags: ${PKG_CONFIG_CFLAGS} 11 | -------------------------------------------------------------------------------- /.circleci/config_pr.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | jobs: 4 | post-coverage-comment: 5 | docker: 6 | - image: cimg/base:current 7 | resource_class: small 8 | steps: 9 | - checkout 10 | - run: .circleci/post_coverage_comment.sh <> 11 | 12 | workflows: 13 | new-pr: 14 | jobs: 15 | - post-coverage-comment -------------------------------------------------------------------------------- /cmake/XlntConfig.cmake.in: -------------------------------------------------------------------------------- 1 | set(XLNT_VERSION "@xlnt_VERSION@") 2 | 3 | @PACKAGE_INIT@ 4 | 5 | get_filename_component(XLNT_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) 6 | 7 | set_and_check(XLNT_INCLUDE_DIR "@XLNT_INCLUDE_INSTALL_DIR@") 8 | 9 | check_required_components(xlnt) 10 | 11 | if(NOT TARGET xlnt::xlnt) 12 | include("${XLNT_CMAKE_DIR}/XlntTargets.cmake") 13 | endif() 14 | -------------------------------------------------------------------------------- /ubsan.supp: -------------------------------------------------------------------------------- 1 | # UBSan suppression file for xlnt 2 | # Usage: UBSAN_OPTIONS="suppressions=../ubsan.supp" ./tests/xlnt.test 3 | 4 | # Suppress null pointer arithmetic in expat (third-party library) 5 | # Bug: hashTableIterInit does `iter->end = iter->p + table->size` where iter->p can be NULL 6 | # This is technically UB but harmless in practice (NULL + 0 = NULL on all platforms) 7 | pointer-overflow:hashTableIterInit 8 | -------------------------------------------------------------------------------- /docs/basics/Cell.md: -------------------------------------------------------------------------------- 1 | ## Cell 2 | 3 | ### Comparisons 4 | 5 | Comparisons that use the `operator==` (e.g. `cell1 == cell2`) do pointer comparisons internally. While this might seem unusual compared to other C++ classes, it aligns with XLNT's Memory Model and ensures the best performance, while being good enough for most use cases. If you instead want to perform a deep comparison of all underlying objects, use `compare()` instead. 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | docs/build/ 3 | docs/doxyxml/ 4 | node_modules/ 5 | *.obj 6 | *.sdf 7 | *.suo 8 | *.opensdf 9 | *.vcxproj.user 10 | *.o 11 | *.txt.user 12 | #*# 13 | *~ 14 | .DS_Store 15 | __pycache__/ 16 | Win32/ 17 | *.pyd 18 | python/record.txt 19 | python/xlntpyarrow.egg-info/ 20 | /x64/ 21 | .envrc 22 | .vscode 23 | /dist/ 24 | /.vs/ 25 | /out/ 26 | /CMakeSettings.json 27 | include/xlnt/utils/xlnt_cmake_export.h 28 | .idea/ 29 | -------------------------------------------------------------------------------- /docs/basics/Workbook.md: -------------------------------------------------------------------------------- 1 | ## Workbook 2 | 3 | ### Comparisons 4 | 5 | Comparisons that use the `operator==` (e.g. `workbook1 == workbook2`) do pointer comparisons internally. While this might seem unusual compared to other C++ classes, it aligns with XLNT's [Memory model](/docs/basics/MemoryModel.md) and ensures the best performance, while being good enough for most use cases. If you instead want to perform a deep comparison of all underlying objects, use `compare()` instead. 6 | -------------------------------------------------------------------------------- /docs/basics/Worksheet.md: -------------------------------------------------------------------------------- 1 | ## Worksheet 2 | 3 | ### Comparisons 4 | 5 | Comparisons that use the `operator==` (e.g. `worksheet1 == worksheet2`) do pointer comparisons internally. While this might seem unusual compared to other C++ classes, it aligns with XLNT's [Memory model](/docs/basics/MemoryModel.md) and ensures the best performance, while being good enough for most use cases. If you instead want to perform a deep comparison of all underlying objects, use `compare()` instead. 6 | -------------------------------------------------------------------------------- /AUTHORS.md: -------------------------------------------------------------------------------- 1 | This project was started by Thomas Fussell. 2 | 3 | It was initially inspired by the openpyxl library: https://openpyxl.readthedocs.org 4 | 5 | Thanks to everyone who has contributed to this project (in alphabetical order): 6 | 7 | * adam-nielsen 8 | * Malvineous 9 | * sukoi26 10 | * tpmccallum 11 | * xpol 12 | * xlnt community (check [contributors on github](https://github.com/xlnt-community/xlnt/graphs/contributors) or committers in the git log) 13 | 14 | Project logo designed by Thomas Fussell. 15 | -------------------------------------------------------------------------------- /benchmarks/disabled/bufzip.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void standard() 7 | { 8 | xlnt::xml_document doc; 9 | 10 | for (int i = 0; i < 1000000; i++) 11 | { 12 | doc.add_child("test"); 13 | } 14 | 15 | xlnt::zip_file archive; 16 | archive.writestr("sheet.xml", doc.to_string()); 17 | } 18 | 19 | int main() 20 | { 21 | standard(); 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /.release-it.json: -------------------------------------------------------------------------------- 1 | { 2 | "git": { 3 | "commitMessage": "release v${version}", 4 | "requireBranch": "master", 5 | "requireCommits": true, 6 | "tagAnnotation": "release v${version}", 7 | "tagName": "v${version}" 8 | }, 9 | "github": { 10 | "release": true, 11 | "releaseName": "xlnt v${version}" 12 | }, 13 | "npm": { 14 | "publish": false 15 | }, 16 | "plugins": { 17 | "@release-it/bumper": { 18 | "out": { 19 | "file": "source/CMakeLists.txt", 20 | "type": "text/plain" 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /.circleci/gcc7_cmake3.9.5_doxygen.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gcc:7 2 | 3 | # 1. Install CMake 4 | 5 | ARG CMAKE_VERSION=3.9.5 6 | 7 | WORKDIR /tmp/ 8 | RUN wget https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}.tar.gz 9 | RUN tar -xzvf cmake-${CMAKE_VERSION}.tar.gz 10 | 11 | WORKDIR /tmp/cmake-${CMAKE_VERSION} 12 | RUN ./bootstrap 13 | RUN make -j$(nproc --all) 14 | RUN make install 15 | 16 | # 2. Install doxygen 17 | 18 | RUN apt-get update -y 19 | RUN apt-get install -y --no-install-recommends doxygen 20 | 21 | # 3. Cleanup 22 | 23 | WORKDIR / 24 | RUN rm -rf /tmp/* 25 | -------------------------------------------------------------------------------- /source/packaging/uri.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace xlnt { 4 | 5 | uri::uri() 6 | { 7 | } 8 | 9 | uri::uri(const std::string &uri_string) 10 | : path_(uri_string) 11 | { 12 | } 13 | 14 | std::string uri::to_string() const 15 | { 16 | return path_.string(); 17 | } 18 | 19 | const path &uri::path() const 20 | { 21 | return path_; 22 | } 23 | 24 | bool uri::operator==(const uri &other) const 25 | { 26 | return to_string() == other.to_string(); 27 | } 28 | 29 | bool uri::operator!=(const uri &other) const 30 | { 31 | return !(*this == other); 32 | } 33 | 34 | } // namespace xlnt 35 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "third-party/libstudxml"] 2 | path = third-party/libstudxml 3 | url = https://git.codesynthesis.com/libstudxml/libstudxml.git 4 | [submodule "third-party/utfcpp"] 5 | path = third-party/utfcpp 6 | url = https://github.com/nemtrif/utfcpp.git 7 | [submodule "third-party/pybind11"] 8 | path = third-party/pybind11 9 | url = https://github.com/pybind/pybind11.git 10 | branch = v2.13 11 | [submodule "third-party/fmt"] 12 | path = third-party/fmt 13 | url = https://github.com/fmtlib/fmt.git 14 | [submodule "third-party/fast_float"] 15 | path = third-party/fast_float 16 | url = https://github.com/fastfloat/fast_float.git 17 | -------------------------------------------------------------------------------- /source/detail/implementations/formatting_record.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace xlnt { 6 | namespace detail { 7 | 8 | struct formatting_record 9 | { 10 | std::size_t index; 11 | 12 | bool pivot_button; 13 | bool quote_prefix; 14 | 15 | bool apply_alignment; 16 | std::size_t alignment_id; 17 | 18 | bool apply_border; 19 | std::size_t border_id; 20 | 21 | bool apply_fill; 22 | std::size_t fill_id; 23 | 24 | bool apply_font; 25 | std::size_t font_id; 26 | 27 | bool apply_number_format; 28 | std::size_t number_format_id; 29 | 30 | bool apply_protection; 31 | std::size_t protection_id; 32 | }; 33 | 34 | } // namespace detail 35 | } // namespace xlnt 36 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | setup: true 4 | 5 | orbs: 6 | continuation: circleci/continuation@1 7 | 8 | # parameters are automatically forwarded to continuation 9 | parameters: 10 | run-build: 11 | type: boolean 12 | default: true 13 | 14 | jobs: 15 | setup: 16 | docker: 17 | - image: cimg/base:current 18 | resource_class: large 19 | steps: 20 | - checkout 21 | - setup_remote_docker 22 | - run: 23 | name: Generate CircleCI config & build Dockerfile(s) if changed 24 | command: cd .circleci && ./setup.sh 25 | - continuation/continue: 26 | configuration_path: .circleci/continue_config.yml 27 | 28 | workflows: 29 | setup: 30 | jobs: 31 | - setup -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "xlnt", 3 | "version": "1.5.0", 4 | "description": "Cross-platform user-friendly xlsx library for C++11+", 5 | "main": "index.js", 6 | "directories": { 7 | "doc": "docs", 8 | "test": "tests" 9 | }, 10 | "devDependencies": { 11 | "@release-it/bumper": "^3.0.1", 12 | "release-it": "^14.11.5" 13 | }, 14 | "scripts": { 15 | "release": "release-it" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "git+https://github.com/tfussell/xlnt.git" 20 | }, 21 | "author": "Thomas Fussell ", 22 | "license": "MIT", 23 | "bugs": { 24 | "url": "https://github.com/tfussell/xlnt/issues" 25 | }, 26 | "homepage": "https://github.com/tfussell/xlnt#readme" 27 | } 28 | -------------------------------------------------------------------------------- /tests/helpers/temporary_file.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | namespace { 9 | 10 | static std::string create_temporary_filename() 11 | { 12 | return "temp.xlsx"; 13 | } 14 | 15 | } // namespace 16 | 17 | class temporary_file 18 | { 19 | public: 20 | temporary_file() : path_(create_temporary_filename()) 21 | { 22 | if(path_.exists()) 23 | { 24 | std::remove(path_.string().c_str()); 25 | } 26 | } 27 | 28 | ~temporary_file() 29 | { 30 | std::remove(path_.string().c_str()); 31 | } 32 | 33 | xlnt::path get_path() const { return path_; } 34 | 35 | private: 36 | const xlnt::path path_; 37 | }; 38 | -------------------------------------------------------------------------------- /.circleci/gcc7_cmake3.2.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gcc:7 2 | 3 | # 1. Install CMake 4 | 5 | ARG CMAKE_VERSION=3.2.0 6 | 7 | WORKDIR /tmp/ 8 | RUN wget https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}.tar.gz 9 | RUN tar -xzvf cmake-${CMAKE_VERSION}.tar.gz 10 | 11 | WORKDIR /tmp/cmake-${CMAKE_VERSION} 12 | RUN ./bootstrap 13 | RUN make -j$(nproc --all) 14 | RUN make install 15 | 16 | # 2. Install required de_DE and ps_AF locale (for benchmarks) 17 | 18 | RUN apt-get update -y 19 | RUN apt-get install -y --no-install-recommends locales 20 | RUN sed -i '/^# de_DE /s/^# //' /etc/locale.gen 21 | RUN sed -i '/^# ps_AF /s/^# //' /etc/locale.gen 22 | RUN locale-gen 23 | 24 | # 3. Cleanup 25 | 26 | WORKDIR / 27 | RUN rm -rf /tmp/* 28 | -------------------------------------------------------------------------------- /.circleci/gcc7_cmake3.9.5.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gcc:7 2 | 3 | # 1. Install CMake 4 | 5 | ARG CMAKE_VERSION=3.9.5 6 | 7 | WORKDIR /tmp/ 8 | RUN wget https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}.tar.gz 9 | RUN tar -xzvf cmake-${CMAKE_VERSION}.tar.gz 10 | 11 | WORKDIR /tmp/cmake-${CMAKE_VERSION} 12 | RUN ./bootstrap 13 | RUN make -j$(nproc --all) 14 | RUN make install 15 | 16 | # 2. Install required de_DE and ps_AF locale (for benchmarks) 17 | 18 | RUN apt-get update -y 19 | RUN apt-get install -y --no-install-recommends locales 20 | RUN sed -i '/^# de_DE /s/^# //' /etc/locale.gen 21 | RUN sed -i '/^# ps_AF /s/^# //' /etc/locale.gen 22 | RUN locale-gen 23 | 24 | # 3. Cleanup 25 | 26 | WORKDIR / 27 | RUN rm -rf /tmp/* 28 | -------------------------------------------------------------------------------- /.circleci/gcc_cmake_latest.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gcc:14 2 | 3 | # 1. Install CMake 4 | 5 | ARG CMAKE_VERSION=3.31.4 6 | 7 | WORKDIR /tmp/ 8 | RUN wget https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}.tar.gz 9 | RUN tar -xzvf cmake-${CMAKE_VERSION}.tar.gz 10 | 11 | WORKDIR /tmp/cmake-${CMAKE_VERSION} 12 | RUN ./bootstrap 13 | RUN make -j$(nproc --all) 14 | RUN make install 15 | 16 | # 2. Install required de_DE and ps_AF locale (for benchmarks) 17 | 18 | RUN apt-get update -y 19 | RUN apt-get install -y --no-install-recommends locales 20 | RUN sed -i '/^# de_DE /s/^# //' /etc/locale.gen 21 | RUN sed -i '/^# ps_AF /s/^# //' /etc/locale.gen 22 | RUN locale-gen 23 | 24 | # 3. Cleanup 25 | 26 | WORKDIR / 27 | RUN rm -rf /tmp/* 28 | -------------------------------------------------------------------------------- /.appveyor.yml: -------------------------------------------------------------------------------- 1 | version: "{build}" 2 | os: Visual Studio 2015 3 | 4 | cache: 5 | - vcpkg -> .appveyor.yml 6 | 7 | platform: 8 | - x64 9 | 10 | configuration: 11 | - Debug 12 | 13 | environment: 14 | matrix: 15 | - STATIC: OFF 16 | - STATIC: ON 17 | 18 | matrix: 19 | fast_finish: true 20 | 21 | init: [] 22 | 23 | before_build: 24 | - git submodule update --init --recursive 25 | - mkdir build 26 | - cd build 27 | - cmake -G "Visual Studio 14 2015" -D CMAKE_GENERATOR_PLATFORM=%platform% -D STATIC=%STATIC% -D SAMPLES=ON -D BENCHMARKS=ON -D TESTS=ON .. 28 | 29 | build: 30 | project: build/xlnt_all.sln 31 | parallel: true 32 | verbosity: minimal 33 | 34 | test_script: 35 | - tests\%configuration%\xlnt.test.exe 36 | - samples\%configuration%\sample-documentation.exe 37 | -------------------------------------------------------------------------------- /source/detail/serialization/serialisation_helpers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #define FMT_HEADER_ONLY 8 | #include 9 | 10 | namespace xlnt { 11 | namespace detail { 12 | 13 | std::string serialise(double d) 14 | { 15 | return fmt::format("{}", d); 16 | } 17 | 18 | double deserialise(const std::string &s, size_t *len_converted) 19 | { 20 | assert(!s.empty()); 21 | double d = std::numeric_limits::quiet_NaN(); 22 | detail::parse(s, d, len_converted); 23 | return d; 24 | } 25 | 26 | double deserialise(const char *s, const char **end) 27 | { 28 | assert(s != nullptr); 29 | double d = std::numeric_limits::quiet_NaN(); 30 | detail::parse(s, d, end); 31 | return d; 32 | } 33 | 34 | } // namespace detail 35 | } // namespace xlnt 36 | -------------------------------------------------------------------------------- /benchmarks/disabled/speed.cpp: -------------------------------------------------------------------------------- 1 | "Benchmark some different implementations for cells" 2 | 3 | from openpyxl.compat import range 4 | 5 | from openpyxl.cell import Cell 6 | from openpyxl.cell.read_only import ReadOnlyCell 7 | from memory_profiler import memory_usage 8 | import time 9 | 10 | 11 | def standard(): 12 | c = Cell(None, "A", "0", None) 13 | 14 | def iterative(): 15 | c = ReadOnlyCell(None, None, None, 'n') 16 | 17 | def dictionary(): 18 | c = {'ws':'None', 'col':'A', 'row':0, 'value':1} 19 | 20 | 21 | if __name__ == '__main__': 22 | initial_use = memory_usage(proc=-1, interval=1)[0] 23 | for fn in (standard, iterative, dictionary): 24 | t = time.time() 25 | container = [] 26 | for i in range(1000000): 27 | container.append(fn()) 28 | print("{0} {1} MB, {2:.2f}s".format( 29 | fn.func_name, 30 | memory_usage(proc=-1, interval=1)[0] - initial_use, 31 | time.time() - t)) 32 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Table of Contents 2 | 3 | * [Read Me](../README.md) 4 | * [Introduction](introduction/README.md) 5 | * [Motivation](introduction/Motivation.md) 6 | * [Examples](introduction/Examples.md) 7 | * [Features](introduction/Features.md) 8 | * [Installation](introduction/Installation.md) 9 | * [Basics](basics/README.md) 10 | * [Workbook](basics/Workbook.md) 11 | * [Worksheet](basics/Worksheet.md) 12 | * [Cell](basics/Cell.md) 13 | * [Iteration](basics/Iteration.md) 14 | * [Memory model](basics/MemoryModel.md) 15 | * [Advanced](advanced/README.md) 16 | * [Formatting](advanced/Formatting.md) 17 | * [Properties](advanced/Properties.md) 18 | * [Printing](advanced/Printing.md) 19 | * [Encryption](advanced/Encryption.md) 20 | * [Views](advanced/Views.md) 21 | * [API Reference](https://xlnt-community.github.io/xlnt/annotated.html) 22 | * [Source code](https://github.com/xlnt-community/xlnt) 23 | * [Change Log](../CHANGELOG.md) 24 | * [Contributing](../CONTRIBUTING.md) 25 | * [License](../LICENSE.md) 26 | -------------------------------------------------------------------------------- /docs/basics/MemoryModel.md: -------------------------------------------------------------------------------- 1 | # Memory Model 2 | 3 | ```c++ 4 | #include 5 | #include 6 | 7 | void set_cell(xlnt::cell cell, int value) 8 | { 9 | cell.value(value); 10 | } 11 | 12 | xlnt::workbook create_wb() 13 | { 14 | xlnt::workbook wb; 15 | auto ws = wb.active_sheet(); 16 | set_cell(wb.cell("A1"), 2); 17 | return wb; 18 | } 19 | 20 | int main() 21 | { 22 | auto wb = create_wb(); 23 | std::cout << wb.value() << std::endl; 24 | return 0; 25 | } 26 | ``` 27 | 28 | xlnt uses the pimpl idiom for most of its core data structures. This primary reason for choosing this technique was simplifying usage of the library. Instead of using pointers or references, classes can be passed around by value. Internally they hold a pointer to memory which is within the primary workbook implementation struct. Methods called on the wrapper object dereference the opaque pointer and manipulate its data directly. 29 | 30 | For the user, this means that workbooks, worksheets, cells, formats, and styles can be passed and stored by value. 31 | -------------------------------------------------------------------------------- /tests/helpers/test_suite.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | //#include 11 | //#include 12 | #include 13 | 14 | struct test_status 15 | { 16 | std::size_t tests_run = 0; 17 | std::size_t tests_failed = 0; 18 | std::size_t tests_passed = 0; 19 | std::vector failures; 20 | }; 21 | 22 | std::string build_name(const std::string &pretty, const std::string &method); 23 | 24 | #define register_test(test) register_test_internal([this]() { test(); }, build_name(__FUNCTION__, #test)); 25 | 26 | class test_suite 27 | { 28 | public: 29 | static test_status go(); 30 | 31 | protected: 32 | static void register_test_internal(std::function t, const std::string &function) 33 | { 34 | tests().push_back(std::make_pair(t, function)); 35 | } 36 | 37 | private: 38 | static std::vector, std::string>> &tests(); 39 | }; 40 | -------------------------------------------------------------------------------- /tests/helpers/temporary_directory.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | class temporary_directory 12 | { 13 | public: 14 | static std::string create() 15 | { 16 | #ifdef _WIN32 17 | std::array buffer; 18 | DWORD result = GetTempPath(static_cast(buffer.size()), buffer.data()); 19 | if(result > MAX_PATH) 20 | { 21 | throw xlnt::exception("buffer is too small"); 22 | } 23 | if(result == 0) 24 | { 25 | throw xlnt::exception("GetTempPath failed"); 26 | } 27 | std::string directory(buffer.begin(), buffer.begin() + result); 28 | return path_helper::windows_to_universal_path(directory + "xlnt"); 29 | #else 30 | return "/tmp/xlsx"; 31 | #endif 32 | } 33 | 34 | temporary_directory() : filename_(create()) 35 | { 36 | 37 | } 38 | 39 | ~temporary_directory() 40 | { 41 | remove(filename_.c_str()); 42 | } 43 | 44 | std::string get_filename() const { return filename_; } 45 | 46 | private: 47 | const std::string filename_; 48 | }; 49 | -------------------------------------------------------------------------------- /third-party/miniz/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2013-2014 RAD Game Tools and Valve Software 2 | Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC 3 | 4 | All Rights Reserved. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /.circleci/post_coverage_comment.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eo pipefail 4 | 5 | PR_NUMBER_OVERRIDE=$1 6 | 7 | post_coverage_comment () 8 | { 9 | PR_NUMBER=$1 10 | COMMIT_SHA=$2 11 | 12 | echo "Posting comment at PR $PR_NUMBER" 13 | 14 | curl -L -X POST \ 15 | -H "Authorization: Bearer ${PR_TOKEN}" \ 16 | "https://api.github.com/repos/xlnt-community/xlnt/issues/${PR_NUMBER}/comments" \ 17 | -d "{\"body\":\"Coverage report is available at: [full](https://xlnt-community.github.io/xlnt-coverage/${COMMIT_SHA}/differential/index.html) | [review summary](https://xlnt-community.github.io/xlnt-coverage/${COMMIT_SHA}/review/index.html)\"}" 18 | } 19 | 20 | main () 21 | { 22 | COMMIT_SHA=`git rev-parse HEAD` 23 | 24 | if [ -n "${PR_NUMBER_OVERRIDE}" ]; then 25 | post_coverage_comment ${PR_NUMBER_OVERRIDE} ${COMMIT_SHA} 26 | elif [ -n "${CIRCLE_PR_NUMBER}" ]; then 27 | post_coverage_comment ${CIRCLE_PR_NUMBER} ${COMMIT_SHA} 28 | elif [[ $"${CIRCLE_PULL_REQUEST}" =~ https://github.com/xlnt-community/xlnt/pull/([0-9]+)$ ]]; then 29 | post_coverage_comment ${BASH_REMATCH[1]} ${COMMIT_SHA} 30 | elif [[ $"${CIRCLE_BRANCH}" =~ pull/([0-9]+)(/.*)?$ ]]; then 31 | post_coverage_comment ${BASH_REMATCH[1]} ${COMMIT_SHA} 32 | else 33 | echo "not associated with a PR" 34 | fi 35 | } 36 | 37 | main 38 | 39 | -------------------------------------------------------------------------------- /samples/disabled/create.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | int main() 7 | { 8 | const std::vector> amounts = 9 | { 10 | { "Anne", 17.31 }, 11 | { "Brent", 21.99 }, 12 | { "Catelyn", 94.47 }, 13 | { "Diedrich", 101.05 } 14 | }; 15 | 16 | xlnt::workbook wb; 17 | auto ws = wb.get_active_sheet(); 18 | 19 | ws.get_cell("A1").set_value("Name"); 20 | ws.get_cell("B1").set_value("Amount"); 21 | 22 | std::size_t row = 2; 23 | auto money_format = xlnt::number_format::from_builtin_id(44); 24 | auto &style = wb.create_style("Currency"); 25 | style.set_builtin_id(4); 26 | style.set_number_format(money_format); 27 | 28 | for (const auto &amount : amounts) 29 | { 30 | ws.get_cell(xlnt::cell_reference(1, row)).set_value(amount.first); 31 | ws.get_cell(xlnt::cell_reference(2, row)).set_value(amount.second); 32 | ws.get_cell(xlnt::cell_reference(2, row)).set_style("Currency"); 33 | 34 | row++; 35 | } 36 | 37 | std::string sum_formula = "=SUM(B2:B" + std::to_string(row - 1) + ")"; 38 | ws.get_cell(xlnt::cell_reference(2, row)).set_style("Currency"); 39 | ws.get_cell(xlnt::cell_reference(2, row)).set_formula(sum_formula); 40 | 41 | wb.save("create.xlsx"); 42 | 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /tests/helpers/test_suite.cpp: -------------------------------------------------------------------------------- 1 | #include "test_suite.hpp" 2 | #include 3 | 4 | std::vector, std::string>> &test_suite::tests() 5 | { 6 | static std::vector, std::string>> all_tests; 7 | return all_tests; 8 | } 9 | 10 | std::string build_name(const std::string &pretty, const std::string &method) 11 | { 12 | return pretty.substr(0, pretty.find("::") + 2) + method; 13 | } 14 | 15 | test_status test_suite::go() 16 | { 17 | test_status status; 18 | 19 | for (auto test : tests()) 20 | { 21 | try 22 | { 23 | test.first(); 24 | std::cout << '.'; 25 | status.tests_passed++; 26 | } 27 | catch (std::exception &ex) 28 | { 29 | std::string fail_msg = test.second + " failed with:\n" + std::string(ex.what()); 30 | std::cout << "*\n" 31 | << fail_msg << '\n'; 32 | status.tests_failed++; 33 | status.failures.push_back(fail_msg); 34 | } 35 | catch (...) 36 | { 37 | std::cout << "*\n" 38 | << test.second << " failed\n"; 39 | status.tests_failed++; 40 | status.failures.push_back(test.second); 41 | } 42 | 43 | std::cout.flush(); 44 | status.tests_run++; 45 | } 46 | 47 | return status; 48 | } -------------------------------------------------------------------------------- /cmake/cmake_uninstall.cmake.in: -------------------------------------------------------------------------------- 1 | if(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt") 2 | message(FATAL_ERROR "Cannot find install manifest: @CMAKE_BINARY_DIR@/install_manifest.txt") 3 | endif(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt") 4 | 5 | file(READ "@CMAKE_BINARY_DIR@/install_manifest.txt" files) 6 | string(REGEX REPLACE "\n" ";" files "${files}") 7 | foreach(file ${files}) 8 | message(STATUS "Uninstalling $ENV{DESTDIR}${file}") 9 | if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") 10 | exec_program( 11 | "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" 12 | OUTPUT_VARIABLE rm_out 13 | RETURN_VALUE rm_retval 14 | ) 15 | if(NOT "${rm_retval}" STREQUAL 0) 16 | message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") 17 | endif(NOT "${rm_retval}" STREQUAL 0) 18 | else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") 19 | message(STATUS "File $ENV{DESTDIR}${file} does not exist.") 20 | endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") 21 | endforeach(file) 22 | 23 | message(STATUS "Uninstalling @INC_DEST_DIR@/xlnt") 24 | 25 | exec_program("@CMAKE_COMMAND@" 26 | ARGS "-E remove_directory @INC_DEST_DIR@/xlnt" 27 | OUTPUT_VARIABLE rm_out 28 | RETURN_VALUE rm_retval 29 | ) 30 | 31 | if(NOT "${rm_retval}" STREQUAL 0) 32 | message(FATAL_ERROR "Problem when removing @INC_DEST_DIR@/xlnt") 33 | endif() -------------------------------------------------------------------------------- /source/detail/implementations/conditional_format_impl.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | namespace xlnt { 10 | 11 | class border; 12 | class fill; 13 | class font; 14 | 15 | namespace detail { 16 | 17 | struct stylesheet; 18 | struct worksheet_impl; 19 | 20 | struct conditional_format_impl 21 | { 22 | stylesheet *parent = nullptr; 23 | worksheet_impl *target_sheet = nullptr; 24 | 25 | bool operator==(const conditional_format_impl& rhs) const 26 | { 27 | // not comparing parent or target sheet 28 | return target_range == rhs.target_range 29 | && priority == rhs.priority 30 | && differential_format_id == rhs.differential_format_id 31 | && when == rhs.when 32 | && border_id == rhs.border_id 33 | && fill_id == rhs.fill_id 34 | && font_id == rhs.font_id; 35 | } 36 | 37 | bool operator!=(const conditional_format_impl& rhs) const 38 | { 39 | return !(*this == rhs); 40 | } 41 | 42 | range_reference target_range; 43 | 44 | std::size_t priority = 0; 45 | std::size_t differential_format_id = 0; 46 | 47 | condition when; 48 | 49 | optional border_id; 50 | optional fill_id; 51 | optional font_id; 52 | }; 53 | 54 | } // namespace detail 55 | } // namespace xlnt 56 | -------------------------------------------------------------------------------- /benchmarks/disabled/memory.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __APPLE__ 4 | #include 5 | #endif 6 | 7 | #include 8 | 9 | #include "../tests/helpers/path_helper.hpp" 10 | 11 | int calc_memory_usage() 12 | { 13 | #ifdef __APPLE__ 14 | struct task_basic_info t_info; 15 | mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT; 16 | 17 | if (KERN_SUCCESS != task_info(mach_task_self(), 18 | TASK_BASIC_INFO, (task_info_t)&t_info, 19 | &t_info_count)) 20 | { 21 | return 0; 22 | } 23 | 24 | return t_info.virtual_size; 25 | #endif 26 | return 0; 27 | } 28 | 29 | void test_memory_use() 30 | { 31 | // Naive test that assumes memory use will never be more than 120 % of 32 | // that for first 50 rows 33 | auto current_folder = PathHelper::GetExecutableDirectory(); 34 | auto src = current_folder + "rks/files/very_large.xlsx"; 35 | 36 | xlnt::workbook wb; 37 | wb.load(src); 38 | auto ws = wb.get_active_sheet(); 39 | 40 | int initial_use = 0; 41 | int n = 0; 42 | 43 | for (auto line : ws.rows()) 44 | { 45 | if (n % 50 == 0) 46 | { 47 | auto use = calc_memory_usage(); 48 | 49 | if (initial_use == 0) 50 | { 51 | initial_use = use; 52 | } 53 | 54 | assert(use / initial_use < 1.2); 55 | std::cout << n << " " << use << std::endl; 56 | } 57 | 58 | n++; 59 | } 60 | } 61 | 62 | int main() 63 | { 64 | test_memory_use(); 65 | } 66 | -------------------------------------------------------------------------------- /samples/disabled/read.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // Read sample1.xlsx and print out a 2-dimensional 5 | // representation of each sheet. Cells are separated by commas. 6 | // Each new line is a new row. 7 | int main() 8 | { 9 | // Create a new workbook by reading sample1.xlsx in the current directory. 10 | xlnt::workbook wb; 11 | wb.load("sample1.xlsx"); 12 | 13 | // The workbook class has begin and end methods so it can be iterated upon. 14 | // Each item is a sheet in the workbook. 15 | for(const auto sheet : wb) 16 | { 17 | // Print the title of the sheet on its own line. 18 | std::cout << sheet.get_title() << ": " << std::endl; 19 | 20 | // Iterating on a range, such as from worksheet::rows, yields cell_vectors. 21 | // Cell vectors don't actually contain cells to reduce overhead. 22 | // Instead they hold a reference to a worksheet and the current cell_reference. 23 | // Internally, calling worksheet::get_cell with the current cell_reference yields the next cell. 24 | // This allows easy and fast iteration over a row (sometimes a column) in the worksheet. 25 | for(auto row : sheet.rows()) 26 | { 27 | for(auto cell : row) 28 | { 29 | // cell::operator<< adds a string represenation of the cell's value to the stream. 30 | std::cout << cell << ", "; 31 | } 32 | 33 | std::cout << std::endl; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /benchmarks/disabled/reader.cpp: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import timeit 4 | 5 | import openpyxl 6 | 7 | 8 | def reader(optimised): 9 | """ 10 | Loop through all cells of a workbook 11 | """ 12 | folder = os.path.split(__file__)[0] 13 | src = os.path.join(folder, "files", "very_large.xlsx") 14 | wb = openpyxl.load_workbook(src, use_iterators=optimised) 15 | ws = wb.active 16 | rows = ws.iter_rows() 17 | for r, row in enumerate(rows): 18 | for c, col in enumerate(row): 19 | pass 20 | print((r+1)* (c+1), "cells") 21 | 22 | def timer(fn): 23 | """ 24 | Create a timeit call to a function and pass in keyword arguments. 25 | The function is called twice, once using the standard workbook, then with the optimised one. 26 | Time from the best of three is taken. 27 | """ 28 | print("lxml", openpyxl.LXML) 29 | result = [] 30 | for opt in (False, True,): 31 | print("Workbook is {0}".format(opt and "optimised" or "not optimised")) 32 | times = timeit.repeat("{0}({1})".format(fn.__name__, opt), 33 | setup="from __main__ import {0}".format(fn.__name__), 34 | number = 1, 35 | repeat = 3 36 | ) 37 | print("{0:.2f}s".format(min(times))) 38 | result.append(min(times)) 39 | std, opt = result 40 | print("Optimised takes {0:.2%} time\n".format(opt/std)) 41 | return std, opt 42 | 43 | 44 | if __name__ == "__main__": 45 | timer(reader) 46 | -------------------------------------------------------------------------------- /source/detail/xlnt_config_impl.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #pragma once 26 | 27 | #include 28 | 29 | #ifdef XLNT_EXPOSE_INTERNAL_API 30 | #define XLNT_API_INTERNAL XLNT_API 31 | #else 32 | #define XLNT_API_INTERNAL 33 | #endif 34 | -------------------------------------------------------------------------------- /python/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.2...3.31) 2 | project(xlntpyarrow) 3 | 4 | if(NOT COMBINED_PROJECT) 5 | add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../source ${CMAKE_CURRENT_BINARY_DIR}/source) 6 | endif() 7 | 8 | add_subdirectory(../third-party/pybind11 pybind11) 9 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake") 10 | 11 | find_package(Arrow) 12 | 13 | if(NOT ARROW_FOUND) 14 | message(FATAL_ERROR "Arrow not found.") 15 | endif() 16 | 17 | pybind11_add_module(xlntpyarrowlib xlntpyarrow.lib.cpp) 18 | 19 | set_target_properties(xlntpyarrowlib PROPERTIES 20 | OUTPUT_NAME "lib") 21 | 22 | target_include_directories(xlntpyarrowlib 23 | PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} 24 | PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../source 25 | PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../third-party/pybind11/include 26 | PRIVATE ${ARROW_INCLUDE_DIR}) 27 | target_link_libraries(xlntpyarrowlib 28 | PRIVATE xlnt) 29 | 30 | if(MSVC) 31 | target_compile_definitions(xlntpyarrowlib 32 | PRIVATE _CRT_SECURE_NO_WARNINGS=1) 33 | target_link_libraries(xlntpyarrowlib 34 | PRIVATE ${ARROW_SHARED_IMP_LIB} 35 | PRIVATE ${ARROW_PYTHON_SHARED_IMP_LIB}) 36 | else() 37 | target_link_libraries(xlntpyarrowlib 38 | PRIVATE ${ARROW_SHARED_LIB} 39 | PRIVATE ${ARROW_PYTHON_SHARED_LIB}) 40 | endif() 41 | 42 | if(NOT STATIC) 43 | add_custom_command(TARGET xlntpyarrowlib POST_BUILD 44 | COMMAND ${CMAKE_COMMAND} -E copy_if_different 45 | $ 46 | $) 47 | endif() 48 | -------------------------------------------------------------------------------- /docs/advanced/Formatting.md: -------------------------------------------------------------------------------- 1 | 2 | # Formatting 3 | 4 | ## Format vs. Style 5 | 6 | ```c++ 7 | #include 8 | #include 9 | 10 | int main() 11 | { 12 | xlnt::workbook wb; 13 | auto cell = wb.active_sheet().cell("A1"); 14 | return 0; 15 | } 16 | ``` 17 | 18 | In the context of xlnt, format and style have specific distinct meanings. A style in xlnt corresponds to a named style created in the "Cell styles" dropdown in Excel. It must have a name and optionally any of: alignment, border, fill, font, number format, protection. A format in xlnt corresponds to the alignment, border, fill, font, number format, and protection settings applied to a cell via right-click->"Format Cells". A cell can have both a format and a style. The style properties will generally override the format properties. 19 | 20 | ## Number Formatting 21 | 22 | ```c++ 23 | #include 24 | #include 25 | 26 | int main() 27 | { 28 | xlnt::workbook wb; 29 | auto cell = wb.active_sheet().cell("A1"); 30 | cell.number_format(xlnt::number_format::percentage()); 31 | cell.value(0.513); 32 | std::cout << cell.to_string() << std::endl; 33 | return 0; 34 | } 35 | ``` 36 | 37 | An xlnt::number_format is the format code used when displaying a value in a cell. For example, a number_format of "0.00" implies that the number 13.726 should be displayed as "13.73". Many number formats are built-in to Excel and can be access with xlnt::number_format static constructors. Other custom number formats can be created by passing a string to the [xlnt::number_format constructor](#cell-const-cell-amp). 38 | -------------------------------------------------------------------------------- /samples/decrypt.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #include 26 | #include 27 | 28 | int main() 29 | { 30 | xlnt::workbook wb; 31 | 32 | const auto password = std::string("secret"); 33 | wb.load(path_helper::sample_file("encrypted.xlsx"), password); 34 | wb.save("decrypted.xlsx"); 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /include/xlnt/worksheet/major_order.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #pragma once 26 | 27 | #include 28 | 29 | namespace xlnt { 30 | 31 | /// 32 | /// Defines whether iterating a range returns columns or rows sequentially. 33 | /// 34 | enum class major_order 35 | { 36 | column, 37 | row 38 | }; 39 | 40 | } // namespace xlnt 41 | -------------------------------------------------------------------------------- /include/xlnt/xlnt_config.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #pragma once 26 | 27 | #include // This file is auto-generated by cmake, see GENERATE_EXPORT_HEADER 28 | 29 | #if defined(_MSC_VER) && !defined(XLNT_EXPORT) 30 | #pragma warning(disable : 4251) 31 | #pragma warning(disable : 4275) 32 | #endif // defined(_MSC_VER) && !defined(XLNT_EXPORT) 33 | -------------------------------------------------------------------------------- /include/xlnt/workbook/external_book.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2010-2015 openpyxl 3 | // Copyright (c) 2024-2025 xlnt-community 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE 22 | // 23 | // @license: http://www.opensource.org/licenses/mit-license.php 24 | // @author: see AUTHORS file 25 | 26 | #pragma once 27 | 28 | #include 29 | 30 | namespace xlnt { 31 | 32 | /// 33 | /// A reference to an external workbook for use in formulae. 34 | /// 35 | class XLNT_API external_book 36 | { 37 | }; 38 | 39 | } // namespace xlnt 40 | -------------------------------------------------------------------------------- /source/detail/default_case.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #pragma once 26 | 27 | #include 28 | 29 | #define EXCEPT_ON_UNHANDLED_SWITCH_CASE 30 | 31 | #ifdef EXCEPT_ON_UNHANDLED_SWITCH_CASE 32 | #define default_case(default_value) throw xlnt::unhandled_switch_case() 33 | #else 34 | #define default_case(default_value) return default_value 35 | #endif 36 | -------------------------------------------------------------------------------- /source/detail/cryptography/base64.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | namespace xlnt { 30 | namespace detail { 31 | 32 | std::string encode_base64(const std::vector &input); 33 | 34 | std::vector decode_base64(const std::string &input); 35 | 36 | } // namespace detail 37 | } // namespace xlnt 38 | -------------------------------------------------------------------------------- /.circleci/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eo pipefail 4 | 5 | REPLACE_REGEX="" 6 | 7 | isBuilt () 8 | { 9 | docker manifest inspect $1 > /dev/null 10 | return $? 11 | } 12 | 13 | setupDocker () 14 | { 15 | printf "\n * Setting up $1\n" 16 | 17 | DOCKERFILE="$1.Dockerfile" 18 | if [ -n "${DOCKERHUB_USERNAME}" ]; then 19 | REPOSITORY="${DOCKERHUB_USERNAME}/ci_$1" 20 | else 21 | REPOSITORY="xlntcommunity/ci_$1" 22 | fi 23 | LATEST_CHANGE_COMMIT=`git log -n 1 --pretty=format:%H -- "${DOCKERFILE}"` 24 | CURRENT_COMMIT=`git rev-parse HEAD` 25 | TAG=${LATEST_CHANGE_COMMIT} 26 | IMAGE=${REPOSITORY}:${TAG} 27 | 28 | if isBuilt "${IMAGE}"; then 29 | echo "${DOCKERFILE} unchanged: using already built image with tag ${TAG}" 30 | else 31 | echo "${DOCKERFILE} changed: building new docker image with tag ${TAG}" 32 | 33 | docker build -t ${IMAGE} --file "${DOCKERFILE}" . 34 | echo ${DOCKERHUB_PASSWORD} | docker login -u ${DOCKERHUB_USERNAME} --password-stdin 35 | docker push ${IMAGE} 36 | fi 37 | 38 | REPLACE_REGEX+="${REPLACE_REGEX} -e s#PLACEHOLDER_IMAGE($1)#${IMAGE}#" 39 | } 40 | 41 | checkCoveralls () 42 | { 43 | if [ -n "${COVERALLS_REPO_TOKEN}" ]; then 44 | REPLACE_REGEX+="${REPLACE_REGEX} -e s#HAS_COVERALLS#true#" 45 | else 46 | REPLACE_REGEX+="${REPLACE_REGEX} -e s#HAS_COVERALLS#false#" 47 | fi 48 | } 49 | 50 | main () 51 | { 52 | for filename in *.Dockerfile; do 53 | setupDocker $(basename "$filename" .Dockerfile) 54 | done 55 | 56 | checkCoveralls 57 | 58 | sed ${REPLACE_REGEX} continue_config_in.yml > continue_config.yml 59 | } 60 | 61 | main 62 | 63 | -------------------------------------------------------------------------------- /include/xlnt/utils/calendar.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #pragma once 26 | 27 | #include 28 | 29 | namespace xlnt { 30 | 31 | /// 32 | /// An enumeration of possible base dates. 33 | /// Dates in Excel are stored as days since this base date. 34 | /// 35 | enum class calendar 36 | { 37 | windows_1900, 38 | mac_1904 39 | }; 40 | 41 | } // namespace xlnt 42 | -------------------------------------------------------------------------------- /source/detail/cryptography/sha.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #pragma once 26 | 27 | #include 28 | #include 29 | 30 | namespace xlnt { 31 | namespace detail { 32 | 33 | void sha1(const std::vector &input, std::vector &output); 34 | void sha512(const std::vector &data, std::vector &output); 35 | 36 | }; // namespace detail 37 | }; // namespace xlnt 38 | -------------------------------------------------------------------------------- /source/cell/rich_text_run.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #include 26 | 27 | namespace xlnt { 28 | 29 | bool rich_text_run::operator==(const rich_text_run &other) const 30 | { 31 | return first == other.first && second == other.second; 32 | } 33 | 34 | bool rich_text_run::operator!=(const rich_text_run &other) const 35 | { 36 | return !(*this == other); 37 | } 38 | 39 | } // namespace xlnt 40 | -------------------------------------------------------------------------------- /source/detail/serialization/defined_name.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #pragma once 26 | 27 | #include 28 | 29 | #include 30 | 31 | namespace xlnt { 32 | namespace detail { 33 | 34 | struct defined_name 35 | { 36 | std::string name; 37 | optional sheet_id; 38 | bool hidden = false; 39 | std::string value; 40 | }; 41 | 42 | } // namespace detail 43 | } // namespace xlnt 44 | -------------------------------------------------------------------------------- /source/worksheet/selection.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2024-2025 xlnt-community 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE 20 | // 21 | // @license: http://www.opensource.org/licenses/mit-license.php 22 | // @author: see AUTHORS file 23 | 24 | #include 25 | #include 26 | 27 | namespace xlnt { 28 | 29 | // ref == ST_Sqref: a space delimited list of range references 30 | void selection::sqref(const std::string &ref) 31 | { 32 | sqref_.clear(); 33 | for (const auto& range : detail::split_string(ref, ' ')) 34 | sqref_.push_back(range_reference(range)); 35 | } 36 | 37 | } // namespace xlnt 38 | -------------------------------------------------------------------------------- /benchmarks/spreadsheet-load.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace { 6 | using milliseconds_d = std::chrono::duration; 7 | 8 | void run_load_test(const xlnt::path &file, int runs = 10) 9 | { 10 | std::cout << file.string() << "\n\n"; 11 | 12 | xlnt::workbook wb; 13 | std::vector test_timings; 14 | 15 | for (int i = 0; i < runs; ++i) 16 | { 17 | auto start = std::chrono::steady_clock::now(); 18 | wb.load(file); 19 | 20 | auto end = std::chrono::steady_clock::now(); 21 | wb.clear(); 22 | test_timings.push_back(end - start); 23 | 24 | std::cout << milliseconds_d(test_timings.back()).count() << " ms\n"; 25 | } 26 | } 27 | 28 | void run_save_test(const xlnt::path &file, int runs = 10) 29 | { 30 | std::cout << file.string() << "\n\n"; 31 | 32 | xlnt::workbook wb; 33 | wb.load(file); 34 | const xlnt::path save_path(file.filename()); 35 | 36 | std::vector test_timings; 37 | 38 | for (int i = 0; i < runs; ++i) 39 | { 40 | auto start = std::chrono::steady_clock::now(); 41 | 42 | wb.save(save_path); 43 | 44 | auto end = std::chrono::steady_clock::now(); 45 | test_timings.push_back(end - start); 46 | std::cout << milliseconds_d(test_timings.back()).count() << " ms\n"; 47 | } 48 | } 49 | } // namespace 50 | 51 | int main() 52 | { 53 | run_load_test(path_helper::benchmark_file("large.xlsx")); 54 | run_load_test(path_helper::benchmark_file("very_large.xlsx")); 55 | 56 | run_save_test(path_helper::benchmark_file("large.xlsx")); 57 | run_save_test(path_helper::benchmark_file("very_large.xlsx")); 58 | } -------------------------------------------------------------------------------- /source/cell/phonetic_run.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #include 26 | #include 27 | 28 | namespace xlnt { 29 | 30 | bool phonetic_run::operator==(const phonetic_run &other) const 31 | { 32 | return std::tie(text, start, end, preserve_space) == std::tie(other.text, other.start, other.end, other.preserve_space); 33 | } 34 | 35 | bool phonetic_run::operator!=(const phonetic_run &other) const 36 | { 37 | return !(*this == other); 38 | } 39 | 40 | } // namespace xlnt 41 | -------------------------------------------------------------------------------- /samples/disabled/write.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // Make 3 sheets containing 10,000 cells with unique numeric values. 4 | int main() 5 | { 6 | // create the workbook 7 | xlnt::workbook workbook; 8 | 9 | // workbooks have a single sheet called "Sheet" initially so let's get rid of it 10 | auto to_remove = workbook.get_sheet_by_name("Sheet"); 11 | workbook.remove_sheet(to_remove); 12 | 13 | // this loop will create three sheets and populate them with data 14 | for(int i = 0; i < 3; i++) 15 | { 16 | // the title will be "Sample2-1", "Sample2-2", or "Sample2-3" 17 | // if we don't specify a title, these would be "Sheet#" where 18 | // # is the lowest number that doesn't have a corresponding sheet yet. 19 | auto sheet = workbook.create_sheet("Sample2-" + std::to_string(i)); 20 | 21 | for(int row = 1; row < 101; row++) 22 | { 23 | for(int column = 1; column < 101; column++) 24 | { 25 | // Since we can't overload subscript to accept both number, 26 | // create a cell_reference which "points" to the current cell. 27 | xlnt::cell_reference ref(column, row); 28 | 29 | // This is important! 30 | // The cell class is really just a wrapper around a pointer. 31 | // For this reason, we can store them by value and still modify 32 | // the data in the containing worksheet. 33 | auto cell = sheet[ref]; 34 | 35 | // set_value has overloads for many types such as strings and ints 36 | cell.set_value(row * 100 + column); 37 | } 38 | } 39 | } 40 | 41 | // This will be written to the current directory. 42 | workbook.save("sample2.xlsx"); 43 | } 44 | -------------------------------------------------------------------------------- /include/xlnt/utils/hash_combine.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 xlnt-community 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE 20 | // 21 | // @license: http://www.opensource.org/licenses/mit-license.php 22 | // @author: see AUTHORS file 23 | 24 | #pragma once 25 | 26 | #include 27 | #include 28 | 29 | namespace xlnt { 30 | namespace detail { 31 | 32 | /// 33 | /// A standard, robust way to combine hash values. 34 | /// Often credited to Boost's hash_combine. 35 | /// 36 | template 37 | inline void hash_combine(std::size_t& seed, const T& v) 38 | { 39 | std::hash hasher; 40 | seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); 41 | } 42 | 43 | } // namespace detail 44 | } // namespace xlnt 45 | -------------------------------------------------------------------------------- /tests/helpers/timing.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | #pragma once 25 | 26 | #include 27 | 28 | namespace xlnt { 29 | namespace benchmarks { 30 | 31 | inline std::size_t current_time() 32 | { 33 | auto now = std::chrono::system_clock::now(); 34 | auto time_since_epoch = now.time_since_epoch(); 35 | auto duration = std::chrono::duration_cast(time_since_epoch); 36 | 37 | return static_cast(duration.count()); 38 | } 39 | 40 | } // namespace benchmarks 41 | } // namespace xlnt 42 | -------------------------------------------------------------------------------- /include/xlnt/cell/phonetic_run.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #pragma once 26 | 27 | #include 28 | #include 29 | 30 | #include 31 | 32 | namespace xlnt { 33 | 34 | /// 35 | /// Encapsulates a run of text that 36 | /// 37 | struct XLNT_API phonetic_run 38 | { 39 | std::string text; 40 | uint32_t start; 41 | uint32_t end; 42 | bool preserve_space; 43 | 44 | bool operator==(const phonetic_run &other) const; 45 | bool operator!=(const phonetic_run &other) const; 46 | }; 47 | 48 | } // namespace xlnt 49 | -------------------------------------------------------------------------------- /include/xlnt/workbook/theme.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #pragma once 26 | 27 | #include 28 | 29 | namespace xlnt { 30 | 31 | /// 32 | /// A theme is a combination of fonts, colors, and effects. 33 | /// This isn't really supported yet. 34 | /// 35 | class XLNT_API theme 36 | { 37 | public: 38 | bool operator==(const theme &) const 39 | { 40 | return true; 41 | } 42 | 43 | bool operator!=(const theme &other) const 44 | { 45 | return !(*this == other); 46 | } 47 | }; 48 | 49 | } // namespace xlnt 50 | -------------------------------------------------------------------------------- /source/detail/header_footer/header_footer_code.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #include 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | namespace xlnt { 34 | namespace detail { 35 | 36 | std::array, 3> decode_header_footer(const std::string &hf_string); 37 | std::string encode_header_footer(const rich_text &t, header_footer::location where); 38 | 39 | } // namespace detail 40 | } // namespace xlnt 41 | -------------------------------------------------------------------------------- /source/detail/cryptography/cipher.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #pragma once 26 | 27 | #include 28 | 29 | namespace xlnt { 30 | namespace detail { 31 | 32 | enum class cipher_algorithm 33 | { 34 | aes, 35 | rc2, 36 | rc4, 37 | des, 38 | desx, 39 | triple_des, 40 | triple_des_112 41 | }; 42 | 43 | enum class cipher_chaining 44 | { 45 | ecb, // electronic code book 46 | cbc // cipher block chaining 47 | }; 48 | 49 | enum class cipher_direction 50 | { 51 | encryption, 52 | decryption 53 | }; 54 | 55 | }; // namespace detail 56 | }; // namespace xlnt 57 | -------------------------------------------------------------------------------- /source/detail/external/include_windows.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | #pragma once 25 | 26 | #ifdef _MSC_VER 27 | 28 | #pragma push_macro("NOMINMAX") 29 | #pragma push_macro("UNICODE") 30 | #pragma push_macro("STRICT") 31 | 32 | #ifndef NOMINMAX 33 | #define NOMINMAX 34 | #endif 35 | 36 | #ifndef UNICODE 37 | #define UNICODE 38 | #endif 39 | 40 | #ifndef STRICT 41 | #define STRICT 42 | #endif 43 | 44 | #ifndef WIN32_LEAN_AND_MEAN 45 | #define WIN32_LEAN_AND_MEAN 46 | #endif 47 | 48 | #include 49 | 50 | #pragma pop_macro("STRICT") 51 | #pragma pop_macro("UNICODE") 52 | #pragma pop_macro("NOMINMAX") 53 | 54 | #endif // _MSC_VER 55 | -------------------------------------------------------------------------------- /tests/styles/alignment_test_suite.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #include 26 | #include 27 | 28 | class alignment_test_suite : public test_suite 29 | { 30 | public: 31 | alignment_test_suite() 32 | { 33 | register_test(test_all); 34 | } 35 | 36 | void test_all() 37 | { 38 | xlnt::alignment alignment; 39 | 40 | xlnt_assert(!alignment.horizontal().is_set()); 41 | xlnt_assert(!alignment.vertical().is_set()); 42 | xlnt_assert(!alignment.shrink()); 43 | xlnt_assert(!alignment.wrap()); 44 | } 45 | }; 46 | static alignment_test_suite x; 47 | -------------------------------------------------------------------------------- /include/xlnt/cell/rich_text_run.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #pragma once 26 | 27 | #include 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | namespace xlnt { 34 | 35 | /// 36 | /// Typedef a rich_text_run as a pair of string and optional font. 37 | /// 38 | struct XLNT_API rich_text_run 39 | { 40 | std::string first; 41 | optional second; 42 | bool preserve_space; 43 | 44 | bool operator==(const rich_text_run &other) const; 45 | 46 | bool operator!=(const rich_text_run &other) const; 47 | }; 48 | 49 | } // namespace xlnt 50 | -------------------------------------------------------------------------------- /samples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1...3.31) 2 | project(xlnt.samples) 3 | 4 | set(CMAKE_CXX_STANDARD ${XLNT_CXX_LANG}) 5 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 6 | set(CMAKE_C_STANDARD ${XLNT_C_LANG}) 7 | set(CMAKE_C_STANDARD_REQUIRED ON) 8 | set(CXX_EXTENSIONS OFF) 9 | 10 | if(NOT COMBINED_PROJECT) 11 | # Include xlnt library 12 | add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../source ${CMAKE_CURRENT_BINARY_DIR}/source) 13 | endif() 14 | 15 | if(STATIC_CRT) 16 | include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/ucm.cmake) 17 | ucm_set_runtime(STATIC) 18 | endif() 19 | 20 | set(XLNT_SAMPLE_DATA_DIR ${CMAKE_CURRENT_SOURCE_DIR}/data) 21 | 22 | file(GLOB SAMPLE_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) 23 | 24 | if(COVERAGE AND STATIC) 25 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage") 26 | endif() 27 | 28 | foreach(SAMPLE_SOURCE IN ITEMS ${SAMPLE_SOURCES}) 29 | # Convert .cpp to sample- 30 | get_filename_component(SAMPLE_NAME ${SAMPLE_SOURCE} NAME_WE) 31 | set(SAMPLE_EXECUTABLE sample-${SAMPLE_NAME}) 32 | 33 | add_executable(${SAMPLE_EXECUTABLE} ${SAMPLE_SOURCE}) 34 | 35 | target_link_libraries(${SAMPLE_EXECUTABLE} PRIVATE xlnt) 36 | # Need to use some test helpers 37 | target_include_directories(${SAMPLE_EXECUTABLE} 38 | PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../tests) 39 | # Some helpers also need further internal includes 40 | target_include_directories(${SAMPLE_EXECUTABLE} 41 | PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../source) 42 | target_compile_definitions(${SAMPLE_EXECUTABLE} 43 | PRIVATE XLNT_SAMPLE_DATA_DIR="${XLNT_SAMPLE_DATA_DIR}") 44 | 45 | if(MSVC AND NOT STATIC) 46 | # Copy xlnt DLL into samples directory 47 | add_custom_command(TARGET ${SAMPLE_EXECUTABLE} POST_BUILD 48 | COMMAND ${CMAKE_COMMAND} -E copy_if_different 49 | $ 50 | $) 51 | endif() 52 | endforeach() 53 | # 54 | -------------------------------------------------------------------------------- /source/detail/external/include_libstudxml.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | #pragma once 25 | 26 | #pragma clang diagnostic push 27 | #pragma clang diagnostic ignored "-Wweak-vtables" 28 | #pragma clang diagnostic ignored "-Wextra-semi" 29 | #pragma clang diagnostic ignored "-Wdeprecated" 30 | #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" 31 | #pragma clang diagnostic ignored "-Wsuggest-destructor-override" 32 | #pragma clang diagnostic ignored "-Wsuggest-override" 33 | #include 34 | #include 35 | #include 36 | #include 37 | #pragma clang diagnostic pop 38 | -------------------------------------------------------------------------------- /include/xlnt/utils/scoped_enum_hash.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #pragma once 26 | 27 | #include // for std::hash 28 | 29 | namespace xlnt { 30 | 31 | /// 32 | /// Allows a scoped enum (aka "enum class") to be used as a key 33 | /// in a std::unordered_map. 34 | /// 35 | template 36 | struct scoped_enum_hash 37 | { 38 | /// 39 | /// Cast the enumeration e to a std::size_t and hash that value using std::hash. 40 | /// 41 | std::size_t operator()(Enum e) const 42 | { 43 | static std::hash hasher; 44 | return hasher(static_cast(e)); 45 | } 46 | }; 47 | 48 | } // namespace xlnt 49 | -------------------------------------------------------------------------------- /tests/runner.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #include 26 | #include 27 | 28 | void print_summary(const test_status& results) 29 | { 30 | std::cout << "\n\n"; 31 | 32 | std::cout << "Run: " << results.tests_run << '\n'; 33 | std::cout << "Passed: " << results.tests_passed << '\n'; 34 | std::cout << "Failed: " << results.tests_failed << '\n' << '\n'; 35 | 36 | for (auto failure : results.failures) 37 | { 38 | std::cout << failure << "\n\n"; 39 | } 40 | } 41 | 42 | int main() 43 | { 44 | test_status overall_status = test_suite::go(); 45 | 46 | print_summary(overall_status); 47 | 48 | return static_cast(overall_status.tests_failed); 49 | } 50 | -------------------------------------------------------------------------------- /source/detail/cryptography/hash.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #pragma once 26 | 27 | #include 28 | 29 | #include 30 | #include 31 | 32 | namespace xlnt { 33 | namespace detail { 34 | 35 | enum class hash_algorithm 36 | { 37 | sha1, 38 | sha256, 39 | sha384, 40 | sha512, 41 | md2, 42 | md4, 43 | md5, 44 | ripemd128, 45 | ripemd160, 46 | whirlpool 47 | }; 48 | 49 | void hash(hash_algorithm algorithm, const std::vector &input, std::vector &output); 50 | std::vector hash(hash_algorithm algorithm, const std::vector &input); 51 | 52 | }; // namespace detail 53 | }; // namespace xlnt 54 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: LLVM 3 | AccessModifierOffset: -4 4 | AlignAfterOpenBracket: DontAlign 5 | AlignConsecutiveAssignments: false 6 | AlignConsecutiveDeclarations: false 7 | AlignOperands: false 8 | AlignTrailingComments: false 9 | AllowAllParametersOfDeclarationOnNextLine: false 10 | AllowShortBlocksOnASingleLine: false 11 | AllowShortCaseLabelsOnASingleLine: false 12 | AllowShortFunctionsOnASingleLine: None 13 | AllowShortIfStatementsOnASingleLine: true 14 | AllowShortLoopsOnASingleLine: false 15 | AlwaysBreakBeforeMultilineStrings: true 16 | AlwaysBreakTemplateDeclarations: true 17 | BraceWrapping: 18 | AfterClass: true 19 | AfterControlStatement: true 20 | AfterEnum: true 21 | AfterFunction: true 22 | AfterNamespace: false 23 | AfterObjCDeclaration: true 24 | AfterStruct: true 25 | AfterUnion: true 26 | BeforeCatch: true 27 | BeforeElse: true 28 | BreakBeforeBinaryOperators: NonAssignment 29 | BreakBeforeBraces: Custom 30 | ColumnLimit: 0 31 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 32 | Cpp11BracedListStyle: true 33 | DerivePointerAlignment: false 34 | DisableFormat: false 35 | IncludeCategories: 36 | - Regex: '^$' 37 | Priority: 2 38 | - Regex: '^&' 43 | Priority: 1 44 | - Regex: '^".*"' 45 | Priority: 5 46 | IndentCaseLabels: false 47 | IndentWidth: 4 48 | KeepEmptyLinesAtTheStartOfBlocks: false 49 | Language: Cpp 50 | NamespaceIndentation: None 51 | MaxEmptyLinesToKeep: 1 52 | PenaltyBreakComment: 1000 53 | PointerAlignment: Right 54 | SortIncludes: true 55 | SpaceAfterCStyleCast: false 56 | SpaceBeforeParens: ControlStatements 57 | SpaceInEmptyParentheses: false 58 | SpacesBeforeTrailingComments: 1 59 | SpacesInAngles: false 60 | SpacesInCStyleCastParentheses: false 61 | SpacesInContainerLiterals: true 62 | SpacesInParentheses: false 63 | SpacesInSquareBrackets: false 64 | Standard: Cpp11 65 | UseTab: Never 66 | 67 | ... 68 | -------------------------------------------------------------------------------- /source/detail/cryptography/xlsx_crypto_consumer.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | #if XLNT_HAS_INCLUDE() && XLNT_HAS_FEATURE(U8_STRING_VIEW) 34 | #include 35 | #endif 36 | 37 | namespace xlnt { 38 | namespace detail { 39 | 40 | XLNT_API_INTERNAL std::vector decrypt_xlsx(const std::vector &bytes, const std::string &password); 41 | 42 | #if XLNT_HAS_FEATURE(U8_STRING_VIEW) 43 | XLNT_API_INTERNAL std::vector decrypt_xlsx(const std::vector &bytes, std::u8string_view password); 44 | #endif 45 | 46 | } // namespace detail 47 | } // namespace xlnt 48 | -------------------------------------------------------------------------------- /source/detail/cryptography/xlsx_crypto_producer.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | #if XLNT_HAS_INCLUDE() && XLNT_HAS_FEATURE(U8_STRING_VIEW) 34 | #include 35 | #endif 36 | 37 | namespace xlnt { 38 | namespace detail { 39 | 40 | XLNT_API_INTERNAL std::vector encrypt_xlsx(const std::vector &bytes, const std::string &password); 41 | 42 | #if XLNT_HAS_FEATURE(U8_STRING_VIEW) 43 | XLNT_API_INTERNAL std::vector encrypt_xlsx(const std::vector &bytes, std::u8string_view password); 44 | #endif 45 | 46 | } // namespace detail 47 | } // namespace xlnt 48 | -------------------------------------------------------------------------------- /source/detail/utils/string_helpers.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2024-2025 xlnt-community 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE 20 | // 21 | // @license: http://www.opensource.org/licenses/mit-license.php 22 | // @author: see AUTHORS file 23 | 24 | #include "string_helpers.hpp" 25 | 26 | namespace xlnt { 27 | namespace detail { 28 | 29 | std::vector split_string(const std::string &string, char delim) 30 | { 31 | std::vector split; 32 | 33 | if (string.empty()) 34 | return split; 35 | 36 | std::string::size_type previous_index = 0; 37 | auto separator_index = string.find(delim); 38 | 39 | while (separator_index != std::string::npos) 40 | { 41 | auto part = string.substr(previous_index, separator_index - previous_index); 42 | split.push_back(part); 43 | 44 | previous_index = separator_index + 1; 45 | separator_index = string.find(delim, previous_index); 46 | } 47 | 48 | split.push_back(string.substr(previous_index)); 49 | 50 | return split; 51 | } 52 | 53 | } // namespace detail 54 | } // namespace xlnt 55 | -------------------------------------------------------------------------------- /include/xlnt/drawing/spreadsheet_drawing.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #pragma once 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | namespace xml { 32 | class parser; 33 | class serializer; 34 | } // namespace xml 35 | 36 | namespace xlnt { 37 | 38 | class worksheet; 39 | 40 | namespace drawing { 41 | 42 | /// 43 | /// The spreadsheet_drawing class encapsulates the information 44 | /// captured from objects within the spreadsheetDrawing schema. 45 | /// 46 | class XLNT_API spreadsheet_drawing 47 | { 48 | public: 49 | spreadsheet_drawing(xml::parser &parser); 50 | void serialize(xml::serializer &serializer); 51 | 52 | std::vector get_embed_ids(); 53 | 54 | private: 55 | std::string serialized_value_; 56 | std::vector embed_ids_; 57 | }; 58 | 59 | } // namespace drawing 60 | } // namespace xlnt 61 | -------------------------------------------------------------------------------- /source/detail/implementations/hyperlink_impl.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #pragma once 26 | 27 | #include 28 | 29 | #include 30 | #include 31 | 32 | namespace xlnt { 33 | namespace detail { 34 | 35 | // [serialised] 36 | struct hyperlink_impl 37 | { 38 | xlnt::relationship relationship; 39 | xlnt::optional location; 40 | xlnt::optional tooltip; 41 | xlnt::optional display; 42 | }; 43 | 44 | inline bool operator==(const hyperlink_impl &lhs, const hyperlink_impl &rhs) 45 | { 46 | return lhs.relationship == rhs.relationship 47 | && lhs.tooltip == rhs.tooltip 48 | && lhs.display == rhs.display; 49 | } 50 | 51 | inline bool operator!=(const hyperlink_impl &lhs, const hyperlink_impl &rhs) 52 | { 53 | return !(lhs == rhs); 54 | } 55 | 56 | } // namespace detail 57 | } // namespace xlnt 58 | -------------------------------------------------------------------------------- /source/detail/limits.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #pragma once 26 | 27 | #include "constants.hpp" 28 | 29 | namespace xlnt { 30 | namespace detail { 31 | 32 | /// 33 | /// Clips the maximum number of reserved elements to a certain upper limit. 34 | /// Information like a "count" is often saved in XLSX files and can be used by std::vector::reserve (or other containers) 35 | /// to allocate the memory right away and thus improve performance. However, malicious or broken files 36 | /// might then cause XLNT to allocate extreme amounts of memory. This function clips the number of elements 37 | /// to an upper limit to protect against such issues, but still allow the caller to pre-allocate memory. 38 | /// 39 | inline size_t clip_reserve_elements(size_t num_elements) 40 | { 41 | return std::min(num_elements, xlnt::constants::max_elements_for_reserve()); 42 | } 43 | 44 | } // namespace detail 45 | } // namespace xlnt 46 | -------------------------------------------------------------------------------- /source/detail/serialization/open_stream.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #pragma once 26 | 27 | #include 28 | #include 29 | 30 | #include 31 | 32 | #if XLNT_HAS_INCLUDE() && XLNT_HAS_FEATURE(U8_STRING_VIEW) 33 | #include 34 | #endif 35 | 36 | namespace xlnt { 37 | namespace detail { 38 | 39 | void open_stream(std::ifstream &stream, const std::string &path); 40 | 41 | void open_stream(std::ofstream &stream, const std::string &path); 42 | 43 | #if XLNT_HAS_FEATURE(U8_STRING_VIEW) 44 | void open_stream(std::ifstream &stream, std::u8string_view path); 45 | 46 | void open_stream(std::ofstream &stream, std::u8string_view path); 47 | #endif 48 | 49 | #ifdef _MSC_VER 50 | void open_stream(std::ifstream &stream, const std::wstring &path); 51 | 52 | void open_stream(std::ofstream &stream, const std::wstring &path); 53 | #endif 54 | 55 | } // namespace detail 56 | } // namespace xlnt 57 | -------------------------------------------------------------------------------- /source/detail/cryptography/hash.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #include 26 | #include 27 | 28 | namespace xlnt { 29 | namespace detail { 30 | 31 | void hash(hash_algorithm algorithm, const std::vector &input, std::vector &output) 32 | { 33 | if (algorithm == hash_algorithm::sha512) 34 | { 35 | xlnt::detail::sha512(input, output); 36 | } 37 | else if (algorithm == hash_algorithm::sha1) 38 | { 39 | xlnt::detail::sha1(input, output); 40 | } 41 | else 42 | { 43 | throw xlnt::exception("unsupported hash algorithm"); 44 | } 45 | } 46 | 47 | std::vector hash(hash_algorithm algorithm, const std::vector &input) 48 | { 49 | auto output = std::vector(); 50 | hash(algorithm, input, output); 51 | 52 | return output; 53 | } 54 | 55 | }; // namespace detail 56 | }; // namespace xlnt 57 | -------------------------------------------------------------------------------- /tests/styles/protection_test_suite.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | class protection_test_suite : public test_suite 30 | { 31 | public: 32 | protection_test_suite() 33 | { 34 | register_test(test_all); 35 | } 36 | 37 | void test_all() 38 | { 39 | auto prot = xlnt::protection::unlocked_and_visible(); 40 | xlnt_assert(!prot.hidden()); 41 | xlnt_assert(!prot.locked()); 42 | 43 | prot = xlnt::protection::locked_and_visible(); 44 | xlnt_assert(!prot.hidden()); 45 | xlnt_assert(prot.locked()); 46 | 47 | prot = xlnt::protection::unlocked_and_hidden(); 48 | xlnt_assert(prot.hidden()); 49 | xlnt_assert(!prot.locked()); 50 | 51 | prot = xlnt::protection::locked_and_hidden(); 52 | xlnt_assert(prot.hidden()); 53 | xlnt_assert(prot.locked()); 54 | } 55 | }; 56 | static protection_test_suite x; 57 | -------------------------------------------------------------------------------- /include/xlnt/cell/cell_type.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2010-2015 openpyxl 3 | // Copyright (c) 2024-2025 xlnt-community 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE 22 | // 23 | // @license: http://www.opensource.org/licenses/mit-license.php 24 | // @author: see AUTHORS file 25 | 26 | #pragma once 27 | 28 | #include 29 | 30 | /// 31 | /// Enumerates the possible types a cell can be determined by it's current value. 32 | /// 33 | 34 | namespace xlnt { 35 | 36 | /// 37 | /// Enumerates the possible types a cell can be determined by it's current value. 38 | /// 39 | enum class cell_type 40 | { 41 | /// no value 42 | empty, 43 | /// value is TRUE or FALSE 44 | boolean, 45 | /// value is an ISO 8601 formatted date 46 | date, 47 | /// value is a known error code such as \#VALUE! 48 | error, 49 | /// value is a string stored in the cell 50 | inline_string, 51 | /// value is a number 52 | number, 53 | /// value is a string shared with other cells to save space 54 | shared_string, 55 | /// value is the string result of a formula 56 | formula_string 57 | }; 58 | 59 | } // namespace xlnt 60 | -------------------------------------------------------------------------------- /benchmarks/microbenchmarks/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # FetchContent added in cmake v3.11 2 | # https://cmake.org/cmake/help/v3.11/module/FetchContent.html 3 | # this file is behind a feature flag (XLNT_MICROBENCH_ENABLED) so the primary build is not affected 4 | # NOTE: FetchContent_Populate has been deprecated in CMake 3.30. Its replacement, 5 | # FetchContent_MakeAvailable, is available since CMake 3.14. 6 | cmake_minimum_required(VERSION 3.14...3.31) 7 | project(xlnt_ubench) 8 | 9 | # acquire google benchmark dependency 10 | # disable generation of the various test projects 11 | set(BENCHMARK_ENABLE_TESTING OFF) 12 | # gtest not required 13 | set(BENCHMARK_ENABLE_GTEST_TESTS OFF) 14 | 15 | include(FetchContent) 16 | FetchContent_Declare( 17 | googlebenchmark 18 | GIT_REPOSITORY https://github.com/google/benchmark 19 | GIT_TAG v1.8.5 20 | ) 21 | # download if not already present 22 | FetchContent_GetProperties(googlebenchmark) 23 | if(NOT googlebenchmark_POPULATED) 24 | FetchContent_MakeAvailable(googlebenchmark) 25 | endif() 26 | # equivalent of add_subdirectory, now available for use 27 | FetchContent_MakeAvailable(googlebenchmark) 28 | 29 | add_executable(xlnt_ubench) 30 | target_include_directories(xlnt_ubench 31 | PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../source) 32 | target_sources(xlnt_ubench 33 | PRIVATE 34 | string_to_double.cpp 35 | double_to_string.cpp 36 | ) 37 | target_link_libraries(xlnt_ubench benchmark_main xlnt) 38 | # Require C++17 for benchmarking std::to_chars and std::from_chars 39 | if (XLNT_CXX_LANG LESS 17) 40 | target_compile_features(xlnt_ubench PRIVATE cxx_std_17) 41 | else() 42 | target_compile_features(xlnt_ubench PRIVATE cxx_std_${XLNT_CXX_LANG}) 43 | endif() 44 | target_compile_features(xlnt_ubench PRIVATE c_std_${XLNT_C_LANG}) 45 | 46 | if (XLNT_USE_LOCALE_COMMA_DECIMAL_SEPARATOR) 47 | target_compile_definitions(xlnt_ubench PRIVATE XLNT_USE_LOCALE_COMMA_DECIMAL_SEPARATOR=1) 48 | endif() 49 | target_compile_definitions(xlnt_ubench PRIVATE XLNT_LOCALE_COMMA_DECIMAL_SEPARATOR="${XLNT_LOCALE_COMMA_DECIMAL_SEPARATOR}") 50 | 51 | if (XLNT_USE_LOCALE_ARABIC_DECIMAL_SEPARATOR) 52 | target_compile_definitions(xlnt_ubench PRIVATE XLNT_USE_LOCALE_ARABIC_DECIMAL_SEPARATOR=1) 53 | endif() 54 | target_compile_definitions(xlnt_ubench PRIVATE XLNT_LOCALE_ARABIC_DECIMAL_SEPARATOR="${XLNT_LOCALE_ARABIC_DECIMAL_SEPARATOR}") 55 | -------------------------------------------------------------------------------- /source/detail/cryptography/aes.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #pragma once 26 | 27 | #include 28 | #include 29 | 30 | namespace xlnt { 31 | namespace detail { 32 | 33 | std::vector aes_ecb_encrypt( 34 | const std::vector &input, 35 | const std::vector &key, 36 | const std::size_t offset = 0); 37 | 38 | std::vector aes_ecb_decrypt( 39 | const std::vector &input, 40 | const std::vector &key, 41 | const std::size_t offset = 0); 42 | 43 | std::vector aes_cbc_encrypt( 44 | const std::vector &input, 45 | const std::vector &key, 46 | const std::vector &iv, 47 | const std::size_t offset = 0); 48 | 49 | std::vector aes_cbc_decrypt( 50 | const std::vector &input, 51 | const std::vector &key, 52 | const std::vector &iv, 53 | const std::size_t offset = 0); 54 | 55 | } // namespace detail 56 | } // namespace xlnt 57 | -------------------------------------------------------------------------------- /tests/drawing/drawing_test_suite.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | class drawing_test_suite : public test_suite 31 | { 32 | public: 33 | drawing_test_suite() 34 | { 35 | register_test(test_load_save); 36 | } 37 | 38 | void test_load_save() 39 | { 40 | xlnt::workbook wb1; 41 | wb1.load(path_helper::test_file("2_minimal.xlsx")); 42 | auto ws1 = wb1.active_sheet(); 43 | xlnt_assert_equals(ws1.has_drawing(), false); 44 | 45 | xlnt::workbook wb2; 46 | wb2.load(path_helper::test_file("14_images.xlsx")); 47 | auto ws2 = wb2.active_sheet(); 48 | xlnt_assert_equals(ws2.has_drawing(), true); 49 | wb2.save("temp_with_images.xlsx"); 50 | 51 | xlnt::workbook wb3; 52 | wb3.load("temp_with_images.xlsx"); 53 | auto ws3 = wb3.active_sheet(); 54 | xlnt_assert_equals(ws3.has_drawing(), true); 55 | } 56 | }; 57 | static drawing_test_suite x{}; 58 | -------------------------------------------------------------------------------- /include/xlnt/worksheet/sheet_protection.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2010-2015 openpyxl 3 | // Copyright (c) 2024-2025 xlnt-community 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE 22 | // 23 | // @license: http://www.opensource.org/licenses/mit-license.php 24 | // @author: see AUTHORS file 25 | 26 | #pragma once 27 | 28 | #include 29 | 30 | #include 31 | 32 | namespace xlnt { 33 | 34 | // TOOD: does this really need its own class? 35 | 36 | /// 37 | /// Protection applied to a particular worksheet to prevent it from being modified. 38 | /// 39 | class XLNT_API sheet_protection 40 | { 41 | public: 42 | /// 43 | /// Calculates and returns the hash of the given protection password. 44 | /// 45 | static std::string hash_password(const std::string &password); 46 | 47 | /// 48 | /// Sets the protection password to password. 49 | /// 50 | void password(const std::string &password); 51 | 52 | /// 53 | /// Returns the hash of the password set for this sheet protection. 54 | /// 55 | std::string hashed_password() const; 56 | 57 | private: 58 | /// 59 | /// The hash of the password. 60 | /// 61 | std::string hashed_password_; 62 | }; 63 | 64 | } // namespace xlnt 65 | -------------------------------------------------------------------------------- /include/xlnt/workbook/calculation_properties.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #pragma once 26 | 27 | #include 28 | 29 | #include 30 | 31 | namespace xlnt { 32 | 33 | /// 34 | /// Workbook file properties relating to calculations. 35 | /// 36 | class XLNT_API calculation_properties 37 | { 38 | public: 39 | /// 40 | /// The version of calculation engine used to calculate cell formula values. 41 | /// If this is older than the version of the Excel calculation engine opening 42 | /// the workbook, cell values will be recalculated. 43 | /// 44 | std::size_t calc_id = 0; 45 | 46 | /// 47 | /// If this is true, concurrent calculation will be enabled for the workbook. 48 | /// 49 | bool concurrent_calc = false; 50 | }; 51 | 52 | inline bool operator==(const calculation_properties &lhs, const calculation_properties &rhs) 53 | { 54 | return lhs.calc_id == rhs.calc_id 55 | && lhs.concurrent_calc == rhs.concurrent_calc; 56 | } 57 | 58 | inline bool operator!=(const calculation_properties &lhs, const calculation_properties &rhs) 59 | { 60 | return !(lhs == rhs); 61 | } 62 | 63 | } // namespace xlnt 64 | -------------------------------------------------------------------------------- /tests/worksheet/page_setup_test_suite.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #include 26 | #include 27 | 28 | class page_setup_test_suite : public test_suite 29 | { 30 | public: 31 | page_setup_test_suite() 32 | { 33 | register_test(test_properties); 34 | } 35 | 36 | void test_properties() 37 | { 38 | xlnt::page_setup ps; 39 | 40 | xlnt_assert(!ps.has_paper_size()); 41 | ps.paper_size(xlnt::paper_size::executive); 42 | xlnt_assert_equals(ps.paper_size(), xlnt::paper_size::executive); 43 | 44 | xlnt_assert(!ps.orientation_.is_set()); 45 | ps.orientation_.set(xlnt::orientation::landscape); 46 | xlnt_assert_equals(ps.orientation_.get(), xlnt::orientation::landscape); 47 | 48 | xlnt_assert(!ps.fit_to_page()); 49 | ps.fit_to_page(true); 50 | xlnt_assert(ps.fit_to_page()); 51 | 52 | xlnt_assert(!ps.fit_to_height()); 53 | ps.fit_to_height(true); 54 | xlnt_assert(ps.fit_to_height()); 55 | 56 | xlnt_assert(!ps.fit_to_width()); 57 | ps.fit_to_width(true); 58 | xlnt_assert(ps.fit_to_width()); 59 | } 60 | }; 61 | static page_setup_test_suite x; 62 | -------------------------------------------------------------------------------- /include/xlnt/cell/hyperlink.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #pragma once 26 | 27 | #include 28 | #include 29 | 30 | namespace xlnt { 31 | 32 | namespace detail { 33 | struct hyperlink_impl; 34 | } 35 | 36 | class cell; 37 | class range; 38 | class relationship; 39 | 40 | /// 41 | /// Describes a hyperlink pointing from a cell to another cell or a URL. 42 | /// 43 | class XLNT_API hyperlink 44 | { 45 | public: 46 | bool external() const; 47 | class relationship relationship() const; 48 | // external target 49 | std::string url() const; 50 | // internal target 51 | std::string target_range() const; 52 | 53 | bool has_display() const; 54 | void display(const std::string &value); 55 | const std::string &display() const; 56 | 57 | bool has_tooltip() const; 58 | void tooltip(const std::string &value); 59 | const std::string &tooltip() const; 60 | 61 | bool has_location() const; 62 | void location(const std::string &value); 63 | const std::string &location() const; 64 | 65 | private: 66 | friend class cell; 67 | hyperlink(detail::hyperlink_impl *d); 68 | detail::hyperlink_impl *d_ = nullptr; 69 | }; 70 | 71 | } // namespace xlnt 72 | -------------------------------------------------------------------------------- /source/detail/unicode.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #pragma once 26 | 27 | #include 28 | 29 | #include 30 | #include 31 | 32 | #if XLNT_HAS_INCLUDE() && XLNT_HAS_FEATURE(U8_STRING_VIEW) 33 | #include 34 | #endif 35 | 36 | namespace xlnt { 37 | namespace detail { 38 | 39 | XLNT_API_INTERNAL std::u16string utf8_to_utf16(const std::string &utf8_string); 40 | XLNT_API_INTERNAL std::u32string utf8_to_utf32(const std::string &utf8_string); 41 | XLNT_API_INTERNAL std::string utf16_to_utf8(const std::u16string &utf16_string); 42 | XLNT_API_INTERNAL std::string utf32_to_utf8(const std::u32string &utf32_string); 43 | XLNT_API_INTERNAL std::string latin1_to_utf8(const std::string &latin1); 44 | XLNT_API_INTERNAL size_t string_length(const std::string &utf8_string); 45 | 46 | #if XLNT_HAS_FEATURE(U8_STRING_VIEW) 47 | XLNT_API_INTERNAL std::u16string utf8_to_utf16(std::u8string_view utf8_string); 48 | XLNT_API_INTERNAL std::u32string utf8_to_utf32(std::u8string_view utf8_string); 49 | XLNT_API_INTERNAL std::u8string utf16_to_utf8_u8(std::u16string_view utf16_string); 50 | XLNT_API_INTERNAL std::u8string utf32_to_utf8_u8(std::u32string_view utf32_string); 51 | #endif 52 | 53 | } // namespace detail 54 | } // namespace xlnt 55 | -------------------------------------------------------------------------------- /source/detail/implementations/style_impl.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | namespace xlnt { 9 | 10 | class alignment; 11 | class border; 12 | class fill; 13 | class font; 14 | class number_format; 15 | class protection; 16 | 17 | namespace detail { 18 | 19 | struct stylesheet; 20 | 21 | struct style_impl 22 | { 23 | stylesheet *parent = nullptr; 24 | 25 | bool operator==(const style_impl& rhs) const 26 | { 27 | // not comparing parent 28 | return name == rhs.name 29 | && formatting_record_id == rhs.formatting_record_id 30 | && custom_builtin == rhs.custom_builtin 31 | && hidden_style == rhs.hidden_style 32 | && builtin_id == rhs.builtin_id 33 | && outline_style == rhs.outline_style 34 | && alignment_id == rhs.alignment_id 35 | && alignment_applied == rhs.alignment_applied 36 | && border_id == rhs.border_id 37 | && border_applied == rhs.border_applied 38 | && fill_id == rhs.fill_id 39 | && fill_applied == rhs.fill_applied 40 | && font_id == rhs.font_id 41 | && font_applied == rhs.font_applied 42 | && number_format_id == rhs.number_format_id 43 | && number_format_applied == number_format_applied 44 | && protection_id == rhs.protection_id 45 | && protection_applied == rhs.protection_applied 46 | && pivot_button_ == rhs.pivot_button_ 47 | && quote_prefix_ == rhs.quote_prefix_; 48 | } 49 | 50 | bool operator!=(const style_impl& rhs) const 51 | { 52 | return !(*this == rhs); 53 | } 54 | 55 | std::string name; 56 | std::size_t formatting_record_id = 0; 57 | 58 | bool custom_builtin = false; 59 | bool hidden_style = false; 60 | 61 | optional builtin_id; 62 | optional outline_style; 63 | 64 | optional alignment_id; 65 | optional alignment_applied; 66 | 67 | optional border_id; 68 | optional border_applied; 69 | 70 | optional fill_id; 71 | optional fill_applied; 72 | 73 | optional font_id; 74 | optional font_applied; 75 | 76 | optional number_format_id; 77 | optional number_format_applied; 78 | 79 | optional protection_id; 80 | optional protection_applied; 81 | 82 | bool pivot_button_ = false; 83 | bool quote_prefix_ = false; 84 | }; 85 | 86 | } // namespace detail 87 | } // namespace xlnt 88 | -------------------------------------------------------------------------------- /source/packaging/relationship.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2010-2015 openpyxl 3 | // Copyright (c) 2024-2025 xlnt-community 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE 22 | // 23 | // @license: http://www.opensource.org/licenses/mit-license.php 24 | // @author: see AUTHORS file 25 | 26 | #include 27 | 28 | namespace xlnt { 29 | 30 | relationship::relationship() 31 | { 32 | } 33 | 34 | relationship::relationship( 35 | const std::string &id, relationship_type t, const uri &source, const uri &target, xlnt::target_mode mode) 36 | : id_(id), type_(t), source_(source), target_(target), mode_(mode) 37 | { 38 | } 39 | 40 | const std::string &relationship::id() const 41 | { 42 | return id_; 43 | } 44 | 45 | target_mode relationship::target_mode() const 46 | { 47 | return mode_; 48 | } 49 | 50 | const uri &relationship::source() const 51 | { 52 | return source_; 53 | } 54 | 55 | const uri &relationship::target() const 56 | { 57 | return target_; 58 | } 59 | 60 | relationship_type relationship::type() const 61 | { 62 | return type_; 63 | } 64 | 65 | bool relationship::operator==(const relationship &rhs) const 66 | { 67 | return type_ == rhs.type_ 68 | && id_ == rhs.id_ 69 | && source_ == rhs.source_ 70 | && target_ == rhs.target_ 71 | && mode_ == rhs.mode_; 72 | } 73 | 74 | bool relationship::operator!=(const relationship &rhs) const 75 | { 76 | return !(*this == rhs); 77 | } 78 | 79 | } // namespace xlnt 80 | -------------------------------------------------------------------------------- /include/xlnt/workbook/metadata_property.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #pragma once 26 | 27 | #include 28 | 29 | namespace xlnt { 30 | 31 | /// 32 | /// Every core property in a workbook must be one of these types. 33 | /// 34 | enum class core_property 35 | { 36 | category, 37 | content_status, 38 | created, 39 | creator, 40 | description, 41 | identifier, 42 | keywords, 43 | language, 44 | last_modified_by, 45 | last_printed, 46 | modified, 47 | revision, 48 | subject, 49 | title, 50 | version 51 | }; 52 | 53 | /// 54 | /// Every extended property in a workbook must be one of these types. 55 | /// 56 | enum class extended_property 57 | { 58 | application, 59 | app_version, 60 | characters, 61 | characters_with_spaces, 62 | company, 63 | dig_sig, 64 | doc_security, 65 | heading_pairs, 66 | hidden_slides, 67 | h_links, 68 | hyperlink_base, 69 | hyperlinks_changed, 70 | lines, 71 | links_up_to_date, 72 | manager, 73 | m_m_clips, 74 | notes, 75 | pages, 76 | paragraphs, 77 | presentation_format, 78 | scale_crop, 79 | shared_doc, 80 | slides, 81 | template_, 82 | titles_of_parts, 83 | total_time, 84 | words 85 | }; 86 | 87 | } // namespace xlnt 88 | -------------------------------------------------------------------------------- /source/styles/protection.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2010-2015 openpyxl 3 | // Copyright (c) 2024-2025 xlnt-community 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE 22 | // 23 | // @license: http://www.opensource.org/licenses/mit-license.php 24 | // @author: see AUTHORS file 25 | 26 | #include 27 | 28 | namespace xlnt { 29 | 30 | protection protection::unlocked_and_visible() 31 | { 32 | return protection(); 33 | } 34 | 35 | protection protection::locked_and_visible() 36 | { 37 | return protection().locked(true); 38 | } 39 | 40 | protection protection::unlocked_and_hidden() 41 | { 42 | return protection().hidden(true); 43 | } 44 | 45 | protection protection::locked_and_hidden() 46 | { 47 | return protection().locked(true).hidden(true); 48 | } 49 | 50 | protection::protection() 51 | : locked_(false), hidden_(false) 52 | { 53 | } 54 | 55 | bool protection::locked() const 56 | { 57 | return locked_; 58 | } 59 | 60 | protection &protection::locked(bool locked) 61 | { 62 | locked_ = locked; 63 | return *this; 64 | } 65 | 66 | bool protection::hidden() const 67 | { 68 | return hidden_; 69 | } 70 | 71 | protection &protection::hidden(bool hidden) 72 | { 73 | hidden_ = hidden; 74 | return *this; 75 | } 76 | 77 | bool protection::operator==(const protection &other) const 78 | { 79 | return locked_ == other.locked_ && hidden_ == other.hidden_; 80 | } 81 | 82 | bool protection::operator!=(const protection &other) const 83 | { 84 | return !(*this == other); 85 | } 86 | 87 | } // namespace xlnt 88 | -------------------------------------------------------------------------------- /tests/internal/locale_helpers.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2024-2025 xlnt-community 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE 20 | // 21 | // @license: http://www.opensource.org/licenses/mit-license.php 22 | // @author: see AUTHORS file 23 | 24 | #pragma once 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | namespace test_helpers 31 | { 32 | 33 | struct SetLocale 34 | { 35 | SetLocale(const char* locale_name, const char *expected_decimal_separator) 36 | : previous_locale(setlocale(LC_ALL, nullptr)) 37 | { 38 | xlnt_assert(std::setlocale(LC_ALL, locale_name) != nullptr); 39 | 40 | if (strcmp(expected_decimal_separator, localeconv()->decimal_point) != 0) 41 | { 42 | std::string error = "Unexpected decimal separator for locale "; 43 | error += locale_name; 44 | error += " expected "; 45 | error += expected_decimal_separator; 46 | error += " but found "; 47 | error += localeconv()->decimal_point; 48 | 49 | // If failed, please install the locale specified by the CMake variable XLNT_LOCALE_****_DECIMAL_SEPARATOR 50 | // to correctly run this test *and* make sure that the locale uses the expected decimal separator, 51 | // or alternatively disable the CMake option XLNT_USE_LOCALE_****_DECIMAL_SEPARATOR. 52 | throw xlnt::invalid_parameter(error.c_str()); 53 | } 54 | 55 | } 56 | ~SetLocale() {std::setlocale(LC_ALL, previous_locale);} 57 | 58 | char * previous_locale = nullptr; 59 | }; 60 | 61 | } // namespace test_helpers 62 | -------------------------------------------------------------------------------- /source/worksheet/sheet_protection.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2010-2015 openpyxl 3 | // Copyright (c) 2024-2025 xlnt-community 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE 22 | // 23 | // @license: http://www.opensource.org/licenses/mit-license.php 24 | // @author: see AUTHORS file 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | 31 | namespace { 32 | 33 | template 34 | std::string int_to_hex(T i) 35 | { 36 | std::stringstream stream; 37 | stream << std::hex << i; 38 | 39 | return stream.str(); 40 | } 41 | 42 | } // namespace 43 | 44 | namespace xlnt { 45 | 46 | void sheet_protection::password(const std::string &password) 47 | { 48 | hashed_password_ = hash_password(password); 49 | } 50 | 51 | std::string sheet_protection::hashed_password() const 52 | { 53 | return hashed_password_; 54 | } 55 | 56 | std::string sheet_protection::hash_password(const std::string &plaintext_password) 57 | { 58 | int password = 0x0000; 59 | int i = 1; 60 | 61 | for (auto character : plaintext_password) 62 | { 63 | int value = character << i; 64 | int rotated_bits = value >> 15; 65 | value &= 0x7fff; 66 | password ^= (value | rotated_bits); 67 | i++; 68 | } 69 | 70 | password ^= plaintext_password.size(); 71 | password ^= 0xCE4B; 72 | 73 | std::string hashed = int_to_hex(password); 74 | std::transform(hashed.begin(), hashed.end(), hashed.begin(), 75 | [](char c) { return std::toupper(c, std::locale::classic()); }); 76 | 77 | return hashed; 78 | } 79 | } // namespace xlnt 80 | -------------------------------------------------------------------------------- /include/xlnt/worksheet/sheet_format_properties.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #pragma once 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | namespace xlnt { 32 | 33 | /// 34 | /// General worksheet formatting properties. 35 | /// 36 | class XLNT_API sheet_format_properties 37 | { 38 | public: 39 | /// 40 | /// The base column width 41 | /// 42 | optional base_col_width; 43 | 44 | /// 45 | /// The default row height is required 46 | /// 47 | double default_row_height = 15.0; 48 | 49 | /// 50 | /// The default column width 51 | /// 52 | optional default_column_width; 53 | 54 | /// 55 | /// x14ac extension, dyDescent property 56 | /// 57 | optional dy_descent; 58 | }; 59 | 60 | inline bool operator==(const sheet_format_properties &lhs, const sheet_format_properties &rhs) 61 | { 62 | return lhs.base_col_width == rhs.base_col_width 63 | && lhs.default_column_width == rhs.default_column_width 64 | && detail::float_equals(lhs.default_row_height, rhs.default_row_height) 65 | && lhs.dy_descent == rhs.dy_descent; 66 | } 67 | 68 | inline bool operator!=(const sheet_format_properties &lhs, const sheet_format_properties &rhs) 69 | { 70 | return !(lhs == rhs); 71 | } 72 | 73 | } // namespace xlnt 74 | -------------------------------------------------------------------------------- /include/xlnt/worksheet/print_options.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #pragma once 26 | 27 | #include 28 | #include 29 | 30 | namespace xlnt { 31 | 32 | struct XLNT_API print_options 33 | { 34 | /// 35 | /// if both grid_lines_set and this are true, grid lines are printed 36 | /// 37 | optional print_grid_lines; 38 | 39 | /// 40 | /// if both print grid lines and this are true, grid lines are printed 41 | /// 42 | optional grid_lines_set; 43 | 44 | /// 45 | /// print row and column headings 46 | /// 47 | optional print_headings; 48 | 49 | /// 50 | /// center on page horizontally 51 | /// 52 | optional horizontal_centered; 53 | 54 | /// 55 | /// center on page vertically 56 | /// 57 | optional vertical_centered; 58 | }; 59 | 60 | inline bool operator==(const print_options &lhs, const print_options &rhs) 61 | { 62 | return lhs.grid_lines_set == rhs.grid_lines_set 63 | && lhs.horizontal_centered == rhs.horizontal_centered 64 | && lhs.print_grid_lines == rhs.print_grid_lines 65 | && lhs.print_headings == rhs.print_headings 66 | && lhs.vertical_centered == rhs.vertical_centered; 67 | } 68 | 69 | inline bool operator!=(const print_options &lhs, const print_options &rhs) 70 | { 71 | return !(lhs == rhs); 72 | } 73 | } // namespace xlnt 74 | -------------------------------------------------------------------------------- /benchmarks/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1...3.31) 2 | project(xlnt.benchmarks) 3 | 4 | set(CMAKE_CXX_STANDARD ${XLNT_CXX_LANG}) 5 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 6 | set(CMAKE_C_STANDARD ${XLNT_C_LANG}) 7 | set(CMAKE_C_STANDARD_REQUIRED ON) 8 | set(CXX_EXTENSIONS OFF) 9 | 10 | if(NOT COMBINED_PROJECT) 11 | # Include xlnt library 12 | add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../source ${CMAKE_CURRENT_BINARY_DIR}/source) 13 | endif() 14 | 15 | if(STATIC_CRT) 16 | include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/ucm.cmake) 17 | ucm_set_runtime(STATIC) 18 | endif() 19 | 20 | set(XLNT_BENCHMARK_DATA_DIR ${CMAKE_CURRENT_SOURCE_DIR}/data) 21 | 22 | file(GLOB BENCHMARK_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) 23 | 24 | if(COVERAGE AND STATIC) 25 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage") 26 | endif() 27 | 28 | foreach(BENCHMARK_SOURCE IN ITEMS ${BENCHMARK_SOURCES}) 29 | # Convert .cpp to benchmark- 30 | get_filename_component(BENCHMARK_NAME ${BENCHMARK_SOURCE} NAME_WE) 31 | set(BENCHMARK_EXECUTABLE benchmark-${BENCHMARK_NAME}) 32 | 33 | add_executable(${BENCHMARK_EXECUTABLE} ${BENCHMARK_SOURCE}) 34 | 35 | target_link_libraries(${BENCHMARK_EXECUTABLE} PRIVATE xlnt) 36 | # Need to use some test helpers 37 | target_include_directories(${BENCHMARK_EXECUTABLE} 38 | PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../tests) 39 | # Some helpers also need further internal includes 40 | target_include_directories(${BENCHMARK_EXECUTABLE} 41 | PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../source) 42 | target_compile_definitions(${BENCHMARK_EXECUTABLE} 43 | PRIVATE XLNT_BENCHMARK_DATA_DIR="${XLNT_BENCHMARK_DATA_DIR}") 44 | 45 | if (XLNT_USE_LOCALE_COMMA_DECIMAL_SEPARATOR) 46 | target_compile_definitions(${BENCHMARK_EXECUTABLE} PRIVATE XLNT_USE_LOCALE_COMMA_DECIMAL_SEPARATOR=1) 47 | endif() 48 | target_compile_definitions(${BENCHMARK_EXECUTABLE} PRIVATE XLNT_LOCALE_COMMA_DECIMAL_SEPARATOR="${XLNT_LOCALE_COMMA_DECIMAL_SEPARATOR}") 49 | 50 | if (XLNT_USE_LOCALE_ARABIC_DECIMAL_SEPARATOR) 51 | target_compile_definitions(${BENCHMARK_EXECUTABLE} PRIVATE XLNT_USE_LOCALE_ARABIC_DECIMAL_SEPARATOR=1) 52 | endif() 53 | target_compile_definitions(${BENCHMARK_EXECUTABLE} PRIVATE XLNT_LOCALE_ARABIC_DECIMAL_SEPARATOR="${XLNT_LOCALE_ARABIC_DECIMAL_SEPARATOR}") 54 | 55 | 56 | if(MSVC AND NOT STATIC) 57 | # Copy xlnt DLL into benchmarks directory 58 | add_custom_command(TARGET ${BENCHMARK_EXECUTABLE} POST_BUILD 59 | COMMAND ${CMAKE_COMMAND} -E copy_if_different 60 | $ 61 | $) 62 | endif() 63 | endforeach() 64 | 65 | option(XLNT_MICROBENCH_ENABLED "Enable small benchmarks typically used for development" OFF) 66 | if (XLNT_MICROBENCH_ENABLED) 67 | add_subdirectory(microbenchmarks) 68 | endif() 69 | -------------------------------------------------------------------------------- /include/xlnt/internal/format_impl_ptr.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 xlnt-community 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE 20 | // 21 | // @license: http://www.opensource.org/licenses/mit-license.php 22 | // @author: see AUTHORS file 23 | 24 | #pragma once 25 | 26 | namespace xlnt { 27 | namespace detail { 28 | 29 | struct format_impl; 30 | 31 | class XLNT_API format_impl_ptr 32 | { 33 | public: 34 | format_impl_ptr() = default; 35 | format_impl_ptr(const format_impl_ptr& r) : format_(r.format_) {increment();} 36 | format_impl_ptr(format_impl_ptr&& r) : format_(r.format_) {r.format_ = nullptr;} 37 | format_impl_ptr(format_impl *format) : format_(format) {increment();} 38 | ~format_impl_ptr() {decrement();} 39 | 40 | format_impl_ptr& operator=(const format_impl_ptr& r) 41 | { 42 | if (this == &r) 43 | return *this; 44 | 45 | decrement(); 46 | format_ = r.format_; 47 | increment(); 48 | return *this; 49 | } 50 | 51 | format_impl_ptr& operator=(format_impl_ptr&& r) 52 | { 53 | decrement(); 54 | format_ = r.format_; 55 | r.format_ = nullptr; 56 | return *this; 57 | } 58 | 59 | std::size_t use_count () const; 60 | 61 | bool is_set () const {return format_ != nullptr;} 62 | void clear () {operator=(nullptr);} 63 | 64 | format_impl *get() const {return format_;} 65 | format_impl *operator->() const {return get();} 66 | operator format_impl *() const {return get();} 67 | 68 | bool operator== (const format_impl_ptr& r) const {return format_ == r.format_;} 69 | bool operator== (format_impl *format) const {return format_ == format;} 70 | 71 | protected: 72 | void increment(); 73 | void decrement(); 74 | 75 | protected: 76 | format_impl *format_ = nullptr; 77 | }; 78 | 79 | } // namespace detail 80 | } // namespace xlnt -------------------------------------------------------------------------------- /include/xlnt/utils/timedelta.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #pragma once 26 | 27 | #include 28 | 29 | namespace xlnt { 30 | 31 | /// 32 | /// Represents a span of time between two datetimes. This is 33 | /// not fully supported yet throughout the library. 34 | /// 35 | struct XLNT_API timedelta 36 | { 37 | /// 38 | /// Returns a timedelta from a number representing the factional number of days elapsed. 39 | /// 40 | static timedelta from_number(double number); 41 | 42 | /// 43 | /// Constructs a timedelta equal to zero. 44 | /// 45 | timedelta(); 46 | 47 | /// 48 | /// Constructs a timedelta from a number of days, hours, minutes, seconds, and microseconds. 49 | /// 50 | timedelta(int days_, int hours_, int minutes_, int seconds_, int microseconds_); 51 | 52 | /// 53 | /// Returns a numeric representation of this timedelta as a fractional number of days. 54 | /// 55 | double to_number() const; 56 | 57 | /// 58 | /// The days 59 | /// 60 | int days; 61 | 62 | /// 63 | /// The hours 64 | /// 65 | int hours; 66 | 67 | /// 68 | /// The minutes 69 | /// 70 | int minutes; 71 | 72 | /// 73 | /// The seconds 74 | /// 75 | int seconds; 76 | 77 | /// 78 | /// The microseconds 79 | /// 80 | int microseconds; 81 | }; 82 | 83 | } // namespace xlnt 84 | -------------------------------------------------------------------------------- /tests/styles/conditional_format_test_suite.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | class conditional_format_test_suite : public test_suite 30 | { 31 | public: 32 | conditional_format_test_suite() 33 | { 34 | register_test(test_all); 35 | } 36 | 37 | void test_all() 38 | { 39 | xlnt::workbook wb; 40 | auto ws = wb.active_sheet(); 41 | auto format = ws.conditional_format(xlnt::range_reference("A1:A10"), xlnt::condition::text_contains("test")); 42 | xlnt_assert(!format.has_border()); 43 | xlnt_assert(!format.has_fill()); 44 | xlnt_assert(!format.has_font()); 45 | // set border 46 | auto border = xlnt::border().diagonal(xlnt::diagonal_direction::both); 47 | format.border(border); 48 | xlnt_assert(format.has_border()); 49 | xlnt_assert_equals(format.border(), border); 50 | // set fill 51 | auto fill = xlnt::fill(xlnt::gradient_fill().type(xlnt::gradient_fill_type::path)); 52 | format.fill(fill); 53 | xlnt_assert(format.has_fill()); 54 | xlnt_assert_equals(format.fill(), fill); 55 | // set font 56 | auto font = xlnt::font().color(xlnt::color::darkblue()); 57 | format.font(font); 58 | xlnt_assert(format.has_font()); 59 | xlnt_assert_equals(format.font(), font); 60 | // copy ctor 61 | auto format_copy(format); 62 | xlnt_assert_equals(format, format_copy); 63 | } 64 | }; 65 | static conditional_format_test_suite x; 66 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to xlnt 2 | 3 | xlnt welcomes contributions from everyone regardless of skill level (provided you can write C++ or documentation). 4 | 5 | ## Getting Started 6 | 7 | Look through the list of issues to find something interesting to work on. Help is appreciated with any issues, but important timely issues are labeled as "help wanted". Issues labeled "docs" might be good for those who want to contribute without having to know too much C++. You might also find something that the code is missing without an associated issue. That's fine to work on to, but it might be best to make an issue first in case someone else is working on it. 8 | 9 | The XLSX format is described in [ECMA 376 5th edition](https://ecma-international.org/publications-and-standards/standards/ecma-376/). Part 1 contains the most relevant information: 10 | 11 | - A PDF with all information, especially section "18. SpreadsheetML Reference Material" may be useful. Using the outline of this section allows you to navigate to all the relevant parts of the XLSX format. 12 | - OfficeOpenXml-XMLSCHEMA-Strict.zip > sml.xsd: contains the xsd specification of the XLSX format. This information is also available in the PDF in annex A.2 SpreadsheetML. 13 | 14 | ## Contributions 15 | 16 | Contributions to xlnt should be made in the form of pull requests on GitHub. Each pull request will be reviewed and either merged into the current development branch or given feedback for changes that would be required to do so. 17 | 18 | All code in this repository is under the MIT License. You should agree to these terms before submitting any code to xlnt. 19 | 20 | ## Pull Request Checklist 21 | 22 | - Branch from the head of the current development branch. Until version 1.0 is released, this the master branch. 23 | 24 | - Commits should be as small as possible, while ensuring that each commit is correct independently (i.e. each commit should compile and pass all tests). Commits that don't follow the coding style indicated in .clang-format (e.g. indentation) are less likely to be accepted until they are fixed. 25 | 26 | - If your pull request is not getting reviewed or you need a specific person to review it, you can @-reply a reviewer asking for a review in the pull request or a comment. 27 | 28 | - Add tests relevant to the fixed defect or new feature. It's best to do this before making any changes, make sure that the tests fail, then make changes ensuring that it ultimately passes the tests (i.e. TDD). xlnt uses cxxtest for testing. Tests are contained in a tests directory inside each module (e.g. source/workbook/tests/test_workbook.hpp) in the form of a header file. Each test is a separate function with a name that starts like "test_". See http://cxxtest.com/guide.html for information about CxxTest or take a look at existing tests. 29 | 30 | ## Conduct 31 | 32 | Just try to be nice--we're all volunteers here. 33 | 34 | ## Communication 35 | 36 | Add a comment to an existing issue on GitHub, open a new issue for defects or feature requests, or contact @m7913d or @doomlaur if you want. 37 | -------------------------------------------------------------------------------- /include/xlnt/worksheet/column_properties.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2010-2015 openpyxl 3 | // Copyright (c) 2024-2025 xlnt-community 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE 22 | // 23 | // @license: http://www.opensource.org/licenses/mit-license.php 24 | // @author: see AUTHORS file 25 | 26 | #pragma once 27 | 28 | #include 29 | 30 | #include 31 | #include 32 | 33 | namespace xlnt { 34 | 35 | /// 36 | /// Properties applied to a column in a worksheet. 37 | /// Columns can have a size and a style. 38 | /// 39 | class XLNT_API column_properties 40 | { 41 | public: 42 | /// 43 | /// The optional width of the column 44 | /// 45 | optional width; 46 | 47 | /// 48 | /// If true, this is a custom width 49 | /// 50 | bool custom_width = false; 51 | 52 | /// 53 | /// The style index of this column. This shouldn't be used since style indices 54 | /// aren't supposed to be used directly in xlnt. (TODO) 55 | /// 56 | optional style; 57 | 58 | /// 59 | /// Is this column sized to fit its content as best it can 60 | /// serialise if true 61 | /// 62 | bool best_fit = false; 63 | 64 | /// 65 | /// If true, this column will be hidden 66 | /// 67 | bool hidden = false; 68 | }; 69 | 70 | inline bool operator==(const column_properties &lhs, const column_properties &rhs) 71 | { 72 | return lhs.width == rhs.width 73 | && lhs.custom_width == rhs.custom_width 74 | && lhs.style == rhs.style 75 | && lhs.best_fit == rhs.best_fit 76 | && lhs.hidden == rhs.hidden; 77 | } 78 | 79 | inline bool operator!=(const column_properties &lhs, const column_properties &rhs) 80 | { 81 | return !(lhs == rhs); 82 | } 83 | 84 | } // namespace xlnt 85 | -------------------------------------------------------------------------------- /tests/styles/style_test_suite.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | class style_test_suite : public test_suite 30 | { 31 | public: 32 | style_test_suite() 33 | { 34 | register_test(test_all); 35 | } 36 | 37 | void test_all() 38 | { 39 | xlnt::workbook wb; 40 | auto test_style = wb.create_style("test_style"); 41 | test_style.number_format(xlnt::number_format::date_ddmmyyyy()); 42 | 43 | auto copy_style(test_style); 44 | xlnt_assert_equals(test_style, copy_style); 45 | 46 | // number format 47 | xlnt_assert_equals(copy_style.name(), "test_style"); 48 | xlnt_assert_equals(copy_style.number_format(), xlnt::number_format::date_ddmmyyyy()); 49 | //xlnt_assert(!copy_style.number_format_applied()); // this doesn't seem to have sensible behaviour? 50 | copy_style.number_format(xlnt::number_format::date_datetime(), true); // true applied param 51 | xlnt_assert_equals(copy_style.number_format(), xlnt::number_format::date_datetime()); 52 | xlnt_assert(copy_style.number_format_applied()); 53 | copy_style.number_format(xlnt::number_format::date_dmminus(), false); // false applied param 54 | xlnt_assert_equals(copy_style.number_format(), xlnt::number_format::date_dmminus()); 55 | xlnt_assert(!copy_style.number_format_applied()); 56 | 57 | xlnt_assert(!copy_style.pivot_button()); 58 | copy_style.pivot_button(true); 59 | xlnt_assert(copy_style.pivot_button()); 60 | 61 | xlnt_assert(!copy_style.quote_prefix()); 62 | copy_style.quote_prefix(true); 63 | xlnt_assert(copy_style.quote_prefix()); 64 | } 65 | }; 66 | static style_test_suite x; 67 | -------------------------------------------------------------------------------- /docs/advanced/Properties.md: -------------------------------------------------------------------------------- 1 | # Properties 2 | 3 | ```c++ 4 | xlnt::workbook wb; 5 | 6 | wb.core_property(xlnt::core_property::category, "hors categorie"); 7 | wb.core_property(xlnt::core_property::content_status, "good"); 8 | wb.core_property(xlnt::core_property::created, xlnt::datetime(2017, 1, 15)); 9 | wb.core_property(xlnt::core_property::creator, "me"); 10 | wb.core_property(xlnt::core_property::description, "description"); 11 | wb.core_property(xlnt::core_property::identifier, "id"); 12 | wb.core_property(xlnt::core_property::keywords, { "wow", "such" }); 13 | wb.core_property(xlnt::core_property::language, "Esperanto"); 14 | wb.core_property(xlnt::core_property::last_modified_by, "someone"); 15 | wb.core_property(xlnt::core_property::last_printed, xlnt::datetime(2017, 1, 15)); 16 | wb.core_property(xlnt::core_property::modified, xlnt::datetime(2017, 1, 15)); 17 | wb.core_property(xlnt::core_property::revision, "3"); 18 | wb.core_property(xlnt::core_property::subject, "subject"); 19 | wb.core_property(xlnt::core_property::title, "title"); 20 | wb.core_property(xlnt::core_property::version, "1.0"); 21 | 22 | wb.extended_property(xlnt::extended_property::application, "xlnt"); 23 | wb.extended_property(xlnt::extended_property::app_version, "0.9.3"); 24 | wb.extended_property(xlnt::extended_property::characters, 123); 25 | wb.extended_property(xlnt::extended_property::characters_with_spaces, 124); 26 | wb.extended_property(xlnt::extended_property::company, "Incorporated Inc."); 27 | wb.extended_property(xlnt::extended_property::dig_sig, "?"); 28 | wb.extended_property(xlnt::extended_property::doc_security, 0); 29 | wb.extended_property(xlnt::extended_property::heading_pairs, true); 30 | wb.extended_property(xlnt::extended_property::hidden_slides, false); 31 | wb.extended_property(xlnt::extended_property::h_links, 0); 32 | wb.extended_property(xlnt::extended_property::hyperlink_base, 0); 33 | wb.extended_property(xlnt::extended_property::hyperlinks_changed, true); 34 | wb.extended_property(xlnt::extended_property::lines, 42); 35 | wb.extended_property(xlnt::extended_property::links_up_to_date, false); 36 | wb.extended_property(xlnt::extended_property::manager, "johnny"); 37 | wb.extended_property(xlnt::extended_property::m_m_clips, "?"); 38 | wb.extended_property(xlnt::extended_property::notes, "note"); 39 | wb.extended_property(xlnt::extended_property::pages, 19); 40 | wb.extended_property(xlnt::extended_property::paragraphs, 18); 41 | wb.extended_property(xlnt::extended_property::presentation_format, "format"); 42 | wb.extended_property(xlnt::extended_property::scale_crop, true); 43 | wb.extended_property(xlnt::extended_property::shared_doc, false); 44 | wb.extended_property(xlnt::extended_property::slides, 17); 45 | wb.extended_property(xlnt::extended_property::template_, "template!"); 46 | wb.extended_property(xlnt::extended_property::titles_of_parts, { "title" }); 47 | wb.extended_property(xlnt::extended_property::total_time, 16); 48 | wb.extended_property(xlnt::extended_property::words, 101); 49 | 50 | wb.custom_property("test", { 1, 2, 3 }); 51 | wb.custom_property("Editor", "John Smith"); 52 | 53 | wb.save("lots_of_properties.xlsx"); 54 | ``` -------------------------------------------------------------------------------- /tests/utils/path_test_suite.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | class path_test_suite : public test_suite 32 | { 33 | public: 34 | path_test_suite() 35 | { 36 | register_test(test_exists); 37 | #ifdef _MSC_VER 38 | register_test(test_msvc_empty_path_wide); 39 | #endif 40 | register_test(test_append); 41 | #if XLNT_HAS_FEATURE(U8_STRING_VIEW) 42 | register_test(test_append_u8); 43 | #endif 44 | } 45 | 46 | void test_exists() 47 | { 48 | temporary_file temp; 49 | 50 | if (temp.get_path().exists()) 51 | { 52 | path_helper::delete_file(temp.get_path()); 53 | } 54 | 55 | xlnt_assert(!temp.get_path().exists()); 56 | std::ofstream stream(temp.get_path().string()); 57 | xlnt_assert(temp.get_path().exists()); 58 | } 59 | 60 | #ifdef _MSC_VER 61 | void test_msvc_empty_path_wide() 62 | { 63 | xlnt::path empty_path; 64 | std::wstring path_wide; 65 | xlnt_assert_throws_nothing(path_wide = empty_path.wstring()); 66 | xlnt_assert(path_wide.empty()); 67 | } 68 | #endif 69 | 70 | void test_append() 71 | { 72 | xlnt::path path("hello"); 73 | path = path.append("world"); 74 | xlnt_assert_equals(path.string(), "hello/world"); 75 | } 76 | 77 | #if XLNT_HAS_FEATURE(U8_STRING_VIEW) 78 | void test_append_u8() 79 | { 80 | xlnt::path path(u8"🤔🥳😇"); 81 | path = path.append(u8"🍕🍟🍔"); 82 | xlnt_assert_equals(path.string(), XLNT_TEST_U8_TO_CHAR_PTR(u8"🤔🥳😇/🍕🍟🍔")); 83 | } 84 | #endif 85 | 86 | }; 87 | static path_test_suite x; 88 | -------------------------------------------------------------------------------- /source/worksheet/page_margins.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2010-2015 openpyxl 3 | // Copyright (c) 2024-2025 xlnt-community 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE 22 | // 23 | // @license: http://www.opensource.org/licenses/mit-license.php 24 | // @author: see AUTHORS file 25 | #include 26 | #include 27 | 28 | namespace xlnt { 29 | 30 | page_margins::page_margins() 31 | { 32 | } 33 | 34 | double page_margins::top() const 35 | { 36 | return top_; 37 | } 38 | 39 | void page_margins::top(double top) 40 | { 41 | top_ = top; 42 | } 43 | 44 | double page_margins::left() const 45 | { 46 | return left_; 47 | } 48 | 49 | void page_margins::left(double left) 50 | { 51 | left_ = left; 52 | } 53 | 54 | double page_margins::bottom() const 55 | { 56 | return bottom_; 57 | } 58 | 59 | void page_margins::bottom(double bottom) 60 | { 61 | bottom_ = bottom; 62 | } 63 | 64 | double page_margins::right() const 65 | { 66 | return right_; 67 | } 68 | 69 | void page_margins::right(double right) 70 | { 71 | right_ = right; 72 | } 73 | 74 | double page_margins::header() const 75 | { 76 | return header_; 77 | } 78 | 79 | void page_margins::header(double header) 80 | { 81 | header_ = header; 82 | } 83 | 84 | double page_margins::footer() const 85 | { 86 | return footer_; 87 | } 88 | 89 | void page_margins::footer(double footer) 90 | { 91 | footer_ = footer; 92 | } 93 | 94 | bool page_margins::operator==(const page_margins &rhs) const 95 | { 96 | return detail::float_equals(top_, rhs.top_) 97 | && detail::float_equals(left_, rhs.left_) 98 | && detail::float_equals(right_, rhs.right_) 99 | && detail::float_equals(header_, rhs.header_) 100 | && detail::float_equals(footer_, rhs.footer_); 101 | } 102 | 103 | bool page_margins::operator!=(const page_margins &rhs) const 104 | { 105 | return !(*this == rhs); 106 | } 107 | 108 | } // namespace xlnt 109 | -------------------------------------------------------------------------------- /include/xlnt/packaging/ext_list.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #pragma once 26 | 27 | #include 28 | #include 29 | 30 | #include 31 | #include 32 | 33 | namespace xml { 34 | class parser; 35 | class serializer; 36 | } // namespace xml 37 | 38 | namespace xlnt { 39 | 40 | /// 41 | /// A list of xml extensions that may or may not be understood by the parser 42 | /// preservation is required for round-tripping even if extension is not understood 43 | /// [serialised: extLst] 44 | /// 45 | class XLNT_API ext_list 46 | { 47 | public: 48 | struct ext 49 | { 50 | ext(xml::parser &parser, const std::string &ns); 51 | ext(const uri &ID, const std::string &serialised); 52 | void serialise(xml::serializer &serialiser, const std::string &ns); 53 | 54 | uri extension_ID_; 55 | std::string serialised_value_; 56 | }; 57 | ext_list() = default; // default ctor required by xlnt::optional 58 | explicit ext_list(xml::parser &parser, const std::string &ns); 59 | void serialize(xml::serializer &serialiser, const std::string &ns); 60 | 61 | void add_extension(const uri &ID, const std::string &element); 62 | 63 | bool has_extension(const uri &extension_uri) const; 64 | 65 | const ext &extension(const uri &extension_uri) const; 66 | 67 | const std::vector &extensions() const; 68 | 69 | bool operator==(const ext_list &rhs) const; 70 | 71 | bool operator!=(const ext_list &rhs) const; 72 | 73 | private: 74 | std::vector extensions_; 75 | }; 76 | 77 | inline bool operator==(const ext_list::ext &lhs, const ext_list::ext &rhs) 78 | { 79 | return lhs.extension_ID_ == rhs.extension_ID_ 80 | && lhs.serialised_value_ == rhs.serialised_value_; 81 | } 82 | 83 | inline bool operator!=(const ext_list::ext &lhs, const ext_list::ext &rhs) 84 | { 85 | return !(lhs == rhs); 86 | } 87 | } // namespace xlnt 88 | -------------------------------------------------------------------------------- /third-party/libstudxml.build/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1...3.31) 2 | project(libstudxml) 3 | 4 | # Require C++11 compiler 5 | set(CMAKE_CXX_STANDARD 11) 6 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 7 | 8 | set(LIBSTUDXML_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../libstudxml) 9 | set(LIBSTUDXML_INCLUDE_DIR ${LIBSTUDXML_ROOT_DIR}/../libstudxml) 10 | 11 | if(STATIC_CRT) 12 | include(${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/ucm.cmake) 13 | ucm_set_runtime(STATIC) 14 | endif() 15 | 16 | set(LIBSTUDXML 17 | ${LIBSTUDXML_ROOT_DIR}/libstudxml/parser.cxx 18 | ${LIBSTUDXML_ROOT_DIR}/libstudxml/qname.cxx 19 | ${LIBSTUDXML_ROOT_DIR}/libstudxml/serializer.cxx 20 | ${LIBSTUDXML_ROOT_DIR}/libstudxml/value-traits.cxx 21 | ${LIBSTUDXML_ROOT_DIR}/libstudxml/content.hxx 22 | ${LIBSTUDXML_ROOT_DIR}/libstudxml/exception.hxx 23 | ${LIBSTUDXML_ROOT_DIR}/libstudxml/forward.hxx 24 | ${LIBSTUDXML_ROOT_DIR}/libstudxml/parser 25 | ${LIBSTUDXML_ROOT_DIR}/libstudxml/qname 26 | ${LIBSTUDXML_ROOT_DIR}/libstudxml/serializer 27 | ${LIBSTUDXML_ROOT_DIR}/libstudxml/value-traits) 28 | 29 | set(GENX 30 | ${LIBSTUDXML_ROOT_DIR}/libstudxml/details/genx/char-props.c 31 | ${LIBSTUDXML_ROOT_DIR}/libstudxml/details/genx/genx.c 32 | ${LIBSTUDXML_ROOT_DIR}/libstudxml/details/genx/genx.h) 33 | 34 | set(EXPAT 35 | ${LIBSTUDXML_ROOT_DIR}/libstudxml/details/expat/xmlparse.c 36 | ${LIBSTUDXML_ROOT_DIR}/libstudxml/details/expat/xmlrole.c 37 | ${LIBSTUDXML_ROOT_DIR}/libstudxml/details/expat/xmltok.c 38 | ${LIBSTUDXML_ROOT_DIR}/libstudxml/details/expat/ascii.h 39 | ${LIBSTUDXML_ROOT_DIR}/libstudxml/details/expat/asciitab.h 40 | ${LIBSTUDXML_ROOT_DIR}/libstudxml/details/expat/config.h 41 | ${LIBSTUDXML_ROOT_DIR}/libstudxml/details/expat/expat_external.h 42 | ${LIBSTUDXML_ROOT_DIR}/libstudxml/details/expat/expat.h 43 | ${LIBSTUDXML_ROOT_DIR}/libstudxml/details/expat/iasciitab.h 44 | ${LIBSTUDXML_ROOT_DIR}/libstudxml/details/expat/internal.h 45 | ${LIBSTUDXML_ROOT_DIR}/libstudxml/details/expat/latin1tab.h 46 | ${LIBSTUDXML_ROOT_DIR}/libstudxml/details/expat/nametab.h 47 | ${LIBSTUDXML_ROOT_DIR}/libstudxml/details/expat/utf8tab.h 48 | ${LIBSTUDXML_ROOT_DIR}/libstudxml/details/expat/xmlrole.h 49 | ${LIBSTUDXML_ROOT_DIR}/libstudxml/details/expat/xmltok_impl.h 50 | ${LIBSTUDXML_ROOT_DIR}/libstudxml/details/expat/xmltok.h) 51 | 52 | add_library(libstudxml OBJECT ${LIBSTUDXML} ${GENX} ${EXPAT}) 53 | 54 | target_compile_definitions(libstudxml PUBLIC LIBSTUDXML_STATIC_LIB=1) 55 | target_include_directories(libstudxml 56 | PUBLIC ${LIBSTUDXML_ROOT_DIR} 57 | PUBLIC ${EXPAT_INCLUDE_DIRS}) 58 | 59 | if(STATIC) 60 | target_compile_definitions(libstudxml PUBLIC XML_STATIC=1) 61 | endif() 62 | 63 | # Prevent warning C4996 caused by strcpy, strncpy, sprintf in genx 64 | # TODO: would it be better to define this only in genx.c? 65 | if(MSVC) 66 | target_compile_definitions(libstudxml PRIVATE _CRT_SECURE_NO_WARNINGS=1) 67 | endif() 68 | 69 | # Build with -fPIC when xlnt is a shared library 70 | # TODO: is this still necessary? try removing 71 | if(NOT STATIC) 72 | set_target_properties(libstudxml PROPERTIES POSITION_INDEPENDENT_CODE 1) 73 | endif() 74 | 75 | # When xlnt is a static library, assume expat will be linked statically too 76 | # TODO: is this a valid assumption? 77 | if(STATIC) 78 | target_compile_definitions(libstudxml PUBLIC XML_STATIC=1) 79 | endif() 80 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at thomas.fussell@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /source/cell/comment.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2010-2015 openpyxl 3 | // Copyright (c) 2024-2025 xlnt-community 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE 22 | // 23 | // @license: http://www.opensource.org/licenses/mit-license.php 24 | // @author: see AUTHORS file 25 | #include 26 | 27 | namespace xlnt { 28 | 29 | comment::comment() 30 | : comment("", "") 31 | { 32 | } 33 | 34 | comment::comment(const rich_text &text, const std::string &author) 35 | : text_(text), author_(author) 36 | { 37 | } 38 | 39 | comment::comment(const std::string &text, const std::string &author) 40 | : text_(), author_(author) 41 | { 42 | text_.plain_text(text, false); 43 | } 44 | 45 | rich_text comment::text() const 46 | { 47 | return text_; 48 | } 49 | 50 | std::string comment::plain_text() const 51 | { 52 | return text_.plain_text(); 53 | } 54 | 55 | std::string comment::author() const 56 | { 57 | return author_; 58 | } 59 | 60 | void comment::hide() 61 | { 62 | visible_ = false; 63 | } 64 | 65 | void comment::show() 66 | { 67 | visible_ = true; 68 | } 69 | 70 | void comment::position(int left, int top) 71 | { 72 | left_ = left; 73 | top_ = top; 74 | } 75 | 76 | void comment::size(int width, int height) 77 | { 78 | width_ = width; 79 | height_ = height; 80 | } 81 | 82 | bool comment::visible() const 83 | { 84 | return visible_; 85 | } 86 | 87 | int comment::left() const 88 | { 89 | return left_; 90 | } 91 | 92 | int comment::top() const 93 | { 94 | return top_; 95 | } 96 | 97 | int comment::width() const 98 | { 99 | return width_; 100 | } 101 | 102 | int comment::height() const 103 | { 104 | return height_; 105 | } 106 | 107 | bool comment::operator==(const comment &other) const 108 | { 109 | // not comparing top/left as this is set on a per cell basis 110 | return text_ == other.text_ 111 | && author_ == other.author_ 112 | && width_ == other.width_ 113 | && height_ == other.height_; 114 | } 115 | 116 | bool comment::operator!=(const comment &other) const 117 | { 118 | return !(*this == other); 119 | } 120 | 121 | } // namespace xlnt 122 | -------------------------------------------------------------------------------- /tests/styles/color_test_suite.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2022 Thomas Fussell 2 | // Copyright (c) 2024-2025 xlnt-community 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE 21 | // 22 | // @license: http://www.opensource.org/licenses/mit-license.php 23 | // @author: see AUTHORS file 24 | 25 | #include 26 | 27 | #include 28 | 29 | class color_test_suite : public test_suite 30 | { 31 | public: 32 | color_test_suite() 33 | { 34 | register_test(test_known_colors); 35 | register_test(test_non_rgb_colors); 36 | } 37 | 38 | void test_known_colors() 39 | { 40 | const std::vector> known_colors{ 41 | {xlnt::color::black(), "FF000000"}, 42 | {xlnt::color::white(), "FFFFFFFF"}, 43 | {xlnt::color::red(), "FFFF0000"}, 44 | {xlnt::color::darkred(), "FF8B0000"}, 45 | {xlnt::color::blue(), "FF0000FF"}, 46 | {xlnt::color::darkblue(), "FF00008B"}, 47 | {xlnt::color::green(), "FF00FF00"}, 48 | {xlnt::color::darkgreen(), "FF008B00"}, 49 | {xlnt::color::yellow(), "FFFFFF00"}, 50 | {xlnt::color::darkyellow(), "FFCCCC00"}}; 51 | 52 | for (auto pair : known_colors) 53 | { 54 | xlnt_assert_equals(pair.first.rgb().hex_string(), pair.second); 55 | } 56 | } 57 | 58 | void test_non_rgb_colors() 59 | { 60 | xlnt::color indexed = xlnt::indexed_color(1); 61 | xlnt_assert(!indexed.auto_()); 62 | xlnt_assert_equals(indexed.indexed().index(), 1); 63 | indexed.indexed().index(2); 64 | xlnt_assert_equals(indexed.indexed().index(), 2); 65 | xlnt_assert_throws(indexed.theme(), xlnt::invalid_attribute); 66 | xlnt_assert_throws(indexed.rgb(), xlnt::invalid_attribute); 67 | 68 | xlnt::color theme = xlnt::theme_color(3); 69 | xlnt_assert(!theme.auto_()); 70 | xlnt_assert_equals(theme.theme().index(), 3); 71 | theme.theme().index(4); 72 | xlnt_assert_equals(theme.theme().index(), 4); 73 | xlnt_assert_throws(theme.indexed(), xlnt::invalid_attribute); 74 | xlnt_assert_throws(theme.rgb(), xlnt::invalid_attribute); 75 | } 76 | }; 77 | static color_test_suite x; 78 | --------------------------------------------------------------------------------