working on styles, don't use yet

This commit is contained in:
Thomas Fussell 2016-11-02 18:16:34 -04:00
parent eeba8ffa86
commit 4e51e9e0e5
17 changed files with 1070 additions and 513 deletions

View File

@ -36,7 +36,6 @@ namespace xlnt {
enum class calendar; enum class calendar;
class alignment; class alignment;
class base_format;
class border; class border;
class cell_reference; class cell_reference;
class comment; class comment;
@ -177,41 +176,32 @@ public:
// computed format // computed format
/// <summary> /// <summary>
/// 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.
/// </summary>
base_format get_computed_format() const;
/// <summary>
/// Returns the result of get_computed_format().get_alignment().
/// </summary> /// </summary>
alignment get_computed_alignment() const; alignment get_computed_alignment() const;
/// <summary> /// <summary>
/// Returns the result of get_computed_format().get_border(). ///
/// </summary> /// </summary>
border get_computed_border() const; border get_computed_border() const;
/// <summary> /// <summary>
/// Returns the result of get_computed_format().get_fill(). ///
/// </summary> /// </summary>
fill get_computed_fill() const; fill get_computed_fill() const;
/// <summary> /// <summary>
/// Returns the result of get_computed_format().get_font(). ///
/// </summary> /// </summary>
font get_computed_font() const; font get_computed_font() const;
/// <summary> /// <summary>
/// Returns the result of get_computed_format().get_number_format(). ///
/// </summary> /// </summary>
number_format get_computed_number_format() const; number_format get_computed_number_format() const;
/// <summary> /// <summary>
/// Returns the result of get_computed_format().get_protection(). ///
/// </summary> /// </summary>
protection get_computed_protection() const; protection get_computed_protection() const;
@ -492,27 +482,21 @@ private:
// make these friends so they can use the private constructor // make these friends so they can use the private constructor
friend class style; friend class style;
friend class worksheet; friend class worksheet;
friend class detail::xlsx_consumer; friend class detail::xlsx_consumer;
friend class detail::xlsx_producer; friend class detail::xlsx_producer;
friend struct detail::cell_impl; friend struct detail::cell_impl;
/// <summary> /// <summary>
/// Helper function to guess the type of a string, convert it, /// Helper function to guess the type of a string, convert it,
/// and then use the correct cell::get_value according to the type. /// and then use the correct cell::get_value according to the type.
/// </summary> /// </summary>
void guess_type_and_set_value(const std::string &value); void guess_type_and_set_value(const std::string &value);
/// <summary>
/// Returns a non-const reference to the format of this cell.
/// This is for internal use only.
/// </summary>
format &get_format_internal();
/// <summary> /// <summary>
/// Use workbook::create_format() to create a new format then copy /// Returns a non-const reference to the format of this cell.
/// this cell's formatting to that new format and return it. /// This is for internal use only.
/// </summary> /// </summary>
format &duplicate_format(); format &get_format_internal();
/// <summary> /// <summary>
/// Private constructor to create a cell from its implementation. /// Private constructor to create a cell from its implementation.

View File

@ -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 <xlnt/xlnt_config.hpp>
#include <xlnt/styles/alignment.hpp>
#include <xlnt/styles/border.hpp>
#include <xlnt/styles/fill.hpp>
#include <xlnt/styles/font.hpp>
#include <xlnt/styles/number_format.hpp>
#include <xlnt/styles/protection.hpp>
namespace xlnt {
/// <summary>
/// Describes the formatting of a particular cell.
/// </summary>
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

View File

@ -36,53 +36,200 @@ class fill;
class font; class font;
class number_format; class number_format;
class protection; class protection;
class workbook;
namespace detail { namespace detail {
struct format_impl; struct format_impl;
struct stylesheet; struct stylesheet;
class xlsx_consumer;
class xlsx_producer;
} // namespace detail } // namespace detail
/// <summary> /// <summary>
/// Describes the formatting of a particular cell. /// Describes the formatting of a particular cell.
/// </summary> /// </summary>
class XLNT_API format : public base_format class XLNT_API format
{ {
public: public:
std::size_t id() const; /// <summary>
/// Returns the index of this format.
bool has_style() const; /// </summary>
void clear_style(); std::size_t id() const;
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;
class font &font() override; // Alignment
const class font &font() const override;
void font(const xlnt::font &new_font, bool applied) override;
class number_format &number_format() override; /// <summary>
const class number_format &number_format() const override; /// Returns the alignment to be applied to contents of cells using this format.
void number_format(const xlnt::number_format &new_number_format, bool applied) override; /// </summary>
class alignment &alignment();
format &alignment_id(std::size_t id); /// <summary>
format &border_id(std::size_t id); /// Returns the alignment to be applied to contents of cells using this format.
format &fill_id(std::size_t id); /// </summary>
format &font_id(std::size_t id); const class alignment &alignment() const;
format &number_format_id(std::size_t id);
format &protection_id(std::size_t id); /// <summary>
/// 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.
/// </summary>
void alignment(const xlnt::alignment &new_alignment,
bool applied = true, bool update = true);
/// <summary>
/// Returns true if the alignment is being applied.
/// </summary>
bool alignment_applied() const;
// Border
/// <summary>
/// Returns the border properties to be applied to the outline of cells using this format.
/// </summary>
class border &border();
/// <summary>
/// Returns the border properties to be applied to the outline of cells using this format.
/// </summary>
const class border &border() const;
/// <summary>
/// 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.
/// </summary>
void border(const xlnt::border &new_border,
bool applied = true, bool update = true);
/// <summary>
/// Returns true if the border is being applied.
/// </summary>
bool border_applied() const;
// Fill
/// <summary>
/// Returns the fill to be applied to the background of cells using this format.
/// </summary>
class fill &fill();
/// <summary>
/// Returns the fill to be applied to the background of cells using this format.
/// </summary>
const class fill &fill() const;
/// <summary>
/// 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.
/// </summary>
void fill(const xlnt::fill &new_fill,
bool applied = true, bool update = true);
/// <summary>
/// Returns true if the fill is being applied.
/// </summary>
bool fill_applied() const;
// Font
/// <summary>
/// Returns the font to be applied to contents of cells using this format.
/// </summary>
class font &font();
/// <summary>
/// Returns the font to be applied to contents of cells using this format.
/// </summary>
const class font &font() const;
/// <summary>
/// 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.
/// </summary>
void font(const xlnt::font &new_font,
bool applied = true, bool update = true);
/// <summary>
/// Returns true if the font is being applied.
/// </summary>
bool font_applied() const;
// Number Format
/// <summary>
/// Returns the number format to be applied to text/numbers in cells using this format.
/// </summary>
class number_format &number_format();
/// <summary>
/// Returns the number format to be applied to text/numbers in cells using this format.
/// </summary>
const class number_format &number_format() const;
/// <summary>
/// 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.
/// </summary>
void number_format(const xlnt::number_format &new_number_format,
bool applied = true, bool update = true);
/// <summary>
/// Returns true if the number format is being applied.
/// </summary>
bool number_format_applied() const;
// Protection
/// <summary>
/// Returns the protection to be applied to the contents of cells using this format.
/// </summary>
class protection &protection();
/// <summary>
/// Returns the protection to be applied to the contents of cells using this format.
/// </summary>
const class protection &protection() const;
/// <summary>
/// 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.
/// </summary>
void protection(const xlnt::protection &new_protection,
bool applied = true, bool update = true);
/// <summary>
/// Returns true if the protection is being applied.
/// </summary>
bool protection_applied() const;
/// <summary>
/// Returns true if the formats are identical.
/// </summary>
XLNT_API friend bool operator==(const format &left, const format &right);
private: private:
friend struct detail::stylesheet; friend struct detail::stylesheet;
format(detail::format_impl *d); friend class detail::xlsx_consumer;
detail::format_impl *d_; friend class detail::xlsx_producer;
friend class cell;
friend class workbook;
/// <summary>
/// Private constructor used by stylesheet.
/// </summary>
format(detail::format_impl *d);
/// <summary>
/// Pointer to implementation. This memory is held in a vector in stylesheet.
/// </summary>
detail::format_impl *d_;
}; };
} // namespace xlnt } // namespace xlnt

View File

@ -27,7 +27,6 @@
#include <string> #include <string>
#include <xlnt/xlnt_config.hpp> #include <xlnt/xlnt_config.hpp>
#include <xlnt/styles/base_format.hpp>
namespace xlnt { namespace xlnt {
@ -40,7 +39,7 @@ struct stylesheet;
/// 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_API style : public base_format class XLNT_API style
{ {
public: public:
std::string name() const; std::string name() const;
@ -55,18 +54,152 @@ public:
optional<std::size_t> builtin_id() const; optional<std::size_t> builtin_id() const;
style &builtin_id(std::size_t builtin_id); style &builtin_id(std::size_t builtin_id);
style &alignment_id(std::size_t id); // Alignment
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);
bool operator==(const style &other); /// <summary>
/// Returns the alignment to be applied to contents of cells using this format.
/// </summary>
class alignment &alignment();
/// <summary>
/// Returns the alignment to be applied to contents of cells using this format.
/// </summary>
const class alignment &alignment() const;
/// <summary>
/// Sets the alignment of this format to new_alignment. If applied is true,
/// the alignment will be used when displaying the cell.
/// </summary>
void alignment(const xlnt::alignment &new_alignment, bool applied = true, bool update = true);
/// <summary>
/// Returns true if the alignment is being applied.
/// </summary>
bool alignment_applied() const;
// Border
/// <summary>
/// Returns the border properties to be applied to the outline of cells using this format.
/// </summary>
class border &border();
/// <summary>
/// Returns the border properties to be applied to the outline of cells using this format.
/// </summary>
const class border &border() const;
/// <summary>
/// Sets the border of this format to new_border. If applied is true,
/// the border will be used when displaying the cell.
/// </summary>
void border(const xlnt::border &new_border, bool applied = true, bool update = true);
/// <summary>
/// Returns true if the border is being applied.
/// </summary>
bool border_applied() const;
// Fill
/// <summary>
/// Returns the fill to be applied to the background of cells using this format.
/// </summary>
class fill &fill();
/// <summary>
/// Returns the fill to be applied to the background of cells using this format.
/// </summary>
const class fill &fill() const;
/// <summary>
/// Sets the fill of this format to new_fill and applies it if applied is true.
/// </summary>
void fill(const xlnt::fill &new_fill, bool applied = true, bool update = true);
/// <summary>
/// Returns true if the fill is being applied.
/// </summary>
bool fill_applied() const;
// Font
/// <summary>
/// Returns the font to be applied to contents of cells using this format.
/// </summary>
class font &font();
/// <summary>
/// Returns the font to be applied to contents of cells using this format.
/// </summary>
const class font &font() const;
/// <summary>
/// Sets the font of this format to new_font and applies it if applied is true.
/// </summary>
void font(const xlnt::font &new_font, bool applied = true, bool update = true);
/// <summary>
/// Returns true if the font is being applied.
/// </summary>
bool font_applied() const;
// Number Format
/// <summary>
/// Returns the number format to be applied to text/numbers in cells using this format.
/// </summary>
class number_format &number_format();
/// <summary>
/// Returns the number format to be applied to text/numbers in cells using this format.
/// </summary>
const class number_format &number_format() const;
/// <summary>
/// Sets the number format applied to text/numbers in cells using this format
/// and applies it if applied is true.
/// </summary>
void number_format(const xlnt::number_format &new_number_format, bool applied = true, bool update = true);
/// <summary>
/// Returns true if the number format is being applied.
/// </summary>
bool number_format_applied() const;
// Protection
/// <summary>
/// Returns the protection to be applied to the contents of cells using this format.
/// </summary>
class protection &protection();
/// <summary>
/// Returns the protection to be applied to the contents of cells using this format.
/// </summary>
const class protection &protection() const;
/// <summary>
/// Sets the protection of the contents of the cell using this format. Applies it if
/// applied is true.
/// </summary>
void protection(const xlnt::protection &new_protection, bool applied = true, bool update = true);
/// <summary>
/// Returns true if the protection is being applied.
/// </summary>
bool protection_applied() const;
/// <summary>
/// Returns true if the formats are identical.
/// </summary>
XLNT_API friend bool operator==(const style &left, const style &right);
private: private:
friend struct detail::stylesheet; friend struct detail::stylesheet;
style(detail::style_impl *d); style(detail::style_impl *d);
detail::style_impl *d_; detail::style_impl *d_;
}; };

View File

@ -36,6 +36,7 @@
namespace xlnt { namespace xlnt {
class alignment; class alignment;
class base_format;
class border; class border;
class cell; class cell;
class cell_style; class cell_style;
@ -419,7 +420,9 @@ public:
format &get_format(std::size_t format_index); format &get_format(std::size_t format_index);
const format &get_format(std::size_t format_index) const; 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(); void clear_formats();
// styles // styles

View File

@ -30,8 +30,14 @@
#include <xlnt/cell/comment.hpp> #include <xlnt/cell/comment.hpp>
#include <xlnt/cell/formatted_text.hpp> #include <xlnt/cell/formatted_text.hpp>
#include <xlnt/packaging/relationship.hpp> #include <xlnt/packaging/relationship.hpp>
#include <xlnt/styles/alignment.hpp>
#include <xlnt/styles/border.hpp>
#include <xlnt/styles/color.hpp> #include <xlnt/styles/color.hpp>
#include <xlnt/styles/fill.hpp>
#include <xlnt/styles/font.hpp>
#include <xlnt/styles/format.hpp> #include <xlnt/styles/format.hpp>
#include <xlnt/styles/number_format.hpp>
#include <xlnt/styles/protection.hpp>
#include <xlnt/styles/style.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>
@ -44,6 +50,7 @@
#include <xlnt/worksheet/worksheet.hpp> #include <xlnt/worksheet/worksheet.hpp>
#include <detail/cell_impl.hpp> #include <detail/cell_impl.hpp>
#include <detail/format_impl.hpp>
namespace { namespace {
@ -610,32 +617,104 @@ void cell::set_data_type(type t)
number_format cell::get_computed_number_format() const 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 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 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 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 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 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() void cell::clear_value()
@ -758,44 +837,80 @@ XLNT_API timedelta cell::get_value() const
void cell::set_alignment(const xlnt::alignment &alignment_) void cell::set_alignment(const xlnt::alignment &alignment_)
{ {
auto &format = duplicate_format(); if (!has_format())
format.alignment(alignment_, true); {
d_->format_id_ = format.id(); 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_) void cell::set_border(const xlnt::border &border_)
{ {
auto &format = duplicate_format(); if (!has_format())
format.border(border_, true); {
d_->format_id_ = format.id(); 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_) void cell::set_fill(const xlnt::fill &fill_)
{ {
auto &format = duplicate_format(); if (!has_format())
format.fill(fill_, true); {
d_->format_id_ = format.id(); 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_) void cell::set_font(const font &font_)
{ {
auto &format = duplicate_format(); if (!has_format())
format.font(font_, true); {
d_->format_id_ = format.id(); 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_) void cell::set_number_format(const number_format &number_format_)
{ {
auto &format = duplicate_format(); if (!has_format())
format.number_format(number_format_, true); {
d_->format_id_ = format.id(); 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_) void cell::set_protection(const xlnt::protection &protection_)
{ {
auto &format = duplicate_format(); if (!has_format())
format.protection(protection_, true); {
d_->format_id_ = format.id(); set_format(get_workbook().create_format());
get_format().protection(protection_, true, true);
}
else
{
get_format().protection(protection_, true, false);
}
} }
template <> template <>
@ -898,81 +1013,39 @@ void cell::clear_style()
{ {
if (has_format()) if (has_format())
{ {
get_format_internal().clear_style(); get_format().d_->style.clear();
} }
} }
void cell::set_style(const style &new_style) void cell::set_style(const style &new_style)
{ {
auto &new_format = duplicate_format(); if (!has_format())
new_format.style(new_style); {
d_->format_id_ = new_format.id(); 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) void cell::set_style(const std::string &style_name)
{ {
auto &new_format = duplicate_format(); set_style(get_workbook().get_style(style_name));
new_format.style(get_workbook().get_style(style_name).name());
d_->format_id_ = new_format.id();
} }
style cell::get_style() const style cell::get_style() const
{ {
if (!has_format() || !get_format().has_style()) if (!has_format() || !get_format().d_->style.is_set())
{ {
throw invalid_attribute(); throw invalid_attribute();
} }
return get_format().style(); return get_workbook().get_style(get_format().d_->style.get());
} }
bool cell::has_style() const bool cell::has_style() const
{ {
return has_format() && get_format().has_style(); return has_format() && get_format().d_->style.is_set();
}
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;
} }
format &cell::get_format_internal() format &cell::get_format_internal()
@ -985,25 +1058,6 @@ format &cell::get_format_internal()
return get_workbook().get_format(*d_->format_id_); return get_workbook().get_format(*d_->format_id_);
} }
format &cell::duplicate_format()
{
auto &new_format = get_workbook().create_format();
if (has_format())
{
auto &current_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 format cell::get_format() const
{ {
if (!d_->format_id_) if (!d_->format_id_)

View File

@ -18,6 +18,19 @@ public:
wb_guess_types.set_guess_types(true); 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() void test_infer_numeric()
{ {
auto ws = wb_guess_types.create_sheet(); auto ws = wb_guess_types.create_sheet();

View File

@ -29,14 +29,42 @@ struct format_impl
std::size_t id; std::size_t id;
bool alignment_applied = false;
optional<std::size_t> alignment_id; optional<std::size_t> alignment_id;
bool border_applied = false;
optional<std::size_t> border_id; optional<std::size_t> border_id;
bool fill_applied = false;
optional<std::size_t> fill_id; optional<std::size_t> fill_id;
bool font_applied = false;
optional<std::size_t> font_id; optional<std::size_t> font_id;
bool number_format_applied = false;
optional<std::size_t> number_format_id; optional<std::size_t> number_format_id;
bool protection_applied = false;
optional<std::size_t> protection_id; optional<std::size_t> protection_id;
optional<std::string> style; optional<std::string> 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 } // namespace detail

View File

@ -31,12 +31,18 @@ struct style_impl
optional<std::size_t> builtin_id; optional<std::size_t> builtin_id;
optional<std::size_t> outline_style; optional<std::size_t> outline_style;
optional<class alignment> alignment; bool alignment_applied = false;
optional<class border> border; optional<std::size_t> alignment_id;
optional<class fill> fill; bool border_applied = false;
optional<class font> font; optional<std::size_t> border_id;
optional<class number_format> number_format; bool fill_applied = false;
optional<class protection> protection; optional<std::size_t> fill_id;
bool font_applied = false;
optional<std::size_t> font_id;
bool number_format_applied = false;
optional<std::size_t> number_format_id;
bool protection_applied = false;
optional<std::size_t> protection_id;
}; };
} // namespace detail } // namespace detail

View File

@ -25,6 +25,7 @@
#include <list> #include <list>
#include <string> #include <string>
#include <unordered_map>
#include <vector> #include <vector>
#include <detail/format_impl.hpp> #include <detail/format_impl.hpp>
@ -38,23 +39,23 @@ namespace detail {
struct stylesheet struct stylesheet
{ {
~stylesheet()
{
}
format &create_format() format &create_format()
{ {
format_impls.push_back(format_impl()); format_impls.push_back(format_impl());
auto &impl = format_impls.back(); auto &impl = format_impls.back();
impl.parent = this; impl.parent = this;
impl.id = format_impls.size() - 1; impl.id = format_impls.size() - 1;
formats.push_back(format(&impl)); formats.push_back(format(&impl));
auto &format = formats.back(); auto &format = formats.back();
if (!alignments.empty()) if (!alignments.empty())
{ {
format.alignment(alignments.front(), false); format.alignment(alignments.front(), false);
} }
else
{
format.alignment(alignment(), false);
}
if (!borders.empty()) if (!borders.empty())
{ {
@ -73,7 +74,7 @@ struct stylesheet
if (!number_formats.empty()) if (!number_formats.empty())
{ {
format.number_format(number_formats.front(), false); format.number_format(number_formats.begin()->second, false);
} }
if (!protections.empty()) if (!protections.empty())
@ -84,10 +85,27 @@ struct stylesheet
return format; return format;
} }
format &get_format(std::size_t index) format &get_format(std::size_t index)
{ {
return formats.at(index); return formats.at(index);
} }
std::pair<bool, std::size_t> 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() style &create_style()
{ {
@ -130,14 +148,26 @@ struct stylesheet
for (const auto &nf : number_formats) 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; 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) std::size_t add_border(const border &new_border)
{ {
@ -196,6 +226,26 @@ struct stylesheet
return index; 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() void clear()
{ {
format_impls.clear(); format_impls.clear();
@ -224,7 +274,7 @@ struct stylesheet
std::vector<border> borders; std::vector<border> borders;
std::vector<fill> fills; std::vector<fill> fills;
std::vector<font> fonts; std::vector<font> fonts;
std::vector<number_format> number_formats; std::unordered_map<std::size_t, number_format> number_formats;
std::vector<protection> protections; std::vector<protection> protections;
std::vector<color> colors; std::vector<color> colors;

View File

@ -1265,7 +1265,7 @@ void xlsx_consumer::read_stylesheet()
nf.set_format_string(format_string); nf.set_format_string(format_string);
nf.set_id(string_to_size_t(parser().attribute("numFmtId"))); 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 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) 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; is_custom_number_format = true;
break; break;
} }
@ -1552,7 +1552,7 @@ void xlsx_consumer::read_stylesheet()
{ {
auto &new_format = stylesheet.create_format(); 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.alignment(record.alignment.first, record.alignment.second);
new_format.border(stylesheet.borders.at(record.border_id.first), record.border_id.second); new_format.border(stylesheet.borders.at(record.border_id.first), record.border_id.second);

View File

@ -776,8 +776,8 @@ void xlsx_producer::write_styles(const relationship &rel)
for (const auto &num_fmt : number_formats) for (const auto &num_fmt : number_formats)
{ {
serializer().start_element(xmlns, "numFmt"); serializer().start_element(xmlns, "numFmt");
serializer().attribute("numFmtId", num_fmt.get_id()); serializer().attribute("numFmtId", num_fmt.first);
serializer().attribute("formatCode", num_fmt.get_format_string()); serializer().attribute("formatCode", num_fmt.second.get_format_string());
serializer().end_element(xmlns, "numFmt"); 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.alignment_applied()) serializer().attribute("applyAlignment", write_bool(true));
if (current_format.protection_applied()) serializer().attribute("applyProtection", 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(), serializer().attribute("xfId", std::distance(stylesheet.styles.begin(),
std::find_if(stylesheet.styles.begin(), stylesheet.styles.end(), 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()) if (current_format.alignment_applied())

View File

@ -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 <xlnt/styles/base_format.hpp>
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

View File

@ -38,132 +38,334 @@ std::size_t format::id() const
return d_->id; 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) auto alignment_id = d_->parent->add_alignment(new_alignment);
{
if (style.name() == new_style)
{
d_->style = new_style;
return;
}
}
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 impl_copy.alignment_id = alignment_id;
{ impl_copy.alignment_applied = applied;
return d_->style;
}
const style &format::style() const auto match = std::find(d_->parent->format_impls.begin(), d_->parent->format_impls.end(), impl_copy);
{
if (!has_style())
{
throw invalid_attribute();
}
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() xlnt::border &format::border()
{ {
return base_format::border(); const auto &self = *this;
return const_cast<class border &>(self.border());
} }
const xlnt::border &format::border() const 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)); auto border_id = d_->parent->add_border(new_border);
base_format::border(new_border, applied);
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() xlnt::fill &format::fill()
{ {
return base_format::fill(); const auto &self = *this;
return const_cast<class fill &>(self.fill());
} }
const xlnt::fill &format::fill() const 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)); auto fill_id = d_->parent->add_fill(new_fill);
base_format::fill(new_fill, applied);
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() xlnt::font &format::font()
{ {
return base_format::font(); const auto &self = *this;
return const_cast<class font &>(self.font());
} }
const xlnt::font &format::font() const 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)); auto font_id = d_->parent->add_font(new_font);
base_format::font(new_font, applied);
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() xlnt::number_format &format::number_format()
{ {
return base_format::number_format(); const auto &self = *this;
return const_cast<class number_format &>(self.number_format());
} }
const xlnt::number_format &format::number_format() const 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; auto copy = new_number_format;
if (!copy.has_id()) if (!copy.has_id())
{ {
copy.set_id(d_->parent->next_custom_number_format_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 d_->parent->protections.at(d_->protection_id);
return *this;
} }
format &format::fill_id(std::size_t id) const protection &format::protection() const
{ {
d_->fill_id = id; return d_->parent->protections.at(d_->protection_id);
return *this;
} }
format &format::font_id(std::size_t id) void format::protection(const xlnt::protection &new_protection, bool applied, bool update)
{ {
d_->font_id = id; auto protection_id = d_->parent->add_protection(new_protection);
return *this;
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 } // namespace xlnt

View File

@ -22,13 +22,14 @@
// @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 <detail/style_impl.hpp> // include order is important here
#include <detail/stylesheet.hpp>
#include <xlnt/styles/alignment.hpp> #include <xlnt/styles/alignment.hpp>
#include <xlnt/styles/border.hpp> #include <xlnt/styles/border.hpp>
#include <xlnt/styles/fill.hpp> #include <xlnt/styles/fill.hpp>
#include <xlnt/styles/font.hpp> #include <xlnt/styles/font.hpp>
#include <xlnt/styles/number_format.hpp> #include <xlnt/styles/number_format.hpp>
#include <xlnt/styles/protection.hpp> #include <xlnt/styles/protection.hpp>
#include <detail/style_impl.hpp> // include order is important here
#include <xlnt/styles/style.hpp> #include <xlnt/styles/style.hpp>
namespace xlnt { namespace xlnt {
@ -81,9 +82,171 @@ style &style::custom(bool value)
return *this; 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<class border &>(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<class fill &>(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<class font &>(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<class number_format &>(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 } // namespace xlnt

View File

@ -165,7 +165,7 @@ workbook workbook::empty_excel()
auto &default_format = wb.create_format(); auto &default_format = wb.create_format();
default_format.font(default_font, false); default_format.font(default_font, false);
default_format.border(default_border, false); default_format.border(default_border, false);
default_format.style("Normal"); default_format.d_->style.set("Normal");
wb.set_theme(theme()); wb.set_theme(theme());
@ -255,7 +255,7 @@ workbook workbook::empty_libre_office()
auto default_number_format = xlnt::number_format(); auto default_number_format = xlnt::number_format();
default_number_format.set_format_string("General"); default_number_format.set_format_string("General");
default_number_format.set_id(164); 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() auto default_protection = xlnt::protection()
.locked(true) .locked(true)
@ -314,7 +314,7 @@ workbook workbook::empty_libre_office()
format.number_format(default_number_format, true); format.number_format(default_number_format, true);
format.alignment(default_alignment, true); format.alignment(default_alignment, true);
format.protection(default_protection, true); format.protection(default_protection, true);
format.style("Normal"); format.d_->style.set("Normal");
wb.d_->has_file_version_ = true; wb.d_->has_file_version_ = true;
wb.d_->file_version_.app_name = "Calc"; wb.d_->file_version_.app_name = "Calc";
@ -993,10 +993,32 @@ std::vector<named_range> workbook::get_named_ranges() const
format &workbook::create_format() format &workbook::create_format()
{ {
register_stylesheet_in_manifest(); register_stylesheet_in_manifest();
return d_->stylesheet_.create_format(); 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 bool workbook::has_style(const std::string &name) const
{ {
return d_->stylesheet_.has_style(name); return d_->stylesheet_.has_style(name);

2
third-party/botan vendored

@ -1 +1 @@
Subproject commit dad94a550613733d8c75b2fbd8db47048dfdaf13 Subproject commit 73c2605f50e6192bf6cb560c51d32bc53b4c5597