diff --git a/include/xlnt/cell/cell.hpp b/include/xlnt/cell/cell.hpp
index 941217b8..0b3d40e3 100644
--- a/include/xlnt/cell/cell.hpp
+++ b/include/xlnt/cell/cell.hpp
@@ -426,7 +426,12 @@ public:
///
/// Returns a wrapper pointing to the named style applied to this cell.
///
- const class style style() const;
+ class style style();
+
+ ///
+ /// Returns a wrapper pointing to the named style applied to this cell.
+ ///
+ const class style style() const;
///
/// Sets the named style applied to this cell to a style named style_name.
diff --git a/include/xlnt/styles/format.hpp b/include/xlnt/styles/format.hpp
index 60b36ddc..0117aabb 100755
--- a/include/xlnt/styles/format.hpp
+++ b/include/xlnt/styles/format.hpp
@@ -43,6 +43,7 @@ namespace detail {
struct format_impl;
struct stylesheet;
+class xlsx_producer;
} // namespace detail
@@ -52,11 +53,6 @@ struct stylesheet;
class XLNT_API format
{
public:
- ///
- ///
- ///
- std::size_t id() const;
-
// Alignment
///
@@ -234,10 +230,16 @@ public:
///
///
///
- const class style style() const;
+ class style style();
+
+ ///
+ ///
+ ///
+ const class style style() const;
private:
friend struct detail::stylesheet;
+ friend class detail::xlsx_producer;
friend class cell;
///
@@ -245,6 +247,11 @@ private:
///
format(detail::format_impl *d);
+ ///
+ ///
+ ///
+ std::size_t id() const;
+
///
///
///
diff --git a/include/xlnt/styles/style.hpp b/include/xlnt/styles/style.hpp
index 4fa07d83..c76432b4 100755
--- a/include/xlnt/styles/style.hpp
+++ b/include/xlnt/styles/style.hpp
@@ -61,81 +61,79 @@ public:
style() = delete;
///
- /// Default copy constructor
+ /// Default copy constructor. Constructs a style using the same PIMPL as other.
///
style(const style &other) = default;
///
- /// Return the name of this style.
+ /// Returns the name of this style.
///
std::string name() const;
///
- ///
+ /// Sets the name of this style to name.
///
style name(const std::string &name);
///
- ///
+ /// Returns true if this style is hidden.
///
bool hidden() const;
///
- ///
+ /// Sets the hidden state of this style to value. A hidden style will not
+ /// be shown in the list of selectable styles in the UI, but will still
+ /// apply its formatting to cells using it.
///
style hidden(bool value);
///
- ///
+ /// Returns true if this is a builtin style that has been customized and
+ /// should therefore be persisted in the workbook.
///
- optional custom() const;
+ bool custom_builtin() const;
///
- ///
+ /// Returns the index of the builtin style that this style is an instance
+ /// of or is a customized version thereof. If style::builtin() is false,
+ /// this will throw an invalid_attribute exception.
///
- style custom(bool value);
+ std::size_t builtin_id() const;
+
+ ///
+ /// Returns true if this is a builtin style.
+ ///
+ bool builtin() const;
+
+ // Formatting (xf) components
///
- ///
+ /// Returns the alignment of this style.
///
- optional builtin_id() const;
+ class alignment alignment() const;
+
+ ///
+ /// Returns true if the alignment of this style should be applied to cells
+ /// using it.
+ ///
+ bool alignment_applied() const;
///
- ///
- ///
- style builtin_id(std::size_t builtin_id);
-
- // Formatting components
-
- ///
- ///
- ///
- class alignment &alignment();
-
- ///
- ///
- ///
- const class alignment &alignment() const;
-
- ///
- ///
+ /// Sets the alignment of this style to new_alignment. Applied, which defaults
+ /// to true, determines whether the alignment should be enabled for cells using
+ /// this style.
///
style alignment(const xlnt::alignment &new_alignment, bool applied = true);
///
///
///
- bool alignment_applied() const;
+ class border border() const;
- ///
- ///
- ///
- class border &border();
-
- ///
- ///
- ///
- const class border &border() const;
+ ///
+ ///
+ ///
+ bool border_applied() const;
///
///
@@ -145,17 +143,12 @@ public:
///
///
///
- bool border_applied() const;
+ class fill fill() const;
- ///
- ///
- ///
- class fill &fill();
-
- ///
- ///
- ///
- const class fill &fill() const;
+ ///
+ ///
+ ///
+ bool fill_applied() const;
///
///
@@ -165,17 +158,12 @@ public:
///
///
///
- bool fill_applied() const;
+ class font font() const;
- ///
- ///
- ///
- class font &font();
-
- ///
- ///
- ///
- const class font &font() const;
+ ///
+ ///
+ ///
+ bool font_applied() const;
///
///
@@ -185,17 +173,12 @@ public:
///
///
///
- bool font_applied() const;
+ class number_format number_format() const;
- ///
- ///
- ///
- class number_format &number_format();
-
- ///
- ///
- ///
- const class number_format &number_format() const;
+ ///
+ ///
+ ///
+ bool number_format_applied() const;
///
///
@@ -205,53 +188,51 @@ public:
///
///
///
- bool number_format_applied() const;
+ class protection protection() const;
+
+ ///
+ ///
+ ///
+ bool protection_applied() const;
///
- ///
- ///
- class protection &protection();
-
- ///
- ///
- ///
- const class protection &protection() const;
-
- ///
- ///
+ ///
///
style protection(const xlnt::protection &new_protection, bool applied = true);
///
- ///
- ///
- bool protection_applied() const;
-
- ///
- ///
+ /// Returns true if the pivot table interface is enabled for this style.
///
bool pivot_button() const;
///
- ///
+ /// If show is true, a pivot table interface will be displayed for cells using
+ /// this style.
///
void pivot_button(bool show);
///
- ///
+ /// Returns true if this style should add a single-quote prefix for all text values.
///
bool quote_prefix() const;
///
- ///
+ /// If quote is true, enables a single-quote prefix for all text values in cells
+ /// using this style (e.g. "abc" will appear as "'abc"). The text will also not
+ /// be stored in sharedStrings when this is enabled.
///
void quote_prefix(bool quote);
///
- ///
+ /// Returns true if this style is equivalent to other.
///
bool operator==(const style &other) const;
+ ///
+ /// Returns true if this style is not equivalent to other.
+ ///
+ bool operator!=(const style &other) const;
+
private:
friend struct detail::stylesheet;
friend class detail::xlsx_consumer;
diff --git a/include/xlnt/workbook/workbook.hpp b/include/xlnt/workbook/workbook.hpp
index 86715b71..01826e88 100644
--- a/include/xlnt/workbook/workbook.hpp
+++ b/include/xlnt/workbook/workbook.hpp
@@ -669,6 +669,11 @@ public:
///
class style create_style(const std::string &name);
+ ///
+ /// Creates a new style and returns it.
+ ///
+ class style create_builtin_style(std::size_t builtin_id);
+
///
/// Clear all named styles from cells and remove the styles from
/// from the styelsheet. This leaves all other styling in place
diff --git a/source/cell/cell.cpp b/source/cell/cell.cpp
index 559b2cc7..aa5addd3 100644
--- a/source/cell/cell.cpp
+++ b/source/cell/cell.cpp
@@ -792,14 +792,26 @@ void cell::style(const std::string &style_name)
style(workbook().style(style_name));
}
-const style cell::style() const
+style cell::style()
{
if (!has_format() || !format().has_style())
{
throw invalid_attribute();
}
- return format().style();
+ auto f = format();
+
+ return f.style();
+}
+
+const style cell::style() const
+{
+ if (!has_format() || !format().has_style())
+ {
+ throw invalid_attribute();
+ }
+
+ return format().style();
}
bool cell::has_style() const
diff --git a/source/detail/style_impl.hpp b/source/detail/style_impl.hpp
index ccffa092..49153ae1 100755
--- a/source/detail/style_impl.hpp
+++ b/source/detail/style_impl.hpp
@@ -25,7 +25,7 @@ struct style_impl
std::string name;
std::size_t formatting_record_id;
- optional custom_builtin;
+ bool custom_builtin;
bool hidden_style;
optional builtin_id;
diff --git a/source/detail/stylesheet.hpp b/source/detail/stylesheet.hpp
index f02e4eb9..1e6f6d36 100644
--- a/source/detail/stylesheet.hpp
+++ b/source/detail/stylesheet.hpp
@@ -83,6 +83,71 @@ struct stylesheet
return xlnt::style(&impl);
}
+ class style create_builtin_style(const std::size_t builtin_id)
+ {
+ // From Annex G.2
+ static const auto *names = new std::unordered_map
+ {
+ { 0, "Normal" },
+ { 1, "RowLevel_1" },
+ { 2, "ColLevel_1" },
+ { 3, "Comma" },
+ { 4, "Currency" },
+ { 5, "Percent" },
+ { 6, "Comma [0]" },
+ { 7, "Currency [0]" },
+ { 8, "Hyperlink" },
+ { 9, "Followed Hyperlink" },
+ { 10, "Note" },
+ { 11, "Warning Text" },
+ { 15, "Title" },
+ { 16, "Heading 1" },
+ { 17, "Heading 2" },
+ { 18, "Heading 3" },
+ { 19, "Heading 4" },
+ { 20, "Input" },
+ { 21, "Output"},
+ { 22, "Calculation"},
+ { 22, "Calculation" },
+ { 23, "Check Cell" },
+ { 24, "Linked Cell" },
+ { 25, "Total" },
+ { 26, "Good" },
+ { 27, "Bad" },
+ { 28, "Neutral" },
+ { 29, "Accent1" },
+ { 30, "20% - Accent1" },
+ { 31, "40% - Accent1" },
+ { 32, "60% - Accent1" },
+ { 33, "Accent2" },
+ { 34, "20% - Accent2" },
+ { 35, "40% - Accent2" },
+ { 36, "60% - Accent2" },
+ { 37, "Accent3" },
+ { 38, "20% - Accent3" },
+ { 39, "40% - Accent3" },
+ { 40, "60% - Accent3" },
+ { 41, "Accent4" },
+ { 42, "20% - Accent4" },
+ { 43, "40% - Accent4" },
+ { 44, "60% - Accent4" },
+ { 45, "Accent5" },
+ { 46, "20% - Accent5" },
+ { 47, "40% - Accent5" },
+ { 48, "60% - Accent5" },
+ { 49, "Accent6" },
+ { 50, "20% - Accent6" },
+ { 51, "40% - Accent6" },
+ { 52, "60% - Accent6" },
+ { 53, "Explanatory Text" }
+ };
+
+ auto new_style = create_style(names->at(builtin_id));
+ new_style.d_->builtin_id = builtin_id;
+
+ return new_style;
+ }
+
class style style(const std::string &name)
{
if (!has_style(name)) throw key_not_found();
diff --git a/source/detail/xlsx_producer.cpp b/source/detail/xlsx_producer.cpp
index f4c243ac..c28cf6bd 100755
--- a/source/detail/xlsx_producer.cpp
+++ b/source/detail/xlsx_producer.cpp
@@ -1422,10 +1422,10 @@ void xlsx_producer::write_styles(const relationship & /*rel*/)
write_attribute("hidden", write_bool(true));
}
- if (current_style.custom_builtin.is_set())
- {
- write_attribute("customBuiltin", write_bool(current_style.custom_builtin.get()));
- }
+ if (current_style.builtin_id.is_set() && current_style.custom_builtin)
+ {
+ write_attribute("customBuiltin", write_bool(current_style.custom_builtin));
+ }
write_end_element(xmlns, "cellStyle");
}
diff --git a/source/styles/format.cpp b/source/styles/format.cpp
index 42a5e581..4f1dab3f 100755
--- a/source/styles/format.cpp
+++ b/source/styles/format.cpp
@@ -61,7 +61,7 @@ bool format::has_style() const
return d_->style.is_set();
}
-const style format::style() const
+style format::style()
{
if (!has_style())
{
@@ -71,6 +71,16 @@ const style format::style() const
return d_->parent->style(d_->style.get());
}
+const style format::style() const
+{
+ if (!has_style())
+ {
+ throw invalid_attribute();
+ }
+
+ return d_->parent->style(d_->style.get());
+}
+
xlnt::alignment &format::alignment()
{
return d_->parent->alignments.at(d_->alignment_id.get());
diff --git a/source/styles/style.cpp b/source/styles/style.cpp
index d2632f6a..694989e1 100755
--- a/source/styles/style.cpp
+++ b/source/styles/style.cpp
@@ -31,6 +31,17 @@
#include
#include
+namespace {
+
+std::vector::iterator find_number_format(
+ std::vector &number_formats, std::size_t id)
+{
+ return std::find_if(number_formats.begin(), number_formats.end(),
+ [=](const xlnt::number_format &nf) { return nf.id() == id; });
+}
+
+}
+
namespace xlnt {
style::style(detail::style_impl *d)
@@ -49,15 +60,9 @@ style style::hidden(bool value)
return style(d_);
}
-optional style::builtin_id() const
+std::size_t style::builtin_id() const
{
- return d_->builtin_id;
-}
-
-style style::builtin_id(std::size_t builtin_id)
-{
- d_->builtin_id = builtin_id;
- return *this;
+ return d_->builtin_id.get();
}
std::string style::name() const
@@ -71,15 +76,9 @@ style style::name(const std::string &name)
return *this;
}
-optional style::custom() const
+bool style::custom_builtin() const
{
- return d_->custom_builtin;
-}
-
-style style::custom(bool value)
-{
- d_->custom_builtin = value;
- return *this;
+ return d_->builtin_id.is_set() && d_->custom_builtin;
}
bool style::operator==(const style &other) const
@@ -87,86 +86,94 @@ bool style::operator==(const style &other) const
return name() == other.name();
}
-xlnt::alignment &style::alignment()
+xlnt::alignment style::alignment() const
{
return d_->parent->alignments.at(d_->alignment_id.get());
}
-const xlnt::alignment &style::alignment() const
+bool style::alignment_applied() const
{
- return d_->parent->alignments.at(d_->alignment_id.get());
+ return d_->alignment_applied;
}
style style::alignment(const xlnt::alignment &new_alignment, bool applied)
{
d_->alignment_id = d_->parent->find_or_add(d_->parent->alignments, new_alignment);
d_->alignment_applied = applied;
- return style(d_);
+
+ return *this;
}
-xlnt::border &style::border()
+xlnt::border style::border() const
{
return d_->parent->borders.at(d_->border_id.get());
}
-const xlnt::border &style::border() const
+bool style::border_applied() const
{
- return d_->parent->borders.at(d_->border_id.get());
+ return d_->border_applied;
}
style style::border(const xlnt::border &new_border, bool applied)
{
d_->border_id = d_->parent->find_or_add(d_->parent->borders, new_border);
d_->border_applied = applied;
- return style(d_);
+
+ return *this;
}
-xlnt::fill &style::fill()
+xlnt::fill style::fill() const
{
return d_->parent->fills.at(d_->fill_id.get());
}
-const xlnt::fill &style::fill() const
+bool style::fill_applied() const
{
- return d_->parent->fills.at(d_->fill_id.get());
+ return d_->fill_applied;
}
style style::fill(const xlnt::fill &new_fill, bool applied)
{
d_->fill_id = d_->parent->find_or_add(d_->parent->fills, new_fill);
d_->fill_applied = applied;
- return style(d_);
+
+ return *this;
}
-xlnt::font &style::font()
+xlnt::font style::font() const
{
return d_->parent->fonts.at(d_->font_id.get());
}
-const xlnt::font &style::font() const
+bool style::font_applied() const
{
- return d_->parent->fonts.at(d_->font_id.get());
+ return d_->font_applied;
}
style style::font(const xlnt::font &new_font, bool applied)
{
d_->font_id = d_->parent->find_or_add(d_->parent->fonts, new_font);
d_->font_applied = applied;
- return style(d_);
+
+ return *this;
}
-xlnt::number_format &style::number_format()
+xlnt::number_format style::number_format() const
{
- auto tarid = d_->number_format_id.get();
- return *std::find_if(d_->parent->number_formats.begin(), d_->parent->number_formats.end(),
- [=](const class number_format &nf) { return nf.id() == tarid; });
+ auto match = find_number_format(d_->parent->number_formats,
+ d_->number_format_id.get());
+
+ if (match == d_->parent->number_formats.end())
+ {
+ throw invalid_attribute();
+ }
+
+ return *match;
}
-const xlnt::number_format &style::number_format() const
+bool style::number_format_applied() const
{
- auto tarid = d_->number_format_id.get();
- return *std::find_if(d_->parent->number_formats.begin(), d_->parent->number_formats.end(),
- [=](const class number_format &nf) { return nf.id() == tarid; });
+ return d_->number_format_applied;
}
style style::number_format(const xlnt::number_format &new_number_format, bool applied)
@@ -178,64 +185,34 @@ style style::number_format(const xlnt::number_format &new_number_format, bool ap
copy.id(d_->parent->next_custom_number_format_id());
d_->parent->number_formats.push_back(copy);
}
- else if (std::find_if(d_->parent->number_formats.begin(), d_->parent->number_formats.end(),
- [©](const class number_format &nf) { return nf.id() == copy.id(); })
- == d_->parent->number_formats.end())
- {
+ else if (find_number_format(d_->parent->number_formats, copy.id())
+ == d_->parent->number_formats.end())
+ {
d_->parent->number_formats.push_back(copy);
}
d_->number_format_id = copy.id();
d_->number_format_applied = applied;
- return style(d_);
+ return *this;
}
-xlnt::protection &style::protection()
+xlnt::protection style::protection() const
{
return d_->parent->protections.at(d_->protection_id.get());
}
-const xlnt::protection &style::protection() const
+bool style::protection_applied() const
{
- return d_->parent->protections.at(d_->protection_id.get());
+ return d_->protection_applied;
}
style style::protection(const xlnt::protection &new_protection, bool applied)
{
d_->protection_id = d_->parent->find_or_add(d_->parent->protections, new_protection);
d_->protection_applied = applied;
- return style(d_);
-}
-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;
+ return *this;
}
bool style::pivot_button() const
diff --git a/source/workbook/workbook.cpp b/source/workbook/workbook.cpp
index 7a3dfcab..59449471 100644
--- a/source/workbook/workbook.cpp
+++ b/source/workbook/workbook.cpp
@@ -497,12 +497,7 @@ workbook workbook::empty()
.color(theme_color(1));
stylesheet.fonts.push_back(default_font);
- wb.create_style("Normal")
- .builtin_id(0)
- .border(default_border, false)
- .fill(default_fill, false)
- .font(default_font, false)
- .number_format(xlnt::number_format::general(), false);
+ wb.create_builtin_style(0);
wb.create_format(true)
.border(default_border, false)
@@ -1351,6 +1346,11 @@ style workbook::create_style(const std::string &name)
return d_->stylesheet_.get().create_style(name);
}
+style workbook::create_builtin_style(const std::size_t builtin_id)
+{
+ return d_->stylesheet_.get().create_builtin_style(builtin_id);
+}
+
style workbook::style(const std::string &name)
{
return d_->stylesheet_.get().style(name);