From a81a0a6dde71940470241c813faba1e4f619bcf2 Mon Sep 17 00:00:00 2001 From: Thomas Fussell Date: Sun, 18 Sep 2016 11:32:59 -0400 Subject: [PATCH] use value_traits for enum parsing/serialization and refactor xlsx_producer helper functions --- include/xlnt/utils/exceptions.hpp | 9 + source/detail/custom_value_traits.cpp | 155 ++++++++ source/detail/custom_value_traits.hpp | 373 ++++++++++++++++++ source/detail/xlsx_consumer.cpp | 50 +-- source/detail/xlsx_producer.cpp | 541 ++++++++++---------------- source/detail/xlsx_producer.hpp | 75 ++-- 6 files changed, 813 insertions(+), 390 deletions(-) create mode 100644 source/detail/custom_value_traits.cpp create mode 100644 source/detail/custom_value_traits.hpp diff --git a/include/xlnt/utils/exceptions.hpp b/include/xlnt/utils/exceptions.hpp index bd800269..bb50975d 100644 --- a/include/xlnt/utils/exceptions.hpp +++ b/include/xlnt/utils/exceptions.hpp @@ -146,4 +146,13 @@ public: no_visible_worksheets(); }; +/// +/// Debug exception for a switch that fell through to the default case +/// +class XLNT_CLASS unhandled_switch_case : public exception +{ +public: + unhandled_switch_case(); +}; + } // namespace xlnt diff --git a/source/detail/custom_value_traits.cpp b/source/detail/custom_value_traits.cpp new file mode 100644 index 00000000..3e2e40ec --- /dev/null +++ b/source/detail/custom_value_traits.cpp @@ -0,0 +1,155 @@ +#include + +namespace xlnt { +namespace detail { + +/// +/// Returns the string representation of the underline style. +/// +std::string to_string(font::underline_style underline_style) +{ + switch (underline_style) + { + case font::underline_style::double_: return "double"; + case font::underline_style::double_accounting: return "doubleAccounting"; + case font::underline_style::single: return "single"; + case font::underline_style::single_accounting: return "singleAccounting"; + case font::underline_style::none: return "none"; + default: return default_case("none"); + } +} + + +/// +/// Returns the string representation of the relationship type. +/// +std::string to_string(relationship::type t) +{ + switch (t) + { + case relationship::type::office_document: + return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"; + case relationship::type::thumbnail: + return "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail"; + case relationship::type::calculation_chain: + return "http://purl.oclc.org/ooxml/officeDocument/relationships/calcChain"; + case relationship::type::extended_properties: + return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties"; + case relationship::type::core_properties: + return "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"; + case relationship::type::worksheet: + return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet"; + case relationship::type::shared_string_table: + return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings"; + case relationship::type::styles: + return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles"; + case relationship::type::theme: + return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme"; + case relationship::type::hyperlink: + return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"; + case relationship::type::chartsheet: + return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chartsheet"; + default: + return default_case("?"); + } +} + +std::string to_string(pattern_fill_type fill_type) +{ + switch (fill_type) + { + case pattern_fill_type::darkdown: return "darkdown"; + case pattern_fill_type::darkgray: return "darkgray"; + case pattern_fill_type::darkgrid: return "darkgrid"; + case pattern_fill_type::darkhorizontal: return "darkhorizontal"; + case pattern_fill_type::darktrellis: return "darkhorizontal"; + case pattern_fill_type::darkup: return "darkup"; + case pattern_fill_type::darkvertical: return "darkvertical"; + case pattern_fill_type::gray0625: return "gray0625"; + case pattern_fill_type::gray125: return "gray125"; + case pattern_fill_type::lightdown: return "lightdown"; + case pattern_fill_type::lightgray: return "lightgray"; + case pattern_fill_type::lightgrid: return "lightgrid"; + case pattern_fill_type::lighthorizontal: return "lighthorizontal"; + case pattern_fill_type::lighttrellis: return "lighttrellis"; + case pattern_fill_type::lightup: return "lightup"; + case pattern_fill_type::lightvertical: return "lightvertical"; + case pattern_fill_type::mediumgray: return "mediumgray"; + case pattern_fill_type::solid: return "solid"; + case pattern_fill_type::none: return "none"; + default: return default_case("none"); + } +} + +std::string to_string(gradient_fill_type fill_type) +{ + return fill_type == gradient_fill_type::linear ? "linear" : "path"; +} + +std::string to_string(border_style border_style) +{ + switch (border_style) + { + case border_style::dashdot: return "dashdot"; + case border_style::dashdotdot: return "dashdotdot"; + case border_style::dashed: return "dashed"; + case border_style::dotted: return "dotted"; + case border_style::double_: return "double"; + case border_style::hair: return "hair"; + case border_style::medium: return "medium"; + case border_style::mediumdashdot: return "mediumdashdot"; + case border_style::mediumdashdotdot: return "mediumdashdotdot"; + case border_style::mediumdashed: return "mediumdashed"; + case border_style::slantdashdot: return "slantdashdot"; + case border_style::thick: return "thick"; + case border_style::thin: return "thin"; + case border_style::none: return "none"; + default: return default_case("none"); + } +} + +std::string to_string(vertical_alignment vertical_alignment) +{ + switch (vertical_alignment) + { + case vertical_alignment::bottom: return "bottom"; + case vertical_alignment::center: return "center"; + case vertical_alignment::justify: return "justify"; + case vertical_alignment::top: return "top"; + case vertical_alignment::none: return "none"; + default: return default_case("none"); + } +} + +std::string to_string(horizontal_alignment horizontal_alignment) +{ + switch (horizontal_alignment) + { + case horizontal_alignment::center: return "center"; + case horizontal_alignment::center_continuous: return "center-continous"; + case horizontal_alignment::general: return "general"; + case horizontal_alignment::justify: return "justify"; + case horizontal_alignment::left: return "left"; + case horizontal_alignment::right: return "right"; + case horizontal_alignment::none: return "none"; + default: return default_case("none"); + } +} + +std::string to_string(border_side side) +{ + switch (side) + { + case border_side::bottom: return "bottom"; + case border_side::top: return "top"; + case border_side::start: return "left"; + case border_side::end: return "right"; + case border_side::horizontal: return "horizontal"; + case border_side::vertical: return "vertical"; + case border_side::diagonal: return "diagonal"; + default: return default_case("top"); + } +} + +} // namespace detail +} // namespace xlnt diff --git a/source/detail/custom_value_traits.hpp b/source/detail/custom_value_traits.hpp new file mode 100644 index 00000000..7c328f16 --- /dev/null +++ b/source/detail/custom_value_traits.hpp @@ -0,0 +1,373 @@ +#pragma once + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace xlnt { +namespace detail { + +template +T default_case(T default_return_value) +{ +#ifdef EXCEPT_ON_UNHANDLED_SWITCH_CASE + throw unhandled_switch_case(); +#endif + return default_return_value; +} + +/// +/// Returns the string representation of the underline style. +/// +std::string to_string(font::underline_style underline_style); + +/// +/// Returns the string representation of the relationship type. +/// +std::string to_string(relationship::type t); + +std::string to_string(pattern_fill_type fill_type); + +std::string to_string(gradient_fill_type fill_type); + +std::string to_string(border_style border_style); + +std::string to_string(vertical_alignment vertical_alignment); + +std::string to_string(horizontal_alignment horizontal_alignment); + +std::string to_string(border_side side); + +} // namespace detail +} // namespace xlnt + +namespace xml { + +template <> +struct value_traits +{ + static xlnt::font::underline_style parse(std::string underline_string, const parser &) + { + using xlnt::font; + + static auto *underline_styles = new std::vector + { + font::underline_style::double_, + font::underline_style::double_accounting, + font::underline_style::single, + font::underline_style::single_accounting, + font::underline_style::none + }; + + for (auto underline_style : *underline_styles) + { + if (xlnt::detail::to_string(underline_style) == underline_string) + { + return underline_style; + } + } + + return xlnt::detail::default_case(font::underline_style::none); + } + + static std::string serialize(xlnt::font::underline_style underline_style, const serializer &) + { + return xlnt::detail::to_string(underline_style); + } +}; // struct value_traits + +template <> +struct value_traits +{ + static xlnt::relationship_type parse(std::string relationship_type_string, const parser &) + { + using xlnt::relationship_type; + + static auto *relationship_types = new std::vector + { + relationship_type::calculation_chain, + relationship_type::chartsheet, + relationship_type::comments, + relationship_type::connections, + relationship_type::core_properties, + relationship_type::custom_properties, + relationship_type::custom_property, + relationship_type::custom_xml_mappings, + relationship_type::dialogsheet, + relationship_type::drawings, + relationship_type::extended_properties, + relationship_type::external_workbook_references, + relationship_type::hyperlink, + relationship_type::image, + relationship_type::metadata, + relationship_type::office_document, + relationship_type::pivot_table, + relationship_type::pivot_table_cache_definition, + relationship_type::pivot_table_cache_records, + relationship_type::printer_settings, + relationship_type::query_table, + relationship_type::revision_log, + relationship_type::shared_string_table, + relationship_type::shared_workbook, + relationship_type::shared_workbook_revision_headers, + relationship_type::shared_workbook_user_data, + relationship_type::single_cell_table_definitions, + relationship_type::styles, + relationship_type::table_definition, + relationship_type::theme, + relationship_type::thumbnail, + relationship_type::unknown, + relationship_type::volatile_dependencies, + relationship_type::worksheet + }; + + for (auto type : *relationship_types) + { + if (xlnt::detail::to_string(type) == relationship_type_string) + { + return type; + } + } + + return xlnt::detail::default_case(relationship_type::unknown); + } + + static std::string serialize(xlnt::relationship_type type, const serializer &) + { + return xlnt::detail::to_string(type); + } +}; // struct value_traits + +template <> +struct value_traits +{ + static xlnt::pattern_fill_type parse(std::string fill_type_string, const parser &) + { + using xlnt::pattern_fill_type; + + static auto *fill_types = new std::vector + { + pattern_fill_type::darkdown, + pattern_fill_type::darkgray, + pattern_fill_type::darkgrid, + pattern_fill_type::darkhorizontal, + pattern_fill_type::darktrellis, + pattern_fill_type::darkup, + pattern_fill_type::darkvertical, + pattern_fill_type::gray0625, + pattern_fill_type::gray125, + pattern_fill_type::lightdown, + pattern_fill_type::lightgray, + pattern_fill_type::lightgrid, + pattern_fill_type::lighthorizontal, + pattern_fill_type::lighttrellis, + pattern_fill_type::lightup, + pattern_fill_type::lightvertical, + pattern_fill_type::mediumgray, + pattern_fill_type::none, + pattern_fill_type::solid + }; + + for (auto fill_type : *fill_types) + { + if (xlnt::detail::to_string(fill_type) == fill_type_string) + { + return fill_type; + } + } + + return xlnt::detail::default_case(pattern_fill_type::none); + } + + static std::string serialize(xlnt::pattern_fill_type fill_type, const serializer &) + { + return xlnt::detail::to_string(fill_type); + } +}; // struct value_traits + +template <> +struct value_traits +{ + static xlnt::gradient_fill_type parse(std::string fill_type_string, const parser &) + { + using xlnt::gradient_fill_type; + + static auto *gradient_fill_types = new std::vector + { + gradient_fill_type::linear, + gradient_fill_type::path + }; + + for (auto fill_type : *gradient_fill_types) + { + if (xlnt::detail::to_string(fill_type) == fill_type_string) + { + return fill_type; + } + } + + return xlnt::detail::default_case(gradient_fill_type::linear); + } + + static std::string serialize(xlnt::gradient_fill_type fill_type, const serializer &) + { + return xlnt::detail::to_string(fill_type); + } +}; // struct value_traits + +template <> +struct value_traits +{ + static xlnt::border_style parse(std::string style_string, const parser &) + { + using xlnt::border_style; + + static auto *border_styles = new std::vector + { + border_style::dashdot, + border_style::dashdotdot, + border_style::dashed, + border_style::dotted, + border_style::double_, + border_style::hair, + border_style::medium, + border_style::mediumdashdot, + border_style::mediumdashdotdot, + border_style::mediumdashed, + border_style::none, + border_style::slantdashdot, + border_style::thick, + border_style::thin + }; + + for (auto style : *border_styles) + { + if (xlnt::detail::to_string(style) == style_string) + { + return style; + } + } + + return xlnt::detail::default_case(border_style::none); + } + + static std::string + serialize (xlnt::border_style style, const serializer &) + { + return xlnt::detail::to_string(style); + } +}; // struct value_traits + +template <> +struct value_traits +{ + static xlnt::vertical_alignment parse(std::string alignment_string, const parser &) + { + using xlnt::vertical_alignment; + + static auto *vertical_alignments = new std::vector + { + vertical_alignment::bottom, + vertical_alignment::center, + vertical_alignment::justify, + vertical_alignment::none, + vertical_alignment::top + }; + + for (auto alignment : *vertical_alignments) + { + if (xlnt::detail::to_string(alignment) == alignment_string) + { + return alignment; + } + } + + return xlnt::detail::default_case(vertical_alignment::none); + } + + static std::string serialize (xlnt::vertical_alignment alignment, const serializer &) + { + return xlnt::detail::to_string(alignment); + } +}; // struct value_traits + +template <> +struct value_traits +{ + static xlnt::horizontal_alignment parse(std::string alignment_string, const parser &) + { + using xlnt::horizontal_alignment; + + static auto *horizontal_alignments = new std::vector + { + horizontal_alignment::center, + horizontal_alignment::center_continuous, + horizontal_alignment::general, + horizontal_alignment::justify, + horizontal_alignment::left, + horizontal_alignment::right, + horizontal_alignment::none + }; + + for (auto alignment : *horizontal_alignments) + { + if (xlnt::detail::to_string(alignment) == alignment_string) + { + return alignment; + } + } + + return xlnt::detail::default_case(horizontal_alignment::none); + } + + static std::string serialize(xlnt::horizontal_alignment alignment, const serializer &) + { + return xlnt::detail::to_string(alignment); + } +}; // struct value_traits + +template <> +struct value_traits +{ + static xlnt::border_side parse(std::string side_string, const parser &) + { + using xlnt::border_side; + + static auto *border_sides = new std::vector + { + border_side::top, + border_side::bottom, + border_side::start, + border_side::end, + border_side::vertical, + border_side::horizontal, + border_side::diagonal + }; + + for (auto side : *border_sides) + { + if (xlnt::detail::to_string(side) == side_string) + { + return side; + } + } + + return border_side::top; + } + + static std::string serialize (xlnt::border_side side, const serializer &) + { + return xlnt::detail::to_string(side); + } +}; // struct value_traits + +} + + diff --git a/source/detail/xlsx_consumer.cpp b/source/detail/xlsx_consumer.cpp index ccc989a3..26bfb2d3 100644 --- a/source/detail/xlsx_consumer.cpp +++ b/source/detail/xlsx_consumer.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -57,16 +58,6 @@ struct EnumClassHash template T from_string(const std::string &string); -template<> -xlnt::font::underline_style from_string(const std::string &underline_string) -{ - if (underline_string == "double") return xlnt::font::underline_style::double_; - if (underline_string == "doubleAccounting") return xlnt::font::underline_style::double_accounting; - if (underline_string == "single") return xlnt::font::underline_style::single; - if (underline_string == "singleAccounting") return xlnt::font::underline_style::single_accounting; - return xlnt::font::underline_style::none; -} - template<> xlnt::pattern_fill_type from_string(const std::string &fill_type) { @@ -250,32 +241,38 @@ xlnt::protection read_protection(xml::parser &parser) xlnt::alignment read_alignment(xml::parser &parser) { xlnt::alignment align; -/* - align.wrap(is_true(alignment_node.attribute("wrapText").value())); - align.shrink(is_true(alignment_node.attribute("shrinkToFit").value())); - if (alignment_node.attribute("vertical")) + align.wrap(is_true(parser.attribute("wrapText"))); + align.shrink(is_true(parser.attribute("shrinkToFit"))); + + if (parser.attribute_present("vertical")) { - std::string vertical = alignment_node.attribute("vertical").value(); - align.vertical(from_string(vertical)); + align.vertical(from_string( + parser.attribute("vertical"))); } - if (alignment_node.attribute("horizontal")) + if (parser.attribute_present("horizontal")) { - std::string horizontal = alignment_node.attribute("horizontal").value(); - align.horizontal(from_string(horizontal)); + align.horizontal(from_string( + parser.attribute("horizontal"))); } -*/ + return align; } void read_number_formats(xml::parser &parser, std::vector &number_formats) { number_formats.clear(); -/* - for (auto num_fmt_node : number_formats_node.children("numFmt")) + + while (true) { - std::string format_string(num_fmt_node.attribute("formatCode").value()); + if (parser.peek() == xml::parser::event_type::end_element) + { + break; + } + + parser.next_expect(xml::parser::event_type::start_element, "numFmt"); + auto format_string = parser.attribute("formatCode"); if (format_string == "GENERAL") { @@ -285,11 +282,14 @@ void read_number_formats(xml::parser &parser, std::vector & xlnt::number_format nf; nf.set_format_string(format_string); - nf.set_id(string_to_size_t(num_fmt_node.attribute("numFmtId").value())); + nf.set_id(string_to_size_t(parser.attribute("numFmtId"))); number_formats.push_back(nf); + + parser.next_expect(xml::parser::event_type::end_element, "numFmt"); } -*/ + + parser.next_expect(xml::parser::event_type::end_element, "numFmts"); } xlnt::color read_color(xml::parser &parser) diff --git a/source/detail/xlsx_producer.cpp b/source/detail/xlsx_producer.cpp index e9eba970..e154a16c 100644 --- a/source/detail/xlsx_producer.cpp +++ b/source/detail/xlsx_producer.cpp @@ -1,5 +1,6 @@ #include +#include #include #include #include @@ -34,227 +35,12 @@ std::string fill(const std::string &string, std::size_t length = 2) std::string datetime_to_w3cdtf(const xlnt::datetime &dt) { - return std::to_string(dt.year) + "-" + fill(std::to_string(dt.month)) + "-" + fill(std::to_string(dt.day)) + "T" + - fill(std::to_string(dt.hour)) + ":" + fill(std::to_string(dt.minute)) + ":" + - fill(std::to_string(dt.second)) + "Z"; -} - -/// -/// Returns the string representation of the relationship type. -/// -std::string to_string(xlnt::relationship::type t) -{ - switch (t) - { - case xlnt::relationship::type::office_document: - return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"; - case xlnt::relationship::type::thumbnail: - return "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail"; - case xlnt::relationship::type::calculation_chain: - return "http://purl.oclc.org/ooxml/officeDocument/relationships/calcChain"; - case xlnt::relationship::type::extended_properties: - return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties"; - case xlnt::relationship::type::core_properties: - return "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"; - case xlnt::relationship::type::worksheet: - return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet"; - case xlnt::relationship::type::shared_string_table: - return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings"; - case xlnt::relationship::type::styles: - return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles"; - case xlnt::relationship::type::theme: - return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme"; - case xlnt::relationship::type::hyperlink: - return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"; - case xlnt::relationship::type::chartsheet: - return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chartsheet"; - default: - return "??"; - } -} - -std::string to_string(xlnt::font::underline_style underline_style) -{ - switch (underline_style) - { - case xlnt::font::underline_style::double_: return "double"; - case xlnt::font::underline_style::double_accounting: return "doubleAccounting"; - case xlnt::font::underline_style::single: return "single"; - case xlnt::font::underline_style::single_accounting: return "singleAccounting"; - default: - case xlnt::font::underline_style::none: return "none"; - } -} - -std::string to_string(xlnt::pattern_fill_type fill_type) -{ - switch (fill_type) - { - case xlnt::pattern_fill_type::darkdown: return "darkdown"; - case xlnt::pattern_fill_type::darkgray: return "darkgray"; - case xlnt::pattern_fill_type::darkgrid: return "darkgrid"; - case xlnt::pattern_fill_type::darkhorizontal: return "darkhorizontal"; - case xlnt::pattern_fill_type::darktrellis: return "darkhorizontal"; - case xlnt::pattern_fill_type::darkup: return "darkup"; - case xlnt::pattern_fill_type::darkvertical: return "darkvertical"; - case xlnt::pattern_fill_type::gray0625: return "gray0625"; - case xlnt::pattern_fill_type::gray125: return "gray125"; - case xlnt::pattern_fill_type::lightdown: return "lightdown"; - case xlnt::pattern_fill_type::lightgray: return "lightgray"; - case xlnt::pattern_fill_type::lightgrid: return "lightgrid"; - case xlnt::pattern_fill_type::lighthorizontal: return "lighthorizontal"; - case xlnt::pattern_fill_type::lighttrellis: return "lighttrellis"; - case xlnt::pattern_fill_type::lightup: return "lightup"; - case xlnt::pattern_fill_type::lightvertical: return "lightvertical"; - case xlnt::pattern_fill_type::mediumgray: return "mediumgray"; - case xlnt::pattern_fill_type::solid: return "solid"; - default: - case xlnt::pattern_fill_type::none: return "none"; - } -} - -std::string to_string(xlnt::gradient_fill_type fill_type) -{ - return fill_type == xlnt::gradient_fill_type::linear ? "linear" : "path"; -} - -std::string to_string(xlnt::border_style border_style) -{ - switch (border_style) - { - case xlnt::border_style::dashdot: return "dashdot"; - case xlnt::border_style::dashdotdot: return "dashdotdot"; - case xlnt::border_style::dashed: return "dashed"; - case xlnt::border_style::dotted: return "dotted"; - case xlnt::border_style::double_: return "double"; - case xlnt::border_style::hair: return "hair"; - case xlnt::border_style::medium: return "medium"; - case xlnt::border_style::mediumdashdot: return "mediumdashdot"; - case xlnt::border_style::mediumdashdotdot: return "mediumdashdotdot"; - case xlnt::border_style::mediumdashed: return "mediumdashed"; - case xlnt::border_style::slantdashdot: return "slantdashdot"; - case xlnt::border_style::thick: return "thick"; - case xlnt::border_style::thin: return "thin"; - default: - case xlnt::border_style::none: return "none"; - } -} - -std::string to_string(xlnt::vertical_alignment vertical_alignment) -{ - switch (vertical_alignment) - { - case xlnt::vertical_alignment::bottom: return "bottom"; - case xlnt::vertical_alignment::center: return "center"; - case xlnt::vertical_alignment::justify: return "justify"; - case xlnt::vertical_alignment::top: return "top"; - default: - case xlnt::vertical_alignment::none: return "none"; - } -} - -std::string to_string(xlnt::horizontal_alignment horizontal_alignment) -{ - switch (horizontal_alignment) - { - case xlnt::horizontal_alignment::center: return "center"; - case xlnt::horizontal_alignment::center_continuous: return "center-continous"; - case xlnt::horizontal_alignment::general: return "general"; - case xlnt::horizontal_alignment::justify: return "justify"; - case xlnt::horizontal_alignment::left: return "left"; - case xlnt::horizontal_alignment::right: return "right"; - default: - case xlnt::horizontal_alignment::none: return "none"; - } -} - -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"; - } -} - -void write_relationships(const std::vector &relationships, xml::serializer &serializer) -{ - const auto xmlns = xlnt::constants::get_namespace("relationships"); - - serializer.start_element(xmlns, "Relationships"); - serializer.namespace_decl(xmlns, ""); - - for (const auto &relationship : relationships) - { - serializer.start_element(xmlns, "Relationship"); - - serializer.attribute("Id", relationship.get_id()); - serializer.attribute("Type", to_string(relationship.get_type())); - serializer.attribute("Target", relationship.get_target().get_path().string()); - - if (relationship.get_target_mode() == xlnt::target_mode::external) - { - serializer.attribute("TargetMode", "External"); - } - - serializer.end_element(xmlns, "Relationship"); - } - - serializer.end_element(xmlns, "Relationships"); -} - - -bool write_color(const xlnt::color &color, xml::serializer &serializer) -{ - switch (color.get_type()) - { - case xlnt::color::type::theme: - serializer.attribute("theme", std::to_string(color.get_theme().get_index())); - break; - - case xlnt::color::type::indexed: - serializer.attribute("indexed", std::to_string(color.get_indexed().get_index())); - break; - - case xlnt::color::type::rgb: - default: - serializer.attribute("rgb", color.get_rgb().get_hex_string()); - break; - } - - return true; -} - -void write_dxfs(xml::serializer &serializer) -{ - serializer.attribute("count", "0"); -} - -void write_table_styles(xml::serializer &serializer) -{ - serializer.attribute("count", "0"); - serializer.attribute("defaultTableStyle", "TableStyleMedium9"); - serializer.attribute("defaultPivotStyle", "PivotStyleMedium7"); -} - -void write_colors(const std::vector &colors, xml::serializer &serializer) -{ - serializer.start_element("indexedColors"); - - for (auto &c : colors) - { - serializer.start_element("rgbColor"); - serializer.attribute("rgb", c.get_rgb().get_hex_string()); - serializer.end_element(); - } - - serializer.end_element(); + return std::to_string(dt.year) + "-" + + fill(std::to_string(dt.month)) + "-" + + fill(std::to_string(dt.day)) + "T" + + fill(std::to_string(dt.hour)) + ":" + + fill(std::to_string(dt.minute)) + ":" + + fill(std::to_string(dt.second)) + "Z"; } } // namespace @@ -288,31 +74,35 @@ void xlsx_producer::write(std::vector &destination) void xlsx_producer::populate_archive() { - write_manifest(); + write_content_types(); + + const auto root_rels = source_.get_manifest().get_relationships(path("/")); + write_relationships(root_rels, path("/")); - for (auto &rel : source_.impl().manifest_.get_relationships(path("/"))) + for (auto &rel : root_rels) { std::ostringstream serializer_stream; xml::serializer serializer(serializer_stream, rel.get_target().get_path().string()); + serializer_ = &serializer; bool write_document = true; switch (rel.get_type()) { case relationship::type::core_properties: - write_core_properties(rel, serializer); + write_core_properties(rel); break; case relationship::type::extended_properties: - write_extended_properties(rel, serializer); + write_extended_properties(rel); break; case relationship::type::custom_properties: - write_custom_properties(rel, serializer); + write_custom_properties(rel); break; case relationship::type::office_document: - write_workbook(rel, serializer); + write_workbook(rel); break; case relationship::type::thumbnail: @@ -338,7 +128,7 @@ void xlsx_producer::populate_archive() // Package Parts -void xlsx_producer::write_manifest() +void xlsx_producer::write_content_types() { std::ostringstream content_types_stream; xml::serializer content_types_serializer(content_types_stream, "[Content_Types].xml"); @@ -367,42 +157,19 @@ void xlsx_producer::write_manifest() } content_types_serializer.end_element(xmlns, "Types"); - - for (const auto &part : source_.get_manifest().get_parts()) - { - auto part_rels = source_.get_manifest().get_relationships(part); - - if (part_rels.empty()) continue; - - path parent = part.parent(); - - if (parent.is_absolute()) - { - parent = path(parent.string().substr(1)); - } - - std::ostringstream rels_stream; - path rels_path(parent.append("_rels").append(part.filename() + ".rels").string()); - xml::serializer rels_serializer(rels_stream, rels_path.string()); - - write_relationships(part_rels, rels_serializer); - - destination_.write_string(rels_stream.str(), rels_path); - } - destination_.write_string(content_types_stream.str(), path("[Content_Types].xml")); } -void xlsx_producer::write_extended_properties(const relationship &rel, xml::serializer &serializer) +void xlsx_producer::write_extended_properties(const relationship &rel) { - serializer.start_element("Properties"); + serializer().start_element("Properties"); - serializer.namespace_decl("http://schemas.openxmlformats.org/officeDocument/2006/extended-properties", "xmlns"); - serializer.namespace_decl("http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes", "vt"); + serializer().namespace_decl("http://schemas.openxmlformats.org/officeDocument/2006/extended-properties", "xmlns"); + serializer().namespace_decl("http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes", "vt"); - serializer.element("Application", source_.get_application()); - serializer.element("DocSecurity", std::to_string(source_.get_doc_security())); - serializer.element("ScaleCrop", source_.get_scale_crop() ? "true" : "false"); + serializer().element("Application", source_.get_application()); + serializer().element("DocSecurity", std::to_string(source_.get_doc_security())); + serializer().element("ScaleCrop", source_.get_scale_crop() ? "true" : "false"); /* auto heading_pairs_node = properties_node.append_child("HeadingPairs"); auto heading_pairs_vector_node = heading_pairs_node.append_child("vt:vector"); @@ -437,7 +204,7 @@ void xlsx_producer::write_extended_properties(const relationship &rel, xml::seri */ } -void xlsx_producer::write_core_properties(const relationship &rel, xml::serializer &serializer) +void xlsx_producer::write_core_properties(const relationship &rel) { /* auto core_properties_node = root.append_child("cp:coreProperties"); @@ -468,14 +235,14 @@ void xlsx_producer::write_core_properties(const relationship &rel, xml::serializ */ } -void xlsx_producer::write_custom_properties(const relationship &rel, xml::serializer &serializer) +void xlsx_producer::write_custom_properties(const relationship &rel) { - serializer.element("Properties"); + serializer().element("Properties"); } // Write SpreadsheetML-Specific Package Parts -void xlsx_producer::write_workbook(const relationship &rel, xml::serializer &serializer) +void xlsx_producer::write_workbook(const relationship &rel) { std::size_t num_visible = 0; bool any_defined_names = false; @@ -500,15 +267,15 @@ void xlsx_producer::write_workbook(const relationship &rel, xml::serializer &ser const auto xmlns = std::string("http://schemas.openxmlformats.org/spreadsheetml/2006/main"); - serializer.start_element(xmlns, "workbook"); - serializer.namespace_decl(xmlns, ""); - serializer.namespace_decl("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "r"); + serializer().start_element(xmlns, "workbook"); + serializer().namespace_decl(xmlns, ""); + serializer().namespace_decl("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "r"); if (source_.x15_enabled()) { - serializer.namespace_decl("http://schemas.openxmlformats.org/markup-compatibility/2006", "mc"); - serializer.attribute("mc:Ignorable", "x15"); - serializer.namespace_decl("http://schemas.microsoft.com/office/spreadsheetml/2010/11/main", "x15"); + serializer().namespace_decl("http://schemas.openxmlformats.org/markup-compatibility/2006", "mc"); + serializer().attribute("mc:Ignorable", "x15"); + serializer().namespace_decl("http://schemas.microsoft.com/office/spreadsheetml/2010/11/main", "x15"); } /* if (source_.has_file_version()) @@ -573,7 +340,7 @@ void xlsx_producer::write_workbook(const relationship &rel, xml::serializer &ser } */ - serializer.start_element(xmlns, "sheets"); + serializer().start_element(xmlns, "sheets"); /* if (any_defined_names) { @@ -586,16 +353,16 @@ void xlsx_producer::write_workbook(const relationship &rel, xml::serializer &ser auto sheet_rel_id = source_.d_->sheet_title_rel_id_map_[ws.get_title()]; auto sheet_rel = source_.d_->manifest_.get_relationship(rel.get_source().get_path(), sheet_rel_id); - serializer.start_element(xmlns, "sheet"); - serializer.attribute("name", ws.get_title()); - serializer.attribute("sheetId", std::to_string(ws.get_id())); + serializer().start_element(xmlns, "sheet"); + serializer().attribute("name", ws.get_title()); + serializer().attribute("sheetId", std::to_string(ws.get_id())); if (ws.has_page_setup() && ws.get_sheet_state() == xlnt::sheet_state::hidden) { - serializer.attribute("state", "hidden"); + serializer().attribute("state", "hidden"); } - serializer.attribute("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "id", sheet_rel_id); + serializer().attribute("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "id", sheet_rel_id); /* if (ws.has_auto_filter()) { @@ -609,7 +376,7 @@ void xlsx_producer::write_workbook(const relationship &rel, xml::serializer &ser } */ - serializer.end_element(xmlns, "sheet"); + serializer().end_element(xmlns, "sheet"); } /* if (source_.has_calculation_properties()) @@ -650,70 +417,74 @@ void xlsx_producer::write_workbook(const relationship &rel, xml::serializer &ser } */ - serializer.end_element(xmlns, "sheets"); - serializer.end_element(xmlns, "workbook"); + serializer().end_element(xmlns, "sheets"); + serializer().end_element(xmlns, "workbook"); - for (const auto &child_rel : source_.get_manifest().get_relationships(rel.get_target().get_path())) + auto workbook_rels = source_.get_manifest().get_relationships(rel.get_target().get_path()); + write_relationships(workbook_rels, rel.get_target().get_path()); + + for (const auto &child_rel : workbook_rels) { std::ostringstream child_stream; xml::serializer child_serializer(child_stream, child_rel.get_target().get_path().string()); + serializer_ = &child_serializer; switch (child_rel.get_type()) { case relationship::type::calculation_chain: - write_calculation_chain(child_rel, child_serializer); + write_calculation_chain(child_rel); break; case relationship::type::chartsheet: - write_chartsheet(child_rel, child_serializer); + write_chartsheet(child_rel); break; case relationship::type::connections: - write_connections(child_rel, child_serializer); + write_connections(child_rel); break; case relationship::type::custom_xml_mappings: - write_custom_xml_mappings(child_rel, child_serializer); + write_custom_xml_mappings(child_rel); break; case relationship::type::dialogsheet: - write_dialogsheet(child_rel, child_serializer); + write_dialogsheet(child_rel); break; case relationship::type::external_workbook_references: - write_external_workbook_references(child_rel, child_serializer); + write_external_workbook_references(child_rel); break; case relationship::type::metadata: - write_metadata(child_rel, child_serializer); + write_metadata(child_rel); break; case relationship::type::pivot_table: - write_pivot_table(child_rel, child_serializer); + write_pivot_table(child_rel); break; case relationship::type::shared_string_table: - write_shared_string_table(child_rel, child_serializer); + write_shared_string_table(child_rel); break; case relationship::type::shared_workbook_revision_headers: - write_shared_workbook_revision_headers(child_rel, child_serializer); + write_shared_workbook_revision_headers(child_rel); break; case relationship::type::styles: - write_styles(child_rel, child_serializer); + write_styles(child_rel); break; case relationship::type::theme: - write_theme(child_rel, child_serializer); + write_theme(child_rel); break; case relationship::type::volatile_dependencies: - write_volatile_dependencies(child_rel, child_serializer); + write_volatile_dependencies(child_rel); break; case relationship::type::worksheet: - write_worksheet(child_rel, child_serializer); + write_worksheet(child_rel); break; default: @@ -727,49 +498,49 @@ void xlsx_producer::write_workbook(const relationship &rel, xml::serializer &ser // Write Workbook Relationship Target Parts -void xlsx_producer::write_calculation_chain(const relationship &rel, xml::serializer &serializer) +void xlsx_producer::write_calculation_chain(const relationship &rel) { - serializer.start_element("calcChain"); + serializer().start_element("calcChain"); } -void xlsx_producer::write_chartsheet(const relationship &rel, xml::serializer &serializer) +void xlsx_producer::write_chartsheet(const relationship &rel) { - serializer.start_element("chartsheet"); + serializer().start_element("chartsheet"); } -void xlsx_producer::write_connections(const relationship &rel, xml::serializer &serializer) +void xlsx_producer::write_connections(const relationship &rel) { - serializer.start_element("connections"); + serializer().start_element("connections"); } -void xlsx_producer::write_custom_xml_mappings(const relationship &rel, xml::serializer &serializer) +void xlsx_producer::write_custom_xml_mappings(const relationship &rel) { - serializer.start_element("MapInfo"); + serializer().start_element("MapInfo"); } -void xlsx_producer::write_dialogsheet(const relationship &rel, xml::serializer &serializer) +void xlsx_producer::write_dialogsheet(const relationship &rel) { - serializer.start_element("dialogsheet"); + serializer().start_element("dialogsheet"); } -void xlsx_producer::write_external_workbook_references(const relationship &rel, xml::serializer &serializer) +void xlsx_producer::write_external_workbook_references(const relationship &rel) { - serializer.start_element("externalLink"); + serializer().start_element("externalLink"); } -void xlsx_producer::write_metadata(const relationship &rel, xml::serializer &serializer) +void xlsx_producer::write_metadata(const relationship &rel) { - serializer.start_element("metadata"); + serializer().start_element("metadata"); } -void xlsx_producer::write_pivot_table(const relationship &rel, xml::serializer &serializer) +void xlsx_producer::write_pivot_table(const relationship &rel) { - serializer.start_element("pivotTableDefinition"); + serializer().start_element("pivotTableDefinition"); } -void xlsx_producer::write_shared_string_table(const relationship &rel, xml::serializer &serializer) +void xlsx_producer::write_shared_string_table(const relationship &rel) { - serializer.start_element("sst"); + serializer().start_element("sst"); /* sst_node.append_attribute("xmlns").set_value("http://schemas.openxmlformats.org/spreadsheetml/2006/main"); std::size_t string_count = 0; @@ -843,24 +614,24 @@ void xlsx_producer::write_shared_string_table(const relationship &rel, xml::seri */ } -void xlsx_producer::write_shared_workbook_revision_headers(const relationship &rel, xml::serializer &serializer) +void xlsx_producer::write_shared_workbook_revision_headers(const relationship &rel) { - serializer.start_element("headers"); + serializer().start_element("headers"); } -void xlsx_producer::write_shared_workbook(const relationship &rel, xml::serializer &serializer) +void xlsx_producer::write_shared_workbook(const relationship &rel) { - serializer.start_element("revisions"); + serializer().start_element("revisions"); } -void xlsx_producer::write_shared_workbook_user_data(const relationship &rel, xml::serializer &serializer) +void xlsx_producer::write_shared_workbook_user_data(const relationship &rel) { - serializer.start_element("users"); + serializer().start_element("users"); } -void xlsx_producer::write_styles(const relationship &rel, xml::serializer &serializer) +void xlsx_producer::write_styles(const relationship &rel) { - serializer.start_element("styleSheet"); + serializer().start_element("styleSheet"); /* // Namespaces @@ -1309,9 +1080,9 @@ void xlsx_producer::write_styles(const relationship &rel, xml::serializer &seria */ } -void xlsx_producer::write_theme(const relationship &rel, xml::serializer &serializer) +void xlsx_producer::write_theme(const relationship &rel) { - serializer.start_element("a:theme"); + serializer().start_element("a:theme"); /* theme_node.append_attribute("xmlns:a").set_value(constants::get_namespace("drawingml").c_str()); theme_node.append_attribute("name").set_value("Office Theme"); @@ -1618,12 +1389,12 @@ void xlsx_producer::write_theme(const relationship &rel, xml::serializer &serial */ } -void xlsx_producer::write_volatile_dependencies(const relationship &rel, xml::serializer &serializer) +void xlsx_producer::write_volatile_dependencies(const relationship &rel) { - serializer.start_element("volTypes"); + serializer().start_element("volTypes"); } -void xlsx_producer::write_worksheet(const relationship &rel, xml::serializer &serializer) +void xlsx_producer::write_worksheet(const relationship &rel) { auto title = std::find_if(source_.d_->sheet_title_rel_id_map_.begin(), source_.d_->sheet_title_rel_id_map_.end(), @@ -1636,15 +1407,15 @@ void xlsx_producer::write_worksheet(const relationship &rel, xml::serializer &se const auto xmlns = std::string("http://schemas.openxmlformats.org/spreadsheetml/2006/main"); - serializer.start_element(xmlns, "worksheet"); - serializer.namespace_decl(xmlns, ""); - serializer.namespace_decl("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "r"); + serializer().start_element(xmlns, "worksheet"); + serializer().namespace_decl(xmlns, ""); + serializer().namespace_decl("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "r"); if (ws.x14ac_enabled()) { - serializer.namespace_decl("http://schemas.openxmlformats.org/markup-compatibility/2006", "mc"); - serializer.attribute("mc:Ignorable", "x14ac"); - serializer.namespace_decl("http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac", "x14ac"); + serializer().namespace_decl("http://schemas.openxmlformats.org/markup-compatibility/2006", "mc"); + serializer().attribute("mc:Ignorable", "x14ac"); + serializer().namespace_decl("http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac", "x14ac"); } /* if (ws.has_page_setup()) @@ -1786,7 +1557,7 @@ void xlsx_producer::write_worksheet(const relationship &rel, xml::serializer &se std::unordered_map hyperlink_references; - serializer.start_element(xmlns, "sheetData"); + serializer().start_element(xmlns, "sheetData"); const auto &shared_strings = ws.get_workbook().get_shared_strings(); /* for (auto row : ws.rows()) @@ -1934,7 +1705,7 @@ void xlsx_producer::write_worksheet(const relationship &rel, xml::serializer &se } } */ - serializer.end_element(); + serializer().end_element(); /* if (ws.has_auto_filter()) { @@ -2055,32 +1826,32 @@ void xlsx_producer::write_worksheet(const relationship &rel, xml::serializer &se } */ - serializer.end_element(); + serializer().end_element(); } // Sheet Relationship Target Parts -void xlsx_producer::write_comments(const relationship &rel, xml::serializer &serializer) +void xlsx_producer::write_comments(const relationship &rel) { - serializer.start_element("comments"); + serializer().start_element("comments"); } -void xlsx_producer::write_drawings(const relationship &rel, xml::serializer &serializer) +void xlsx_producer::write_drawings(const relationship &rel) { - serializer.start_element("wsDr"); + serializer().start_element("wsDr"); } // Other Parts -void xlsx_producer::write_custom_property(xml::serializer &serializer) +void xlsx_producer::write_custom_property() { } -void xlsx_producer::write_unknown_parts(xml::serializer &serializer) +void xlsx_producer::write_unknown_parts() { } -void xlsx_producer::write_unknown_relationships(xml::serializer &serializer) +void xlsx_producer::write_unknown_relationships() { } @@ -2091,6 +1862,11 @@ void xlsx_producer::write_thumbnail(const relationship &rel) destination_.write_string(thumbnail_string, rel.get_target().get_path()); } +xml::serializer &xlsx_producer::serializer() +{ + return *serializer_; +} + std::string xlsx_producer::write_bool(bool boolean) const { if (source_.d_->short_bools_) @@ -2101,5 +1877,92 @@ std::string xlsx_producer::write_bool(bool boolean) const return boolean ? "true" : "false"; } + +void xlsx_producer::write_relationships(const std::vector &relationships, const path &part) +{ + path parent = part.parent(); + + if (parent.is_absolute()) + { + parent = path(parent.string().substr(1)); + } + + std::ostringstream rels_stream; + path rels_path(parent.append("_rels").append(part.filename() + ".rels").string()); + xml::serializer rels_serializer(rels_stream, rels_path.string()); + + const auto xmlns = xlnt::constants::get_namespace("relationships"); + + rels_serializer.start_element(xmlns, "Relationships"); + rels_serializer.namespace_decl(xmlns, ""); + + for (const auto &relationship : relationships) + { + rels_serializer.start_element(xmlns, "Relationship"); + + rels_serializer.attribute("Id", relationship.get_id()); + rels_serializer.attribute("Type", relationship.get_type()); + rels_serializer.attribute("Target", relationship.get_target().get_path().string()); + + if (relationship.get_target_mode() == xlnt::target_mode::external) + { + rels_serializer.attribute("TargetMode", "External"); + } + + rels_serializer.end_element(xmlns, "Relationship"); + } + + rels_serializer.end_element(xmlns, "Relationships"); + destination_.write_string(rels_stream.str(), rels_path); +} + + +bool xlsx_producer::write_color(const xlnt::color &color) +{ + switch (color.get_type()) + { + case xlnt::color::type::theme: + serializer().attribute("theme", std::to_string(color.get_theme().get_index())); + break; + + case xlnt::color::type::indexed: + serializer().attribute("indexed", std::to_string(color.get_indexed().get_index())); + break; + + case xlnt::color::type::rgb: + default: + serializer().attribute("rgb", color.get_rgb().get_hex_string()); + break; + } + + return true; +} + +void xlsx_producer::write_dxfs() +{ + serializer().attribute("count", "0"); +} + +void xlsx_producer::write_table_styles() +{ + serializer().attribute("count", "0"); + serializer().attribute("defaultTableStyle", "TableStyleMedium9"); + serializer().attribute("defaultPivotStyle", "PivotStyleMedium7"); +} + +void xlsx_producer::write_colors(const std::vector &colors) +{ + serializer().start_element("indexedColors"); + + for (auto &c : colors) + { + serializer().start_element("rgbColor"); + serializer().attribute("rgb", c.get_rgb().get_hex_string()); + serializer().end_element(); + } + + serializer().end_element(); +} + } // namespace detail } // namepsace xlnt diff --git a/source/detail/xlsx_producer.hpp b/source/detail/xlsx_producer.hpp index 3f2d82af..e52967e7 100644 --- a/source/detail/xlsx_producer.hpp +++ b/source/detail/xlsx_producer.hpp @@ -31,8 +31,13 @@ #include #include +namespace xml { +class serializer; +} // namespace xml + namespace xlnt { +class color; class path; class relationship; class workbook; @@ -62,46 +67,46 @@ private: // Package Parts - void write_manifest(); - void write_core_properties(const relationship &rel, xml::serializer &serializer); - void write_extended_properties(const relationship &rel, xml::serializer &serializer); - void write_custom_properties(const relationship &rel, xml::serializer &serializer); + void write_content_types(); + void write_core_properties(const relationship &rel); + void write_extended_properties(const relationship &rel); + void write_custom_properties(const relationship &rel); void write_thumbnail(const relationship &rel); // SpreadsheetML-Specific Package Parts - void write_workbook(const relationship &rel, xml::serializer &serializer); + void write_workbook(const relationship &rel); // Workbook Relationship Target Parts - void write_calculation_chain(const relationship &rel, xml::serializer &serializer); - void write_connections(const relationship &rel, xml::serializer &serializer); - void write_custom_xml_mappings(const relationship &rel, xml::serializer &serializer); - void write_external_workbook_references(const relationship &rel, xml::serializer &serializer); - void write_metadata(const relationship &rel, xml::serializer &serializer); - void write_pivot_table(const relationship &rel, xml::serializer &serializer); - void write_shared_string_table(const relationship &rel, xml::serializer &serializer); - void write_shared_workbook_revision_headers(const relationship &rel, xml::serializer &serializer); - void write_shared_workbook(const relationship &rel, xml::serializer &serializer); - void write_shared_workbook_user_data(const relationship &rel, xml::serializer &serializer); - void write_styles(const relationship &rel, xml::serializer &serializer); - void write_theme(const relationship &rel, xml::serializer &serializer); - void write_volatile_dependencies(const relationship &rel, xml::serializer &serializer); + void write_calculation_chain(const relationship &rel); + void write_connections(const relationship &rel); + void write_custom_xml_mappings(const relationship &rel); + void write_external_workbook_references(const relationship &rel); + void write_metadata(const relationship &rel); + void write_pivot_table(const relationship &rel); + void write_shared_string_table(const relationship &rel); + void write_shared_workbook_revision_headers(const relationship &rel); + void write_shared_workbook(const relationship &rel); + void write_shared_workbook_user_data(const relationship &rel); + void write_styles(const relationship &rel); + void write_theme(const relationship &rel); + void write_volatile_dependencies(const relationship &rel); - void write_chartsheet(const relationship &rel, xml::serializer &serializer); - void write_dialogsheet(const relationship &rel, xml::serializer &serializer); - void write_worksheet(const relationship &rel, xml::serializer &serializer); + void write_chartsheet(const relationship &rel); + void write_dialogsheet(const relationship &rel); + void write_worksheet(const relationship &rel); // Sheet Relationship Target Parts - void write_comments(const relationship &rel, xml::serializer &serializer); - void write_drawings(const relationship &rel, xml::serializer &serializer); + void write_comments(const relationship &rel); + void write_drawings(const relationship &rel); // Other Parts - void write_custom_property(xml::serializer &serializer); - void write_unknown_parts(xml::serializer &serializer); - void write_unknown_relationships(xml::serializer &serializer); + void write_custom_property(); + void write_unknown_parts(); + void write_unknown_relationships(); // Helpers @@ -111,6 +116,18 @@ private: /// we're trying to match. /// std::string write_bool(bool boolean) const; + + void write_relationships(const std::vector &relationships, const path &part); + bool write_color(const xlnt::color &color); + void write_dxfs(); + void write_table_styles(); + void write_colors(const std::vector &colors); + + /// + /// Dereference serializer_ pointer and return a reference to the object. + /// This is called by internal methods so that we can use . instead of ->. + /// + xml::serializer &serializer(); /// /// A reference to the workbook which is the object of read/write operations. @@ -122,6 +139,12 @@ private: /// will be written. /// zip_file destination_; + + /// + /// Instead of passing the current serializer into part serialization methods, + /// store pointer in this field and access it in methods with xlsx_producer::serializer(). + /// + xml::serializer *serializer_; }; } // namespace detail