From e8dd38d0d6c7ba3b71ad354758b4d86d288b6041 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=89=91=E6=B3=A2?= <940930034@qq.com> Date: Tue, 25 Aug 2020 15:08:20 +0800 Subject: [PATCH] Fix throwing exception when duplicate shared strings occur. --- include/xlnt/workbook/workbook.hpp | 9 ++------ .../detail/implementations/workbook_impl.hpp | 2 +- source/detail/serialization/xlsx_consumer.cpp | 2 +- source/detail/serialization/xlsx_producer.cpp | 6 ++--- source/workbook/workbook.cpp | 21 ++++++------------ tests/data/Issue494_shared_string.xlsx | Bin 0 -> 15618 bytes tests/workbook/workbook_test_suite.cpp | 10 +++++++++ 7 files changed, 24 insertions(+), 26 deletions(-) create mode 100755 tests/data/Issue494_shared_string.xlsx diff --git a/include/xlnt/workbook/workbook.hpp b/include/xlnt/workbook/workbook.hpp index 00ad3710..275363fb 100644 --- a/include/xlnt/workbook/workbook.hpp +++ b/include/xlnt/workbook/workbook.hpp @@ -760,11 +760,6 @@ public: /// std::size_t add_shared_string(const rich_text &shared, bool allow_duplicates = false); - /// - /// Returns a reference to the shared string ordered by id - /// - const std::map &shared_strings_by_id() const; - /// /// Returns a reference to the shared string related to the specified index /// @@ -774,13 +769,13 @@ public: /// Returns a reference to the shared strings being used by cells /// in this workbook. /// - std::unordered_map &shared_strings(); + std::vector &shared_strings(); /// /// Returns a reference to the shared strings being used by cells /// in this workbook. /// - const std::unordered_map &shared_strings() const; + const std::vector &shared_strings() const; // Thumbnail diff --git a/source/detail/implementations/workbook_impl.hpp b/source/detail/implementations/workbook_impl.hpp index 710e13e6..76308872 100644 --- a/source/detail/implementations/workbook_impl.hpp +++ b/source/detail/implementations/workbook_impl.hpp @@ -118,7 +118,7 @@ struct workbook_impl std::list worksheets_; std::unordered_map shared_strings_ids_; - std::map shared_strings_values_; + std::vector shared_strings_values_; optional stylesheet_; diff --git a/source/detail/serialization/xlsx_consumer.cpp b/source/detail/serialization/xlsx_consumer.cpp index 62d9c418..ede14048 100644 --- a/source/detail/serialization/xlsx_consumer.cpp +++ b/source/detail/serialization/xlsx_consumer.cpp @@ -2088,7 +2088,7 @@ void xlsx_consumer::read_shared_string_table() { expect_start_element(qn("spreadsheetml", "si"), xml::content::complex); auto rt = read_rich_text(qn("spreadsheetml", "si")); - target_.add_shared_string(rt); + target_.add_shared_string(rt, true); expect_end_element(qn("spreadsheetml", "si")); } diff --git a/source/detail/serialization/xlsx_producer.cpp b/source/detail/serialization/xlsx_producer.cpp index e6683a31..db8279af 100644 --- a/source/detail/serialization/xlsx_producer.cpp +++ b/source/detail/serialization/xlsx_producer.cpp @@ -944,12 +944,12 @@ void xlsx_producer::write_shared_string_table(const relationship & /*rel*/) } write_attribute("count", string_count); - write_attribute("uniqueCount", source_.shared_strings_by_id().size()); + write_attribute("uniqueCount", source_.shared_strings().size()); - for (const auto &string : source_.shared_strings_by_id()) + for (const auto &text : source_.shared_strings()) { write_start_element(xmlns, "si"); - write_rich_text(xmlns, string.second); + write_rich_text(xmlns, text); write_end_element(xmlns, "si"); } diff --git a/source/workbook/workbook.cpp b/source/workbook/workbook.cpp index 32217224..11c7afa0 100644 --- a/source/workbook/workbook.cpp +++ b/source/workbook/workbook.cpp @@ -1348,32 +1348,25 @@ const manifest &workbook::manifest() const return d_->manifest_; } -const std::map &workbook::shared_strings_by_id() const -{ - return d_->shared_strings_values_; -} - const rich_text &workbook::shared_strings(std::size_t index) const { - auto it = d_->shared_strings_values_.find(index); - - if (it != d_->shared_strings_values_.end()) + if (index < d_->shared_strings_values_.size()) { - return it->second; + return d_->shared_strings_values_.at(index); } static rich_text empty; return empty; } -std::unordered_map &workbook::shared_strings() +std::vector &workbook::shared_strings() { - return d_->shared_strings_ids_; + return d_->shared_strings_values_; } -const std::unordered_map &workbook::shared_strings() const +const std::vector &workbook::shared_strings() const { - return d_->shared_strings_ids_; + return d_->shared_strings_values_; } std::size_t workbook::add_shared_string(const rich_text &shared, bool allow_duplicates) @@ -1392,7 +1385,7 @@ std::size_t workbook::add_shared_string(const rich_text &shared, bool allow_dupl auto sz = d_->shared_strings_ids_.size(); d_->shared_strings_ids_[shared] = sz; - d_->shared_strings_values_[sz] = shared; + d_->shared_strings_values_.push_back(shared); return sz; } diff --git a/tests/data/Issue494_shared_string.xlsx b/tests/data/Issue494_shared_string.xlsx new file mode 100755 index 0000000000000000000000000000000000000000..87d8a17d927481cddafee66df37a19dbb4cad2eb GIT binary patch literal 15618 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