diff --git a/include/xlnt/cell/cell.hpp b/include/xlnt/cell/cell.hpp
index 803893ac..740cb29a 100644
--- a/include/xlnt/cell/cell.hpp
+++ b/include/xlnt/cell/cell.hpp
@@ -36,7 +36,6 @@ namespace xlnt {
enum class calendar;
class alignment;
-class base_format;
class border;
class cell_reference;
class comment;
@@ -177,41 +176,32 @@ public:
// computed format
///
- /// For each of alignment, border, fill, font, number format, and protection,
- /// returns a format using the value from the cell format if that value is
- /// applied, or else the value from the named style if that value is applied,
- /// or else the default value. This is used to retreive the formatting of the cell
- /// as it will be displayed in an editing application.
- ///
- base_format get_computed_format() const;
-
- ///
- /// Returns the result of get_computed_format().get_alignment().
+ ///
///
alignment get_computed_alignment() const;
///
- /// Returns the result of get_computed_format().get_border().
+ ///
///
border get_computed_border() const;
///
- /// Returns the result of get_computed_format().get_fill().
+ ///
///
fill get_computed_fill() const;
///
- /// Returns the result of get_computed_format().get_font().
+ ///
///
font get_computed_font() const;
///
- /// Returns the result of get_computed_format().get_number_format().
+ ///
///
number_format get_computed_number_format() const;
///
- /// Returns the result of get_computed_format().get_protection().
+ ///
///
protection get_computed_protection() const;
@@ -492,27 +482,21 @@ private:
// make these friends so they can use the private constructor
friend class style;
friend class worksheet;
- friend class detail::xlsx_consumer;
- friend class detail::xlsx_producer;
+ friend class detail::xlsx_consumer;
+ friend class detail::xlsx_producer;
friend struct detail::cell_impl;
- ///
- /// Helper function to guess the type of a string, convert it,
- /// and then use the correct cell::get_value according to the type.
- ///
- void guess_type_and_set_value(const std::string &value);
-
- ///
- /// Returns a non-const reference to the format of this cell.
- /// This is for internal use only.
- ///
- format &get_format_internal();
+ ///
+ /// Helper function to guess the type of a string, convert it,
+ /// and then use the correct cell::get_value according to the type.
+ ///
+ void guess_type_and_set_value(const std::string &value);
///
- /// Use workbook::create_format() to create a new format then copy
- /// this cell's formatting to that new format and return it.
+ /// Returns a non-const reference to the format of this cell.
+ /// This is for internal use only.
///
- format &duplicate_format();
+ format &get_format_internal();
///
/// Private constructor to create a cell from its implementation.
diff --git a/include/xlnt/styles/base_format.hpp b/include/xlnt/styles/base_format.hpp
index af00c55a..e69de29b 100644
--- a/include/xlnt/styles/base_format.hpp
+++ b/include/xlnt/styles/base_format.hpp
@@ -1,94 +0,0 @@
-// 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
-#pragma once
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-namespace xlnt {
-
-///
-/// Describes the formatting of a particular cell.
-///
-class XLNT_API base_format
-{
-public:
- // Alignment
- class alignment &alignment();
- const class alignment &alignment() const;
- void alignment(const xlnt::alignment &new_alignment, bool applied);
- bool alignment_applied() const;
-
- // Border
- virtual class border &border();
- virtual const class border &border() const;
- virtual void border(const xlnt::border &new_border, bool applied);
- bool border_applied() const;
-
- // Fill
- virtual class fill &fill();
- virtual const class fill &fill() const;
- virtual void fill(const xlnt::fill &new_fill, bool applied);
- bool fill_applied() const;
-
- // Font
- virtual class font &font();
- virtual const class font &font() const;
- virtual void font(const xlnt::font &new_font, bool applied);
- bool font_applied() const;
-
- // Number Format
- virtual class number_format &number_format();
- virtual const class number_format &number_format() const;
- virtual void number_format(const xlnt::number_format &new_number_format, bool applied);
- bool number_format_applied() const;
-
- // Protection
- class protection &protection();
- const class protection &protection() const;
- void protection(const xlnt::protection &new_protection, bool applied);
- bool protection_applied() const;
-
-protected:
- class alignment alignment_;
- class border border_;
- class fill fill_;
- class font font_;
- class number_format number_format_;
- class protection protection_;
-
- bool apply_alignment_ = false;
- bool apply_border_ = false;
- bool apply_fill_ = false;
- bool apply_font_ = false;
- bool apply_number_format_ = false;
- bool apply_protection_ = false;
-};
-
-} // namespace xlnt
diff --git a/include/xlnt/styles/format.hpp b/include/xlnt/styles/format.hpp
index f609c235..2fbe8302 100644
--- a/include/xlnt/styles/format.hpp
+++ b/include/xlnt/styles/format.hpp
@@ -36,53 +36,200 @@ class fill;
class font;
class number_format;
class protection;
+class workbook;
namespace detail {
struct format_impl;
struct stylesheet;
+class xlsx_consumer;
+class xlsx_producer;
} // namespace detail
///
/// Describes the formatting of a particular cell.
///
-class XLNT_API format : public base_format
+class XLNT_API format
{
public:
- std::size_t id() const;
-
- bool has_style() const;
- void clear_style();
- void style(const std::string &name);
- void style(const xlnt::style &new_style);
- const class style &style() const;
-
- class border &border() override;
- const class border &border() const override;
- void border(const xlnt::border &new_border, bool applied) override;
-
- class fill &fill() override;
- const class fill &fill() const override;
- void fill(const xlnt::fill &new_fill, bool applied) override;
+ ///
+ /// Returns the index of this format.
+ ///
+ std::size_t id() const;
- class font &font() override;
- const class font &font() const override;
- void font(const xlnt::font &new_font, bool applied) override;
+ // Alignment
- class number_format &number_format() override;
- const class number_format &number_format() const override;
- void number_format(const xlnt::number_format &new_number_format, bool applied) override;
+ ///
+ /// Returns the alignment to be applied to contents of cells using this format.
+ ///
+ class alignment &alignment();
- format &alignment_id(std::size_t id);
- format &border_id(std::size_t id);
- format &fill_id(std::size_t id);
- format &font_id(std::size_t id);
- format &number_format_id(std::size_t id);
- format &protection_id(std::size_t id);
+ ///
+ /// Returns the alignment to be applied to contents of cells using this format.
+ ///
+ const class alignment &alignment() const;
+
+ ///
+ /// Sets the alignment of this format to new_alignment. If applied is true,
+ /// the alignment will be used when displaying the cell. Updates all cells
+ /// currently using this format if update is true, otherwise creates new
+ /// format with the new protection.
+ ///
+ void alignment(const xlnt::alignment &new_alignment,
+ bool applied = true, bool update = true);
+
+ ///
+ /// Returns true if the alignment is being applied.
+ ///
+ bool alignment_applied() const;
+
+ // Border
+
+ ///
+ /// Returns the border properties to be applied to the outline of cells using this format.
+ ///
+ class border &border();
+
+ ///
+ /// Returns the border properties to be applied to the outline of cells using this format.
+ ///
+ const class border &border() const;
+
+ ///
+ /// Sets the border of this format to new_border. If applied is true,
+ /// the border will be used when displaying the cell. Updates all cells
+ /// currently using this format if update is true, otherwise creates
+ /// new format with the new protection.
+ ///
+ void border(const xlnt::border &new_border,
+ bool applied = true, bool update = true);
+
+ ///
+ /// Returns true if the border is being applied.
+ ///
+ bool border_applied() const;
+
+ // Fill
+
+ ///
+ /// Returns the fill to be applied to the background of cells using this format.
+ ///
+ class fill &fill();
+
+ ///
+ /// Returns the fill to be applied to the background of cells using this format.
+ ///
+ const class fill &fill() const;
+
+ ///
+ /// Sets the fill of this format to new_fill and applies it if applied is true.
+ /// Updates all cells currently using this format if update is true,
+ /// otherwise creates new format with the new protection.
+ ///
+ void fill(const xlnt::fill &new_fill,
+ bool applied = true, bool update = true);
+
+ ///
+ /// Returns true if the fill is being applied.
+ ///
+ bool fill_applied() const;
+
+ // Font
+
+ ///
+ /// Returns the font to be applied to contents of cells using this format.
+ ///
+ class font &font();
+
+ ///
+ /// Returns the font to be applied to contents of cells using this format.
+ ///
+ const class font &font() const;
+
+ ///
+ /// Sets the font of this format to new_font and applies it if applied is true.
+ /// Updates all cells currently using this format if update is true,
+ /// otherwise creates new format with the new protection.
+ ///
+ void font(const xlnt::font &new_font,
+ bool applied = true, bool update = true);
+
+ ///
+ /// Returns true if the font is being applied.
+ ///
+ bool font_applied() const;
+
+ // Number Format
+
+ ///
+ /// Returns the number format to be applied to text/numbers in cells using this format.
+ ///
+ class number_format &number_format();
+
+ ///
+ /// Returns the number format to be applied to text/numbers in cells using this format.
+ ///
+ const class number_format &number_format() const;
+
+ ///
+ /// Sets the number format applied to text/numbers in cells using this format
+ /// and applies it if applied is true. Updates all cells currently using this
+ /// format if update is true, otherwise creates new format with the new number
+ /// format.
+ ///
+ void number_format(const xlnt::number_format &new_number_format,
+ bool applied = true, bool update = true);
+
+ ///
+ /// Returns true if the number format is being applied.
+ ///
+ bool number_format_applied() const;
+
+ // Protection
+
+ ///
+ /// Returns the protection to be applied to the contents of cells using this format.
+ ///
+ class protection &protection();
+
+ ///
+ /// Returns the protection to be applied to the contents of cells using this format.
+ ///
+ const class protection &protection() const;
+
+ ///
+ /// Sets the protection of the contents of the cell using this format. Applies it if
+ /// applied is true. Updates all cells currently using this format if update is true,
+ /// otherwise creates new format with the new protection.
+ ///
+ void protection(const xlnt::protection &new_protection,
+ bool applied = true, bool update = true);
+
+ ///
+ /// Returns true if the protection is being applied.
+ ///
+ bool protection_applied() const;
+
+ ///
+ /// Returns true if the formats are identical.
+ ///
+ XLNT_API friend bool operator==(const format &left, const format &right);
private:
- friend struct detail::stylesheet;
- format(detail::format_impl *d);
- detail::format_impl *d_;
+ friend struct detail::stylesheet;
+ friend class detail::xlsx_consumer;
+ friend class detail::xlsx_producer;
+ friend class cell;
+ friend class workbook;
+
+ ///
+ /// Private constructor used by stylesheet.
+ ///
+ format(detail::format_impl *d);
+
+ ///
+ /// Pointer to implementation. This memory is held in a vector in stylesheet.
+ ///
+ detail::format_impl *d_;
};
} // namespace xlnt
diff --git a/include/xlnt/styles/style.hpp b/include/xlnt/styles/style.hpp
index de64f099..aca8e21e 100644
--- a/include/xlnt/styles/style.hpp
+++ b/include/xlnt/styles/style.hpp
@@ -27,7 +27,6 @@
#include
#include
-#include
namespace xlnt {
@@ -40,7 +39,7 @@ struct stylesheet;
/// Describes a style which has a name and can be applied to multiple individual
/// formats. In Excel this is a "Cell Style".
///
-class XLNT_API style : public base_format
+class XLNT_API style
{
public:
std::string name() const;
@@ -55,18 +54,152 @@ public:
optional builtin_id() const;
style &builtin_id(std::size_t builtin_id);
- style &alignment_id(std::size_t id);
- style &border_id(std::size_t id);
- style &fill_id(std::size_t id);
- style &font_id(std::size_t id);
- style &number_format_id(std::size_t id);
- style &protection_id(std::size_t id);
+ // Alignment
- bool operator==(const style &other);
+ ///
+ /// Returns the alignment to be applied to contents of cells using this format.
+ ///
+ class alignment &alignment();
+
+ ///
+ /// Returns the alignment to be applied to contents of cells using this format.
+ ///
+ const class alignment &alignment() const;
+
+ ///
+ /// Sets the alignment of this format to new_alignment. If applied is true,
+ /// the alignment will be used when displaying the cell.
+ ///
+ void alignment(const xlnt::alignment &new_alignment, bool applied = true, bool update = true);
+
+ ///
+ /// Returns true if the alignment is being applied.
+ ///
+ bool alignment_applied() const;
+
+ // Border
+
+ ///
+ /// Returns the border properties to be applied to the outline of cells using this format.
+ ///
+ class border &border();
+
+ ///
+ /// Returns the border properties to be applied to the outline of cells using this format.
+ ///
+ const class border &border() const;
+
+ ///
+ /// Sets the border of this format to new_border. If applied is true,
+ /// the border will be used when displaying the cell.
+ ///
+ void border(const xlnt::border &new_border, bool applied = true, bool update = true);
+
+ ///
+ /// Returns true if the border is being applied.
+ ///
+ bool border_applied() const;
+
+ // Fill
+
+ ///
+ /// Returns the fill to be applied to the background of cells using this format.
+ ///
+ class fill &fill();
+
+ ///
+ /// Returns the fill to be applied to the background of cells using this format.
+ ///
+ const class fill &fill() const;
+
+ ///
+ /// Sets the fill of this format to new_fill and applies it if applied is true.
+ ///
+ void fill(const xlnt::fill &new_fill, bool applied = true, bool update = true);
+
+ ///
+ /// Returns true if the fill is being applied.
+ ///
+ bool fill_applied() const;
+
+ // Font
+
+ ///
+ /// Returns the font to be applied to contents of cells using this format.
+ ///
+ class font &font();
+
+ ///
+ /// Returns the font to be applied to contents of cells using this format.
+ ///
+ const class font &font() const;
+
+ ///
+ /// Sets the font of this format to new_font and applies it if applied is true.
+ ///
+ void font(const xlnt::font &new_font, bool applied = true, bool update = true);
+
+ ///
+ /// Returns true if the font is being applied.
+ ///
+ bool font_applied() const;
+
+ // Number Format
+
+ ///
+ /// Returns the number format to be applied to text/numbers in cells using this format.
+ ///
+ class number_format &number_format();
+
+ ///
+ /// Returns the number format to be applied to text/numbers in cells using this format.
+ ///
+ const class number_format &number_format() const;
+
+ ///
+ /// Sets the number format applied to text/numbers in cells using this format
+ /// and applies it if applied is true.
+ ///
+ void number_format(const xlnt::number_format &new_number_format, bool applied = true, bool update = true);
+
+ ///
+ /// Returns true if the number format is being applied.
+ ///
+ bool number_format_applied() const;
+
+ // Protection
+
+ ///
+ /// Returns the protection to be applied to the contents of cells using this format.
+ ///
+ class protection &protection();
+
+ ///
+ /// Returns the protection to be applied to the contents of cells using this format.
+ ///
+ const class protection &protection() const;
+
+ ///
+ /// Sets the protection of the contents of the cell using this format. Applies it if
+ /// applied is true.
+ ///
+ void protection(const xlnt::protection &new_protection, bool applied = true, bool update = true);
+
+ ///
+ /// Returns true if the protection is being applied.
+ ///
+ bool protection_applied() const;
+
+ ///
+ /// Returns true if the formats are identical.
+ ///
+ XLNT_API friend bool operator==(const style &left, const style &right);
private:
friend struct detail::stylesheet;
+
style(detail::style_impl *d);
+
detail::style_impl *d_;
};
diff --git a/include/xlnt/workbook/workbook.hpp b/include/xlnt/workbook/workbook.hpp
index 72736d7e..fb1ebb55 100644
--- a/include/xlnt/workbook/workbook.hpp
+++ b/include/xlnt/workbook/workbook.hpp
@@ -36,6 +36,7 @@
namespace xlnt {
class alignment;
+class base_format;
class border;
class cell;
class cell_style;
@@ -419,7 +420,9 @@ public:
format &get_format(std::size_t format_index);
const format &get_format(std::size_t format_index) const;
- format &create_format();
+ format &create_format();
+ format &create_format(format pattern);
+ format &create_format(base_format pattern);
void clear_formats();
// styles
diff --git a/source/cell/cell.cpp b/source/cell/cell.cpp
index 0bcd539b..a43da945 100644
--- a/source/cell/cell.cpp
+++ b/source/cell/cell.cpp
@@ -30,8 +30,14 @@
#include
#include
#include
+#include
+#include
#include
+#include
+#include
#include
+#include
+#include
#include
#include
#include
@@ -44,6 +50,7 @@
#include
#include
+#include
namespace {
@@ -610,32 +617,104 @@ void cell::set_data_type(type t)
number_format cell::get_computed_number_format() const
{
- return get_computed_format().number_format();
+ number_format computed;
+
+ if (has_format() && get_format().number_format_applied())
+ {
+ computed = get_format().number_format();
+ }
+/*
+ if (has_style() && get_style().number_format_applied())
+ {
+ computed = get_style().number_format();
+ }
+*/
+ return computed;
}
font cell::get_computed_font() const
{
- return get_computed_format().font();
+ font computed;
+
+ if (has_format() && get_format().number_format_applied())
+ {
+ computed = get_format().font();
+ }
+/*
+ if (has_style() && get_style().number_format_applied())
+ {
+ computed = get_style().number_format();
+ }
+*/
+ return computed;
}
fill cell::get_computed_fill() const
{
- return get_computed_format().fill();
+ fill computed;
+
+ if (has_format() && get_format().number_format_applied())
+ {
+ computed = get_format().fill();
+ }
+/*
+ if (has_style() && get_style().number_format_applied())
+ {
+ computed = get_style().number_format();
+ }
+*/
+ return computed;
}
border cell::get_computed_border() const
{
- return get_computed_format().border();
+ border computed;
+
+ if (has_format() && get_format().number_format_applied())
+ {
+ computed = get_format().border();
+ }
+/*
+ if (has_style() && get_style().number_format_applied())
+ {
+ computed = get_style().number_format();
+ }
+*/
+ return computed;
}
alignment cell::get_computed_alignment() const
{
- return get_computed_format().alignment();
+ alignment computed;
+
+ if (has_format() && get_format().number_format_applied())
+ {
+ computed = get_format().alignment();
+ }
+/*
+ if (has_style() && get_style().number_format_applied())
+ {
+ computed = get_style().number_format();
+ }
+*/
+ return computed;
}
protection cell::get_computed_protection() const
{
- return get_computed_format().protection();
+ protection computed;
+
+ if (has_format() && get_format().number_format_applied())
+ {
+ computed = get_format().protection();
+ }
+/*
+ if (has_style() && get_style().number_format_applied())
+ {
+ computed = get_style().number_format();
+ }
+*/
+ return computed;
}
void cell::clear_value()
@@ -758,44 +837,80 @@ XLNT_API timedelta cell::get_value() const
void cell::set_alignment(const xlnt::alignment &alignment_)
{
- auto &format = duplicate_format();
- format.alignment(alignment_, true);
- d_->format_id_ = format.id();
+ if (!has_format())
+ {
+ set_format(get_workbook().create_format());
+ get_format().alignment(alignment_, true, true);
+ }
+ else
+ {
+ get_format().alignment(alignment_, true, false);
+ }
}
void cell::set_border(const xlnt::border &border_)
{
- auto &format = duplicate_format();
- format.border(border_, true);
- d_->format_id_ = format.id();
+ if (!has_format())
+ {
+ set_format(get_workbook().create_format());
+ get_format().border(border_, true, true);
+ }
+ else
+ {
+ get_format().border(border_, true, false);
+ }
}
void cell::set_fill(const xlnt::fill &fill_)
{
- auto &format = duplicate_format();
- format.fill(fill_, true);
- d_->format_id_ = format.id();
+ if (!has_format())
+ {
+ set_format(get_workbook().create_format());
+ get_format().fill(fill_, true, true);
+ }
+ else
+ {
+ get_format().fill(fill_, true, false);
+ }
}
void cell::set_font(const font &font_)
{
- auto &format = duplicate_format();
- format.font(font_, true);
- d_->format_id_ = format.id();
+ if (!has_format())
+ {
+ set_format(get_workbook().create_format());
+ get_format().font(font_, true, true);
+ }
+ else
+ {
+ get_format().font(font_, true, false);
+ }
}
void cell::set_number_format(const number_format &number_format_)
{
- auto &format = duplicate_format();
- format.number_format(number_format_, true);
- d_->format_id_ = format.id();
+ if (!has_format())
+ {
+ set_format(get_workbook().create_format());
+ get_format().number_format(number_format_, true, true);
+ }
+ else
+ {
+ get_format().number_format(number_format_, true, false);
+ }
}
void cell::set_protection(const xlnt::protection &protection_)
{
- auto &format = duplicate_format();
- format.protection(protection_, true);
- d_->format_id_ = format.id();
+ if (!has_format())
+ {
+ set_format(get_workbook().create_format());
+ get_format().protection(protection_, true, true);
+ }
+ else
+ {
+ get_format().protection(protection_, true, false);
+ }
}
template <>
@@ -898,81 +1013,39 @@ void cell::clear_style()
{
if (has_format())
{
- get_format_internal().clear_style();
+ get_format().d_->style.clear();
}
}
void cell::set_style(const style &new_style)
{
- auto &new_format = duplicate_format();
- new_format.style(new_style);
- d_->format_id_ = new_format.id();
+ if (!has_format())
+ {
+ set_format(get_workbook().create_format());
+ }
+
+ auto current_format = get_format();
+ current_format.d_->style = new_style.name();
}
void cell::set_style(const std::string &style_name)
{
- auto &new_format = duplicate_format();
- new_format.style(get_workbook().get_style(style_name).name());
- d_->format_id_ = new_format.id();
+ set_style(get_workbook().get_style(style_name));
}
style cell::get_style() const
{
- if (!has_format() || !get_format().has_style())
+ if (!has_format() || !get_format().d_->style.is_set())
{
throw invalid_attribute();
}
- return get_format().style();
+ return get_workbook().get_style(get_format().d_->style.get());
}
bool cell::has_style() const
{
- return has_format() && get_format().has_style();
-}
-
-base_format cell::get_computed_format() const
-{
- base_format result;
-
- // Check style first
-
- if (has_style())
- {
- style cell_style = get_style();
-
- if (cell_style.alignment_applied()) result.alignment(cell_style.alignment(), true);
- if (cell_style.border_applied()) result.border(cell_style.border(), true);
- if (cell_style.fill_applied()) result.fill(cell_style.fill(), true);
- if (cell_style.font_applied()) result.font(cell_style.font(), true);
- if (cell_style.number_format_applied()) result.number_format(cell_style.number_format(), true);
- if (cell_style.protection_applied()) result.protection(cell_style.protection(), true);
- }
-
- // Cell format overrides style
-
- if (has_format())
- {
- format cell_format = get_format();
-
- if (cell_format.alignment_applied()) result.alignment(cell_format.alignment(), true);
- if (cell_format.border_applied()) result.border(cell_format.border(), true);
- if (cell_format.fill_applied()) result.fill(cell_format.fill(), true);
- if (cell_format.font_applied()) result.font(cell_format.font(), true);
- if (cell_format.number_format_applied()) result.number_format(cell_format.number_format(), true);
- if (cell_format.protection_applied()) result.protection(cell_format.protection(), true);
- }
-
- // Use defaults for any remaining non-applied components
-
- if (!result.alignment_applied()) result.alignment(alignment(), true);
- if (!result.border_applied()) result.border(border(), true);
- if (!result.fill_applied()) result.fill(fill(), true);
- if (!result.font_applied()) result.font(font(), true);
- if (!result.number_format_applied()) result.number_format(number_format(), true);
- if (!result.protection_applied()) result.protection(protection(), true);
-
- return result;
+ return has_format() && get_format().d_->style.is_set();
}
format &cell::get_format_internal()
@@ -985,25 +1058,6 @@ format &cell::get_format_internal()
return get_workbook().get_format(*d_->format_id_);
}
-format &cell::duplicate_format()
-{
- auto &new_format = get_workbook().create_format();
-
- if (has_format())
- {
- auto ¤t_format = get_format_internal();
-
- new_format.alignment(current_format.alignment(), current_format.alignment_applied());
- new_format.border(current_format.border(), current_format.border_applied());
- new_format.fill(current_format.fill(), current_format.fill_applied());
- new_format.font(current_format.font(), current_format.font_applied());
- new_format.number_format(current_format.number_format(), current_format.number_format_applied());
- new_format.protection(current_format.protection(), current_format.protection_applied());
- }
-
- return new_format;
-}
-
format cell::get_format() const
{
if (!d_->format_id_)
diff --git a/source/cell/tests/test_cell.hpp b/source/cell/tests/test_cell.hpp
index c3f1c4a4..51cb7ab5 100644
--- a/source/cell/tests/test_cell.hpp
+++ b/source/cell/tests/test_cell.hpp
@@ -18,6 +18,19 @@ public:
wb_guess_types.set_guess_types(true);
}
+ void test_temp()
+ {
+ xlnt::workbook wb;
+ auto cell = wb[0].get_cell("A1");
+ cell.set_value("right");
+ cell.set_alignment(xlnt::alignment().horizontal(xlnt::horizontal_alignment::right));
+ cell.set_font(xlnt::font().size(20).color(xlnt::color::white()));
+ cell.set_fill(xlnt::fill::solid(xlnt::color::black()));
+ wb.create_style("yellow-fill").fill(xlnt::fill::solid(xlnt::color::yellow()), true);
+ cell.set_style("yellow-fill");
+ wb.save("temp.xlsx");
+ }
+
void test_infer_numeric()
{
auto ws = wb_guess_types.create_sheet();
diff --git a/source/detail/format_impl.hpp b/source/detail/format_impl.hpp
index bc1e6561..b9972d63 100644
--- a/source/detail/format_impl.hpp
+++ b/source/detail/format_impl.hpp
@@ -29,14 +29,42 @@ struct format_impl
std::size_t id;
+ bool alignment_applied = false;
optional alignment_id;
+ bool border_applied = false;
optional border_id;
+ bool fill_applied = false;
optional fill_id;
+ bool font_applied = false;
optional font_id;
+ bool number_format_applied = false;
optional number_format_id;
+ bool protection_applied = false;
optional protection_id;
optional style;
+
+ bool operator==(const format_impl &other) const
+ {
+ return alignment_applied == other.alignment_applied
+ && alignment_id.is_set() == other.alignment_id.is_set()
+ && (!alignment_id.is_set() || alignment_id.get() == other.alignment_id.get())
+ && border_applied == other.border_applied
+ && border_id.is_set() == other.border_id.is_set()
+ && (!border_id.is_set() || border_id.get() == other.border_id.get())
+ && fill_applied == other.fill_applied
+ && fill_id.is_set() == other.fill_id.is_set()
+ && (!fill_id.is_set() || fill_id.get() == other.fill_id.get())
+ && font_applied == other.font_applied
+ && font_id.is_set() == other.font_id.is_set()
+ && (!font_id.is_set() || font_id.get() == other.font_id.get())
+ && number_format_applied == other.number_format_applied
+ && number_format_id.is_set() == other.number_format_id.is_set()
+ && (!number_format_id.is_set() || number_format_id.get() == other.number_format_id.get())
+ && protection_applied == other.protection_applied
+ && protection_id.is_set() == other.protection_id.is_set()
+ && (!protection_id.is_set() || protection_id.get() == other.protection_id.get());
+ }
};
} // namespace detail
diff --git a/source/detail/style_impl.hpp b/source/detail/style_impl.hpp
index d1c71ff7..86cefd49 100644
--- a/source/detail/style_impl.hpp
+++ b/source/detail/style_impl.hpp
@@ -31,12 +31,18 @@ struct style_impl
optional builtin_id;
optional outline_style;
- optional alignment;
- optional border;
- optional fill;
- optional font;
- optional number_format;
- optional protection;
+ bool alignment_applied = false;
+ optional alignment_id;
+ bool border_applied = false;
+ optional border_id;
+ bool fill_applied = false;
+ optional fill_id;
+ bool font_applied = false;
+ optional font_id;
+ bool number_format_applied = false;
+ optional number_format_id;
+ bool protection_applied = false;
+ optional protection_id;
};
} // namespace detail
diff --git a/source/detail/stylesheet.hpp b/source/detail/stylesheet.hpp
index b9bb9bc6..6c58c14b 100644
--- a/source/detail/stylesheet.hpp
+++ b/source/detail/stylesheet.hpp
@@ -25,6 +25,7 @@
#include
#include
+#include
#include
#include
@@ -38,23 +39,23 @@ namespace detail {
struct stylesheet
{
- ~stylesheet()
- {
- }
-
format &create_format()
{
- format_impls.push_back(format_impl());
- auto &impl = format_impls.back();
- impl.parent = this;
- impl.id = format_impls.size() - 1;
- formats.push_back(format(&impl));
+ format_impls.push_back(format_impl());
+ auto &impl = format_impls.back();
+ impl.parent = this;
+ impl.id = format_impls.size() - 1;
+ formats.push_back(format(&impl));
auto &format = formats.back();
-
+
if (!alignments.empty())
{
format.alignment(alignments.front(), false);
}
+ else
+ {
+ format.alignment(alignment(), false);
+ }
if (!borders.empty())
{
@@ -73,7 +74,7 @@ struct stylesheet
if (!number_formats.empty())
{
- format.number_format(number_formats.front(), false);
+ format.number_format(number_formats.begin()->second, false);
}
if (!protections.empty())
@@ -84,10 +85,27 @@ struct stylesheet
return format;
}
- format &get_format(std::size_t index)
- {
- return formats.at(index);
- }
+ format &get_format(std::size_t index)
+ {
+ return formats.at(index);
+ }
+
+ std::pair find_format(format pattern)
+ {
+ std::size_t index = 0;
+
+ for (const format &f : formats)
+ {
+ if (f == pattern)
+ {
+ return {true, index};
+ }
+
+ ++index;
+ }
+
+ return {false, 0};
+ }
style &create_style()
{
@@ -130,14 +148,26 @@ struct stylesheet
for (const auto &nf : number_formats)
{
- if (nf.get_id() >= id)
+ if (nf.second.get_id() >= id)
{
- id = nf.get_id() + 1;
+ id = nf.second.get_id() + 1;
}
}
return id;
}
+
+ std::size_t add_alignment(const alignment &new_alignment)
+ {
+ auto match = std::find(alignments.begin(), alignments.end(), new_alignment);
+
+ if (match == alignments.end())
+ {
+ match = alignments.insert(alignments.end(), new_alignment);
+ }
+
+ return std::distance(alignments.begin(), match);
+ }
std::size_t add_border(const border &new_border)
{
@@ -196,6 +226,26 @@ struct stylesheet
return index;
}
+ std::size_t add_protection(const protection &new_protection)
+ {
+ std::size_t index = 0;
+
+ for (const auto &p : protections)
+ {
+ if (p == new_protection)
+ {
+ return index;
+ }
+
+ ++index;
+ }
+
+ protections.push_back(new_protection);
+
+ return index;
+ }
+
+
void clear()
{
format_impls.clear();
@@ -224,7 +274,7 @@ struct stylesheet
std::vector borders;
std::vector fills;
std::vector fonts;
- std::vector number_formats;
+ std::unordered_map number_formats;
std::vector protections;
std::vector colors;
diff --git a/source/detail/xlsx_consumer.cpp b/source/detail/xlsx_consumer.cpp
index 8b84cbc1..9700266e 100644
--- a/source/detail/xlsx_consumer.cpp
+++ b/source/detail/xlsx_consumer.cpp
@@ -1265,7 +1265,7 @@ void xlsx_consumer::read_stylesheet()
nf.set_format_string(format_string);
nf.set_id(string_to_size_t(parser().attribute("numFmtId")));
- stylesheet.number_formats.push_back(nf);
+ stylesheet.number_formats[nf.get_id()] = nf;
parser().next_expect(xml::parser::event_type::end_element); // numFmt
}
@@ -1510,9 +1510,9 @@ void xlsx_consumer::read_stylesheet()
for (const auto &nf : stylesheet.number_formats)
{
- if (nf.get_id() == number_format_id)
+ if (nf.first == number_format_id)
{
- result = nf;
+ result = nf.second;
is_custom_number_format = true;
break;
}
@@ -1552,7 +1552,7 @@ void xlsx_consumer::read_stylesheet()
{
auto &new_format = stylesheet.create_format();
- new_format.style(stylesheet.styles.at(record.style_id.first).name());
+ new_format.d_->style = stylesheet.styles.at(record.style_id.first).name();
new_format.alignment(record.alignment.first, record.alignment.second);
new_format.border(stylesheet.borders.at(record.border_id.first), record.border_id.second);
diff --git a/source/detail/xlsx_producer.cpp b/source/detail/xlsx_producer.cpp
index bbd5b453..523060e0 100644
--- a/source/detail/xlsx_producer.cpp
+++ b/source/detail/xlsx_producer.cpp
@@ -776,8 +776,8 @@ void xlsx_producer::write_styles(const relationship &rel)
for (const auto &num_fmt : number_formats)
{
serializer().start_element(xmlns, "numFmt");
- serializer().attribute("numFmtId", num_fmt.get_id());
- serializer().attribute("formatCode", num_fmt.get_format_string());
+ serializer().attribute("numFmtId", num_fmt.first);
+ serializer().attribute("formatCode", num_fmt.second.get_format_string());
serializer().end_element(xmlns, "numFmt");
}
@@ -1117,11 +1117,11 @@ void xlsx_producer::write_styles(const relationship &rel)
if (current_format.alignment_applied()) serializer().attribute("applyAlignment", write_bool(true));
if (current_format.protection_applied()) serializer().attribute("applyProtection", write_bool(true));
- if (current_format.has_style())
+ if (current_format.d_->style.is_set())
{
serializer().attribute("xfId", std::distance(stylesheet.styles.begin(),
std::find_if(stylesheet.styles.begin(), stylesheet.styles.end(),
- [&](const xlnt::style &s) { return s.name() == current_format.style().name(); })));
+ [&](const xlnt::style &s) { return s.name() == current_format.d_->style.get(); })));
}
if (current_format.alignment_applied())
diff --git a/source/styles/base_format.cpp b/source/styles/base_format.cpp
index 1d42898c..e69de29b 100644
--- a/source/styles/base_format.cpp
+++ b/source/styles/base_format.cpp
@@ -1,154 +0,0 @@
-// 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
-
-namespace xlnt {
-
-alignment &base_format::alignment()
-{
- return alignment_;
-}
-
-const alignment &base_format::alignment() const
-{
- return alignment_;
-}
-
-void base_format::alignment(const xlnt::alignment &new_alignment, bool apply)
-{
- alignment_ = new_alignment;
- apply_alignment_ = apply;
-}
-
-number_format &base_format::number_format()
-{
- return number_format_;
-}
-
-const number_format &base_format::number_format() const
-{
- return number_format_;
-}
-
-void base_format::number_format(const xlnt::number_format &new_number_format, bool apply)
-{
- number_format_ = new_number_format;
- apply_number_format_ = apply;
-}
-
-border &base_format::border()
-{
- return border_;
-}
-
-const border &base_format::border() const
-{
- return border_;
-}
-
-void base_format::border(const xlnt::border &new_border, bool apply)
-{
- border_ = new_border;
- apply_border_ = apply;
-}
-
-fill &base_format::fill()
-{
- return fill_;
-}
-
-const fill &base_format::fill() const
-{
- return fill_;
-}
-
-void base_format::fill(const xlnt::fill &new_fill, bool apply)
-{
- fill_ = new_fill;
- apply_fill_ = apply;
-}
-
-font &base_format::font()
-{
- return font_;
-}
-
-const font &base_format::font() const
-{
- return font_;
-}
-
-void base_format::font(const xlnt::font &new_font, bool apply)
-{
- font_ = new_font;
- apply_font_ = apply;
-}
-
-protection &base_format::protection()
-{
- return protection_;
-}
-
-const protection &base_format::protection() const
-{
- return protection_;
-}
-
-void base_format::protection(const xlnt::protection &new_protection, bool apply)
-{
- protection_ = new_protection;
- apply_protection_ = apply;
-}
-
-bool base_format::alignment_applied() const
-{
- return apply_alignment_;
-}
-
-bool base_format::border_applied() const
-{
- return apply_border_;
-}
-
-bool base_format::fill_applied() const
-{
- return apply_fill_;
-}
-
-bool base_format::font_applied() const
-{
- return apply_font_;
-}
-
-bool base_format::number_format_applied() const
-{
- return apply_number_format_;
-}
-
-bool base_format::protection_applied() const
-{
- return apply_protection_;
-}
-
-} // namespace xlnt
diff --git a/source/styles/format.cpp b/source/styles/format.cpp
index 1bfb5cb7..88f76870 100644
--- a/source/styles/format.cpp
+++ b/source/styles/format.cpp
@@ -38,132 +38,334 @@ std::size_t format::id() const
return d_->id;
}
-void format::clear_style()
+alignment &format::alignment()
{
- d_->style.clear();
+ return d_->parent->alignments.at(d_->alignment_id);
}
-void format::style(const xlnt::style &new_style)
+const alignment &format::alignment() const
{
- d_->style = new_style.name();
+ return d_->parent->alignments.at(d_->alignment_id);
}
-void format::style(const std::string &new_style)
+void format::alignment(const xlnt::alignment &new_alignment, bool applied, bool update)
{
- for (auto &style : d_->parent->styles)
- {
- if (style.name() == new_style)
- {
- d_->style = new_style;
- return;
- }
- }
+ auto alignment_id = d_->parent->add_alignment(new_alignment);
- throw key_not_found();
-}
+ if (update)
+ {
+ d_->alignment_id = alignment_id;
+ d_->alignment_applied = applied;
+ }
+ else
+ {
+ auto impl_copy = *d_;
-bool format::has_style() const
-{
- return d_->style;
-}
+ impl_copy.alignment_id = alignment_id;
+ impl_copy.alignment_applied = applied;
-const style &format::style() const
-{
- if (!has_style())
- {
- throw invalid_attribute();
- }
+ auto match = std::find(d_->parent->format_impls.begin(), d_->parent->format_impls.end(), impl_copy);
- return d_->parent->get_style(*d_->style);
+ if (match != d_->parent->format_impls.end())
+ {
+ d_ = &*match;
+ }
+ else
+ {
+ d_->parent->format_impls.push_back(impl_copy);
+ d_ = &d_->parent->format_impls.back();
+ }
+ }
}
xlnt::border &format::border()
{
- return base_format::border();
+ const auto &self = *this;
+ return const_cast(self.border());
}
const xlnt::border &format::border() const
{
- return base_format::border();
+ if (!d_->border_id)
+ {
+ throw xlnt::exception("no border");
+ }
+
+ return d_->parent->borders.at(d_->border_id.get());
}
-void format::border(const xlnt::border &new_border, bool applied)
+void format::border(const xlnt::border &new_border, bool applied, bool update)
{
- border_id(d_->parent->add_border(new_border));
- base_format::border(new_border, applied);
+ auto border_id = d_->parent->add_border(new_border);
+
+ if (update)
+ {
+ d_->border_id = border_id;
+ d_->border_applied = applied;
+ }
+ else
+ {
+ auto impl_copy = *d_;
+
+ impl_copy.border_id = border_id;
+ impl_copy.border_applied = applied;
+
+ auto match = std::find(d_->parent->format_impls.begin(), d_->parent->format_impls.end(), impl_copy);
+
+ if (match != d_->parent->format_impls.end())
+ {
+ d_ = &*match;
+ }
+ else
+ {
+ d_->parent->format_impls.push_back(impl_copy);
+ d_ = &d_->parent->format_impls.back();
+ }
+ }
}
xlnt::fill &format::fill()
{
- return base_format::fill();
+ const auto &self = *this;
+ return const_cast(self.fill());
}
const xlnt::fill &format::fill() const
{
- return base_format::fill();
+ if (!d_->fill_id)
+ {
+ throw xlnt::exception("no border");
+ }
+
+ return d_->parent->fills.at(d_->fill_id.get());
}
-void format::fill(const xlnt::fill &new_fill, bool applied)
+void format::fill(const xlnt::fill &new_fill, bool applied, bool update)
{
- fill_id(d_->parent->add_fill(new_fill));
- base_format::fill(new_fill, applied);
+ auto fill_id = d_->parent->add_fill(new_fill);
+
+ if (update)
+ {
+ d_->fill_id = fill_id;
+ d_->fill_applied = applied;
+ }
+ else
+ {
+ auto impl_copy = *d_;
+
+ impl_copy.fill_id = fill_id;
+ impl_copy.fill_applied = applied;
+
+ auto match = std::find(d_->parent->format_impls.begin(), d_->parent->format_impls.end(), impl_copy);
+
+ if (match != d_->parent->format_impls.end())
+ {
+ d_ = &*match;
+ }
+ else
+ {
+ d_->parent->format_impls.push_back(impl_copy);
+ d_ = &d_->parent->format_impls.back();
+ }
+ }
}
xlnt::font &format::font()
{
- return base_format::font();
+ const auto &self = *this;
+ return const_cast(self.font());
}
const xlnt::font &format::font() const
{
- return base_format::font();
+ if (!d_->font_id)
+ {
+ throw xlnt::exception("no border");
+ }
+
+ return d_->parent->fonts.at(d_->font_id.get());
}
-void format::font(const xlnt::font &new_font, bool applied)
+void format::font(const xlnt::font &new_font, bool applied, bool update)
{
- font_id(d_->parent->add_font(new_font));
- base_format::font(new_font, applied);
+ auto font_id = d_->parent->add_font(new_font);
+
+ if (update)
+ {
+ d_->font_id = font_id;
+ d_->font_applied = applied;
+ }
+ else
+ {
+ auto impl_copy = *d_;
+
+ impl_copy.font_id = font_id;
+ impl_copy.font_applied = applied;
+
+ auto match = std::find(d_->parent->format_impls.begin(), d_->parent->format_impls.end(), impl_copy);
+
+ if (match != d_->parent->format_impls.end())
+ {
+ d_ = &*match;
+ }
+ else
+ {
+ d_->parent->format_impls.push_back(impl_copy);
+ d_ = &d_->parent->format_impls.back();
+ }
+ }
}
xlnt::number_format &format::number_format()
{
- return base_format::number_format();
+ const auto &self = *this;
+ return const_cast(self.number_format());
}
const xlnt::number_format &format::number_format() const
{
- return base_format::number_format();
+ if (!d_->number_format_id)
+ {
+ throw xlnt::exception("no number format");
+ }
+
+ return d_->parent->number_formats.at(d_->number_format_id.get());
}
-void format::number_format(const xlnt::number_format &new_number_format, bool applied)
+void format::number_format(const xlnt::number_format &new_number_format, bool applied, bool update)
{
auto copy = new_number_format;
if (!copy.has_id())
{
copy.set_id(d_->parent->next_custom_number_format_id());
- d_->parent->number_formats.push_back(copy);
+ d_->parent->number_formats[copy.get_id()] = copy;
}
- base_format::number_format(copy, applied);
+ auto number_format_id = copy.get_id();
+
+ if (update)
+ {
+ d_->number_format_id = number_format_id;
+ d_->number_format_applied = applied;
+ }
+ else
+ {
+ auto impl_copy = *d_;
+
+ impl_copy.number_format_id = number_format_id;
+ impl_copy.number_format_applied = applied;
+
+ auto match = std::find(d_->parent->format_impls.begin(), d_->parent->format_impls.end(), impl_copy);
+
+ if (match != d_->parent->format_impls.end())
+ {
+ d_ = &*match;
+ }
+ else
+ {
+ d_->parent->format_impls.push_back(impl_copy);
+ d_ = &d_->parent->format_impls.back();
+ }
+ }
}
-format &format::border_id(std::size_t id)
+protection &format::protection()
{
- d_->border_id = id;
- return *this;
+ return d_->parent->protections.at(d_->protection_id);
}
-format &format::fill_id(std::size_t id)
+const protection &format::protection() const
{
- d_->fill_id = id;
- return *this;
+ return d_->parent->protections.at(d_->protection_id);
}
-format &format::font_id(std::size_t id)
+void format::protection(const xlnt::protection &new_protection, bool applied, bool update)
{
- d_->font_id = id;
- return *this;
+ auto protection_id = d_->parent->add_protection(new_protection);
+
+ if (update)
+ {
+ d_->protection_id = protection_id;
+ d_->protection_applied = applied;
+ }
+ else
+ {
+ auto impl_copy = *d_;
+
+ impl_copy.protection_id = protection_id;
+ impl_copy.protection_applied = applied;
+
+ auto match = std::find(d_->parent->format_impls.begin(), d_->parent->format_impls.end(), impl_copy);
+
+ if (match != d_->parent->format_impls.end())
+ {
+ d_ = &*match;
+ }
+ else
+ {
+ d_->parent->format_impls.push_back(impl_copy);
+ d_ = &d_->parent->format_impls.back();
+ }
+ }
+}
+
+bool format::alignment_applied() const
+{
+ return d_->alignment_applied;
+}
+
+bool format::border_applied() const
+{
+ return d_->border_applied;
+}
+
+bool format::fill_applied() const
+{
+ return d_->fill_applied;
+}
+
+bool format::font_applied() const
+{
+ return d_->font_applied;
+}
+
+bool format::number_format_applied() const
+{
+ return d_->number_format_applied;
+}
+
+bool format::protection_applied() const
+{
+ return d_->protection_applied;
+}
+
+
+
+XLNT_API bool operator==(const format &left, const format &right)
+{
+ if (left.alignment_applied() != right.alignment_applied()) return false;
+ if (left.alignment_applied() && left.alignment() != right.alignment()) return false;
+
+ if (left.border_applied() != right.border_applied()) return false;
+ if (left.border_applied() && left.border() != right.border()) return false;
+
+ if (left.fill_applied() != right.fill_applied()) return false;
+ if (left.fill_applied() && left.fill() != right.fill()) return false;
+
+ if (left.font_applied() != right.font_applied()) return false;
+ if (left.font_applied() && left.font() != right.font()) return false;
+
+ if (left.number_format_applied() != right.number_format_applied()) return false;
+ if (left.number_format_applied() && left.number_format() != right.number_format()) return false;
+
+ if (left.protection_applied() != right.protection_applied()) return false;
+ if (left.protection_applied() && left.protection() != right.protection()) return false;
+
+ if (left.d_->style.is_set() != right.d_->style.is_set()) return false;
+ if (left.d_->style.is_set() && left.d_->style.get() != right.d_->style.get()) return false;
+
+ return true;
}
} // namespace xlnt
diff --git a/source/styles/style.cpp b/source/styles/style.cpp
index ef3f0e71..a6848203 100644
--- a/source/styles/style.cpp
+++ b/source/styles/style.cpp
@@ -22,13 +22,14 @@
// @license: http://www.opensource.org/licenses/mit-license.php
// @author: see AUTHORS file
+#include // include order is important here
+#include
#include
#include
#include
#include
#include
#include
-#include // include order is important here
#include
namespace xlnt {
@@ -81,9 +82,171 @@ style &style::custom(bool value)
return *this;
}
-bool style::operator==(const style &other)
+alignment &style::alignment()
{
- return d_ == other.d_;
+ return d_->parent->alignments.at(d_->alignment_id);
+}
+
+const alignment &style::alignment() const
+{
+ return d_->parent->alignments.at(d_->alignment_id);
+}
+
+void style::alignment(const xlnt::alignment &new_alignment, bool applied, bool update)
+{
+ if (update)
+ {
+ d_->alignment_id = 0;
+ }
+}
+
+xlnt::border &style::border()
+{
+ const auto &self = *this;
+ return const_cast(self.border());
+}
+
+const xlnt::border &style::border() const
+{
+ if (!d_->border_id)
+ {
+ throw xlnt::exception("no border");
+ }
+
+ return d_->parent->borders.at(d_->border_id.get());
+}
+
+void style::border(const xlnt::border &new_border, bool applied, bool update)
+{
+ d_->border_id = d_->parent->add_border(new_border);
+}
+
+xlnt::fill &style::fill()
+{
+ const auto &self = *this;
+ return const_cast(self.fill());
+}
+
+const xlnt::fill &style::fill() const
+{
+ if (!d_->fill_id)
+ {
+ throw xlnt::exception("no border");
+ }
+
+ return d_->parent->fills.at(d_->fill_id.get());
+}
+
+void style::fill(const xlnt::fill &new_fill, bool applied, bool update)
+{
+ d_->fill_id = d_->parent->add_fill(new_fill);
+ d_->fill_applied = applied;
+}
+
+xlnt::font &style::font()
+{
+ const auto &self = *this;
+ return const_cast(self.font());
+}
+
+const xlnt::font &style::font() const
+{
+ if (!d_->font_id)
+ {
+ throw xlnt::exception("no border");
+ }
+
+ return d_->parent->fonts.at(d_->font_id.get());
+}
+
+void style::font(const xlnt::font &new_font, bool applied, bool update)
+{
+ d_->font_id = d_->parent->add_font(new_font);
+ d_->font_applied = applied;
+}
+
+xlnt::number_format &style::number_format()
+{
+ const auto &self = *this;
+ return const_cast(self.number_format());
+}
+
+const xlnt::number_format &style::number_format() const
+{
+ if (!d_->number_format_id)
+ {
+ throw xlnt::exception("no number format");
+ }
+
+ return d_->parent->number_formats.at(d_->number_format_id.get());
+}
+
+void style::number_format(const xlnt::number_format &new_number_format, bool applied, bool update)
+{
+ auto copy = new_number_format;
+
+ if (!copy.has_id())
+ {
+ copy.set_id(d_->parent->next_custom_number_format_id());
+ d_->parent->number_formats[copy.get_id()] = copy;
+ }
+
+ d_->number_format_id = copy.get_id();
+ d_->number_format_applied = applied;
+}
+
+protection &style::protection()
+{
+ return d_->parent->protections.at(d_->protection_id);
+}
+
+const protection &style::protection() const
+{
+ return d_->parent->protections.at(d_->protection_id);
+}
+
+void style::protection(const xlnt::protection &new_protection, bool applied, bool update)
+{
+ if (update)
+ {
+ d_->protection_id = 0;
+ }
+}
+
+
+bool style::alignment_applied() const
+{
+ return d_->alignment_applied;
+}
+
+bool style::border_applied() const
+{
+ return d_->border_applied;
+}
+
+bool style::fill_applied() const
+{
+ return d_->fill_applied;
+}
+
+bool style::font_applied() const
+{
+ return d_->font_applied;
+}
+
+bool style::number_format_applied() const
+{
+ return d_->number_format_applied;
+}
+
+bool style::protection_applied() const
+{
+ return d_->protection_applied;
+}
+
+XLNT_API bool operator==(const style &left, const style &right)
+{
+ return left.d_ == right.d_;
}
} // namespace xlnt
diff --git a/source/workbook/workbook.cpp b/source/workbook/workbook.cpp
index de13debf..53185d57 100644
--- a/source/workbook/workbook.cpp
+++ b/source/workbook/workbook.cpp
@@ -165,7 +165,7 @@ workbook workbook::empty_excel()
auto &default_format = wb.create_format();
default_format.font(default_font, false);
default_format.border(default_border, false);
- default_format.style("Normal");
+ default_format.d_->style.set("Normal");
wb.set_theme(theme());
@@ -255,7 +255,7 @@ workbook workbook::empty_libre_office()
auto default_number_format = xlnt::number_format();
default_number_format.set_format_string("General");
default_number_format.set_id(164);
- wb.d_->stylesheet_.number_formats.push_back(default_number_format);
+ wb.d_->stylesheet_.number_formats[default_number_format.get_id()] = default_number_format;
auto default_protection = xlnt::protection()
.locked(true)
@@ -314,7 +314,7 @@ workbook workbook::empty_libre_office()
format.number_format(default_number_format, true);
format.alignment(default_alignment, true);
format.protection(default_protection, true);
- format.style("Normal");
+ format.d_->style.set("Normal");
wb.d_->has_file_version_ = true;
wb.d_->file_version_.app_name = "Calc";
@@ -993,10 +993,32 @@ std::vector workbook::get_named_ranges() const
format &workbook::create_format()
{
- register_stylesheet_in_manifest();
+ register_stylesheet_in_manifest();
return d_->stylesheet_.create_format();
}
+format &workbook::create_format(format pattern)
+{
+ register_stylesheet_in_manifest();
+
+ auto existing = d_->stylesheet_.find_format(pattern);
+
+ if (existing.first)
+ {
+ return d_->stylesheet_.get_format(existing.second);
+ }
+
+ auto &new_format = create_format();
+ new_format.alignment(pattern.alignment(), pattern.alignment_applied());
+ new_format.border(pattern.border(), pattern.border_applied());
+ new_format.fill(pattern.fill(), pattern.fill_applied());
+ new_format.font(pattern.font(), pattern.font_applied());
+ new_format.number_format(pattern.number_format(), pattern.number_format_applied());
+ new_format.protection(pattern.protection(), pattern.protection_applied());;
+ new_format.d_->style.set(pattern.d_->style.get());
+ return new_format;
+}
+
bool workbook::has_style(const std::string &name) const
{
return d_->stylesheet_.has_style(name);
diff --git a/third-party/botan b/third-party/botan
index dad94a55..73c2605f 160000
--- a/third-party/botan
+++ b/third-party/botan
@@ -1 +1 @@
-Subproject commit dad94a550613733d8c75b2fbd8db47048dfdaf13
+Subproject commit 73c2605f50e6192bf6cb560c51d32bc53b4c5597