almost done finally. still need to figure out the interaction between styles and named styles, maybe improve naming

This commit is contained in:
Thomas Fussell 2016-05-03 15:37:34 -04:00
parent 198483c88e
commit 713bd1ea12
12 changed files with 238 additions and 84 deletions

View File

@ -28,6 +28,7 @@
#include <vector>
#include <xlnt/xlnt_config.hpp>
#include <xlnt/styles/named_style.hpp>
#include <xlnt/workbook/workbook.hpp>
namespace xlnt {
@ -256,6 +257,16 @@ public:
bool write_ext_list(xml_node &ext_list_node) const;
const std::vector<border> &get_borders() const;
const std::vector<fill> &get_fills() const;
const std::vector<font> &get_fonts() const;
const std::vector<number_format> &get_number_formats() const;
const std::vector<color> &get_colors() const;
private:
void initialize_vectors();
@ -270,7 +281,7 @@ private:
std::vector<font> fonts_;
std::vector<number_format> number_formats_;
std::vector<cell_style> cell_styles_;
std::vector<named_style> named_styles_;
std::unordered_map<std::size_t, named_style> named_styles_;
};
} // namespace xlnt

View File

@ -83,6 +83,8 @@ public:
workbook &operator=(workbook other);
workbook(workbook &&other);
workbook(const workbook &other);
~workbook();
friend void swap(workbook &left, workbook &right);
@ -190,6 +192,7 @@ public:
named_style &get_named_style(const std::string &name);
const named_style &get_named_style(const std::string &name) const;
named_style &create_named_style(const std::string &name);
const std::vector<named_style> &get_named_styles() const;
manifest &get_manifest();
const manifest &get_manifest() const;

View File

@ -358,87 +358,90 @@ public:
void test_font()
{
auto ws = wb.create_sheet();
auto cell = ws.get_cell("A1");
xlnt::font font;
font.set_bold(true);
auto ws = wb.create_sheet();
auto cell = xlnt::cell(ws, "A1");
cell.set_font(font);
TS_ASSERT(cell.has_style());
TS_ASSERT(cell.get_font().apply());
TS_ASSERT_EQUALS(cell.get_font(), font);
}
void test_fill()
{
auto ws = wb.create_sheet();
auto cell = ws.get_cell("A1");
xlnt::fill f;
f.set_pattern_type(xlnt::fill::pattern_type::solid);
f.set_foreground_color(xlnt::color(xlnt::color::type::rgb, "FF0000"));
auto ws = wb.create_sheet();
xlnt::cell cell(ws, "A1");
cell.set_fill(f);
TS_ASSERT(cell.get_fill() == f);
TS_ASSERT(cell.has_style());
TS_ASSERT(cell.get_fill().apply());
TS_ASSERT_EQUALS(cell.get_fill(), f);
}
void test_border()
{
xlnt::border border;
auto ws = wb.create_sheet();
auto cell = ws.get_cell("A1");
auto cell = ws.get_cell(xlnt::cell_reference(1, 1));
xlnt::border border;
cell.set_border(border);
TS_ASSERT(cell.get_border() == border);
TS_ASSERT(cell.has_style());
TS_ASSERT(cell.get_border().apply());
TS_ASSERT_EQUALS(cell.get_border(), border);
}
void test_number_format()
{
auto ws = wb.create_sheet();
ws.get_parent().add_number_format(xlnt::number_format("dd--hh--mm"));
auto cell = ws.get_cell("A1");
xlnt::number_format format("dd--hh--mm");
xlnt::cell cell(ws, "A1");
cell.set_number_format(xlnt::number_format("dd--hh--mm"));
TS_ASSERT(cell.get_number_format().get_format_string() == "dd--hh--mm");
cell.set_number_format(format);
TS_ASSERT(cell.has_style());
TS_ASSERT(cell.get_number_format().apply());
TS_ASSERT_EQUALS(cell.get_number_format().get_format_string(), "dd--hh--mm");
}
void test_alignment()
{
auto ws = wb.create_sheet();
auto cell = ws.get_cell("A1");
xlnt::alignment align;
align.set_wrap_text(true);
auto ws = wb.create_sheet();
xlnt::cell cell(ws, "A1");
cell.set_alignment(align);
TS_ASSERT(cell.get_alignment() == align);
TS_ASSERT(cell.has_style());
TS_ASSERT(cell.get_alignment().apply());
TS_ASSERT_EQUALS(cell.get_alignment(), align);
}
void test_protection()
{
auto ws = wb.create_sheet();
auto cell = ws.get_cell("A1");
xlnt::protection prot;
prot.set_locked(xlnt::protection::type::protected_);
auto ws = wb.create_sheet();
xlnt::cell cell(ws, "A1");
cell.set_protection(prot);
TS_ASSERT(cell.get_protection() == prot);
}
void test_pivot_button()
{
auto ws = wb.create_sheet();
xlnt::cell cell(ws, "A1");
cell.set_pivot_button(true);
TS_ASSERT(cell.pivot_button());
}
void test_quote_prefix()
{
auto ws = wb.create_sheet();
xlnt::cell cell(ws, "A1");
cell.set_quote_prefix(true);
TS_ASSERT(cell.quote_prefix());
TS_ASSERT(cell.has_style());
TS_ASSERT(cell.get_protection().apply());
TS_ASSERT_EQUALS(cell.get_protection(), prot);
}
};

View File

@ -37,7 +37,6 @@ struct workbook_impl
worksheets_(other.worksheets_),
relationships_(other.relationships_),
root_relationships_(other.root_relationships_),
drawings_(other.drawings_),
shared_strings_(other.shared_strings_),
properties_(other.properties_),
app_properties_(other.app_properties_),
@ -60,8 +59,6 @@ struct workbook_impl
root_relationships_.clear();
std::copy(other.root_relationships_.begin(), other.root_relationships_.end(),
std::back_inserter(root_relationships_));
drawings_.clear();
std::copy(other.drawings_.begin(), other.drawings_.end(), back_inserter(drawings_));
shared_strings_.clear();
std::copy(other.shared_strings_.begin(), other.shared_strings_.end(), std::back_inserter(shared_strings_));
properties_ = other.properties_;
@ -78,7 +75,6 @@ struct workbook_impl
std::vector<worksheet_impl> worksheets_;
std::vector<relationship> relationships_;
std::vector<relationship> root_relationships_;
std::vector<drawing> drawings_;
std::vector<std::string> shared_strings_;
document_properties properties_;

View File

@ -346,13 +346,20 @@ named_style style_serializer::read_named_style(const xml_node &named_style_node,
auto base_style_node = style_parent_node.get_children().at(base_style_id);
auto base_style = read_cell_style(base_style_node);
//TODO shouldn't have to set apply after set_X()
s.set_alignment(base_style.get_alignment());
s.get_alignment().apply(base_style.get_alignment().apply());
s.set_border(base_style.get_border());
s.get_border().apply(base_style.get_border().apply());
s.set_fill(base_style.get_fill());
s.get_fill().apply(base_style.get_fill().apply());
s.set_font(base_style.get_font());
s.get_font().apply(base_style.get_font().apply());
s.set_number_format(base_style.get_number_format());
s.get_number_format().apply(base_style.get_number_format().apply());
s.set_protection(base_style.get_protection());
s.get_protection().apply(base_style.get_protection().apply());
return s;
}
@ -368,6 +375,16 @@ bool style_serializer::read_stylesheet(const xml_document &xml)
read_named_styles(stylesheet_node.get_child("cellStyles"), stylesheet_node.get_child("cellStyleXfs"));
read_cell_styles(stylesheet_node.get_child("cellXfs"));
for (const auto &ns : named_styles_)
{
workbook_.create_named_style(ns.second.get_name()) = ns.second;
}
for (const auto &s : cell_styles_)
{
workbook_.add_style(s);
}
return true;
}
@ -386,7 +403,24 @@ bool style_serializer::read_cell_styles(const xlnt::xml_node &cell_styles_node)
{
auto named_style_index = std::stoull(style_node.get_attribute("xfId"));
auto named_style = named_styles_.at(named_style_index);
style.set_named_style(named_style.get_name());
}
cell_styles_.push_back(style);
}
return true;
}
bool style_serializer::read_named_styles(const xlnt::xml_node &named_styles_node, const xlnt::xml_node &cell_styles_node)
{
for (auto named_style_node : named_styles_node.get_children())
{
auto ns = read_named_style(named_style_node, cell_styles_node);
auto named_style_index = std::stoull(named_style_node.get_attribute("xfId"));
named_styles_[named_style_index] = ns;
}
return true;
@ -1115,23 +1149,23 @@ bool style_serializer::write_named_styles(xml_node &cell_styles_node, xml_node &
{
styles_node.add_attribute("count", std::to_string(named_styles_.size()));
for(auto &style : named_styles_)
for(auto &key_style : named_styles_)
{
auto xf_node = styles_node.add_child("xf");
write_named_style(style, xf_node);
write_named_style(key_style.second, xf_node);
}
cell_styles_node.add_attribute("count", std::to_string(named_styles_.size()));
for(auto &style : named_styles_)
for(auto &key_style : named_styles_)
{
auto cell_style_node = cell_styles_node.add_child("cellStyle");
cell_style_node.add_attribute("name", style.get_name());
// cell_style_node.add_attribute("xfId", std::to_string(style.get_format_id()));
cell_style_node.add_attribute("builtinId", std::to_string(style.get_builtin_id()));
cell_style_node.add_attribute("name", key_style.second.get_name());
cell_style_node.add_attribute("xfId", std::to_string(key_style.first));
cell_style_node.add_attribute("builtinId", std::to_string(key_style.second.get_builtin_id()));
if (style.get_hidden())
if (key_style.second.get_hidden())
{
cell_style_node.add_attribute("hidden", "1");
}
@ -1253,9 +1287,29 @@ bool style_serializer::write_number_formats(xml_node &number_formats_node) const
return true;
}
bool style_serializer::read_named_styles(const xlnt::xml_node &named_styles_node, const xlnt::xml_node &cell_styles_node)
const std::vector<border> &style_serializer::get_borders() const
{
return false;
return borders_;
}
const std::vector<fill> &style_serializer::get_fills() const
{
return fills_;
}
const std::vector<font> &style_serializer::get_fonts() const
{
return fonts_;
}
const std::vector<number_format> &style_serializer::get_number_formats() const
{
return number_formats_;
}
const std::vector<color> &style_serializer::get_colors() const
{
return colors_;
}
} // namespace xlnt

View File

@ -11,10 +11,11 @@ public:
void test_write_number_formats()
{
xlnt::workbook wb;
wb.add_number_format(xlnt::number_format("YYYY"));
wb.get_active_sheet().get_cell("A1").set_number_format(xlnt::number_format("YYYY"));
xlnt::style_serializer writer(wb);
xlnt::xml_document observed;
writer.write_number_formats(observed.add_child("numFmts"));
auto num_fmts_node = observed.add_child("numFmts");
writer.write_number_formats(num_fmts_node);
std::string expected =
" <numFmts count=\"1\">"
" <numFmt formatCode=\"YYYY\" numFmtId=\"164\"></numFmt>"

View File

@ -56,27 +56,24 @@ cell_style &cell_style::operator=(const cell_style &other)
std::string cell_style::to_hash_string() const
{
std::string hash_string("style");
auto hash_string = common_style::to_hash_string();
hash_string.append(":cell_style:");
hash_string.append(std::to_string(alignment_.apply()));
hash_string.append(alignment_.apply() ? std::to_string(alignment_.hash()) : " ");
hash_string.append(std::to_string(border_.apply()));
hash_string.append(border_.apply() ? std::to_string(border_.hash()) : " ");
hash_string.append(std::to_string(font_.apply()));
hash_string.append(font_.apply() ? std::to_string(font_.hash()) : " ");
hash_string.append(std::to_string(fill_.apply()));
hash_string.append(fill_.apply() ? std::to_string(fill_.hash()) : " ");
hash_string.append(std::to_string(number_format_.apply()));
hash_string.append(number_format_.apply() ? std::to_string(number_format_.hash()) : " ");
hash_string.append(std::to_string(protection_.apply()));
hash_string.append(protection_.apply() ? std::to_string(protection_.hash()) : " ");
if (!named_style_name_.empty())
{
hash_string.append(named_style_name_);
}
else
{
hash_string.append(":");
}
return hash_string;
}
void cell_style::set_named_style(const std::string &style_name)
{
named_style_name_ = style_name;
}
} // namespace xlnt

View File

@ -30,9 +30,27 @@ common_style::common_style()
}
common_style::common_style(const common_style &other)
: alignment_(other.alignment_),
border_(other.border_),
fill_(other.fill_),
font_(other.font_),
number_format_(other.number_format_),
protection_(other.protection_)
{
}
common_style &common_style::operator=(const xlnt::common_style &other)
{
alignment_ = other.alignment_;
border_ = other.border_;
fill_ = other.fill_;
font_ = other.font_;
number_format_ = other.number_format_;
protection_ = other.protection_;
return *this;
}
alignment &common_style::get_alignment()
{
return alignment_;
@ -46,6 +64,7 @@ const alignment &common_style::get_alignment() const
void common_style::set_alignment(const xlnt::alignment &new_alignment)
{
alignment_ = new_alignment;
alignment_.apply(true);
}
number_format &common_style::get_number_format()
@ -61,6 +80,7 @@ const number_format &common_style::get_number_format() const
void common_style::set_number_format(const xlnt::number_format &new_number_format)
{
number_format_ = new_number_format;
number_format_.apply(true);
}
border &common_style::get_border()
@ -76,6 +96,7 @@ const border &common_style::get_border() const
void common_style::set_border(const xlnt::border &new_border)
{
border_ = new_border;
border_.apply(true);
}
fill &common_style::get_fill()
@ -91,6 +112,7 @@ const fill &common_style::get_fill() const
void common_style::set_fill(const xlnt::fill &new_fill)
{
fill_ = new_fill;
fill_.apply(true);
}
font &common_style::get_font()
@ -106,6 +128,7 @@ const font &common_style::get_font() const
void common_style::set_font(const xlnt::font &new_font)
{
font_ = new_font;
font_.apply(true);
}
protection &common_style::get_protection()
@ -121,11 +144,32 @@ const protection &common_style::get_protection() const
void common_style::set_protection(const xlnt::protection &new_protection)
{
protection_ = new_protection;
protection_.apply(true);
}
std::string common_style::to_hash_string() const
{
return "common_style";
std::string hash_string("common_style:");
hash_string.append(std::to_string(alignment_.apply()));
hash_string.append(alignment_.apply() ? std::to_string(alignment_.hash()) : ":");
hash_string.append(std::to_string(border_.apply()));
hash_string.append(border_.apply() ? std::to_string(border_.hash()) : ":");
hash_string.append(std::to_string(font_.apply()));
hash_string.append(font_.apply() ? std::to_string(font_.hash()) : ":");
hash_string.append(std::to_string(fill_.apply()));
hash_string.append(fill_.apply() ? std::to_string(fill_.hash()) : ":");
hash_string.append(std::to_string(number_format_.apply()));
hash_string.append(number_format_.apply() ? std::to_string(number_format_.hash()) : ":");
hash_string.append(std::to_string(protection_.apply()));
hash_string.append(protection_.apply() ? std::to_string(protection_.hash()) : ":");
return hash_string;
}
} // namespace xlnt

View File

@ -26,13 +26,30 @@
namespace xlnt {
named_style::named_style()
: hidden_(false),
builtin_id_(0)
{
}
named_style::named_style(const named_style &other)
: common_style(other),
name_(other.name_),
hidden_(other.hidden_),
builtin_id_(other.builtin_id_)
{
}
named_style &named_style::operator=(const named_style &other)
{
common_style::operator=(other);
name_ = other.name_;
hidden_ = other.hidden_;
builtin_id_ = other.builtin_id_;
return *this;
}
bool named_style::get_hidden() const
{
return hidden_;

View File

@ -1095,7 +1095,7 @@ std::string number_format::to_hash_string() const
{
std::string hash_string("number_format");
hash_string.append(std::to_string(id_));
// hash_string.append(std::to_string(id_));
hash_string.append(format_string_);
return hash_string;

View File

@ -57,7 +57,7 @@ public:
xlnt::workbook wb;
xlnt::style_serializer s(wb);
TS_ASSERT(s.read_stylesheet(doc));
TS_ASSERT_EQUALS(wb.get_number_formats().size(), 1);
TS_ASSERT_EQUALS(s.get_number_formats().size(), 1);
}
void test_from_complex()
@ -68,10 +68,10 @@ public:
xlnt::workbook wb;
xlnt::style_serializer s(wb);
TS_ASSERT(s.read_stylesheet(doc));
TS_ASSERT_EQUALS(wb.get_borders().size(), 7);
TS_ASSERT_EQUALS(wb.get_fills().size(), 6);
TS_ASSERT_EQUALS(wb.get_fonts().size(), 8);
TS_ASSERT_EQUALS(wb.get_number_formats().size(), 1);
TS_ASSERT_EQUALS(s.get_borders().size(), 7);
TS_ASSERT_EQUALS(s.get_fills().size(), 6);
TS_ASSERT_EQUALS(s.get_fonts().size(), 8);
TS_ASSERT_EQUALS(s.get_number_formats().size(), 1);
}
void test_merge_named_styles()

View File

@ -27,7 +27,6 @@
#include <set>
#include <sstream>
#include <xlnt/drawing/drawing.hpp>
#include <xlnt/packaging/app_properties.hpp>
#include <xlnt/packaging/document_properties.hpp>
#include <xlnt/packaging/manifest.hpp>
@ -86,6 +85,8 @@ workbook::workbook() : d_(new detail::workbook_impl())
d_->manifest_.add_override_type("/xl/sharedStrings.xml", "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml");
d_->manifest_.add_override_type("/docProps/core.xml", "application/vnd.openxmlformats-package.core-properties+xml");
d_->manifest_.add_override_type("/docProps/app.xml", "application/vnd.openxmlformats-officedocument.extended-properties+xml");
add_style(cell_style());
}
workbook::workbook(encoding e) : workbook()
@ -454,7 +455,6 @@ void workbook::clear()
d_->worksheets_.clear();
d_->relationships_.clear();
d_->active_sheet_index_ = 0;
d_->drawings_.clear();
d_->properties_ = document_properties();
}
@ -547,6 +547,15 @@ workbook::workbook(const workbook &other) : workbook()
}
}
workbook::~workbook()
{
}
const std::vector<named_style> &workbook::get_named_styles() const
{
return d_->named_styles_;
}
bool workbook::get_data_only() const
{
return d_->data_only_;
@ -598,8 +607,17 @@ std::vector<named_range> workbook::get_named_ranges() const
std::size_t workbook::add_style(const cell_style &style)
{
for (std::size_t i = 0; i < d_->cell_styles_.size(); i++)
{
if (d_->cell_styles_[i] == style)
{
return i;
}
}
d_->cell_styles_.push_back(style);
return d_->cell_styles_.size();
return d_->cell_styles_.size() - 1;
}
cell_style &workbook::get_style(std::size_t style_index)
@ -680,4 +698,14 @@ const std::vector<std::uint8_t> &workbook::get_thumbnail() const
return d_->thumbnail_;
}
named_style &workbook::create_named_style(const std::string &name)
{
named_style style;
style.set_name(name);
d_->named_styles_.push_back(style);
return d_->named_styles_.back();
}
} // namespace xlnt