diff --git a/include/xlnt/cell/text.hpp b/include/xlnt/cell/text.hpp index 33dd9395..d1bc66b0 100644 --- a/include/xlnt/cell/text.hpp +++ b/include/xlnt/cell/text.hpp @@ -38,9 +38,11 @@ public: void clear(); void set_plain_string(const std::string &s); std::string get_plain_string() const; - std::vector get_runs(); + std::vector get_runs() const; void add_run(const text_run &t); void set_run(const std::vector &parts); + + bool operator==(const text &rhs) const; private: std::vector runs_; diff --git a/include/xlnt/cell/text_run.hpp b/include/xlnt/cell/text_run.hpp index 68d456c8..24337d2f 100644 --- a/include/xlnt/cell/text_run.hpp +++ b/include/xlnt/cell/text_run.hpp @@ -33,12 +33,26 @@ class XLNT_CLASS text_run public: text_run(); text_run(const std::string &string); + + bool has_formatting() const; std::string get_string() const; void set_string(const std::string &string); + + std::size_t get_size() const; + std::string get_color() const; + std::string get_font() const; + std::size_t get_family() const; + std::string get_scheme() const; private: std::string string_; + bool has_formatting_ = false; + std::size_t size_; + std::string color_; + std::string font_; + std::size_t family_; + std::string scheme_; }; } // namespace xlnt diff --git a/include/xlnt/serialization/shared_strings_serializer.hpp b/include/xlnt/serialization/shared_strings_serializer.hpp index 2a405c69..8ced3b37 100644 --- a/include/xlnt/serialization/shared_strings_serializer.hpp +++ b/include/xlnt/serialization/shared_strings_serializer.hpp @@ -23,13 +23,13 @@ // @author: see AUTHORS file #pragma once -#include #include #include namespace xlnt { +class text; class xml_document; /// @@ -38,8 +38,8 @@ class xml_document; class XLNT_CLASS shared_strings_serializer { public: - static bool read_shared_strings(const xml_document &xml, std::vector &strings); - static xml_document write_shared_strings(const std::vector &strings); + static bool read_shared_strings(const xml_document &xml, std::vector &strings); + static xml_document write_shared_strings(const std::vector &strings); }; } // namespace xlnt diff --git a/include/xlnt/workbook/workbook.hpp b/include/xlnt/workbook/workbook.hpp index 10b7429c..0351adfd 100644 --- a/include/xlnt/workbook/workbook.hpp +++ b/include/xlnt/workbook/workbook.hpp @@ -54,6 +54,7 @@ class range; class range_reference; class relationship; class style; +class text; class theme; class worksheet; class worksheet_iterator; @@ -202,9 +203,9 @@ public: const std::vector &get_root_relationships() const; - void add_shared_string(const std::string &shared, bool allow_duplicates=false); - std::vector &get_shared_strings(); - const std::vector &get_shared_strings() const; + void add_shared_string(const text &shared, bool allow_duplicates=false); + std::vector &get_shared_strings(); + const std::vector &get_shared_strings() const; void set_thumbnail(const std::vector &thumbnail); const std::vector &get_thumbnail() const; diff --git a/source/cell/cell.cpp b/source/cell/cell.cpp index c0369653..e77052d0 100644 --- a/source/cell/cell.cpp +++ b/source/cell/cell.cpp @@ -335,18 +335,6 @@ XLNT_FUNCTION void cell::set_value(long double d) d_->type_ = type::numeric; } -template <> -XLNT_FUNCTION void cell::set_value(text t) -{ - d_->value_text_ = t; - d_->type_ = type::string; - - if (!t.get_plain_string().empty()) - { - get_workbook().add_shared_string(t.get_plain_string()); - } -} - template <> XLNT_FUNCTION void cell::set_value(std::string s) { @@ -363,9 +351,13 @@ XLNT_FUNCTION void cell::set_value(std::string s) } else { - text t; - t.set_plain_string(s); - set_value(t); + d_->type_ = type::string; + d_->value_text_.set_plain_string(s); + + if (s.size() > 0) + { + get_workbook().add_shared_string(d_->value_text_); + } } if (get_workbook().get_guess_types()) @@ -374,6 +366,21 @@ XLNT_FUNCTION void cell::set_value(std::string s) } } +template <> +XLNT_FUNCTION void cell::set_value(text t) +{ + if (t.get_runs().size() == 1 && !t.get_runs().front().has_formatting()) + { + set_value(t.get_plain_string()); + } + else + { + d_->type_ = type::string; + d_->value_text_ = t; + get_workbook().add_shared_string(t); + } +} + template <> XLNT_FUNCTION void cell::set_value(char const *c) { @@ -927,6 +934,12 @@ XLNT_FUNCTION std::string cell::get_value() const return d_->value_text_.get_plain_string(); } +template <> +XLNT_FUNCTION text cell::get_value() const +{ + return d_->value_text_; +} + bool cell::has_value() const { return d_->type_ != cell::type::null; diff --git a/source/cell/text.cpp b/source/cell/text.cpp index da62331d..43a524c2 100644 --- a/source/cell/text.cpp +++ b/source/cell/text.cpp @@ -49,7 +49,8 @@ std::string text::get_plain_string() const return plain_string; } -std::vector text::get_runs() + +std::vector text::get_runs() const { return runs_; } @@ -59,4 +60,26 @@ void text::add_run(const text_run &t) runs_.push_back(t); } +bool text::operator==(const text &rhs) const +{ + if (runs_.size() != rhs.runs_.size()) return false; + + for (std::size_t i = 0; i < runs_.size(); i++) + { + if (runs_[i].get_string() != rhs.runs_[i].get_string()) return false; + if (runs_[i].has_formatting() != rhs.runs_[i].has_formatting()) return false; + + if (runs_[i].has_formatting()) + { + if (runs_[i].get_color() != rhs.runs_[i].get_color()) return false; + if (runs_[i].get_family() != rhs.runs_[i].get_family()) return false; + if (runs_[i].get_font() != rhs.runs_[i].get_font()) return false; + if (runs_[i].get_scheme() != rhs.runs_[i].get_scheme()) return false; + if (runs_[i].get_size() != rhs.runs_[i].get_size()) return false; + } + } + + return true; +} + } // namespace xlnt diff --git a/source/cell/text_run.cpp b/source/cell/text_run.cpp index 05c5ccf0..3c0c77aa 100644 --- a/source/cell/text_run.cpp +++ b/source/cell/text_run.cpp @@ -43,4 +43,34 @@ void text_run::set_string(const std::string &string) string_ = string; } +bool text_run::has_formatting() const +{ + return has_formatting_; +} + +std::size_t text_run::get_size() const +{ + return size_; +} + +std::string text_run::get_color() const +{ + return color_; +} + +std::string text_run::get_font() const +{ + return font_; +} + +std::size_t text_run::get_family() const +{ + return family_; +} + +std::string text_run::get_scheme() const +{ + return scheme_; +} + } // namespace xlnt diff --git a/source/detail/workbook_impl.hpp b/source/detail/workbook_impl.hpp index 4f481f35..fce6fc34 100644 --- a/source/detail/workbook_impl.hpp +++ b/source/detail/workbook_impl.hpp @@ -75,7 +75,7 @@ struct workbook_impl std::vector worksheets_; std::vector relationships_; std::vector root_relationships_; - std::vector shared_strings_; + std::vector shared_strings_; document_properties properties_; app_properties app_properties_; diff --git a/source/serialization/excel_serializer.cpp b/source/serialization/excel_serializer.cpp index b9ee7b76..fb2c6ae5 100644 --- a/source/serialization/excel_serializer.cpp +++ b/source/serialization/excel_serializer.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -125,12 +126,12 @@ bool load_workbook(xlnt::zip_file &archive, bool guess_types, bool data_only, xl if(archive.has_file(xlnt::constants::ArcSharedString())) { - std::vector shared_strings; + std::vector shared_strings; xlnt::xml_document shared_strings_xml; shared_strings_xml.from_string(archive.read(xlnt::constants::ArcSharedString())); xlnt::shared_strings_serializer::read_shared_strings(shared_strings_xml, shared_strings); - for (auto shared_string : shared_strings) + for (auto &shared_string : shared_strings) { wb.add_shared_string(shared_string, true); } diff --git a/source/serialization/shared_strings_serializer.cpp b/source/serialization/shared_strings_serializer.cpp index 9afce1f5..e50eb654 100644 --- a/source/serialization/shared_strings_serializer.cpp +++ b/source/serialization/shared_strings_serializer.cpp @@ -21,13 +21,15 @@ // // @license: http://www.opensource.org/licenses/mit-license.php // @author: see AUTHORS file + #include +#include #include #include namespace xlnt { -xml_document shared_strings_serializer::write_shared_strings(const std::vector &strings) +xml_document shared_strings_serializer::write_shared_strings(const std::vector &strings) { xml_document xml; @@ -39,13 +41,38 @@ xml_document shared_strings_serializer::write_shared_strings(const std::vector &strings) +bool shared_strings_serializer::read_shared_strings(const xml_document &xml, std::vector &strings) { strings.clear(); @@ -57,28 +84,34 @@ bool shared_strings_serializer::read_shared_strings(const xml_document &xml, std unique_count = std::stoull(root_node.get_attribute("uniqueCount")); } - for (const auto &si_node : root_node.get_children()) + for (const auto &string_item_node : root_node.get_children()) { - if (si_node.get_name() != "si") + if (string_item_node.get_name() != "si") { continue; } - if (si_node.has_child("t")) + if (string_item_node.has_child("t")) { - strings.push_back(si_node.get_child("t").get_text()); + text t; + t.set_plain_string(string_item_node.get_child("t").get_text()); + strings.push_back(t); } - else if (si_node.has_child("r")) // possible multiple text entities. + else if (string_item_node.has_child("r")) // possible multiple text entities. { - std::string text; - for (const auto& r_node : si_node.get_children()) + text t; + + for (const auto& rich_text_run_node : string_item_node.get_children()) { - if (r_node.get_name() == "r" && r_node.has_child("t")) + if (rich_text_run_node.get_name() == "r" && rich_text_run_node.has_child("t")) { - text += r_node.get_child("t").get_text(); + text_run run; + run.set_string(rich_text_run_node.get_child("t").get_text()); + t.add_run(run); } } - strings.push_back(std::move(text)); + + strings.push_back(t); } } diff --git a/source/serialization/tests/test_write.hpp b/source/serialization/tests/test_write.hpp index becedac3..5d6f9416 100644 --- a/source/serialization/tests/test_write.hpp +++ b/source/serialization/tests/test_write.hpp @@ -73,7 +73,7 @@ public: ws.get_cell("A3").set_value("nice"); auto content = xlnt::shared_strings_serializer::write_shared_strings(wb.get_shared_strings()); - + TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sharedStrings.xml", content)); } @@ -220,7 +220,7 @@ public: xlnt::worksheet_serializer serializer(ws); auto observed = serializer.write_worksheet(); - + auto temp = observed.to_string(); TS_ASSERT(Helper::compare_xml(PathHelper::GetDataDirectory() + "/writer/expected/sheet1_freeze_panes_horiz.xml", observed)); } diff --git a/source/serialization/worksheet_serializer.cpp b/source/serialization/worksheet_serializer.cpp index 69bdaedd..5f417d0d 100644 --- a/source/serialization/worksheet_serializer.cpp +++ b/source/serialization/worksheet_serializer.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -438,7 +439,7 @@ xml_document worksheet_serializer::write_worksheet() const for (std::size_t i = 0; i < shared_strings.size(); i++) { - if (shared_strings[i] == cell.get_value()) + if (shared_strings[i] == cell.get_value()) { match_index = static_cast(i); break; diff --git a/source/workbook/workbook.cpp b/source/workbook/workbook.cpp index a92f4e42..ef6f6eb8 100644 --- a/source/workbook/workbook.cpp +++ b/source/workbook/workbook.cpp @@ -685,17 +685,17 @@ const std::vector &workbook::get_root_relationships() const return d_->root_relationships_; } -std::vector &workbook::get_shared_strings() +std::vector &workbook::get_shared_strings() { return d_->shared_strings_; } -const std::vector &workbook::get_shared_strings() const +const std::vector &workbook::get_shared_strings() const { return d_->shared_strings_; } -void workbook::add_shared_string(const std::string &shared, bool allow_duplicates) +void workbook::add_shared_string(const text &shared, bool allow_duplicates) { if (!allow_duplicates) {