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 <unordered_map>
|
||||
|
||||
#include <xlnt/xlnt_config.hpp>
|
||||
#include <xlnt/cell/cell_type.hpp>
|
||||
#include <xlnt/cell/types.hpp>
|
||||
#include <xlnt/xlnt_config.hpp> // for XLNT_CLASS, XLNT_FUNCTION
|
||||
#include <xlnt/cell/cell_type.hpp> // for cell_type
|
||||
#include <xlnt/cell/index_types.hpp> // for column_t, row_t
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include <utility>
|
||||
|
||||
#include <xlnt/xlnt_config.hpp>
|
||||
#include <xlnt/cell/types.hpp>
|
||||
#include <xlnt/cell/index_types.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
|
|
|
@ -29,6 +29,11 @@
|
|||
|
||||
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
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
namespace xlnt {
|
||||
|
||||
/// <summary>
|
||||
/// High-level properties of the document.
|
||||
/// High-level properties of the OOXML document.
|
||||
/// </summary>
|
||||
class XLNT_CLASS document_properties
|
||||
{
|
||||
|
|
|
@ -32,6 +32,10 @@
|
|||
|
||||
namespace xlnt {
|
||||
|
||||
/// <summary>
|
||||
/// The manifest keeps track of all files the OOXML package and
|
||||
/// their type.
|
||||
/// </summary>
|
||||
class XLNT_CLASS manifest
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -29,6 +29,10 @@
|
|||
|
||||
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
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -67,134 +67,41 @@ class XLNT_CLASS relationship
|
|||
custom_xml
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
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 "??";
|
||||
}
|
||||
}
|
||||
static type type_from_string(const std::string &type_string);
|
||||
|
||||
static std::string type_to_string(type t);
|
||||
|
||||
relationship();
|
||||
relationship(const std::string &t, const std::string &r_id = "", const std::string &target_uri = "")
|
||||
: relationship(type_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 = "");
|
||||
|
||||
/// <summary>
|
||||
/// gets a string that identifies the relationship.
|
||||
/// </summary>
|
||||
std::string get_id() const
|
||||
{
|
||||
return id_;
|
||||
}
|
||||
std::string get_id() const;
|
||||
|
||||
/// <summary>
|
||||
/// gets the URI of the package or part that owns the relationship.
|
||||
/// </summary>
|
||||
std::string get_source_uri() const
|
||||
{
|
||||
return source_uri_;
|
||||
}
|
||||
std::string get_source_uri() const;
|
||||
|
||||
/// <summary>
|
||||
/// gets a value that indicates whether the target of the relationship is or External to the Package.
|
||||
/// </summary>
|
||||
target_mode get_target_mode() const
|
||||
{
|
||||
return target_mode_;
|
||||
}
|
||||
target_mode get_target_mode() const;
|
||||
|
||||
/// <summary>
|
||||
/// gets the URI of the target resource of the relationship.
|
||||
/// </summary>
|
||||
std::string get_target_uri() const
|
||||
{
|
||||
return target_uri_;
|
||||
}
|
||||
std::string get_target_uri() 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)
|
||||
{
|
||||
return left.type_ == right.type_ && left.id_ == right.id_ && left.source_uri_ == right.source_uri_ &&
|
||||
left.target_uri_ == right.target_uri_ && left.target_mode_ == right.target_mode_;
|
||||
}
|
||||
type get_type() const;
|
||||
|
||||
std::string get_type_string() const;
|
||||
|
||||
bool operator==(const relationship &rhs) const;
|
||||
|
||||
private:
|
||||
type type_;
|
||||
|
|
|
@ -33,6 +33,9 @@ namespace xlnt {
|
|||
|
||||
class xml_document;
|
||||
|
||||
/// <summary>
|
||||
/// Manages converting comments to and from XML.
|
||||
/// </summary>
|
||||
class XLNT_CLASS comment_serializer
|
||||
{
|
||||
comment_serializer(worksheet sheet);
|
||||
|
|
|
@ -32,6 +32,9 @@ namespace xlnt {
|
|||
class manifest;
|
||||
class xml_document;
|
||||
|
||||
/// <summary>
|
||||
/// Manages converting a manifest to and from XML.
|
||||
/// </summary>
|
||||
class XLNT_CLASS manifest_serializer
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -32,6 +32,9 @@ namespace xlnt {
|
|||
|
||||
class xml_document;
|
||||
|
||||
/// <summary>
|
||||
/// Manages converting a set of shared strings to and from XML.
|
||||
/// </summary>
|
||||
class XLNT_CLASS shared_strings_serializer
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -32,6 +32,9 @@ namespace xlnt {
|
|||
class theme;
|
||||
class xml_document;
|
||||
|
||||
/// <summary>
|
||||
/// Manages converting a theme to and from XML.
|
||||
/// </summary>
|
||||
class XLNT_CLASS theme_serializer
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -39,6 +39,9 @@ class zip_file;
|
|||
class xml_document;
|
||||
class xml_node;
|
||||
|
||||
/// <summary>
|
||||
/// Manages converting workbook to and from XML.
|
||||
/// </summary>
|
||||
class XLNT_CLASS workbook_serializer
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -36,6 +36,9 @@ class workbook;
|
|||
class worksheet;
|
||||
class xml_document;
|
||||
|
||||
/// <summary>
|
||||
/// Manages converting a worksheet to and from XML.
|
||||
/// </summary>
|
||||
class XLNT_CLASS worksheet_serializer
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -34,6 +34,9 @@ namespace detail { struct xml_document_impl; }
|
|||
class xml_node;
|
||||
class xml_serializer;
|
||||
|
||||
/// <summary>
|
||||
/// Abstracts an XML document from a particular implementation.
|
||||
/// </summary>
|
||||
class XLNT_CLASS xml_document
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -33,6 +33,9 @@ namespace detail { struct xml_node_impl; }
|
|||
|
||||
class xml_document;
|
||||
|
||||
/// <summary>
|
||||
/// Abstracts an XML node from a particular implementation.
|
||||
/// </summary>
|
||||
class XLNT_CLASS xml_node
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -31,6 +31,9 @@ namespace xlnt {
|
|||
class xml_document;
|
||||
class xml_node;
|
||||
|
||||
/// <summary>
|
||||
/// Converts XML documents to and from raw strings.
|
||||
/// </summary>
|
||||
class XLNT_CLASS xml_serializer
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
#include <xlnt/xlnt_config.hpp>
|
||||
#include <xlnt/utils/hash_combine.hpp>
|
||||
#include <xlnt/styles/horizontal_alignment.hpp>
|
||||
#include <xlnt/styles/vertical_alignment.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
|
@ -34,82 +36,25 @@ namespace xlnt {
|
|||
class XLNT_CLASS alignment
|
||||
{
|
||||
public:
|
||||
enum class horizontal_alignment
|
||||
{
|
||||
none,
|
||||
general,
|
||||
left,
|
||||
right,
|
||||
center,
|
||||
center_continuous,
|
||||
justify
|
||||
};
|
||||
bool get_wrap_text() const;
|
||||
|
||||
enum class vertical_alignment
|
||||
{
|
||||
none,
|
||||
bottom,
|
||||
top,
|
||||
center,
|
||||
justify
|
||||
};
|
||||
void set_wrap_text(bool wrap_text);
|
||||
|
||||
bool get_wrap_text() const
|
||||
{
|
||||
return wrap_text_;
|
||||
}
|
||||
bool has_horizontal() const;
|
||||
|
||||
void set_wrap_text(bool wrap_text)
|
||||
{
|
||||
wrap_text_ = wrap_text;
|
||||
}
|
||||
horizontal_alignment get_horizontal() const;
|
||||
|
||||
bool has_horizontal() const
|
||||
{
|
||||
return horizontal_ != horizontal_alignment::none;
|
||||
}
|
||||
void set_horizontal(horizontal_alignment horizontal);
|
||||
|
||||
horizontal_alignment get_horizontal() const
|
||||
{
|
||||
return horizontal_;
|
||||
}
|
||||
bool has_vertical() const;
|
||||
|
||||
void set_horizontal(horizontal_alignment horizontal)
|
||||
{
|
||||
horizontal_ = horizontal;
|
||||
}
|
||||
vertical_alignment get_vertical() const;
|
||||
|
||||
bool has_vertical() const
|
||||
{
|
||||
return vertical_ != vertical_alignment::none;
|
||||
}
|
||||
void set_vertical(vertical_alignment vertical);
|
||||
|
||||
vertical_alignment get_vertical() const
|
||||
{
|
||||
return vertical_;
|
||||
}
|
||||
bool operator==(const alignment &other) const;
|
||||
|
||||
void set_vertical(vertical_alignment vertical)
|
||||
{
|
||||
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;
|
||||
}
|
||||
std::size_t hash() const;
|
||||
|
||||
private:
|
||||
horizontal_alignment horizontal_ = horizontal_alignment::none;
|
||||
|
|
|
@ -27,19 +27,15 @@
|
|||
#include <functional>
|
||||
|
||||
#include <xlnt/xlnt_config.hpp>
|
||||
#include <xlnt/styles/diagonal_direction.hpp>
|
||||
#include <xlnt/styles/side.hpp>
|
||||
#include <xlnt/utils/hash_combine.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
enum class XLNT_CLASS diagonal_direction
|
||||
{
|
||||
none,
|
||||
up,
|
||||
down,
|
||||
both
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Describes the border style of a particular cell.
|
||||
/// </summary>
|
||||
class XLNT_CLASS border
|
||||
{
|
||||
public:
|
||||
|
@ -70,36 +66,9 @@ class XLNT_CLASS border
|
|||
|
||||
diagonal_direction diagonal_direction_ = diagonal_direction::none;
|
||||
|
||||
bool operator==(const border &other) const
|
||||
{
|
||||
return hash() == other.hash();
|
||||
}
|
||||
bool operator==(const border &other) 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;
|
||||
}
|
||||
std::size_t hash() const;
|
||||
};
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -30,9 +30,15 @@
|
|||
|
||||
namespace xlnt {
|
||||
|
||||
/// <summary>
|
||||
/// Colors can be applied to many parts of a cell's style.
|
||||
/// </summary>
|
||||
class XLNT_CLASS color
|
||||
{
|
||||
public:
|
||||
public:
|
||||
/// <summary>
|
||||
/// Some colors are references to colors rather than having a particular RGB value.
|
||||
/// </summary>
|
||||
enum class type
|
||||
{
|
||||
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 {
|
||||
|
||||
/// <summary>
|
||||
/// Describes the fill style of a particular cell.
|
||||
/// </summary>
|
||||
class XLNT_CLASS fill
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -33,6 +33,9 @@ namespace xlnt {
|
|||
|
||||
class style;
|
||||
|
||||
/// <summary>
|
||||
/// Describes the font style of a particular cell.
|
||||
/// </summary>
|
||||
class XLNT_CLASS font
|
||||
{
|
||||
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 {
|
||||
|
||||
/// <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
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -31,6 +31,11 @@
|
|||
|
||||
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
|
||||
{
|
||||
public:
|
||||
|
@ -81,33 +86,19 @@ class XLNT_CLASS number_format
|
|||
|
||||
std::string get_format_string() const;
|
||||
|
||||
bool has_id() const
|
||||
{
|
||||
return id_set_;
|
||||
}
|
||||
|
||||
void set_id(std::size_t id)
|
||||
{
|
||||
id_ = id;
|
||||
id_set_ = true;
|
||||
}
|
||||
bool has_id() const;
|
||||
void set_id(std::size_t id);
|
||||
|
||||
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 get_id() const;
|
||||
|
||||
std::size_t hash() const;
|
||||
|
||||
std::string format(const std::string &text) const;
|
||||
std::string format(long double number, calendar base_date) const;
|
||||
|
||||
bool is_date_format() const;
|
||||
|
||||
bool operator==(const number_format &other) const
|
||||
{
|
||||
return hash() == other.hash();
|
||||
}
|
||||
bool operator==(const number_format &other) const;
|
||||
|
||||
private:
|
||||
bool id_set_;
|
||||
|
|
|
@ -30,6 +30,9 @@
|
|||
|
||||
namespace xlnt {
|
||||
|
||||
/// <summary>
|
||||
/// Describes the protection style of a particular cell.
|
||||
/// </summary>
|
||||
class XLNT_CLASS protection
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -48,6 +48,9 @@ enum class XLNT_CLASS border_style
|
|||
thin
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Describes the one of the sides of a border of a particular cell.
|
||||
/// </summary>
|
||||
class XLNT_CLASS side
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -35,6 +35,9 @@ namespace xlnt {
|
|||
|
||||
class workbook;
|
||||
|
||||
/// <summary>
|
||||
/// Describes the entirety of the styling of a particular cell.
|
||||
/// </summary>
|
||||
class XLNT_CLASS style
|
||||
{
|
||||
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 <xlnt/cell/types.hpp>
|
||||
#include <xlnt/xlnt_config.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include <string>
|
||||
|
||||
#include <xlnt/xlnt_config.hpp>
|
||||
#include <xlnt/cell/types.hpp>
|
||||
#include <xlnt/cell/index_types.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
|
|
|
@ -29,6 +29,9 @@
|
|||
|
||||
namespace xlnt {
|
||||
|
||||
/// <summary>
|
||||
/// A datetime is a combination of a date and a time.
|
||||
/// </summary>
|
||||
struct XLNT_CLASS datetime
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
// @author: see AUTHORS file
|
||||
#pragma once
|
||||
|
||||
// An shortcut for including all possible exceptions in xlnt.
|
||||
|
||||
#include <xlnt/utils/attribute_error.hpp>
|
||||
#include <xlnt/utils/cell_coordinates_exception.hpp>
|
||||
#include <xlnt/utils/column_string_index_exception.hpp>
|
||||
|
|
|
@ -35,6 +35,9 @@
|
|||
namespace xlnt {
|
||||
|
||||
// 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>
|
||||
inline void XLNT_FUNCTION hash_combine(std::size_t &seed, const T &v)
|
||||
{
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
namespace xlnt {
|
||||
|
||||
/// <summary>
|
||||
/// Error for trying to open a non-ooxml file.
|
||||
/// Error for trying to open a non-OOXML file.
|
||||
/// </summary>
|
||||
class XLNT_CLASS invalid_file_exception : public std::runtime_error
|
||||
{
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
namespace xlnt {
|
||||
|
||||
/// <summary>
|
||||
/// Error when a references number format is not in the stylesheet.
|
||||
/// Error when a referenced number format is not in the stylesheet.
|
||||
/// </summary>
|
||||
class XLNT_CLASS missing_number_format : public std::runtime_error
|
||||
{
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
namespace xlnt {
|
||||
|
||||
/// <summary>
|
||||
/// Error for badly formatted named ranges.
|
||||
/// Error for incorrectly formatted named ranges.
|
||||
/// </summary>
|
||||
class XLNT_CLASS named_range_exception : public std::runtime_error
|
||||
{
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
namespace xlnt {
|
||||
|
||||
/// <summary>
|
||||
/// Security information about the document.
|
||||
/// Security information about the OOXML document.
|
||||
/// </summary>
|
||||
class XLNT_CLASS document_security
|
||||
{
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
|
||||
namespace xlnt {
|
||||
|
||||
/// <summary>
|
||||
/// A reference to an external workbook for use in formulae.
|
||||
/// </summary>
|
||||
class XLNT_CLASS external_book
|
||||
{
|
||||
};
|
||||
|
|
|
@ -33,8 +33,13 @@ namespace xlnt {
|
|||
class range_reference;
|
||||
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);
|
||||
|
||||
/// <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
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -26,6 +26,10 @@
|
|||
|
||||
namespace xlnt {
|
||||
|
||||
/// <summary>
|
||||
/// A theme is a combination of fonts, colors, and effects.
|
||||
/// This isn't really supported yet.
|
||||
/// </summary>
|
||||
class XLNT_CLASS theme
|
||||
{
|
||||
};
|
||||
|
|
|
@ -35,78 +35,33 @@ namespace xlnt {
|
|||
class cell;
|
||||
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
|
||||
{
|
||||
public:
|
||||
template <bool is_const = true>
|
||||
class XLNT_CLASS common_iterator : public std::iterator<std::bidirectional_iterator_tag, cell>
|
||||
class XLNT_CLASS iterator : public std::iterator<std::bidirectional_iterator_tag, cell>
|
||||
{
|
||||
public:
|
||||
common_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)
|
||||
{
|
||||
}
|
||||
iterator(worksheet ws, const cell_reference &start_cell, major_order order = major_order::row);
|
||||
|
||||
common_iterator(const common_iterator<false> &other)
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
iterator(const iterator &other);
|
||||
|
||||
cell operator*();
|
||||
|
||||
bool operator==(const common_iterator &other) const
|
||||
{
|
||||
return ws_ == other.ws_ && current_cell_ == other.current_cell_ && order_ == other.order_;
|
||||
}
|
||||
bool operator==(const iterator &other) const;
|
||||
|
||||
bool operator!=(const common_iterator &other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
bool operator!=(const iterator &other) const;
|
||||
|
||||
common_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);
|
||||
}
|
||||
iterator &operator--();
|
||||
|
||||
iterator operator--(int);
|
||||
|
||||
return *this;
|
||||
}
|
||||
iterator &operator++();
|
||||
|
||||
common_iterator operator--(int)
|
||||
{
|
||||
iterator old = *this;
|
||||
--*this;
|
||||
return old;
|
||||
}
|
||||
|
||||
common_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;
|
||||
}
|
||||
|
||||
common_iterator operator++(int)
|
||||
{
|
||||
iterator old = *this;
|
||||
++*this;
|
||||
return old;
|
||||
}
|
||||
|
||||
friend class common_iterator<true>;
|
||||
iterator operator++(int);
|
||||
|
||||
private:
|
||||
worksheet ws_;
|
||||
|
@ -114,9 +69,34 @@ class XLNT_CLASS cell_vector
|
|||
range_reference range_;
|
||||
major_order order_;
|
||||
};
|
||||
|
||||
class XLNT_CLASS const_iterator : public std::iterator<std::bidirectional_iterator_tag, const cell>
|
||||
{
|
||||
public:
|
||||
const_iterator(worksheet ws, const cell_reference &start_cell, major_order order = major_order::row);
|
||||
|
||||
using iterator = common_iterator<false>;
|
||||
using const_iterator = common_iterator<true>;
|
||||
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);
|
||||
|
||||
|
|
|
@ -27,6 +27,10 @@
|
|||
|
||||
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
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -14,30 +14,16 @@ class XLNT_CLASS footer
|
|||
{
|
||||
public:
|
||||
footer();
|
||||
void set_text(const std::string &text)
|
||||
{
|
||||
default_ = false;
|
||||
text_ = text;
|
||||
}
|
||||
void set_font_name(const std::string &font_name)
|
||||
{
|
||||
default_ = false;
|
||||
font_name_ = font_name;
|
||||
}
|
||||
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_;
|
||||
}
|
||||
|
||||
void set_text(const std::string &text);
|
||||
|
||||
void set_font_name(const std::string &font_name);
|
||||
|
||||
void set_font_size(std::size_t font_size);
|
||||
|
||||
void set_font_color(const std::string &font_color);
|
||||
|
||||
bool is_default() const;
|
||||
|
||||
private:
|
||||
bool default_;
|
||||
|
|
|
@ -14,30 +14,16 @@ class XLNT_CLASS header
|
|||
{
|
||||
public:
|
||||
header();
|
||||
void set_text(const std::string &text)
|
||||
{
|
||||
default_ = false;
|
||||
text_ = text;
|
||||
}
|
||||
void set_font_name(const std::string &font_name)
|
||||
{
|
||||
default_ = false;
|
||||
font_name_ = font_name;
|
||||
}
|
||||
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_;
|
||||
}
|
||||
|
||||
void set_text(const std::string &text);
|
||||
|
||||
void set_font_name(const std::string &font_name);
|
||||
|
||||
void set_font_size(std::size_t font_size);
|
||||
|
||||
void set_font_color(const std::string &font_color);
|
||||
|
||||
bool is_default() const;
|
||||
|
||||
private:
|
||||
bool default_;
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
namespace xlnt {
|
||||
|
||||
/// <summary>
|
||||
/// Worksheet header and footer
|
||||
/// Worksheet header and footer for all six possible positions.
|
||||
/// </summary>
|
||||
class XLNT_CLASS header_footer
|
||||
{
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
|
||||
namespace xlnt {
|
||||
|
||||
/// <summary>
|
||||
/// Defines whether iterating a range returns columns or rows sequentially.
|
||||
/// </summary>
|
||||
enum class XLNT_CLASS major_order
|
||||
{
|
||||
column,
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
|
||||
namespace xlnt {
|
||||
|
||||
/// <summary>
|
||||
/// The orientation of the worksheet when it is printed.
|
||||
/// </summary>
|
||||
enum class XLNT_CLASS orientation
|
||||
{
|
||||
portrait,
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
|
||||
namespace xlnt {
|
||||
|
||||
/// <summary>
|
||||
/// The types of page breaks.
|
||||
/// </summary>
|
||||
enum class XLNT_CLASS page_break
|
||||
{
|
||||
none = 0,
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
|
||||
namespace xlnt {
|
||||
|
||||
/// <summary>
|
||||
/// Describes the margins around a worksheet for printing.
|
||||
/// </summary>
|
||||
class XLNT_CLASS page_margins
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -31,6 +31,9 @@
|
|||
|
||||
namespace xlnt {
|
||||
|
||||
/// <summary>
|
||||
/// Describes how a worksheet will be converted into a page during printing.
|
||||
/// </summary>
|
||||
struct XLNT_CLASS page_setup
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
|
||||
namespace xlnt {
|
||||
|
||||
/// <summary>
|
||||
/// A fixed portion of a worksheet.
|
||||
/// </summary>
|
||||
class XLNT_CLASS pane
|
||||
{
|
||||
};
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
|
||||
namespace xlnt {
|
||||
|
||||
/// <summary>
|
||||
/// The possible paper sizes for printing.
|
||||
/// </summary>
|
||||
enum class XLNT_CLASS paper_size
|
||||
{
|
||||
letter = 1,
|
||||
|
|
|
@ -30,95 +30,22 @@
|
|||
#include <xlnt/xlnt_config.hpp>
|
||||
#include <xlnt/worksheet/cell_vector.hpp>
|
||||
#include <xlnt/worksheet/major_order.hpp>
|
||||
#include <xlnt/worksheet/range_iterator_2d.hpp>
|
||||
#include <xlnt/worksheet/range_reference.hpp>
|
||||
#include <xlnt/worksheet/worksheet.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
/// <summary>
|
||||
/// A range is a 2D collection of cells with defined extens that can be iterated upon.
|
||||
/// </summary>
|
||||
class XLNT_CLASS range
|
||||
{
|
||||
public:
|
||||
template <bool is_const = true>
|
||||
class XLNT_CLASS common_iterator : public std::iterator<std::bidirectional_iterator_tag, cell>
|
||||
{
|
||||
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)
|
||||
{
|
||||
*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);
|
||||
using iterator = range_iterator_2d;
|
||||
using const_iterator = const_range_iterator_2d;
|
||||
|
||||
range(worksheet ws, const range_reference &reference, major_order order = major_order::row, bool skip_null = false);
|
||||
|
||||
~range();
|
||||
|
||||
|
@ -128,10 +55,7 @@ class XLNT_CLASS range
|
|||
|
||||
bool operator==(const range &comparand) const;
|
||||
|
||||
bool operator!=(const range &comparand) const
|
||||
{
|
||||
return !(*this == comparand);
|
||||
}
|
||||
bool operator!=(const range &comparand) const;
|
||||
|
||||
cell_vector get_vector(std::size_t vector_index);
|
||||
|
||||
|
@ -150,14 +74,8 @@ class XLNT_CLASS range
|
|||
iterator begin();
|
||||
iterator end();
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
return cbegin();
|
||||
}
|
||||
const_iterator end() const
|
||||
{
|
||||
return cend();
|
||||
}
|
||||
const_iterator begin() const;
|
||||
const_iterator end() const;
|
||||
|
||||
const_iterator cbegin() const;
|
||||
const_iterator cend() const;
|
||||
|
@ -166,6 +84,7 @@ class XLNT_CLASS range
|
|||
worksheet ws_;
|
||||
range_reference ref_;
|
||||
major_order order_;
|
||||
bool skip_null_;
|
||||
};
|
||||
|
||||
} // 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 {
|
||||
|
||||
/// <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
|
||||
{
|
||||
public:
|
||||
|
@ -48,69 +52,43 @@ class XLNT_CLASS range_reference
|
|||
|
||||
std::size_t get_height() const;
|
||||
|
||||
cell_reference get_top_left() const
|
||||
{
|
||||
return top_left_;
|
||||
}
|
||||
cell_reference get_bottom_right() const
|
||||
{
|
||||
return bottom_right_;
|
||||
}
|
||||
cell_reference &get_top_left()
|
||||
{
|
||||
return top_left_;
|
||||
}
|
||||
cell_reference &get_bottom_right()
|
||||
{
|
||||
return bottom_right_;
|
||||
}
|
||||
cell_reference get_top_left() const;
|
||||
|
||||
cell_reference get_bottom_right() const;
|
||||
|
||||
cell_reference &get_top_left();
|
||||
|
||||
cell_reference &get_bottom_right();
|
||||
|
||||
range_reference make_offset(int column_offset, int row_offset) const;
|
||||
|
||||
std::string to_string() const;
|
||||
|
||||
bool operator==(const range_reference &comparand) const;
|
||||
bool operator==(const std::string &reference_string) const
|
||||
{
|
||||
return *this == range_reference(reference_string);
|
||||
}
|
||||
bool operator==(const char *reference_string) const
|
||||
{
|
||||
return *this == std::string(reference_string);
|
||||
}
|
||||
|
||||
bool operator==(const std::string &reference_string) const;
|
||||
|
||||
bool operator==(const char *reference_string) const;
|
||||
|
||||
bool operator!=(const range_reference &comparand) const;
|
||||
bool operator!=(const std::string &reference_string) const
|
||||
{
|
||||
return *this != range_reference(reference_string);
|
||||
}
|
||||
bool operator!=(const char *reference_string) const
|
||||
{
|
||||
return *this != std::string(reference_string);
|
||||
}
|
||||
|
||||
bool operator!=(const std::string &reference_string) const;
|
||||
|
||||
bool operator!=(const char *reference_string) const;
|
||||
|
||||
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);
|
||||
|
||||
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:
|
||||
cell_reference top_left_;
|
||||
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
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
|
||||
namespace xlnt {
|
||||
|
||||
/// <summary>
|
||||
/// The properties of a row in a worksheet.
|
||||
/// </summary>
|
||||
class XLNT_CLASS row_properties
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
|
||||
namespace xlnt {
|
||||
|
||||
/// <summary>
|
||||
/// The selected area of a worksheet.
|
||||
/// </summary>
|
||||
class XLNT_CLASS selection
|
||||
{
|
||||
};
|
||||
|
|
|
@ -29,16 +29,16 @@
|
|||
|
||||
namespace xlnt {
|
||||
|
||||
/// <summary>
|
||||
/// Protection applied to a particular worksheet to prevent it from being modified.
|
||||
/// </summary>
|
||||
class XLNT_CLASS sheet_protection
|
||||
{
|
||||
public:
|
||||
static std::string hash_password(const std::string &password);
|
||||
|
||||
void set_password(const std::string &password);
|
||||
std::string get_hashed_password() const
|
||||
{
|
||||
return hashed_password_;
|
||||
}
|
||||
std::string get_hashed_password() const;
|
||||
|
||||
private:
|
||||
std::string hashed_password_;
|
||||
|
|
|
@ -27,6 +27,10 @@
|
|||
|
||||
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
|
||||
{
|
||||
visible,
|
||||
|
|
|
@ -27,6 +27,10 @@
|
|||
|
||||
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
|
||||
{
|
||||
};
|
||||
|
|
|
@ -23,23 +23,24 @@
|
|||
// @author: see AUTHORS file
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <xlnt/xlnt_config.hpp>
|
||||
#include <xlnt/cell/types.hpp>
|
||||
#include <xlnt/cell/index_types.hpp>
|
||||
#include <xlnt/packaging/relationship.hpp>
|
||||
#include <xlnt/worksheet/header_footer.hpp>
|
||||
#include <xlnt/worksheet/page_margins.hpp>
|
||||
#include <xlnt/worksheet/page_setup.hpp>
|
||||
#include <xlnt/worksheet/range_iterator_2d.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
class cell;
|
||||
class cell_reference;
|
||||
class cell_vector;
|
||||
class column_properties;
|
||||
class comment;
|
||||
class range;
|
||||
|
@ -53,11 +54,15 @@ struct date;
|
|||
namespace detail { struct worksheet_impl; }
|
||||
|
||||
/// <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>
|
||||
class XLNT_CLASS worksheet
|
||||
{
|
||||
public:
|
||||
public:
|
||||
using iterator = range_iterator_2d;
|
||||
using const_iterator = const_range_iterator_2d;
|
||||
|
||||
worksheet();
|
||||
worksheet(const worksheet &rhs);
|
||||
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(const std::string &range_string, int row_offset, int column_offset) const;
|
||||
range columns() const;
|
||||
std::list<cell> get_cell_collection();
|
||||
|
||||
// properties
|
||||
column_properties &get_column_properties(column_t column);
|
||||
|
@ -198,9 +202,23 @@ class XLNT_CLASS worksheet
|
|||
|
||||
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:
|
||||
friend class workbook;
|
||||
friend class cell;
|
||||
friend class range_iterator_2d;
|
||||
friend class const_range_iterator_2d;
|
||||
|
||||
worksheet(detail::worksheet_impl *d);
|
||||
detail::worksheet_impl *d_;
|
||||
};
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
|
||||
namespace xlnt {
|
||||
|
||||
/// <summary>
|
||||
/// ?
|
||||
/// </summary>
|
||||
class XLNT_CLASS worksheet_properties
|
||||
{
|
||||
};
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include <xlnt/cell/cell.hpp>
|
||||
#include <xlnt/cell/cell_reference.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/manifest.hpp>
|
||||
#include <xlnt/packaging/relationship.hpp>
|
||||
|
|
|
@ -21,767 +21,6 @@
|
|||
#include <detail/cell_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 {
|
||||
|
||||
const std::unordered_map<std::string, int> &cell::error_codes()
|
||||
|
@ -1012,25 +251,7 @@ bool cell::is_merged() const
|
|||
|
||||
bool cell::is_date() const
|
||||
{
|
||||
if (get_data_type() == type::numeric)
|
||||
{
|
||||
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;
|
||||
return get_data_type() == type::numeric && get_number_format().is_date_format();
|
||||
}
|
||||
|
||||
cell_reference cell::get_reference() const
|
||||
|
@ -1448,11 +669,11 @@ std::string cell::to_string() const
|
|||
case cell::type::null:
|
||||
return "";
|
||||
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::formula:
|
||||
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:
|
||||
return get_value<long double>() == 0 ? "FALSE" : "TRUE";
|
||||
default:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include <locale>
|
||||
|
||||
#include <xlnt/cell/types.hpp>
|
||||
#include <xlnt/cell/index_types.hpp>
|
||||
#include <xlnt/utils/exceptions.hpp>
|
||||
|
||||
#include <detail/constants.hpp>
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include <xlnt/cell/cell.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/time.hpp>
|
||||
#include <xlnt/packaging/relationship.hpp>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <xlnt/cell/types.hpp>
|
||||
#include <xlnt/cell/index_types.hpp>
|
||||
|
||||
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
|
||||
|
|
|
@ -160,19 +160,19 @@ alignment style_serializer::read_alignment(const xml_node &alignment_node)
|
|||
|
||||
if (vertical == "bottom")
|
||||
{
|
||||
align.set_vertical(alignment::vertical_alignment::bottom);
|
||||
align.set_vertical(vertical_alignment::bottom);
|
||||
}
|
||||
else if (vertical == "center")
|
||||
{
|
||||
align.set_vertical(alignment::vertical_alignment::center);
|
||||
align.set_vertical(vertical_alignment::center);
|
||||
}
|
||||
else if (vertical == "justify")
|
||||
{
|
||||
align.set_vertical(alignment::vertical_alignment::justify);
|
||||
align.set_vertical(vertical_alignment::justify);
|
||||
}
|
||||
else if (vertical == "top")
|
||||
{
|
||||
align.set_vertical(alignment::vertical_alignment::top);
|
||||
align.set_vertical(vertical_alignment::top);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -188,27 +188,27 @@ alignment style_serializer::read_alignment(const xml_node &alignment_node)
|
|||
|
||||
if (horizontal == "left")
|
||||
{
|
||||
align.set_horizontal(alignment::horizontal_alignment::left);
|
||||
align.set_horizontal(horizontal_alignment::left);
|
||||
}
|
||||
else if (horizontal == "center")
|
||||
{
|
||||
align.set_horizontal(alignment::horizontal_alignment::center);
|
||||
align.set_horizontal(horizontal_alignment::center);
|
||||
}
|
||||
else if (horizontal == "center-continuous")
|
||||
{
|
||||
align.set_horizontal(alignment::horizontal_alignment::center_continuous);
|
||||
align.set_horizontal(horizontal_alignment::center_continuous);
|
||||
}
|
||||
else if (horizontal == "right")
|
||||
{
|
||||
align.set_horizontal(alignment::horizontal_alignment::right);
|
||||
align.set_horizontal(horizontal_alignment::right);
|
||||
}
|
||||
else if (horizontal == "justify")
|
||||
{
|
||||
align.set_horizontal(alignment::horizontal_alignment::justify);
|
||||
align.set_horizontal(horizontal_alignment::justify);
|
||||
}
|
||||
else if (horizontal == "general")
|
||||
{
|
||||
align.set_horizontal(alignment::horizontal_alignment::general);
|
||||
align.set_horizontal(horizontal_alignment::general);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -885,16 +885,16 @@ xml_document style_serializer::write_stylesheet() const
|
|||
{
|
||||
switch (style.alignment_.get_vertical())
|
||||
{
|
||||
case alignment::vertical_alignment::bottom:
|
||||
case vertical_alignment::bottom:
|
||||
alignment_node.add_attribute("vertical", "bottom");
|
||||
break;
|
||||
case alignment::vertical_alignment::center:
|
||||
case vertical_alignment::center:
|
||||
alignment_node.add_attribute("vertical", "center");
|
||||
break;
|
||||
case alignment::vertical_alignment::justify:
|
||||
case vertical_alignment::justify:
|
||||
alignment_node.add_attribute("vertical", "justify");
|
||||
break;
|
||||
case alignment::vertical_alignment::top:
|
||||
case vertical_alignment::top:
|
||||
alignment_node.add_attribute("vertical", "top");
|
||||
break;
|
||||
default:
|
||||
|
@ -906,22 +906,22 @@ xml_document style_serializer::write_stylesheet() const
|
|||
{
|
||||
switch (style.alignment_.get_horizontal())
|
||||
{
|
||||
case alignment::horizontal_alignment::center:
|
||||
case horizontal_alignment::center:
|
||||
alignment_node.add_attribute("horizontal", "center");
|
||||
break;
|
||||
case alignment::horizontal_alignment::center_continuous:
|
||||
case horizontal_alignment::center_continuous:
|
||||
alignment_node.add_attribute("horizontal", "center_continuous");
|
||||
break;
|
||||
case alignment::horizontal_alignment::general:
|
||||
case horizontal_alignment::general:
|
||||
alignment_node.add_attribute("horizontal", "general");
|
||||
break;
|
||||
case alignment::horizontal_alignment::justify:
|
||||
case horizontal_alignment::justify:
|
||||
alignment_node.add_attribute("horizontal", "justify");
|
||||
break;
|
||||
case alignment::horizontal_alignment::left:
|
||||
case horizontal_alignment::left:
|
||||
alignment_node.add_attribute("horizontal", "left");
|
||||
break;
|
||||
case alignment::horizontal_alignment::right:
|
||||
case horizontal_alignment::right:
|
||||
alignment_node.add_attribute("horizontal", "right");
|
||||
break;
|
||||
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 <regex>
|
||||
|
||||
#include <xlnt/utils/datetime.hpp>
|
||||
#include <xlnt/utils/hash_combine.hpp>
|
||||
#include <xlnt/styles/number_format.hpp>
|
||||
|
||||
|
@ -65,6 +66,764 @@ const std::unordered_map<std::size_t, std::string> &builtin_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 xlnt {
|
||||
|
@ -340,4 +1099,58 @@ void number_format::set_format_string(const std::string &format_string, std::siz
|
|||
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
|
||||
|
|
|
@ -3,7 +3,130 @@
|
|||
|
||||
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*()
|
||||
{
|
||||
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 {
|
||||
|
||||
range::range(worksheet ws, const range_reference &reference, major_order order)
|
||||
: ws_(ws), ref_(reference), order_(order)
|
||||
range::range(worksheet ws, const range_reference &reference, major_order order, bool skip_null)
|
||||
: 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_);
|
||||
}
|
||||
|
||||
template <>
|
||||
cell_vector range::iterator::operator*()
|
||||
{
|
||||
if (order_ == major_order::row)
|
||||
|
@ -148,4 +147,147 @@ cell_vector range::iterator::operator*()
|
|||
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
|
||||
|
|
|
@ -82,4 +82,62 @@ bool range_reference::operator!=(const range_reference &comparand) const
|
|||
{
|
||||
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>
|
||||
|
||||
namespace {
|
||||
|
||||
template <typename T>
|
||||
std::string int_to_hex(T i)
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream << std::hex << i;
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::string int_to_hex(T i)
|
||||
std::string sheet_protection::get_hashed_password() const
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream << std::hex << i;
|
||||
return stream.str();
|
||||
return hashed_password_;
|
||||
}
|
||||
|
||||
std::string sheet_protection::hash_password(const std::string &plaintext_password)
|
||||
|
|
|
@ -192,8 +192,16 @@ public:
|
|||
|
||||
ws.garbage_collect();
|
||||
|
||||
auto cell_collection = ws.get_cell_collection();
|
||||
std::set<xlnt::cell> cells(cell_collection.begin(), cell_collection.end());
|
||||
std::set<xlnt::cell> cells;
|
||||
|
||||
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")};
|
||||
|
||||
// Set difference
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include <xlnt/cell/cell.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/utils/date.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
|
||||
{
|
||||
if (d_ == nullptr)
|
||||
|
@ -766,4 +753,57 @@ const row_properties &worksheet::get_row_properties(row_t row) const
|
|||
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
|
||||
|
|
Loading…
Reference in New Issue
Block a user