mirror of
https://github.com/tfussell/xlnt.git
synced 2024-03-22 13:11:17 +08:00
keep cleaning up iterators, documenting classes, and moving implementations to source files
This commit is contained in:
parent
47b81a83de
commit
acfb5c642b
|
@ -27,9 +27,9 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include <xlnt/xlnt_config.hpp>
|
#include <xlnt/xlnt_config.hpp> // for XLNT_CLASS, XLNT_FUNCTION
|
||||||
#include <xlnt/cell/cell_type.hpp>
|
#include <xlnt/cell/cell_type.hpp> // for cell_type
|
||||||
#include <xlnt/cell/types.hpp>
|
#include <xlnt/cell/index_types.hpp> // for column_t, row_t
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include <xlnt/xlnt_config.hpp>
|
#include <xlnt/xlnt_config.hpp>
|
||||||
#include <xlnt/cell/types.hpp>
|
#include <xlnt/cell/index_types.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,11 @@
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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.
|
||||||
|
/// </summary>
|
||||||
class XLNT_CLASS default_type
|
class XLNT_CLASS default_type
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// High-level properties of the document.
|
/// High-level properties of the OOXML document.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
class XLNT_CLASS document_properties
|
class XLNT_CLASS document_properties
|
||||||
{
|
{
|
||||||
|
|
|
@ -32,6 +32,10 @@
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The manifest keeps track of all files the OOXML package and
|
||||||
|
/// their type.
|
||||||
|
/// </summary>
|
||||||
class XLNT_CLASS manifest
|
class XLNT_CLASS manifest
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -29,6 +29,10 @@
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An override_type applies a different content type to a file which
|
||||||
|
/// already has a default content type for its extension.
|
||||||
|
/// </summary>
|
||||||
class XLNT_CLASS override_type
|
class XLNT_CLASS override_type
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -67,134 +67,41 @@ class XLNT_CLASS relationship
|
||||||
custom_xml
|
custom_xml
|
||||||
};
|
};
|
||||||
|
|
||||||
static type type_from_string(const std::string &type_string)
|
static type type_from_string(const std::string &type_string);
|
||||||
{
|
|
||||||
if (type_string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties")
|
|
||||||
{
|
|
||||||
return type::extended_properties;
|
|
||||||
}
|
|
||||||
else if (type_string == "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties")
|
|
||||||
{
|
|
||||||
return type::core_properties;
|
|
||||||
}
|
|
||||||
else if (type_string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument")
|
|
||||||
{
|
|
||||||
return type::office_document;
|
|
||||||
}
|
|
||||||
else if (type_string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet")
|
|
||||||
{
|
|
||||||
return type::worksheet;
|
|
||||||
}
|
|
||||||
else if (type_string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings")
|
|
||||||
{
|
|
||||||
return type::shared_strings;
|
|
||||||
}
|
|
||||||
else if (type_string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles")
|
|
||||||
{
|
|
||||||
return type::styles;
|
|
||||||
}
|
|
||||||
else if (type_string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme")
|
|
||||||
{
|
|
||||||
return type::theme;
|
|
||||||
}
|
|
||||||
else if (type_string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink")
|
|
||||||
{
|
|
||||||
return type::hyperlink;
|
|
||||||
}
|
|
||||||
else if (type_string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chartsheet")
|
|
||||||
{
|
|
||||||
return type::chartsheet;
|
|
||||||
}
|
|
||||||
else if (type_string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml")
|
|
||||||
{
|
|
||||||
return type::custom_xml;
|
|
||||||
}
|
|
||||||
|
|
||||||
return type::invalid;
|
static std::string type_to_string(type t);
|
||||||
}
|
|
||||||
|
|
||||||
static std::string type_to_string(type t)
|
|
||||||
{
|
|
||||||
switch (t)
|
|
||||||
{
|
|
||||||
case type::extended_properties:
|
|
||||||
return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties";
|
|
||||||
case type::core_properties:
|
|
||||||
return "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties";
|
|
||||||
case type::office_document:
|
|
||||||
return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument";
|
|
||||||
case type::worksheet:
|
|
||||||
return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet";
|
|
||||||
case type::shared_strings:
|
|
||||||
return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings";
|
|
||||||
case type::styles:
|
|
||||||
return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles";
|
|
||||||
case type::theme:
|
|
||||||
return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme";
|
|
||||||
case type::hyperlink:
|
|
||||||
return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink";
|
|
||||||
case type::chartsheet:
|
|
||||||
return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chartsheet";
|
|
||||||
case type::custom_xml:
|
|
||||||
return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml";
|
|
||||||
default:
|
|
||||||
return "??";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
relationship();
|
relationship();
|
||||||
relationship(const std::string &t, const std::string &r_id = "", const std::string &target_uri = "")
|
|
||||||
: relationship(type_from_string(t), r_id, target_uri)
|
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(type t, const std::string &r_id = "", const std::string &target_uri = "");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// gets a string that identifies the relationship.
|
/// gets a string that identifies the relationship.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
std::string get_id() const
|
std::string get_id() const;
|
||||||
{
|
|
||||||
return id_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// gets the URI of the package or part that owns the relationship.
|
/// gets the URI of the package or part that owns the relationship.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
std::string get_source_uri() const
|
std::string get_source_uri() const;
|
||||||
{
|
|
||||||
return source_uri_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// gets a value that indicates whether the target of the relationship is or External to the Package.
|
/// gets a value that indicates whether the target of the relationship is or External to the Package.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
target_mode get_target_mode() const
|
target_mode get_target_mode() const;
|
||||||
{
|
|
||||||
return target_mode_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// gets the URI of the target resource of the relationship.
|
/// gets the URI of the target resource of the relationship.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
std::string get_target_uri() const
|
std::string get_target_uri() const;
|
||||||
{
|
|
||||||
return target_uri_;
|
|
||||||
}
|
|
||||||
|
|
||||||
type get_type() const
|
type get_type() const;
|
||||||
{
|
|
||||||
return type_;
|
|
||||||
}
|
|
||||||
std::string get_type_string() const
|
|
||||||
{
|
|
||||||
return type_to_string(type_);
|
|
||||||
}
|
|
||||||
|
|
||||||
friend bool operator==(const relationship &left, const relationship &right)
|
std::string get_type_string() const;
|
||||||
{
|
|
||||||
return left.type_ == right.type_ && left.id_ == right.id_ && left.source_uri_ == right.source_uri_ &&
|
bool operator==(const relationship &rhs) const;
|
||||||
left.target_uri_ == right.target_uri_ && left.target_mode_ == right.target_mode_;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
type type_;
|
type type_;
|
||||||
|
|
|
@ -33,6 +33,9 @@ namespace xlnt {
|
||||||
|
|
||||||
class xml_document;
|
class xml_document;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Manages converting comments to and from XML.
|
||||||
|
/// </summary>
|
||||||
class XLNT_CLASS comment_serializer
|
class XLNT_CLASS comment_serializer
|
||||||
{
|
{
|
||||||
comment_serializer(worksheet sheet);
|
comment_serializer(worksheet sheet);
|
||||||
|
|
|
@ -32,6 +32,9 @@ namespace xlnt {
|
||||||
class manifest;
|
class manifest;
|
||||||
class xml_document;
|
class xml_document;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Manages converting a manifest to and from XML.
|
||||||
|
/// </summary>
|
||||||
class XLNT_CLASS manifest_serializer
|
class XLNT_CLASS manifest_serializer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -32,6 +32,9 @@ namespace xlnt {
|
||||||
|
|
||||||
class xml_document;
|
class xml_document;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Manages converting a set of shared strings to and from XML.
|
||||||
|
/// </summary>
|
||||||
class XLNT_CLASS shared_strings_serializer
|
class XLNT_CLASS shared_strings_serializer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -32,6 +32,9 @@ namespace xlnt {
|
||||||
class theme;
|
class theme;
|
||||||
class xml_document;
|
class xml_document;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Manages converting a theme to and from XML.
|
||||||
|
/// </summary>
|
||||||
class XLNT_CLASS theme_serializer
|
class XLNT_CLASS theme_serializer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -39,6 +39,9 @@ class zip_file;
|
||||||
class xml_document;
|
class xml_document;
|
||||||
class xml_node;
|
class xml_node;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Manages converting workbook to and from XML.
|
||||||
|
/// </summary>
|
||||||
class XLNT_CLASS workbook_serializer
|
class XLNT_CLASS workbook_serializer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -36,6 +36,9 @@ class workbook;
|
||||||
class worksheet;
|
class worksheet;
|
||||||
class xml_document;
|
class xml_document;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Manages converting a worksheet to and from XML.
|
||||||
|
/// </summary>
|
||||||
class XLNT_CLASS worksheet_serializer
|
class XLNT_CLASS worksheet_serializer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -34,6 +34,9 @@ namespace detail { struct xml_document_impl; }
|
||||||
class xml_node;
|
class xml_node;
|
||||||
class xml_serializer;
|
class xml_serializer;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Abstracts an XML document from a particular implementation.
|
||||||
|
/// </summary>
|
||||||
class XLNT_CLASS xml_document
|
class XLNT_CLASS xml_document
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -33,6 +33,9 @@ namespace detail { struct xml_node_impl; }
|
||||||
|
|
||||||
class xml_document;
|
class xml_document;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Abstracts an XML node from a particular implementation.
|
||||||
|
/// </summary>
|
||||||
class XLNT_CLASS xml_node
|
class XLNT_CLASS xml_node
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -31,6 +31,9 @@ namespace xlnt {
|
||||||
class xml_document;
|
class xml_document;
|
||||||
class xml_node;
|
class xml_node;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts XML documents to and from raw strings.
|
||||||
|
/// </summary>
|
||||||
class XLNT_CLASS xml_serializer
|
class XLNT_CLASS xml_serializer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
|
|
||||||
#include <xlnt/xlnt_config.hpp>
|
#include <xlnt/xlnt_config.hpp>
|
||||||
#include <xlnt/utils/hash_combine.hpp>
|
#include <xlnt/utils/hash_combine.hpp>
|
||||||
|
#include <xlnt/styles/horizontal_alignment.hpp>
|
||||||
|
#include <xlnt/styles/vertical_alignment.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
@ -34,82 +36,25 @@ namespace xlnt {
|
||||||
class XLNT_CLASS alignment
|
class XLNT_CLASS alignment
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum class horizontal_alignment
|
bool get_wrap_text() const;
|
||||||
{
|
|
||||||
none,
|
|
||||||
general,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
center,
|
|
||||||
center_continuous,
|
|
||||||
justify
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class vertical_alignment
|
void set_wrap_text(bool wrap_text);
|
||||||
{
|
|
||||||
none,
|
|
||||||
bottom,
|
|
||||||
top,
|
|
||||||
center,
|
|
||||||
justify
|
|
||||||
};
|
|
||||||
|
|
||||||
bool get_wrap_text() const
|
bool has_horizontal() const;
|
||||||
{
|
|
||||||
return wrap_text_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_wrap_text(bool wrap_text)
|
horizontal_alignment get_horizontal() const;
|
||||||
{
|
|
||||||
wrap_text_ = wrap_text;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool has_horizontal() const
|
void set_horizontal(horizontal_alignment horizontal);
|
||||||
{
|
|
||||||
return horizontal_ != horizontal_alignment::none;
|
|
||||||
}
|
|
||||||
|
|
||||||
horizontal_alignment get_horizontal() const
|
bool has_vertical() const;
|
||||||
{
|
|
||||||
return horizontal_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_horizontal(horizontal_alignment horizontal)
|
vertical_alignment get_vertical() const;
|
||||||
{
|
|
||||||
horizontal_ = horizontal;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool has_vertical() const
|
void set_vertical(vertical_alignment vertical);
|
||||||
{
|
|
||||||
return vertical_ != vertical_alignment::none;
|
|
||||||
}
|
|
||||||
|
|
||||||
vertical_alignment get_vertical() const
|
bool operator==(const alignment &other) const;
|
||||||
{
|
|
||||||
return vertical_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_vertical(vertical_alignment vertical)
|
std::size_t hash() const;
|
||||||
{
|
|
||||||
vertical_ = vertical;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const alignment &other) const
|
|
||||||
{
|
|
||||||
return hash() == other.hash();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t hash() const
|
|
||||||
{
|
|
||||||
std::size_t seed = 0;
|
|
||||||
hash_combine(seed, wrap_text_);
|
|
||||||
hash_combine(seed, shrink_to_fit_);
|
|
||||||
hash_combine(seed, static_cast<std::size_t>(horizontal_));
|
|
||||||
hash_combine(seed, static_cast<std::size_t>(vertical_));
|
|
||||||
hash_combine(seed, text_rotation_);
|
|
||||||
hash_combine(seed, indent_);
|
|
||||||
return seed;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
horizontal_alignment horizontal_ = horizontal_alignment::none;
|
horizontal_alignment horizontal_ = horizontal_alignment::none;
|
||||||
|
|
|
@ -27,19 +27,15 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
#include <xlnt/xlnt_config.hpp>
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
#include <xlnt/styles/diagonal_direction.hpp>
|
||||||
#include <xlnt/styles/side.hpp>
|
#include <xlnt/styles/side.hpp>
|
||||||
#include <xlnt/utils/hash_combine.hpp>
|
#include <xlnt/utils/hash_combine.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
enum class XLNT_CLASS diagonal_direction
|
/// <summary>
|
||||||
{
|
/// Describes the border style of a particular cell.
|
||||||
none,
|
/// </summary>
|
||||||
up,
|
|
||||||
down,
|
|
||||||
both
|
|
||||||
};
|
|
||||||
|
|
||||||
class XLNT_CLASS border
|
class XLNT_CLASS border
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -70,36 +66,9 @@ class XLNT_CLASS border
|
||||||
|
|
||||||
diagonal_direction diagonal_direction_ = diagonal_direction::none;
|
diagonal_direction diagonal_direction_ = diagonal_direction::none;
|
||||||
|
|
||||||
bool operator==(const border &other) const
|
bool operator==(const border &other) const;
|
||||||
{
|
|
||||||
return hash() == other.hash();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t hash() const
|
std::size_t hash() const;
|
||||||
{
|
|
||||||
std::size_t seed = 0;
|
|
||||||
|
|
||||||
hash_combine(seed, start_assigned);
|
|
||||||
if (start_assigned) hash_combine(seed, start.hash());
|
|
||||||
hash_combine(seed, end_assigned);
|
|
||||||
if (end_assigned) hash_combine(seed, end.hash());
|
|
||||||
hash_combine(seed, left_assigned);
|
|
||||||
if (left_assigned) hash_combine(seed, left.hash());
|
|
||||||
hash_combine(seed, right_assigned);
|
|
||||||
if (right_assigned) hash_combine(seed, right.hash());
|
|
||||||
hash_combine(seed, top_assigned);
|
|
||||||
if (top_assigned) hash_combine(seed, top.hash());
|
|
||||||
hash_combine(seed, bottom_assigned);
|
|
||||||
if (bottom_assigned) hash_combine(seed, bottom.hash());
|
|
||||||
hash_combine(seed, diagonal_assigned);
|
|
||||||
if (diagonal_assigned) hash_combine(seed, diagonal.hash());
|
|
||||||
hash_combine(seed, vertical_assigned);
|
|
||||||
if (vertical_assigned) hash_combine(seed, vertical.hash());
|
|
||||||
hash_combine(seed, horizontal_assigned);
|
|
||||||
if (horizontal_assigned) hash_combine(seed, horizontal.hash());
|
|
||||||
|
|
||||||
return seed;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace xlnt
|
} // namespace xlnt
|
||||||
|
|
|
@ -30,9 +30,15 @@
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Colors can be applied to many parts of a cell's style.
|
||||||
|
/// </summary>
|
||||||
class XLNT_CLASS color
|
class XLNT_CLASS color
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/// <summary>
|
||||||
|
/// Some colors are references to colors rather than having a particular RGB value.
|
||||||
|
/// </summary>
|
||||||
enum class type
|
enum class type
|
||||||
{
|
{
|
||||||
indexed,
|
indexed,
|
||||||
|
|
43
include/xlnt/styles/diagonal_direction.hpp
Normal file
43
include/xlnt/styles/diagonal_direction.hpp
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
// Copyright (c) 2014-2015 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 <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
|
namespace xlnt {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cells can have borders that go from the top-left to bottom-right
|
||||||
|
/// or from the top-right to bottom-left, or both, or neither.
|
||||||
|
/// Used by style->border.
|
||||||
|
/// </summary>
|
||||||
|
enum class XLNT_CLASS diagonal_direction
|
||||||
|
{
|
||||||
|
none,
|
||||||
|
up,
|
||||||
|
down,
|
||||||
|
both
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace xlnt
|
|
@ -29,6 +29,9 @@
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Describes the fill style of a particular cell.
|
||||||
|
/// </summary>
|
||||||
class XLNT_CLASS fill
|
class XLNT_CLASS fill
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -33,6 +33,9 @@ namespace xlnt {
|
||||||
|
|
||||||
class style;
|
class style;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Describes the font style of a particular cell.
|
||||||
|
/// </summary>
|
||||||
class XLNT_CLASS font
|
class XLNT_CLASS font
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
44
include/xlnt/styles/horizontal_alignment.hpp
Normal file
44
include/xlnt/styles/horizontal_alignment.hpp
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
// Copyright (c) 2014-2015 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 <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
|
namespace xlnt {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Text can be aligned horizontally in these enumerated ways.
|
||||||
|
/// </summary>
|
||||||
|
enum class XLNT_CLASS horizontal_alignment
|
||||||
|
{
|
||||||
|
none,
|
||||||
|
general,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
center,
|
||||||
|
center_continuous,
|
||||||
|
justify
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace xlnt
|
|
@ -28,6 +28,9 @@
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A named style is simply a style that can be referred to by name rather than by index.
|
||||||
|
/// </summary>
|
||||||
class XLNT_CLASS named_style
|
class XLNT_CLASS named_style
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -31,6 +31,11 @@
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
enum class calendar;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Describes the number formatting applied to text and numbers within a certain cell.
|
||||||
|
/// </summary>
|
||||||
class XLNT_CLASS number_format
|
class XLNT_CLASS number_format
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -81,33 +86,19 @@ class XLNT_CLASS number_format
|
||||||
|
|
||||||
std::string get_format_string() const;
|
std::string get_format_string() const;
|
||||||
|
|
||||||
bool has_id() const
|
bool has_id() const;
|
||||||
{
|
void set_id(std::size_t id);
|
||||||
return id_set_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_id(std::size_t id)
|
std::size_t get_id() const;
|
||||||
{
|
|
||||||
id_ = id;
|
|
||||||
id_set_ = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t get_id() const
|
|
||||||
{
|
|
||||||
if(!id_set_)
|
|
||||||
{
|
|
||||||
throw std::runtime_error("number format doesn't have an id");
|
|
||||||
}
|
|
||||||
|
|
||||||
return id_;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t hash() const;
|
std::size_t hash() const;
|
||||||
|
|
||||||
bool operator==(const number_format &other) const
|
std::string format(const std::string &text) const;
|
||||||
{
|
std::string format(long double number, calendar base_date) const;
|
||||||
return hash() == other.hash();
|
|
||||||
}
|
bool is_date_format() const;
|
||||||
|
|
||||||
|
bool operator==(const number_format &other) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool id_set_;
|
bool id_set_;
|
||||||
|
|
|
@ -30,6 +30,9 @@
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Describes the protection style of a particular cell.
|
||||||
|
/// </summary>
|
||||||
class XLNT_CLASS protection
|
class XLNT_CLASS protection
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -48,6 +48,9 @@ enum class XLNT_CLASS border_style
|
||||||
thin
|
thin
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Describes the one of the sides of a border of a particular cell.
|
||||||
|
/// </summary>
|
||||||
class XLNT_CLASS side
|
class XLNT_CLASS side
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -35,6 +35,9 @@ namespace xlnt {
|
||||||
|
|
||||||
class workbook;
|
class workbook;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Describes the entirety of the styling of a particular cell.
|
||||||
|
/// </summary>
|
||||||
class XLNT_CLASS style
|
class XLNT_CLASS style
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
42
include/xlnt/styles/vertical_alignment.hpp
Normal file
42
include/xlnt/styles/vertical_alignment.hpp
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
// Copyright (c) 2014-2015 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 <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
|
namespace xlnt {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Text can be aligned vertically in these enumerated ways.
|
||||||
|
/// </summary>
|
||||||
|
enum class XLNT_CLASS vertical_alignment
|
||||||
|
{
|
||||||
|
none,
|
||||||
|
bottom,
|
||||||
|
top,
|
||||||
|
center,
|
||||||
|
justify
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace xlnt
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#include <xlnt/cell/types.hpp>
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <xlnt/xlnt_config.hpp>
|
#include <xlnt/xlnt_config.hpp>
|
||||||
#include <xlnt/cell/types.hpp>
|
#include <xlnt/cell/index_types.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,9 @@
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A datetime is a combination of a date and a time.
|
||||||
|
/// </summary>
|
||||||
struct XLNT_CLASS datetime
|
struct XLNT_CLASS datetime
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
// @author: see AUTHORS file
|
// @author: see AUTHORS file
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
// An shortcut for including all possible exceptions in xlnt.
|
||||||
|
|
||||||
#include <xlnt/utils/attribute_error.hpp>
|
#include <xlnt/utils/attribute_error.hpp>
|
||||||
#include <xlnt/utils/cell_coordinates_exception.hpp>
|
#include <xlnt/utils/cell_coordinates_exception.hpp>
|
||||||
#include <xlnt/utils/column_string_index_exception.hpp>
|
#include <xlnt/utils/column_string_index_exception.hpp>
|
||||||
|
|
|
@ -35,6 +35,9 @@
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
// TODO: Can this be in source->detail, or must it be in a header?
|
// TODO: Can this be in source->detail, or must it be in a header?
|
||||||
|
/// <summary>
|
||||||
|
/// Return a value by combining the hashed value of v (using std::hash) with seed.
|
||||||
|
/// </summary>
|
||||||
template <class T>
|
template <class T>
|
||||||
inline void XLNT_FUNCTION hash_combine(std::size_t &seed, const T &v)
|
inline void XLNT_FUNCTION hash_combine(std::size_t &seed, const T &v)
|
||||||
{
|
{
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Error for trying to open a non-ooxml file.
|
/// Error for trying to open a non-OOXML file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
class XLNT_CLASS invalid_file_exception : public std::runtime_error
|
class XLNT_CLASS invalid_file_exception : public std::runtime_error
|
||||||
{
|
{
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Error when a references number format is not in the stylesheet.
|
/// Error when a referenced number format is not in the stylesheet.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
class XLNT_CLASS missing_number_format : public std::runtime_error
|
class XLNT_CLASS missing_number_format : public std::runtime_error
|
||||||
{
|
{
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Error for badly formatted named ranges.
|
/// Error for incorrectly formatted named ranges.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
class XLNT_CLASS named_range_exception : public std::runtime_error
|
class XLNT_CLASS named_range_exception : public std::runtime_error
|
||||||
{
|
{
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Security information about the document.
|
/// Security information about the OOXML document.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
class XLNT_CLASS document_security
|
class XLNT_CLASS document_security
|
||||||
{
|
{
|
||||||
|
|
|
@ -27,6 +27,9 @@
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A reference to an external workbook for use in formulae.
|
||||||
|
/// </summary>
|
||||||
class XLNT_CLASS external_book
|
class XLNT_CLASS external_book
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
|
@ -33,8 +33,13 @@ namespace xlnt {
|
||||||
class range_reference;
|
class range_reference;
|
||||||
class worksheet;
|
class worksheet;
|
||||||
|
|
||||||
|
//TODO: why is this not in a class?
|
||||||
std::vector<std::pair<std::string, std::string>> XLNT_FUNCTION split_named_range(const std::string &named_range_string);
|
std::vector<std::pair<std::string, std::string>> XLNT_FUNCTION split_named_range(const std::string &named_range_string);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A 2D range of cells in a worksheet that is referred to by name.
|
||||||
|
/// ws->get_range("A1:B2") could be replaced by ws->get_range("range1")
|
||||||
|
/// </summary>
|
||||||
class XLNT_CLASS named_range
|
class XLNT_CLASS named_range
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -26,6 +26,10 @@
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A theme is a combination of fonts, colors, and effects.
|
||||||
|
/// This isn't really supported yet.
|
||||||
|
/// </summary>
|
||||||
class XLNT_CLASS theme
|
class XLNT_CLASS theme
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
|
@ -35,78 +35,33 @@ namespace xlnt {
|
||||||
class cell;
|
class cell;
|
||||||
class range_reference;
|
class range_reference;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A cell vector is a linear (1D) range of cells, either vertical or horizontal
|
||||||
|
/// depending on the major order specified in the constructor.
|
||||||
|
/// </summary>
|
||||||
class XLNT_CLASS cell_vector
|
class XLNT_CLASS cell_vector
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
template <bool is_const = true>
|
class XLNT_CLASS iterator : public std::iterator<std::bidirectional_iterator_tag, cell>
|
||||||
class XLNT_CLASS common_iterator : public std::iterator<std::bidirectional_iterator_tag, cell>
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
common_iterator(worksheet ws, const cell_reference &start_cell, major_order order = major_order::row)
|
iterator(worksheet ws, const cell_reference &start_cell, major_order order = major_order::row);
|
||||||
: ws_(ws), current_cell_(start_cell), range_(start_cell.to_range()), order_(order)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
common_iterator(const common_iterator<false> &other)
|
iterator(const iterator &other);
|
||||||
{
|
|
||||||
*this = other;
|
|
||||||
}
|
|
||||||
|
|
||||||
cell operator*();
|
cell operator*();
|
||||||
|
|
||||||
bool operator==(const common_iterator &other) const
|
bool operator==(const iterator &other) const;
|
||||||
{
|
|
||||||
return ws_ == other.ws_ && current_cell_ == other.current_cell_ && order_ == other.order_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=(const common_iterator &other) const
|
bool operator!=(const iterator &other) const;
|
||||||
{
|
|
||||||
return !(*this == other);
|
|
||||||
}
|
|
||||||
|
|
||||||
common_iterator &operator--()
|
iterator &operator--();
|
||||||
{
|
|
||||||
if (order_ == major_order::row)
|
|
||||||
{
|
|
||||||
current_cell_.set_column_index(current_cell_.get_column_index() - 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
current_cell_.set_row(current_cell_.get_row() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
iterator operator--(int);
|
||||||
}
|
|
||||||
|
|
||||||
common_iterator operator--(int)
|
iterator &operator++();
|
||||||
{
|
|
||||||
iterator old = *this;
|
|
||||||
--*this;
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
common_iterator &operator++()
|
iterator operator++(int);
|
||||||
{
|
|
||||||
if (order_ == major_order::row)
|
|
||||||
{
|
|
||||||
current_cell_.set_column_index(current_cell_.get_column_index() + 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
current_cell_.set_row(current_cell_.get_row() + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
common_iterator operator++(int)
|
|
||||||
{
|
|
||||||
iterator old = *this;
|
|
||||||
++*this;
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend class common_iterator<true>;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
worksheet ws_;
|
worksheet ws_;
|
||||||
|
@ -115,8 +70,33 @@ class XLNT_CLASS cell_vector
|
||||||
major_order order_;
|
major_order order_;
|
||||||
};
|
};
|
||||||
|
|
||||||
using iterator = common_iterator<false>;
|
class XLNT_CLASS const_iterator : public std::iterator<std::bidirectional_iterator_tag, const cell>
|
||||||
using const_iterator = common_iterator<true>;
|
{
|
||||||
|
public:
|
||||||
|
const_iterator(worksheet ws, const cell_reference &start_cell, major_order order = major_order::row);
|
||||||
|
|
||||||
|
const_iterator(const const_iterator &other);
|
||||||
|
|
||||||
|
const cell operator*();
|
||||||
|
|
||||||
|
bool operator==(const const_iterator &other) const;
|
||||||
|
|
||||||
|
bool operator!=(const const_iterator &other) const;
|
||||||
|
|
||||||
|
const_iterator &operator--();
|
||||||
|
|
||||||
|
const_iterator operator--(int);
|
||||||
|
|
||||||
|
const_iterator &operator++();
|
||||||
|
|
||||||
|
const_iterator operator++(int);
|
||||||
|
|
||||||
|
private:
|
||||||
|
worksheet ws_;
|
||||||
|
cell_reference current_cell_;
|
||||||
|
range_reference range_;
|
||||||
|
major_order order_;
|
||||||
|
};
|
||||||
|
|
||||||
cell_vector(worksheet ws, const range_reference &ref, major_order order = major_order::row);
|
cell_vector(worksheet ws, const range_reference &ref, major_order order = major_order::row);
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,10 @@
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Properties applied to a column in a worksheet.
|
||||||
|
/// Columns can have a size and a style.
|
||||||
|
/// </summary>
|
||||||
class XLNT_CLASS column_properties
|
class XLNT_CLASS column_properties
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -14,30 +14,16 @@ class XLNT_CLASS footer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
footer();
|
footer();
|
||||||
void set_text(const std::string &text)
|
|
||||||
{
|
void set_text(const std::string &text);
|
||||||
default_ = false;
|
|
||||||
text_ = text;
|
void set_font_name(const std::string &font_name);
|
||||||
}
|
|
||||||
void set_font_name(const std::string &font_name)
|
void set_font_size(std::size_t font_size);
|
||||||
{
|
|
||||||
default_ = false;
|
void set_font_color(const std::string &font_color);
|
||||||
font_name_ = font_name;
|
|
||||||
}
|
bool is_default() const;
|
||||||
void set_font_size(std::size_t font_size)
|
|
||||||
{
|
|
||||||
default_ = false;
|
|
||||||
font_size_ = font_size;
|
|
||||||
}
|
|
||||||
void set_font_color(const std::string &font_color)
|
|
||||||
{
|
|
||||||
default_ = false;
|
|
||||||
font_color_ = font_color;
|
|
||||||
}
|
|
||||||
bool is_default() const
|
|
||||||
{
|
|
||||||
return default_;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool default_;
|
bool default_;
|
||||||
|
|
|
@ -14,30 +14,16 @@ class XLNT_CLASS header
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
header();
|
header();
|
||||||
void set_text(const std::string &text)
|
|
||||||
{
|
void set_text(const std::string &text);
|
||||||
default_ = false;
|
|
||||||
text_ = text;
|
void set_font_name(const std::string &font_name);
|
||||||
}
|
|
||||||
void set_font_name(const std::string &font_name)
|
void set_font_size(std::size_t font_size);
|
||||||
{
|
|
||||||
default_ = false;
|
void set_font_color(const std::string &font_color);
|
||||||
font_name_ = font_name;
|
|
||||||
}
|
bool is_default() const;
|
||||||
void set_font_size(std::size_t font_size)
|
|
||||||
{
|
|
||||||
default_ = false;
|
|
||||||
font_size_ = font_size;
|
|
||||||
}
|
|
||||||
void set_font_color(const std::string &font_color)
|
|
||||||
{
|
|
||||||
default_ = false;
|
|
||||||
font_color_ = font_color;
|
|
||||||
}
|
|
||||||
bool is_default() const
|
|
||||||
{
|
|
||||||
return default_;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool default_;
|
bool default_;
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Worksheet header and footer
|
/// Worksheet header and footer for all six possible positions.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
class XLNT_CLASS header_footer
|
class XLNT_CLASS header_footer
|
||||||
{
|
{
|
||||||
|
|
|
@ -26,6 +26,9 @@
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines whether iterating a range returns columns or rows sequentially.
|
||||||
|
/// </summary>
|
||||||
enum class XLNT_CLASS major_order
|
enum class XLNT_CLASS major_order
|
||||||
{
|
{
|
||||||
column,
|
column,
|
||||||
|
|
|
@ -27,6 +27,9 @@
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The orientation of the worksheet when it is printed.
|
||||||
|
/// </summary>
|
||||||
enum class XLNT_CLASS orientation
|
enum class XLNT_CLASS orientation
|
||||||
{
|
{
|
||||||
portrait,
|
portrait,
|
||||||
|
|
|
@ -27,6 +27,9 @@
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The types of page breaks.
|
||||||
|
/// </summary>
|
||||||
enum class XLNT_CLASS page_break
|
enum class XLNT_CLASS page_break
|
||||||
{
|
{
|
||||||
none = 0,
|
none = 0,
|
||||||
|
|
|
@ -27,6 +27,9 @@
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Describes the margins around a worksheet for printing.
|
||||||
|
/// </summary>
|
||||||
class XLNT_CLASS page_margins
|
class XLNT_CLASS page_margins
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -31,6 +31,9 @@
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Describes how a worksheet will be converted into a page during printing.
|
||||||
|
/// </summary>
|
||||||
struct XLNT_CLASS page_setup
|
struct XLNT_CLASS page_setup
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -27,6 +27,9 @@
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A fixed portion of a worksheet.
|
||||||
|
/// </summary>
|
||||||
class XLNT_CLASS pane
|
class XLNT_CLASS pane
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,6 +27,9 @@
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The possible paper sizes for printing.
|
||||||
|
/// </summary>
|
||||||
enum class XLNT_CLASS paper_size
|
enum class XLNT_CLASS paper_size
|
||||||
{
|
{
|
||||||
letter = 1,
|
letter = 1,
|
||||||
|
|
|
@ -30,95 +30,22 @@
|
||||||
#include <xlnt/xlnt_config.hpp>
|
#include <xlnt/xlnt_config.hpp>
|
||||||
#include <xlnt/worksheet/cell_vector.hpp>
|
#include <xlnt/worksheet/cell_vector.hpp>
|
||||||
#include <xlnt/worksheet/major_order.hpp>
|
#include <xlnt/worksheet/major_order.hpp>
|
||||||
|
#include <xlnt/worksheet/range_iterator_2d.hpp>
|
||||||
#include <xlnt/worksheet/range_reference.hpp>
|
#include <xlnt/worksheet/range_reference.hpp>
|
||||||
#include <xlnt/worksheet/worksheet.hpp>
|
#include <xlnt/worksheet/worksheet.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A range is a 2D collection of cells with defined extens that can be iterated upon.
|
||||||
|
/// </summary>
|
||||||
class XLNT_CLASS range
|
class XLNT_CLASS range
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
template <bool is_const = true>
|
using iterator = range_iterator_2d;
|
||||||
class XLNT_CLASS common_iterator : public std::iterator<std::bidirectional_iterator_tag, cell>
|
using const_iterator = const_range_iterator_2d;
|
||||||
{
|
|
||||||
public:
|
|
||||||
common_iterator(worksheet ws, const range_reference &start_cell, major_order order = major_order::row)
|
|
||||||
: ws_(ws), current_cell_(start_cell.get_top_left()), range_(start_cell), order_(order)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
common_iterator(const common_iterator<false> &other)
|
range(worksheet ws, const range_reference &reference, major_order order = major_order::row, bool skip_null = false);
|
||||||
{
|
|
||||||
*this = other;
|
|
||||||
}
|
|
||||||
|
|
||||||
cell_vector operator*();
|
|
||||||
|
|
||||||
bool operator==(const common_iterator &other) const
|
|
||||||
{
|
|
||||||
return ws_ == other.ws_ && current_cell_ == other.current_cell_ && order_ == other.order_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=(const common_iterator &other) const
|
|
||||||
{
|
|
||||||
return !(*this == other);
|
|
||||||
}
|
|
||||||
|
|
||||||
common_iterator &operator--()
|
|
||||||
{
|
|
||||||
if (order_ == major_order::row)
|
|
||||||
{
|
|
||||||
current_cell_.set_row(current_cell_.get_row() - 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
current_cell_.set_column_index(current_cell_.get_column_index() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
common_iterator operator--(int)
|
|
||||||
{
|
|
||||||
iterator old = *this;
|
|
||||||
--*this;
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
common_iterator &operator++()
|
|
||||||
{
|
|
||||||
if (order_ == major_order::row)
|
|
||||||
{
|
|
||||||
current_cell_.set_row(current_cell_.get_row() + 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
current_cell_.set_column_index(current_cell_.get_column_index() + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
common_iterator operator++(int)
|
|
||||||
{
|
|
||||||
iterator old = *this;
|
|
||||||
++*this;
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend class common_iterator<true>;
|
|
||||||
|
|
||||||
private:
|
|
||||||
worksheet ws_;
|
|
||||||
cell_reference current_cell_;
|
|
||||||
range_reference range_;
|
|
||||||
major_order order_;
|
|
||||||
};
|
|
||||||
|
|
||||||
using iterator = common_iterator<false>;
|
|
||||||
using const_iterator = common_iterator<true>;
|
|
||||||
|
|
||||||
range(worksheet ws, const range_reference &reference, major_order order = major_order::row);
|
|
||||||
|
|
||||||
~range();
|
~range();
|
||||||
|
|
||||||
|
@ -128,10 +55,7 @@ class XLNT_CLASS range
|
||||||
|
|
||||||
bool operator==(const range &comparand) const;
|
bool operator==(const range &comparand) const;
|
||||||
|
|
||||||
bool operator!=(const range &comparand) const
|
bool operator!=(const range &comparand) const;
|
||||||
{
|
|
||||||
return !(*this == comparand);
|
|
||||||
}
|
|
||||||
|
|
||||||
cell_vector get_vector(std::size_t vector_index);
|
cell_vector get_vector(std::size_t vector_index);
|
||||||
|
|
||||||
|
@ -150,14 +74,8 @@ class XLNT_CLASS range
|
||||||
iterator begin();
|
iterator begin();
|
||||||
iterator end();
|
iterator end();
|
||||||
|
|
||||||
const_iterator begin() const
|
const_iterator begin() const;
|
||||||
{
|
const_iterator end() const;
|
||||||
return cbegin();
|
|
||||||
}
|
|
||||||
const_iterator end() const
|
|
||||||
{
|
|
||||||
return cend();
|
|
||||||
}
|
|
||||||
|
|
||||||
const_iterator cbegin() const;
|
const_iterator cbegin() const;
|
||||||
const_iterator cend() const;
|
const_iterator cend() const;
|
||||||
|
@ -166,6 +84,7 @@ class XLNT_CLASS range
|
||||||
worksheet ws_;
|
worksheet ws_;
|
||||||
range_reference ref_;
|
range_reference ref_;
|
||||||
major_order order_;
|
major_order order_;
|
||||||
|
bool skip_null_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace xlnt
|
} // namespace xlnt
|
||||||
|
|
80
include/xlnt/worksheet/range_iterator_2d.hpp
Normal file
80
include/xlnt/worksheet/range_iterator_2d.hpp
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
#include <xlnt/cell/cell_reference.hpp>
|
||||||
|
#include <xlnt/worksheet/major_order.hpp>
|
||||||
|
#include <xlnt/worksheet/range_reference.hpp>
|
||||||
|
|
||||||
|
namespace xlnt {
|
||||||
|
|
||||||
|
class cell_vector;
|
||||||
|
class worksheet;
|
||||||
|
|
||||||
|
namespace detail { struct worksheet_impl; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An iterator used by worksheet and range for traversing
|
||||||
|
/// a 2D grid of cells by row/column then across that row/column.
|
||||||
|
/// </summary>
|
||||||
|
class XLNT_CLASS range_iterator_2d : public std::iterator<std::bidirectional_iterator_tag, cell_vector>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
range_iterator_2d(worksheet &ws, const range_reference &start_cell, major_order order = major_order::row);
|
||||||
|
|
||||||
|
range_iterator_2d(const range_iterator_2d &other);
|
||||||
|
|
||||||
|
cell_vector operator*();
|
||||||
|
|
||||||
|
bool operator==(const range_iterator_2d &other) const;
|
||||||
|
|
||||||
|
bool operator!=(const range_iterator_2d &other) const;
|
||||||
|
|
||||||
|
range_iterator_2d &operator--();
|
||||||
|
|
||||||
|
range_iterator_2d operator--(int);
|
||||||
|
|
||||||
|
range_iterator_2d &operator++();
|
||||||
|
|
||||||
|
range_iterator_2d operator++(int);
|
||||||
|
|
||||||
|
private:
|
||||||
|
detail::worksheet_impl *ws_;
|
||||||
|
cell_reference current_cell_;
|
||||||
|
range_reference range_;
|
||||||
|
major_order order_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A const version of range_iterator_2d which does not allow modification
|
||||||
|
/// to the dereferenced cell_vector.
|
||||||
|
/// </summary>
|
||||||
|
class XLNT_CLASS const_range_iterator_2d : public std::iterator<std::bidirectional_iterator_tag, const cell_vector>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const_range_iterator_2d(const worksheet &ws, const range_reference &start_cell, major_order order = major_order::row);
|
||||||
|
|
||||||
|
const_range_iterator_2d(const const_range_iterator_2d &other);
|
||||||
|
|
||||||
|
const cell_vector operator*();
|
||||||
|
|
||||||
|
bool operator==(const const_range_iterator_2d &other) const;
|
||||||
|
|
||||||
|
bool operator!=(const const_range_iterator_2d &other) const;
|
||||||
|
|
||||||
|
const_range_iterator_2d &operator--();
|
||||||
|
|
||||||
|
const_range_iterator_2d operator--(int);
|
||||||
|
|
||||||
|
const_range_iterator_2d &operator++();
|
||||||
|
|
||||||
|
const_range_iterator_2d operator++(int);
|
||||||
|
|
||||||
|
private:
|
||||||
|
detail::worksheet_impl *ws_;
|
||||||
|
cell_reference current_cell_;
|
||||||
|
range_reference range_;
|
||||||
|
major_order order_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace xlnt
|
|
@ -27,6 +27,10 @@
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A range_reference describes a rectangular area of a worksheet with positive
|
||||||
|
/// width and height defined by a top-left and bottom-right corner.
|
||||||
|
/// </summary>
|
||||||
class XLNT_CLASS range_reference
|
class XLNT_CLASS range_reference
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -48,69 +52,43 @@ class XLNT_CLASS range_reference
|
||||||
|
|
||||||
std::size_t get_height() const;
|
std::size_t get_height() const;
|
||||||
|
|
||||||
cell_reference get_top_left() const
|
cell_reference get_top_left() const;
|
||||||
{
|
|
||||||
return top_left_;
|
cell_reference get_bottom_right() const;
|
||||||
}
|
|
||||||
cell_reference get_bottom_right() const
|
cell_reference &get_top_left();
|
||||||
{
|
|
||||||
return bottom_right_;
|
cell_reference &get_bottom_right();
|
||||||
}
|
|
||||||
cell_reference &get_top_left()
|
|
||||||
{
|
|
||||||
return top_left_;
|
|
||||||
}
|
|
||||||
cell_reference &get_bottom_right()
|
|
||||||
{
|
|
||||||
return bottom_right_;
|
|
||||||
}
|
|
||||||
|
|
||||||
range_reference make_offset(int column_offset, int row_offset) const;
|
range_reference make_offset(int column_offset, int row_offset) const;
|
||||||
|
|
||||||
std::string to_string() const;
|
std::string to_string() const;
|
||||||
|
|
||||||
bool operator==(const range_reference &comparand) const;
|
bool operator==(const range_reference &comparand) const;
|
||||||
bool operator==(const std::string &reference_string) const
|
|
||||||
{
|
bool operator==(const std::string &reference_string) const;
|
||||||
return *this == range_reference(reference_string);
|
|
||||||
}
|
bool operator==(const char *reference_string) const;
|
||||||
bool operator==(const char *reference_string) const
|
|
||||||
{
|
|
||||||
return *this == std::string(reference_string);
|
|
||||||
}
|
|
||||||
bool operator!=(const range_reference &comparand) const;
|
bool operator!=(const range_reference &comparand) const;
|
||||||
bool operator!=(const std::string &reference_string) const
|
|
||||||
{
|
bool operator!=(const std::string &reference_string) const;
|
||||||
return *this != range_reference(reference_string);
|
|
||||||
}
|
bool operator!=(const char *reference_string) const;
|
||||||
bool operator!=(const char *reference_string) const
|
|
||||||
{
|
XLNT_FUNCTION friend bool operator==(const std::string &reference_string, const range_reference &ref);
|
||||||
return *this != std::string(reference_string);
|
|
||||||
}
|
XLNT_FUNCTION friend bool operator==(const char *reference_string, const range_reference &ref);
|
||||||
|
|
||||||
|
XLNT_FUNCTION friend bool operator!=(const std::string &reference_string, const range_reference &ref);
|
||||||
|
|
||||||
|
XLNT_FUNCTION friend bool operator!=(const char *reference_string, const range_reference &ref);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
cell_reference top_left_;
|
cell_reference top_left_;
|
||||||
cell_reference bottom_right_;
|
cell_reference bottom_right_;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool XLNT_FUNCTION operator==(const std::string &reference_string, const range_reference &ref)
|
|
||||||
{
|
|
||||||
return ref == reference_string;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool XLNT_FUNCTION operator==(const char *reference_string, const range_reference &ref)
|
|
||||||
{
|
|
||||||
return ref == reference_string;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool XLNT_FUNCTION operator!=(const std::string &reference_string, const range_reference &ref)
|
|
||||||
{
|
|
||||||
return ref != reference_string;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool XLNT_FUNCTION operator!=(const char *reference_string, const range_reference &ref)
|
|
||||||
{
|
|
||||||
return ref != reference_string;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace xlnt
|
} // namespace xlnt
|
||||||
|
|
|
@ -27,6 +27,9 @@
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The properties of a row in a worksheet.
|
||||||
|
/// </summary>
|
||||||
class XLNT_CLASS row_properties
|
class XLNT_CLASS row_properties
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -26,6 +26,9 @@
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The selected area of a worksheet.
|
||||||
|
/// </summary>
|
||||||
class XLNT_CLASS selection
|
class XLNT_CLASS selection
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
|
@ -29,16 +29,16 @@
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Protection applied to a particular worksheet to prevent it from being modified.
|
||||||
|
/// </summary>
|
||||||
class XLNT_CLASS sheet_protection
|
class XLNT_CLASS sheet_protection
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static std::string hash_password(const std::string &password);
|
static std::string hash_password(const std::string &password);
|
||||||
|
|
||||||
void set_password(const std::string &password);
|
void set_password(const std::string &password);
|
||||||
std::string get_hashed_password() const
|
std::string get_hashed_password() const;
|
||||||
{
|
|
||||||
return hashed_password_;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string hashed_password_;
|
std::string hashed_password_;
|
||||||
|
|
|
@ -27,6 +27,10 @@
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines how a worksheet appears in the workbook.
|
||||||
|
/// A workbook must have at least one sheet which is visible at all times.
|
||||||
|
/// </summary>
|
||||||
enum class XLNT_CLASS sheet_state
|
enum class XLNT_CLASS sheet_state
|
||||||
{
|
{
|
||||||
visible,
|
visible,
|
||||||
|
|
|
@ -27,6 +27,10 @@
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Describes a view of a worksheet.
|
||||||
|
/// Worksheets can have multiple views which show the data differently.
|
||||||
|
/// </summary>
|
||||||
class XLNT_CLASS sheet_view
|
class XLNT_CLASS sheet_view
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,23 +23,24 @@
|
||||||
// @author: see AUTHORS file
|
// @author: see AUTHORS file
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <list>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <xlnt/xlnt_config.hpp>
|
#include <xlnt/xlnt_config.hpp>
|
||||||
#include <xlnt/cell/types.hpp>
|
#include <xlnt/cell/index_types.hpp>
|
||||||
#include <xlnt/packaging/relationship.hpp>
|
#include <xlnt/packaging/relationship.hpp>
|
||||||
#include <xlnt/worksheet/header_footer.hpp>
|
#include <xlnt/worksheet/header_footer.hpp>
|
||||||
#include <xlnt/worksheet/page_margins.hpp>
|
#include <xlnt/worksheet/page_margins.hpp>
|
||||||
#include <xlnt/worksheet/page_setup.hpp>
|
#include <xlnt/worksheet/page_setup.hpp>
|
||||||
|
#include <xlnt/worksheet/range_iterator_2d.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
class cell;
|
class cell;
|
||||||
class cell_reference;
|
class cell_reference;
|
||||||
|
class cell_vector;
|
||||||
class column_properties;
|
class column_properties;
|
||||||
class comment;
|
class comment;
|
||||||
class range;
|
class range;
|
||||||
|
@ -53,11 +54,15 @@ struct date;
|
||||||
namespace detail { struct worksheet_impl; }
|
namespace detail { struct worksheet_impl; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A worksheet is a 2D array of cells.
|
/// A worksheet is a 2D array of cells starting with cell A1 in the top-left corner
|
||||||
|
/// and extending indefinitely down and right as needed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
class XLNT_CLASS worksheet
|
class XLNT_CLASS worksheet
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using iterator = range_iterator_2d;
|
||||||
|
using const_iterator = const_range_iterator_2d;
|
||||||
|
|
||||||
worksheet();
|
worksheet();
|
||||||
worksheet(const worksheet &rhs);
|
worksheet(const worksheet &rhs);
|
||||||
worksheet(workbook &parent_workbook, const std::string &title = std::string());
|
worksheet(workbook &parent_workbook, const std::string &title = std::string());
|
||||||
|
@ -92,7 +97,6 @@ class XLNT_CLASS worksheet
|
||||||
range rows(int row_offset, int column_offset) const;
|
range rows(int row_offset, int column_offset) const;
|
||||||
range rows(const std::string &range_string, int row_offset, int column_offset) const;
|
range rows(const std::string &range_string, int row_offset, int column_offset) const;
|
||||||
range columns() const;
|
range columns() const;
|
||||||
std::list<cell> get_cell_collection();
|
|
||||||
|
|
||||||
// properties
|
// properties
|
||||||
column_properties &get_column_properties(column_t column);
|
column_properties &get_column_properties(column_t column);
|
||||||
|
@ -198,9 +202,23 @@ class XLNT_CLASS worksheet
|
||||||
|
|
||||||
void set_sheet_state(sheet_state state);
|
void set_sheet_state(sheet_state state);
|
||||||
|
|
||||||
|
iterator begin();
|
||||||
|
iterator end();
|
||||||
|
|
||||||
|
const_iterator begin() const;
|
||||||
|
const_iterator end() const;
|
||||||
|
|
||||||
|
const_iterator cbegin() const;
|
||||||
|
const_iterator cend() const;
|
||||||
|
|
||||||
|
range iter_cells(bool skip_null);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class workbook;
|
friend class workbook;
|
||||||
friend class cell;
|
friend class cell;
|
||||||
|
friend class range_iterator_2d;
|
||||||
|
friend class const_range_iterator_2d;
|
||||||
|
|
||||||
worksheet(detail::worksheet_impl *d);
|
worksheet(detail::worksheet_impl *d);
|
||||||
detail::worksheet_impl *d_;
|
detail::worksheet_impl *d_;
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,6 +27,9 @@
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ?
|
||||||
|
/// </summary>
|
||||||
class XLNT_CLASS worksheet_properties
|
class XLNT_CLASS worksheet_properties
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#include <xlnt/cell/cell.hpp>
|
#include <xlnt/cell/cell.hpp>
|
||||||
#include <xlnt/cell/cell_reference.hpp>
|
#include <xlnt/cell/cell_reference.hpp>
|
||||||
#include <xlnt/cell/comment.hpp>
|
#include <xlnt/cell/comment.hpp>
|
||||||
#include <xlnt/cell/types.hpp>
|
#include <xlnt/cell/index_types.hpp>
|
||||||
#include <xlnt/packaging/document_properties.hpp>
|
#include <xlnt/packaging/document_properties.hpp>
|
||||||
#include <xlnt/packaging/manifest.hpp>
|
#include <xlnt/packaging/manifest.hpp>
|
||||||
#include <xlnt/packaging/relationship.hpp>
|
#include <xlnt/packaging/relationship.hpp>
|
||||||
|
|
|
@ -21,767 +21,6 @@
|
||||||
#include <detail/cell_impl.hpp>
|
#include <detail/cell_impl.hpp>
|
||||||
#include <detail/comment_impl.hpp>
|
#include <detail/comment_impl.hpp>
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
enum class condition_type
|
|
||||||
{
|
|
||||||
less_than,
|
|
||||||
less_or_equal,
|
|
||||||
equal,
|
|
||||||
greater_than,
|
|
||||||
greater_or_equal,
|
|
||||||
invalid
|
|
||||||
};
|
|
||||||
|
|
||||||
struct section
|
|
||||||
{
|
|
||||||
bool has_value = false;
|
|
||||||
std::string value;
|
|
||||||
bool has_color = false;
|
|
||||||
std::string color;
|
|
||||||
bool has_condition = false;
|
|
||||||
condition_type condition = condition_type::invalid;
|
|
||||||
std::string condition_value;
|
|
||||||
bool has_locale = false;
|
|
||||||
std::string locale;
|
|
||||||
|
|
||||||
section &operator=(const section &other)
|
|
||||||
{
|
|
||||||
has_value = other.has_value;
|
|
||||||
value = other.value;
|
|
||||||
has_color = other.has_color;
|
|
||||||
color = other.color;
|
|
||||||
has_condition = other.has_condition;
|
|
||||||
condition = other.condition;
|
|
||||||
condition_value = other.condition_value;
|
|
||||||
has_locale = other.has_locale;
|
|
||||||
locale = other.locale;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct format_sections
|
|
||||||
{
|
|
||||||
section first;
|
|
||||||
section second;
|
|
||||||
section third;
|
|
||||||
section fourth;
|
|
||||||
};
|
|
||||||
|
|
||||||
// copied from named_range.cpp, keep in sync
|
|
||||||
/// <summary>
|
|
||||||
/// Return a vector containing string split at each delim.
|
|
||||||
/// </summary>
|
|
||||||
/// <remark>
|
|
||||||
/// This should maybe be in a utility header so it can be used elsewhere.
|
|
||||||
/// </remarks>
|
|
||||||
std::vector<std::string> split_string(const std::string &string, char delim)
|
|
||||||
{
|
|
||||||
std::vector<std::string> split;
|
|
||||||
std::string::size_type previous_index = 0;
|
|
||||||
auto separator_index = string.find(delim);
|
|
||||||
|
|
||||||
while (separator_index != std::string::npos)
|
|
||||||
{
|
|
||||||
auto part = string.substr(previous_index, separator_index - previous_index);
|
|
||||||
split.push_back(part);
|
|
||||||
|
|
||||||
previous_index = separator_index + 1;
|
|
||||||
separator_index = string.find(delim, previous_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
split.push_back(string.substr(previous_index));
|
|
||||||
|
|
||||||
return split;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> split_string_any(const std::string &string, const std::string &delims)
|
|
||||||
{
|
|
||||||
std::vector<std::string> split;
|
|
||||||
std::string::size_type previous_index = 0;
|
|
||||||
auto separator_index = string.find_first_of(delims);
|
|
||||||
|
|
||||||
while (separator_index != std::string::npos)
|
|
||||||
{
|
|
||||||
auto part = string.substr(previous_index, separator_index - previous_index);
|
|
||||||
|
|
||||||
if (!part.empty())
|
|
||||||
{
|
|
||||||
split.push_back(part);
|
|
||||||
}
|
|
||||||
|
|
||||||
previous_index = separator_index + 1;
|
|
||||||
separator_index = string.find_first_of(delims, previous_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
split.push_back(string.substr(previous_index));
|
|
||||||
|
|
||||||
return split;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_date_format(const std::string &format_string)
|
|
||||||
{
|
|
||||||
auto not_in = format_string.find_first_not_of("/-:, mMyYdDhHsS");
|
|
||||||
return not_in == std::string::npos;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_valid_color(const std::string &color)
|
|
||||||
{
|
|
||||||
static const std::vector<std::string> *colors =
|
|
||||||
new std::vector<std::string>(
|
|
||||||
{
|
|
||||||
"Black",
|
|
||||||
"Green"
|
|
||||||
"White",
|
|
||||||
"Blue",
|
|
||||||
"Magenta",
|
|
||||||
"Yellow",
|
|
||||||
"Cyan",
|
|
||||||
"Red"
|
|
||||||
});
|
|
||||||
|
|
||||||
auto compare_color = [&](const std::string &other) {
|
|
||||||
if (color.size() != other.size()) return false;
|
|
||||||
|
|
||||||
for (std::size_t i = 0; i < color.size(); i++)
|
|
||||||
{
|
|
||||||
if (std::toupper(color[i]) != std::toupper(other[i]))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
return std::find_if(colors->begin(), colors->end(), compare_color) != colors->end();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool parse_condition(const std::string &string, section &s)
|
|
||||||
{
|
|
||||||
s.has_condition = false;
|
|
||||||
s.condition = condition_type::invalid;
|
|
||||||
s.condition_value.clear();
|
|
||||||
|
|
||||||
if (string[0] == '<')
|
|
||||||
{
|
|
||||||
s.has_condition = true;
|
|
||||||
|
|
||||||
if (string[1] == '=')
|
|
||||||
{
|
|
||||||
s.condition = condition_type::less_or_equal;
|
|
||||||
s.condition_value = string.substr(2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
s.condition = condition_type::less_than;
|
|
||||||
s.condition_value = string.substr(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (string[0] == '>')
|
|
||||||
{
|
|
||||||
s.has_condition = true;
|
|
||||||
|
|
||||||
if (string[1] == '=')
|
|
||||||
{
|
|
||||||
s.condition = condition_type::greater_or_equal;
|
|
||||||
s.condition_value = string.substr(2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
s.condition = condition_type::greater_than;
|
|
||||||
s.condition_value = string.substr(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (string[0] == '=')
|
|
||||||
{
|
|
||||||
s.has_condition = true;
|
|
||||||
s.condition = condition_type::equal;
|
|
||||||
s.condition_value = string.substr(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return s.has_condition;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_hex(char c)
|
|
||||||
{
|
|
||||||
if (c >= 'A' || c <= 'F') return true;
|
|
||||||
if (c >= '0' || c <= '9') return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::unordered_map<int, std::string> known_locales()
|
|
||||||
{
|
|
||||||
const std::unordered_map<int, std::string> *all =
|
|
||||||
new std::unordered_map<int, std::string>(
|
|
||||||
{
|
|
||||||
{ 0x401, "Arabic - Saudi Arabia" },
|
|
||||||
{ 0x402, "Bulgarian" },
|
|
||||||
{ 0x403, "Catalan" },
|
|
||||||
{ 0x404, "Chinese - Taiwan" },
|
|
||||||
{ 0x405, "Czech" },
|
|
||||||
{ 0x406, "Danish" },
|
|
||||||
{ 0x407, "German - Germany" },
|
|
||||||
{ 0x408, "Greek" },
|
|
||||||
{ 0x409, "English - United States" },
|
|
||||||
{ 0x410, "Italian - Italy" },
|
|
||||||
{ 0x411, "Japanese" },
|
|
||||||
{ 0x412, "Korean" },
|
|
||||||
{ 0x413, "Dutch - Netherlands" },
|
|
||||||
{ 0x414, "Norwegian - Bokml" },
|
|
||||||
{ 0x415, "Polish" },
|
|
||||||
{ 0x416, "Portuguese - Brazil" },
|
|
||||||
{ 0x417, "Raeto-Romance" },
|
|
||||||
{ 0x418, "Romanian - Romania" },
|
|
||||||
{ 0x419, "Russian" },
|
|
||||||
{ 0x420, "Urdu" },
|
|
||||||
{ 0x421, "Indonesian" },
|
|
||||||
{ 0x422, "Ukrainian" },
|
|
||||||
{ 0x423, "Belarusian" },
|
|
||||||
{ 0x424, "Slovenian" },
|
|
||||||
{ 0x425, "Estonian" },
|
|
||||||
{ 0x426, "Latvian" },
|
|
||||||
{ 0x427, "Lithuanian" },
|
|
||||||
{ 0x428, "Tajik" },
|
|
||||||
{ 0x429, "Farsi - Persian" },
|
|
||||||
{ 0x430, "Sesotho (Sutu)" },
|
|
||||||
{ 0x431, "Tsonga" },
|
|
||||||
{ 0x432, "Setsuana" },
|
|
||||||
{ 0x433, "Venda" },
|
|
||||||
{ 0x434, "Xhosa" },
|
|
||||||
{ 0x435, "Zulu" },
|
|
||||||
{ 0x436, "Afrikaans" },
|
|
||||||
{ 0x437, "Georgian" },
|
|
||||||
{ 0x438, "Faroese" },
|
|
||||||
{ 0x439, "Hindi" },
|
|
||||||
{ 0x440, "Kyrgyz - Cyrillic" },
|
|
||||||
{ 0x441, "Swahili" },
|
|
||||||
{ 0x442, "Turkmen" },
|
|
||||||
{ 0x443, "Uzbek - Latin" },
|
|
||||||
{ 0x444, "Tatar" },
|
|
||||||
{ 0x445, "Bengali - India" },
|
|
||||||
{ 0x446, "Punjabi" },
|
|
||||||
{ 0x447, "Gujarati" },
|
|
||||||
{ 0x448, "Oriya" },
|
|
||||||
{ 0x449, "Tamil" },
|
|
||||||
{ 0x450, "Mongolian" },
|
|
||||||
{ 0x451, "Tibetan" },
|
|
||||||
{ 0x452, "Welsh" },
|
|
||||||
{ 0x453, "Khmer" },
|
|
||||||
{ 0x454, "Lao" },
|
|
||||||
{ 0x455, "Burmese" },
|
|
||||||
{ 0x456, "Galician" },
|
|
||||||
{ 0x457, "Konkani" },
|
|
||||||
{ 0x458, "Manipuri" },
|
|
||||||
{ 0x459, "Sindhi" },
|
|
||||||
{ 0x460, "Kashmiri" },
|
|
||||||
{ 0x461, "Nepali" },
|
|
||||||
{ 0x462, "Frisian - Netherlands" },
|
|
||||||
{ 0x464, "Filipino" },
|
|
||||||
{ 0x465, "Divehi; Dhivehi; Maldivian" },
|
|
||||||
{ 0x466, "Edo" },
|
|
||||||
{ 0x470, "Igbo - Nigeria" },
|
|
||||||
{ 0x474, "Guarani - Paraguay" },
|
|
||||||
{ 0x476, "Latin" },
|
|
||||||
{ 0x477, "Somali" },
|
|
||||||
{ 0x481, "Maori" },
|
|
||||||
{ 0x801, "Arabic - Iraq" },
|
|
||||||
{ 0x804, "Chinese - China" },
|
|
||||||
{ 0x807, "German - Switzerland" },
|
|
||||||
{ 0x809, "English - Great Britain" },
|
|
||||||
{ 0x810, "Italian - Switzerland" },
|
|
||||||
{ 0x813, "Dutch - Belgium" },
|
|
||||||
{ 0x814, "Norwegian - Nynorsk" },
|
|
||||||
{ 0x816, "Portuguese - Portugal" },
|
|
||||||
{ 0x818, "Romanian - Moldova" },
|
|
||||||
{ 0x819, "Russian - Moldova" },
|
|
||||||
{ 0x843, "Uzbek - Cyrillic" },
|
|
||||||
{ 0x845, "Bengali - Bangladesh" },
|
|
||||||
{ 0x850, "Mongolian" },
|
|
||||||
{ 0x1001, "Arabic - Libya" },
|
|
||||||
{ 0x1004, "Chinese - Singapore" },
|
|
||||||
{ 0x1007, "German - Luxembourg" },
|
|
||||||
{ 0x1009, "English - Canada" },
|
|
||||||
{ 0x1401, "Arabic - Algeria" },
|
|
||||||
{ 0x1404, "Chinese - Macau SAR" },
|
|
||||||
{ 0x1407, "German - Liechtenstein" },
|
|
||||||
{ 0x1409, "English - New Zealand" },
|
|
||||||
{ 0x1801, "Arabic - Morocco" },
|
|
||||||
{ 0x1809, "English - Ireland" },
|
|
||||||
{ 0x2001, "Arabic - Oman" },
|
|
||||||
{ 0x2009, "English - Jamaica" },
|
|
||||||
{ 0x2401, "Arabic - Yemen" },
|
|
||||||
{ 0x2409, "English - Caribbean" },
|
|
||||||
{ 0x2801, "Arabic - Syria" },
|
|
||||||
{ 0x2809, "English - Belize" },
|
|
||||||
{ 0x3001, "Arabic - Lebanon" },
|
|
||||||
{ 0x3009, "English - Zimbabwe" },
|
|
||||||
{ 0x3401, "Arabic - Kuwait" },
|
|
||||||
{ 0x3409, "English - Phillippines" },
|
|
||||||
{ 0x3801, "Arabic - United Arab Emirates" },
|
|
||||||
{ 0x4001, "Arabic - Qatar" }
|
|
||||||
});
|
|
||||||
|
|
||||||
return *all;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_valid_locale(const std::string &locale_string)
|
|
||||||
{
|
|
||||||
std::string country = locale_string.substr(locale_string.find('-') + 1);
|
|
||||||
|
|
||||||
if (country.empty())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto c : country)
|
|
||||||
{
|
|
||||||
if (!is_hex(static_cast<char>(std::toupper(c))))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto index = std::stoi(country, 0, 16);
|
|
||||||
|
|
||||||
auto known_locales_ = known_locales();
|
|
||||||
|
|
||||||
if (known_locales_.find(index) == known_locales_.end())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string beginning = locale_string.substr(0, locale_string.find('-'));
|
|
||||||
|
|
||||||
if (beginning.empty() || beginning[0] != '$')
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (beginning.size() == 1)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
beginning = beginning.substr(1);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
section parse_section(const std::string §ion_string)
|
|
||||||
{
|
|
||||||
section s;
|
|
||||||
|
|
||||||
std::string format_part;
|
|
||||||
std::string bracket_part;
|
|
||||||
|
|
||||||
std::vector<std::string> bracket_parts;
|
|
||||||
|
|
||||||
bool in_quotes = false;
|
|
||||||
bool in_brackets = false;
|
|
||||||
|
|
||||||
const std::vector<std::string> bracket_times = { "h", "hh", "m", "mm", "s", "ss" };
|
|
||||||
|
|
||||||
for (std::size_t i = 0; i < section_string.size(); i++)
|
|
||||||
{
|
|
||||||
if (!in_quotes && section_string[i] == '"')
|
|
||||||
{
|
|
||||||
format_part.push_back(section_string[i]);
|
|
||||||
in_quotes = true;
|
|
||||||
}
|
|
||||||
else if (in_quotes && section_string[i] == '"')
|
|
||||||
{
|
|
||||||
format_part.push_back(section_string[i]);
|
|
||||||
|
|
||||||
if (i < section_string.size() - 1 && section_string[i + 1] != '"')
|
|
||||||
{
|
|
||||||
in_quotes = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!in_brackets && section_string[i] == '[')
|
|
||||||
{
|
|
||||||
in_brackets = true;
|
|
||||||
|
|
||||||
for (auto bracket_time : bracket_times)
|
|
||||||
{
|
|
||||||
if (i < section_string.size() - bracket_time.size() &&
|
|
||||||
section_string.substr(i + 1, bracket_time.size()) == bracket_time)
|
|
||||||
{
|
|
||||||
in_brackets = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (in_brackets)
|
|
||||||
{
|
|
||||||
if (section_string[i] == ']')
|
|
||||||
{
|
|
||||||
in_brackets = false;
|
|
||||||
|
|
||||||
if (is_valid_color(bracket_part))
|
|
||||||
{
|
|
||||||
if (s.color.empty())
|
|
||||||
{
|
|
||||||
s.color = bracket_part;
|
|
||||||
s.has_color = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw std::runtime_error("two colors");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (is_valid_locale(bracket_part))
|
|
||||||
{
|
|
||||||
if (s.locale.empty())
|
|
||||||
{
|
|
||||||
s.locale = bracket_part;
|
|
||||||
s.has_locale = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw std::runtime_error("two locales");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (s.has_condition || !parse_condition(bracket_part, s))
|
|
||||||
{
|
|
||||||
throw std::runtime_error("invalid bracket format");
|
|
||||||
}
|
|
||||||
|
|
||||||
bracket_part.clear();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bracket_part.push_back(section_string[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
format_part.push_back(section_string[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
s.value = format_part;
|
|
||||||
s.has_value = true;
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
format_sections parse_format_sections(const std::string &combined)
|
|
||||||
{
|
|
||||||
format_sections result = {};
|
|
||||||
|
|
||||||
auto split = split_string(combined, ';');
|
|
||||||
|
|
||||||
if (split.empty())
|
|
||||||
{
|
|
||||||
throw std::runtime_error("empty string");
|
|
||||||
}
|
|
||||||
|
|
||||||
result.first = parse_section(split[0]);
|
|
||||||
|
|
||||||
if (!result.first.has_condition)
|
|
||||||
{
|
|
||||||
result.second = result.first;
|
|
||||||
result.third = result.first;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (split.size() > 1)
|
|
||||||
{
|
|
||||||
result.second = parse_section(split[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (split.size() > 2)
|
|
||||||
{
|
|
||||||
if (result.first.has_condition && !result.second.has_condition)
|
|
||||||
{
|
|
||||||
throw std::runtime_error("first two sections should have conditions");
|
|
||||||
}
|
|
||||||
|
|
||||||
result.third = parse_section(split[2]);
|
|
||||||
|
|
||||||
if (result.third.has_condition)
|
|
||||||
{
|
|
||||||
throw std::runtime_error("third section shouldn't have a condition");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (split.size() > 3)
|
|
||||||
{
|
|
||||||
if (result.first.has_condition)
|
|
||||||
{
|
|
||||||
throw std::runtime_error("too many parts");
|
|
||||||
}
|
|
||||||
|
|
||||||
result.fourth = parse_section(split[3]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (split.size() > 4)
|
|
||||||
{
|
|
||||||
throw std::runtime_error("too many parts");
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string format_section(long double number, const section &format, xlnt::calendar base_date)
|
|
||||||
{
|
|
||||||
const std::string unquoted = "$+(:^'{<=-/)!&~}> ";
|
|
||||||
std::string format_temp = format.value;
|
|
||||||
std::string result;
|
|
||||||
|
|
||||||
if (is_date_format(format.value))
|
|
||||||
{
|
|
||||||
const std::string date_unquoted = ",-/: ";
|
|
||||||
|
|
||||||
const std::vector<std::string> dates = { "m", "mm", "mmm", "mmmmm", "mmmmmm", "d", "dd", "ddd", "dddd", "yy",
|
|
||||||
"yyyy", "h", "[h]", "hh", "m", "[m]", "mm", "s", "[s]", "ss", "AM/PM",
|
|
||||||
"am/pm", "A/P", "a/p" };
|
|
||||||
|
|
||||||
const std::vector<std::string> MonthNames = { "January", "February", "March",
|
|
||||||
"April", "May", "June", "July", "August", "September", "October", "November", "December" };
|
|
||||||
|
|
||||||
|
|
||||||
auto split = split_string_any(format.value, date_unquoted);
|
|
||||||
std::string::size_type index = 0, prev = 0;
|
|
||||||
auto d = xlnt::datetime::from_number(number, base_date);
|
|
||||||
bool processed_month = false;
|
|
||||||
|
|
||||||
auto lower_string = [](const std::string &s) {
|
|
||||||
std::string lower;
|
|
||||||
lower.resize(s.size());
|
|
||||||
for (std::size_t i = 0; i < s.size(); i++)
|
|
||||||
lower[i] = static_cast<char>(std::tolower(s[i]));
|
|
||||||
return lower;
|
|
||||||
};
|
|
||||||
|
|
||||||
for (auto part : split)
|
|
||||||
{
|
|
||||||
while (format.value.substr(index, part.size()) != part)
|
|
||||||
{
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto between = format.value.substr(prev, index - prev);
|
|
||||||
result.append(between);
|
|
||||||
|
|
||||||
part = lower_string(part);
|
|
||||||
|
|
||||||
if (part == "m" && !processed_month)
|
|
||||||
{
|
|
||||||
result.append(std::to_string(d.month));
|
|
||||||
processed_month = true;
|
|
||||||
}
|
|
||||||
else if (part == "mm" && !processed_month)
|
|
||||||
{
|
|
||||||
if (d.month < 10)
|
|
||||||
{
|
|
||||||
result.append("0");
|
|
||||||
}
|
|
||||||
|
|
||||||
result.append(std::to_string(d.month));
|
|
||||||
processed_month = true;
|
|
||||||
}
|
|
||||||
else if (part == "mmm" && !processed_month)
|
|
||||||
{
|
|
||||||
result.append(MonthNames.at(static_cast<std::size_t>(d.month - 1)).substr(0, 3));
|
|
||||||
processed_month = true;
|
|
||||||
}
|
|
||||||
else if (part == "mmmm" && !processed_month)
|
|
||||||
{
|
|
||||||
result.append(MonthNames.at(static_cast<std::size_t>(d.month - 1)));
|
|
||||||
processed_month = true;
|
|
||||||
}
|
|
||||||
else if (part == "d")
|
|
||||||
{
|
|
||||||
result.append(std::to_string(d.day));
|
|
||||||
}
|
|
||||||
else if (part == "dd")
|
|
||||||
{
|
|
||||||
if (d.day < 10)
|
|
||||||
{
|
|
||||||
result.append("0");
|
|
||||||
}
|
|
||||||
|
|
||||||
result.append(std::to_string(d.day));
|
|
||||||
}
|
|
||||||
else if (part == "yyyy")
|
|
||||||
{
|
|
||||||
result.append(std::to_string(d.year));
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (part == "h")
|
|
||||||
{
|
|
||||||
result.append(std::to_string(d.hour));
|
|
||||||
processed_month = true;
|
|
||||||
}
|
|
||||||
else if (part == "hh")
|
|
||||||
{
|
|
||||||
if (d.hour < 10)
|
|
||||||
{
|
|
||||||
result.append("0");
|
|
||||||
}
|
|
||||||
|
|
||||||
result.append(std::to_string(d.hour));
|
|
||||||
processed_month = true;
|
|
||||||
}
|
|
||||||
else if (part == "m")
|
|
||||||
{
|
|
||||||
result.append(std::to_string(d.minute));
|
|
||||||
}
|
|
||||||
else if (part == "mm")
|
|
||||||
{
|
|
||||||
if (d.minute < 10)
|
|
||||||
{
|
|
||||||
result.append("0");
|
|
||||||
}
|
|
||||||
|
|
||||||
result.append(std::to_string(d.minute));
|
|
||||||
}
|
|
||||||
else if (part == "s")
|
|
||||||
{
|
|
||||||
result.append(std::to_string(d.second));
|
|
||||||
}
|
|
||||||
else if (part == "ss")
|
|
||||||
{
|
|
||||||
if (d.second < 10)
|
|
||||||
{
|
|
||||||
result.append("0");
|
|
||||||
}
|
|
||||||
|
|
||||||
result.append(std::to_string(d.second));
|
|
||||||
}
|
|
||||||
else if (part == "am/pm" || part == "a/p")
|
|
||||||
{
|
|
||||||
if (d.hour < 12)
|
|
||||||
{
|
|
||||||
result.append("AM");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result.append("PM");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
index += part.size();
|
|
||||||
prev = index;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index < format.value.size())
|
|
||||||
{
|
|
||||||
result.append(format.value.substr(index));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (format.value == "General" || format.value == "0")
|
|
||||||
{
|
|
||||||
if (number == static_cast<long long int>(number))
|
|
||||||
{
|
|
||||||
result = std::to_string(static_cast<long long int>(number));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = std::to_string(number);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (format.value.substr(0, 8) == "#,##0.00" || format.value.substr(0, 9) == "-#,##0.00")
|
|
||||||
{
|
|
||||||
if (format.value[0] == '-')
|
|
||||||
{
|
|
||||||
result = "-";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (format.has_locale && format.locale == "$$-1009")
|
|
||||||
{
|
|
||||||
result += "CA$";
|
|
||||||
}
|
|
||||||
else if (format.has_locale && format.locale == "$€-407")
|
|
||||||
{
|
|
||||||
result += "€";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result += "$";
|
|
||||||
}
|
|
||||||
|
|
||||||
result += std::to_string(number < 0 ? -number : number);
|
|
||||||
|
|
||||||
auto decimal_pos = result.find('.');
|
|
||||||
|
|
||||||
if (decimal_pos != std::string::npos)
|
|
||||||
{
|
|
||||||
result[decimal_pos] = ',';
|
|
||||||
decimal_pos += 3;
|
|
||||||
|
|
||||||
while (decimal_pos < result.size())
|
|
||||||
{
|
|
||||||
result.pop_back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string format_section(const std::string &text, const section &format)
|
|
||||||
{
|
|
||||||
auto arobase_index = format.value.find('@');
|
|
||||||
|
|
||||||
std::string first_part, middle_part, last_part;
|
|
||||||
|
|
||||||
if (arobase_index != std::string::npos)
|
|
||||||
{
|
|
||||||
first_part = format.value.substr(0, arobase_index);
|
|
||||||
middle_part = text;
|
|
||||||
last_part = format.value.substr(arobase_index + 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
first_part = format.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto unquote = [](std::string &s) {
|
|
||||||
if (!s.empty())
|
|
||||||
{
|
|
||||||
if (s.front() != '"' || s.back() != '"') return false;
|
|
||||||
s = s.substr(0, s.size() - 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!unquote(first_part) || !unquote(last_part))
|
|
||||||
{
|
|
||||||
throw std::runtime_error(std::string("additional text must be enclosed in quotes: ") + format.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return first_part + middle_part + last_part;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string format_number(long double number, const std::string &format, xlnt::calendar base_date)
|
|
||||||
{
|
|
||||||
auto sections = parse_format_sections(format);
|
|
||||||
|
|
||||||
if (number > 0)
|
|
||||||
{
|
|
||||||
return format_section(number, sections.first, base_date);
|
|
||||||
}
|
|
||||||
else if (number < 0)
|
|
||||||
{
|
|
||||||
return format_section(number, sections.second, base_date);
|
|
||||||
}
|
|
||||||
|
|
||||||
// number == 0
|
|
||||||
return format_section(number, sections.third, base_date);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string format_text(const std::string &text, const std::string &format)
|
|
||||||
{
|
|
||||||
if (format == "General") return text;
|
|
||||||
auto sections = parse_format_sections(format);
|
|
||||||
return format_section(text, sections.fourth);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
const std::unordered_map<std::string, int> &cell::error_codes()
|
const std::unordered_map<std::string, int> &cell::error_codes()
|
||||||
|
@ -1012,25 +251,7 @@ bool cell::is_merged() const
|
||||||
|
|
||||||
bool cell::is_date() const
|
bool cell::is_date() const
|
||||||
{
|
{
|
||||||
if (get_data_type() == type::numeric)
|
return get_data_type() == type::numeric && get_number_format().is_date_format();
|
||||||
{
|
|
||||||
auto number_format = get_number_format().get_format_string();
|
|
||||||
|
|
||||||
if (number_format != "General")
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
auto sections = parse_format_sections(number_format);
|
|
||||||
return is_date_format(sections.first.value);
|
|
||||||
}
|
|
||||||
catch (std::exception)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cell_reference cell::get_reference() const
|
cell_reference cell::get_reference() const
|
||||||
|
@ -1448,11 +669,11 @@ std::string cell::to_string() const
|
||||||
case cell::type::null:
|
case cell::type::null:
|
||||||
return "";
|
return "";
|
||||||
case cell::type::numeric:
|
case cell::type::numeric:
|
||||||
return format_number(get_value<long double>(), nf.get_format_string(), get_base_date());
|
return get_number_format().format(get_value<long double>(), get_base_date());
|
||||||
case cell::type::string:
|
case cell::type::string:
|
||||||
case cell::type::formula:
|
case cell::type::formula:
|
||||||
case cell::type::error:
|
case cell::type::error:
|
||||||
return format_text(get_value<std::string>(), nf.get_format_string());
|
return get_number_format().format(get_value<std::string>());
|
||||||
case cell::type::boolean:
|
case cell::type::boolean:
|
||||||
return get_value<long double>() == 0 ? "FALSE" : "TRUE";
|
return get_value<long double>() == 0 ? "FALSE" : "TRUE";
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include <locale>
|
#include <locale>
|
||||||
|
|
||||||
#include <xlnt/cell/types.hpp>
|
#include <xlnt/cell/index_types.hpp>
|
||||||
#include <xlnt/utils/exceptions.hpp>
|
#include <xlnt/utils/exceptions.hpp>
|
||||||
|
|
||||||
#include <detail/constants.hpp>
|
#include <detail/constants.hpp>
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
#include <xlnt/cell/cell.hpp>
|
#include <xlnt/cell/cell.hpp>
|
||||||
#include <xlnt/cell/comment.hpp>
|
#include <xlnt/cell/comment.hpp>
|
||||||
#include <xlnt/cell/types.hpp>
|
#include <xlnt/cell/index_types.hpp>
|
||||||
#include <xlnt/utils/exceptions.hpp>
|
#include <xlnt/utils/exceptions.hpp>
|
||||||
#include <xlnt/utils/time.hpp>
|
#include <xlnt/utils/time.hpp>
|
||||||
#include <xlnt/packaging/relationship.hpp>
|
#include <xlnt/packaging/relationship.hpp>
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include <xlnt/cell/types.hpp>
|
#include <xlnt/cell/index_types.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -16,4 +16,119 @@ relationship::relationship()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
relationship::type relationship::type_from_string(const std::string &type_string)
|
||||||
|
{
|
||||||
|
if (type_string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties")
|
||||||
|
{
|
||||||
|
return type::extended_properties;
|
||||||
|
}
|
||||||
|
else if (type_string == "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties")
|
||||||
|
{
|
||||||
|
return type::core_properties;
|
||||||
|
}
|
||||||
|
else if (type_string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument")
|
||||||
|
{
|
||||||
|
return type::office_document;
|
||||||
|
}
|
||||||
|
else if (type_string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet")
|
||||||
|
{
|
||||||
|
return type::worksheet;
|
||||||
|
}
|
||||||
|
else if (type_string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings")
|
||||||
|
{
|
||||||
|
return type::shared_strings;
|
||||||
|
}
|
||||||
|
else if (type_string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles")
|
||||||
|
{
|
||||||
|
return type::styles;
|
||||||
|
}
|
||||||
|
else if (type_string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme")
|
||||||
|
{
|
||||||
|
return type::theme;
|
||||||
|
}
|
||||||
|
else if (type_string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink")
|
||||||
|
{
|
||||||
|
return type::hyperlink;
|
||||||
|
}
|
||||||
|
else if (type_string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chartsheet")
|
||||||
|
{
|
||||||
|
return type::chartsheet;
|
||||||
|
}
|
||||||
|
else if (type_string == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml")
|
||||||
|
{
|
||||||
|
return type::custom_xml;
|
||||||
|
}
|
||||||
|
|
||||||
|
return type::invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string relationship::type_to_string(type t)
|
||||||
|
{
|
||||||
|
switch (t)
|
||||||
|
{
|
||||||
|
case type::extended_properties:
|
||||||
|
return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties";
|
||||||
|
case type::core_properties:
|
||||||
|
return "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties";
|
||||||
|
case type::office_document:
|
||||||
|
return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument";
|
||||||
|
case type::worksheet:
|
||||||
|
return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet";
|
||||||
|
case type::shared_strings:
|
||||||
|
return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings";
|
||||||
|
case type::styles:
|
||||||
|
return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles";
|
||||||
|
case type::theme:
|
||||||
|
return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme";
|
||||||
|
case type::hyperlink:
|
||||||
|
return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink";
|
||||||
|
case type::chartsheet:
|
||||||
|
return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chartsheet";
|
||||||
|
case type::custom_xml:
|
||||||
|
return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml";
|
||||||
|
default:
|
||||||
|
return "??";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
relationship::relationship(const std::string &t, const std::string &r_id, const std::string &target_uri)
|
||||||
|
: relationship(type_from_string(t), r_id, target_uri)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string relationship::get_id() const
|
||||||
|
{
|
||||||
|
return id_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string relationship::get_source_uri() const
|
||||||
|
{
|
||||||
|
return source_uri_;
|
||||||
|
}
|
||||||
|
|
||||||
|
target_mode relationship::get_target_mode() const
|
||||||
|
{
|
||||||
|
return target_mode_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string relationship::get_target_uri() const
|
||||||
|
{
|
||||||
|
return target_uri_;
|
||||||
|
}
|
||||||
|
|
||||||
|
relationship::type relationship::get_type() const
|
||||||
|
{
|
||||||
|
return type_;
|
||||||
|
}
|
||||||
|
std::string relationship::get_type_string() const
|
||||||
|
{
|
||||||
|
return type_to_string(type_);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool relationship::operator==(const relationship &rhs) const
|
||||||
|
{
|
||||||
|
return type_ == rhs.type_ && id_ == rhs.id_ && source_uri_ == rhs.source_uri_ &&
|
||||||
|
target_uri_ == rhs.target_uri_ && target_mode_ == rhs.target_mode_;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace xlnt
|
} // namespace xlnt
|
||||||
|
|
|
@ -160,19 +160,19 @@ alignment style_serializer::read_alignment(const xml_node &alignment_node)
|
||||||
|
|
||||||
if (vertical == "bottom")
|
if (vertical == "bottom")
|
||||||
{
|
{
|
||||||
align.set_vertical(alignment::vertical_alignment::bottom);
|
align.set_vertical(vertical_alignment::bottom);
|
||||||
}
|
}
|
||||||
else if (vertical == "center")
|
else if (vertical == "center")
|
||||||
{
|
{
|
||||||
align.set_vertical(alignment::vertical_alignment::center);
|
align.set_vertical(vertical_alignment::center);
|
||||||
}
|
}
|
||||||
else if (vertical == "justify")
|
else if (vertical == "justify")
|
||||||
{
|
{
|
||||||
align.set_vertical(alignment::vertical_alignment::justify);
|
align.set_vertical(vertical_alignment::justify);
|
||||||
}
|
}
|
||||||
else if (vertical == "top")
|
else if (vertical == "top")
|
||||||
{
|
{
|
||||||
align.set_vertical(alignment::vertical_alignment::top);
|
align.set_vertical(vertical_alignment::top);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -188,27 +188,27 @@ alignment style_serializer::read_alignment(const xml_node &alignment_node)
|
||||||
|
|
||||||
if (horizontal == "left")
|
if (horizontal == "left")
|
||||||
{
|
{
|
||||||
align.set_horizontal(alignment::horizontal_alignment::left);
|
align.set_horizontal(horizontal_alignment::left);
|
||||||
}
|
}
|
||||||
else if (horizontal == "center")
|
else if (horizontal == "center")
|
||||||
{
|
{
|
||||||
align.set_horizontal(alignment::horizontal_alignment::center);
|
align.set_horizontal(horizontal_alignment::center);
|
||||||
}
|
}
|
||||||
else if (horizontal == "center-continuous")
|
else if (horizontal == "center-continuous")
|
||||||
{
|
{
|
||||||
align.set_horizontal(alignment::horizontal_alignment::center_continuous);
|
align.set_horizontal(horizontal_alignment::center_continuous);
|
||||||
}
|
}
|
||||||
else if (horizontal == "right")
|
else if (horizontal == "right")
|
||||||
{
|
{
|
||||||
align.set_horizontal(alignment::horizontal_alignment::right);
|
align.set_horizontal(horizontal_alignment::right);
|
||||||
}
|
}
|
||||||
else if (horizontal == "justify")
|
else if (horizontal == "justify")
|
||||||
{
|
{
|
||||||
align.set_horizontal(alignment::horizontal_alignment::justify);
|
align.set_horizontal(horizontal_alignment::justify);
|
||||||
}
|
}
|
||||||
else if (horizontal == "general")
|
else if (horizontal == "general")
|
||||||
{
|
{
|
||||||
align.set_horizontal(alignment::horizontal_alignment::general);
|
align.set_horizontal(horizontal_alignment::general);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -885,16 +885,16 @@ xml_document style_serializer::write_stylesheet() const
|
||||||
{
|
{
|
||||||
switch (style.alignment_.get_vertical())
|
switch (style.alignment_.get_vertical())
|
||||||
{
|
{
|
||||||
case alignment::vertical_alignment::bottom:
|
case vertical_alignment::bottom:
|
||||||
alignment_node.add_attribute("vertical", "bottom");
|
alignment_node.add_attribute("vertical", "bottom");
|
||||||
break;
|
break;
|
||||||
case alignment::vertical_alignment::center:
|
case vertical_alignment::center:
|
||||||
alignment_node.add_attribute("vertical", "center");
|
alignment_node.add_attribute("vertical", "center");
|
||||||
break;
|
break;
|
||||||
case alignment::vertical_alignment::justify:
|
case vertical_alignment::justify:
|
||||||
alignment_node.add_attribute("vertical", "justify");
|
alignment_node.add_attribute("vertical", "justify");
|
||||||
break;
|
break;
|
||||||
case alignment::vertical_alignment::top:
|
case vertical_alignment::top:
|
||||||
alignment_node.add_attribute("vertical", "top");
|
alignment_node.add_attribute("vertical", "top");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -906,22 +906,22 @@ xml_document style_serializer::write_stylesheet() const
|
||||||
{
|
{
|
||||||
switch (style.alignment_.get_horizontal())
|
switch (style.alignment_.get_horizontal())
|
||||||
{
|
{
|
||||||
case alignment::horizontal_alignment::center:
|
case horizontal_alignment::center:
|
||||||
alignment_node.add_attribute("horizontal", "center");
|
alignment_node.add_attribute("horizontal", "center");
|
||||||
break;
|
break;
|
||||||
case alignment::horizontal_alignment::center_continuous:
|
case horizontal_alignment::center_continuous:
|
||||||
alignment_node.add_attribute("horizontal", "center_continuous");
|
alignment_node.add_attribute("horizontal", "center_continuous");
|
||||||
break;
|
break;
|
||||||
case alignment::horizontal_alignment::general:
|
case horizontal_alignment::general:
|
||||||
alignment_node.add_attribute("horizontal", "general");
|
alignment_node.add_attribute("horizontal", "general");
|
||||||
break;
|
break;
|
||||||
case alignment::horizontal_alignment::justify:
|
case horizontal_alignment::justify:
|
||||||
alignment_node.add_attribute("horizontal", "justify");
|
alignment_node.add_attribute("horizontal", "justify");
|
||||||
break;
|
break;
|
||||||
case alignment::horizontal_alignment::left:
|
case horizontal_alignment::left:
|
||||||
alignment_node.add_attribute("horizontal", "left");
|
alignment_node.add_attribute("horizontal", "left");
|
||||||
break;
|
break;
|
||||||
case alignment::horizontal_alignment::right:
|
case horizontal_alignment::right:
|
||||||
alignment_node.add_attribute("horizontal", "right");
|
alignment_node.add_attribute("horizontal", "right");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
86
source/styles/alignment.cpp
Normal file
86
source/styles/alignment.cpp
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
// Copyright (c) 2014-2015 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
|
||||||
|
|
||||||
|
#include <xlnt/styles/alignment.hpp>
|
||||||
|
|
||||||
|
namespace xlnt {
|
||||||
|
|
||||||
|
bool alignment::get_wrap_text() const
|
||||||
|
{
|
||||||
|
return wrap_text_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void alignment::set_wrap_text(bool wrap_text)
|
||||||
|
{
|
||||||
|
wrap_text_ = wrap_text;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool alignment::has_horizontal() const
|
||||||
|
{
|
||||||
|
return horizontal_ != horizontal_alignment::none;
|
||||||
|
}
|
||||||
|
|
||||||
|
horizontal_alignment alignment::get_horizontal() const
|
||||||
|
{
|
||||||
|
return horizontal_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void alignment::set_horizontal(horizontal_alignment horizontal)
|
||||||
|
{
|
||||||
|
horizontal_ = horizontal;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool alignment::has_vertical() const
|
||||||
|
{
|
||||||
|
return vertical_ != vertical_alignment::none;
|
||||||
|
}
|
||||||
|
|
||||||
|
vertical_alignment alignment::get_vertical() const
|
||||||
|
{
|
||||||
|
return vertical_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void alignment::set_vertical(vertical_alignment vertical)
|
||||||
|
{
|
||||||
|
vertical_ = vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool alignment::operator==(const alignment &other) const
|
||||||
|
{
|
||||||
|
return hash() == other.hash();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t alignment::hash() const
|
||||||
|
{
|
||||||
|
std::size_t seed = 0;
|
||||||
|
hash_combine(seed, wrap_text_);
|
||||||
|
hash_combine(seed, shrink_to_fit_);
|
||||||
|
hash_combine(seed, static_cast<std::size_t>(horizontal_));
|
||||||
|
hash_combine(seed, static_cast<std::size_t>(vertical_));
|
||||||
|
hash_combine(seed, text_rotation_);
|
||||||
|
hash_combine(seed, indent_);
|
||||||
|
return seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace xlnt
|
36
source/styles/border.cpp
Normal file
36
source/styles/border.cpp
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#include <xlnt/styles/border.hpp>
|
||||||
|
|
||||||
|
namespace xlnt {
|
||||||
|
|
||||||
|
bool border::operator==(const border &other) const
|
||||||
|
{
|
||||||
|
return hash() == other.hash();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t border::hash() const
|
||||||
|
{
|
||||||
|
std::size_t seed = 0;
|
||||||
|
|
||||||
|
hash_combine(seed, start_assigned);
|
||||||
|
if (start_assigned) hash_combine(seed, start.hash());
|
||||||
|
hash_combine(seed, end_assigned);
|
||||||
|
if (end_assigned) hash_combine(seed, end.hash());
|
||||||
|
hash_combine(seed, left_assigned);
|
||||||
|
if (left_assigned) hash_combine(seed, left.hash());
|
||||||
|
hash_combine(seed, right_assigned);
|
||||||
|
if (right_assigned) hash_combine(seed, right.hash());
|
||||||
|
hash_combine(seed, top_assigned);
|
||||||
|
if (top_assigned) hash_combine(seed, top.hash());
|
||||||
|
hash_combine(seed, bottom_assigned);
|
||||||
|
if (bottom_assigned) hash_combine(seed, bottom.hash());
|
||||||
|
hash_combine(seed, diagonal_assigned);
|
||||||
|
if (diagonal_assigned) hash_combine(seed, diagonal.hash());
|
||||||
|
hash_combine(seed, vertical_assigned);
|
||||||
|
if (vertical_assigned) hash_combine(seed, vertical.hash());
|
||||||
|
hash_combine(seed, horizontal_assigned);
|
||||||
|
if (horizontal_assigned) hash_combine(seed, horizontal.hash());
|
||||||
|
|
||||||
|
return seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace xlnt
|
|
@ -1,6 +1,7 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
|
||||||
|
#include <xlnt/utils/datetime.hpp>
|
||||||
#include <xlnt/utils/hash_combine.hpp>
|
#include <xlnt/utils/hash_combine.hpp>
|
||||||
#include <xlnt/styles/number_format.hpp>
|
#include <xlnt/styles/number_format.hpp>
|
||||||
|
|
||||||
|
@ -65,6 +66,764 @@ const std::unordered_map<std::size_t, std::string> &builtin_formats()
|
||||||
return *formats;
|
return *formats;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class condition_type
|
||||||
|
{
|
||||||
|
less_than,
|
||||||
|
less_or_equal,
|
||||||
|
equal,
|
||||||
|
greater_than,
|
||||||
|
greater_or_equal,
|
||||||
|
invalid
|
||||||
|
};
|
||||||
|
|
||||||
|
struct section
|
||||||
|
{
|
||||||
|
bool has_value = false;
|
||||||
|
std::string value;
|
||||||
|
bool has_color = false;
|
||||||
|
std::string color;
|
||||||
|
bool has_condition = false;
|
||||||
|
condition_type condition = condition_type::invalid;
|
||||||
|
std::string condition_value;
|
||||||
|
bool has_locale = false;
|
||||||
|
std::string locale;
|
||||||
|
|
||||||
|
section &operator=(const section &other)
|
||||||
|
{
|
||||||
|
has_value = other.has_value;
|
||||||
|
value = other.value;
|
||||||
|
has_color = other.has_color;
|
||||||
|
color = other.color;
|
||||||
|
has_condition = other.has_condition;
|
||||||
|
condition = other.condition;
|
||||||
|
condition_value = other.condition_value;
|
||||||
|
has_locale = other.has_locale;
|
||||||
|
locale = other.locale;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct format_sections
|
||||||
|
{
|
||||||
|
section first;
|
||||||
|
section second;
|
||||||
|
section third;
|
||||||
|
section fourth;
|
||||||
|
};
|
||||||
|
|
||||||
|
// copied from named_range.cpp, keep in sync
|
||||||
|
/// <summary>
|
||||||
|
/// Return a vector containing string split at each delim.
|
||||||
|
/// </summary>
|
||||||
|
/// <remark>
|
||||||
|
/// This should maybe be in a utility header so it can be used elsewhere.
|
||||||
|
/// </remarks>
|
||||||
|
std::vector<std::string> split_string(const std::string &string, char delim)
|
||||||
|
{
|
||||||
|
std::vector<std::string> split;
|
||||||
|
std::string::size_type previous_index = 0;
|
||||||
|
auto separator_index = string.find(delim);
|
||||||
|
|
||||||
|
while (separator_index != std::string::npos)
|
||||||
|
{
|
||||||
|
auto part = string.substr(previous_index, separator_index - previous_index);
|
||||||
|
split.push_back(part);
|
||||||
|
|
||||||
|
previous_index = separator_index + 1;
|
||||||
|
separator_index = string.find(delim, previous_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
split.push_back(string.substr(previous_index));
|
||||||
|
|
||||||
|
return split;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> split_string_any(const std::string &string, const std::string &delims)
|
||||||
|
{
|
||||||
|
std::vector<std::string> split;
|
||||||
|
std::string::size_type previous_index = 0;
|
||||||
|
auto separator_index = string.find_first_of(delims);
|
||||||
|
|
||||||
|
while (separator_index != std::string::npos)
|
||||||
|
{
|
||||||
|
auto part = string.substr(previous_index, separator_index - previous_index);
|
||||||
|
|
||||||
|
if (!part.empty())
|
||||||
|
{
|
||||||
|
split.push_back(part);
|
||||||
|
}
|
||||||
|
|
||||||
|
previous_index = separator_index + 1;
|
||||||
|
separator_index = string.find_first_of(delims, previous_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
split.push_back(string.substr(previous_index));
|
||||||
|
|
||||||
|
return split;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_date_format(const std::string &format_string)
|
||||||
|
{
|
||||||
|
auto not_in = format_string.find_first_not_of("/-:, mMyYdDhHsS");
|
||||||
|
return not_in == std::string::npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_valid_color(const std::string &color)
|
||||||
|
{
|
||||||
|
static const std::vector<std::string> *colors =
|
||||||
|
new std::vector<std::string>(
|
||||||
|
{
|
||||||
|
"Black",
|
||||||
|
"Green"
|
||||||
|
"White",
|
||||||
|
"Blue",
|
||||||
|
"Magenta",
|
||||||
|
"Yellow",
|
||||||
|
"Cyan",
|
||||||
|
"Red"
|
||||||
|
});
|
||||||
|
|
||||||
|
auto compare_color = [&](const std::string &other) {
|
||||||
|
if (color.size() != other.size()) return false;
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < color.size(); i++)
|
||||||
|
{
|
||||||
|
if (std::toupper(color[i]) != std::toupper(other[i]))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
return std::find_if(colors->begin(), colors->end(), compare_color) != colors->end();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool parse_condition(const std::string &string, section &s)
|
||||||
|
{
|
||||||
|
s.has_condition = false;
|
||||||
|
s.condition = condition_type::invalid;
|
||||||
|
s.condition_value.clear();
|
||||||
|
|
||||||
|
if (string[0] == '<')
|
||||||
|
{
|
||||||
|
s.has_condition = true;
|
||||||
|
|
||||||
|
if (string[1] == '=')
|
||||||
|
{
|
||||||
|
s.condition = condition_type::less_or_equal;
|
||||||
|
s.condition_value = string.substr(2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s.condition = condition_type::less_than;
|
||||||
|
s.condition_value = string.substr(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (string[0] == '>')
|
||||||
|
{
|
||||||
|
s.has_condition = true;
|
||||||
|
|
||||||
|
if (string[1] == '=')
|
||||||
|
{
|
||||||
|
s.condition = condition_type::greater_or_equal;
|
||||||
|
s.condition_value = string.substr(2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s.condition = condition_type::greater_than;
|
||||||
|
s.condition_value = string.substr(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (string[0] == '=')
|
||||||
|
{
|
||||||
|
s.has_condition = true;
|
||||||
|
s.condition = condition_type::equal;
|
||||||
|
s.condition_value = string.substr(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.has_condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_hex(char c)
|
||||||
|
{
|
||||||
|
if (c >= 'A' || c <= 'F') return true;
|
||||||
|
if (c >= '0' || c <= '9') return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::unordered_map<int, std::string> known_locales()
|
||||||
|
{
|
||||||
|
const std::unordered_map<int, std::string> *all =
|
||||||
|
new std::unordered_map<int, std::string>(
|
||||||
|
{
|
||||||
|
{ 0x401, "Arabic - Saudi Arabia" },
|
||||||
|
{ 0x402, "Bulgarian" },
|
||||||
|
{ 0x403, "Catalan" },
|
||||||
|
{ 0x404, "Chinese - Taiwan" },
|
||||||
|
{ 0x405, "Czech" },
|
||||||
|
{ 0x406, "Danish" },
|
||||||
|
{ 0x407, "German - Germany" },
|
||||||
|
{ 0x408, "Greek" },
|
||||||
|
{ 0x409, "English - United States" },
|
||||||
|
{ 0x410, "Italian - Italy" },
|
||||||
|
{ 0x411, "Japanese" },
|
||||||
|
{ 0x412, "Korean" },
|
||||||
|
{ 0x413, "Dutch - Netherlands" },
|
||||||
|
{ 0x414, "Norwegian - Bokml" },
|
||||||
|
{ 0x415, "Polish" },
|
||||||
|
{ 0x416, "Portuguese - Brazil" },
|
||||||
|
{ 0x417, "Raeto-Romance" },
|
||||||
|
{ 0x418, "Romanian - Romania" },
|
||||||
|
{ 0x419, "Russian" },
|
||||||
|
{ 0x420, "Urdu" },
|
||||||
|
{ 0x421, "Indonesian" },
|
||||||
|
{ 0x422, "Ukrainian" },
|
||||||
|
{ 0x423, "Belarusian" },
|
||||||
|
{ 0x424, "Slovenian" },
|
||||||
|
{ 0x425, "Estonian" },
|
||||||
|
{ 0x426, "Latvian" },
|
||||||
|
{ 0x427, "Lithuanian" },
|
||||||
|
{ 0x428, "Tajik" },
|
||||||
|
{ 0x429, "Farsi - Persian" },
|
||||||
|
{ 0x430, "Sesotho (Sutu)" },
|
||||||
|
{ 0x431, "Tsonga" },
|
||||||
|
{ 0x432, "Setsuana" },
|
||||||
|
{ 0x433, "Venda" },
|
||||||
|
{ 0x434, "Xhosa" },
|
||||||
|
{ 0x435, "Zulu" },
|
||||||
|
{ 0x436, "Afrikaans" },
|
||||||
|
{ 0x437, "Georgian" },
|
||||||
|
{ 0x438, "Faroese" },
|
||||||
|
{ 0x439, "Hindi" },
|
||||||
|
{ 0x440, "Kyrgyz - Cyrillic" },
|
||||||
|
{ 0x441, "Swahili" },
|
||||||
|
{ 0x442, "Turkmen" },
|
||||||
|
{ 0x443, "Uzbek - Latin" },
|
||||||
|
{ 0x444, "Tatar" },
|
||||||
|
{ 0x445, "Bengali - India" },
|
||||||
|
{ 0x446, "Punjabi" },
|
||||||
|
{ 0x447, "Gujarati" },
|
||||||
|
{ 0x448, "Oriya" },
|
||||||
|
{ 0x449, "Tamil" },
|
||||||
|
{ 0x450, "Mongolian" },
|
||||||
|
{ 0x451, "Tibetan" },
|
||||||
|
{ 0x452, "Welsh" },
|
||||||
|
{ 0x453, "Khmer" },
|
||||||
|
{ 0x454, "Lao" },
|
||||||
|
{ 0x455, "Burmese" },
|
||||||
|
{ 0x456, "Galician" },
|
||||||
|
{ 0x457, "Konkani" },
|
||||||
|
{ 0x458, "Manipuri" },
|
||||||
|
{ 0x459, "Sindhi" },
|
||||||
|
{ 0x460, "Kashmiri" },
|
||||||
|
{ 0x461, "Nepali" },
|
||||||
|
{ 0x462, "Frisian - Netherlands" },
|
||||||
|
{ 0x464, "Filipino" },
|
||||||
|
{ 0x465, "Divehi; Dhivehi; Maldivian" },
|
||||||
|
{ 0x466, "Edo" },
|
||||||
|
{ 0x470, "Igbo - Nigeria" },
|
||||||
|
{ 0x474, "Guarani - Paraguay" },
|
||||||
|
{ 0x476, "Latin" },
|
||||||
|
{ 0x477, "Somali" },
|
||||||
|
{ 0x481, "Maori" },
|
||||||
|
{ 0x801, "Arabic - Iraq" },
|
||||||
|
{ 0x804, "Chinese - China" },
|
||||||
|
{ 0x807, "German - Switzerland" },
|
||||||
|
{ 0x809, "English - Great Britain" },
|
||||||
|
{ 0x810, "Italian - Switzerland" },
|
||||||
|
{ 0x813, "Dutch - Belgium" },
|
||||||
|
{ 0x814, "Norwegian - Nynorsk" },
|
||||||
|
{ 0x816, "Portuguese - Portugal" },
|
||||||
|
{ 0x818, "Romanian - Moldova" },
|
||||||
|
{ 0x819, "Russian - Moldova" },
|
||||||
|
{ 0x843, "Uzbek - Cyrillic" },
|
||||||
|
{ 0x845, "Bengali - Bangladesh" },
|
||||||
|
{ 0x850, "Mongolian" },
|
||||||
|
{ 0x1001, "Arabic - Libya" },
|
||||||
|
{ 0x1004, "Chinese - Singapore" },
|
||||||
|
{ 0x1007, "German - Luxembourg" },
|
||||||
|
{ 0x1009, "English - Canada" },
|
||||||
|
{ 0x1401, "Arabic - Algeria" },
|
||||||
|
{ 0x1404, "Chinese - Macau SAR" },
|
||||||
|
{ 0x1407, "German - Liechtenstein" },
|
||||||
|
{ 0x1409, "English - New Zealand" },
|
||||||
|
{ 0x1801, "Arabic - Morocco" },
|
||||||
|
{ 0x1809, "English - Ireland" },
|
||||||
|
{ 0x2001, "Arabic - Oman" },
|
||||||
|
{ 0x2009, "English - Jamaica" },
|
||||||
|
{ 0x2401, "Arabic - Yemen" },
|
||||||
|
{ 0x2409, "English - Caribbean" },
|
||||||
|
{ 0x2801, "Arabic - Syria" },
|
||||||
|
{ 0x2809, "English - Belize" },
|
||||||
|
{ 0x3001, "Arabic - Lebanon" },
|
||||||
|
{ 0x3009, "English - Zimbabwe" },
|
||||||
|
{ 0x3401, "Arabic - Kuwait" },
|
||||||
|
{ 0x3409, "English - Phillippines" },
|
||||||
|
{ 0x3801, "Arabic - United Arab Emirates" },
|
||||||
|
{ 0x4001, "Arabic - Qatar" }
|
||||||
|
});
|
||||||
|
|
||||||
|
return *all;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_valid_locale(const std::string &locale_string)
|
||||||
|
{
|
||||||
|
std::string country = locale_string.substr(locale_string.find('-') + 1);
|
||||||
|
|
||||||
|
if (country.empty())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto c : country)
|
||||||
|
{
|
||||||
|
if (!is_hex(static_cast<char>(std::toupper(c))))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto index = std::stoi(country, 0, 16);
|
||||||
|
|
||||||
|
auto known_locales_ = known_locales();
|
||||||
|
|
||||||
|
if (known_locales_.find(index) == known_locales_.end())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string beginning = locale_string.substr(0, locale_string.find('-'));
|
||||||
|
|
||||||
|
if (beginning.empty() || beginning[0] != '$')
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (beginning.size() == 1)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
beginning = beginning.substr(1);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
section parse_section(const std::string §ion_string)
|
||||||
|
{
|
||||||
|
section s;
|
||||||
|
|
||||||
|
std::string format_part;
|
||||||
|
std::string bracket_part;
|
||||||
|
|
||||||
|
std::vector<std::string> bracket_parts;
|
||||||
|
|
||||||
|
bool in_quotes = false;
|
||||||
|
bool in_brackets = false;
|
||||||
|
|
||||||
|
const std::vector<std::string> bracket_times = { "h", "hh", "m", "mm", "s", "ss" };
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < section_string.size(); i++)
|
||||||
|
{
|
||||||
|
if (!in_quotes && section_string[i] == '"')
|
||||||
|
{
|
||||||
|
format_part.push_back(section_string[i]);
|
||||||
|
in_quotes = true;
|
||||||
|
}
|
||||||
|
else if (in_quotes && section_string[i] == '"')
|
||||||
|
{
|
||||||
|
format_part.push_back(section_string[i]);
|
||||||
|
|
||||||
|
if (i < section_string.size() - 1 && section_string[i + 1] != '"')
|
||||||
|
{
|
||||||
|
in_quotes = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!in_brackets && section_string[i] == '[')
|
||||||
|
{
|
||||||
|
in_brackets = true;
|
||||||
|
|
||||||
|
for (auto bracket_time : bracket_times)
|
||||||
|
{
|
||||||
|
if (i < section_string.size() - bracket_time.size() &&
|
||||||
|
section_string.substr(i + 1, bracket_time.size()) == bracket_time)
|
||||||
|
{
|
||||||
|
in_brackets = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (in_brackets)
|
||||||
|
{
|
||||||
|
if (section_string[i] == ']')
|
||||||
|
{
|
||||||
|
in_brackets = false;
|
||||||
|
|
||||||
|
if (is_valid_color(bracket_part))
|
||||||
|
{
|
||||||
|
if (s.color.empty())
|
||||||
|
{
|
||||||
|
s.color = bracket_part;
|
||||||
|
s.has_color = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw std::runtime_error("two colors");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (is_valid_locale(bracket_part))
|
||||||
|
{
|
||||||
|
if (s.locale.empty())
|
||||||
|
{
|
||||||
|
s.locale = bracket_part;
|
||||||
|
s.has_locale = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw std::runtime_error("two locales");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (s.has_condition || !parse_condition(bracket_part, s))
|
||||||
|
{
|
||||||
|
throw std::runtime_error("invalid bracket format");
|
||||||
|
}
|
||||||
|
|
||||||
|
bracket_part.clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bracket_part.push_back(section_string[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
format_part.push_back(section_string[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s.value = format_part;
|
||||||
|
s.has_value = true;
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
format_sections parse_format_sections(const std::string &combined)
|
||||||
|
{
|
||||||
|
format_sections result = {};
|
||||||
|
|
||||||
|
auto split = split_string(combined, ';');
|
||||||
|
|
||||||
|
if (split.empty())
|
||||||
|
{
|
||||||
|
throw std::runtime_error("empty string");
|
||||||
|
}
|
||||||
|
|
||||||
|
result.first = parse_section(split[0]);
|
||||||
|
|
||||||
|
if (!result.first.has_condition)
|
||||||
|
{
|
||||||
|
result.second = result.first;
|
||||||
|
result.third = result.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (split.size() > 1)
|
||||||
|
{
|
||||||
|
result.second = parse_section(split[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (split.size() > 2)
|
||||||
|
{
|
||||||
|
if (result.first.has_condition && !result.second.has_condition)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("first two sections should have conditions");
|
||||||
|
}
|
||||||
|
|
||||||
|
result.third = parse_section(split[2]);
|
||||||
|
|
||||||
|
if (result.third.has_condition)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("third section shouldn't have a condition");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (split.size() > 3)
|
||||||
|
{
|
||||||
|
if (result.first.has_condition)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("too many parts");
|
||||||
|
}
|
||||||
|
|
||||||
|
result.fourth = parse_section(split[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (split.size() > 4)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("too many parts");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string format_section(long double number, const section &format, xlnt::calendar base_date)
|
||||||
|
{
|
||||||
|
const std::string unquoted = "$+(:^'{<=-/)!&~}> ";
|
||||||
|
std::string format_temp = format.value;
|
||||||
|
std::string result;
|
||||||
|
|
||||||
|
if (is_date_format(format.value))
|
||||||
|
{
|
||||||
|
const std::string date_unquoted = ",-/: ";
|
||||||
|
|
||||||
|
const std::vector<std::string> dates = { "m", "mm", "mmm", "mmmmm", "mmmmmm", "d", "dd", "ddd", "dddd", "yy",
|
||||||
|
"yyyy", "h", "[h]", "hh", "m", "[m]", "mm", "s", "[s]", "ss", "AM/PM",
|
||||||
|
"am/pm", "A/P", "a/p" };
|
||||||
|
|
||||||
|
const std::vector<std::string> MonthNames = { "January", "February", "March",
|
||||||
|
"April", "May", "June", "July", "August", "September", "October", "November", "December" };
|
||||||
|
|
||||||
|
|
||||||
|
auto split = split_string_any(format.value, date_unquoted);
|
||||||
|
std::string::size_type index = 0, prev = 0;
|
||||||
|
auto d = xlnt::datetime::from_number(number, base_date);
|
||||||
|
bool processed_month = false;
|
||||||
|
|
||||||
|
auto lower_string = [](const std::string &s) {
|
||||||
|
std::string lower;
|
||||||
|
lower.resize(s.size());
|
||||||
|
for (std::size_t i = 0; i < s.size(); i++)
|
||||||
|
lower[i] = static_cast<char>(std::tolower(s[i]));
|
||||||
|
return lower;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto part : split)
|
||||||
|
{
|
||||||
|
while (format.value.substr(index, part.size()) != part)
|
||||||
|
{
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto between = format.value.substr(prev, index - prev);
|
||||||
|
result.append(between);
|
||||||
|
|
||||||
|
part = lower_string(part);
|
||||||
|
|
||||||
|
if (part == "m" && !processed_month)
|
||||||
|
{
|
||||||
|
result.append(std::to_string(d.month));
|
||||||
|
processed_month = true;
|
||||||
|
}
|
||||||
|
else if (part == "mm" && !processed_month)
|
||||||
|
{
|
||||||
|
if (d.month < 10)
|
||||||
|
{
|
||||||
|
result.append("0");
|
||||||
|
}
|
||||||
|
|
||||||
|
result.append(std::to_string(d.month));
|
||||||
|
processed_month = true;
|
||||||
|
}
|
||||||
|
else if (part == "mmm" && !processed_month)
|
||||||
|
{
|
||||||
|
result.append(MonthNames.at(static_cast<std::size_t>(d.month - 1)).substr(0, 3));
|
||||||
|
processed_month = true;
|
||||||
|
}
|
||||||
|
else if (part == "mmmm" && !processed_month)
|
||||||
|
{
|
||||||
|
result.append(MonthNames.at(static_cast<std::size_t>(d.month - 1)));
|
||||||
|
processed_month = true;
|
||||||
|
}
|
||||||
|
else if (part == "d")
|
||||||
|
{
|
||||||
|
result.append(std::to_string(d.day));
|
||||||
|
}
|
||||||
|
else if (part == "dd")
|
||||||
|
{
|
||||||
|
if (d.day < 10)
|
||||||
|
{
|
||||||
|
result.append("0");
|
||||||
|
}
|
||||||
|
|
||||||
|
result.append(std::to_string(d.day));
|
||||||
|
}
|
||||||
|
else if (part == "yyyy")
|
||||||
|
{
|
||||||
|
result.append(std::to_string(d.year));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (part == "h")
|
||||||
|
{
|
||||||
|
result.append(std::to_string(d.hour));
|
||||||
|
processed_month = true;
|
||||||
|
}
|
||||||
|
else if (part == "hh")
|
||||||
|
{
|
||||||
|
if (d.hour < 10)
|
||||||
|
{
|
||||||
|
result.append("0");
|
||||||
|
}
|
||||||
|
|
||||||
|
result.append(std::to_string(d.hour));
|
||||||
|
processed_month = true;
|
||||||
|
}
|
||||||
|
else if (part == "m")
|
||||||
|
{
|
||||||
|
result.append(std::to_string(d.minute));
|
||||||
|
}
|
||||||
|
else if (part == "mm")
|
||||||
|
{
|
||||||
|
if (d.minute < 10)
|
||||||
|
{
|
||||||
|
result.append("0");
|
||||||
|
}
|
||||||
|
|
||||||
|
result.append(std::to_string(d.minute));
|
||||||
|
}
|
||||||
|
else if (part == "s")
|
||||||
|
{
|
||||||
|
result.append(std::to_string(d.second));
|
||||||
|
}
|
||||||
|
else if (part == "ss")
|
||||||
|
{
|
||||||
|
if (d.second < 10)
|
||||||
|
{
|
||||||
|
result.append("0");
|
||||||
|
}
|
||||||
|
|
||||||
|
result.append(std::to_string(d.second));
|
||||||
|
}
|
||||||
|
else if (part == "am/pm" || part == "a/p")
|
||||||
|
{
|
||||||
|
if (d.hour < 12)
|
||||||
|
{
|
||||||
|
result.append("AM");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.append("PM");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
index += part.size();
|
||||||
|
prev = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index < format.value.size())
|
||||||
|
{
|
||||||
|
result.append(format.value.substr(index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (format.value == "General" || format.value == "0")
|
||||||
|
{
|
||||||
|
if (number == static_cast<long long int>(number))
|
||||||
|
{
|
||||||
|
result = std::to_string(static_cast<long long int>(number));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = std::to_string(number);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (format.value.substr(0, 8) == "#,##0.00" || format.value.substr(0, 9) == "-#,##0.00")
|
||||||
|
{
|
||||||
|
if (format.value[0] == '-')
|
||||||
|
{
|
||||||
|
result = "-";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format.has_locale && format.locale == "$$-1009")
|
||||||
|
{
|
||||||
|
result += "CA$";
|
||||||
|
}
|
||||||
|
else if (format.has_locale && format.locale == "$€-407")
|
||||||
|
{
|
||||||
|
result += "€";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result += "$";
|
||||||
|
}
|
||||||
|
|
||||||
|
result += std::to_string(number < 0 ? -number : number);
|
||||||
|
|
||||||
|
auto decimal_pos = result.find('.');
|
||||||
|
|
||||||
|
if (decimal_pos != std::string::npos)
|
||||||
|
{
|
||||||
|
result[decimal_pos] = ',';
|
||||||
|
decimal_pos += 3;
|
||||||
|
|
||||||
|
while (decimal_pos < result.size())
|
||||||
|
{
|
||||||
|
result.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string format_section(const std::string &text, const section &format)
|
||||||
|
{
|
||||||
|
auto arobase_index = format.value.find('@');
|
||||||
|
|
||||||
|
std::string first_part, middle_part, last_part;
|
||||||
|
|
||||||
|
if (arobase_index != std::string::npos)
|
||||||
|
{
|
||||||
|
first_part = format.value.substr(0, arobase_index);
|
||||||
|
middle_part = text;
|
||||||
|
last_part = format.value.substr(arobase_index + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
first_part = format.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto unquote = [](std::string &s) {
|
||||||
|
if (!s.empty())
|
||||||
|
{
|
||||||
|
if (s.front() != '"' || s.back() != '"') return false;
|
||||||
|
s = s.substr(0, s.size() - 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!unquote(first_part) || !unquote(last_part))
|
||||||
|
{
|
||||||
|
throw std::runtime_error(std::string("additional text must be enclosed in quotes: ") + format.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return first_part + middle_part + last_part;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string format_number(long double number, const std::string &format, xlnt::calendar base_date)
|
||||||
|
{
|
||||||
|
auto sections = parse_format_sections(format);
|
||||||
|
|
||||||
|
if (number > 0)
|
||||||
|
{
|
||||||
|
return format_section(number, sections.first, base_date);
|
||||||
|
}
|
||||||
|
else if (number < 0)
|
||||||
|
{
|
||||||
|
return format_section(number, sections.second, base_date);
|
||||||
|
}
|
||||||
|
|
||||||
|
// number == 0
|
||||||
|
return format_section(number, sections.third, base_date);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string format_text(const std::string &text, const std::string &format)
|
||||||
|
{
|
||||||
|
if (format == "General") return text;
|
||||||
|
auto sections = parse_format_sections(format);
|
||||||
|
return format_section(text, sections.fourth);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
@ -340,4 +1099,58 @@ void number_format::set_format_string(const std::string &format_string, std::siz
|
||||||
id_set_ = true;
|
id_set_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool number_format::has_id() const
|
||||||
|
{
|
||||||
|
return id_set_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void number_format::set_id(std::size_t id)
|
||||||
|
{
|
||||||
|
id_ = id;
|
||||||
|
id_set_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t number_format::get_id() const
|
||||||
|
{
|
||||||
|
if(!id_set_)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("number format doesn't have an id");
|
||||||
|
}
|
||||||
|
|
||||||
|
return id_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool number_format::is_date_format() const
|
||||||
|
{
|
||||||
|
if (format_string_ != "General")
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
auto sections = parse_format_sections(format_string_);
|
||||||
|
return ::is_date_format(sections.first.value);
|
||||||
|
}
|
||||||
|
catch (std::exception)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string number_format::format(const std::string &text) const
|
||||||
|
{
|
||||||
|
return format_text(text, format_string_);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string number_format::format(long double number, calendar base_date) const
|
||||||
|
{
|
||||||
|
return format_number(number, format_string_, base_date);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool number_format::operator==(const number_format &other) const
|
||||||
|
{
|
||||||
|
return hash() == other.hash();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace xlnt
|
} // namespace xlnt
|
||||||
|
|
|
@ -3,7 +3,130 @@
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
template <>
|
cell_vector::iterator::iterator(worksheet ws, const cell_reference &start_cell, major_order order)
|
||||||
|
: ws_(ws), current_cell_(start_cell), range_(start_cell.to_range()), order_(order)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
cell_vector::iterator::iterator(const iterator &other)
|
||||||
|
{
|
||||||
|
*this = other;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cell_vector::iterator::operator==(const iterator &other) const
|
||||||
|
{
|
||||||
|
return ws_ == other.ws_ && current_cell_ == other.current_cell_ && order_ == other.order_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cell_vector::iterator::operator!=(const iterator &other) const
|
||||||
|
{
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
cell_vector::iterator &cell_vector::iterator::operator--()
|
||||||
|
{
|
||||||
|
if (order_ == major_order::row)
|
||||||
|
{
|
||||||
|
current_cell_.set_column_index(current_cell_.get_column_index() - 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
current_cell_.set_row(current_cell_.get_row() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
cell_vector::iterator cell_vector::iterator::operator--(int)
|
||||||
|
{
|
||||||
|
iterator old = *this;
|
||||||
|
--*this;
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
|
||||||
|
cell_vector::iterator &cell_vector::iterator::operator++()
|
||||||
|
{
|
||||||
|
if (order_ == major_order::row)
|
||||||
|
{
|
||||||
|
current_cell_.set_column_index(current_cell_.get_column_index() + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
current_cell_.set_row(current_cell_.get_row() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
cell_vector::iterator cell_vector::iterator::operator++(int)
|
||||||
|
{
|
||||||
|
iterator old = *this;
|
||||||
|
++*this;
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
|
||||||
|
cell_vector::const_iterator::const_iterator(worksheet ws, const cell_reference &start_cell, major_order order)
|
||||||
|
: ws_(ws), current_cell_(start_cell), range_(start_cell.to_range()), order_(order)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
cell_vector::const_iterator::const_iterator(const const_iterator &other)
|
||||||
|
{
|
||||||
|
*this = other;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cell_vector::const_iterator::operator==(const const_iterator &other) const
|
||||||
|
{
|
||||||
|
return ws_ == other.ws_ && current_cell_ == other.current_cell_ && order_ == other.order_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cell_vector::const_iterator::operator!=(const const_iterator &other) const
|
||||||
|
{
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
cell_vector::const_iterator &cell_vector::const_iterator::operator--()
|
||||||
|
{
|
||||||
|
if (order_ == major_order::row)
|
||||||
|
{
|
||||||
|
current_cell_.set_column_index(current_cell_.get_column_index() - 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
current_cell_.set_row(current_cell_.get_row() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
cell_vector::const_iterator cell_vector::const_iterator::operator--(int)
|
||||||
|
{
|
||||||
|
const_iterator old = *this;
|
||||||
|
--*this;
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
|
||||||
|
cell_vector::const_iterator &cell_vector::const_iterator::operator++()
|
||||||
|
{
|
||||||
|
if (order_ == major_order::row)
|
||||||
|
{
|
||||||
|
current_cell_.set_column_index(current_cell_.get_column_index() + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
current_cell_.set_row(current_cell_.get_row() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
cell_vector::const_iterator cell_vector::const_iterator::operator++(int)
|
||||||
|
{
|
||||||
|
const_iterator old = *this;
|
||||||
|
++*this;
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
|
||||||
cell cell_vector::iterator::operator*()
|
cell cell_vector::iterator::operator*()
|
||||||
{
|
{
|
||||||
return ws_[current_cell_];
|
return ws_[current_cell_];
|
||||||
|
|
34
source/worksheet/footer.cpp
Normal file
34
source/worksheet/footer.cpp
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#include <xlnt/worksheet/footer.hpp>
|
||||||
|
|
||||||
|
namespace xlnt {
|
||||||
|
|
||||||
|
void footer::set_text(const std::string &text)
|
||||||
|
{
|
||||||
|
default_ = false;
|
||||||
|
text_ = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
void footer::set_font_name(const std::string &font_name)
|
||||||
|
{
|
||||||
|
default_ = false;
|
||||||
|
font_name_ = font_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void footer::set_font_size(std::size_t font_size)
|
||||||
|
{
|
||||||
|
default_ = false;
|
||||||
|
font_size_ = font_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void footer::set_font_color(const std::string &font_color)
|
||||||
|
{
|
||||||
|
default_ = false;
|
||||||
|
font_color_ = font_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool footer::is_default() const
|
||||||
|
{
|
||||||
|
return default_;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace xlnt
|
34
source/worksheet/header.cpp
Normal file
34
source/worksheet/header.cpp
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#include <xlnt/worksheet/header.hpp>
|
||||||
|
|
||||||
|
namespace xlnt {
|
||||||
|
|
||||||
|
void header::set_text(const std::string &text)
|
||||||
|
{
|
||||||
|
default_ = false;
|
||||||
|
text_ = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
void header::set_font_name(const std::string &font_name)
|
||||||
|
{
|
||||||
|
default_ = false;
|
||||||
|
font_name_ = font_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void header::set_font_size(std::size_t font_size)
|
||||||
|
{
|
||||||
|
default_ = false;
|
||||||
|
font_size_ = font_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void header::set_font_color(const std::string &font_color)
|
||||||
|
{
|
||||||
|
default_ = false;
|
||||||
|
font_color_ = font_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool header::is_default() const
|
||||||
|
{
|
||||||
|
return default_;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace xlnt
|
|
@ -5,8 +5,8 @@
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
range::range(worksheet ws, const range_reference &reference, major_order order)
|
range::range(worksheet ws, const range_reference &reference, major_order order, bool skip_null)
|
||||||
: ws_(ws), ref_(reference), order_(order)
|
: ws_(ws), ref_(reference), order_(order), skip_null_(skip_null)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +133,6 @@ range::const_iterator range::cend() const
|
||||||
return const_iterator(ws_, range_reference(top_right, bottom_right), order_);
|
return const_iterator(ws_, range_reference(top_right, bottom_right), order_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
|
||||||
cell_vector range::iterator::operator*()
|
cell_vector range::iterator::operator*()
|
||||||
{
|
{
|
||||||
if (order_ == major_order::row)
|
if (order_ == major_order::row)
|
||||||
|
@ -148,4 +147,147 @@ cell_vector range::iterator::operator*()
|
||||||
return cell_vector(ws_, reference, order_);
|
return cell_vector(ws_, reference, order_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
range_iterator_2d::range_iterator_2d(worksheet &ws, const range_reference &start_cell, major_order order)
|
||||||
|
: ws_(ws.d_), current_cell_(start_cell.get_top_left()), range_(start_cell), order_(order)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
range_iterator_2d::range_iterator_2d(const range_iterator_2d &other)
|
||||||
|
{
|
||||||
|
*this = other;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool range_iterator_2d::operator==(const range_iterator_2d &other) const
|
||||||
|
{
|
||||||
|
return ws_ == other.ws_ && current_cell_ == other.current_cell_ && order_ == other.order_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool range_iterator_2d::operator!=(const range_iterator_2d &other) const
|
||||||
|
{
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
range_iterator_2d &range_iterator_2d::operator--()
|
||||||
|
{
|
||||||
|
if (order_ == major_order::row)
|
||||||
|
{
|
||||||
|
current_cell_.set_row(current_cell_.get_row() - 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
current_cell_.set_column_index(current_cell_.get_column_index() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
range_iterator_2d range_iterator_2d::operator--(int)
|
||||||
|
{
|
||||||
|
range_iterator_2d old = *this;
|
||||||
|
--*this;
|
||||||
|
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
|
||||||
|
range_iterator_2d &range_iterator_2d::operator++()
|
||||||
|
{
|
||||||
|
if (order_ == major_order::row)
|
||||||
|
{
|
||||||
|
current_cell_.set_row(current_cell_.get_row() + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
current_cell_.set_column_index(current_cell_.get_column_index() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
range_iterator_2d range_iterator_2d::operator++(int)
|
||||||
|
{
|
||||||
|
range_iterator_2d old = *this;
|
||||||
|
++*this;
|
||||||
|
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
|
||||||
|
const_range_iterator_2d::const_range_iterator_2d(const worksheet &ws, const range_reference &start_cell, major_order order)
|
||||||
|
: ws_(ws.d_), current_cell_(start_cell.get_top_left()), range_(start_cell), order_(order)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const_range_iterator_2d::const_range_iterator_2d(const const_range_iterator_2d &other)
|
||||||
|
{
|
||||||
|
*this = other;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool const_range_iterator_2d::operator==(const const_range_iterator_2d &other) const
|
||||||
|
{
|
||||||
|
return ws_ == other.ws_ && current_cell_ == other.current_cell_ && order_ == other.order_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool const_range_iterator_2d::operator!=(const const_range_iterator_2d &other) const
|
||||||
|
{
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
range::const_iterator &range::const_iterator::operator--()
|
||||||
|
{
|
||||||
|
if (order_ == major_order::row)
|
||||||
|
{
|
||||||
|
current_cell_.set_row(current_cell_.get_row() - 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
current_cell_.set_column_index(current_cell_.get_column_index() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
range::const_iterator range::const_iterator::operator--(int)
|
||||||
|
{
|
||||||
|
const_range_iterator_2d old = *this;
|
||||||
|
--*this;
|
||||||
|
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
|
||||||
|
range::const_iterator &range::const_iterator::operator++()
|
||||||
|
{
|
||||||
|
if (order_ == major_order::row)
|
||||||
|
{
|
||||||
|
current_cell_.set_row(current_cell_.get_row() + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
current_cell_.set_column_index(current_cell_.get_column_index() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
range::const_iterator range::const_iterator::operator++(int)
|
||||||
|
{
|
||||||
|
const_range_iterator_2d old = *this;
|
||||||
|
++*this;
|
||||||
|
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool range::operator!=(const range &comparand) const
|
||||||
|
{
|
||||||
|
return !(*this == comparand);
|
||||||
|
}
|
||||||
|
|
||||||
|
range::const_iterator range::begin() const
|
||||||
|
{
|
||||||
|
return cbegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
range::const_iterator range::end() const
|
||||||
|
{
|
||||||
|
return cend();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace xlnt
|
} // namespace xlnt
|
||||||
|
|
|
@ -82,4 +82,62 @@ bool range_reference::operator!=(const range_reference &comparand) const
|
||||||
{
|
{
|
||||||
return comparand.top_left_ != top_left_ || comparand.bottom_right_ != bottom_right_;
|
return comparand.top_left_ != top_left_ || comparand.bottom_right_ != bottom_right_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cell_reference range_reference::get_top_left() const
|
||||||
|
{
|
||||||
|
return top_left_;
|
||||||
}
|
}
|
||||||
|
cell_reference range_reference::get_bottom_right() const
|
||||||
|
{
|
||||||
|
return bottom_right_;
|
||||||
|
}
|
||||||
|
cell_reference &range_reference::get_top_left()
|
||||||
|
{
|
||||||
|
return top_left_;
|
||||||
|
}
|
||||||
|
cell_reference &range_reference::get_bottom_right()
|
||||||
|
{
|
||||||
|
return bottom_right_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool range_reference::operator==(const std::string &reference_string) const
|
||||||
|
{
|
||||||
|
return *this == range_reference(reference_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool range_reference::operator==(const char *reference_string) const
|
||||||
|
{
|
||||||
|
return *this == std::string(reference_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool range_reference::operator!=(const std::string &reference_string) const
|
||||||
|
{
|
||||||
|
return *this != range_reference(reference_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool range_reference::operator!=(const char *reference_string) const
|
||||||
|
{
|
||||||
|
return *this != std::string(reference_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
XLNT_FUNCTION bool operator==(const std::string &reference_string, const range_reference &ref)
|
||||||
|
{
|
||||||
|
return ref == reference_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
XLNT_FUNCTION bool operator==(const char *reference_string, const range_reference &ref)
|
||||||
|
{
|
||||||
|
return ref == reference_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
XLNT_FUNCTION bool operator!=(const std::string &reference_string, const range_reference &ref)
|
||||||
|
{
|
||||||
|
return ref != reference_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
XLNT_FUNCTION bool operator!=(const char *reference_string, const range_reference &ref)
|
||||||
|
{
|
||||||
|
return ref != reference_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace xlnt
|
||||||
|
|
|
@ -4,6 +4,18 @@
|
||||||
|
|
||||||
#include <xlnt/worksheet/sheet_protection.hpp>
|
#include <xlnt/worksheet/sheet_protection.hpp>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::string int_to_hex(T i)
|
||||||
|
{
|
||||||
|
std::stringstream stream;
|
||||||
|
stream << std::hex << i;
|
||||||
|
return stream.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
void sheet_protection::set_password(const std::string &password)
|
void sheet_protection::set_password(const std::string &password)
|
||||||
|
@ -11,12 +23,9 @@ void sheet_protection::set_password(const std::string &password)
|
||||||
hashed_password_ = hash_password(password);
|
hashed_password_ = hash_password(password);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
std::string sheet_protection::get_hashed_password() const
|
||||||
std::string int_to_hex(T i)
|
|
||||||
{
|
{
|
||||||
std::stringstream stream;
|
return hashed_password_;
|
||||||
stream << std::hex << i;
|
|
||||||
return stream.str();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string sheet_protection::hash_password(const std::string &plaintext_password)
|
std::string sheet_protection::hash_password(const std::string &plaintext_password)
|
||||||
|
|
|
@ -192,8 +192,16 @@ public:
|
||||||
|
|
||||||
ws.garbage_collect();
|
ws.garbage_collect();
|
||||||
|
|
||||||
auto cell_collection = ws.get_cell_collection();
|
std::set<xlnt::cell> cells;
|
||||||
std::set<xlnt::cell> cells(cell_collection.begin(), cell_collection.end());
|
|
||||||
|
for(auto row : ws)
|
||||||
|
{
|
||||||
|
for(auto cell : row)
|
||||||
|
{
|
||||||
|
if(!cell.garbage_collectible()) cells.insert(cell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::set<xlnt::cell> expected = {ws.get_cell("B2"), ws.get_cell("C4"), ws.get_cell("D1")};
|
std::set<xlnt::cell> expected = {ws.get_cell("B2"), ws.get_cell("C4"), ws.get_cell("D1")};
|
||||||
|
|
||||||
// Set difference
|
// Set difference
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
#include <xlnt/cell/cell.hpp>
|
#include <xlnt/cell/cell.hpp>
|
||||||
#include <xlnt/cell/cell_reference.hpp>
|
#include <xlnt/cell/cell_reference.hpp>
|
||||||
#include <xlnt/cell/types.hpp>
|
#include <xlnt/cell/index_types.hpp>
|
||||||
#include <xlnt/packaging/relationship.hpp>
|
#include <xlnt/packaging/relationship.hpp>
|
||||||
#include <xlnt/utils/date.hpp>
|
#include <xlnt/utils/date.hpp>
|
||||||
#include <xlnt/utils/datetime.hpp>
|
#include <xlnt/utils/datetime.hpp>
|
||||||
|
@ -173,19 +173,6 @@ void worksheet::garbage_collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::list<cell> worksheet::get_cell_collection()
|
|
||||||
{
|
|
||||||
std::list<cell> cells;
|
|
||||||
for (auto &c : d_->cell_map_)
|
|
||||||
{
|
|
||||||
for (auto &d : c.second)
|
|
||||||
{
|
|
||||||
cells.push_back(cell(&d.second));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cells;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string worksheet::get_title() const
|
std::string worksheet::get_title() const
|
||||||
{
|
{
|
||||||
if (d_ == nullptr)
|
if (d_ == nullptr)
|
||||||
|
@ -766,4 +753,57 @@ const row_properties &worksheet::get_row_properties(row_t row) const
|
||||||
return d_->row_properties_.at(row);
|
return d_->row_properties_.at(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
worksheet::iterator worksheet::begin()
|
||||||
|
{
|
||||||
|
auto dimensions = calculate_dimension();
|
||||||
|
cell_reference top_right(dimensions.get_bottom_right().get_column_index(), dimensions.get_top_left().get_row());
|
||||||
|
range_reference row_range(dimensions.get_top_left(), top_right);
|
||||||
|
|
||||||
|
return iterator(*this, row_range, major_order::row);
|
||||||
|
}
|
||||||
|
|
||||||
|
worksheet::iterator worksheet::end()
|
||||||
|
{
|
||||||
|
auto dimensions = calculate_dimension();
|
||||||
|
auto past_end_row_index = dimensions.get_bottom_right().get_row() + 1;
|
||||||
|
cell_reference bottom_left(dimensions.get_top_left().get_column_index(), past_end_row_index);
|
||||||
|
cell_reference bottom_right(dimensions.get_bottom_right().get_column_index(), past_end_row_index);
|
||||||
|
|
||||||
|
return iterator(*this, range_reference(bottom_left, bottom_right), major_order::row);
|
||||||
|
}
|
||||||
|
|
||||||
|
worksheet::const_iterator worksheet::cbegin() const
|
||||||
|
{
|
||||||
|
auto dimensions = calculate_dimension();
|
||||||
|
cell_reference top_right(dimensions.get_bottom_right().get_column_index(), dimensions.get_top_left().get_row());
|
||||||
|
range_reference row_range(dimensions.get_top_left(), top_right);
|
||||||
|
|
||||||
|
return const_iterator(*this, row_range, major_order::row);
|
||||||
|
}
|
||||||
|
|
||||||
|
worksheet::const_iterator worksheet::cend() const
|
||||||
|
{
|
||||||
|
auto dimensions = calculate_dimension();
|
||||||
|
auto past_end_row_index = dimensions.get_bottom_right().get_row() + 1;
|
||||||
|
cell_reference bottom_left(dimensions.get_top_left().get_column_index(), past_end_row_index);
|
||||||
|
cell_reference bottom_right(dimensions.get_bottom_right().get_column_index(), past_end_row_index);
|
||||||
|
|
||||||
|
return const_iterator(*this, range_reference(bottom_left, bottom_right), major_order::row);
|
||||||
|
}
|
||||||
|
|
||||||
|
worksheet::const_iterator worksheet::begin() const
|
||||||
|
{
|
||||||
|
return cbegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
worksheet::const_iterator worksheet::end() const
|
||||||
|
{
|
||||||
|
return cend();
|
||||||
|
}
|
||||||
|
|
||||||
|
range worksheet::iter_cells(bool skip_null)
|
||||||
|
{
|
||||||
|
return range(*this, calculate_dimension(), major_order::row, skip_null);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace xlnt
|
} // namespace xlnt
|
||||||
|
|
Loading…
Reference in New Issue
Block a user