diff --git a/source/detail/xlsx_consumer.cpp b/source/detail/xlsx_consumer.cpp index 439cf287..2a5d6fe3 100644 --- a/source/detail/xlsx_consumer.cpp +++ b/source/detail/xlsx_consumer.cpp @@ -24,14 +24,14 @@ #include #include // for std::accumulate -#include #include #include #include +#include #include #include -#include #include +#include #include #include #include @@ -41,7 +41,7 @@ namespace std { template <> struct hash { - std::size_t operator()(const xml::qname& k) const + std::size_t operator()(const xml::qname &k) const { static std::hash hasher; return hasher(k.string()); @@ -54,63 +54,63 @@ namespace { bool is_true(const std::string &bool_string) { - return bool_string == "1" || bool_string == "true"; + return bool_string == "1" || bool_string == "true"; } std::size_t string_to_size_t(const std::string &s) { #if ULLONG_MAX == SIZE_MAX - return std::stoull(s); + return std::stoull(s); #else - return std::stoul(s); + return std::stoul(s); #endif } xlnt::datetime w3cdtf_to_datetime(const std::string &string) { - xlnt::datetime result(1900, 1, 1); - auto separator_index = string.find('-'); - result.year = std::stoi(string.substr(0, separator_index)); - result.month = std::stoi(string.substr(separator_index + 1, string.find('-', separator_index + 1))); - separator_index = string.find('-', separator_index + 1); - result.day = std::stoi(string.substr(separator_index + 1, string.find('T', separator_index + 1))); - separator_index = string.find('T', separator_index + 1); - result.hour = std::stoi(string.substr(separator_index + 1, string.find(':', separator_index + 1))); - separator_index = string.find(':', separator_index + 1); - result.minute = std::stoi(string.substr(separator_index + 1, string.find(':', separator_index + 1))); - separator_index = string.find(':', separator_index + 1); - result.second = std::stoi(string.substr(separator_index + 1, string.find('Z', separator_index + 1))); - return result; + xlnt::datetime result(1900, 1, 1); + auto separator_index = string.find('-'); + result.year = std::stoi(string.substr(0, separator_index)); + result.month = std::stoi(string.substr(separator_index + 1, string.find('-', separator_index + 1))); + separator_index = string.find('-', separator_index + 1); + result.day = std::stoi(string.substr(separator_index + 1, string.find('T', separator_index + 1))); + separator_index = string.find('T', separator_index + 1); + result.hour = std::stoi(string.substr(separator_index + 1, string.find(':', separator_index + 1))); + separator_index = string.find(':', separator_index + 1); + result.minute = std::stoi(string.substr(separator_index + 1, string.find(':', separator_index + 1))); + separator_index = string.find(':', separator_index + 1); + result.second = std::stoi(string.substr(separator_index + 1, string.find('Z', separator_index + 1))); + return result; } xlnt::color read_color(xml::parser &parser) { - xlnt::color result; + xlnt::color result; - if (parser.attribute_present("auto")) - { - return result; - } + if (parser.attribute_present("auto")) + { + return result; + } - if (parser.attribute_present("rgb")) - { - result = xlnt::rgb_color(parser.attribute("rgb")); - } - else if (parser.attribute_present("theme")) - { - result = xlnt::theme_color(string_to_size_t(parser.attribute("theme"))); - } - else if (parser.attribute_present("indexed")) - { - result = xlnt::indexed_color(string_to_size_t(parser.attribute("indexed"))); - } + if (parser.attribute_present("rgb")) + { + result = xlnt::rgb_color(parser.attribute("rgb")); + } + else if (parser.attribute_present("theme")) + { + result = xlnt::theme_color(string_to_size_t(parser.attribute("theme"))); + } + else if (parser.attribute_present("indexed")) + { + result = xlnt::indexed_color(string_to_size_t(parser.attribute("indexed"))); + } - if (parser.attribute_present("tint")) - { - result.set_tint(parser.attribute("tint", 0.0)); - } + if (parser.attribute_present("tint")) + { + result.set_tint(parser.attribute("tint", 0.0)); + } - return result; + return result; } std::vector read_relationships(const xlnt::path &part, xlnt::detail::ZipFileReader &archive) @@ -128,29 +128,29 @@ std::vector read_relationships(const xlnt::path &part, xlnt: parser.content(xml::content::complex); while (true) - { + { if (parser.peek() == xml::parser::event_type::end_element) break; - + parser.next_expect(xml::parser::event_type::start_element, xmlns, "Relationship"); - relationships.emplace_back(parser.attribute("Id"), + relationships.emplace_back(parser.attribute("Id"), parser.attribute("Type"), source, - xlnt::uri(parser.attribute("Target")), xlnt::target_mode::internal); - parser.next_expect(xml::parser::event_type::end_element, - xlnt::constants::get_namespace("relationships"), "Relationship"); - } - + xlnt::uri(parser.attribute("Target")), + xlnt::target_mode::internal); + parser.next_expect(xml::parser::event_type::end_element, xmlns, "Relationship"); + } + parser.next_expect(xml::parser::event_type::end_element, xmlns, "Relationships"); - return relationships; + return relationships; } void check_document_type(const std::string &document_content_type) { - if (document_content_type != "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml" - && document_content_type != "application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml ") - { - throw xlnt::invalid_file(document_content_type); - } + if (document_content_type != "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml" && + document_content_type != "application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml ") + { + throw xlnt::invalid_file(document_content_type); + } } } // namespace @@ -158,38 +158,39 @@ void check_document_type(const std::string &document_content_type) namespace xlnt { namespace detail { -xlsx_consumer::xlsx_consumer(workbook &target) - : target_(target), - parser_(nullptr) +xlsx_consumer::xlsx_consumer(workbook &target) + : target_(target), + parser_(nullptr) { } void xlsx_consumer::read(std::istream &source) { - archive_.reset(new ZipFileReader(source)); - populate_workbook(); + archive_.reset(new ZipFileReader(source)); + populate_workbook(); } xml::parser &xlsx_consumer::parser() { - return *parser_; + return *parser_; } void xlsx_consumer::read_part(const std::vector &rel_chain) { + // ignore namespace declarations except in parts of these types const auto using_namespaces = std::vector { relationship::type::office_document, relationship::type::stylesheet, relationship::type::chartsheet, - relationship::type::dialogsheet, - relationship::type::worksheet + relationship::type::dialogsheet, + relationship::type::worksheet }; - + auto receive = xml::parser::receive_default; auto receive_namespaces = std::find(using_namespaces.begin(), using_namespaces.end(), rel_chain.back().get_type()) != using_namespaces.end(); - + if (receive_namespaces) { receive |= xml::parser::receive_namespace_decls; @@ -200,135 +201,169 @@ void xlsx_consumer::read_part(const std::vector &rel_chain) auto &stream = archive_->open(part_path.string()); xml::parser parser(stream, part_path.string(), receive); parser_ = &parser; - + switch (rel_chain.back().get_type()) { - case relationship::type::core_properties: - read_core_properties(); - break; + case relationship::type::core_properties: + read_core_properties(); + break; - case relationship::type::extended_properties: - read_extended_properties(); - break; + case relationship::type::extended_properties: + read_extended_properties(); + break; - case relationship::type::custom_properties: - read_custom_property(); - break; + case relationship::type::custom_properties: + read_custom_property(); + break; - case relationship::type::office_document: - check_document_type(manifest.get_content_type(part_path)); - read_workbook(); - break; + case relationship::type::office_document: + read_workbook(); + break; - case relationship::type::connections: - read_connections(); - break; + case relationship::type::connections: + read_connections(); + break; - case relationship::type::custom_xml_mappings: - read_custom_xml_mappings(); - break; + case relationship::type::custom_xml_mappings: + read_custom_xml_mappings(); + break; - case relationship::type::external_workbook_references: - read_external_workbook_references(); - break; + case relationship::type::external_workbook_references: + read_external_workbook_references(); + break; - case relationship::type::metadata: - read_metadata(); - break; + case relationship::type::metadata: + read_metadata(); + break; - case relationship::type::pivot_table: - read_pivot_table(); - break; + case relationship::type::pivot_table: + read_pivot_table(); + break; - case relationship::type::shared_workbook_revision_headers: - read_shared_workbook_revision_headers(); - break; + case relationship::type::shared_workbook_revision_headers: + read_shared_workbook_revision_headers(); + break; - case relationship::type::volatile_dependencies: - read_volatile_dependencies(); - break; + case relationship::type::volatile_dependencies: + read_volatile_dependencies(); + break; - case relationship::type::shared_string_table: - read_shared_string_table(); - break; + case relationship::type::shared_string_table: + read_shared_string_table(); + break; - case relationship::type::stylesheet: - read_stylesheet(); - break; + case relationship::type::stylesheet: + read_stylesheet(); + break; - case relationship::type::theme: - read_theme(); - break; + case relationship::type::theme: + read_theme(); + break; - case relationship::type::chartsheet: - read_chartsheet(rel_chain.back().get_id()); - break; + case relationship::type::chartsheet: + read_chartsheet(rel_chain.back().get_id()); + break; - case relationship::type::dialogsheet: - read_dialogsheet(rel_chain.back().get_id()); - break; + case relationship::type::dialogsheet: + read_dialogsheet(rel_chain.back().get_id()); + break; - case relationship::type::worksheet: - read_worksheet(rel_chain.back().get_id()); - break; + case relationship::type::worksheet: + read_worksheet(rel_chain.back().get_id()); + break; - case relationship::type::thumbnail: break; - case relationship::type::calculation_chain: break; - case relationship::type::hyperlink: break; - case relationship::type::comments: break; - case relationship::type::vml_drawing: break; - case relationship::type::unknown: break; - case relationship::type::printer_settings: break; - case relationship::type::custom_property: break; - case relationship::type::drawings: break; - case relationship::type::pivot_table_cache_definition: break; - case relationship::type::pivot_table_cache_records: break; - case relationship::type::query_table: break; - case relationship::type::shared_workbook: break; - case relationship::type::revision_log: break; - case relationship::type::shared_workbook_user_data: break; - case relationship::type::single_cell_table_definitions: break; - case relationship::type::table_definition: break; - case relationship::type::image: break; + case relationship::type::thumbnail: + break; + + case relationship::type::calculation_chain: + read_calculation_chain(); + break; + + case relationship::type::hyperlink: + break; + + case relationship::type::comments: + break; + + case relationship::type::vml_drawing: + break; + + case relationship::type::unknown: + break; + + case relationship::type::printer_settings: + break; + + case relationship::type::custom_property: + break; + + case relationship::type::drawings: + break; + + case relationship::type::pivot_table_cache_definition: + break; + + case relationship::type::pivot_table_cache_records: + break; + + case relationship::type::query_table: + break; + + case relationship::type::shared_workbook: + break; + + case relationship::type::revision_log: + break; + + case relationship::type::shared_workbook_user_data: + break; + + case relationship::type::single_cell_table_definitions: + break; + + case relationship::type::table_definition: + break; + + case relationship::type::image: + break; } - + parser_ = nullptr; } void xlsx_consumer::populate_workbook() { - target_.clear(); + target_.clear(); + + read_manifest(); + auto &manifest = target_.get_manifest(); - read_manifest(); - auto &manifest = target_.get_manifest(); - auto package_parts = std::vector { relationship::type::core_properties, - relationship::type::extended_properties, - relationship::type::custom_properties, - relationship::type::office_document, - relationship::type::connections, - relationship::type::custom_xml_mappings, - relationship::type::external_workbook_references, - relationship::type::metadata, - relationship::type::pivot_table, - relationship::type::shared_workbook_revision_headers, - relationship::type::volatile_dependencies + relationship::type::extended_properties, + relationship::type::custom_properties, + relationship::type::office_document, + relationship::type::connections, + relationship::type::custom_xml_mappings, + relationship::type::external_workbook_references, + relationship::type::metadata, + relationship::type::pivot_table, + relationship::type::shared_workbook_revision_headers, + relationship::type::volatile_dependencies }; - + auto root_path = path("/"); for (auto rel_type : package_parts) { if (manifest.has_relationship(root_path, rel_type)) { - read_part({ manifest.get_relationship(root_path, rel_type) }); + read_part({manifest.get_relationship(root_path, rel_type)}); } - } + } - const auto workbook_rel = manifest.get_relationship(root_path, - relationship::type::office_document); + const auto workbook_rel = manifest.get_relationship(root_path, relationship::type::office_document); const auto workbook_parts_first = std::vector { @@ -341,7 +376,7 @@ void xlsx_consumer::populate_workbook() { if (manifest.has_relationship(workbook_rel.get_target().get_path(), rel_type)) { - read_part({ workbook_rel, manifest.get_relationship(workbook_rel.get_target().get_path(), rel_type) }); + read_part({workbook_rel, manifest.get_relationship(workbook_rel.get_target().get_path(), rel_type)}); } } @@ -358,7 +393,7 @@ void xlsx_consumer::populate_workbook() { for (auto rel : manifest.get_relationships(workbook_rel.get_target().get_path(), rel_type)) { - read_part({ workbook_rel, rel }); + read_part({workbook_rel, rel}); } } } @@ -368,15 +403,15 @@ void xlsx_consumer::populate_workbook() void xlsx_consumer::read_manifest() { - path package_rels_path("_rels/.rels"); + path package_rels_path("_rels/.rels"); - if (!archive_->has_file(package_rels_path.string())) - { - throw invalid_file("missing package rels"); - } + if (!archive_->has_file(package_rels_path.string())) + { + throw invalid_file("missing package rels"); + } - auto package_rels = read_relationships(package_rels_path, *archive_); - auto &manifest = target_.get_manifest(); + auto package_rels = read_relationships(package_rels_path, *archive_); + auto &manifest = target_.get_manifest(); static const auto &xmlns = constants::get_namespace("content-types"); @@ -385,58 +420,70 @@ void xlsx_consumer::read_manifest() parser.content(xml::content::complex); while (true) - { + { if (parser.peek() == xml::parser::event_type::end_element) break; - + parser.next_expect(xml::parser::event_type::start_element); - + if (parser.name() == "Default") { - manifest.register_default_type(parser.attribute("Extension"), - parser.attribute("ContentType")); + auto extension = parser.attribute("Extension"); + auto content_type = parser.attribute("ContentType"); + manifest.register_default_type(extension, content_type); + parser.next_expect(xml::parser::event_type::end_element, xmlns, "Default"); } else if (parser.name() == "Override") { - manifest.register_override_type(path(parser.attribute("PartName")), - parser.attribute("ContentType")); + auto part_name = parser.attribute("PartName"); + auto content_type = parser.attribute("ContentType"); + manifest.register_override_type(path(part_name), content_type); + parser.next_expect(xml::parser::event_type::end_element, xmlns, "Override"); } - } - + } + parser.next_expect(xml::parser::event_type::end_element, xmlns, "Types"); - for (const auto &package_rel : package_rels) - { - manifest.register_relationship(uri("/"), + for (const auto &package_rel : package_rels) + { + if (package_rel.get_type() == relationship::type::office_document) + { + auto content_type = manifest.get_content_type(manifest.canonicalize({ package_rel })); + check_document_type(content_type); + } + + manifest.register_relationship(uri("/"), package_rel.get_type(), - package_rel.get_target(), - package_rel.get_target_mode(), - package_rel.get_id()); - } + package_rel.get_target(), + package_rel.get_target_mode(), + package_rel.get_id()); + } - for (const auto &relationship_source_string : archive_->files()) - { - auto relationship_source = path(relationship_source_string); + for (const auto &relationship_source_string : archive_->files()) + { + auto relationship_source = path(relationship_source_string); - if (relationship_source == path("_rels/.rels") - || relationship_source.extension() != "rels") continue; + if (relationship_source == path("_rels/.rels") || relationship_source.extension() != "rels") continue; - path part(relationship_source.parent().parent()); - part = part.append(relationship_source.split_extension().first); - uri source(part.string()); + path part(relationship_source.parent().parent()); + part = part.append(relationship_source.split_extension().first); + uri source(part.string()); - path source_directory = part.parent(); + path source_directory = part.parent(); - auto part_rels = read_relationships(relationship_source, *archive_); + auto part_rels = read_relationships(relationship_source, *archive_); - for (const auto &part_rel : part_rels) - { - path target_path(source_directory.append(part_rel.get_target().get_path())); - manifest.register_relationship(source, part_rel.get_type(), - part_rel.get_target(), part_rel.get_target_mode(), part_rel.get_id()); - } - } + for (const auto &part_rel : part_rels) + { + path target_path(source_directory.append(part_rel.get_target().get_path())); + manifest.register_relationship(source, + part_rel.get_type(), + part_rel.get_target(), + part_rel.get_target_mode(), + part_rel.get_id()); + } + } } void xlsx_consumer::read_extended_properties() @@ -446,78 +493,48 @@ void xlsx_consumer::read_extended_properties() parser().next_expect(xml::parser::event_type::start_element, xmlns, "Properties"); parser().content(xml::parser::content_type::complex); - + read_block( { { xml::qname(xmlns, "Application"), - [](xlsx_consumer &c) - { - c.target_.set_application(c.read_text()); - } + [](xlsx_consumer &c) { c.target_.set_application(c.read_text()); } }, { xml::qname(xmlns, "DocSecurity"), - [](xlsx_consumer &c) - { - c.target_.set_doc_security(std::stoi(c.read_text())); - } + [](xlsx_consumer &c) { c.target_.set_doc_security(std::stoi(c.read_text())); } }, { xml::qname(xmlns, "ScaleCrop"), - [](xlsx_consumer &c) - { - c.target_.set_scale_crop(is_true(c.read_text())); - } + [](xlsx_consumer &c) { c.target_.set_scale_crop(is_true(c.read_text())); } }, { xml::qname(xmlns, "Company"), - [](xlsx_consumer &c) - { - c.target_.set_company(c.read_text()); - } + [](xlsx_consumer &c) { c.target_.set_company(c.read_text()); } }, { xml::qname(xmlns, "SharedDoc"), - [](xlsx_consumer &c) - { - c.target_.set_shared_doc(is_true(c.read_text())); - } + [](xlsx_consumer &c) { c.target_.set_shared_doc(is_true(c.read_text())); } }, { xml::qname(xmlns, "HyperlinksChanged"), - [](xlsx_consumer &c) - { - c.target_.set_hyperlinks_changed(is_true(c.read_text())); - } + [](xlsx_consumer &c) { c.target_.set_hyperlinks_changed(is_true(c.read_text())); } }, { xml::qname(xmlns, "AppVersion"), - [](xlsx_consumer &c) - { - c.target_.set_app_version(c.read_text()); - } + [](xlsx_consumer &c) { c.target_.set_app_version(c.read_text()); } }, { xml::qname(xmlns, "LinksUpToDate"), - [](xlsx_consumer &c) - { - c.target_.set_links_up_to_date(is_true(c.read_text())); - } + [](xlsx_consumer &c) { c.target_.set_links_up_to_date(is_true(c.read_text())); } }, { xml::qname(xmlns, "Template"), - [](xlsx_consumer &c) - { - c.read_text(); - } + [](xlsx_consumer &c) { c.read_text(); } }, { xml::qname(xmlns, "TotalTime"), - [](xlsx_consumer &c) - { - c.read_text(); - } + [](xlsx_consumer &c) { c.read_text(); } }, { xml::qname(xmlns, "HeadingPairs"), @@ -556,7 +573,7 @@ void xlsx_consumer::read_extended_properties() auto size = c.parser().attribute("size"); c.parser().attribute("baseType"); - + for (auto i = std::size_t(0); i < size; ++i) { c.parser().next_expect(xml::parser::event_type::start_element, xmlns_vt, "lpstr"); @@ -567,7 +584,7 @@ void xlsx_consumer::read_extended_properties() c.parser().next_expect(xml::parser::event_type::end_element, xmlns_vt, "vector"); } - }, + } }); } @@ -580,11 +597,11 @@ void xlsx_consumer::read_core_properties() parser().next_expect(xml::parser::event_type::start_element, xmlns_cp, "coreProperties"); parser().content(xml::parser::content_type::complex); - + while (true) - { + { if (parser().peek() == xml::parser::event_type::end_element) break; - + parser().next_expect(xml::parser::event_type::start_element); std::string characters; @@ -594,28 +611,28 @@ void xlsx_consumer::read_core_properties() characters = parser().value(); } - if (parser().namespace_() == xmlns_dc && parser().name() == "creator") + if (parser().namespace_() == xmlns_dc && parser().name() == "creator") { target_.set_creator(characters); } - else if (parser().namespace_() == xmlns_cp && parser().name() == "lastModifiedBy") + else if (parser().namespace_() == xmlns_cp && parser().name() == "lastModifiedBy") { target_.set_last_modified_by(characters); } - else if (parser().namespace_() == xmlns_dcterms && parser().name() == "created") + else if (parser().namespace_() == xmlns_dcterms && parser().name() == "created") { parser().attribute(xml::qname(xmlns_xsi, "type")); target_.set_created(w3cdtf_to_datetime(characters)); } - else if (parser().namespace_() == xmlns_dcterms && parser().name() == "modified") + else if (parser().namespace_() == xmlns_dcterms && parser().name() == "modified") { parser().attribute(xml::qname(xmlns_xsi, "type")); target_.set_modified(w3cdtf_to_datetime(characters)); } - + parser().next_expect(xml::parser::event_type::end_element); - } - + } + parser().next_expect(xml::parser::event_type::end_element, xmlns_cp, "coreProperties"); } @@ -637,17 +654,17 @@ void xlsx_consumer::read_workbook() parser().next_expect(xml::parser::event_type::start_element, xmlns, "workbook"); parser().content(xml::parser::content_type::complex); - - while (parser().peek() == xml::parser::event_type::start_namespace_decl) - { + + while (parser().peek() == xml::parser::event_type::start_namespace_decl) + { parser().next_expect(xml::parser::event_type::start_namespace_decl); if (parser().namespace_() == xmlns_x15) { target_.enable_x15(); } - } - + } + if (parser().attribute_present(xml::qname(xmlns_mc, "Ignorable"))) { parser().attribute(xml::qname(xmlns_mc, "Ignorable")); @@ -655,9 +672,10 @@ void xlsx_consumer::read_workbook() while (true) { - if (parser().peek() == xml::parser::event_type::end_element - || parser().peek() == xml::parser::event_type::end_namespace_decl) break; - + if (parser().peek() == xml::parser::event_type::end_element || + parser().peek() == xml::parser::event_type::end_namespace_decl) + break; + parser().next_expect(xml::parser::event_type::start_element); parser().content(xml::parser::content_type::complex); @@ -667,6 +685,7 @@ void xlsx_consumer::read_workbook() { target_.d_->has_file_version_ = true; target_.d_->file_version_.app_name = parser().attribute("appName"); + if (parser().attribute_present("lastEdited")) { target_.d_->file_version_.last_edited = string_to_size_t(parser().attribute("lastEdited")); @@ -679,7 +698,7 @@ void xlsx_consumer::read_workbook() { target_.d_->file_version_.rup_build = string_to_size_t(parser().attribute("rupBuild")); } - + parser().next_expect(xml::parser::event_type::end_element); } else if (qname == xml::qname(xmlns_mc, "AlternateContent")) @@ -721,42 +740,42 @@ void xlsx_consumer::read_workbook() view.y_window = string_to_size_t(parser().attribute("yWindow")); view.window_width = string_to_size_t(parser().attribute("windowWidth")); view.window_height = string_to_size_t(parser().attribute("windowHeight")); - - if (parser().attribute_present("tabRatio")) - { - view.tab_ratio = string_to_size_t(parser().attribute("tabRatio")); - } - + + if (parser().attribute_present("tabRatio")) + { + view.tab_ratio = string_to_size_t(parser().attribute("tabRatio")); + } + if (parser().attribute_present("activeTab")) - { - parser().attribute("activeTab"); - } - + { + parser().attribute("activeTab"); + } + if (parser().attribute_present("firstSheet")) - { - parser().attribute("firstSheet"); - } - + { + parser().attribute("firstSheet"); + } + if (parser().attribute_present("showHorizontalScroll")) - { - parser().attribute("showHorizontalScroll"); - } - + { + parser().attribute("showHorizontalScroll"); + } + if (parser().attribute_present("showSheetTabs")) - { - parser().attribute("showSheetTabs"); - } - + { + parser().attribute("showSheetTabs"); + } + if (parser().attribute_present("showVerticalScroll")) - { - parser().attribute("showVerticalScroll"); - } - + { + parser().attribute("showVerticalScroll"); + } + target_.set_view(view); - + parser().next_expect(xml::parser::event_type::end_element, xmlns, "workbookView"); } - + parser().next_expect(xml::parser::event_type::end_element, xmlns, "bookViews"); } else if (qname == xml::qname(xmlns, "workbookPr")) @@ -773,37 +792,37 @@ void xlsx_consumer::read_workbook() } } - if (parser().attribute_present("defaultThemeVersion")) - { - parser().attribute("defaultThemeVersion"); - } - + if (parser().attribute_present("defaultThemeVersion")) + { + parser().attribute("defaultThemeVersion"); + } + // todo: turn these structures into a method like skip_attribute(string name, bool optional) if (parser().attribute_present("backupFile")) - { - parser().attribute("backupFile"); - } - + { + parser().attribute("backupFile"); + } + if (parser().attribute_present("showObjects")) - { - parser().attribute("showObjects"); - } + { + parser().attribute("showObjects"); + } if (parser().attribute_present("filterPrivacy")) - { - parser().attribute("filterPrivacy"); - } + { + parser().attribute("filterPrivacy"); + } parser().next_expect(xml::parser::event_type::end_element, xmlns, "workbookPr"); } else if (qname == xml::qname(xmlns, "sheets")) { std::size_t index = 0; - + while (true) { if (parser().peek() == xml::parser::event_type::end_element) break; - + parser().next_expect(xml::parser::event_type::start_element, xmlns_s, "sheet"); std::string rel_id(parser().attribute(xml::qname(xmlns_r, "id"))); @@ -813,15 +832,15 @@ void xlsx_consumer::read_workbook() sheet_title_id_map_[title] = id; sheet_title_index_map_[title] = index++; target_.d_->sheet_title_rel_id_map_[title] = rel_id; - + if (parser().attribute_present("state")) - { - parser().attribute("state"); - } - + { + parser().attribute("state"); + } + parser().next_expect(xml::parser::event_type::end_element, xmlns_s, "sheet"); } - + parser().next_expect(xml::parser::event_type::end_element, xmlns, "sheets"); } else if (qname == xml::qname(xmlns, "calcPr")) @@ -833,30 +852,30 @@ void xlsx_consumer::read_workbook() parser().attribute("calcId"); } - if (parser().attribute_present("concurrentCalc")) - { - parser().attribute("concurrentCalc"); - } - - if (parser().attribute_present("iterate")) - { - parser().attribute("iterate"); - } - - if (parser().attribute_present("iterateCount")) - { - parser().attribute("iterateCount"); - } - - if (parser().attribute_present("iterateDelta")) - { - parser().attribute("iterateDelta"); - } - - if (parser().attribute_present("refMode")) - { - parser().attribute("refMode"); - } + if (parser().attribute_present("concurrentCalc")) + { + parser().attribute("concurrentCalc"); + } + + if (parser().attribute_present("iterate")) + { + parser().attribute("iterate"); + } + + if (parser().attribute_present("iterateCount")) + { + parser().attribute("iterateCount"); + } + + if (parser().attribute_present("iterateDelta")) + { + parser().attribute("iterateDelta"); + } + + if (parser().attribute_present("refMode")) + { + parser().attribute("refMode"); + } parser().next_expect(xml::parser::event_type::end_element, xmlns, "calcPr"); } @@ -866,30 +885,30 @@ void xlsx_consumer::read_workbook() parser().content(xml::parser::content_type::complex); parser().attribute("uri"); - for (;;) - { - if (parser().peek() == xml::parser::event_type::end_element) break; + for (;;) + { + if (parser().peek() == xml::parser::event_type::end_element) break; - parser().next_expect(xml::parser::event_type::start_namespace_decl); - parser().next_expect(xml::parser::event_type::start_element); + parser().next_expect(xml::parser::event_type::start_namespace_decl); + parser().next_expect(xml::parser::event_type::start_element); + + if (parser().qname() == xml::qname(xmlns_mx, "ArchID")) + { + target_.d_->has_arch_id_ = true; + parser().attribute("Flags"); + } + else if (parser().qname() == xml::qname(xmlns_x15, "workbookPr")) + { + parser().attribute("chartTrackingRefBase"); + } - if (parser().qname() == xml::qname(xmlns_mx, "ArchID")) - { - target_.d_->has_arch_id_ = true; - parser().attribute("Flags"); - } - else if (parser().qname() == xml::qname(xmlns_x15, "workbookPr")) - { - parser().attribute("chartTrackingRefBase"); - } - if (parser().attribute_present("stringRefSyntax")) { parser().attribute("stringRefSyntax"); } - parser().next_expect(xml::parser::event_type::end_element); - } + parser().next_expect(xml::parser::event_type::end_element); + } parser().next_expect(xml::parser::event_type::end_element, xmlns, "ext"); parser().next_expect(xml::parser::event_type::end_namespace_decl); @@ -897,12 +916,12 @@ void xlsx_consumer::read_workbook() } else if (qname == xml::qname(xmlns, "workbookProtection")) { - while (parser().peek() != xml::parser::event_type::end_element - || parser().qname() != xml::qname(xmlns, "workbookProtection")) + while (parser().peek() != xml::parser::event_type::end_element || + parser().qname() != xml::qname(xmlns, "workbookProtection")) { parser().next(); } - + parser().next(); } } @@ -916,7 +935,7 @@ void xlsx_consumer::read_calculation_chain() { } -void xlsx_consumer::read_chartsheet(const std::string &/*title*/) +void xlsx_consumer::read_chartsheet(const std::string & /*title*/) { } @@ -932,7 +951,7 @@ void xlsx_consumer::read_custom_xml_mappings() { } -void xlsx_consumer::read_dialogsheet(const std::string &/*title*/) +void xlsx_consumer::read_dialogsheet(const std::string & /*title*/) { } @@ -951,45 +970,45 @@ void xlsx_consumer::read_pivot_table() void xlsx_consumer::read_shared_string_table() { static const auto &xmlns = constants::get_namespace("worksheet"); - + parser().next_expect(xml::parser::event_type::start_element, xmlns, "sst"); - parser().content(xml::content::complex); + parser().content(xml::content::complex); - std::size_t unique_count = 0; + std::size_t unique_count = 0; - if (parser().attribute_present("uniqueCount")) - { - unique_count = string_to_size_t(parser().attribute("uniqueCount")); - } + if (parser().attribute_present("uniqueCount")) + { + unique_count = string_to_size_t(parser().attribute("uniqueCount")); + } - auto &strings = target_.get_shared_strings(); + auto &strings = target_.get_shared_strings(); while (true) { if (parser().peek() == xml::parser::event_type::end_element) break; - + parser().next_expect(xml::parser::event_type::start_element, xmlns, "si"); - parser().content(xml::content::complex); + parser().content(xml::content::complex); parser().next_expect(xml::parser::event_type::start_element); - + formatted_text t; - + parser().attribute_map(); - - if (parser().name() == "t") - { - parser().next_expect(xml::parser::event_type::characters); - t.plain_text(parser().value()); - } - else if (parser().name() == "r") // possible multiple text entities. - { + + if (parser().name() == "t") + { + parser().next_expect(xml::parser::event_type::characters); + t.plain_text(parser().value()); + } + else if (parser().name() == "r") // possible multiple text entities. + { while (true) { if (parser().peek() == xml::parser::event_type::end_element) break; - + parser().next_expect(xml::parser::event_type::start_element, xmlns, "t"); - parser().next_expect(xml::parser::event_type::characters); - text_run run; + parser().next_expect(xml::parser::event_type::characters); + text_run run; run.set_string(parser().value()); if (parser().peek() == xml::parser::event_type::start_element) @@ -999,7 +1018,7 @@ void xlsx_consumer::read_shared_string_table() while (true) { if (parser().peek() == xml::parser::event_type::end_element) break; - + parser().next_expect(xml::parser::event_type::start_element); if (parser().qname() == xml::qname(xmlns, "sz")) @@ -1022,25 +1041,25 @@ void xlsx_consumer::read_shared_string_table() { run.set_scheme(parser().attribute("val")); } - + parser().next_expect(xml::parser::event_type::end_element); } } t.add_run(run); } - } + } - parser().next_expect(xml::parser::event_type::end_element); - parser().next_expect(xml::parser::event_type::end_element); + parser().next_expect(xml::parser::event_type::end_element); + parser().next_expect(xml::parser::event_type::end_element); strings.push_back(t); - } + } - if (unique_count != strings.size()) - { - throw invalid_file("sizes don't match"); - } + if (unique_count != strings.size()) + { + throw invalid_file("sizes don't match"); + } } void xlsx_consumer::read_shared_workbook_revision_headers() @@ -1061,9 +1080,9 @@ void xlsx_consumer::read_stylesheet() static const auto &xmlns_mc = constants::get_namespace("mc"); static const auto &xmlns_x14 = constants::get_namespace("x14"); static const auto &xmlns_x14ac = constants::get_namespace("x14ac"); - static const auto &xmlns_x15 = constants::get_namespace("x15"); - - auto &stylesheet = target_.impl().stylesheet_; + static const auto &xmlns_x15 = constants::get_namespace("x15"); + + auto &stylesheet = target_.impl().stylesheet_; parser().next_expect(xml::parser::event_type::start_element, xmlns, "styleSheet"); parser().content(xml::parser::content_type::complex); @@ -1079,23 +1098,23 @@ void xlsx_consumer::read_stylesheet() target_.enable_x15(); } } - + if (parser().attribute_present(xml::qname(xmlns_mc, "Ignorable"))) { parser().attribute(xml::qname(xmlns_mc, "Ignorable")); } - + struct formatting_record { - std::pair alignment = { {}, 0 }; - std::pair border_id = { 0, false }; - std::pair fill_id = { 0, false }; - std::pair font_id = { 0, false }; - std::pair number_format_id = { 0, false }; - std::pair protection = { {}, false }; - std::pair style_id = { 0, false }; + std::pair alignment = {{}, 0}; + std::pair border_id = {0, false}; + std::pair fill_id = {0, false}; + std::pair font_id = {0, false}; + std::pair number_format_id = {0, false}; + std::pair protection = {{}, false}; + std::pair style_id = {0, false}; }; - + struct style_data { std::string name; @@ -1120,63 +1139,63 @@ void xlsx_consumer::read_stylesheet() if (parser().qname() == xml::qname(xmlns, "borders")) { stylesheet.borders.clear(); - + auto count = parser().attribute("count"); - + while (true) { if (parser().peek() == xml::parser::event_type::end_element) break; stylesheet.borders.push_back(xlnt::border()); - auto &border = stylesheet.borders.back(); + auto &border = stylesheet.borders.back(); + + parser().next_expect(xml::parser::event_type::start_element); // + parser().content(xml::parser::content_type::complex); - parser().next_expect(xml::parser::event_type::start_element); // - parser().content(xml::parser::content_type::complex); - auto diagonal = diagonal_direction::neither; - + if (parser().attribute_present("diagonalDown") && parser().attribute("diagonalDown") == "1") { diagonal = diagonal_direction::down; } - + if (parser().attribute_present("diagonalUp") && parser().attribute("diagonalUp") == "1") { diagonal = diagonal == diagonal_direction::down ? diagonal_direction::both : diagonal_direction::up; } - + if (diagonal != diagonal_direction::neither) { border.diagonal(diagonal); } - while (true) - { - if (parser().peek() == xml::parser::event_type::end_element) break; - parser().next_expect(xml::parser::event_type::start_element); + while (true) + { + if (parser().peek() == xml::parser::event_type::end_element) break; + parser().next_expect(xml::parser::event_type::start_element); - auto side_type = xml::value_traits::parse(parser().name(), parser()); - xlnt::border::border_property side; + auto side_type = xml::value_traits::parse(parser().name(), parser()); + xlnt::border::border_property side; - if (parser().attribute_present("style")) - { - side.style(parser().attribute("style")); - } + if (parser().attribute_present("style")) + { + side.style(parser().attribute("style")); + } - if (parser().peek() == xml::parser::event_type::start_element) - { - parser().next_expect(xml::parser::event_type::start_element, "color"); - side.color(read_color(parser())); - parser().next_expect(xml::parser::event_type::end_element, "color"); - } + if (parser().peek() == xml::parser::event_type::start_element) + { + parser().next_expect(xml::parser::event_type::start_element, "color"); + side.color(read_color(parser())); + parser().next_expect(xml::parser::event_type::end_element, "color"); + } - border.side(side_type, side); - parser().next_expect(xml::parser::event_type::end_element); - } + border.side(side_type, side); + parser().next_expect(xml::parser::event_type::end_element); + } - parser().next_expect(xml::parser::event_type::end_element); // + parser().next_expect(xml::parser::event_type::end_element); // } - + if (count != stylesheet.borders.size()) { throw xlnt::exception("counts don't match"); @@ -1185,7 +1204,7 @@ void xlsx_consumer::read_stylesheet() else if (parser().qname() == xml::qname(xmlns, "fills")) { stylesheet.fills.clear(); - + auto count = parser().attribute("count"); while (true) @@ -1193,78 +1212,78 @@ void xlsx_consumer::read_stylesheet() if (parser().peek() == xml::parser::event_type::end_element) break; stylesheet.fills.push_back(xlnt::fill()); - auto &new_fill = stylesheet.fills.back(); + auto &new_fill = stylesheet.fills.back(); - parser().next_expect(xml::parser::event_type::start_element, xmlns, "fill"); - parser().content(xml::parser::content_type::complex); - parser().next_expect(xml::parser::event_type::start_element); + parser().next_expect(xml::parser::event_type::start_element, xmlns, "fill"); + parser().content(xml::parser::content_type::complex); + parser().next_expect(xml::parser::event_type::start_element); - if (parser().qname() == xml::qname(xmlns, "patternFill")) - { - xlnt::pattern_fill pattern; + if (parser().qname() == xml::qname(xmlns, "patternFill")) + { + xlnt::pattern_fill pattern; - if (parser().attribute_present("patternType")) - { - pattern.type(parser().attribute("patternType")); + if (parser().attribute_present("patternType")) + { + pattern.type(parser().attribute("patternType")); - while (true) - { - if (parser().peek() == xml::parser::event_type::end_element) - { - break; - } + while (true) + { + if (parser().peek() == xml::parser::event_type::end_element) + { + break; + } - parser().next_expect(xml::parser::event_type::start_element); + parser().next_expect(xml::parser::event_type::start_element); - if (parser().name() == "fgColor") - { - pattern.foreground(read_color(parser())); - } - else if (parser().name() == "bgColor") - { - pattern.background(read_color(parser())); - } + if (parser().name() == "fgColor") + { + pattern.foreground(read_color(parser())); + } + else if (parser().name() == "bgColor") + { + pattern.background(read_color(parser())); + } - parser().next_expect(xml::parser::event_type::end_element); - } - } + parser().next_expect(xml::parser::event_type::end_element); + } + } - new_fill = pattern; - } - else if (parser().qname() == xml::qname(xmlns, "gradientFill")) - { - xlnt::gradient_fill gradient; + new_fill = pattern; + } + else if (parser().qname() == xml::qname(xmlns, "gradientFill")) + { + xlnt::gradient_fill gradient; - if (parser().attribute_present("type")) - { - gradient.type(parser().attribute("type")); - } - else - { - gradient.type(xlnt::gradient_fill_type::linear); - } + if (parser().attribute_present("type")) + { + gradient.type(parser().attribute("type")); + } + else + { + gradient.type(xlnt::gradient_fill_type::linear); + } - while (true) - { - if (parser().peek() == xml::parser::event_type::end_element) break; + while (true) + { + if (parser().peek() == xml::parser::event_type::end_element) break; - parser().next_expect(xml::parser::event_type::start_element, "stop"); - auto position = parser().attribute("position"); - parser().next_expect(xml::parser::event_type::start_element, "color"); - auto color = read_color(parser()); - parser().next_expect(xml::parser::event_type::end_element, "color"); - parser().next_expect(xml::parser::event_type::end_element, "stop"); + parser().next_expect(xml::parser::event_type::start_element, "stop"); + auto position = parser().attribute("position"); + parser().next_expect(xml::parser::event_type::start_element, "color"); + auto color = read_color(parser()); + parser().next_expect(xml::parser::event_type::end_element, "color"); + parser().next_expect(xml::parser::event_type::end_element, "stop"); - gradient.add_stop(position, color); - } + gradient.add_stop(position, color); + } - new_fill = gradient; - } + new_fill = gradient; + } - parser().next_expect(xml::parser::event_type::end_element); // or - parser().next_expect(xml::parser::event_type::end_element); // + parser().next_expect(xml::parser::event_type::end_element); // or + parser().next_expect(xml::parser::event_type::end_element); // } - + if (count != stylesheet.fills.size()) { throw xlnt::exception("counts don't match"); @@ -1275,7 +1294,7 @@ void xlsx_consumer::read_stylesheet() stylesheet.fonts.clear(); auto count = parser().attribute("count"); - + if (parser().attribute_present(xml::qname(xmlns_x14ac, "knownFonts"))) { parser().attribute(xml::qname(xmlns_x14ac, "knownFonts")); @@ -1285,101 +1304,101 @@ void xlsx_consumer::read_stylesheet() { if (parser().peek() == xml::parser::event_type::end_element) break; - stylesheet.fonts.push_back(xlnt::font()); - auto &new_font = stylesheet.fonts.back(); + stylesheet.fonts.push_back(xlnt::font()); + auto &new_font = stylesheet.fonts.back(); - parser().next_expect(xml::parser::event_type::start_element, xmlns, "font"); - parser().content(xml::parser::content_type::complex); + parser().next_expect(xml::parser::event_type::start_element, xmlns, "font"); + parser().content(xml::parser::content_type::complex); - while (true) - { - if (parser().peek() == xml::parser::event_type::end_element) break; + while (true) + { + if (parser().peek() == xml::parser::event_type::end_element) break; - parser().next_expect(xml::parser::event_type::start_element); - parser().content(xml::parser::content_type::simple); + parser().next_expect(xml::parser::event_type::start_element); + parser().content(xml::parser::content_type::simple); - if (parser().name() == "sz") - { - new_font.size(string_to_size_t(parser().attribute("val"))); - } - else if (parser().name() == "name") - { - new_font.name(parser().attribute("val")); - } - else if (parser().name() == "color") - { - new_font.color(read_color(parser())); - } - else if (parser().name() == "family") - { - new_font.family(string_to_size_t(parser().attribute("val"))); - } - else if (parser().name() == "scheme") - { - new_font.scheme(parser().attribute("val")); - } - else if (parser().name() == "b") - { - if (parser().attribute_present("val")) - { - new_font.bold(is_true(parser().attribute("val"))); - } - else - { - new_font.bold(true); - } - } - else if (parser().name() == "vertAlign") - { - new_font.superscript(parser().attribute("val") == "superscript"); - } - else if (parser().name() == "strike") - { - if (parser().attribute_present("val")) - { - new_font.strikethrough(is_true(parser().attribute("val"))); - } - else - { - new_font.strikethrough(true); - } - } - else if (parser().name() == "i") - { - if (parser().attribute_present("val")) - { - new_font.italic(is_true(parser().attribute("val"))); - } - else - { - new_font.italic(true); - } - } - else if (parser().name() == "u") - { - if (parser().attribute_present("val")) - { - new_font.underline(parser().attribute("val")); - } - else - { - new_font.underline(xlnt::font::underline_style::single); - } - } + if (parser().name() == "sz") + { + new_font.size(string_to_size_t(parser().attribute("val"))); + } + else if (parser().name() == "name") + { + new_font.name(parser().attribute("val")); + } + else if (parser().name() == "color") + { + new_font.color(read_color(parser())); + } + else if (parser().name() == "family") + { + new_font.family(string_to_size_t(parser().attribute("val"))); + } + else if (parser().name() == "scheme") + { + new_font.scheme(parser().attribute("val")); + } + else if (parser().name() == "b") + { + if (parser().attribute_present("val")) + { + new_font.bold(is_true(parser().attribute("val"))); + } + else + { + new_font.bold(true); + } + } + else if (parser().name() == "vertAlign") + { + new_font.superscript(parser().attribute("val") == "superscript"); + } + else if (parser().name() == "strike") + { + if (parser().attribute_present("val")) + { + new_font.strikethrough(is_true(parser().attribute("val"))); + } + else + { + new_font.strikethrough(true); + } + } + else if (parser().name() == "i") + { + if (parser().attribute_present("val")) + { + new_font.italic(is_true(parser().attribute("val"))); + } + else + { + new_font.italic(true); + } + } + else if (parser().name() == "u") + { + if (parser().attribute_present("val")) + { + new_font.underline(parser().attribute("val")); + } + else + { + new_font.underline(xlnt::font::underline_style::single); + } + } else if (parser().name() == "charset") - { - if (parser().attribute_present("val")) - { - parser().attribute("val"); - } - } + { + if (parser().attribute_present("val")) + { + parser().attribute("val"); + } + } - parser().next_expect(xml::parser::event_type::end_element); - } + parser().next_expect(xml::parser::event_type::end_element); + } - parser().next_expect(xml::parser::event_type::end_element, xmlns, "font"); + parser().next_expect(xml::parser::event_type::end_element, xmlns, "font"); } - + if (count != stylesheet.fonts.size()) { throw xlnt::exception("counts don't match"); @@ -1388,7 +1407,7 @@ void xlsx_consumer::read_stylesheet() else if (parser().qname() == xml::qname(xmlns, "numFmts")) { stylesheet.number_formats.clear(); - + auto count = parser().attribute("count"); while (true) @@ -1411,7 +1430,7 @@ void xlsx_consumer::read_stylesheet() stylesheet.number_formats.push_back(nf); parser().next_expect(xml::parser::event_type::end_element); // numFmt } - + if (count != stylesheet.number_formats.size()) { throw xlnt::exception("counts don't match"); @@ -1419,8 +1438,8 @@ void xlsx_consumer::read_stylesheet() } else if (parser().qname() == xml::qname(xmlns, "colors")) { - while (parser().peek() != xml::parser::event_type::end_element - || parser().qname() != xml::qname(xmlns, "colors")) + while (parser().peek() != xml::parser::event_type::end_element || + parser().qname() != xml::qname(xmlns, "colors")) { if (parser().next() == xml::parser::event_type::start_element) { @@ -1431,18 +1450,18 @@ void xlsx_consumer::read_stylesheet() else if (parser().qname() == xml::qname(xmlns, "cellStyles")) { auto count = parser().attribute("count"); - + while (true) { if (parser().peek() == xml::parser::event_type::end_element) break; - + auto &data = *style_datas.emplace(style_datas.end()); - + parser().next_expect(xml::parser::event_type::start_element, xmlns, "cellStyle"); data.name = parser().attribute("name"); data.record_id = parser().attribute("xfId"); - + if (parser().attribute_present("builtinId")) { data.builtin_id = {parser().attribute("builtinId"), true}; @@ -1465,57 +1484,56 @@ void xlsx_consumer::read_stylesheet() parser().next_expect(xml::parser::event_type::end_element, xmlns, "cellStyle"); } - + if (count != style_datas.size()) { throw xlnt::exception("counts don't match"); } } - else if (parser().qname() == xml::qname(xmlns, "cellStyleXfs") - || parser().qname() == xml::qname(xmlns, "cellXfs")) + else if (parser().qname() == xml::qname(xmlns, "cellStyleXfs") || + parser().qname() == xml::qname(xmlns, "cellXfs")) { auto in_style_records = parser().name() == "cellStyleXfs"; auto count = parser().attribute("count"); - + while (true) { if (parser().peek() == xml::parser::event_type::end_element) break; - + parser().next_expect(xml::parser::event_type::start_element, xmlns, "xf"); - parser().content(xml::content::complex); + parser().content(xml::content::complex); auto &record = *(!in_style_records ? format_records.emplace(format_records.end()) : style_records.emplace(style_records.end())); auto apply_alignment_present = parser().attribute_present("applyAlignment"); - auto alignment_applied = apply_alignment_present - && is_true(parser().attribute("applyAlignment")); + auto alignment_applied = apply_alignment_present && is_true(parser().attribute("applyAlignment")); record.alignment.second = alignment_applied; auto border_applied = parser().attribute_present("applyBorder") && is_true(parser().attribute("applyBorder")); auto border_index = parser().attribute_present("borderId") ? string_to_size_t(parser().attribute("borderId")) : 0; - record.border_id = { border_index, border_applied }; - + record.border_id = {border_index, border_applied}; + auto fill_applied = parser().attribute_present("applyFill") && is_true(parser().attribute("applyFill")); auto fill_index = parser().attribute_present("fillId") ? string_to_size_t(parser().attribute("fillId")) : 0; - record.fill_id = { fill_index, fill_applied }; + record.fill_id = {fill_index, fill_applied}; auto font_applied = parser().attribute_present("applyFont") && is_true(parser().attribute("applyFont")); auto font_index = parser().attribute_present("fontId") ? string_to_size_t(parser().attribute("fontId")) : 0; - record.font_id = { font_index, font_applied }; + record.font_id = {font_index, font_applied}; auto number_format_applied = parser().attribute_present("applyNumberFormat") && is_true(parser().attribute("applyNumberFormat")); auto number_format_id = parser().attribute_present("numFmtId") ? string_to_size_t(parser().attribute("numFmtId")) : 0; - record.number_format_id = { number_format_id, number_format_applied }; + record.number_format_id = {number_format_id, number_format_applied}; auto apply_protection_present = parser().attribute_present("applyProtection"); auto protection_applied = apply_protection_present @@ -1524,67 +1542,70 @@ void xlsx_consumer::read_stylesheet() if (parser().attribute_present("xfId") && parser().name() == "cellXfs") { - record.style_id = { parser().attribute("xfId"), true }; + record.style_id = {parser().attribute("xfId"), true}; } - + while (true) { if (parser().peek() == xml::parser::event_type::end_element) break; - + parser().next_expect(xml::parser::event_type::start_element); - + if (parser().qname() == xml::qname(xmlns, "alignment")) { - if (parser().attribute_present("wrapText")) - { - record.alignment.first.wrap(is_true(parser().attribute("wrapText"))); - } + if (parser().attribute_present("wrapText")) + { + auto value = is_true(parser().attribute("wrapText")); + record.alignment.first.wrap(value); + } - if (parser().attribute_present("shrinkToFit")) - { - record.alignment.first.shrink(is_true(parser().attribute("shrinkToFit"))); - } + if (parser().attribute_present("shrinkToFit")) + { + auto value = is_true(parser().attribute("shrinkToFit")); + record.alignment.first.shrink(value); + } - if (parser().attribute_present("indent")) - { - record.alignment.first.indent(parser().attribute("indent")); - } + if (parser().attribute_present("indent")) + { + auto value = parser().attribute("indent"); + record.alignment.first.indent(value); + } - if (parser().attribute_present("textRotation")) - { - record.alignment.first.rotation(parser().attribute("textRotation")); - } + if (parser().attribute_present("textRotation")) + { + auto value = parser().attribute("textRotation"); + record.alignment.first.rotation(value); + } - if (parser().attribute_present("vertical")) - { - record.alignment.first.vertical( - parser().attribute("vertical")); - } + if (parser().attribute_present("vertical")) + { + auto value = parser().attribute("vertical"); + record.alignment.first.vertical(value); + } - if (parser().attribute_present("horizontal")) - { - record.alignment.first.horizontal( - parser().attribute("horizontal")); - } + if (parser().attribute_present("horizontal")) + { + auto value = parser().attribute("horizontal"); + record.alignment.first.horizontal(value); + } record.alignment.second = !apply_alignment_present || alignment_applied; } else if (parser().qname() == xml::qname(xmlns, "protection")) { - record.protection.first.locked(is_true(parser().attribute("locked"))); - record.protection.first.hidden(is_true(parser().attribute("hidden"))); + record.protection.first.locked(is_true(parser().attribute("locked"))); + record.protection.first.hidden(is_true(parser().attribute("hidden"))); record.protection.second = !apply_protection_present || protection_applied; } - + parser().next_expect(xml::parser::event_type::end_element, parser().qname()); } - + parser().next_expect(xml::parser::event_type::end_element, xmlns, "xf"); - } - - if ((in_style_records && count != style_records.size()) - || (!in_style_records && count != format_records.size())) + + if ((in_style_records && count != style_records.size()) || + (!in_style_records && count != format_records.size())) { throw xlnt::exception("counts don't match"); } @@ -1593,14 +1614,14 @@ void xlsx_consumer::read_stylesheet() { auto count = parser().attribute("count"); std::size_t processed = 0; - + while (true) { if (parser().peek() == xml::parser::event_type::end_element) break; parser().next_expect(xml::parser::event_type::start_element); parser().next_expect(xml::parser::event_type::end_element); } - + if (count != processed) { throw xlnt::exception("counts don't match"); @@ -1612,14 +1633,14 @@ void xlsx_consumer::read_stylesheet() auto default_pivot_style = parser().attribute("defaultPivotStyle"); auto count = parser().attribute("count"); std::size_t processed = 0; - + while (true) { if (parser().peek() == xml::parser::event_type::end_element) break; parser().next_expect(xml::parser::event_type::start_element); parser().next_expect(xml::parser::event_type::end_element); } - + if (count != processed) { throw xlnt::exception("counts don't match"); @@ -1627,47 +1648,47 @@ void xlsx_consumer::read_stylesheet() } else if (parser().qname() == xml::qname(xmlns, "extLst")) { - for (;;) - { - if (parser().peek() == xml::parser::event_type::end_element) break; + for (;;) + { + if (parser().peek() == xml::parser::event_type::end_element) break; - parser().next_expect(xml::parser::event_type::start_element, xmlns, "ext"); - parser().content(xml::parser::content_type::complex); - parser().attribute("uri"); - parser().next_expect(xml::parser::event_type::start_namespace_decl); + parser().next_expect(xml::parser::event_type::start_element, xmlns, "ext"); + parser().content(xml::parser::content_type::complex); + parser().attribute("uri"); + parser().next_expect(xml::parser::event_type::start_namespace_decl); - parser().next_expect(xml::parser::event_type::start_element); + parser().next_expect(xml::parser::event_type::start_element); - if (parser().qname() == xml::qname(xmlns_x14, "slicerStyles")) - { - parser().attribute("defaultSlicerStyle"); - } - else if (parser().qname() == xml::qname(xmlns_x15, "timelineStyles")) - { - parser().attribute("defaultTimelineStyle"); - } + if (parser().qname() == xml::qname(xmlns_x14, "slicerStyles")) + { + parser().attribute("defaultSlicerStyle"); + } + else if (parser().qname() == xml::qname(xmlns_x15, "timelineStyles")) + { + parser().attribute("defaultTimelineStyle"); + } - parser().next_expect(xml::parser::event_type::end_element); + parser().next_expect(xml::parser::event_type::end_element); - parser().next_expect(xml::parser::event_type::end_element, xmlns, "ext"); - parser().next_expect(xml::parser::event_type::end_namespace_decl); - } + parser().next_expect(xml::parser::event_type::end_element, xmlns, "ext"); + parser().next_expect(xml::parser::event_type::end_namespace_decl); + } } else if (parser().qname() == xml::qname(xmlns, "indexedColors")) { parser().next_expect(xml::parser::event_type::end_element, xmlns, "indexedColors"); } - + parser().next_expect(xml::parser::event_type::end_element); } - + parser().next_expect(xml::parser::event_type::end_element); - + auto lookup_number_format = [&](std::size_t number_format_id) { auto result = number_format::general(); bool is_custom_number_format = false; - + for (const auto &nf : stylesheet.number_formats) { if (nf.get_id() == number_format_id) @@ -1682,22 +1703,22 @@ void xlsx_consumer::read_stylesheet() { result = number_format::from_builtin_id(number_format_id); } - + return result; }; - + std::size_t xf_id = 0; - + for (const auto &record : style_records) { auto style_data_iter = std::find_if(style_datas.begin(), style_datas.end(), [&xf_id](const style_data &s) { return s.record_id == xf_id; }); ++xf_id; - + if (style_data_iter == style_datas.end()) continue; auto new_style = stylesheet.create_style(style_data_iter->name); - + if (style_data_iter->builtin_id.second) { new_style.builtin_id(style_data_iter->builtin_id.first); @@ -1715,14 +1736,14 @@ void xlsx_consumer::read_stylesheet() new_style.number_format(lookup_number_format(record.number_format_id.first), record.number_format_id.second); new_style.protection(record.protection.first, record.protection.second); } - + std::size_t record_index = 0; for (const auto &record : format_records) { stylesheet.format_impls.push_back(format_impl()); auto &new_format = stylesheet.format_impls.back(); - + new_format.id = record_index++; new_format.parent = &stylesheet; @@ -1750,7 +1771,7 @@ void xlsx_consumer::read_stylesheet() void xlsx_consumer::read_theme() { - target_.set_theme(theme()); + target_.set_theme(theme()); } void xlsx_consumer::read_volatile_dependencies() @@ -1764,54 +1785,51 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id) static const auto &xmlns_r = constants::get_namespace("r"); static const auto &xmlns_x14ac = constants::get_namespace("x14ac"); - auto title = std::find_if(target_.d_->sheet_title_rel_id_map_.begin(), - target_.d_->sheet_title_rel_id_map_.end(), - [&](const std::pair &p) - { - return p.second == rel_id; - })->first; + auto title = std::find_if(target_.d_->sheet_title_rel_id_map_.begin(), + target_.d_->sheet_title_rel_id_map_.end(), + [&](const std::pair &p) { return p.second == rel_id; })->first; - auto id = sheet_title_id_map_[title]; - auto index = sheet_title_index_map_[title]; + auto id = sheet_title_id_map_[title]; + auto index = sheet_title_index_map_[title]; - auto insertion_iter = target_.d_->worksheets_.begin(); - while (insertion_iter != target_.d_->worksheets_.end() - && sheet_title_index_map_[insertion_iter->title_] < index) - { - ++insertion_iter; - } + auto insertion_iter = target_.d_->worksheets_.begin(); + while (insertion_iter != target_.d_->worksheets_.end() + && sheet_title_index_map_[insertion_iter->title_] < index) + { + ++insertion_iter; + } - target_.d_->worksheets_.emplace(insertion_iter, &target_, id, title); + target_.d_->worksheets_.emplace(insertion_iter, &target_, id, title); - auto ws = target_.get_sheet_by_id(id); + auto ws = target_.get_sheet_by_id(id); - parser().next_expect(xml::parser::event_type::start_element, xmlns, "worksheet"); + parser().next_expect(xml::parser::event_type::start_element, xmlns, "worksheet"); parser().content(xml::parser::content_type::complex); while (parser().peek() == xml::parser::event_type::start_namespace_decl) - { + { parser().next_expect(xml::parser::event_type::start_namespace_decl); if (parser().namespace_() == xmlns_x14ac) { ws.enable_x14ac(); } - } - + } + if (parser().attribute_present(xml::qname(xmlns_mc, "Ignorable"))) { parser().attribute(xml::qname(xmlns_mc, "Ignorable")); } - xlnt::range_reference full_range; + xlnt::range_reference full_range; while (true) { if (parser().peek() == xml::parser::event_type::end_element) break; - + parser().next_expect(xml::parser::event_type::start_element); parser().content(xml::parser::content_type::complex); - + if (parser().qname() == xml::qname(xmlns, "dimension")) { full_range = xlnt::range_reference(parser().attribute("ref")); @@ -1821,7 +1839,7 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id) else if (parser().qname() == xml::qname(xmlns, "sheetViews")) { ws.d_->has_view_ = true; - + while (true) { parser().attribute_map(); @@ -1835,7 +1853,7 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id) else if (parser().qname() == xml::qname(xmlns, "sheetFormatPr")) { ws.d_->has_format_properties_ = true; - + while (true) { parser().attribute_map(); @@ -1865,7 +1883,7 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id) { throw invalid_file("sizes don't match"); } - + parser().next_expect(xml::parser::event_type::end_element, xmlns, "mergeCells"); } else if (parser().qname() == xml::qname(xmlns, "sheetData")) @@ -1875,9 +1893,9 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id) while (true) { if (parser().peek() == xml::parser::event_type::end_element) break; - + parser().next_expect(xml::parser::event_type::start_element, xmlns, "row"); - parser().content(xml::content::complex); + parser().content(xml::content::complex); auto row_index = static_cast(std::stoull(parser().attribute("r"))); @@ -1886,20 +1904,20 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id) ws.get_row_properties(row_index).height = std::stold(parser().attribute("ht")); } - if (parser().attribute_present("customHeight")) - { + if (parser().attribute_present("customHeight")) + { auto custom_height = parser().attribute("customHeight"); - + if (custom_height != "false") { ws.get_row_properties(row_index).height = std::stold(custom_height); } - } + } - if (parser().attribute_present(xml::qname(xmlns_x14ac, "dyDescent"))) - { - parser().attribute(xml::qname(xmlns_x14ac, "dyDescent")); - } + if (parser().attribute_present(xml::qname(xmlns_x14ac, "dyDescent"))) + { + parser().attribute(xml::qname(xmlns_x14ac, "dyDescent")); + } auto min_column = full_range.get_top_left().get_column_index(); auto max_column = full_range.get_bottom_right().get_column_index(); @@ -1916,58 +1934,58 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id) } } - if (parser().attribute_present("customFormat")) - { - parser().attribute("customFormat"); - } + if (parser().attribute_present("customFormat")) + { + parser().attribute("customFormat"); + } + + if (parser().attribute_present("s")) + { + parser().attribute("s"); + } - if (parser().attribute_present("s")) - { - parser().attribute("s"); - } - if (parser().attribute_present("collapsed")) - { - parser().attribute("collapsed"); - } - + { + parser().attribute("collapsed"); + } + if (parser().attribute_present("hidden")) - { - parser().attribute("hidden"); - } - + { + parser().attribute("hidden"); + } + if (parser().attribute_present("outlineLevel")) - { - parser().attribute("outlineLevel"); - } + { + parser().attribute("outlineLevel"); + } while (true) { if (parser().peek() == xml::parser::event_type::end_element) break; parser().next_expect(xml::parser::event_type::start_element, xmlns, "c"); - parser().content(xml::content::complex); + parser().content(xml::content::complex); auto cell = ws.get_cell(cell_reference(parser().attribute("r"))); - + auto has_type = parser().attribute_present("t"); auto type = has_type ? parser().attribute("t") : ""; auto has_format = parser().attribute_present("s"); auto format_id = static_cast(has_format ? std::stoull(parser().attribute("s")) : 0LL); - + auto has_value = false; auto value_string = std::string(); - + auto has_formula = false; auto has_shared_formula = false; auto formula_value_string = std::string(); - + while (true) { if (parser().peek() == xml::parser::event_type::end_element) break; - + parser().next_expect(xml::parser::event_type::start_element); - + if (parser().qname() == xml::qname(xmlns, "v")) { has_value = true; @@ -1982,19 +2000,18 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id) else if (parser().qname() == xml::qname(xmlns, "f")) { has_formula = true; - has_shared_formula = parser().attribute_present("t") - && parser().attribute("t") == "shared"; - parser().next_expect(xml::parser::event_type::characters); + has_shared_formula = parser().attribute_present("t") && parser().attribute("t") == "shared"; + parser().next_expect(xml::parser::event_type::characters); formula_value_string = parser().value(); } else if (parser().qname() == xml::qname(xmlns, "is")) { parser().next_expect(xml::parser::event_type::start_element, xmlns, "t"); - parser().next_expect(xml::parser::event_type::characters); + parser().next_expect(xml::parser::event_type::characters); value_string = parser().value(); parser().next_expect(xml::parser::event_type::end_element, xmlns, "t"); } - + parser().next_expect(xml::parser::event_type::end_element); } @@ -2003,7 +2020,7 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id) cell.set_formula(formula_value_string); } - if (has_type && (type == "inlineStr" || type =="str")) + if (has_type && (type == "inlineStr" || type == "str")) { cell.set_value(value_string); } @@ -2033,13 +2050,13 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id) { cell.format(target_.get_format(format_id)); } - + parser().next_expect(xml::parser::event_type::end_element, xmlns, "c"); } - parser().next_expect(xml::parser::event_type::end_element, xmlns, "row"); + parser().next_expect(xml::parser::event_type::end_element, xmlns, "row"); } - + parser().next_expect(xml::parser::event_type::end_element, xmlns, "sheetData"); } else if (parser().qname() == xml::qname(xmlns, "cols")) @@ -2047,14 +2064,14 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id) while (true) { if (parser().peek() == xml::parser::event_type::end_element) break; - + parser().next_expect(xml::parser::event_type::start_element, xmlns, "col"); auto min = static_cast(std::stoull(parser().attribute("min"))); auto max = static_cast(std::stoull(parser().attribute("max"))); auto width = std::stold(parser().attribute("width")); - auto column_style = parser().attribute_present("style") + auto column_style = parser().attribute_present("style") ? parser().attribute("style") : static_cast(0); auto custom = parser().attribute_present("customWidth") ? is_true(parser().attribute("customWidth")) : false; @@ -2070,29 +2087,29 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id) ws.add_column_properties(column, props); } - if (parser().attribute_present("bestFit")) - { - parser().attribute("bestFit"); - } - - if (parser().attribute_present("collapsed")) - { - parser().attribute("collapsed"); - } - + if (parser().attribute_present("bestFit")) + { + parser().attribute("bestFit"); + } + + if (parser().attribute_present("collapsed")) + { + parser().attribute("collapsed"); + } + if (parser().attribute_present("hidden")) - { - parser().attribute("hidden"); - } - + { + parser().attribute("hidden"); + } + if (parser().attribute_present("outlineLevel")) - { - parser().attribute("outlineLevel"); - } - + { + parser().attribute("outlineLevel"); + } + parser().next_expect(xml::parser::event_type::end_element, xmlns, "col"); } - + parser().next_expect(xml::parser::event_type::end_element, xmlns, "cols"); } else if (parser().qname() == xml::qname(xmlns, "autoFilter")) @@ -2112,7 +2129,7 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id) margins.set_footer(parser().attribute("footer")); ws.set_page_margins(margins); - + parser().next_expect(xml::parser::event_type::end_element, xmlns, "pageMargins"); } else if (parser().qname() == xml::qname(xmlns, "pageSetUpPr")) @@ -2134,30 +2151,30 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id) { parser().attribute_map(); - while (parser().peek() != xml::parser::event_type::end_element - || parser().qname() != xml::qname(xmlns, "sheetPr")) + while (parser().peek() != xml::parser::event_type::end_element || + parser().qname() != xml::qname(xmlns, "sheetPr")) { if (parser().next() == xml::parser::event_type::start_element) { parser().attribute_map(); } } - + parser().next(); } else if (parser().qname() == xml::qname(xmlns, "headerFooter")) { parser().attribute_map(); - while (parser().peek() != xml::parser::event_type::end_element - || parser().qname() != xml::qname(xmlns, "headerFooter")) + while (parser().peek() != xml::parser::event_type::end_element || + parser().qname() != xml::qname(xmlns, "headerFooter")) { if (parser().next() == xml::parser::event_type::start_element) { parser().attribute_map(); } } - + parser().next(); } else if (parser().qname() == xml::qname(xmlns, "legacyDrawing")) @@ -2169,19 +2186,19 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id) { parser().attribute_map(); - while (parser().peek() != xml::parser::event_type::end_element - || parser().qname() != xml::qname(xmlns, "protectedRanges")) + while (parser().peek() != xml::parser::event_type::end_element || + parser().qname() != xml::qname(xmlns, "protectedRanges")) { if (parser().next() == xml::parser::event_type::start_element) { parser().attribute_map(); } } - + parser().next(); } } - + parser().next_expect(xml::parser::event_type::end_element, xmlns, "worksheet"); auto &manifest = target_.get_manifest(); @@ -2191,15 +2208,15 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id) if (manifest.has_relationship(sheet_path, xlnt::relationship::type::comments)) { - auto comments_part = manifest.canonicalize({workbook_rel, sheet_rel, - manifest.get_relationship(sheet_path, xlnt::relationship::type::comments)}); + auto comments_part = manifest.canonicalize( + {workbook_rel, sheet_rel, manifest.get_relationship(sheet_path, xlnt::relationship::type::comments)}); auto receive = xml::parser::receive_default; xml::parser parser(archive_->open(comments_part.string()), comments_part.string(), receive); parser_ = &parser; - + read_comments(ws); - + if (manifest.has_relationship(sheet_path, xlnt::relationship::type::vml_drawing)) { auto vml_drawings_part = manifest.canonicalize({workbook_rel, sheet_rel, @@ -2208,7 +2225,7 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id) auto receive = xml::parser::receive_default; xml::parser parser(archive_->open(vml_drawings_part.string()), vml_drawings_part.string(), receive); parser_ = &parser; - + read_vml_drawings(ws); } } @@ -2218,20 +2235,19 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id) void xlsx_consumer::read_vml_drawings(worksheet ws) { - } void xlsx_consumer::read_comments(worksheet ws) { static const auto &xmlns = xlnt::constants::get_namespace("worksheet"); - + std::vector authors; - + parser().next_expect(xml::parser::event_type::start_element, xmlns, "comments"); - parser().content(xml::content::complex); + parser().content(xml::content::complex); parser().next_expect(xml::parser::event_type::start_element, xmlns, "authors"); - parser().content(xml::content::complex); - + parser().content(xml::content::complex); + for (;;) { if (parser().peek() == xml::parser::event_type::end_element) break; @@ -2241,24 +2257,24 @@ void xlsx_consumer::read_comments(worksheet ws) authors.push_back(parser().value()); parser().next_expect(xml::parser::event_type::end_element, xmlns, "author"); } - + parser().next_expect(xml::parser::event_type::end_element, xmlns, "authors"); parser().next_expect(xml::parser::event_type::start_element, xmlns, "commentList"); - parser().content(xml::content::complex); - + parser().content(xml::content::complex); + for (;;) { if (parser().peek() == xml::parser::event_type::end_element) break; parser().next_expect(xml::parser::event_type::start_element, xmlns, "comment"); - parser().content(xml::content::complex); + parser().content(xml::content::complex); auto cell_ref = parser().attribute("ref"); auto author_id = parser().attribute("authorId"); - + parser().next_expect(xml::parser::event_type::start_element, xmlns, "text"); - parser().content(xml::content::complex); + parser().content(xml::content::complex); // todo: this is duplicated from shared strings formatted_text text; @@ -2266,18 +2282,18 @@ void xlsx_consumer::read_comments(worksheet ws) for (;;) { if (parser().peek() == xml::parser::event_type::end_element) break; - + parser().next_expect(xml::parser::event_type::start_element, xmlns, "r"); - parser().content(xml::content::complex); + parser().content(xml::content::complex); text_run run; - + for (;;) { if (parser().peek() == xml::parser::event_type::end_element) break; - + parser().next_expect(xml::parser::event_type::start_element); - + if (parser().name() == "t") { parser().next_expect(xml::parser::event_type::characters); @@ -2286,12 +2302,12 @@ void xlsx_consumer::read_comments(worksheet ws) } else if (parser().name() == "rPr") { - parser().content(xml::content::complex); + parser().content(xml::content::complex); for (;;) { if (parser().peek() == xml::parser::event_type::end_element) break; - + parser().next_expect(xml::parser::event_type::start_element); if (parser().qname() == xml::qname(xmlns, "sz")) @@ -2318,23 +2334,23 @@ void xlsx_consumer::read_comments(worksheet ws) { run.set_bold(true); } - + parser().next_expect(xml::parser::event_type::end_element); } - + parser().next_expect(xml::parser::event_type::end_element, xmlns, "rPr"); } } - + text.add_run(run); parser().next_expect(xml::parser::event_type::end_element, xmlns, "r"); } - + ws.get_cell(cell_ref).comment(comment(text, authors.at(author_id))); parser().next_expect(xml::parser::event_type::end_element, xmlns, "text"); parser().next_expect(xml::parser::event_type::end_element, xmlns, "comment"); } - + parser().next_expect(xml::parser::event_type::end_element, xmlns, "commentList"); parser().next_expect(xml::parser::event_type::end_element, xmlns, "comments"); }