diff --git a/include/xlnt/cell/cell.hpp b/include/xlnt/cell/cell.hpp index b4f4f7b1..49ed6402 100644 --- a/include/xlnt/cell/cell.hpp +++ b/include/xlnt/cell/cell.hpp @@ -44,17 +44,24 @@ class font; class format; class number_format; class protection; -class relationship; class style; class workbook; class worksheet; +class xlsx_consumer; +class xlsx_producer; struct date; struct datetime; struct time; struct timedelta; -namespace detail { struct cell_impl; } +namespace detail { + +class xlsx_consumer; +class xlsx_producer; +struct cell_impl; + +} // namespace detail /// /// Describes cell associated properties. @@ -151,9 +158,9 @@ public: // hyperlink /// - /// Return a relationship representing this cell's hyperlink. + /// Return the URL of this cell's hyperlink. /// - relationship get_hyperlink() const; + std::string get_hyperlink() const; /// /// Add a hyperlink to this cell pointing to the URI of the given value. @@ -183,6 +190,8 @@ public: const format &get_format() const; void set_format(const format &new_format); + + void set_format_id(std::size_t format_id); void clear_format(); @@ -380,7 +389,8 @@ private: // make these friends so they can use the private constructor friend class style; friend class worksheet; - friend class worksheet_serializer; + friend class detail::xlsx_consumer; + friend class detail::xlsx_producer; friend struct detail::cell_impl; void guess_type_and_set_value(const std::string &value); diff --git a/include/xlnt/packaging/default_type.hpp b/include/xlnt/packaging/default_type.hpp deleted file mode 100644 index 654425ea..00000000 --- a/include/xlnt/packaging/default_type.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2014-2016 Thomas Fussell -// Copyright (c) 2010-2015 openpyxl -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, WRISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE -// -// @license: http://www.opensource.org/licenses/mit-license.php -// @author: see AUTHORS file -#pragma once - -#include - -#include - -namespace xlnt { - -/// -/// Default types in an OOXML package are identified by their extension. -/// All files in the package with this extension will be assigned the given -/// content type unless an override type for the exact file is provided. -/// -class XLNT_CLASS default_type -{ -public: - default_type(); - default_type(const std::string &extension, const std::string &content_type); - default_type(const default_type &other); - default_type &operator=(const default_type &other); - - std::string get_extension() const; - std::string get_content_type() const; - -private: - std::string extension_; - std::string content_type_; -}; - -} // namespace xlnt diff --git a/include/xlnt/packaging/manifest.hpp b/include/xlnt/packaging/manifest.hpp index 3a076444..82ae89c8 100644 --- a/include/xlnt/packaging/manifest.hpp +++ b/include/xlnt/packaging/manifest.hpp @@ -27,37 +27,236 @@ #include #include -#include -#include +#include #include namespace xlnt { +enum class content_type +{ + core_properties, + extended_properties, + custom_properties, + + calculation_chain, + chartsheet, + comments, + connections, + custom_property, + custom_xml_mappings, + dialogsheet, + drawings, + external_workbook_references, + metadata, + pivot_table, + pivot_table_cache_definition, + pivot_table_cache_records, + query_table, + shared_string_table, + shared_workbook_revision_headers, + shared_workbook, + revision_log, + shared_workbook_user_data, + single_cell_table_definitions, + styles, + table_definition, + theme, + volatile_dependencies, + workbook, + worksheet, + + unknown +}; + /// -/// The manifest keeps track of all files the OOXML package and -/// their type. +/// The manifest keeps track of all files in the OOXML package and +/// their type and relationships. /// class XLNT_CLASS manifest { public: - using default_types_container = std::unordered_map; - using override_types_container = std::unordered_map>; - + /// + /// Convenience method for clear_types() and clear_relationships() + /// void clear(); - bool has_default_type(const std::string &extension) const; - std::string get_default_type(const std::string &extension) const; - const default_types_container &get_default_types() const; - void add_default_type(const std::string &extension, const std::string &content_type); + /// + /// Convenince method for clear_default_types() and clear_override_types() + /// + void clear_types(); - bool has_override_type(const path &part) const; - std::string get_override_type(const path &part) const; - const override_types_container &get_override_types() const; - void add_override_type(const path &part, const std::string &content_type); + /// + /// Unregisters every default content type (i.e. type based on part extension). + /// + void clear_default_types(); + + /// + /// Unregisters every content type for every part except default types. + /// + void clear_override_types(); + + /// + /// Convenince method for clear_package_relationships() and clear_part_relationships() + /// + void clear_relationships(); + + /// + /// Unregisters every relationship with the package root as the source. + /// + void clear_package_relationships(); + + /// + /// Unregisters every relationship except those with the package root as the source. + /// + void clear_part_relationships(); + + /// + /// Returns true if the manifest contains a package relationship with the given type. + /// + bool has_package_relationship(relationship::type type) const; + + /// + /// Returns true if the manifest contains a relationship with the given type with part as the source. + /// + bool has_part_relationship(const path &part, relationship::type type) const; + + relationship get_package_relationship(relationship::type type) const; + + std::vector get_package_relationships(relationship::type type) const; + + relationship get_part_relationship(const path &part, relationship::type type) const; + + std::vector get_part_relationships(const path &part, relationship::type type) const; + + /// + /// Given the path to a part, returns the content type of the part as + /// a content_type enum value or content_type::unknown if it isn't known. + /// + content_type get_part_content_type(const path &part) const; + + /// + /// Given the path to a part, returns the content type of the part as a string. + /// + std::string get_part_content_type_string(const path &part) const; + + /// + /// Registers a part of the given type at the standard path and creates a + /// relationship with the new part as a target of "source". The type of the + /// relationship is inferred based on the provided types. + /// + void register_part(const path &part, const path &parent, const std::string &content_type, relationship::type relation); + + /// + /// + /// + void register_part(const path &parent, const relationship &rel, const std::string &content_type); + + /// + /// Registers a package part of the given type at the standard path and creates a + /// relationship with the package root as the source. The type of the + /// relationship is inferred based on the provided type. + /// + void register_package_part(const path &part, const std::string &content_type, relationship::type relation); + + /// + /// Unregisters the path of the part of the given type and removes all relationships + /// with the part as a source or target. + /// + void unregister_part(const path &part); + + /// + /// Returns true if the part at the given path has been registered in this manifest. + /// + bool has_part(const path &part) const; + + /// + /// Returns the path of every registered part in this manifest. + /// + std::vector get_parts() const; + + /// + /// Returns every registered relationship with the package root as the source. + /// + std::vector get_package_relationships() const; + + /// + /// Returns the package relationship with the given ID. + /// + relationship get_package_relationship(const std::string &rel_id); + + /// + /// Returns every registered relationship with the part of the given type + /// as the source. + /// + std::vector get_part_relationships(const path &part) const; + + /// + /// Returns the registered relationship with the part of the given type + /// as the source and the ID matching the provided ID. + /// + relationship get_part_relationship(const path &part, const std::string &rel_id) const; + + /// + /// + /// + std::string register_external_package_relationship(relationship::type type, const std::string &target_uri); + + /// + /// + /// + std::string register_external_package_relationship(relationship::type type, const std::string &target_uri, const std::string &rel_id); + + /// + /// + /// + std::string register_external_relationship(const path &source_part, relationship::type type, const std::string &target_uri); + + /// + /// + /// + std::string register_external_relationship(const path &source_part, relationship::type type, const std::string &target_uri, const std::string &rel_id); + + /// + /// Returns true if a default content type for the extension has been registered. + /// + bool has_default_type(const std::string &extension) const; + + /// + /// Returns a vector of all extensions with registered default content types. + /// + std::vector get_default_type_extensions() const; + + /// + /// Returns the registered default content type for parts of the given extension. + /// + std::string get_default_type(const std::string &extension) const; + + /// + /// Associates the given extension with the given content type. + /// + void register_default_type(const std::string &extension, const std::string &content_type); + + /// + /// Unregisters the default content type for the given extension. + /// + void unregister_default_type(const std::string &extension); private: - default_types_container default_types_; - override_types_container override_types_; + struct part_info + { + std::string content_type; + std::vector relationships; + }; + + std::string next_package_relationship_id() const;\ + + std::string next_relationship_id(const path &part) const; + + std::unordered_map> part_infos_; + + std::vector package_relationships_; + + std::unordered_map extension_content_type_map_; }; } // namespace xlnt diff --git a/include/xlnt/packaging/override_type.hpp b/include/xlnt/packaging/override_type.hpp deleted file mode 100644 index 645cb793..00000000 --- a/include/xlnt/packaging/override_type.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2014-2016 Thomas Fussell -// Copyright (c) 2010-2015 openpyxl -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, WRISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE -// -// @license: http://www.opensource.org/licenses/mit-license.php -// @author: see AUTHORS file -#pragma once - -#include - -#include -#include - -namespace xlnt { - -/// -/// An override_type applies a different content type to a file which -/// already has a default content type for its extension. -/// -class XLNT_CLASS override_type -{ -public: - override_type(); - override_type(const path &part, const std::string &content_type); - override_type(const override_type &other); - override_type &operator=(const override_type &other); - - path get_part() const; - std::string get_content_type() const; - -private: - path part_; - std::string content_type_; -}; - -} // namespace xlnt diff --git a/include/xlnt/packaging/relationship.hpp b/include/xlnt/packaging/relationship.hpp index 42b2af2c..e60dc560 100644 --- a/include/xlnt/packaging/relationship.hpp +++ b/include/xlnt/packaging/relationship.hpp @@ -26,6 +26,7 @@ #include #include +#include namespace xlnt { @@ -34,34 +35,61 @@ namespace xlnt { /// enum class XLNT_CLASS target_mode { + /// + /// The relationship references a resource that is external to the package. + /// + internal, /// /// The relationship references a part that is inside the package. /// - external, - /// - /// The relationship references a resource that is external to the package. - /// - internal + external }; /// /// All package relationships must be one of these defined types. /// -enum class relationship_type +enum class XLNT_CLASS relationship_type { - invalid, - hyperlink, - drawing, - worksheet, - chartsheet, - shared_strings, - styles, - theme, - extended_properties, - core_properties, - office_document, - custom_xml, - thumbnail + unknown, + + // Package + core_properties, + extended_properties, + custom_properties, + office_document, + thumbnail, + printer_settings, + + // SpreadsheetML + calculation_chain, + chartsheet, + comments, + connections, + custom_property, + custom_xml_mappings, + dialogsheet, + drawings, + external_workbook_references, + metadata, + pivot_table, + pivot_table_cache_definition, + pivot_table_cache_records, + query_table, + shared_string_table, + shared_workbook_revision_headers, + shared_workbook, + theme, + revision_log, + shared_workbook_user_data, + single_cell_table_definitions, + styles, + table_definition, + volatile_dependencies, + workbook, + worksheet, + + hyperlink, + image }; /// @@ -73,47 +101,44 @@ class XLNT_CLASS relationship public: using type = relationship_type; - static type type_from_string(const std::string &type_string); - - static std::string type_to_string(type t); - relationship(); - relationship(const std::string &t, const std::string &r_id = "", const std::string &target_uri = ""); - - relationship(type t, const std::string &r_id = "", const std::string &target_uri = ""); + relationship(const std::string &id, type t, const path &target, target_mode mode); /// - /// gets a string that identifies the relationship. + /// Returns a string of the form rId# that identifies the relationship. /// std::string get_id() const; - /// - /// gets the URI of the package or part that owns the relationship. - /// - std::string get_source_uri() const; + /// + /// Returns the type of this relationship. + /// + type get_type() const; /// - /// gets a value that indicates whether the target of the relationship is or External to the Package. + /// Returns whether the target of the relationship is internal or external to the package. /// target_mode get_target_mode() const; /// - /// gets the URI of the target resource of the relationship. + /// Returns the URI of the package part this relationship points to. /// - std::string get_target_uri() const; - - type get_type() const; - - std::string get_type_string() const; + path get_target_uri() const; + /// + /// Returns true if and only if rhs is equal to this relationship. + /// bool operator==(const relationship &rhs) const; + /// + /// Returns true if and only if rhs is not equal to this relationship. + /// + bool operator!=(const relationship &rhs) const; + private: + std::string id_; type type_; - std::string id_; - std::string source_uri_; - std::string target_uri_; + path target_uri_; target_mode target_mode_; }; diff --git a/include/xlnt/utils/path.hpp b/include/xlnt/utils/path.hpp index 4b652527..57f924bc 100644 --- a/include/xlnt/utils/path.hpp +++ b/include/xlnt/utils/path.hpp @@ -106,7 +106,12 @@ public: /// /// Return the last component of this path. /// - std::string basename(); + std::string basename() const; + + /// + /// Return the part of the path following the last . in the basename. + /// + std::string extension() const; // conversion diff --git a/include/xlnt/workbook/workbook.hpp b/include/xlnt/workbook/workbook.hpp index a387685f..b7acd4fd 100644 --- a/include/xlnt/workbook/workbook.hpp +++ b/include/xlnt/workbook/workbook.hpp @@ -68,7 +68,10 @@ enum class calendar; enum class relationship_type; namespace detail { +struct stylesheet; struct workbook_impl; +class xlsx_consumer; +class xlsx_producer; } // namespace detail /// @@ -183,14 +186,14 @@ public: /// This may throw an exception if the sheet isn't found. /// Use workbook::contains(const std::string &) to make sure the sheet exists. /// - worksheet get_sheet_by_name(const std::string &sheet_name); + worksheet get_sheet_by_title(const std::string &sheet_name); /// /// Return the const worksheet with the given name. /// This may throw an exception if the sheet isn't found. /// Use workbook::contains(const std::string &) to make sure the sheet exists. /// - const worksheet get_sheet_by_name(const std::string &sheet_name) const; + const worksheet get_sheet_by_title(const std::string &sheet_name) const; /// /// Return the worksheet at the given index. @@ -202,6 +205,16 @@ public: /// const worksheet get_sheet_by_index(std::size_t index) const; + /// + /// Return the worksheet with a sheetId of id. + /// + worksheet get_sheet_by_id(std::size_t id); + + /// + /// Return the const worksheet with a sheetId of id. + /// + const worksheet get_sheet_by_id(std::size_t id) const; + /// /// Return true if this workbook contains a sheet with the given name. /// @@ -360,15 +373,15 @@ public: // serialization - bool save(std::vector &data); - bool save(const std::string &filename); - bool save(const xlnt::path &filename); - bool save(std::ostream &stream); + void save(std::vector &data); + void save(const std::string &filename); + void save(const xlnt::path &filename); + void save(std::ostream &stream); - bool load(const std::vector &data); - bool load(const std::string &filename); - bool load(const xlnt::path &filename); - bool load(std::istream &stream); + void load(const std::vector &data); + void load(const std::string &filename); + void load(const xlnt::path &filename); + void load(std::istream &stream); void set_code_name(const std::string &code_name); @@ -396,22 +409,12 @@ public: style &create_style(const std::string &name); std::size_t add_style(const style &new_style); void clear_styles(); - const std::vector