diff --git a/include/xlnt/serialization/style_serializer.hpp b/include/xlnt/serialization/style_serializer.hpp index 988f2e47..5da0b181 100644 --- a/include/xlnt/serialization/style_serializer.hpp +++ b/include/xlnt/serialization/style_serializer.hpp @@ -37,6 +37,7 @@ class alignment; class border; class cell_style; class color; +class common_style; class conditional_format; class fill; class font; @@ -231,7 +232,7 @@ public: /// bool write_number_formats(xml_node &number_formats_node) const; - bool write_style_common(const alignment &style_alignment, const border &style_border, const fill &style_fill, const font &style_font, const number_format &style_number_format, const protection &style_protection, xml_node xf_node) const; + bool write_style_common(const common_style &style, xml_node xf_node) const; /// /// Build an xml tree representing the given style into style_node. diff --git a/include/xlnt/styles/alignment.hpp b/include/xlnt/styles/alignment.hpp index bb48690b..03289da3 100644 --- a/include/xlnt/styles/alignment.hpp +++ b/include/xlnt/styles/alignment.hpp @@ -56,15 +56,11 @@ public: void set_shrink_to_fit(bool shrink_to_fit); bool get_shrink_to_fit() const; - - void apply(bool value); - bool apply() const; protected: std::string to_hash_string() const override; private: - bool apply_ = false; horizontal_alignment horizontal_ = horizontal_alignment::none; vertical_alignment vertical_ = vertical_alignment::none; int text_rotation_ = 0; diff --git a/include/xlnt/styles/border.hpp b/include/xlnt/styles/border.hpp index 51df0cb0..d8679c7f 100644 --- a/include/xlnt/styles/border.hpp +++ b/include/xlnt/styles/border.hpp @@ -60,16 +60,11 @@ public: const std::experimental::optional &get_vertical() const; std::experimental::optional &get_horizontal(); const std::experimental::optional &get_horizontal() const; - - void apply(bool value); - bool apply() const; protected: std::string to_hash_string() const override; private: - bool apply_ = false; - std::experimental::optional start_; std::experimental::optional end_; std::experimental::optional left_; diff --git a/include/xlnt/styles/common_style.hpp b/include/xlnt/styles/common_style.hpp index a58be223..26837089 100644 --- a/include/xlnt/styles/common_style.hpp +++ b/include/xlnt/styles/common_style.hpp @@ -53,36 +53,48 @@ public: const alignment &get_alignment() const; void set_alignment(const alignment &new_alignment); void remove_alignment(); + bool alignment_applied() const; + void alignment_applied(bool applied); // Border border &get_border(); const border &get_border() const; void set_border(const border &new_border); void remove_border(); + bool border_applied() const; + void border_applied(bool applied); // Fill fill &get_fill(); const fill &get_fill() const; void set_fill(const fill &new_fill); void remove_fill(); + bool fill_applied() const; + void fill_applied(bool applied); // Font font &get_font(); const font &get_font() const; void set_font(const font &new_font); void remove_font(); + bool font_applied() const; + void font_applied(bool applied); // Number Format number_format &get_number_format(); const number_format &get_number_format() const; void set_number_format(const number_format &new_number_format); void remove_number_format(); + bool number_format_applied() const; + void number_format_applied(bool applied); // Protection protection &get_protection(); const protection &get_protection() const; void set_protection(const protection &new_protection); void remove_protection(); + bool protection_applied() const; + void protection_applied(bool applied); protected: std::string to_hash_string() const override; @@ -93,6 +105,13 @@ protected: font font_; number_format number_format_; protection protection_; + + bool apply_alignment_; + bool apply_border_; + bool apply_fill_; + bool apply_font_; + bool apply_number_format_; + bool apply_protection_; }; } // namespace xlnt diff --git a/include/xlnt/styles/fill.hpp b/include/xlnt/styles/fill.hpp index 1b743cd9..fa599875 100644 --- a/include/xlnt/styles/fill.hpp +++ b/include/xlnt/styles/fill.hpp @@ -117,16 +117,11 @@ public: double get_gradient_top() const; double get_gradient_bottom() const; - - void apply(bool value); - bool apply() const; protected: std::string to_hash_string() const override; private: - bool apply_ = false; - type type_ = type::none; pattern_type pattern_type_; gradient_type gradient_type_; diff --git a/include/xlnt/styles/font.hpp b/include/xlnt/styles/font.hpp index 83deda5d..d0658894 100644 --- a/include/xlnt/styles/font.hpp +++ b/include/xlnt/styles/font.hpp @@ -87,17 +87,12 @@ public: std::size_t get_family() const; bool has_scheme() const; - - void apply(bool value); - bool apply() const; protected: std::string to_hash_string() const override; private: friend class style; - - bool apply_ = false; std::string name_ = "Calibri"; std::size_t size_ = 11; diff --git a/include/xlnt/styles/number_format.hpp b/include/xlnt/styles/number_format.hpp index 83be1c80..19c392e9 100644 --- a/include/xlnt/styles/number_format.hpp +++ b/include/xlnt/styles/number_format.hpp @@ -95,15 +95,11 @@ public: std::string format(long double number, calendar base_date) const; bool is_date_format() const; - - void apply(bool value); - bool apply() const; protected: std::string to_hash_string() const override; private: - bool apply_ = false; bool id_set_; std::size_t id_; std::string format_string_; diff --git a/include/xlnt/styles/protection.hpp b/include/xlnt/styles/protection.hpp index 450b9e6c..c89f4193 100644 --- a/include/xlnt/styles/protection.hpp +++ b/include/xlnt/styles/protection.hpp @@ -48,15 +48,11 @@ public: void set_locked(type locked_type); void set_hidden(type hidden_type); - - void apply(bool value); - bool apply() const; protected: std::string to_hash_string() const override; private: - bool apply_ = false; type locked_; type hidden_; }; diff --git a/include/xlnt/workbook/workbook.hpp b/include/xlnt/workbook/workbook.hpp index 6dc7d179..e9cf7bd2 100644 --- a/include/xlnt/workbook/workbook.hpp +++ b/include/xlnt/workbook/workbook.hpp @@ -186,6 +186,7 @@ public: cell_style &get_style(std::size_t style_index); const cell_style &get_style(std::size_t style_index) const; std::size_t add_style(const cell_style &style); + void clear_styles(); // Named Styles bool has_named_style(const std::string &name); diff --git a/source/cell/cell.cpp b/source/cell/cell.cpp index 9ab62df1..2537bae5 100644 --- a/source/cell/cell.cpp +++ b/source/cell/cell.cpp @@ -876,49 +876,49 @@ XLNT_FUNCTION timedelta cell::get_value() const void cell::set_border(const xlnt::border &border_) { d_->has_style_ = true; - auto style_copy = get_parent().get_parent().get_style(d_->style_id_); + auto style_copy = get_workbook().get_style(d_->style_id_); style_copy.set_border(border_); - d_->style_id_ = get_parent().get_parent().add_style(style_copy); + d_->style_id_ = get_workbook().add_style(style_copy); } void cell::set_fill(const xlnt::fill &fill_) { d_->has_style_ = true; - auto style_copy = get_parent().get_parent().get_style(d_->style_id_); + auto style_copy = get_workbook().get_style(d_->style_id_); style_copy.set_fill(fill_); - d_->style_id_ = get_parent().get_parent().add_style(style_copy); + d_->style_id_ = get_workbook().add_style(style_copy); } void cell::set_font(const font &font_) { d_->has_style_ = true; - auto style_copy = get_parent().get_parent().get_style(d_->style_id_); + auto style_copy = get_workbook().get_style(d_->style_id_); style_copy.set_font(font_); - d_->style_id_ = get_parent().get_parent().add_style(style_copy); + d_->style_id_ = get_workbook().add_style(style_copy); } void cell::set_number_format(const number_format &number_format_) { d_->has_style_ = true; - auto style_copy = get_parent().get_parent().get_style(d_->style_id_); + auto style_copy = get_workbook().get_style(d_->style_id_); style_copy.set_number_format(number_format_); - d_->style_id_ = get_parent().get_parent().add_style(style_copy); + d_->style_id_ = get_workbook().add_style(style_copy); } void cell::set_alignment(const xlnt::alignment &alignment_) { d_->has_style_ = true; - auto style_copy = get_parent().get_parent().get_style(d_->style_id_); + auto style_copy = get_workbook().get_style(d_->style_id_); style_copy.set_alignment(alignment_); - d_->style_id_ = get_parent().get_parent().add_style(style_copy); + d_->style_id_ = get_workbook().add_style(style_copy); } void cell::set_protection(const xlnt::protection &protection_) { d_->has_style_ = true; - auto style_copy = get_parent().get_parent().get_style(d_->style_id_); + auto style_copy = get_workbook().get_style(d_->style_id_); style_copy.set_protection(protection_); - d_->style_id_ = get_parent().get_parent().add_style(style_copy); + d_->style_id_ = get_workbook().add_style(style_copy); } template <> @@ -955,7 +955,7 @@ std::string cell::to_string() const cell_style &cell::get_style() { - return get_parent().get_parent().get_style(d_->style_id_); + return get_workbook().get_style(d_->style_id_); } bool cell::has_style() const @@ -965,7 +965,7 @@ bool cell::has_style() const void cell::set_style(const cell_style &style) { - d_->style_id_ = get_parent().get_parent().add_style(style); + d_->style_id_ = get_workbook().add_style(style); d_->has_style_ = true; } diff --git a/source/cell/tests/test_cell.hpp b/source/cell/tests/test_cell.hpp index 8b9c990d..a63cf1ab 100644 --- a/source/cell/tests/test_cell.hpp +++ b/source/cell/tests/test_cell.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -367,7 +368,7 @@ public: cell.set_font(font); TS_ASSERT(cell.has_style()); - TS_ASSERT(cell.get_font().apply()); + TS_ASSERT(cell.get_style().font_applied()); TS_ASSERT_EQUALS(cell.get_font(), font); } @@ -383,7 +384,7 @@ public: cell.set_fill(f); TS_ASSERT(cell.has_style()); - TS_ASSERT(cell.get_fill().apply()); + TS_ASSERT(cell.get_style().fill_applied()); TS_ASSERT_EQUALS(cell.get_fill(), f); } @@ -397,7 +398,7 @@ public: cell.set_border(border); TS_ASSERT(cell.has_style()); - TS_ASSERT(cell.get_border().apply()); + TS_ASSERT(cell.get_style().border_applied()); TS_ASSERT_EQUALS(cell.get_border(), border); } @@ -410,7 +411,7 @@ public: cell.set_number_format(format); TS_ASSERT(cell.has_style()); - TS_ASSERT(cell.get_number_format().apply()); + TS_ASSERT(cell.get_style().number_format_applied()); TS_ASSERT_EQUALS(cell.get_number_format().get_format_string(), "dd--hh--mm"); } @@ -425,7 +426,7 @@ public: cell.set_alignment(align); TS_ASSERT(cell.has_style()); - TS_ASSERT(cell.get_alignment().apply()); + TS_ASSERT(cell.get_style().alignment_applied()); TS_ASSERT_EQUALS(cell.get_alignment(), align); } @@ -440,7 +441,7 @@ public: cell.set_protection(prot); TS_ASSERT(cell.has_style()); - TS_ASSERT(cell.get_protection().apply()); + TS_ASSERT(cell.get_style().protection_applied()); TS_ASSERT_EQUALS(cell.get_protection(), prot); } }; diff --git a/source/cell/text.cpp b/source/cell/text.cpp new file mode 100644 index 00000000..da62331d --- /dev/null +++ b/source/cell/text.cpp @@ -0,0 +1,62 @@ +// Copyright (c) 2014-2016 Thomas Fussell +// Copyright (c) 2010-2015 openpyxl +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, WRISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE +// +// @license: http://www.opensource.org/licenses/mit-license.php +// @author: see AUTHORS file + +#include +#include + +namespace xlnt { + +void text::clear() +{ + runs_.clear(); +} + +void text::set_plain_string(const std::string &s) +{ + clear(); + add_run(text_run(s)); +} + +std::string text::get_plain_string() const +{ + std::string plain_string; + + for (const auto &run : runs_) + { + plain_string.append(run.get_string()); + } + + return plain_string; +} +std::vector text::get_runs() +{ + return runs_; +} + +void text::add_run(const text_run &t) +{ + runs_.push_back(t); +} + +} // namespace xlnt diff --git a/source/cell/text_run.cpp b/source/cell/text_run.cpp new file mode 100644 index 00000000..05c5ccf0 --- /dev/null +++ b/source/cell/text_run.cpp @@ -0,0 +1,46 @@ +// Copyright (c) 2014-2016 Thomas Fussell +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, WRISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE +// +// @license: http://www.opensource.org/licenses/mit-license.php +// @author: see AUTHORS file + +#include + +namespace xlnt { + +text_run::text_run() : text_run("") +{ +} + +text_run::text_run(const std::string &string) : string_(string) +{ +} + +std::string text_run::get_string() const +{ + return string_; +} + +void text_run::set_string(const std::string &string) +{ + string_ = string; +} + +} // namespace xlnt diff --git a/source/serialization/style_serializer.cpp b/source/serialization/style_serializer.cpp index e3fa3383..96cd5385 100644 --- a/source/serialization/style_serializer.cpp +++ b/source/serialization/style_serializer.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -39,6 +40,7 @@ #include #include #include +#include #include #include @@ -64,7 +66,7 @@ bool equals_case_insensitive(const std::string &left, const std::string &right) bool is_true(const std::string &bool_string) { - return bool_string == "1"; + return bool_string == "1" || bool_string == "true"; } xlnt::protection::type protection_type_from_string(const std::string &type_string) @@ -187,6 +189,26 @@ namespace xlnt { style_serializer::style_serializer(workbook &wb) : workbook_(wb) { + std::unordered_set> number_format_set; + + for (auto ws : workbook_) + { + for (auto row : ws.rows()) + { + for (auto cell : row) + { + if (cell.has_style()) + { + number_format_set.insert(cell.get_number_format()); + } + } + } + } + + for (auto nf : number_format_set) + { + number_formats_.push_back(nf); + } } protection style_serializer::read_protection(const xml_node &protection_node) @@ -278,31 +300,30 @@ cell_style style_serializer::read_cell_style(const xml_node &style_node) cell_style s; // Alignment - s.get_alignment().apply(style_node.has_child("alignment") || is_true(style_node.get_attribute("applyAlignment"))); + s.alignment_applied(style_node.has_child("alignment") || is_true(style_node.get_attribute("applyAlignment"))); - if (s.get_alignment().apply()) + if (s.alignment_applied()) { auto inline_alignment = read_alignment(style_node.get_child("alignment")); s.set_alignment(inline_alignment); } // Border - s.get_border().apply(is_true(style_node.get_attribute("applyBorder"))); auto border_index = style_node.has_attribute("borderId") ? std::stoull(style_node.get_attribute("borderId")) : 0; s.set_border(borders_.at(border_index)); + s.border_applied(is_true(style_node.get_attribute("applyBorder"))); // Fill - s.get_fill().apply(is_true(style_node.get_attribute("applyFill"))); auto fill_index = style_node.has_attribute("fillId") ? std::stoull(style_node.get_attribute("fillId")) : 0; s.set_fill(fills_.at(fill_index)); + s.fill_applied(is_true(style_node.get_attribute("applyFill"))); // Font - s.get_font().apply(is_true(style_node.get_attribute("applyFont"))); auto font_index = style_node.has_attribute("fontId") ? std::stoull(style_node.get_attribute("fontId")) : 0; s.set_font(fonts_.at(font_index)); + s.font_applied(is_true(style_node.get_attribute("applyFont"))); // Number Format - s.get_number_format().apply(is_true(style_node.get_attribute("applyNumberFormat"))); auto number_format_id = std::stoull(style_node.get_attribute("numFmtId")); bool builtin_format = true; @@ -321,11 +342,13 @@ cell_style style_serializer::read_cell_style(const xml_node &style_node) { s.set_number_format(number_format::from_builtin_id(number_format_id)); } + + s.number_format_applied(is_true(style_node.get_attribute("applyNumberFormat"))); // Protection - s.get_protection().apply(style_node.has_attribute("protection") || is_true(style_node.get_attribute("applyProtection"))); + s.protection_applied(style_node.has_attribute("protection") || is_true(style_node.get_attribute("applyProtection"))); - if (s.get_protection().apply()) + if (s.protection_applied()) { auto inline_protection = read_protection(style_node.get_child("protection")); s.set_protection(inline_protection); @@ -348,17 +371,17 @@ named_style style_serializer::read_named_style(const xml_node &named_style_node, //TODO shouldn't have to set apply after set_X() s.set_alignment(base_style.get_alignment()); - s.get_alignment().apply(base_style.get_alignment().apply()); + s.alignment_applied(base_style.alignment_applied()); s.set_border(base_style.get_border()); - s.get_border().apply(base_style.get_border().apply()); + s.border_applied(base_style.border_applied()); s.set_fill(base_style.get_fill()); - s.get_fill().apply(base_style.get_fill().apply()); + s.fill_applied(base_style.fill_applied()); s.set_font(base_style.get_font()); - s.get_font().apply(base_style.get_font().apply()); + s.font_applied(base_style.font_applied()); s.set_number_format(base_style.get_number_format()); - s.get_number_format().apply(base_style.get_number_format().apply()); + s.number_format_applied(base_style.number_format_applied()); s.set_protection(base_style.get_protection()); - s.get_protection().apply(base_style.get_protection().apply()); + s.protection_applied(base_style.protection_applied()); return s; } @@ -380,6 +403,11 @@ bool style_serializer::read_stylesheet(const xml_document &xml) workbook_.create_named_style(ns.second.get_name()) = ns.second; } + if (!cell_styles_.empty()) + { + workbook_.clear_styles(); + } + for (const auto &s : cell_styles_) { workbook_.add_style(s); @@ -752,6 +780,11 @@ void style_serializer::initialize_vectors() { fonts_.push_back(font()); } + + if (number_formats_.empty()) + { + number_formats_.push_back(number_format::general()); + } } bool style_serializer::write_fonts(xlnt::xml_node &fonts_node) const @@ -1043,39 +1076,39 @@ bool style_serializer::write_borders(xlnt::xml_node &borders_node) const return true; } -bool style_serializer::write_style_common(const alignment &style_alignment, const border &style_border, const fill &style_fill, const font &style_font, const number_format &style_number_format, const protection &style_protection, xml_node xf_node) const +bool style_serializer::write_style_common(const common_style &style, xml_node xf_node) const { - xf_node.add_attribute("numFmtId", std::to_string(style_number_format.get_id())); + xf_node.add_attribute("numFmtId", std::to_string(style.get_number_format().get_id())); - auto font_id = std::distance(fonts_.begin(), std::find(fonts_.begin(), fonts_.end(), style_font)); + auto font_id = std::distance(fonts_.begin(), std::find(fonts_.begin(), fonts_.end(), style.get_font())); xf_node.add_attribute("fontId", std::to_string(font_id)); - if (style_fill.apply()) + if (style.fill_applied()) { - auto fill_id = std::distance(fills_.begin(), std::find(fills_.begin(), fills_.end(), style_fill)); + auto fill_id = std::distance(fills_.begin(), std::find(fills_.begin(), fills_.end(), style.get_fill())); xf_node.add_attribute("fillId", std::to_string(fill_id)); } - if (style_border.apply()) + if (style.border_applied()) { - auto border_id = std::distance(borders_.begin(), std::find(borders_.begin(), borders_.end(), style_border)); + auto border_id = std::distance(borders_.begin(), std::find(borders_.begin(), borders_.end(), style.get_border())); xf_node.add_attribute("borderId", std::to_string(border_id)); } - xf_node.add_attribute("applyNumberFormat", style_number_format.apply() ? "1" : "0"); - xf_node.add_attribute("applyFill", style_fill.apply() ? "1" : "0"); - xf_node.add_attribute("applyFont", style_font.apply() ? "1" : "0"); - xf_node.add_attribute("applyBorder", style_border.apply() ? "1" : "0"); - xf_node.add_attribute("applyAlignment", style_alignment.apply() ? "1" : "0"); - xf_node.add_attribute("applyProtection", style_protection.apply() ? "1" : "0"); + xf_node.add_attribute("applyNumberFormat", style.number_format_applied() ? "1" : "0"); + xf_node.add_attribute("applyFill", style.fill_applied() ? "1" : "0"); + xf_node.add_attribute("applyFont", style.font_applied() ? "1" : "0"); + xf_node.add_attribute("applyBorder", style.border_applied() ? "1" : "0"); + xf_node.add_attribute("applyAlignment", style.alignment_applied() ? "1" : "0"); + xf_node.add_attribute("applyProtection", style.protection_applied() ? "1" : "0"); - if (style_alignment.apply()) + if (style.alignment_applied()) { auto alignment_node = xf_node.add_child("alignment"); - if (style_alignment.has_vertical()) + if (style.get_alignment().has_vertical()) { - switch (style_alignment.get_vertical()) + switch (style.get_alignment().get_vertical()) { case vertical_alignment::bottom: alignment_node.add_attribute("vertical", "bottom"); @@ -1094,9 +1127,9 @@ bool style_serializer::write_style_common(const alignment &style_alignment, cons } } - if (style_alignment.has_horizontal()) + if (style.get_alignment().has_horizontal()) { - switch (style_alignment.get_horizontal()) + switch (style.get_alignment().get_horizontal()) { case horizontal_alignment::center: alignment_node.add_attribute("horizontal", "center"); @@ -1121,12 +1154,12 @@ bool style_serializer::write_style_common(const alignment &style_alignment, cons } } - if (style_alignment.get_wrap_text()) + if (style.get_alignment().get_wrap_text()) { alignment_node.add_attribute("wrapText", "1"); } - if (style_alignment.get_shrink_to_fit()) + if (style.get_alignment().get_shrink_to_fit()) { alignment_node.add_attribute("shrinkToFit", "1"); } @@ -1137,12 +1170,12 @@ bool style_serializer::write_style_common(const alignment &style_alignment, cons bool style_serializer::write_cell_style(const cell_style &style, xml_node &xf_node) const { - return write_style_common(style.get_alignment(), style.get_border(), style.get_fill(), style.get_font(), style.get_number_format(), style.get_protection(), xf_node); + return write_style_common(style, xf_node); } bool style_serializer::write_named_style(const named_style &style, xml_node &xf_node) const { - return write_style_common(style.get_alignment(), style.get_border(), style.get_fill(), style.get_font(), style.get_number_format(), style.get_protection(), xf_node); + return write_style_common(style, xf_node); } bool style_serializer::write_named_styles(xml_node &cell_styles_node, xml_node &styles_node) const @@ -1249,11 +1282,12 @@ xml_document style_serializer::write_stylesheet() write_borders(borders_node); auto cell_style_xfs_node = root_node.add_child("cellStyleXfs"); - auto cell_styles_node = root_node.add_child("cellStyles"); - write_named_styles(root_node, cell_style_xfs_node); auto cell_xfs_node = root_node.add_child("cellXfs"); - write_cell_styles(cell_styles_node); + write_cell_styles(cell_xfs_node); + + auto cell_styles_node = root_node.add_child("cellStyles"); + write_named_styles(cell_style_xfs_node, cell_styles_node); auto dxfs_node = root_node.add_child("dxfs"); write_dxfs(dxfs_node); diff --git a/source/serialization/worksheet_serializer.cpp b/source/serialization/worksheet_serializer.cpp index 227f6a86..77d117cc 100644 --- a/source/serialization/worksheet_serializer.cpp +++ b/source/serialization/worksheet_serializer.cpp @@ -197,7 +197,7 @@ bool worksheet_serializer::read_worksheet(const xml_document &xml) if (has_style) { - cell.set_style(sheet_.get_parent().get_style(style_id)); + cell.set_style(sheet_.get_workbook().get_style(style_id)); } } } diff --git a/source/styles/alignment.cpp b/source/styles/alignment.cpp index 0c8c4c19..2f7e7c4c 100644 --- a/source/styles/alignment.cpp +++ b/source/styles/alignment.cpp @@ -90,14 +90,4 @@ std::string alignment::to_hash_string() const return hash_string; } -bool alignment::apply() const -{ - return apply_; -} - -void alignment::apply(bool value) -{ - apply_ = value; -} - } // namespace xlnt diff --git a/source/styles/border.cpp b/source/styles/border.cpp index 3cca63bd..e13565b0 100644 --- a/source/styles/border.cpp +++ b/source/styles/border.cpp @@ -149,14 +149,4 @@ std::string border::to_hash_string() const return hash_string; } -bool border::apply() const -{ - return apply_; -} - -void border::apply(bool value) -{ - apply_ = value; -} - } // namespace xlnt diff --git a/source/styles/cell_style.cpp b/source/styles/cell_style.cpp index a42646e0..dbf256dc 100644 --- a/source/styles/cell_style.cpp +++ b/source/styles/cell_style.cpp @@ -41,15 +41,10 @@ cell_style::cell_style(const cell_style &other) cell_style &cell_style::operator=(const cell_style &other) { + common_style::operator=(other); + parent_ = other.parent_; named_style_name_ = other.named_style_name_; - - alignment_ = other.alignment_; - border_ = other.border_; - fill_ = other.fill_; - font_ = other.font_; - number_format_ = other.number_format_; - protection_ = other.protection_; return *this; } diff --git a/source/styles/common_style.cpp b/source/styles/common_style.cpp index c738b145..8b9d36d3 100644 --- a/source/styles/common_style.cpp +++ b/source/styles/common_style.cpp @@ -26,6 +26,12 @@ namespace xlnt { common_style::common_style() + : apply_alignment_(false), + apply_border_(false), + apply_fill_(false), + apply_font_(false), + apply_number_format_(false), + apply_protection_(false) { } @@ -35,7 +41,13 @@ common_style::common_style(const common_style &other) fill_(other.fill_), font_(other.font_), number_format_(other.number_format_), - protection_(other.protection_) + protection_(other.protection_), + apply_alignment_(other.apply_alignment_), + apply_border_(other.apply_border_), + apply_fill_(other.apply_fill_), + apply_font_(other.apply_font_), + apply_number_format_(other.apply_number_format_), + apply_protection_(other.apply_protection_) { } @@ -47,6 +59,13 @@ common_style &common_style::operator=(const xlnt::common_style &other) font_ = other.font_; number_format_ = other.number_format_; protection_ = other.protection_; + + apply_alignment_ = other.apply_alignment_; + apply_border_ = other.apply_border_; + apply_fill_ = other.apply_fill_; + apply_font_ = other.apply_font_; + apply_number_format_ = other.apply_number_format_; + apply_protection_ = other.apply_protection_; return *this; } @@ -64,7 +83,7 @@ const alignment &common_style::get_alignment() const void common_style::set_alignment(const xlnt::alignment &new_alignment) { alignment_ = new_alignment; - alignment_.apply(true); + alignment_applied(true); } number_format &common_style::get_number_format() @@ -80,7 +99,7 @@ const number_format &common_style::get_number_format() const void common_style::set_number_format(const xlnt::number_format &new_number_format) { number_format_ = new_number_format; - number_format_.apply(true); + number_format_applied(true); } border &common_style::get_border() @@ -96,7 +115,7 @@ const border &common_style::get_border() const void common_style::set_border(const xlnt::border &new_border) { border_ = new_border; - border_.apply(true); + border_applied(true); } fill &common_style::get_fill() @@ -112,7 +131,7 @@ const fill &common_style::get_fill() const void common_style::set_fill(const xlnt::fill &new_fill) { fill_ = new_fill; - fill_.apply(true); + fill_applied(true); } font &common_style::get_font() @@ -128,7 +147,7 @@ const font &common_style::get_font() const void common_style::set_font(const xlnt::font &new_font) { font_ = new_font; - font_.apply(true); + font_applied(true); } protection &common_style::get_protection() @@ -144,32 +163,92 @@ const protection &common_style::get_protection() const void common_style::set_protection(const xlnt::protection &new_protection) { protection_ = new_protection; - protection_.apply(true); + protection_applied(true); } std::string common_style::to_hash_string() const { std::string hash_string("common_style:"); - hash_string.append(std::to_string(alignment_.apply())); - hash_string.append(alignment_.apply() ? std::to_string(alignment_.hash()) : ":"); + hash_string.append(std::to_string(alignment_applied())); + hash_string.append(alignment_applied() ? std::to_string(alignment_.hash()) : ":"); - hash_string.append(std::to_string(border_.apply())); - hash_string.append(border_.apply() ? std::to_string(border_.hash()) : ":"); + hash_string.append(std::to_string(border_applied())); + hash_string.append(border_applied() ? std::to_string(border_.hash()) : ":"); - hash_string.append(std::to_string(font_.apply())); - hash_string.append(font_.apply() ? std::to_string(font_.hash()) : ":"); + hash_string.append(std::to_string(font_applied())); + hash_string.append(font_applied() ? std::to_string(font_.hash()) : ":"); - hash_string.append(std::to_string(fill_.apply())); - hash_string.append(fill_.apply() ? std::to_string(fill_.hash()) : ":"); + hash_string.append(std::to_string(fill_applied())); + hash_string.append(fill_applied() ? std::to_string(fill_.hash()) : ":"); - hash_string.append(std::to_string(number_format_.apply())); - hash_string.append(number_format_.apply() ? std::to_string(number_format_.hash()) : ":"); + hash_string.append(std::to_string(number_format_applied())); + hash_string.append(std::to_string(number_format_.hash())); - hash_string.append(std::to_string(protection_.apply())); - hash_string.append(protection_.apply() ? std::to_string(protection_.hash()) : ":"); + hash_string.append(std::to_string(protection_applied())); + hash_string.append(protection_applied() ? std::to_string(protection_.hash()) : ":"); return hash_string; } +void common_style::alignment_applied(bool applied) +{ + apply_alignment_ = applied; +} + +void common_style::border_applied(bool applied) +{ + apply_border_ = applied; +} + +void common_style::fill_applied(bool applied) +{ + apply_fill_ = applied; +} + +void common_style::font_applied(bool applied) +{ + apply_font_ = applied; +} + +void common_style::number_format_applied(bool applied) +{ + apply_number_format_ = applied; +} + +void common_style::protection_applied(bool applied) +{ + apply_protection_ = applied; +} + +bool common_style::alignment_applied() const +{ + return apply_alignment_; +} + +bool common_style::border_applied() const +{ + return apply_border_; +} + +bool common_style::fill_applied() const +{ + return apply_fill_; +} + +bool common_style::font_applied() const +{ + return apply_font_; +} + +bool common_style::number_format_applied() const +{ + return apply_number_format_; +} + +bool common_style::protection_applied() const +{ + return apply_protection_; +} + } // namespace xlnt diff --git a/source/styles/fill.cpp b/source/styles/fill.cpp index 454beb4a..e4a1b1ae 100644 --- a/source/styles/fill.cpp +++ b/source/styles/fill.cpp @@ -267,14 +267,4 @@ double fill::get_gradient_bottom() const return gradient_path_bottom_; } -bool fill::apply() const -{ - return apply_; -} - -void fill::apply(bool value) -{ - apply_ = value; -} - } // namespace xlnt diff --git a/source/styles/font.cpp b/source/styles/font.cpp index a6e0a0b3..db93bb08 100644 --- a/source/styles/font.cpp +++ b/source/styles/font.cpp @@ -146,14 +146,4 @@ std::string font::to_hash_string() const return hash_string; } -bool font::apply() const -{ - return apply_; -} - -void font::apply(bool value) -{ - apply_ = value; -} - } // namespace xlnt diff --git a/source/styles/number_format.cpp b/source/styles/number_format.cpp index 1f1be61f..c843b6c5 100644 --- a/source/styles/number_format.cpp +++ b/source/styles/number_format.cpp @@ -1094,9 +1094,9 @@ std::string number_format::get_format_string() const std::string number_format::to_hash_string() const { std::string hash_string("number_format"); - -// hash_string.append(std::to_string(id_)); hash_string.append(format_string_); + hash_string.append("|||"); + hash_string.append(std::to_string(id_)); return hash_string; } @@ -1175,14 +1175,4 @@ std::string number_format::format(long double number, calendar base_date) const return format_number(number, format_string_, base_date); } -bool number_format::apply() const -{ - return apply_; -} - -void number_format::apply(bool value) -{ - apply_ = value; -} - } // namespace xlnt diff --git a/source/styles/protection.cpp b/source/styles/protection.cpp index f173a15a..d728e087 100644 --- a/source/styles/protection.cpp +++ b/source/styles/protection.cpp @@ -54,14 +54,4 @@ std::string protection::to_hash_string() const return hash_string; } -bool protection::apply() const -{ - return apply_; -} - -void protection::apply(bool value) -{ - apply_ = value; -} - } // namespace xlnt diff --git a/source/workbook/workbook.cpp b/source/workbook/workbook.cpp index 87b28be4..8e1f6fb4 100644 --- a/source/workbook/workbook.cpp +++ b/source/workbook/workbook.cpp @@ -607,19 +607,47 @@ std::vector workbook::get_named_ranges() const std::size_t workbook::add_style(const cell_style &style) { + cell_style style_copy = style; + + //TODO this is ugly + if (!style.get_number_format().has_id()) + { + bool match = false; + + for (std::size_t i = 0; i < d_->cell_styles_.size(); i++) + { + if (d_->cell_styles_.at(i).get_number_format().get_format_string() == style_copy.get_number_format().get_format_string()) + { + style_copy.set_number_format(d_->cell_styles_.at(i).get_number_format()); + match = true; + break; + } + } + + if (!match) + { + style_copy.get_number_format().set_id(d_->next_custom_format_id_++); + } + } + for (std::size_t i = 0; i < d_->cell_styles_.size(); i++) { - if (d_->cell_styles_[i] == style) + if (d_->cell_styles_[i] == style_copy) { return i; } } - d_->cell_styles_.push_back(style); + d_->cell_styles_.push_back(style_copy); return d_->cell_styles_.size() - 1; } +void workbook::clear_styles() +{ + d_->cell_styles_.clear(); +} + cell_style &workbook::get_style(std::size_t style_index) { return d_->cell_styles_.at(style_index);