refactor styles... again

This commit is contained in:
Thomas Fussell 2016-06-10 13:40:50 -04:00
parent 4e9c48eba9
commit 85e1b4a333
28 changed files with 912 additions and 954 deletions

View File

@ -38,7 +38,6 @@ enum class calendar;
class alignment; class alignment;
class border; class border;
class cell_reference; class cell_reference;
class cell_style;
class comment; class comment;
class fill; class fill;
class font; class font;
@ -46,6 +45,7 @@ class format;
class number_format; class number_format;
class protection; class protection;
class relationship; class relationship;
class style;
class workbook; class workbook;
class worksheet; class worksheet;
@ -205,6 +205,26 @@ public:
const format &get_format() const; const format &get_format() const;
void set_format(const format &new_format); void set_format(const format &new_format);
void clear_format();
// style
/// <summary>
/// Return true if this cell has had a format applied to it.
/// </summary>
bool has_style() const;
/// <summary>
/// Return a reference to the format applied to this cell.
/// </summary>
const style &get_style() const;
void set_style(const style &new_style);
void set_style(const std::string &style_name);
void clear_style();
/// <summary> /// <summary>
/// Return the number format of this cell. /// Return the number format of this cell.

View File

@ -30,6 +30,7 @@
#include <xlnt/xlnt_config.hpp> #include <xlnt/xlnt_config.hpp>
#include <xlnt/packaging/zip_file.hpp> #include <xlnt/packaging/zip_file.hpp>
#include <detail/stylesheet.hpp>
namespace xlnt { namespace xlnt {
@ -93,6 +94,8 @@ public:
/// binary data to stream. /// binary data to stream.
/// </summary> /// </summary>
bool save_stream_workbook(std::ostream &stream, bool as_template = false); bool save_stream_workbook(std::ostream &stream, bool as_template = false);
xlnt::detail::stylesheet &get_stylesheet();
private: private:
/// <summary> /// <summary>

View File

@ -28,8 +28,6 @@
#include <vector> #include <vector>
#include <xlnt/xlnt_config.hpp> #include <xlnt/xlnt_config.hpp>
#include <xlnt/styles/style.hpp>
#include <xlnt/workbook/workbook.hpp>
namespace xlnt { namespace xlnt {
@ -40,7 +38,7 @@ class conditional_format;
class fill; class fill;
class font; class font;
class format; class format;
class formattable; class base_format;
class style; class style;
class number_format; class number_format;
class protection; class protection;
@ -49,8 +47,10 @@ class style;
class xml_document; class xml_document;
class xml_node; class xml_node;
namespace detail { struct stylesheet; }
/// <summary> /// <summary>
/// Reads and writes xl/styles.xml from/to an associated workbook. /// Reads and writes xl/styles.xml from/to an associated stylesheet.
/// </summary> /// </summary>
class XLNT_CLASS style_serializer class XLNT_CLASS style_serializer
{ {
@ -58,11 +58,7 @@ public:
/// <summary> /// <summary>
/// Construct a style_serializer which can write styles.xml based on wb or populate wb /// Construct a style_serializer which can write styles.xml based on wb or populate wb
/// with styles from an existing styles.xml. /// with styles from an existing styles.xml.
style_serializer(workbook &wb); style_serializer(detail::stylesheet &s);
//
// Primary methods
//
/// <summary> /// <summary>
/// Load all styles from xml_document into workbook given in constructor. /// Load all styles from xml_document into workbook given in constructor.
@ -73,204 +69,13 @@ public:
/// Populate parameter xml with an XML tree representing the styles contained in the workbook /// Populate parameter xml with an XML tree representing the styles contained in the workbook
/// given in the constructor. /// given in the constructor.
/// </summary> /// </summary>
xml_document write_stylesheet(); bool write_stylesheet(xml_document &xml);
// TODO: These need to be public for unit tests. Could also make test class a friend?
// private:
//
// Static element readers (i.e. readers that don't use internal state)
//
/// <summary>
/// Read and return an alignment from alignment_node.
/// </summary>
static alignment read_alignment(const xml_node &alignment_node);
/// <summary>
/// Read and return a border side from side_node.
/// </summary>
static side read_side(const xml_node &side_node);
/// <summary>
/// Read and return a border from border_node.
/// </summary>
static border read_border(const xml_node &border_node);
/// <summary>
/// Read and return a fill from fill_node.
/// </summary>
static fill read_fill(const xml_node &fill_node);
/// <summary>
/// Read and return a font from font_node.
/// </summary>
static font read_font(const xml_node &font_node);
/// <summary>
/// Read and return a number format from number_format_node.
/// </summary>
static number_format read_number_format(const xml_node &number_format_node);
/// <summary>
/// Read and return a protection from protection_node.
/// </summary>
static protection read_protection(const xml_node &protection_node);
/// <summary>
/// Read and return all indexed colors from indexed_colors_node.
/// </summary>
static std::vector<color> read_indexed_colors(const xml_node &indexed_colors_node);
/// <summary>
/// Read and return a color from color_node.
/// </summary>
static color read_color(const xml_node &color_node);
/// <summary>
/// Read and return a conditional format, dxf, from conditional_format_node.
/// </summary>
static conditional_format read_conditional_format(const xml_node &conditional_formats_node);
/// <summary>
/// Read a single format from the given node. In styles.xml, this is an "xf" element.
/// A format has an optional border id, fill id, font id, and number format id where
/// each id is an index in the corresponding list of borders, etc. A style also has
/// optional alignment and protection children. A style also defines whether each of
/// these is "applied". For example, a style with a defined font id, font=# but with
/// "applyFont=0" will not use the font in formatting.
/// </summary>
format read_format(const xml_node &format_node);
/// <summary>
/// Read a single named style from the given named_style_node. In styles.xml, this is a
/// (confusingly named) "cellStyle" element. This node defines the name, whether it is
/// built-in and an xfId which is the index of an element in cellStyleXfs. style_format_node
/// should be the XML node of the element at the index of xfId.
/// </summary>
style read_style(const xml_node &style_node, const xml_node &style_format_node);
//
// Non-static element readers (i.e. readers that modify internal state)
//
bool read_number_formats(const xml_node &number_formats_node);
/// <summary>
/// Read all borders from borders_node and add them to workbook.
/// Return true on success.
/// </summary>
bool read_borders(const xml_node &borders_node);
/// <summary>
/// Read all fills from fills_node and add them to workbook.
/// Return true on success.
/// </summary>
bool read_fills(const xml_node &fills_node);
/// <summary>
/// Read all fonts from fonts_node and add them to workbook.
/// Return true on success.
/// </summary>
bool read_fonts(const xml_node &fonts_node);
/// <summary>
/// Read all colors from colors_node and add them to workbook.
/// Return true on success.
/// </summary>
bool read_colors(const xml_node &colors_node);
/// <summary>
/// Read all cell styles from cell_styles_node and add them to workbook.
/// Return true on success.
/// </summary>
bool read_formats(const xml_node &formats_node);
/// <summary>
/// Read all named styles from named_style_node and cell_styles_node and add them to workbook.
/// Return true on success.
/// </summary>
bool read_styles(const xml_node &styles_node, const xml_node &style_formats_node);
/// <summary>
/// Read all borders from number_formats_node and add them to workbook.
/// Return true on success.
/// </summary>
bool read_stylesheet(const xml_node &number_formats_node);
//
// Non-static element writers (i.e. writers that modify internal workbook)
//
/// <summary>
/// Build an xml tree representing all borders in workbook into borders_node.
/// Returns true on success.
/// </summary>
bool write_borders(xml_node &borders_node) const;
/// <summary>
/// Build an xml tree representing all conditional formats in workbook into conditional_formats_node.
/// Returns true on success.
/// </summary>
bool write_conditional_formats(xml_node &conditional_formats_node) const;
/// <summary>
/// Build an xml tree representing all fills in workbook into fills_node.
/// Returns true on success.
/// </summary>
bool write_fills(xml_node &fills_node) const;
/// <summary>
/// Build an xml tree representing all fonts in workbook into fonts_node.
/// Returns true on success.
/// </summary>
bool write_fonts(xml_node &fonts_node) const;
/// <summary>
/// Build an xml tree representing all number formats in workbook into number_formats_node.
/// Returns true on success.
/// </summary>
bool write_number_formats(xml_node &number_formats_node) const;
bool write_formattable(const formattable &xf, xml_node xf_node) const;
/// <summary>
/// Build an xml tree representing the given style into style_node.
/// Returns true on success.
/// </summary>
bool write_formats(xml_node &styles_node) const;
bool write_styles(xml_node &cell_styles_node, xml_node &cell_style_formats_node) const;
bool write_colors(xml_node &colors_node) const;
bool write_ext_list(xml_node &ext_list_node) const;
const std::vector<border> &get_borders() const;
const std::vector<fill> &get_fills() const;
const std::vector<font> &get_fonts() const;
const std::vector<number_format> &get_number_formats() const;
const std::vector<color> &get_colors() const;
private: private:
void initialize_vectors();
/// <summary> /// <summary>
/// Set in the constructor, this workbook is used as the source or target for all writing or reading, respectively. /// Set in the constructor, this stylesheet is used as the source or target for all writing or reading, respectively.
/// </summary> /// </summary>
workbook &workbook_; detail::stylesheet &stylesheet_;
std::vector<color> colors_;
std::vector<border> borders_;
std::vector<fill> fills_;
std::vector<font> fonts_;
std::vector<number_format> number_formats_;
std::vector<format> formats_;
std::vector<style> styles_;
}; };
} // namespace xlnt } // namespace xlnt

View File

@ -36,6 +36,8 @@ class workbook;
class worksheet; class worksheet;
class xml_document; class xml_document;
namespace detail { struct stylesheet; }
/// <summary> /// <summary>
/// Manages converting a worksheet to and from XML. /// Manages converting a worksheet to and from XML.
/// </summary> /// </summary>
@ -44,7 +46,7 @@ class XLNT_CLASS worksheet_serializer
public: public:
worksheet_serializer(worksheet sheet); worksheet_serializer(worksheet sheet);
bool read_worksheet(const xml_document &xml); bool read_worksheet(const xml_document &xml, detail::stylesheet &stylesheet);
xml_document write_worksheet() const; xml_document write_worksheet() const;
private: private:

View File

@ -38,12 +38,12 @@ class cell;
/// <summary> /// <summary>
/// Describes the formatting of a particular cell. /// Describes the formatting of a particular cell.
/// </summary> /// </summary>
class XLNT_CLASS formattable : public hashable class XLNT_CLASS base_format : public hashable
{ {
public: public:
formattable(); base_format();
formattable(const formattable &other); base_format(const base_format &other);
formattable &operator=(const formattable &other); base_format &operator=(const base_format &other);
void reset(); void reset();

View File

@ -71,6 +71,8 @@ public:
lightvertical, lightvertical,
mediumgray, mediumgray,
}; };
fill();
type get_type() const; type get_type() const;
@ -122,21 +124,21 @@ protected:
std::string to_hash_string() const override; std::string to_hash_string() const override;
private: private:
type type_ = type::pattern; type type_;
pattern_type pattern_type_ = pattern_type::none; pattern_type pattern_type_;
gradient_type gradient_type_; gradient_type gradient_type_;
double rotation_ = 0; double rotation_;
std::experimental::optional<color> foreground_color_ = color::black(); std::experimental::optional<color> foreground_color_;
std::experimental::optional<color> background_color_ = color::white(); std::experimental::optional<color> background_color_;
std::experimental::optional<color> start_color_ = color::white(); std::experimental::optional<color> start_color_;
std::experimental::optional<color> end_color_ = color::black(); std::experimental::optional<color> end_color_;
double gradient_path_left_ = 0; double gradient_path_left_;
double gradient_path_right_ = 0; double gradient_path_right_;
double gradient_path_top_ = 0; double gradient_path_top_;
double gradient_path_bottom_ = 0; double gradient_path_bottom_;
}; };
} // namespace xlnt } // namespace xlnt

View File

@ -47,6 +47,8 @@ public:
single, single,
single_accounting single_accounting
}; };
font();
void set_bold(bool bold); void set_bold(bool bold);

View File

@ -23,7 +23,7 @@
// @author: see AUTHORS file // @author: see AUTHORS file
#pragma once #pragma once
#include <xlnt/styles/formattable.hpp> #include <xlnt/styles/base_format.hpp>
namespace xlnt { namespace xlnt {
@ -33,28 +33,15 @@ namespace detail { struct workbook_impl; }
/// <summary> /// <summary>
/// Describes the formatting of a particular cell. /// Describes the formatting of a particular cell.
/// </summary> /// </summary>
class XLNT_CLASS format : public formattable class XLNT_CLASS format : public base_format
{ {
public: public:
format(); format();
format(const format &other); format(const format &other);
format &operator=(const format &other); format &operator=(const format &other);
// Named Style
bool has_style() const;
std::string get_style_name() const;
style &get_style();
const style &get_style() const;
void set_style(const std::string &name);
void set_style(const style &new_style);
void remove_style();
protected: protected:
std::string to_hash_string() const override; std::string to_hash_string() const override;
private:
detail::workbook_impl *parent_;
std::string named_style_name_;
}; };
} // namespace xlnt } // namespace xlnt

View File

@ -26,7 +26,7 @@
#include <cstdint> #include <cstdint>
#include <string> #include <string>
#include <xlnt/styles/formattable.hpp> #include <xlnt/styles/base_format.hpp>
namespace xlnt { namespace xlnt {
@ -36,7 +36,7 @@ class workbook;
/// Describes a style which has a name and can be applied to multiple individual /// Describes a style which has a name and can be applied to multiple individual
/// formats. In Excel this is a "Cell Style". /// formats. In Excel this is a "Cell Style".
/// </summary> /// </summary>
class XLNT_CLASS style : public formattable class XLNT_CLASS style : public base_format
{ {
public: public:
style(); style();

View File

@ -23,6 +23,7 @@
// @author: see AUTHORS file // @author: see AUTHORS file
#pragma once #pragma once
#include <functional>
#include <memory> #include <memory>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
@ -32,11 +33,14 @@
#include <xlnt/xlnt_config.hpp> #include <xlnt/xlnt_config.hpp>
#include <xlnt/packaging/relationship.hpp> #include <xlnt/packaging/relationship.hpp>
namespace CxxTest { class TestSuite; }
namespace xlnt { namespace xlnt {
class alignment; class alignment;
class app_properties; class app_properties;
class border; class border;
class cell;
class cell_style; class cell_style;
class color; class color;
class const_worksheet_iterator; class const_worksheet_iterator;
@ -193,10 +197,12 @@ public:
const std::vector<format> &get_formats() const; const std::vector<format> &get_formats() const;
// Named Styles // Named Styles
bool has_style(const std::string &name); bool has_style(const std::string &name) const;
style &get_style(const std::string &name); style &get_style(const std::string &name);
const style &get_style(const std::string &name) const; const style &get_style(const std::string &name) const;
std::size_t get_style_id(const std::string &name) const;
style &create_style(const std::string &name); style &create_style(const std::string &name);
std::size_t add_style(const style &new_style);
void clear_styles(); void clear_styles();
const std::vector<style> &get_styles() const; const std::vector<style> &get_styles() const;
@ -214,10 +220,11 @@ public:
const std::vector<std::uint8_t> &get_thumbnail() const; const std::vector<std::uint8_t> &get_thumbnail() const;
private: private:
friend class excel_serializer;
friend class worksheet; friend class worksheet;
friend class style_serializer;
std::string next_relationship_id() const; std::string next_relationship_id() const;
void apply_to_cells(std::function<void(cell)> f);
std::unique_ptr<detail::workbook_impl> d_; std::unique_ptr<detail::workbook_impl> d_;
}; };

View File

@ -237,6 +237,8 @@ private:
friend class cell; friend class cell;
friend class range_iterator; friend class range_iterator;
friend class const_range_iterator; friend class const_range_iterator;
std::size_t next_custom_number_format_id();
worksheet(detail::worksheet_impl *d); worksheet(detail::worksheet_impl *d);
detail::worksheet_impl *d_; detail::worksheet_impl *d_;

View File

@ -31,8 +31,9 @@
#include <xlnt/packaging/document_properties.hpp> #include <xlnt/packaging/document_properties.hpp>
#include <xlnt/packaging/relationship.hpp> #include <xlnt/packaging/relationship.hpp>
#include <xlnt/serialization/encoding.hpp> #include <xlnt/serialization/encoding.hpp>
#include <xlnt/styles/format.hpp>
#include <xlnt/styles/color.hpp> #include <xlnt/styles/color.hpp>
#include <xlnt/styles/format.hpp>
#include <xlnt/styles/style.hpp>
#include <xlnt/utils/date.hpp> #include <xlnt/utils/date.hpp>
#include <xlnt/utils/datetime.hpp> #include <xlnt/utils/datetime.hpp>
#include <xlnt/utils/time.hpp> #include <xlnt/utils/time.hpp>
@ -906,10 +907,24 @@ void cell::set_font(const font &font_)
void cell::set_number_format(const number_format &number_format_) void cell::set_number_format(const number_format &number_format_)
{ {
format new_format;
if (d_->has_format_)
{
new_format = get_workbook().get_format(d_->format_id_);
}
auto number_format_with_id = number_format_;
if (!number_format_with_id.has_id())
{
number_format_with_id.set_id(get_worksheet().next_custom_number_format_id());
}
new_format.set_number_format(number_format_with_id);
d_->has_format_ = true; d_->has_format_ = true;
auto format_copy = get_workbook().get_format(d_->format_id_); d_->format_id_ = get_workbook().add_format(new_format);
format_copy.set_number_format(number_format_);
d_->format_id_ = get_workbook().add_format(format_copy);
} }
void cell::set_alignment(const xlnt::alignment &alignment_) void cell::set_alignment(const xlnt::alignment &alignment_)
@ -1030,4 +1045,42 @@ void cell::guess_type_and_set_value(const std::string &value)
} }
} }
void cell::clear_format()
{
d_->format_id_ = 0;
d_->has_format_ = false;
}
void cell::clear_style()
{
d_->style_id_ = 0;
d_->has_style_ = false;
}
void cell::set_style(const style &new_style)
{
d_->has_style_ = true;
if (get_workbook().has_style(new_style.get_name()))
{
d_->style_id_ = get_workbook().get_style_id(new_style.get_name());
}
else
{
d_->style_id_ = get_workbook().add_style(new_style);
}
}
void cell::set_style(const std::string &style_name)
{
d_->has_style_ = true;
if (!get_workbook().has_style(style_name))
{
throw std::runtime_error("style " + style_name + " doesn't exist in workbook");
}
d_->style_id_ = get_workbook().get_style_id(style_name);
}
} // namespace xlnt } // namespace xlnt

View File

@ -72,6 +72,9 @@ struct cell_impl
bool has_format_; bool has_format_;
std::size_t format_id_; std::size_t format_id_;
bool has_style_;
std::size_t style_id_;
std::unique_ptr<comment_impl> comment_; std::unique_ptr<comment_impl> comment_;
}; };

View File

@ -0,0 +1,172 @@
// 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 <string>
#include <unordered_map>
#include <vector>
#include <xlnt/styles/border.hpp>
#include <xlnt/styles/fill.hpp>
#include <xlnt/styles/font.hpp>
#include <xlnt/styles/format.hpp>
#include <xlnt/styles/number_format.hpp>
#include <xlnt/styles/style.hpp>
namespace {
template<typename T>
std::size_t search_vector(const std::vector<T> &items, const T &to_find)
{
auto match = std::find(items.begin(), items.end(), to_find);
if (match == items.end())
{
throw std::out_of_range("xlnt::stylesheet index lookup");
}
return std::distance(items.begin(), match);
}
} // namespace
namespace xlnt {
namespace detail {
struct stylesheet
{
~stylesheet() {}
std::size_t index(const format &f) { return search_vector(formats, f); }
std::size_t index(const std::string &style_name)
{
auto match = std::find_if(styles.begin(), styles.end(),
[&](const style &s) { return s.get_name() == style_name; });
if (match == styles.end())
{
throw std::out_of_range("xlnt::stylesheet style index lookup");
}
return std::distance(styles.begin(), match);
}
std::size_t index(const border &b) { return search_vector(borders, b); }
std::size_t index(const fill &f) { return search_vector(fills, f); }
std::size_t index(const font &f) { return search_vector(fonts, f); }
std::size_t index(const number_format &f) { return search_vector(number_formats, f); }
std::size_t add_format(const format &f)
{
auto match = std::find(formats.begin(), formats.end(), f);
if (match != formats.end())
{
return std::distance(formats.begin(), match);
}
auto number_format_match = std::find_if(number_formats.begin(), number_formats.end(), [&](const number_format &nf) { return nf.get_format_string() == f.get_number_format().get_format_string(); });
if (number_format_match == number_formats.end() && f.get_number_format().get_id() >= 164)
{
number_formats.push_back(f.get_number_format());
}
formats.push_back(f);
format_styles.push_back("");
try
{
search_vector(borders, f.get_border());
}
catch(std::out_of_range)
{
borders.push_back(f.get_border());
}
try
{
search_vector(fills, f.get_fill());
}
catch(std::out_of_range)
{
fills.push_back(f.get_fill());
}
try
{
search_vector(fonts, f.get_font());
}
catch(std::out_of_range)
{
fonts.push_back(f.get_font());
}
if (f.get_number_format().get_id() >= 164)
{
try
{
search_vector(number_formats, f.get_number_format());
}
catch(std::out_of_range)
{
number_formats.push_back(f.get_number_format());
}
}
return formats.size() - 1;
}
std::size_t add_style(const style &s)
{
auto match = std::find(styles.begin(), styles.end(), s);
if (match != styles.end())
{
return std::distance(styles.begin(), match);
}
styles.push_back(s);
return styles.size() - 1;
}
std::vector<format> formats;
std::vector<std::string> format_styles;
std::vector<style> styles;
std::vector<border> borders;
std::vector<fill> fills;
std::vector<font> fonts;
std::vector<number_format> number_formats;
std::vector<color> colors;
std::unordered_map<std::size_t, std::string> style_name_map;
std::size_t next_custom_format_id = 164;
};
} // namespace detail
} // namespace xlnt

View File

@ -25,7 +25,9 @@
#include <iterator> #include <iterator>
#include <vector> #include <vector>
#include <detail/stylesheet.hpp>
#include <detail/worksheet_impl.hpp> #include <detail/worksheet_impl.hpp>
#include <xlnt/serialization/encoding.hpp>
#include <xlnt/packaging/app_properties.hpp> #include <xlnt/packaging/app_properties.hpp>
#include <xlnt/packaging/document_properties.hpp> #include <xlnt/packaging/document_properties.hpp>
#include <xlnt/packaging/manifest.hpp> #include <xlnt/packaging/manifest.hpp>
@ -54,8 +56,7 @@ struct workbook_impl
guess_types_(other.guess_types_), guess_types_(other.guess_types_),
data_only_(other.data_only_), data_only_(other.data_only_),
read_only_(other.read_only_), read_only_(other.read_only_),
formats_(other.formats_), stylesheet_(other.stylesheet_),
styles_(other.styles_),
manifest_(other.manifest_) manifest_(other.manifest_)
{ {
} }
@ -95,9 +96,7 @@ struct workbook_impl
bool data_only_; bool data_only_;
bool read_only_; bool read_only_;
std::vector<format> formats_; stylesheet stylesheet_;
std::vector<style> styles_;
std::size_t next_custom_format_id_;
manifest manifest_; manifest manifest_;
theme theme_; theme theme_;

View File

@ -47,6 +47,8 @@
#include <xlnt/worksheet/worksheet.hpp> #include <xlnt/worksheet/worksheet.hpp>
#include <detail/constants.hpp> #include <detail/constants.hpp>
#include <detail/stylesheet.hpp>
#include <detail/workbook_impl.hpp>
namespace { namespace {
@ -144,10 +146,11 @@ bool load_workbook(xlnt::zip_file &archive, bool guess_types, bool data_only, xl
} }
} }
xlnt::style_serializer style_reader_(wb); xlnt::detail::stylesheet stylesheet;
xlnt::style_serializer style_serializer(stylesheet);
xlnt::xml_document style_xml; xlnt::xml_document style_xml;
style_xml.from_string(archive.read(xlnt::constants::ArcStyles())); style_xml.from_string(archive.read(xlnt::constants::ArcStyles()));
style_reader_.read_stylesheet(style_xml); style_serializer.read_stylesheet(style_xml);
auto sheets_node = root_node.get_child("sheets"); auto sheets_node = root_node.get_child("sheets");
@ -169,7 +172,7 @@ bool load_workbook(xlnt::zip_file &archive, bool guess_types, bool data_only, xl
xlnt::worksheet_serializer worksheet_serializer(ws); xlnt::worksheet_serializer worksheet_serializer(ws);
xlnt::xml_document worksheet_xml; xlnt::xml_document worksheet_xml;
worksheet_xml.from_string(archive.read(ws_filename)); worksheet_xml.from_string(archive.read(ws_filename));
worksheet_serializer.read_worksheet(worksheet_xml); worksheet_serializer.read_worksheet(worksheet_xml, stylesheet);
} }
if (archive.has_file("docProps/thumbnail.jpeg")) if (archive.has_file("docProps/thumbnail.jpeg"))
@ -264,8 +267,10 @@ void excel_serializer::write_data(bool /*as_template*/)
archive_.writestr(constants::ArcWorkbook(), xml_serializer::serialize(workbook_serializer_.write_workbook())); archive_.writestr(constants::ArcWorkbook(), xml_serializer::serialize(workbook_serializer_.write_workbook()));
style_serializer style_serializer_(workbook_); style_serializer style_serializer(workbook_.d_->stylesheet_);
archive_.writestr(constants::ArcStyles(), style_serializer_.write_stylesheet().to_string()); xlnt::xml_document style_xml;
style_serializer.write_stylesheet(style_xml);
archive_.writestr(constants::ArcStyles(), style_xml.to_string());
manifest_serializer manifest_serializer_(workbook_.get_manifest()); manifest_serializer manifest_serializer_(workbook_.get_manifest());
archive_.writestr(constants::ArcContentTypes(), manifest_serializer_.write_manifest().to_string()); archive_.writestr(constants::ArcContentTypes(), manifest_serializer_.write_manifest().to_string());
@ -329,4 +334,9 @@ bool excel_serializer::save_virtual_workbook(std::vector<std::uint8_t> &bytes, b
return true; return true;
} }
detail::stylesheet &excel_serializer::get_stylesheet()
{
return workbook_.d_->stylesheet_;
}
} // namespace xlnt } // namespace xlnt

File diff suppressed because it is too large Load Diff

View File

@ -4,6 +4,8 @@
#include <cxxtest/TestSuite.h> #include <cxxtest/TestSuite.h>
#include <xlnt/serialization/style_serializer.hpp> #include <xlnt/serialization/style_serializer.hpp>
#include <detail/stylesheet.hpp>
#include <detail/workbook_impl.hpp>
class test_style_writer : public CxxTest::TestSuite class test_style_writer : public CxxTest::TestSuite
{ {
@ -12,15 +14,17 @@ public:
{ {
xlnt::workbook wb; xlnt::workbook wb;
wb.get_active_sheet().get_cell("A1").set_number_format(xlnt::number_format("YYYY")); wb.get_active_sheet().get_cell("A1").set_number_format(xlnt::number_format("YYYY"));
xlnt::style_serializer writer(wb); xlnt::excel_serializer excel_serializer(wb);
xlnt::style_serializer style_serializer(excel_serializer.get_stylesheet());
xlnt::xml_document observed; xlnt::xml_document observed;
auto num_fmts_node = observed.add_child("numFmts"); style_serializer.write_stylesheet(observed);
writer.write_number_formats(num_fmts_node); xlnt::xml_document expected_doc;
std::string expected = std::string expected =
" <numFmts count=\"1\">" " <numFmts count=\"1\">"
" <numFmt formatCode=\"YYYY\" numFmtId=\"164\"></numFmt>" " <numFmt formatCode=\"YYYY\" numFmtId=\"164\"></numFmt>"
" </numFmts>"; " </numFmts>";
auto diff = Helper::compare_xml(expected, observed); expected_doc.from_string(expected);
auto diff = Helper::compare_xml(expected_doc.get_child("numFmts"), observed.get_child("styleSheet").get_child("numFmts"));
TS_ASSERT(diff); TS_ASSERT(diff);
} }
/* /*

View File

@ -40,6 +40,7 @@
#include <xlnt/worksheet/row_properties.hpp> #include <xlnt/worksheet/row_properties.hpp>
#include <detail/constants.hpp> #include <detail/constants.hpp>
#include <detail/stylesheet.hpp>
namespace { namespace {
@ -56,7 +57,7 @@ worksheet_serializer::worksheet_serializer(worksheet sheet) : sheet_(sheet)
{ {
} }
bool worksheet_serializer::read_worksheet(const xml_document &xml) bool worksheet_serializer::read_worksheet(const xml_document &xml, detail::stylesheet &stylesheet)
{ {
auto &root_node = xml.get_child("worksheet"); auto &root_node = xml.get_child("worksheet");
@ -198,7 +199,7 @@ bool worksheet_serializer::read_worksheet(const xml_document &xml)
if (has_format) if (has_format)
{ {
cell.set_format(sheet_.get_workbook().get_format(format_id)); cell.set_format(stylesheet.formats.at(format_id));
} }
} }
} }

View File

@ -21,11 +21,11 @@
// //
// @license: http://www.opensource.org/licenses/mit-license.php // @license: http://www.opensource.org/licenses/mit-license.php
// @author: see AUTHORS file // @author: see AUTHORS file
#include <xlnt/styles/formattable.hpp> #include <xlnt/styles/base_format.hpp>
namespace xlnt { namespace xlnt {
formattable::formattable() base_format::base_format()
: apply_alignment_(false), : apply_alignment_(false),
apply_border_(false), apply_border_(false),
apply_fill_(false), apply_fill_(false),
@ -35,7 +35,7 @@ formattable::formattable()
{ {
} }
formattable::formattable(const formattable &other) base_format::base_format(const base_format &other)
: alignment_(other.alignment_), : alignment_(other.alignment_),
border_(other.border_), border_(other.border_),
fill_(other.fill_), fill_(other.fill_),
@ -51,7 +51,7 @@ formattable::formattable(const formattable &other)
{ {
} }
formattable &formattable::operator=(const xlnt::formattable &other) base_format &base_format::operator=(const xlnt::base_format &other)
{ {
alignment_ = other.alignment_; alignment_ = other.alignment_;
border_ = other.border_; border_ = other.border_;
@ -70,105 +70,105 @@ formattable &formattable::operator=(const xlnt::formattable &other)
return *this; return *this;
} }
alignment &formattable::get_alignment() alignment &base_format::get_alignment()
{ {
return alignment_; return alignment_;
} }
const alignment &formattable::get_alignment() const const alignment &base_format::get_alignment() const
{ {
return alignment_; return alignment_;
} }
void formattable::set_alignment(const xlnt::alignment &new_alignment) void base_format::set_alignment(const xlnt::alignment &new_alignment)
{ {
alignment_ = new_alignment; alignment_ = new_alignment;
alignment_applied(true); alignment_applied(true);
} }
number_format &formattable::get_number_format() number_format &base_format::get_number_format()
{ {
return number_format_; return number_format_;
} }
const number_format &formattable::get_number_format() const const number_format &base_format::get_number_format() const
{ {
return number_format_; return number_format_;
} }
void formattable::set_number_format(const xlnt::number_format &new_number_format) void base_format::set_number_format(const xlnt::number_format &new_number_format)
{ {
number_format_ = new_number_format; number_format_ = new_number_format;
number_format_applied(true); number_format_applied(true);
} }
border &formattable::get_border() border &base_format::get_border()
{ {
return border_; return border_;
} }
const border &formattable::get_border() const const border &base_format::get_border() const
{ {
return border_; return border_;
} }
void formattable::set_border(const xlnt::border &new_border) void base_format::set_border(const xlnt::border &new_border)
{ {
border_ = new_border; border_ = new_border;
border_applied(true); border_applied(true);
} }
fill &formattable::get_fill() fill &base_format::get_fill()
{ {
return fill_; return fill_;
} }
const fill &formattable::get_fill() const const fill &base_format::get_fill() const
{ {
return fill_; return fill_;
} }
void formattable::set_fill(const xlnt::fill &new_fill) void base_format::set_fill(const xlnt::fill &new_fill)
{ {
fill_ = new_fill; fill_ = new_fill;
fill_applied(true); fill_applied(true);
} }
font &formattable::get_font() font &base_format::get_font()
{ {
return font_; return font_;
} }
const font &formattable::get_font() const const font &base_format::get_font() const
{ {
return font_; return font_;
} }
void formattable::set_font(const xlnt::font &new_font) void base_format::set_font(const xlnt::font &new_font)
{ {
font_ = new_font; font_ = new_font;
font_applied(true); font_applied(true);
} }
protection &formattable::get_protection() protection &base_format::get_protection()
{ {
return protection_; return protection_;
} }
const protection &formattable::get_protection() const const protection &base_format::get_protection() const
{ {
return protection_; return protection_;
} }
void formattable::set_protection(const xlnt::protection &new_protection) void base_format::set_protection(const xlnt::protection &new_protection)
{ {
protection_ = new_protection; protection_ = new_protection;
protection_applied(true); protection_applied(true);
} }
std::string formattable::to_hash_string() const std::string base_format::to_hash_string() const
{ {
std::string hash_string("formattable:"); std::string hash_string("base_format:");
hash_string.append(std::to_string(alignment_applied())); hash_string.append(std::to_string(alignment_applied()));
hash_string.append(alignment_applied() ? std::to_string(alignment_.hash()) : ":"); hash_string.append(alignment_applied() ? std::to_string(alignment_.hash()) : ":");
@ -191,62 +191,62 @@ std::string formattable::to_hash_string() const
return hash_string; return hash_string;
} }
void formattable::alignment_applied(bool applied) void base_format::alignment_applied(bool applied)
{ {
apply_alignment_ = applied; apply_alignment_ = applied;
} }
void formattable::border_applied(bool applied) void base_format::border_applied(bool applied)
{ {
apply_border_ = applied; apply_border_ = applied;
} }
void formattable::fill_applied(bool applied) void base_format::fill_applied(bool applied)
{ {
apply_fill_ = applied; apply_fill_ = applied;
} }
void formattable::font_applied(bool applied) void base_format::font_applied(bool applied)
{ {
apply_font_ = applied; apply_font_ = applied;
} }
void formattable::number_format_applied(bool applied) void base_format::number_format_applied(bool applied)
{ {
apply_number_format_ = applied; apply_number_format_ = applied;
} }
void formattable::protection_applied(bool applied) void base_format::protection_applied(bool applied)
{ {
apply_protection_ = applied; apply_protection_ = applied;
} }
bool formattable::alignment_applied() const bool base_format::alignment_applied() const
{ {
return apply_alignment_; return apply_alignment_;
} }
bool formattable::border_applied() const bool base_format::border_applied() const
{ {
return apply_border_; return apply_border_;
} }
bool formattable::fill_applied() const bool base_format::fill_applied() const
{ {
return apply_fill_; return apply_fill_;
} }
bool formattable::font_applied() const bool base_format::font_applied() const
{ {
return apply_font_; return apply_font_;
} }
bool formattable::number_format_applied() const bool base_format::number_format_applied() const
{ {
return apply_number_format_; return apply_number_format_;
} }
bool formattable::protection_applied() const bool base_format::protection_applied() const
{ {
return apply_protection_; return apply_protection_;
} }

View File

@ -26,6 +26,18 @@
namespace xlnt { namespace xlnt {
fill::fill()
: type_(type::pattern),
pattern_type_(pattern_type::none),
gradient_type_(gradient_type::linear),
rotation_(0),
gradient_path_left_(0),
gradient_path_right_(0),
gradient_path_top_(0),
gradient_path_bottom_(0)
{
}
fill::type fill::get_type() const fill::type fill::get_type() const
{ {
return type_; return type_;

View File

@ -26,6 +26,24 @@
namespace xlnt { namespace xlnt {
font::font()
: name_("Calibri"),
size_(12),
bold_(false),
italic_(false),
superscript_(false),
subscript_(false),
underline_(underline_style::none),
strikethrough_(false),
color_(xlnt::color::type::theme, 1),
has_family_(true),
family_(2),
has_scheme_(true),
scheme_("minor")
{
}
void font::set_bold(bool bold) void font::set_bold(bool bold)
{ {
bold_ = bold; bold_ = bold;

View File

@ -31,60 +31,27 @@
namespace xlnt { namespace xlnt {
format::format() format::format() : base_format()
: formattable(),
parent_(nullptr),
named_style_name_("Normal")
{ {
} }
format::format(const format &other) format::format(const format &other) : base_format(other)
: formattable(other),
parent_(other.parent_),
named_style_name_(other.named_style_name_)
{ {
} }
format &format::operator=(const format &other) format &format::operator=(const format &other)
{ {
formattable::operator=(other); base_format::operator=(other);
parent_ = other.parent_;
named_style_name_ = other.named_style_name_;
return *this; return *this;
} }
std::string format::to_hash_string() const std::string format::to_hash_string() const
{ {
auto hash_string = formattable::to_hash_string(); auto hash_string = base_format::to_hash_string();
hash_string.append(":format:"); hash_string.append(":format:");
if (!named_style_name_.empty())
{
hash_string.append(named_style_name_);
}
else
{
hash_string.append(":");
}
return hash_string; return hash_string;
} }
void format::set_style(const std::string &style_name)
{
named_style_name_ = style_name;
}
bool format::has_style() const
{
return !named_style_name_.empty();
}
std::string format::get_style_name() const
{
return named_style_name_;
}
} // namespace xlnt } // namespace xlnt

View File

@ -70,7 +70,7 @@ const std::unordered_map<std::size_t, std::string> &builtin_formats()
{ 42, "_(\"$\"* #,##0_);_(\"$\"* \\(#,##0\\);_(\"$\"* \"-\"_);_(@_)" }, { 42, "_(\"$\"* #,##0_);_(\"$\"* \\(#,##0\\);_(\"$\"* \"-\"_);_(@_)" },
{ 43, "_(* #,##0.00_);_(* \\(#,##0.00\\);_(* \"-\"??_);_(@_)" }, { 43, "_(* #,##0.00_);_(* \\(#,##0.00\\);_(* \"-\"??_);_(@_)" },
{ 44, "_(\"$\"* #,##0.00_)_(\"$\"* \\(#,##0.00\\)_(\"$\"* \"-\"??_)_(@_)" }, { 44, "_-\"$\"* #,##0.00_-;\\-\"$\"* #,##0.00_-;_-\"$\"* \"-\"??_-;_-@_-" },
{ 45, "mm:ss" }, { 45, "mm:ss" },
{ 46, "[h]:mm:ss" }, { 46, "[h]:mm:ss" },
{ 47, "mmss.0" }, { 47, "mmss.0" },

View File

@ -27,14 +27,14 @@
namespace xlnt { namespace xlnt {
style::style() style::style()
: formattable(), : base_format(),
hidden_(false), hidden_(false),
builtin_id_(0) builtin_id_(0)
{ {
} }
style::style(const style &other) style::style(const style &other)
: formattable(other), : base_format(other),
name_(other.name_), name_(other.name_),
hidden_(other.hidden_), hidden_(other.hidden_),
builtin_id_(other.builtin_id_) builtin_id_(other.builtin_id_)
@ -43,7 +43,7 @@ style::style(const style &other)
style &style::operator=(const style &other) style &style::operator=(const style &other)
{ {
formattable::operator=(other); base_format::operator=(other);
name_ = other.name_; name_ = other.name_;
hidden_ = other.hidden_; hidden_ = other.hidden_;
@ -84,7 +84,7 @@ void style::set_name(const std::string &name)
std::string style::to_hash_string() const std::string style::to_hash_string() const
{ {
return formattable::to_hash_string() + name_; return base_format::to_hash_string() + name_;
} }
} // namespace xlnt } // namespace xlnt

View File

@ -15,9 +15,12 @@ public:
void test_ctor() void test_ctor()
{ {
xlnt::workbook wb; xlnt::workbook wb;
xlnt::style_serializer style_serializer(wb); xlnt::excel_serializer excel_serializer(wb);
xlnt::style_serializer style_serializer(excel_serializer.get_stylesheet());
xlnt::zip_file archive; xlnt::zip_file archive;
auto stylesheet_xml = style_serializer.write_stylesheet().to_string(); xlnt::xml_document stylesheet_doc;
style_serializer.write_stylesheet(stylesheet_doc);
auto stylesheet_xml = stylesheet_doc.to_string();
const std::string expected = const std::string expected =
"<styleSheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" xmlns:x14ac=\"http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac\" mc:Ignorable=\"x14ac\">" "<styleSheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" xmlns:x14ac=\"http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac\" mc:Ignorable=\"x14ac\">"
@ -72,9 +75,10 @@ public:
auto xml = PathHelper::read_file(PathHelper::GetDataDirectory("/reader/styles/simple-styles.xml")); auto xml = PathHelper::read_file(PathHelper::GetDataDirectory("/reader/styles/simple-styles.xml"));
doc.from_string(xml); doc.from_string(xml);
xlnt::workbook wb; xlnt::workbook wb;
xlnt::style_serializer s(wb); xlnt::excel_serializer e(wb);
xlnt::style_serializer s(e.get_stylesheet());
TS_ASSERT(s.read_stylesheet(doc)); TS_ASSERT(s.read_stylesheet(doc));
TS_ASSERT_EQUALS(s.get_number_formats().size(), 1); TS_ASSERT_EQUALS(e.get_stylesheet().number_formats.size(), 1);
} }
void test_from_complex() void test_from_complex()
@ -83,12 +87,13 @@ public:
auto xml = PathHelper::read_file(PathHelper::GetDataDirectory("/reader/styles/complex-styles.xml")); auto xml = PathHelper::read_file(PathHelper::GetDataDirectory("/reader/styles/complex-styles.xml"));
doc.from_string(xml); doc.from_string(xml);
xlnt::workbook wb; xlnt::workbook wb;
xlnt::style_serializer s(wb); xlnt::excel_serializer e(wb);
xlnt::style_serializer s(e.get_stylesheet());
TS_ASSERT(s.read_stylesheet(doc)); TS_ASSERT(s.read_stylesheet(doc));
TS_ASSERT_EQUALS(s.get_borders().size(), 7); TS_ASSERT_EQUALS(e.get_stylesheet().borders.size(), 7);
TS_ASSERT_EQUALS(s.get_fills().size(), 6); TS_ASSERT_EQUALS(e.get_stylesheet().fills.size(), 6);
TS_ASSERT_EQUALS(s.get_fonts().size(), 8); TS_ASSERT_EQUALS(e.get_stylesheet().fonts.size(), 8);
TS_ASSERT_EQUALS(s.get_number_formats().size(), 1); TS_ASSERT_EQUALS(e.get_stylesheet().number_formats.size(), 0);
} }
/* /*

View File

@ -24,6 +24,7 @@
#include <algorithm> #include <algorithm>
#include <array> #include <array>
#include <fstream> #include <fstream>
#include <functional>
#include <set> #include <set>
#include <sstream> #include <sstream>
@ -60,7 +61,10 @@ namespace xlnt {
namespace detail { namespace detail {
workbook_impl::workbook_impl() workbook_impl::workbook_impl()
: active_sheet_index_(0), guess_types_(false), data_only_(false), read_only_(false), next_custom_format_id_(164) : active_sheet_index_(0),
guess_types_(false),
data_only_(false),
read_only_(false)
{ {
} }
@ -86,6 +90,7 @@ workbook::workbook() : d_(new detail::workbook_impl())
add_format(format()); add_format(format());
create_style("Normal"); create_style("Normal");
d_->stylesheet_.format_styles.front() = "Normal";
} }
workbook::workbook(encoding e) : workbook() workbook::workbook(encoding e) : workbook()
@ -555,11 +560,6 @@ workbook::~workbook()
{ {
} }
const std::vector<style> &workbook::get_styles() const
{
return d_->styles_;
}
bool workbook::get_data_only() const bool workbook::get_data_only() const
{ {
return d_->data_only_; return d_->data_only_;
@ -609,65 +609,63 @@ std::vector<named_range> workbook::get_named_ranges() const
return named_ranges; return named_ranges;
} }
std::size_t workbook::add_format(const format &style) std::size_t workbook::add_format(const format &to_add)
{ {
auto format_copy = style; return d_->stylesheet_.add_format(to_add);
}
//TODO this is ugly
if (!style.get_number_format().has_id()) std::size_t workbook::add_style(const style &to_add)
{ {
bool match = false; return d_->stylesheet_.add_style(to_add);
}
for (std::size_t i = 0; i < d_->formats_.size(); i++)
{ bool workbook::has_style(const std::string &name) const
const auto &current_number_format = d_->formats_.at(i).get_number_format(); {
return std::find_if(d_->stylesheet_.styles.begin(), d_->stylesheet_.styles.end(),
if (current_number_format.get_format_string() == format_copy.get_number_format().get_format_string()) [&](const style &s) { return s.get_name() == name; }) != d_->stylesheet_.styles.end();
{ }
format_copy.set_number_format(current_number_format);
match = true; std::size_t workbook::get_style_id(const std::string &name) const
break; {
} return std::distance(d_->stylesheet_.styles.begin(),
} std::find_if(d_->stylesheet_.styles.begin(), d_->stylesheet_.styles.end(),
[&](const style &s) { return s.get_name() == name; }));
if (!match)
{
format_copy.get_number_format().set_id(d_->next_custom_format_id_++);
}
}
// TODO hashmap?
for (std::size_t i = 0; i < d_->formats_.size(); i++)
{
if (d_->formats_[i] == format_copy)
{
return i;
}
}
d_->formats_.push_back(format_copy);
return d_->formats_.size() - 1;
} }
void workbook::clear_styles() void workbook::clear_styles()
{ {
d_->styles_.clear(); d_->stylesheet_.styles.clear();
apply_to_cells([](cell c) { c.clear_style(); });
} }
void workbook::clear_formats() void workbook::clear_formats()
{ {
d_->formats_.clear(); d_->stylesheet_.formats.clear();
apply_to_cells([](cell c) { c.clear_format(); });
}
void workbook::apply_to_cells(std::function<void(cell)> f)
{
for (auto ws : *this)
{
for (auto r : ws.iter_cells(true))
{
for (auto c : r)
{
f.operator()(c);
}
}
}
} }
format &workbook::get_format(std::size_t format_index) format &workbook::get_format(std::size_t format_index)
{ {
return d_->formats_.at(format_index); return d_->stylesheet_.formats.at(format_index);
} }
const format &workbook::get_format(std::size_t format_index) const const format &workbook::get_format(std::size_t format_index) const
{ {
return d_->formats_.at(format_index); return d_->stylesheet_.formats.at(format_index);
} }
manifest &workbook::get_manifest() manifest &workbook::get_manifest()
@ -749,30 +747,30 @@ style &workbook::create_style(const std::string &name)
style style; style style;
style.set_name(name); style.set_name(name);
d_->styles_.push_back(style); d_->stylesheet_.styles.push_back(style);
return d_->styles_.back(); return d_->stylesheet_.styles.back();
} }
std::vector<format> &workbook::get_formats() std::vector<format> &workbook::get_formats()
{ {
return d_->formats_; return d_->stylesheet_.formats;
} }
const std::vector<format> &workbook::get_formats() const const std::vector<format> &workbook::get_formats() const
{ {
return d_->formats_; return d_->stylesheet_.formats;
} }
style &workbook::get_style(const std::string &name) style &workbook::get_style(const std::string &name)
{ {
return *std::find_if(d_->styles_.begin(), d_->styles_.end(), return *std::find_if(d_->stylesheet_.styles.begin(), d_->stylesheet_.styles.end(),
[&name](const style &s) { return s.get_name() == name; }); [&name](const style &s) { return s.get_name() == name; });
} }
const style &workbook::get_style(const std::string &name) const const style &workbook::get_style(const std::string &name) const
{ {
return *std::find_if(d_->styles_.begin(), d_->styles_.end(), return *std::find_if(d_->stylesheet_.styles.begin(), d_->stylesheet_.styles.end(),
[&name](const style &s) { return s.get_name() == name; }); [&name](const style &s) { return s.get_name() == name; });
} }

View File

@ -43,6 +43,7 @@
#include <detail/cell_impl.hpp> #include <detail/cell_impl.hpp>
#include <detail/constants.hpp> #include <detail/constants.hpp>
#include <detail/workbook_impl.hpp>
#include <detail/worksheet_impl.hpp> #include <detail/worksheet_impl.hpp>
namespace xlnt { namespace xlnt {
@ -995,4 +996,9 @@ sheet_view worksheet::get_sheet_view() const
return d_->view_; return d_->view_;
} }
std::size_t worksheet::next_custom_number_format_id()
{
return get_workbook().d_->stylesheet_.next_custom_format_id++;
}
} // namespace xlnt } // namespace xlnt