mirror of
https://github.com/tfussell/xlnt.git
synced 2024-03-22 13:11:17 +08:00
continue fixing up border and fill round tripping
This commit is contained in:
parent
ba2186ff7b
commit
cb5a9d8802
|
@ -46,15 +46,15 @@ public:
|
||||||
bool alignment_applied() const;
|
bool alignment_applied() const;
|
||||||
|
|
||||||
// Border
|
// Border
|
||||||
class border &border();
|
virtual class border &border();
|
||||||
const class border &border() const;
|
virtual const class border &border() const;
|
||||||
void border(const xlnt::border &new_border, bool applied);
|
virtual void border(const xlnt::border &new_border, bool applied);
|
||||||
bool border_applied() const;
|
bool border_applied() const;
|
||||||
|
|
||||||
// Fill
|
// Fill
|
||||||
class fill &fill();
|
virtual class fill &fill();
|
||||||
const class fill &fill() const;
|
virtual const class fill &fill() const;
|
||||||
void fill(const xlnt::fill &new_fill, bool applied);
|
virtual void fill(const xlnt::fill &new_fill, bool applied);
|
||||||
bool fill_applied() const;
|
bool fill_applied() const;
|
||||||
|
|
||||||
// Font
|
// Font
|
||||||
|
|
|
@ -54,6 +54,14 @@ public:
|
||||||
void style(const std::string &name);
|
void style(const std::string &name);
|
||||||
void style(const xlnt::style &new_style);
|
void style(const xlnt::style &new_style);
|
||||||
const class style &style() const;
|
const class style &style() const;
|
||||||
|
|
||||||
|
class border &border() override;
|
||||||
|
const class border &border() const override;
|
||||||
|
void border(const xlnt::border &new_border, bool applied) override;
|
||||||
|
|
||||||
|
class fill &fill() override;
|
||||||
|
const class fill &fill() const override;
|
||||||
|
void fill(const xlnt::fill &new_fill, bool applied) override;
|
||||||
|
|
||||||
class font &font() override;
|
class font &font() override;
|
||||||
const class font &font() const override;
|
const class font &font() const override;
|
||||||
|
|
|
@ -9,7 +9,7 @@ template<typename T>
|
||||||
class XLNT_CLASS optional
|
class XLNT_CLASS optional
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
optional() : has_value_(false)
|
optional() : has_value_(false), value_(T())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -139,6 +139,44 @@ struct stylesheet
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::size_t add_border(const border &new_border)
|
||||||
|
{
|
||||||
|
std::size_t index = 0;
|
||||||
|
|
||||||
|
for (const border &f : borders)
|
||||||
|
{
|
||||||
|
if (f == new_border)
|
||||||
|
{
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
|
||||||
|
borders.push_back(new_border);
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t add_fill(const fill &new_fill)
|
||||||
|
{
|
||||||
|
std::size_t index = 0;
|
||||||
|
|
||||||
|
for (const fill &f : fills)
|
||||||
|
{
|
||||||
|
if (f == new_fill)
|
||||||
|
{
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
|
||||||
|
fills.push_back(new_fill);
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
std::size_t add_font(const font &new_font)
|
std::size_t add_font(const font &new_font)
|
||||||
{
|
{
|
||||||
std::size_t index = 0;
|
std::size_t index = 0;
|
||||||
|
@ -157,6 +195,24 @@ struct stylesheet
|
||||||
|
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
format_impls.clear();
|
||||||
|
formats.clear();
|
||||||
|
|
||||||
|
style_impls.clear();
|
||||||
|
styles.clear();
|
||||||
|
|
||||||
|
alignments.clear();
|
||||||
|
borders.clear();
|
||||||
|
fills.clear();
|
||||||
|
fonts.clear();
|
||||||
|
number_formats.clear();
|
||||||
|
protections.clear();
|
||||||
|
|
||||||
|
colors.clear();
|
||||||
|
}
|
||||||
|
|
||||||
std::list<format_impl> format_impls;
|
std::list<format_impl> format_impls;
|
||||||
std::vector<format> formats;
|
std::vector<format> formats;
|
||||||
|
|
|
@ -213,8 +213,8 @@ std::string to_string(xlnt::border_side side)
|
||||||
{
|
{
|
||||||
case xlnt::border_side::bottom: return "bottom";
|
case xlnt::border_side::bottom: return "bottom";
|
||||||
case xlnt::border_side::top: return "top";
|
case xlnt::border_side::top: return "top";
|
||||||
case xlnt::border_side::start: return "start";
|
case xlnt::border_side::start: return "left";
|
||||||
case xlnt::border_side::end: return "end";
|
case xlnt::border_side::end: return "right";
|
||||||
case xlnt::border_side::horizontal: return "horizontal";
|
case xlnt::border_side::horizontal: return "horizontal";
|
||||||
case xlnt::border_side::vertical: return "vertical";
|
case xlnt::border_side::vertical: return "vertical";
|
||||||
default:
|
default:
|
||||||
|
@ -669,6 +669,15 @@ void xlsx_consumer::populate_workbook()
|
||||||
case relationship::type::worksheet:
|
case relationship::type::worksheet:
|
||||||
read_worksheet(document.root(), rel.get_id());
|
read_worksheet(document.root(), rel.get_id());
|
||||||
break;
|
break;
|
||||||
|
case relationship::type::shared_string_table:
|
||||||
|
read_shared_string_table(document);
|
||||||
|
break;
|
||||||
|
case relationship::type::styles:
|
||||||
|
read_stylesheet(document);
|
||||||
|
break;
|
||||||
|
case relationship::type::theme:
|
||||||
|
read_theme(document);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1046,7 +1055,9 @@ void xlsx_consumer::read_stylesheet(const pugi::xml_node root)
|
||||||
for (auto xf_node : cell_style_xfs_node.children("xf"))
|
for (auto xf_node : cell_style_xfs_node.children("xf"))
|
||||||
{
|
{
|
||||||
auto cell_style_node = *(cell_style_iter++);
|
auto cell_style_node = *(cell_style_iter++);
|
||||||
auto &style = destination_.create_style(cell_style_node.attribute("Name").value());
|
auto &style = destination_.create_style(cell_style_node.attribute("name").value());
|
||||||
|
|
||||||
|
style.builtin_id(string_to_size_t(cell_style_node.attribute("builtinId").value()));
|
||||||
|
|
||||||
// Alignment
|
// Alignment
|
||||||
auto alignment_node = xf_node.child("alignment");
|
auto alignment_node = xf_node.child("alignment");
|
||||||
|
@ -1076,7 +1087,23 @@ void xlsx_consumer::read_stylesheet(const pugi::xml_node root)
|
||||||
// Number Format
|
// Number Format
|
||||||
auto number_format_applied = is_true(xf_node.attribute("applyNumberFormat").value());
|
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_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);
|
auto number_format = number_format::general();
|
||||||
|
bool is_custom_number_format = false;
|
||||||
|
|
||||||
|
for (const auto &nf : stylesheet.number_formats)
|
||||||
|
{
|
||||||
|
if (nf.get_id() == number_format_id)
|
||||||
|
{
|
||||||
|
number_format = nf;
|
||||||
|
is_custom_number_format = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (number_format_id < 164 && !is_custom_number_format)
|
||||||
|
{
|
||||||
|
number_format = number_format::from_builtin_id(number_format_id);
|
||||||
|
}
|
||||||
|
|
||||||
style.number_format(number_format, number_format_applied);
|
style.number_format(number_format, number_format_applied);
|
||||||
|
|
||||||
// Protection
|
// Protection
|
||||||
|
@ -1119,7 +1146,23 @@ void xlsx_consumer::read_stylesheet(const pugi::xml_node root)
|
||||||
// Number Format
|
// Number Format
|
||||||
auto number_format_applied = is_true(xf_node.attribute("applyNumberFormat").value());
|
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_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);
|
auto number_format = number_format::general();
|
||||||
|
bool is_custom_number_format = false;
|
||||||
|
|
||||||
|
for (const auto &nf : stylesheet.number_formats)
|
||||||
|
{
|
||||||
|
if (nf.get_id() == number_format_id)
|
||||||
|
{
|
||||||
|
number_format = nf;
|
||||||
|
is_custom_number_format = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (number_format_id < 164 && !is_custom_number_format)
|
||||||
|
{
|
||||||
|
number_format = number_format::from_builtin_id(number_format_id);
|
||||||
|
}
|
||||||
|
|
||||||
format.number_format(number_format, number_format_applied);
|
format.number_format(number_format, number_format_applied);
|
||||||
|
|
||||||
// Protection
|
// Protection
|
||||||
|
|
|
@ -1070,12 +1070,27 @@ void xlsx_producer::write_styles(const relationship &rel, pugi::xml_node root)
|
||||||
|
|
||||||
xf_node.append_attribute("numFmtId").set_value(std::to_string(current_format.number_format().get_id()).c_str());
|
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()));
|
auto font_iter = std::find(stylesheet.fonts.begin(), stylesheet.fonts.end(), current_format.font());
|
||||||
|
if (font_iter == stylesheet.fonts.end())
|
||||||
|
{
|
||||||
|
throw xlnt::exception("font not found");
|
||||||
|
}
|
||||||
|
auto font_id = std::distance(stylesheet.fonts.begin(), font_iter);
|
||||||
xf_node.append_attribute("fontId").set_value(std::to_string(font_id).c_str());
|
xf_node.append_attribute("fontId").set_value(std::to_string(font_id).c_str());
|
||||||
|
|
||||||
|
auto fill_iter = std::find(stylesheet.fills.begin(), stylesheet.fills.end(), current_format.fill());
|
||||||
|
if (fill_iter == stylesheet.fills.end())
|
||||||
|
{
|
||||||
|
throw xlnt::exception("fill not found");
|
||||||
|
}
|
||||||
auto fill_id = std::distance(stylesheet.fills.begin(), std::find(stylesheet.fills.begin(), stylesheet.fills.end(), current_format.fill()));
|
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());
|
xf_node.append_attribute("fillId").set_value(std::to_string(fill_id).c_str());
|
||||||
|
|
||||||
|
auto border_iter = std::find(stylesheet.borders.begin(), stylesheet.borders.end(), current_format.border());
|
||||||
|
if (border_iter == stylesheet.borders.end())
|
||||||
|
{
|
||||||
|
throw xlnt::exception("border not found");
|
||||||
|
}
|
||||||
auto border_id = std::distance(stylesheet.borders.begin(), std::find(stylesheet.borders.begin(), stylesheet.borders.end(), current_format.border()));
|
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());
|
xf_node.append_attribute("borderId").set_value(std::to_string(border_id).c_str());
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,38 @@ const style &format::style() const
|
||||||
return d_->parent->get_style(*d_->style);
|
return d_->parent->get_style(*d_->style);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xlnt::border &format::border()
|
||||||
|
{
|
||||||
|
return base_format::border();
|
||||||
|
}
|
||||||
|
|
||||||
|
const xlnt::border &format::border() const
|
||||||
|
{
|
||||||
|
return base_format::border();
|
||||||
|
}
|
||||||
|
|
||||||
|
void format::border(const xlnt::border &new_border, bool applied)
|
||||||
|
{
|
||||||
|
border_id(d_->parent->add_border(new_border));
|
||||||
|
base_format::border(new_border, applied);
|
||||||
|
}
|
||||||
|
|
||||||
|
xlnt::fill &format::fill()
|
||||||
|
{
|
||||||
|
return base_format::fill();
|
||||||
|
}
|
||||||
|
|
||||||
|
const xlnt::fill &format::fill() const
|
||||||
|
{
|
||||||
|
return base_format::fill();
|
||||||
|
}
|
||||||
|
|
||||||
|
void format::fill(const xlnt::fill &new_fill, bool applied)
|
||||||
|
{
|
||||||
|
fill_id(d_->parent->add_fill(new_fill));
|
||||||
|
base_format::fill(new_fill, applied);
|
||||||
|
}
|
||||||
|
|
||||||
xlnt::font &format::font()
|
xlnt::font &format::font()
|
||||||
{
|
{
|
||||||
return base_format::font();
|
return base_format::font();
|
||||||
|
@ -88,7 +120,6 @@ void format::font(const xlnt::font &new_font, bool applied)
|
||||||
base_format::font(new_font, applied);
|
base_format::font(new_font, applied);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
xlnt::number_format &format::number_format()
|
xlnt::number_format &format::number_format()
|
||||||
{
|
{
|
||||||
return base_format::number_format();
|
return base_format::number_format();
|
||||||
|
@ -112,6 +143,18 @@ void format::number_format(const xlnt::number_format &new_number_format, bool ap
|
||||||
base_format::number_format(copy, applied);
|
base_format::number_format(copy, applied);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
format &format::border_id(std::size_t id)
|
||||||
|
{
|
||||||
|
d_->border_id = id;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
format &format::fill_id(std::size_t id)
|
||||||
|
{
|
||||||
|
d_->fill_id = id;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
format &format::font_id(std::size_t id)
|
format &format::font_id(std::size_t id)
|
||||||
{
|
{
|
||||||
d_->font_id = id;
|
d_->font_id = id;
|
||||||
|
|
|
@ -20,6 +20,7 @@ public:
|
||||||
{
|
{
|
||||||
std::vector<std::uint8_t> buffer;
|
std::vector<std::uint8_t> buffer;
|
||||||
original.save(buffer);
|
original.save(buffer);
|
||||||
|
original.save("a.xlsx");
|
||||||
|
|
||||||
xlnt::zip_file original_archive;
|
xlnt::zip_file original_archive;
|
||||||
original_archive.load(buffer);
|
original_archive.load(buffer);
|
||||||
|
@ -29,6 +30,7 @@ public:
|
||||||
|
|
||||||
buffer.clear();
|
buffer.clear();
|
||||||
resulting_workbook.save(buffer);
|
resulting_workbook.save(buffer);
|
||||||
|
resulting_workbook.save("b.xlsx");
|
||||||
|
|
||||||
xlnt::zip_file resulting_archive;
|
xlnt::zip_file resulting_archive;
|
||||||
resulting_archive.load(buffer);
|
resulting_archive.load(buffer);
|
||||||
|
@ -57,26 +59,26 @@ public:
|
||||||
return xml_helper::xlsx_archives_match(original_archive, resulting_archive);
|
return xml_helper::xlsx_archives_match(original_archive, resulting_archive);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_round_trip_minimal_wr()
|
void test_round_trip_minimal_wrw()
|
||||||
{
|
{
|
||||||
xlnt::workbook wb = xlnt::workbook::minimal();
|
xlnt::workbook wb = xlnt::workbook::minimal();
|
||||||
TS_ASSERT(round_trip_matches_wrw(wb));
|
TS_ASSERT(round_trip_matches_wrw(wb));
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_round_trip_empty_excel_wr()
|
void test_round_trip_empty_excel_wrw()
|
||||||
{
|
{
|
||||||
xlnt::workbook wb = xlnt::workbook::empty_excel();
|
xlnt::workbook wb = xlnt::workbook::empty_excel();
|
||||||
TS_ASSERT(round_trip_matches_wrw(wb));
|
TS_ASSERT(round_trip_matches_wrw(wb));
|
||||||
}
|
}
|
||||||
|
|
||||||
void _test_round_trip_empty_libre_office_wr()
|
void _test_round_trip_empty_libre_office_wrw()
|
||||||
{
|
{
|
||||||
TS_SKIP("");
|
TS_SKIP("");
|
||||||
xlnt::workbook wb = xlnt::workbook::empty_libre_office();
|
xlnt::workbook wb = xlnt::workbook::empty_libre_office();
|
||||||
TS_ASSERT(round_trip_matches_wrw(wb));
|
TS_ASSERT(round_trip_matches_wrw(wb));
|
||||||
}
|
}
|
||||||
|
|
||||||
void _test_round_trip_empty_pages_wr()
|
void _test_round_trip_empty_pages_wrw()
|
||||||
{
|
{
|
||||||
TS_SKIP("");
|
TS_SKIP("");
|
||||||
xlnt::workbook wb = xlnt::workbook::empty_numbers();
|
xlnt::workbook wb = xlnt::workbook::empty_numbers();
|
||||||
|
|
|
@ -766,6 +766,7 @@ worksheet workbook::operator[](std::size_t index)
|
||||||
void workbook::clear()
|
void workbook::clear()
|
||||||
{
|
{
|
||||||
*d_ = detail::workbook_impl();
|
*d_ = detail::workbook_impl();
|
||||||
|
d_->stylesheet_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool workbook::operator==(const workbook &rhs) const
|
bool workbook::operator==(const workbook &rhs) const
|
||||||
|
|
Loading…
Reference in New Issue
Block a user