improve styles

pull/67/head
Thomas Fussell 2016-08-18 07:34:18 -04:00
parent 182e37958d
commit f9a45313a0
28 changed files with 1212 additions and 838 deletions

View File

@ -36,6 +36,7 @@ namespace xlnt {
enum class calendar;
class alignment;
class base_format;
class border;
class cell_reference;
class comment;
@ -107,6 +108,7 @@ public:
/// Set the value of this cell to the given value.
/// Overloads exist for most C++ fundamental types like bool, int, etc. as well
/// as for std::string and xlnt datetime types: date, time, datetime, and timedelta.
/// </summary>
template <typename T>
void set_value(T value);
@ -181,7 +183,7 @@ public:
/// 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>
format get_computed_format() const;
base_format get_computed_format() const;
/// <summary>
/// Returns the result of get_computed_format().get_alignment().
@ -241,7 +243,7 @@ public:
/// <summary>
/// Returns the number format of this cell.
/// </summary>
const number_format &get_number_format() const;
number_format get_number_format() const;
/// <summary>
/// Creates a new format in the workbook, sets its number_format
@ -252,7 +254,7 @@ public:
/// <summary>
/// Returns the font applied to the text in this cell.
/// </summary>
const font &get_font() const;
font get_font() const;
/// <summary>
/// Creates a new format in the workbook, sets its font
@ -263,7 +265,7 @@ public:
/// <summary>
/// Returns the fill applied to this cell.
/// </summary>
const fill &get_fill() const;
fill get_fill() const;
/// <summary>
/// Creates a new format in the workbook, sets its fill
@ -274,7 +276,7 @@ public:
/// <summary>
/// Returns the border of this cell.
/// </summary>
const border &get_border() const;
border get_border() const;
/// <summary>
/// Creates a new format in the workbook, sets its border
@ -285,7 +287,7 @@ public:
/// <summary>
/// Returns the alignment of the text in this cell.
/// </summary>
const alignment &get_alignment() const;
alignment get_alignment() const;
/// <summary>
/// Creates a new format in the workbook, sets its alignment
@ -296,7 +298,7 @@ public:
/// <summary>
/// Returns the protection of this cell.
/// </summary>
const protection &get_protection() const;
protection get_protection() const;
/// <summary>
/// Creates a new format in the workbook, sets its protection
@ -316,11 +318,6 @@ public:
/// </summary>
style get_style() const;
/// <summary>
/// Returns the name of the style applied to this cell.
/// </summary>
std::string get_style_name() const;
/// <summary>
/// Equivalent to set_style(new_style.name())
/// </summary>
@ -487,7 +484,7 @@ private:
/// Returns a non-const reference to the format of this cell.
/// This is for internal use only.
/// </summary>
format &get_format();
format &get_format_internal();
/// <summary>
/// Private constructor to create a cell from its implementation.

View File

@ -70,8 +70,8 @@ private:
optional<bool> wrap_text_;
optional<int> indent_;
optional<int> text_rotation_;
optional<horizontal_alignment> horizontal_;
optional<vertical_alignment> vertical_;
optional<horizontal_alignment> horizontal_ = horizontal_alignment::general;
optional<vertical_alignment> vertical_ = vertical_alignment::bottom;
};
} // namespace xlnt

View File

@ -36,79 +36,59 @@ namespace xlnt {
/// <summary>
/// Describes the formatting of a particular cell.
/// </summary>
class XLNT_CLASS base_format : public hashable
class XLNT_CLASS base_format
{
public:
base_format();
base_format(const base_format &other);
base_format &operator=(const base_format &other);
void reset();
// Alignment
alignment &get_alignment();
const alignment &get_alignment() const;
void set_alignment(const alignment &new_alignment);
void remove_alignment();
xlnt::alignment &alignment();
const xlnt::alignment &alignment() const;
void alignment(const xlnt::alignment &new_alignment, bool applied);
bool alignment_applied() const;
void alignment_applied(bool applied);
// Border
border &get_border();
const border &get_border() const;
void set_border(const border &new_border);
void remove_border();
xlnt::border &border();
const xlnt::border &border() const;
void border(const xlnt::border &new_border, bool applied);
bool border_applied() const;
void border_applied(bool applied);
// Fill
fill &get_fill();
const fill &get_fill() const;
void set_fill(const fill &new_fill);
void remove_fill();
xlnt::fill &fill();
const xlnt::fill &fill() const;
void fill(const xlnt::fill &new_fill, bool applied);
bool fill_applied() const;
void fill_applied(bool applied);
// Font
font &get_font();
const font &get_font() const;
void set_font(const font &new_font);
void remove_font();
xlnt::font &font();
const xlnt::font &font() const;
void font(const xlnt::font &new_font, bool applied);
bool font_applied() const;
void font_applied(bool applied);
// Number Format
number_format &get_number_format();
const number_format &get_number_format() const;
void set_number_format(const number_format &new_number_format);
void remove_number_format();
virtual xlnt::number_format &number_format();
virtual const xlnt::number_format &number_format() const;
virtual void number_format(const xlnt::number_format &new_number_format, bool applied);
bool number_format_applied() const;
void number_format_applied(bool applied);
// Protection
protection &get_protection();
const protection &get_protection() const;
void set_protection(const protection &new_protection);
void remove_protection();
xlnt::protection &protection();
const xlnt::protection &protection() const;
void protection(const xlnt::protection &new_protection, bool applied);
bool protection_applied() const;
void protection_applied(bool applied);
protected:
std::string to_hash_string() const override;
alignment alignment_;
border border_;
fill fill_;
font font_;
number_format number_format_;
protection protection_;
xlnt::alignment alignment_;
xlnt::border border_;
xlnt::fill fill_;
xlnt::font font_;
xlnt::number_format number_format_;
xlnt::protection protection_;
bool apply_alignment_;
bool apply_border_;
bool apply_fill_;
bool apply_font_;
bool apply_number_format_;
bool apply_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

@ -26,6 +26,7 @@
#include <string>
#include <xlnt/xlnt_config.hpp>
#include <xlnt/styles/base_format.hpp>
namespace xlnt {
@ -44,31 +45,26 @@ struct stylesheet;
/// <summary>
/// Describes the formatting of a particular cell.
/// </summary>
class XLNT_CLASS format
class XLNT_CLASS format : public base_format
{
public:
std::size_t get_id() const;
std::size_t id() const;
alignment get_alignment() const;
void set_alignment(const alignment &new_alignment);
bool has_style() const;
void style(const std::string &name);
void style(const xlnt::style &new_style);
const xlnt::style &style() const;
border get_border() const;
void set_border(const border &new_border);
virtual xlnt::number_format &number_format();
virtual const xlnt::number_format &number_format() const;
void number_format(const xlnt::number_format &new_number_format, bool applied) override;
fill get_fill() const;
void set_fill(const fill &new_fill);
font get_font() const;
void set_font(const font &new_font);
number_format get_number_format() const;
void set_number_format(const number_format &new_number_format);
protection get_protection() const;
void set_protection(const protection &new_protection);
void set_style(const std::string &name);
std::string get_name() const;
format &alignment_id(std::size_t id);
format &border_id(std::size_t id);
format &fill_id(std::size_t id);
format &font_id(std::size_t id);
format &number_format_id(std::size_t id);
format &protection_id(std::size_t id);
private:
friend struct detail::stylesheet;

View File

@ -26,6 +26,7 @@
#include <cstdint>
#include <string>
#include <xlnt/xlnt_config.hpp>
#include <xlnt/styles/base_format.hpp>
namespace xlnt {
@ -39,7 +40,7 @@ struct stylesheet;
/// Describes a style which has a name and can be applied to multiple individual
/// formats. In Excel this is a "Cell Style".
/// </summary>
class XLNT_CLASS style
class XLNT_CLASS style : public base_format
{
public:
std::string name() const;
@ -48,11 +49,20 @@ public:
bool hidden() const;
style &hidden(bool value);
bool custom() const;
optional<bool> custom() const;
style &custom(bool value);
std::size_t built_in_id() const;
style &built_in_id(std::size_t builtin_id);
optional<std::size_t> builtin_id() const;
style &builtin_id(std::size_t builtin_id);
style &alignment_id(std::size_t id);
style &border_id(std::size_t id);
style &fill_id(std::size_t id);
style &font_id(std::size_t id);
style &number_format_id(std::size_t id);
style &protection_id(std::size_t id);
bool operator==(const style &other);
private:
friend struct detail::stylesheet;

View File

@ -185,6 +185,12 @@ bool cell::garbage_collectible() const
return !(get_data_type() != type::null || is_merged() || has_formula() || has_format());
}
template <>
XLNT_FUNCTION void cell::set_value(nullptr_t)
{
d_->type_ = type::null;
}
template <>
XLNT_FUNCTION void cell::set_value(bool b)
{
@ -411,7 +417,9 @@ bool cell::is_merged() const
bool cell::is_date() const
{
return get_data_type() == type::numeric && get_number_format().is_date_format();
return get_data_type() == type::numeric
&& has_format()
&& get_number_format().is_date_format();
}
cell_reference cell::get_reference() const
@ -605,32 +613,32 @@ void cell::set_data_type(type t)
number_format cell::get_computed_number_format() const
{
return get_computed_format().get_number_format();
return get_computed_format().number_format();
}
font cell::get_computed_font() const
{
return get_computed_format().get_font();
return get_computed_format().font();
}
fill cell::get_computed_fill() const
{
return get_computed_format().get_fill();
return get_computed_format().fill();
}
border cell::get_computed_border() const
{
return get_computed_format().get_border();
return get_computed_format().border();
}
alignment cell::get_computed_alignment() const
{
return get_computed_format().get_alignment();
return get_computed_format().alignment();
}
protection cell::get_computed_protection() const
{
return get_computed_format().get_protection();
return get_computed_format().protection();
}
void cell::clear_value()
@ -753,32 +761,44 @@ XLNT_FUNCTION timedelta cell::get_value() const
void cell::set_border(const xlnt::border &border_)
{
get_format().set_border(border_);
auto &format = get_workbook().create_format();
format.border(border_, true);
d_->format_id_ = format.id();
}
void cell::set_fill(const xlnt::fill &fill_)
{
get_format().set_fill(fill_);
auto &format = get_workbook().create_format();
format.fill(fill_, true);
d_->format_id_ = format.id();
}
void cell::set_font(const font &font_)
{
get_format().set_font(font_);
auto &format = get_workbook().create_format();
format.font(font_, true);
d_->format_id_ = format.id();
}
void cell::set_number_format(const number_format &number_format_)
{
get_format().set_number_format(number_format_);
auto &format = get_workbook().create_format();
format.number_format(number_format_, true);
d_->format_id_ = format.id();
}
void cell::set_alignment(const xlnt::alignment &alignment_)
{
get_format().set_alignment(alignment_);
auto &format = get_workbook().create_format();
format.alignment(alignment_, true);
d_->format_id_ = format.id();
}
void cell::set_protection(const xlnt::protection &protection_)
{
get_format().set_protection(protection_);
auto &format = get_workbook().create_format();
format.protection(protection_, true);
d_->format_id_ = format.id();
}
template <>
@ -800,18 +820,18 @@ bool cell::has_value() const
std::string cell::to_string() const
{
auto nf = get_number_format();
auto nf = get_computed_number_format();
switch (get_data_type())
{
case cell::type::null:
return "";
case cell::type::numeric:
return get_number_format().format(get_value<long double>(), get_base_date());
return nf.format(get_value<long double>(), get_base_date());
case cell::type::string:
case cell::type::formula:
case cell::type::error:
return get_number_format().format(get_value<std::string>());
return nf.format(get_value<std::string>());
case cell::type::boolean:
return get_value<long double>() == 0 ? "FALSE" : "TRUE";
default:
@ -819,11 +839,6 @@ std::string cell::to_string() const
}
}
format &cell::get_format()
{
return get_workbook().get_format(d_->format_id_);
}
bool cell::has_format() const
{
return d_->format_id_.is_set();
@ -831,7 +846,7 @@ bool cell::has_format() const
void cell::set_format(const format &new_format)
{
d_->format_id_ = get_workbook().create_format().get_id();
d_->format_id_ = get_workbook().create_format().id();
}
calendar cell::get_base_date() const
@ -894,7 +909,7 @@ void cell::set_style(const style &new_style)
void cell::set_style(const std::string &style_name)
{
d_->style_name_ = style_name;
d_->style_name_ = get_workbook().get_style(style_name).name();
}
style cell::get_style() const
@ -912,4 +927,103 @@ bool cell::has_style() const
return d_->style_name_;
}
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()
{
if (!d_->format_id_)
{
throw invalid_attribute();
}
return get_workbook().get_format(*d_->format_id_);
}
format cell::get_format() const
{
if (!d_->format_id_)
{
throw invalid_attribute();
}
return get_workbook().get_format(*d_->format_id_);
}
alignment cell::get_alignment() const
{
return get_format().alignment();
}
border cell::get_border() const
{
return get_format().border();
}
fill cell::get_fill() const
{
return get_format().fill();
}
font cell::get_font() const
{
return get_format().font();
}
number_format cell::get_number_format() const
{
return get_format().number_format();
}
protection cell::get_protection() const
{
return get_format().protection();
}
bool cell::has_hyperlink() const
{
return d_->hyperlink_;
}
} // namespace xlnt

View File

@ -34,8 +34,8 @@ comment::comment(detail::comment_impl *d) : d_(d)
comment::comment(cell parent, const std::string &text, const std::string &author) : d_(nullptr)
{
d_->text_ = text;
d_->author_ = author;
/*d_->text_ = text;
d_->author_ = author;*/
}
comment::comment() : d_(nullptr)

View File

@ -73,7 +73,6 @@ public:
TS_ASSERT(cell.get_row() == 1);
TS_ASSERT(cell.get_reference() == "A1");
TS_ASSERT(!cell.has_value());
TS_ASSERT(!cell.has_comment());
}
void test_null()
@ -297,37 +296,6 @@ public:
TS_ASSERT(cell.to_repr() == "<Cell Sheet2.A1>");
}
void test_comment_assignment()
{
auto ws = wb.create_sheet();
auto cell = ws.get_cell(xlnt::cell_reference(1, 1));
TS_ASSERT(!cell.has_comment());
xlnt::comment comm(cell, "text", "author");
TS_ASSERT(cell.get_comment() == comm);
cell.set_comment(comm);
}
void test_only_one_cell_per_comment()
{
auto ws = wb.create_sheet();
auto cell = ws.get_cell(xlnt::cell_reference(1, 1));
xlnt::comment comm(cell, "text", "author");
auto c2 = ws.get_cell(xlnt::cell_reference(1, 2));
TS_ASSERT_THROWS(c2.set_comment(comm), xlnt::invalid_attribute);
}
void test_remove_comment()
{
auto ws = wb.create_sheet();
auto cell = ws.get_cell(xlnt::cell_reference(1, 1));
xlnt::comment comm(cell, "text", "author");
cell.clear_comment();
TS_ASSERT(!cell.has_comment());
}
void test_cell_offset()
{
auto ws = wb.create_sheet();
@ -340,8 +308,7 @@ public:
auto ws = wb.create_sheet();
auto cell = ws.get_cell("A1");
xlnt::font font;
font.set_bold(true);
auto font = xlnt::font().bold(true);
cell.set_font(font);
@ -398,7 +365,7 @@ public:
auto cell = ws.get_cell("A1");
xlnt::alignment align;
align.set_wrap_text(true);
align.wrap(true);
cell.set_alignment(align);
@ -414,11 +381,12 @@ public:
TS_ASSERT(!cell.has_format());
cell.set_protection(xlnt::protection(false, true));
auto protection = xlnt::protection().locked(false).hidden(true);
cell.set_protection(protection);
TS_ASSERT(cell.has_format());
TS_ASSERT(cell.get_format().protection_applied());
TS_ASSERT_EQUALS(cell.get_protection(), xlnt::protection(false, true));
TS_ASSERT_EQUALS(cell.get_protection(), protection);
TS_ASSERT(cell.has_format());
cell.clear_format();
@ -433,25 +401,25 @@ public:
TS_ASSERT(!cell.has_style());
auto &test_style = wb.create_style("test_style");
test_style.set_number_format(xlnt::number_format::date_ddmmyyyy());
test_style.number_format(xlnt::number_format::date_ddmmyyyy(), true);
cell.set_style(test_style);
TS_ASSERT(cell.has_style());
TS_ASSERT_EQUALS(cell.get_style().get_number_format(), xlnt::number_format::date_ddmmyyyy());
TS_ASSERT_EQUALS(cell.get_style().number_format(), xlnt::number_format::date_ddmmyyyy());
TS_ASSERT_EQUALS(cell.get_style(), test_style);
auto &other_style = wb.create_style("other_style");
other_style.set_number_format(xlnt::number_format::date_time2());
other_style.number_format(xlnt::number_format::date_time2(), true);
cell.set_style("other_style");
TS_ASSERT_EQUALS(cell.get_style().get_number_format(), xlnt::number_format::date_time2());
TS_ASSERT_EQUALS(cell.get_style().number_format(), xlnt::number_format::date_time2());
TS_ASSERT_EQUALS(cell.get_style(), other_style);
xlnt::style last_style;
last_style.set_number_format(xlnt::number_format::percentage());
auto &last_style = wb.create_style("last_style");
last_style.number_format(xlnt::number_format::percentage(), true);
cell.set_style(last_style);
TS_ASSERT_EQUALS(cell.get_style().get_number_format(), xlnt::number_format::percentage());
TS_ASSERT_EQUALS(cell.get_style().number_format(), xlnt::number_format::percentage());
TS_ASSERT_EQUALS(cell.get_style(), last_style);
TS_ASSERT_THROWS(cell.set_style("doesn't exist"), xlnt::key_not_found);
@ -604,20 +572,6 @@ public:
TS_ASSERT_EQUALS(cell.get_value<std::string>(), std::string(32'767, 'a'));
}
void test_comment()
{
xlnt::workbook wb;
auto cell_a1 = wb.get_active_sheet().get_cell("A1");
xlnt::comment comment(cell_a1, "text", "author");
auto cell_a2 = wb.get_active_sheet().get_cell("A2");
cell_a2 = cell_a1;
TS_ASSERT(cell_a2.has_comment());
TS_ASSERT_EQUALS(cell_a2.get_comment().get_text(), "text");
TS_ASSERT_EQUALS(cell_a2.get_comment().get_author(), "author");
xlnt::comment null;
TS_ASSERT_DIFFERS(null, comment);
}
void test_reference()
{
xlnt::cell_reference_hash hash;

View File

@ -27,14 +27,16 @@ struct format_impl
{
stylesheet *parent;
std::size_t formatting_record_id;
std::size_t id;
optional<alignment> alignment;
optional<border> border;
optional<fill> fill;
optional<font> font;
optional<number_format> number_format;
optional<protection> protection;
optional<std::size_t> alignment;
optional<std::size_t> border;
optional<std::size_t> fill;
optional<std::size_t> font;
optional<std::size_t> number_format;
optional<std::size_t> protection;
optional<std::string> style;
};
} // namespace detail

View File

@ -25,10 +25,10 @@ struct style_impl
std::string name;
std::size_t formatting_record_id;
bool custom_built_in;
optional<bool> custom_builtin;
bool hidden_style;
optional<std::size_t> built_in_style_id;
optional<std::size_t> builtin_id;
optional<std::size_t> outline_style;
optional<alignment> alignment;

View File

@ -23,6 +23,7 @@
// @author: see AUTHORS file
#pragma once
#include <list>
#include <string>
#include <vector>
@ -43,28 +44,35 @@ struct stylesheet
format &create_format()
{
formats.push_back(format_impl());
return format(&formats.back());
format_impls.push_back(format_impl());
auto &impl = format_impls.back();
impl.parent = this;
impl.id = format_impls.size() - 1;
formats.push_back(format(&impl));
return formats.back();
}
format &get_format(std::size_t index)
{
return format(&formats.at(index));
return formats.at(index);
}
style &create_style()
{
styles.push_back(style_impl());
return style(&styles.back());
style_impls.push_back(style_impl());
auto &impl = style_impls.back();
impl.parent = this;
styles.push_back(style(&impl));
return styles.back();
}
style &get_style(const std::string &name)
{
for (auto &s : styles)
{
if (s.name == name)
if (s.name() == name)
{
return style(&s);
return s;
}
}
@ -75,7 +83,7 @@ struct stylesheet
{
for (auto &s : styles)
{
if (s.name == name)
if (s.name() == name)
{
return true;
}
@ -84,8 +92,26 @@ struct stylesheet
return false;
}
std::vector<format_impl> formats;
std::vector<style_impl> styles;
std::size_t next_custom_number_format_id() const
{
std::size_t id = 164;
for (const auto &nf : number_formats)
{
if (nf.get_id() > id)
{
id = nf.get_id() + 1;
}
}
return id;
}
std::list<format_impl> format_impls;
std::vector<format> formats;
std::list<style_impl> style_impls;
std::vector<style> styles;
std::vector<alignment> alignments;
std::vector<border> borders;

View File

@ -68,7 +68,8 @@ struct workbook_impl
has_code_name_(false),
has_file_version_(false),
has_calculation_properties_(false),
has_arch_id_(false)
has_arch_id_(false),
short_bools_(true)
{
}
@ -114,7 +115,8 @@ struct workbook_impl
has_file_version_(other.has_file_version_),
file_version_(other.file_version_),
has_calculation_properties_(other.has_calculation_properties_),
has_arch_id_(other.has_arch_id_)
has_arch_id_(other.has_arch_id_),
short_bools_(other.short_bools_)
{
}
@ -170,6 +172,8 @@ struct workbook_impl
has_calculation_properties_ = other.has_calculation_properties_;
has_arch_id_ = other.has_arch_id_;
short_bools_ = other.short_bools_;
return *this;
}
@ -235,6 +239,8 @@ struct workbook_impl
bool has_calculation_properties_;
bool has_arch_id_;
bool short_bools_;
};
} // namespace detail

View File

@ -5,6 +5,7 @@
#include <detail/constants.hpp>
#include <detail/include_pugixml.hpp>
#include <detail/workbook_impl.hpp>
#include <xlnt/cell/cell.hpp>
#include <xlnt/utils/path.hpp>
#include <xlnt/packaging/manifest.hpp>
#include <xlnt/packaging/zip_file.hpp>
@ -211,6 +212,13 @@ std::string to_string(xlnt::border_side side)
switch (side)
{
case xlnt::border_side::bottom: return "bottom";
case xlnt::border_side::top: return "top";
case xlnt::border_side::start: return "start";
case xlnt::border_side::end: return "end";
case xlnt::border_side::horizontal: return "horizontal";
case xlnt::border_side::vertical: return "vertical";
default:
case xlnt::border_side::diagonal: return "diagonal";
}
}
@ -513,130 +521,6 @@ void read_borders(const pugi::xml_node &borders_node, std::vector<xlnt::border>
}
}
bool read_base_format(const pugi::xml_node &format_node, const xlnt::detail::stylesheet &stylesheet, xlnt::base_format &f)
{
// Alignment
f.alignment_applied(format_node.child("alignment") || is_true(format_node.attribute("applyAlignment").value()));
if (f.alignment_applied())
{
auto inline_alignment = read_alignment(format_node.child("alignment"));
f.set_alignment(inline_alignment);
}
// Border
auto border_index = format_node.attribute("borderId") ? string_to_size_t(format_node.attribute("borderId").value()) : 0;
f.set_border(stylesheet.borders.at(border_index));
f.border_applied(is_true(format_node.attribute("applyBorder").value()));
// Fill
auto fill_index = format_node.attribute("fillId") ? string_to_size_t(format_node.attribute("fillId").value()) : 0;
f.set_fill(stylesheet.fills.at(fill_index));
f.fill_applied(is_true(format_node.attribute("applyFill").value()));
// Font
auto font_index = format_node.attribute("fontId") ? string_to_size_t(format_node.attribute("fontId").value()) : 0;
f.set_font(stylesheet.fonts.at(font_index));
f.font_applied(is_true(format_node.attribute("applyFont").value()));
// Number Format
auto number_format_id = string_to_size_t(format_node.attribute("numFmtId").value());
bool builtin_format = true;
for (const auto &num_fmt : stylesheet.number_formats)
{
if (static_cast<std::size_t>(num_fmt.get_id()) == number_format_id)
{
f.set_number_format(num_fmt);
builtin_format = false;
break;
}
}
if (builtin_format)
{
try
{
f.set_number_format(xlnt::number_format::from_builtin_id(number_format_id));
}
catch (std::runtime_error)
{
f.set_number_format(xlnt::number_format::general());
}
}
f.number_format_applied(is_true(format_node.attribute("applyNumberFormat").value()));
// Protection
f.protection_applied(format_node.attribute("protection") || is_true(format_node.attribute("applyProtection").value()));
if (f.protection_applied())
{
auto inline_protection = read_protection(format_node.child("protection"));
f.set_protection(inline_protection);
}
return true;
}
void read_formats(const pugi::xml_node &formats_node, const xlnt::detail::stylesheet &stylesheet,
std::vector<xlnt::format> &formats, std::vector<std::string> &format_styles)
{
for (auto format_node : formats_node.children("xf"))
{
xlnt::format format;
read_base_format(format_node, stylesheet, format);
auto style_index = string_to_size_t(format_node.attribute("xfId").value());
auto style_name = stylesheet.style_name_map.at(style_index);
format_styles.push_back(style_name);
formats.push_back(format);
}
}
xlnt::style read_style(const pugi::xml_node &style_node, const pugi::xml_node &style_format_node, const xlnt::detail::stylesheet &stylesheet)
{
xlnt::style s;
read_base_format(style_format_node, stylesheet, s);
s.name(style_node.attribute("name").value());
s.hidden(style_node.attribute("hidden") && is_true(style_node.attribute("hidden").value()));
s.built_in_id(string_to_size_t(style_node.attribute("builtinId").value()));
return s;
}
void read_styles(const pugi::xml_node &styles_node, const pugi::xml_node &style_formats_node, const xlnt::detail::stylesheet stylesheet, std::vector<xlnt::style> &styles, std::unordered_map<std::size_t, std::string> &style_names)
{
std::size_t style_index = 0;
for (auto cell_style_format_node : style_formats_node.children())
{
bool match = false;
for (auto cell_style_node : styles_node.children())
{
auto cell_style_format_index = std::stoull(cell_style_node.attribute("xfId").value());
if (cell_style_format_index == style_index)
{
styles.push_back(read_style(cell_style_node, cell_style_format_node, stylesheet));
style_names[style_index] = styles.back().get_name();
match = true;
break;
}
}
style_index++;
}
}
std::vector<xlnt::relationship> read_relationships(const xlnt::path &part, xlnt::zip_file &archive)
{
std::vector<xlnt::relationship> relationships;
@ -1153,8 +1037,103 @@ void xlsx_consumer::read_stylesheet(const pugi::xml_node root)
read_fonts(stylesheet_node.child("fonts"), stylesheet.fonts);
read_number_formats(stylesheet_node.child("numFmts"), stylesheet.number_formats);
read_colors(stylesheet_node.child("colors"), stylesheet.colors);
read_styles(stylesheet_node.child("cellStyles"), stylesheet_node.child("cellStyleXfs"), stylesheet, stylesheet.styles, stylesheet.style_name_map);
read_formats(stylesheet_node.child("cellXfs"), stylesheet, stylesheet.formats, stylesheet.format_styles);
auto cell_styles_node = stylesheet_node.child("cellStyles");
auto cell_style_range = cell_styles_node.children("cellStyle");
auto cell_style_iter = cell_style_range.begin();
auto cell_style_xfs_node = stylesheet_node.child("cellStyleXfs");
for (auto xf_node : cell_style_xfs_node.children("xf"))
{
auto cell_style_node = *(cell_style_iter++);
auto &style = destination_.create_style(cell_style_node.attribute("Name").value());
// Alignment
auto alignment_node = xf_node.child("alignment");
auto apply_alignment_attr = xf_node.attribute("applyAlignment");
auto alignment_applied = apply_alignment_attr ? is_true(xf_node.attribute("applyAlignment").value()) : alignment_node != nullptr;
auto alignment = alignment_node ? read_alignment(alignment_node) : xlnt::alignment();
style.alignment(alignment, alignment_applied);
// Border
auto border_applied = is_true(xf_node.attribute("applyBorder").value());
auto border_index = xf_node.attribute("borderId") ? string_to_size_t(xf_node.attribute("borderId").value()) : 0;
auto border = stylesheet.borders.at(border_index);
style.border(stylesheet.borders.at(border_index), border_applied);
// Fill
auto fill_applied = is_true(xf_node.attribute("applyFill").value());
auto fill_index = xf_node.attribute("fillId") ? string_to_size_t(xf_node.attribute("fillId").value()) : 0;
auto fill = stylesheet.fills.at(fill_index);
style.fill(fill, fill_applied);
// Font
auto font_applied = is_true(xf_node.attribute("applyFont").value());
auto font_index = xf_node.attribute("fontId") ? string_to_size_t(xf_node.attribute("fontId").value()) : 0;
auto font = stylesheet.fonts.at(font_index);
style.font(font, font_applied);
// Number Format
auto number_format_applied = is_true(xf_node.attribute("applyNumberFormat").value());
auto number_format_id = xf_node.attribute("numFmtId") ? string_to_size_t(xf_node.attribute("numFmtId").value()) : 0;
auto number_format = stylesheet.number_formats.at(number_format_id);
style.number_format(number_format, number_format_applied);
// Protection
auto protection_node = xf_node.child("protection");
auto apply_protection_attr = xf_node.attribute("applyProtection");
auto protection_applied = apply_protection_attr ? is_true(apply_protection_attr.value()) : protection_node != nullptr;
auto protection = protection_node ? read_protection(protection_node) : xlnt::protection();
style.protection(protection, protection_applied);
}
for (auto xf_node : stylesheet_node.child("cellXfs").children("xf"))
{
auto &format = destination_.create_format();
// Alignment
auto alignment_node = xf_node.child("alignment");
auto apply_alignment_attr = xf_node.attribute("applyAlignment");
auto alignment_applied = apply_alignment_attr ? is_true(xf_node.attribute("applyAlignment").value()) : alignment_node != nullptr;
auto alignment = alignment_node ? read_alignment(alignment_node) : xlnt::alignment();
format.alignment(alignment, alignment_applied);
// Border
auto border_applied = is_true(xf_node.attribute("applyBorder").value());
auto border_index = xf_node.attribute("borderId") ? string_to_size_t(xf_node.attribute("borderId").value()) : 0;
auto border = stylesheet.borders.at(border_index);
format.border(stylesheet.borders.at(border_index), border_applied);
// Fill
auto fill_applied = is_true(xf_node.attribute("applyFill").value());
auto fill_index = xf_node.attribute("fillId") ? string_to_size_t(xf_node.attribute("fillId").value()) : 0;
auto fill = stylesheet.fills.at(fill_index);
format.fill(fill, fill_applied);
// Font
auto font_applied = is_true(xf_node.attribute("applyFont").value());
auto font_index = xf_node.attribute("fontId") ? string_to_size_t(xf_node.attribute("fontId").value()) : 0;
auto font = stylesheet.fonts.at(font_index);
format.font(font, font_applied);
// Number Format
auto number_format_applied = is_true(xf_node.attribute("applyNumberFormat").value());
auto number_format_id = xf_node.attribute("numFmtId") ? string_to_size_t(xf_node.attribute("numFmtId").value()) : 0;
auto number_format = stylesheet.number_formats.at(number_format_id);
format.number_format(number_format, number_format_applied);
// Protection
auto protection_node = xf_node.child("protection");
auto apply_protection_attr = xf_node.attribute("applyProtection");
auto protection_applied = apply_protection_attr ? is_true(apply_protection_attr.value()) : protection_node != nullptr;
auto protection = protection_node ? read_protection(protection_node) : xlnt::protection();
format.protection(protection, protection_applied);
// Style
auto style_index = string_to_size_t(xf_node.attribute("xfId").value());
auto style_name = stylesheet.styles.at(style_index).name();
format.style(stylesheet.get_style(style_name));
}
}
void xlsx_consumer::read_theme(const pugi::xml_node root)
@ -1338,7 +1317,7 @@ void xlsx_consumer::read_worksheet(const pugi::xml_node root, const std::string
if (has_format)
{
cell.set_format_id(format_id);
cell.set_format(destination_.get_format(format_id));
}
}
}

View File

@ -3,6 +3,7 @@
#include <detail/constants.hpp>
#include <detail/include_pugixml.hpp>
#include <detail/workbook_impl.hpp>
#include <xlnt/cell/cell.hpp>
#include <xlnt/utils/path.hpp>
#include <xlnt/packaging/manifest.hpp>
#include <xlnt/packaging/zip_file.hpp>
@ -183,6 +184,13 @@ std::string to_string(xlnt::border_side side)
switch (side)
{
case xlnt::border_side::bottom: return "bottom";
case xlnt::border_side::top: return "top";
case xlnt::border_side::start: return "left";
case xlnt::border_side::end: return "right";
case xlnt::border_side::horizontal: return "horizontal";
case xlnt::border_side::vertical: return "vertical";
default:
case xlnt::border_side::diagonal: return "diagonal";
}
}
@ -231,291 +239,6 @@ bool write_color(const xlnt::color &color, pugi::xml_node color_node)
return true;
}
bool write_fonts(const std::vector<xlnt::font> &fonts, pugi::xml_node &fonts_node)
{
fonts_node.append_attribute("count").set_value(std::to_string(fonts.size()).c_str());
fonts_node.append_attribute("x14ac:knownFonts").set_value(std::to_string(fonts.size()).c_str());
for (auto &f : fonts)
{
auto font_node = fonts_node.append_child("font");
if (f.bold())
{
auto bold_node = font_node.append_child("b");
bold_node.append_attribute("val").set_value("1");
}
if (f.italic())
{
auto italic_node = font_node.append_child("i");
italic_node.append_attribute("val").set_value("1");
}
if (f.underlined())
{
auto underline_node = font_node.append_child("u");
underline_node.append_attribute("val").set_value(to_string(f.underline()).c_str());
}
if (f.strikethrough())
{
auto strike_node = font_node.append_child("strike");
strike_node.append_attribute("val").set_value("1");
}
auto size_node = font_node.append_child("sz");
size_node.append_attribute("val").set_value(std::to_string(f.size()).c_str());
if (f.color())
{
auto color_node = font_node.append_child("color");
write_color(*f.color(), color_node);
}
auto name_node = font_node.append_child("name");
name_node.append_attribute("val").set_value(f.name().c_str());
if (f.family())
{
auto family_node = font_node.append_child("family");
family_node.append_attribute("val").set_value(std::to_string(*f.family()).c_str());
}
if (f.scheme())
{
auto scheme_node = font_node.append_child("scheme");
scheme_node.append_attribute("val").set_value(f.scheme()->c_str());
}
}
return true;
}
bool write_fills(const std::vector<xlnt::fill> &fills, pugi::xml_node &fills_node)
{
fills_node.append_attribute("count").set_value(std::to_string(fills.size()).c_str());
for (auto &fill_ : fills)
{
auto fill_node = fills_node.append_child("fill");
if (fill_.type() == xlnt::fill_type::pattern)
{
const auto &pattern = fill_.pattern_fill();
auto pattern_fill_node = fill_node.append_child("patternFill");
pattern_fill_node.append_attribute("patternType").set_value(to_string(pattern.type()).c_str());
if (pattern.foreground())
{
write_color(*pattern.foreground(), pattern_fill_node.append_child("fgColor"));
}
if (pattern.background())
{
write_color(*pattern.background(), pattern_fill_node.append_child("bgColor"));
}
}
else if (fill_.type() == xlnt::fill_type::gradient)
{
const auto &gradient = fill_.gradient_fill();
auto gradient_fill_node = fill_node.append_child("gradientFill");
auto gradient_fill_type_string = to_string(gradient.type());
gradient_fill_node.append_attribute("gradientType").set_value(gradient_fill_type_string.c_str());
if (gradient.degree() != 0)
{
gradient_fill_node.append_attribute("degree").set_value(gradient.degree());
}
if (gradient.left() != 0)
{
gradient_fill_node.append_attribute("left").set_value(gradient.left());
}
if (gradient.right() != 0)
{
gradient_fill_node.append_attribute("right").set_value(gradient.right());
}
if (gradient.top() != 0)
{
gradient_fill_node.append_attribute("top").set_value(gradient.top());
}
if (gradient.bottom() != 0)
{
gradient_fill_node.append_attribute("bottom").set_value(gradient.bottom());
}
for (const auto &stop : gradient.stops())
{
auto stop_node = gradient_fill_node.append_child("stop");
stop_node.append_attribute("position").set_value(stop.first);
write_color(stop.second, stop_node.append_child("color"));
}
}
}
return true;
}
bool write_borders(const std::vector<xlnt::border> &borders, pugi::xml_node &borders_node)
{
borders_node.append_attribute("count").set_value(std::to_string(borders.size()).c_str());
for (const auto &border_ : borders)
{
auto border_node = borders_node.append_child("border");
for (const auto &side : xlnt::border::all_sides())
{
if (border_.side(side))
{
auto side_name = to_string(side);
auto side_node = border_node.append_child(side_name.c_str());
const auto current_side = *border_.side(side);
if (current_side.style())
{
auto style_string = to_string(*current_side.style());
side_node.append_attribute("style").set_value(style_string.c_str());
}
if (current_side.color())
{
auto color_node = side_node.append_child("color");
write_color(*current_side.color(), color_node);
}
}
}
}
return true;
}
bool write_alignment(const xlnt::alignment &a, pugi::xml_node alignment_node)
{
if (a.has_vertical())
{
auto vertical = to_string(a.get_vertical());
alignment_node.append_attribute("vertical").set_value(vertical.c_str());
}
if (a.has_horizontal())
{
auto horizontal = to_string(a.get_horizontal());
alignment_node.append_attribute("horizontal").set_value(horizontal.c_str());
}
if (a.get_wrap_text())
{
alignment_node.append_attribute("wrapText").set_value("1");
}
if (a.get_shrink_to_fit())
{
alignment_node.append_attribute("shrinkToFit").set_value("1");
}
return true;
}
bool write_protection(const xlnt::protection &p, pugi::xml_node protection_node)
{
protection_node.append_attribute("locked").set_value(p.get_locked() ? "1" : "0");
protection_node.append_attribute("hidden").set_value(p.get_hidden() ? "1" : "0");
return true;
}
bool write_base_format(const xlnt::base_format &xf, const xlnt::detail::stylesheet &stylesheet, pugi::xml_node xf_node)
{
xf_node.append_attribute("numFmtId").set_value(std::to_string(xf.get_number_format().get_id()).c_str());
auto font_id = std::distance(stylesheet.fonts.begin(), std::find(stylesheet.fonts.begin(), stylesheet.fonts.end(), xf.get_font()));
xf_node.append_attribute("fontId").set_value(std::to_string(font_id).c_str());
auto fill_id = std::distance(stylesheet.fills.begin(), std::find(stylesheet.fills.begin(), stylesheet.fills.end(), xf.get_fill()));
xf_node.append_attribute("fillId").set_value(std::to_string(fill_id).c_str());
auto border_id = std::distance(stylesheet.borders.begin(), std::find(stylesheet.borders.begin(), stylesheet.borders.end(), xf.get_border()));
xf_node.append_attribute("borderId").set_value(std::to_string(border_id).c_str());
if (xf.number_format_applied()) xf_node.append_attribute("applyNumberFormat").set_value("1");
if (xf.fill_applied()) xf_node.append_attribute("applyFill").set_value("1");
if (xf.font_applied()) xf_node.append_attribute("applyFont").set_value("1");
if (xf.border_applied()) xf_node.append_attribute("applyBorder").set_value("1");
if (xf.alignment_applied())
{
xf_node.append_attribute("applyAlignment").set_value("1");
write_alignment(xf.get_alignment(), xf_node.append_child("alignment"));
}
if (xf.protection_applied())
{
xf_node.append_attribute("applyProtection").set_value("1");
write_protection(xf.get_protection(), xf_node.append_child("protection"));
}
return true;
}
bool write_styles(const xlnt::detail::stylesheet &stylesheet, pugi::xml_node &styles_node, pugi::xml_node &style_formats_node)
{
style_formats_node.append_attribute("count").set_value(std::to_string(stylesheet.styles.size()).c_str());
styles_node.append_attribute("count").set_value(std::to_string(stylesheet.styles.size()).c_str());
std::size_t style_index = 0;
for (auto &current_style : stylesheet.styles)
{
auto xf_node = style_formats_node.append_child("xf");
write_base_format(current_style, stylesheet, xf_node);
auto cell_style_node = styles_node.append_child("cellStyle");
cell_style_node.append_attribute("name").set_value(current_style.get_name().c_str());
cell_style_node.append_attribute("xfId").set_value(std::to_string(style_index++).c_str());
cell_style_node.append_attribute("builtinId").set_value(std::to_string(current_style.get_builtin_id()).c_str());
if (current_style.get_hidden())
{
cell_style_node.append_attribute("hidden").set_value("1");
}
}
return true;
}
bool write_formats(const xlnt::detail::stylesheet &stylesheet, pugi::xml_node &formats_node)
{
formats_node.append_attribute("count").set_value(std::to_string(stylesheet.formats.size()).c_str());
auto format_style_iterator = stylesheet.format_styles.begin();
for (auto &current_format : stylesheet.formats)
{
auto xf_node = formats_node.append_child("xf");
write_base_format(current_format, stylesheet, xf_node);
const auto format_style_name = *(format_style_iterator++);
if (!format_style_name.empty())
{
auto style = std::find_if(stylesheet.styles.begin(), stylesheet.styles.end(),
[&](const xlnt::style &s) { return s.get_name() == format_style_name; });
auto style_index = std::distance(stylesheet.styles.begin(), style);
xf_node.append_attribute("xfId").set_value(std::to_string(style_index).c_str());
}
}
return true;
}
bool write_dxfs(pugi::xml_node &dxfs_node)
{
dxfs_node.append_attribute("count").set_value("0");
@ -545,20 +268,6 @@ bool write_colors(const std::vector<xlnt::color> &colors, pugi::xml_node &colors
return true;
}
bool write_number_formats(const std::vector<xlnt::number_format> &number_formats, pugi::xml_node &number_formats_node)
{
number_formats_node.append_attribute("count").set_value(std::to_string(number_formats.size()).c_str());
for (const auto &num_fmt : number_formats)
{
auto num_fmt_node = number_formats_node.append_child("numFmt");
num_fmt_node.append_attribute("numFmtId").set_value(std::to_string(num_fmt.get_id()).c_str());
num_fmt_node.append_attribute("formatCode").set_value(num_fmt.get_format_string().c_str());
}
return true;
}
} // namespace
namespace xlnt {
@ -889,7 +598,7 @@ void xlsx_producer::write_workbook(const relationship &rel, pugi::xml_node root)
{
auto defined_name_node = defined_names_node.append_child("definedName");
defined_name_node.append_attribute("name").set_value("_xlnm._FilterDatabase");
defined_name_node.append_attribute("hidden").set_value("1");
defined_name_node.append_attribute("hidden").set_value(write_bool(true).c_str());
defined_name_node.append_attribute("localSheetId").set_value("0");
std::string name =
"'" + ws.get_title() + "'!" + range_reference::make_absolute(ws.get_auto_filter()).to_string();
@ -971,9 +680,11 @@ void xlsx_producer::write_workbook(const relationship &rel, pugi::xml_node root)
case relationship::type::pivot_table:
write_pivot_table(child_rel, document.root());
break;
case relationship::type::shared_string_table:
write_shared_string_table(child_rel, document.root());
break;
case relationship::type::shared_workbook_revision_headers:
write_shared_workbook_revision_headers(child_rel, document.root());
break;
@ -1123,57 +834,430 @@ void xlsx_producer::write_shared_workbook_user_data(const relationship &rel, pug
void xlsx_producer::write_styles(const relationship &rel, pugi::xml_node root)
{
auto stylesheet_node = root.append_child("styleSheet");
// Namespaces
stylesheet_node.append_attribute("xmlns").set_value("http://schemas.openxmlformats.org/spreadsheetml/2006/main");
stylesheet_node.append_attribute("xmlns:mc").set_value("http://schemas.openxmlformats.org/markup-compatibility/2006");
stylesheet_node.append_attribute("mc:Ignorable").set_value("x14ac");
stylesheet_node.append_attribute("xmlns:x14ac").set_value("http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac");
if (source_.x15_enabled())
{
stylesheet_node.append_attribute("xmlns:mc").set_value("http://schemas.openxmlformats.org/markup-compatibility/2006");
stylesheet_node.append_attribute("mc:Ignorable").set_value("x14ac");
stylesheet_node.append_attribute("xmlns:x14ac").set_value("http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac");
}
const auto &stylesheet = source_.impl().stylesheet_;
// Number Formats
if (!stylesheet.number_formats.empty())
{
auto number_formats_node = stylesheet_node.append_child("numFmts");
write_number_formats(stylesheet.number_formats, number_formats_node);
const auto &number_formats = stylesheet.number_formats;
number_formats_node.append_attribute("count").set_value(std::to_string(number_formats.size()).c_str());
for (const auto &num_fmt : number_formats)
{
auto num_fmt_node = number_formats_node.append_child("numFmt");
num_fmt_node.append_attribute("numFmtId").set_value(std::to_string(num_fmt.get_id()).c_str());
num_fmt_node.append_attribute("formatCode").set_value(num_fmt.get_format_string().c_str());
}
}
// Fonts
if (!stylesheet.fonts.empty())
{
auto fonts_node = stylesheet_node.append_child("fonts");
write_fonts(stylesheet.fonts, fonts_node);
const auto &fonts = stylesheet.fonts;
fonts_node.append_attribute("count").set_value(std::to_string(fonts.size()).c_str());
if (source_.x15_enabled())
{
fonts_node.append_attribute("x14ac:knownFonts").set_value(std::to_string(fonts.size()).c_str());
}
for (const auto &current_font : fonts)
{
auto font_node = fonts_node.append_child("font");
if (current_font.bold())
{
auto bold_node = font_node.append_child("b");
bold_node.append_attribute("val").set_value(write_bool(true).c_str());
}
if (current_font.italic())
{
auto italic_node = font_node.append_child("i");
italic_node.append_attribute("val").set_value(write_bool(true).c_str());
}
if (current_font.underlined())
{
auto underline_node = font_node.append_child("u");
underline_node.append_attribute("val").set_value(to_string(current_font.underline()).c_str());
}
if (current_font.strikethrough())
{
auto strike_node = font_node.append_child("strike");
strike_node.append_attribute("val").set_value(write_bool(true).c_str());
}
auto size_node = font_node.append_child("sz");
size_node.append_attribute("val").set_value(std::to_string(current_font.size()).c_str());
if (current_font.color())
{
auto color_node = font_node.append_child("color");
write_color(*current_font.color(), color_node);
}
auto name_node = font_node.append_child("name");
name_node.append_attribute("val").set_value(current_font.name().c_str());
if (current_font.family())
{
auto family_node = font_node.append_child("family");
family_node.append_attribute("val").set_value(std::to_string(*current_font.family()).c_str());
}
if (current_font.scheme())
{
auto scheme_node = font_node.append_child("scheme");
scheme_node.append_attribute("val").set_value(current_font.scheme()->c_str());
}
}
}
// Fills
if (!stylesheet.fills.empty())
{
auto fills_node = stylesheet_node.append_child("fills");
write_fills(stylesheet.fills, fills_node);
const auto &fills = stylesheet.fills;
fills_node.append_attribute("count").set_value(std::to_string(fills.size()).c_str());
for (auto &fill_ : fills)
{
auto fill_node = fills_node.append_child("fill");
if (fill_.type() == xlnt::fill_type::pattern)
{
const auto &pattern = fill_.pattern_fill();
auto pattern_fill_node = fill_node.append_child("patternFill");
pattern_fill_node.append_attribute("patternType").set_value(to_string(pattern.type()).c_str());
if (pattern.foreground())
{
write_color(*pattern.foreground(), pattern_fill_node.append_child("fgColor"));
}
if (pattern.background())
{
write_color(*pattern.background(), pattern_fill_node.append_child("bgColor"));
}
}
else if (fill_.type() == xlnt::fill_type::gradient)
{
const auto &gradient = fill_.gradient_fill();
auto gradient_fill_node = fill_node.append_child("gradientFill");
auto gradient_fill_type_string = to_string(gradient.type());
gradient_fill_node.append_attribute("gradientType").set_value(gradient_fill_type_string.c_str());
if (gradient.degree() != 0)
{
gradient_fill_node.append_attribute("degree").set_value(gradient.degree());
}
if (gradient.left() != 0)
{
gradient_fill_node.append_attribute("left").set_value(gradient.left());
}
if (gradient.right() != 0)
{
gradient_fill_node.append_attribute("right").set_value(gradient.right());
}
if (gradient.top() != 0)
{
gradient_fill_node.append_attribute("top").set_value(gradient.top());
}
if (gradient.bottom() != 0)
{
gradient_fill_node.append_attribute("bottom").set_value(gradient.bottom());
}
for (const auto &stop : gradient.stops())
{
auto stop_node = gradient_fill_node.append_child("stop");
stop_node.append_attribute("position").set_value(stop.first);
write_color(stop.second, stop_node.append_child("color"));
}
}
}
}
// Borders
if (!stylesheet.borders.empty())
{
auto borders_node = stylesheet_node.append_child("borders");
write_borders(stylesheet.borders, borders_node);
const auto &borders = stylesheet.borders;
borders_node.append_attribute("count").set_value(std::to_string(borders.size()).c_str());
for (const auto &current_border : borders)
{
auto border_node = borders_node.append_child("border");
if (current_border.diagonal())
{
auto up = *current_border.diagonal() == diagonal_direction::both
|| *current_border.diagonal() == diagonal_direction::up;
border_node.append_attribute("diagonalUp").set_value(up ? "true" : "false");
auto down = *current_border.diagonal() == diagonal_direction::both
|| *current_border.diagonal() == diagonal_direction::down;
border_node.append_attribute("diagonalDown").set_value(down ? "true" : "false");
}
for (const auto &side : xlnt::border::all_sides())
{
if (current_border.side(side))
{
const auto current_side = *current_border.side(side);
auto side_name = to_string(side);
auto side_node = border_node.append_child(side_name.c_str());
if (current_side.style())
{
auto style_string = to_string(*current_side.style());
side_node.append_attribute("style").set_value(style_string.c_str());
}
if (current_side.color())
{
auto color_node = side_node.append_child("color");
write_color(*current_side.color(), color_node);
}
}
}
}
}
auto cell_style_xfs_node = stylesheet_node.append_child("cellStyleXfs");
// Formats & Styles
auto cell_style_xfs_node = stylesheet_node.append_child("cellStyleXfs");
auto cell_xfs_node = stylesheet_node.append_child("cellXfs");
write_formats(stylesheet, cell_xfs_node);
cell_xfs_node.append_attribute("count").set_value(std::to_string(stylesheet.formats.size()).c_str());
// Formats
for (auto &current_format : stylesheet.formats)
{
auto xf_node = cell_xfs_node.append_child("xf");
xf_node.append_attribute("numFmtId").set_value(std::to_string(current_format.number_format().get_id()).c_str());
auto font_id = std::distance(stylesheet.fonts.begin(), std::find(stylesheet.fonts.begin(), stylesheet.fonts.end(), current_format.font()));
xf_node.append_attribute("fontId").set_value(std::to_string(font_id).c_str());
auto fill_id = std::distance(stylesheet.fills.begin(), std::find(stylesheet.fills.begin(), stylesheet.fills.end(), current_format.fill()));
xf_node.append_attribute("fillId").set_value(std::to_string(fill_id).c_str());
auto border_id = std::distance(stylesheet.borders.begin(), std::find(stylesheet.borders.begin(), stylesheet.borders.end(), current_format.border()));
xf_node.append_attribute("borderId").set_value(std::to_string(border_id).c_str());
if (current_format.number_format_applied()) xf_node.append_attribute("applyNumberFormat").set_value(write_bool(true).c_str());
if (current_format.fill_applied()) xf_node.append_attribute("applyFill").set_value(write_bool(true).c_str());
if (current_format.font_applied()) xf_node.append_attribute("applyFont").set_value(write_bool(true).c_str());
if (current_format.border_applied()) xf_node.append_attribute("applyBorder").set_value(write_bool(true).c_str());
if (current_format.alignment_applied())
{
xf_node.append_attribute("applyAlignment").set_value(write_bool(true).c_str());
auto alignment_node = xf_node.append_child("alignment");
auto current_alignment = current_format.alignment();
if (current_alignment.vertical())
{
auto vertical = to_string(*current_alignment.vertical());
alignment_node.append_attribute("vertical").set_value(vertical.c_str());
}
if (current_alignment.horizontal())
{
auto horizontal = to_string(*current_alignment.horizontal());
alignment_node.append_attribute("horizontal").set_value(horizontal.c_str());
}
if (current_alignment.rotation())
{
alignment_node.append_attribute("textRotation").set_value(std::to_string(*current_alignment.rotation()).c_str());
}
if (current_alignment.wrap())
{
alignment_node.append_attribute("wrapText").set_value(*current_alignment.wrap() ? "true" : "false");
}
if (current_alignment.indent())
{
alignment_node.append_attribute("indent").set_value(std::to_string(*current_alignment.indent()).c_str());
}
if (current_alignment.shrink())
{
alignment_node.append_attribute("shrinkToFit").set_value(*current_alignment.shrink() ? "true" : "false");
}
}
if (current_format.protection_applied())
{
xf_node.append_attribute("applyProtection").set_value(write_bool(true).c_str());
auto protection_node = xf_node.append_child("protection");
auto current_protection = current_format.protection();
protection_node.append_attribute("locked").set_value(current_protection.locked() ? "true" : "false");
protection_node.append_attribute("hidden").set_value(current_protection.hidden() ? "true" : "false");
}
if (current_format.has_style())
{
auto style_iter = std::find_if(stylesheet.styles.begin(), stylesheet.styles.end(),
[&](const xlnt::style &s) { return s.name() == current_format.style().name(); });
auto style_index = std::distance(stylesheet.styles.begin(), style_iter);
xf_node.append_attribute("xfId").set_value(std::to_string(style_index).c_str());
}
}
// Styles
auto cell_styles_node = stylesheet_node.append_child("cellStyles");
::write_styles(stylesheet, cell_styles_node, cell_style_xfs_node);
cell_style_xfs_node.append_attribute("count").set_value(std::to_string(stylesheet.styles.size()).c_str());
cell_styles_node.append_attribute("count").set_value(std::to_string(stylesheet.styles.size()).c_str());
std::size_t style_index = 0;
for (auto &current_style : stylesheet.styles)
{
auto cell_style_node = cell_styles_node.append_child("cellStyle");
cell_style_node.append_attribute("name").set_value(current_style.name().c_str());
cell_style_node.append_attribute("xfId").set_value(std::to_string(style_index++).c_str());
if (current_style.builtin_id())
{
cell_style_node.append_attribute("builtinId").set_value(std::to_string(*current_style.builtin_id()).c_str());
}
if (current_style.hidden())
{
cell_style_node.append_attribute("hidden").set_value(write_bool(true).c_str());
}
if (current_style.custom())
{
cell_style_node.append_attribute("customBuiltin").set_value(write_bool(*current_style.custom()).c_str());
}
auto xf_node = cell_style_xfs_node.append_child("xf");
xf_node.append_attribute("numFmtId").set_value(std::to_string(current_style.number_format().get_id()).c_str());
auto font_id = std::distance(stylesheet.fonts.begin(), std::find(stylesheet.fonts.begin(), stylesheet.fonts.end(), current_style.font()));
xf_node.append_attribute("fontId").set_value(std::to_string(font_id).c_str());
auto fill_id = std::distance(stylesheet.fills.begin(), std::find(stylesheet.fills.begin(), stylesheet.fills.end(), current_style.fill()));
xf_node.append_attribute("fillId").set_value(std::to_string(fill_id).c_str());
auto border_id = std::distance(stylesheet.borders.begin(), std::find(stylesheet.borders.begin(), stylesheet.borders.end(), current_style.border()));
xf_node.append_attribute("borderId").set_value(std::to_string(border_id).c_str());
if (current_style.number_format_applied()) xf_node.append_attribute("applyNumberFormat").set_value(write_bool(true).c_str());
if (current_style.fill_applied()) xf_node.append_attribute("applyFill").set_value(write_bool(true).c_str());
if (current_style.font_applied()) xf_node.append_attribute("applyFont").set_value(write_bool(true).c_str());
if (current_style.border_applied()) xf_node.append_attribute("applyBorder").set_value(write_bool(true).c_str());
if (current_style.alignment_applied())
{
xf_node.append_attribute("applyAlignment").set_value(write_bool(true).c_str());
auto alignment_node = xf_node.append_child("alignment");
auto current_alignment = current_style.alignment();
if (current_alignment.vertical())
{
auto vertical = to_string(*current_alignment.vertical());
alignment_node.append_attribute("vertical").set_value(vertical.c_str());
}
if (current_alignment.horizontal())
{
auto horizontal = to_string(*current_alignment.horizontal());
alignment_node.append_attribute("horizontal").set_value(horizontal.c_str());
}
if (current_alignment.rotation())
{
alignment_node.append_attribute("textRotation").set_value(std::to_string(*current_alignment.rotation()).c_str());
}
if (current_alignment.wrap())
{
alignment_node.append_attribute("wrapText").set_value(write_bool(*current_alignment.wrap()).c_str());
}
if (current_alignment.indent())
{
alignment_node.append_attribute("indent").set_value(std::to_string(*current_alignment.indent()).c_str());
}
if (current_alignment.shrink())
{
alignment_node.append_attribute("shrinkToFit").set_value(write_bool(*current_alignment.shrink()).c_str());
}
}
if (current_style.protection_applied())
{
xf_node.append_attribute("applyProtection").set_value(write_bool(true).c_str());
auto protection_node = xf_node.append_child("protection");
auto current_protection = current_style.protection();
protection_node.append_attribute("locked").set_value(write_bool(current_protection.locked()).c_str());
protection_node.append_attribute("hidden").set_value(write_bool(current_protection.hidden()).c_str());
}
}
// Dxfs
auto dxfs_node = stylesheet_node.append_child("dxfs");
write_dxfs(dxfs_node);
// Table Styles
auto table_styles_node = stylesheet_node.append_child("tableStyles");
write_table_styles(table_styles_node);
// Colors
if (!stylesheet.colors.empty())
{
auto colors_node = stylesheet_node.append_child("colors");
write_colors(stylesheet.colors, colors_node);
}
// Ext Lst
auto ext_list_node = stylesheet_node.append_child("extLst");
auto ext_node = ext_list_node.append_child("ext");
ext_node.append_attribute("uri").set_value("{EB79DEF2-80B8-43e5-95BD-54CBDDF9020C}");
@ -1796,7 +1880,7 @@ void xlsx_producer::write_worksheet(const relationship &rel, pugi::xml_node root
if (cell.has_format())
{
cell_node.append_attribute("s").set_value(std::to_string(cell.get_format_id()).c_str());
cell_node.append_attribute("s").set_value(std::to_string(cell.get_format().id()).c_str());
}
}
}
@ -1954,5 +2038,15 @@ void xlsx_producer::write_thumbnail(const relationship &rel)
destination_.write_string(thumbnail_string, rel.get_target().get_path());
}
std::string xlsx_producer::write_bool(bool boolean) const
{
if (source_.d_->short_bools_)
{
return boolean ? "1" : "0";
}
return boolean ? "true" : "false";
}
} // namespace detail
} // namepsace xlnt

View File

@ -103,6 +103,15 @@ private:
void write_unknown_parts();
void write_unknown_relationships();
// Helpers
/// <summary>
/// Some XLSX producers write booleans as "true" or "false" while others use "1" and "0".
/// Both are valid, but we can use this method to write either depending on the producer
/// we're trying to match.
/// </summary>
std::string write_bool(bool boolean) const;
/// <summary>
/// A reference to the workbook which is the object of read/write operations.
/// </summary>

View File

@ -34,6 +34,7 @@ optional<bool> alignment::wrap() const
alignment &alignment::wrap(bool wrap_text)
{
wrap_text_ = wrap_text;
return *this;
}
optional<bool> alignment::shrink() const
@ -44,6 +45,7 @@ optional<bool> alignment::shrink() const
alignment &alignment::shrink(bool shrink_to_fit)
{
shrink_to_fit_ = shrink_to_fit;
return *this;
}
optional<horizontal_alignment> alignment::horizontal() const
@ -54,6 +56,7 @@ optional<horizontal_alignment> alignment::horizontal() const
alignment &alignment::horizontal(horizontal_alignment horizontal)
{
horizontal_ = horizontal;
return *this;
}
optional<vertical_alignment> alignment::vertical() const
@ -64,6 +67,29 @@ optional<vertical_alignment> alignment::vertical() const
alignment &alignment::vertical(vertical_alignment vertical)
{
vertical_ = vertical;
return *this;
}
alignment &alignment::indent(int value)
{
indent_ = value;
return *this;
}
optional<int> alignment::indent() const
{
return indent_;
}
alignment &alignment::rotation(bool value)
{
text_rotation_ = 0;
return *this;
}
optional<int> alignment::rotation() const
{
return text_rotation_;
}
std::string alignment::to_hash_string() const

View File

@ -25,203 +25,100 @@
namespace xlnt {
base_format::base_format()
: apply_alignment_(false),
apply_border_(false),
apply_fill_(false),
apply_font_(false),
apply_number_format_(false),
apply_protection_(false)
{
}
base_format::base_format(const base_format &other)
: alignment_(other.alignment_),
border_(other.border_),
fill_(other.fill_),
font_(other.font_),
number_format_(other.number_format_),
protection_(other.protection_),
apply_alignment_(other.apply_alignment_),
apply_border_(other.apply_border_),
apply_fill_(other.apply_fill_),
apply_font_(other.apply_font_),
apply_number_format_(other.apply_number_format_),
apply_protection_(other.apply_protection_)
{
}
base_format &base_format::operator=(const xlnt::base_format &other)
{
alignment_ = other.alignment_;
border_ = other.border_;
fill_ = other.fill_;
font_ = other.font_;
number_format_ = other.number_format_;
protection_ = other.protection_;
apply_alignment_ = other.apply_alignment_;
apply_border_ = other.apply_border_;
apply_fill_ = other.apply_fill_;
apply_font_ = other.apply_font_;
apply_number_format_ = other.apply_number_format_;
apply_protection_ = other.apply_protection_;
return *this;
}
alignment &base_format::get_alignment()
alignment &base_format::alignment()
{
return alignment_;
}
const alignment &base_format::get_alignment() const
const alignment &base_format::alignment() const
{
return alignment_;
}
void base_format::set_alignment(const xlnt::alignment &new_alignment)
void base_format::alignment(const xlnt::alignment &new_alignment, bool apply)
{
alignment_ = new_alignment;
alignment_applied(true);
apply_alignment_ = apply;
}
number_format &base_format::get_number_format()
number_format &base_format::number_format()
{
return number_format_;
}
const number_format &base_format::get_number_format() const
const number_format &base_format::number_format() const
{
return number_format_;
}
void base_format::set_number_format(const xlnt::number_format &new_number_format)
void base_format::number_format(const xlnt::number_format &new_number_format, bool apply)
{
number_format_ = new_number_format;
number_format_applied(true);
apply_number_format_ = apply;
}
border &base_format::get_border()
border &base_format::border()
{
return border_;
}
const border &base_format::get_border() const
const border &base_format::border() const
{
return border_;
}
void base_format::set_border(const xlnt::border &new_border)
void base_format::border(const xlnt::border &new_border, bool apply)
{
border_ = new_border;
border_applied(true);
apply_border_ = apply;
}
fill &base_format::get_fill()
fill &base_format::fill()
{
return fill_;
}
const fill &base_format::get_fill() const
const fill &base_format::fill() const
{
return fill_;
}
void base_format::set_fill(const xlnt::fill &new_fill)
void base_format::fill(const xlnt::fill &new_fill, bool apply)
{
fill_ = new_fill;
fill_applied(true);
apply_fill_ = apply;
}
font &base_format::get_font()
font &base_format::font()
{
return font_;
}
const font &base_format::get_font() const
const font &base_format::font() const
{
return font_;
}
void base_format::set_font(const xlnt::font &new_font)
void base_format::font(const xlnt::font &new_font, bool apply)
{
font_ = new_font;
font_applied(true);
apply_font_ = apply;
}
protection &base_format::get_protection()
protection &base_format::protection()
{
return protection_;
}
const protection &base_format::get_protection() const
const protection &base_format::protection() const
{
return protection_;
}
void base_format::set_protection(const xlnt::protection &new_protection)
void base_format::protection(const xlnt::protection &new_protection, bool apply)
{
if (!new_protection.get_locked() || new_protection.get_hidden())
{
protection_ = new_protection;
protection_applied(true);
}
}
std::string base_format::to_hash_string() const
{
std::string hash_string("base_format:");
hash_string.append(std::to_string(alignment_applied()));
hash_string.append(alignment_applied() ? std::to_string(alignment_.hash()) : ":");
hash_string.append(std::to_string(border_applied()));
hash_string.append(border_applied() ? std::to_string(border_.hash()) : ":");
hash_string.append(std::to_string(font_applied()));
hash_string.append(font_applied() ? std::to_string(font_.hash()) : ":");
hash_string.append(std::to_string(fill_applied()));
hash_string.append(fill_applied() ? std::to_string(fill_.hash()) : ":");
hash_string.append(std::to_string(number_format_applied()));
hash_string.append(std::to_string(number_format_.hash()));
hash_string.append(std::to_string(protection_applied()));
hash_string.append(protection_applied() ? std::to_string(protection_.hash()) : ":");
return hash_string;
}
void base_format::alignment_applied(bool applied)
{
apply_alignment_ = applied;
}
void base_format::border_applied(bool applied)
{
apply_border_ = applied;
}
void base_format::fill_applied(bool applied)
{
apply_fill_ = applied;
}
void base_format::font_applied(bool applied)
{
apply_font_ = applied;
}
void base_format::number_format_applied(bool applied)
{
apply_number_format_ = applied;
}
void base_format::protection_applied(bool applied)
{
apply_protection_ = applied;
protection_ = new_protection;
apply_protection_ = apply;
}
bool base_format::alignment_applied() const

View File

@ -74,6 +74,13 @@ optional<border::border_property> border::side(border_side s) const
switch (s)
{
case border_side::bottom: return bottom_;
case border_side::top: return top_;
case border_side::start: return start_;
case border_side::end: return end_;
case border_side::vertical: return vertical_;
case border_side::horizontal: return horizontal_;
default:
case border_side::diagonal: return diagonal_;
}
}
@ -81,8 +88,28 @@ border &border::side(border_side s, const border_property &prop)
{
switch (s)
{
case border_side::bottom: bottom_ = prop;
case border_side::bottom: bottom_ = prop; break;
case border_side::top: top_ = prop; break;
case border_side::start: start_ = prop; break;
case border_side::end: end_ = prop; break;
case border_side::vertical: vertical_ = prop; break;
case border_side::horizontal: horizontal_ = prop; break;
default:
case border_side::diagonal: diagonal_ = prop; break;
}
return *this;
}
border &border::diagonal(diagonal_direction direction)
{
diagonal_direction_ = direction;
return *this;
}
optional<diagonal_direction> border::diagonal() const
{
return diagonal_direction_;
}
std::string border::to_hash_string() const

View File

@ -42,6 +42,7 @@ font::font()
font &font::bold(bool bold)
{
bold_ = bold;
return *this;
}
bool font::bold() const
@ -52,6 +53,7 @@ bool font::bold() const
font &font::italic(bool italic)
{
italic_ = italic;
return *this;
}
bool font::italic() const
@ -62,6 +64,7 @@ bool font::italic() const
font &font::strikethrough(bool strikethrough)
{
strikethrough_ = strikethrough;
return *this;
}
bool font::strikethrough() const
@ -72,6 +75,7 @@ bool font::strikethrough() const
font &font::underline(underline_style new_underline)
{
underline_ = new_underline;
return *this;
}
bool font::underlined() const
@ -87,6 +91,7 @@ font::underline_style font::underline() const
font &font::size(std::size_t size)
{
size_ = size;
return *this;
}
std::size_t font::size() const
@ -97,6 +102,7 @@ std::size_t font::size() const
font &font::name(const std::string &name)
{
name_ = name;
return *this;
}
std::string font::name() const
{
@ -106,16 +112,19 @@ std::string font::name() const
font &font::color(const xlnt::color &c)
{
color_ = c;
return *this;
}
font &font::family(std::size_t family)
{
family_ = family;
return *this;
}
font &font::scheme(const std::string &scheme)
{
scheme_ = scheme;
return *this;
}
optional<color> font::color() const

View File

@ -22,15 +22,77 @@
// @license: http://www.opensource.org/licenses/mit-license.php
// @author: see AUTHORS file
#include <xlnt/styles/format.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>
#include <detail/format_impl.hpp>
#include <detail/stylesheet.hpp>
#include <xlnt/styles/format.hpp>
#include <xlnt/styles/style.hpp>
namespace xlnt {
format::format(detail::format_impl *d) : d_(d)
{
}
std::size_t format::id() const
{
return d_->id;
}
void format::style(const xlnt::style &new_style)
{
d_->style = new_style.name();
}
void format::style(const std::string &new_style)
{
for (auto &style : d_->parent->styles)
{
if (style.name() == new_style)
{
d_->style = new_style;
return;
}
}
throw key_not_found();
}
bool format::has_style() const
{
return d_->style;
}
const style &format::style() const
{
if (!has_style())
{
throw invalid_attribute();
}
return d_->parent->get_style(*d_->style);
}
xlnt::number_format &format::number_format()
{
return base_format::number_format();
}
const xlnt::number_format &format::number_format() const
{
return base_format::number_format();
}
void format::number_format(const xlnt::number_format &new_number_format, bool applied)
{
auto copy = new_number_format;
if (!copy.has_id())
{
copy.set_id(d_->parent->next_custom_number_format_id());
d_->parent->number_formats.push_back(copy);
}
base_format::number_format(copy, applied);
}
} // namespace xlnt

View File

@ -61,7 +61,14 @@ const std::unordered_map<std::size_t, std::string> &builtin_formats()
{ 37, "#,##0 ;(#,##0)" },
{ 38, "#,##0 ;[Red](#,##0)" },
{ 39, "#,##0.00;(#,##0.00)" },
{ 40, "#,##0.00;[Red](#,##0.00)" },
{ 40, "#,##0.00;[Red](#,##0.00)" },
// 41-44 aren't in the ECMA 376 v4 standard, but Libre Office uses them
{ 41, "_(* #,##0_);_(* \\(#,##0\\);_(* \"-\"_);_(@_)" },
{ 42, "_(\"$\"* #,##0_);_(\"$\"* \\(#,##0\\);_(\"$\"* \"-\"_);_(@_)" },
{ 43, "_(* #,##0.00_);_(* \\(#,##0.00\\);_(* \"-\"??_);_(@_)" },
{ 44, "_(\"$\"* #,##0.00_)_(\"$\"* \\(#,##0.00\\)_(\"$\"* \"-\"??_)_(@_)" },
{ 45, "mm:ss" },
{ 46, "[h]:mm:ss" },
{ 47, "mmss.0" },

View File

@ -26,6 +26,10 @@
namespace xlnt {
protection::protection() : locked_(false), hidden_(false)
{
}
bool protection::locked() const
{
return locked_;
@ -34,6 +38,7 @@ bool protection::locked() const
protection &protection::locked(bool locked)
{
locked_ = locked;
return *this;
}
bool protection::hidden() const
@ -44,6 +49,7 @@ bool protection::hidden() const
protection &protection::hidden(bool hidden)
{
hidden_ = hidden;
return *this;
}
std::string protection::to_hash_string() const

View File

@ -33,6 +33,10 @@
namespace xlnt {
style::style(detail::style_impl *d) : d_(d)
{
}
bool style::hidden() const
{
return d_->hidden_style;
@ -41,16 +45,18 @@ bool style::hidden() const
style &style::hidden(bool value)
{
d_->hidden_style = value;
return *this;
}
std::size_t style::built_in_id() const
optional<std::size_t> style::builtin_id() const
{
return d_->built_in_style_id;
return d_->builtin_id;
}
style &style::built_in_id(std::size_t builtin_id)
style &style::builtin_id(std::size_t builtin_id)
{
d_->built_in_style_id = builtin_id;
d_->builtin_id = builtin_id;
return *this;
}
std::string style::name() const
@ -61,6 +67,23 @@ std::string style::name() const
style &style::name(const std::string &name)
{
d_->name = name;
return *this;
}
optional<bool> style::custom() const
{
return d_->custom_builtin;
}
style &style::custom(bool value)
{
d_->custom_builtin = value;
return *this;
}
bool style::operator==(const style &other)
{
return d_ == other.d_;
}
} // namespace xlnt

View File

@ -12,22 +12,11 @@ public:
{
xlnt::alignment alignment;
TS_ASSERT(alignment.has_horizontal());
TS_ASSERT_EQUALS(alignment.get_horizontal(), xlnt::horizontal_alignment::general);
alignment.set_horizontal(xlnt::horizontal_alignment::none);
TS_ASSERT(!alignment.has_horizontal());
TS_ASSERT(alignment.has_vertical());
TS_ASSERT_EQUALS(alignment.get_vertical(), xlnt::vertical_alignment::bottom);
alignment.set_vertical(xlnt::vertical_alignment::none);
TS_ASSERT(!alignment.has_vertical());
TS_ASSERT(!alignment.get_shrink_to_fit());
alignment.set_shrink_to_fit(true);
TS_ASSERT(alignment.get_shrink_to_fit());
TS_ASSERT(!alignment.get_wrap_text());
alignment.set_wrap_text(true);
TS_ASSERT(alignment.get_wrap_text());
TS_ASSERT(alignment.horizontal());
TS_ASSERT_EQUALS(*alignment.horizontal(), xlnt::horizontal_alignment::general);
TS_ASSERT(alignment.vertical());
TS_ASSERT_EQUALS(*alignment.vertical(), xlnt::vertical_alignment::bottom);
TS_ASSERT(!alignment.shrink());
TS_ASSERT(!alignment.wrap());
}
};

View File

@ -41,4 +41,85 @@ public:
xlnt::workbook wb = xlnt::workbook::empty_libre_office();
TS_ASSERT(workbook_matches_file(wb, path_helper::get_data_directory("10_default-libre-office.xlsx")));
}
void test_produce_simple_excel()
{
xlnt::workbook wb = xlnt::workbook::empty_excel();
auto ws = wb.get_active_sheet();
auto bold_font = xlnt::font().bold(true);
ws.get_cell("A1").set_value("Type");
ws.get_cell("A1").set_font(bold_font);
ws.get_cell("B1").set_value("Value");
ws.get_cell("B1").set_font(bold_font);
ws.get_cell("A2").set_value("null");
ws.get_cell("B2").set_value(nullptr);
ws.get_cell("A3").set_value("bool (true)");
ws.get_cell("B3").set_value(true);
ws.get_cell("A4").set_value("bool (false)");
ws.get_cell("B4").set_value(false);
ws.get_cell("A5").set_value("number (std::int8_t)");
ws.get_cell("B5").set_value(std::numeric_limits<std::int8_t>::max());
ws.get_cell("A6").set_value("number (std::uint8_t)");
ws.get_cell("B6").set_value(std::numeric_limits<std::uint8_t>::max());
ws.get_cell("A7").set_value("number (std::uint16_t)");
ws.get_cell("B7").set_value(std::numeric_limits<std::int16_t>::max());
ws.get_cell("A8").set_value("number (std::uint16_t)");
ws.get_cell("B8").set_value(std::numeric_limits<std::uint16_t>::max());
ws.get_cell("A9").set_value("number (std::uint32_t)");
ws.get_cell("B9").set_value(std::numeric_limits<std::int32_t>::max());
ws.get_cell("A10").set_value("number (std::uint32_t)");
ws.get_cell("B10").set_value(std::numeric_limits<std::uint32_t>::max());
ws.get_cell("A11").set_value("number (std::uint64_t)");
ws.get_cell("B11").set_value(std::numeric_limits<std::int64_t>::max());
ws.get_cell("A12").set_value("number (std::uint64_t)");
ws.get_cell("B12").set_value(std::numeric_limits<std::uint64_t>::max());
ws.get_cell("A13").set_value("number (std::size_t)");
ws.get_cell("B13").set_value(std::numeric_limits<std::size_t>::max());
ws.get_cell("A14").set_value("number (float)");
ws.get_cell("B14").set_value(std::numeric_limits<float>::max());
ws.get_cell("A15").set_value("number (double)");
ws.get_cell("B15").set_value(std::numeric_limits<double>::max());
ws.get_cell("A16").set_value("number (long double)");
ws.get_cell("B16").set_value(std::numeric_limits<long double>::max());
ws.get_cell("A17").set_value("text (char *)");
ws.get_cell("B17").set_value("string");
ws.get_cell("A18").set_value("text (std::string)");
ws.get_cell("B18").set_value(std::string("string"));
ws.get_cell("A19").set_value("date");
ws.get_cell("B19").set_value(xlnt::date(2016, 2, 3));
ws.get_cell("A20").set_value("time");
ws.get_cell("B20").set_value(xlnt::time(1, 2, 3, 4));
ws.get_cell("A21").set_value("datetime");
ws.get_cell("B21").set_value(xlnt::datetime(2016, 2, 3, 1, 2, 3, 4));
ws.get_cell("A22").set_value("timedelta");
ws.get_cell("B22").set_value(xlnt::timedelta(1, 2, 3, 4, 5));
ws.freeze_panes("B2");
wb.save("simple.xlsx");
}
};

View File

@ -253,10 +253,10 @@ public:
TS_ASSERT(wb.get_active_sheet().get_cell("B2").has_style());
wb.clear_styles();
TS_ASSERT(!wb.get_active_sheet().get_cell("B2").has_style());
xlnt::format format;
xlnt::format format = wb.create_format();
xlnt::font font;
font.set_size(41);
format.set_font(font);
font.size(41);
format.font(font, true);
wb.get_active_sheet().get_cell("B2").set_format(format);
TS_ASSERT(wb.get_active_sheet().get_cell("B2").has_format());
wb.clear_formats();
@ -282,6 +282,5 @@ public:
wb.create_style("style1");
wb.get_style("style1");
wb_const.get_style("style1");
wb.get_style_by_id(0);
}
};

View File

@ -139,12 +139,30 @@ workbook workbook::empty_excel()
ws.d_->has_format_properties_ = true;
ws.d_->has_view_ = true;
wb.create_format();
wb.create_style("Normal");
wb.set_theme(theme());
wb.d_->stylesheet_.fills.push_back(pattern_fill().type(pattern_fill_type::none));
wb.d_->stylesheet_.fills.push_back(pattern_fill().type(pattern_fill_type::gray125));
auto default_font = font().name("Calibri").size(12).scheme("minor").family(2).color(theme_color(1));
wb.d_->stylesheet_.fonts.push_back(default_font);
auto default_border = border().side(border_side::bottom, border::border_property())
.side(border_side::top, border::border_property())
.side(border_side::start, border::border_property())
.side(border_side::end, border::border_property())
.side(border_side::diagonal, border::border_property());
wb.d_->stylesheet_.borders.push_back(default_border);
auto &normal_style = wb.create_style("Normal").builtin_id(0);
normal_style.font(default_font, false);
normal_style.border(default_border, false);
auto &default_format = wb.create_format();
default_format.font(default_font, false);
default_format.border(default_border, false);
default_format.style("Normal");
wb.set_theme(theme());
return wb;
}
@ -182,60 +200,123 @@ workbook workbook::empty_libre_office()
relationship::type::worksheet, uri("worksheets/sheet1.xml"), target_mode::internal);
wb.d_->sheet_title_rel_id_map_[title] = ws_rel;
wb.d_->stylesheet_.number_formats.push_back(xlnt::number_format("General", 164));
wb.d_->stylesheet_.fonts.push_back(xlnt::font().size(10).name("Arial").family(2));
wb.d_->stylesheet_.fonts.push_back(xlnt::font().size(10).name("Arial").family(0));
wb.d_->stylesheet_.fills.push_back(xlnt::pattern_fill().type(pattern_fill_type::none));
wb.d_->stylesheet_.fills.push_back(xlnt::pattern_fill().type(pattern_fill_type::gray125));
wb.d_->stylesheet_.borders.push_back(xlnt::border().diagonal(xlnt::diagonal_direction::neither));
auto ws = wb.get_sheet_by_index(0);
ws.d_->has_format_properties_ = true;
ws.d_->has_view_ = true;
ws.d_->has_dimension_ = true;
page_margins margins;
margins.set_left(0.7875);
margins.set_right(0.7875);
margins.set_top(1.05277777777778);
margins.set_bottom(1.05277777777778);
margins.set_header(0.7875);
margins.set_footer(0.7875);
ws.set_page_margins(margins);
ws.set_page_setup(page_setup());
ws.get_header_footer().get_center_header().set_font_name("&C&\"Times New Roman\"&12&A");
ws.get_header_footer().get_center_footer().set_font_name("&C&\"Times New Roman\"&12Page &B");
ws.add_column_properties(1, column_properties());
auto alignment = xlnt::alignment()
auto default_alignment = xlnt::alignment()
.horizontal(horizontal_alignment::general)
.vertical(vertical_alignment::bottom)
.rotation(0)
.wrap(false)
.indent(0)
.shrink(false);
wb.d_->stylesheet_.alignments.push_back(default_alignment);
auto protection = xlnt::protection()
auto default_border = border().side(border_side::bottom, border::border_property())
.side(border_side::top, border::border_property())
.side(border_side::start, border::border_property())
.side(border_side::end, border::border_property())
.side(border_side::diagonal, border::border_property())
.diagonal(diagonal_direction::neither);
wb.d_->stylesheet_.borders.push_back(default_border);
auto default_fill = xlnt::fill(xlnt::pattern_fill().type(pattern_fill_type::none));
wb.d_->stylesheet_.fills.push_back(default_fill);
auto gray125_fill = xlnt::fill(xlnt::pattern_fill().type(pattern_fill_type::gray125));
wb.d_->stylesheet_.fills.push_back(gray125_fill);
auto default_font = font().name("Arial").size(10).family(2);
wb.d_->stylesheet_.fonts.push_back(default_font);
auto second_font = font().name("Arial").size(10).family(0);
wb.d_->stylesheet_.fonts.push_back(second_font);
auto default_number_format = xlnt::number_format();
default_number_format.set_format_string("General");
default_number_format.set_id(164);
wb.d_->stylesheet_.number_formats.push_back(default_number_format);
auto default_protection = xlnt::protection()
.locked(true)
.hidden(false);
wb.d_->stylesheet_.protections.push_back(default_protection);
wb.create_style("Normal").built_in_id(0).custom(false);
wb.create_style("Comma").built_in_id(0).custom(false);
wb.create_style("Comma [0]").built_in_id(0).custom(false);
wb.create_style("Currency").built_in_id(0).custom(false);
wb.create_style("Currency [0]").built_in_id(0).custom(false);
wb.create_style("Percent").built_in_id(0).custom(false);
auto &normal_style = wb.create_style("Normal").builtin_id(0).custom(false);
normal_style.alignment(default_alignment, false);
normal_style.border(default_border, true);
normal_style.fill(default_fill, true);
normal_style.font(default_font, true);
normal_style.number_format(default_number_format, false);
normal_style.protection(default_protection, false);
/*
wb.d_->stylesheet_.styles.push_back(xlnt::style().name("Normal")
.builtin_id(0).custom(false).number_format_id(164)
.font_id(0).fill_id(0).border_id(0).font_applied(true)
.border_applied(true).alignment(alignment).protection(protection));
wb.d_->stylesheet_.styles.push_back(xlnt::style().name("Comma")
.builtin_id(3).custom(false).number_format_id(164)
.number_format_id(43).font_id(1).fill_id(0).border_id(0).font_applied(true));
wb.d_->stylesheet_.styles.push_back(xlnt::style().name("Comma [0]")
.builtin_id(6).custom(false).number_format_id(164)
.number_format_id(41).font_id(1).fill_id(0).border_id(0).font_applied(true));
wb.d_->stylesheet_.styles.push_back(xlnt::style().name("Currency")
.builtin_id(4).custom(false).number_format_id(164)
.number_format_id(44).font_id(1).fill_id(0).border_id(0).font_applied(true));
wb.d_->stylesheet_.styles.push_back(xlnt::style().name("Currency[0]")
.builtin_id(7).custom(false).number_format_id(164)
.number_format_id(42).font_id(1).fill_id(0).border_id(0).font_applied(true));
wb.d_->stylesheet_.styles.push_back(xlnt::style().name("Percent")
.builtin_id(5).custom(false).number_format_id(164)
.number_format_id(9).font_id(1).fill_id(0).border_id(0).font_applied(true));
*/
auto &comma_style = wb.create_style("Comma").builtin_id(3).custom(false);
comma_style.alignment(default_alignment, false);
comma_style.border(default_border, true);
comma_style.fill(default_fill, true);
comma_style.font(second_font, true);
comma_style.number_format(number_format::from_builtin_id(43), false);
comma_style.protection(default_protection, false);
auto &comma0_style = wb.create_style("Comma [0]").builtin_id(6).custom(false);
comma0_style.alignment(default_alignment, false);
comma0_style.border(default_border, true);
comma0_style.fill(default_fill, true);
comma0_style.font(second_font, true);
comma0_style.number_format(number_format::from_builtin_id(41), false);
comma0_style.protection(default_protection, false);
auto &currency_style = wb.create_style("Currency").builtin_id(4).custom(false);
currency_style.alignment(default_alignment, false);
currency_style.border(default_border, true);
currency_style.fill(default_fill, true);
currency_style.font(second_font, true);
currency_style.number_format(number_format::from_builtin_id(44), false);
currency_style.protection(default_protection, false);
auto &currency0_style = wb.create_style("Currency [0]").builtin_id(7).custom(false);
currency0_style.alignment(default_alignment, false);
currency0_style.border(default_border, true);
currency0_style.fill(default_fill, true);
currency0_style.font(second_font, true);
currency0_style.number_format(number_format::from_builtin_id(42), false);
currency0_style.protection(default_protection, false);
auto &percent_style = wb.create_style("Percent").builtin_id(5).custom(false);
percent_style.alignment(default_alignment, false);
percent_style.border(default_border, true);
percent_style.fill(default_fill, false);
percent_style.font(second_font, true);
percent_style.number_format(number_format::percentage(), false);
percent_style.protection(default_protection, false);
auto &format = wb.create_format();
format.set_number_format(number_format("General", 164));
format.set_alignment(alignment);
format.set_protection(protection);
format.set_style("Normal");
format.number_format(default_number_format, true);
format.alignment(default_alignment, true);
format.protection(default_protection, true);
format.style("Normal");
wb.d_->has_file_version_ = true;
wb.d_->file_version_.app_name = "Calc";
wb.d_->has_properties_ = true;
wb.d_->has_view_ = true;
wb.d_->has_calculation_properties_ = true;
wb.d_->application_ = "LibreOffice/5.1.4.2$Windows_x86 LibreOffice_project/f99d75f39f1c57ebdd7ffc5f42867c12031db97a";
wb.d_->short_bools_ = false;
return wb;
}

View File

@ -346,7 +346,7 @@ cell worksheet::get_cell(const cell_reference &reference)
if (row.find(reference.get_column_index()) == row.end())
{
auto impl = row[reference.get_column_index()] = detail::cell_impl();
auto &impl = row[reference.get_column_index()] = detail::cell_impl();
impl.parent_ = d_;
impl.column_ = reference.get_column_index();
impl.row_ = reference.get_row();