2014-05-22 05:48:51 +08:00
|
|
|
#include <algorithm>
|
2015-11-03 03:22:13 +08:00
|
|
|
#include <cctype>
|
2014-05-21 22:20:30 +08:00
|
|
|
#include <sstream>
|
|
|
|
|
2014-08-14 06:56:34 +08:00
|
|
|
#include <xlnt/cell/cell.hpp>
|
|
|
|
#include <xlnt/cell/cell_reference.hpp>
|
|
|
|
#include <xlnt/cell/comment.hpp>
|
|
|
|
#include <xlnt/common/datetime.hpp>
|
|
|
|
#include <xlnt/common/exceptions.hpp>
|
2015-10-19 03:30:46 +08:00
|
|
|
#include <xlnt/common/relationship.hpp>
|
2014-08-14 06:56:34 +08:00
|
|
|
#include <xlnt/workbook/workbook.hpp>
|
|
|
|
#include <xlnt/workbook/document_properties.hpp>
|
2015-11-01 22:43:01 +08:00
|
|
|
#include <xlnt/worksheet/column_properties.hpp>
|
|
|
|
#include <xlnt/worksheet/row_properties.hpp>
|
2015-10-19 03:30:46 +08:00
|
|
|
#include <xlnt/worksheet/worksheet.hpp>
|
|
|
|
#include <xlnt/styles/color.hpp>
|
2014-08-14 06:56:34 +08:00
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
#include <detail/cell_impl.hpp>
|
|
|
|
#include <detail/comment_impl.hpp>
|
2014-05-21 22:20:30 +08:00
|
|
|
|
2015-10-17 06:35:11 +08:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
enum class condition_type
|
|
|
|
{
|
|
|
|
less_than,
|
|
|
|
less_or_equal,
|
|
|
|
equal,
|
|
|
|
greater_than,
|
|
|
|
greater_or_equal,
|
|
|
|
invalid
|
|
|
|
};
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-17 06:35:11 +08:00
|
|
|
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;
|
2015-10-26 12:26:48 +08:00
|
|
|
bool has_locale = false;
|
|
|
|
std::string locale;
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-17 06:35:11 +08:00
|
|
|
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;
|
2015-10-26 12:26:48 +08:00
|
|
|
has_locale = other.has_locale;
|
|
|
|
locale = other.locale;
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-17 06:35:11 +08:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
};
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-17 06:35:11 +08:00
|
|
|
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);
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
while (separator_index != std::string::npos)
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
|
|
|
auto part = string.substr(previous_index, separator_index - previous_index);
|
|
|
|
split.push_back(part);
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-17 06:35:11 +08:00
|
|
|
previous_index = separator_index + 1;
|
|
|
|
separator_index = string.find(delim, previous_index);
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-17 06:35:11 +08:00
|
|
|
split.push_back(string.substr(previous_index));
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-17 06:35:11 +08:00
|
|
|
return split;
|
|
|
|
}
|
|
|
|
|
2015-10-19 03:30:46 +08:00
|
|
|
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);
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
while (separator_index != std::string::npos)
|
2015-10-19 03:30:46 +08:00
|
|
|
{
|
|
|
|
auto part = string.substr(previous_index, separator_index - previous_index);
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
if (!part.empty())
|
2015-10-19 03:30:46 +08:00
|
|
|
{
|
|
|
|
split.push_back(part);
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-19 03:30:46 +08:00
|
|
|
previous_index = separator_index + 1;
|
|
|
|
separator_index = string.find_first_of(delims, previous_index);
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-19 03:30:46 +08:00
|
|
|
split.push_back(string.substr(previous_index));
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-19 03:30:46 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2015-10-17 06:35:11 +08:00
|
|
|
bool is_valid_color(const std::string &color)
|
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
static const std::vector<std::string> colors = { "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++)
|
2015-10-26 12:26:48 +08:00
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
if (std::toupper(color[i]) != std::toupper(other[i]))
|
2015-10-26 12:26:48 +08:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-26 12:26:48 +08:00
|
|
|
return true;
|
|
|
|
};
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-26 12:26:48 +08:00
|
|
|
return std::find_if(colors.begin(), colors.end(), compare_color) != colors.end();
|
2015-10-17 06:35:11 +08:00
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-17 06:35:11 +08:00
|
|
|
bool parse_condition(const std::string &string, section &s)
|
|
|
|
{
|
|
|
|
s.has_condition = false;
|
|
|
|
s.condition = condition_type::invalid;
|
|
|
|
s.condition_value.clear();
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
if (string[0] == '<')
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
|
|
|
s.has_condition = true;
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
if (string[1] == '=')
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
if (string[0] == '>')
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
|
|
|
s.has_condition = true;
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
if (string[1] == '=')
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
else if (string[0] == '=')
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
|
|
|
s.has_condition = true;
|
|
|
|
s.condition = condition_type::equal;
|
|
|
|
s.condition_value = string.substr(1);
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-17 06:35:11 +08:00
|
|
|
return s.has_condition;
|
|
|
|
}
|
|
|
|
|
2015-10-26 12:26:48 +08:00
|
|
|
bool is_hex(char c)
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
if (c >= 'A' || c <= 'F') return true;
|
|
|
|
if (c >= '0' || c <= '9') return true;
|
2015-10-26 12:26:48 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
const std::unordered_map<int, std::string> known_locales = { { 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" } };
|
2015-10-26 12:26:48 +08:00
|
|
|
|
|
|
|
bool is_valid_locale(const std::string &locale_string)
|
|
|
|
{
|
|
|
|
std::string country = locale_string.substr(locale_string.find('-') + 1);
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
if (country.empty())
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
2015-10-26 12:26:48 +08:00
|
|
|
return false;
|
2015-10-17 06:35:11 +08:00
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
for (auto c : country)
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
if (!is_hex(std::toupper(c)))
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
2015-10-26 12:26:48 +08:00
|
|
|
return false;
|
2015-10-17 06:35:11 +08:00
|
|
|
}
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-26 12:26:48 +08:00
|
|
|
auto index = std::stoi(country, 0, 16);
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
if (known_locales.find(index) == known_locales.end())
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
2015-10-26 12:26:48 +08:00
|
|
|
return false;
|
2015-10-17 06:35:11 +08:00
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-26 12:26:48 +08:00
|
|
|
std::string beginning = locale_string.substr(0, locale_string.find('-'));
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
if (beginning.empty() || beginning[0] != '$')
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
2015-10-26 12:26:48 +08:00
|
|
|
return false;
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
if (beginning.size() == 1)
|
2015-10-26 12:26:48 +08:00
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-26 12:26:48 +08:00
|
|
|
beginning = beginning.substr(1);
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-26 12:26:48 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
section parse_section(const std::string §ion_string)
|
|
|
|
{
|
|
|
|
section s;
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-26 12:26:48 +08:00
|
|
|
std::string format_part;
|
|
|
|
std::string bracket_part;
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-26 12:26:48 +08:00
|
|
|
std::vector<std::string> bracket_parts;
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-26 12:26:48 +08:00
|
|
|
bool in_quotes = false;
|
|
|
|
bool in_brackets = false;
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-26 12:26:48 +08:00
|
|
|
static const std::vector<std::string> bracket_times = { "h", "hh", "m", "mm", "s", "ss" };
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
for (std::size_t i = 0; i < section_string.size(); i++)
|
2015-10-26 12:26:48 +08:00
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
if (!in_quotes && section_string[i] == '"')
|
2015-10-26 12:26:48 +08:00
|
|
|
{
|
|
|
|
format_part.push_back(section_string[i]);
|
|
|
|
in_quotes = true;
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
else if (in_quotes && section_string[i] == '"')
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
2015-10-26 12:26:48 +08:00
|
|
|
format_part.push_back(section_string[i]);
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
if (i < section_string.size() - 1 && section_string[i + 1] != '"')
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
2015-10-26 12:26:48 +08:00
|
|
|
in_quotes = false;
|
2015-10-17 06:35:11 +08:00
|
|
|
}
|
2015-10-26 12:26:48 +08:00
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
else if (!in_brackets && section_string[i] == '[')
|
2015-10-26 12:26:48 +08:00
|
|
|
{
|
|
|
|
in_brackets = true;
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
for (auto bracket_time : bracket_times)
|
2015-10-26 12:26:48 +08:00
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
if (i < section_string.size() - bracket_time.size() &&
|
|
|
|
section_string.substr(i + 1, bracket_time.size()) == bracket_time)
|
2015-10-26 12:26:48 +08:00
|
|
|
{
|
|
|
|
in_brackets = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2015-10-17 06:35:11 +08:00
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
else if (in_brackets)
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
if (section_string[i] == ']')
|
2015-10-26 12:26:48 +08:00
|
|
|
{
|
|
|
|
in_brackets = false;
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
if (is_valid_color(bracket_part))
|
2015-10-26 12:26:48 +08:00
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
if (s.color.empty())
|
2015-10-26 12:26:48 +08:00
|
|
|
{
|
|
|
|
s.color = bracket_part;
|
|
|
|
s.has_color = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw std::runtime_error("two colors");
|
|
|
|
}
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
else if (is_valid_locale(bracket_part))
|
2015-10-26 12:26:48 +08:00
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
if (s.locale.empty())
|
2015-10-26 12:26:48 +08:00
|
|
|
{
|
|
|
|
s.locale = bracket_part;
|
|
|
|
s.has_locale = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw std::runtime_error("two locales");
|
|
|
|
}
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
else if (s.has_condition || !parse_condition(bracket_part, s))
|
2015-10-26 12:26:48 +08:00
|
|
|
{
|
|
|
|
throw std::runtime_error("invalid bracket format");
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-26 12:26:48 +08:00
|
|
|
bracket_part.clear();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bracket_part.push_back(section_string[i]);
|
|
|
|
}
|
2015-10-17 06:35:11 +08:00
|
|
|
}
|
2015-10-26 12:26:48 +08:00
|
|
|
else
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
2015-10-26 12:26:48 +08:00
|
|
|
format_part.push_back(section_string[i]);
|
2015-10-17 06:35:11 +08:00
|
|
|
}
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-26 12:26:48 +08:00
|
|
|
s.value = format_part;
|
2015-10-17 06:35:11 +08:00
|
|
|
s.has_value = true;
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-17 06:35:11 +08:00
|
|
|
return s;
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-17 06:35:11 +08:00
|
|
|
format_sections parse_format_sections(const std::string &combined)
|
|
|
|
{
|
|
|
|
format_sections result = {};
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-17 06:35:11 +08:00
|
|
|
auto split = split_string(combined, ';');
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
if (split.empty())
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
|
|
|
throw std::runtime_error("empty string");
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-17 06:35:11 +08:00
|
|
|
result.first = parse_section(split[0]);
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
if (!result.first.has_condition)
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
|
|
|
result.second = result.first;
|
|
|
|
result.third = result.first;
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
if (split.size() > 1)
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
|
|
|
result.second = parse_section(split[1]);
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
if (split.size() > 2)
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
if (result.first.has_condition && !result.second.has_condition)
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
|
|
|
throw std::runtime_error("first two sections should have conditions");
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-17 06:35:11 +08:00
|
|
|
result.third = parse_section(split[2]);
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
if (result.third.has_condition)
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
|
|
|
throw std::runtime_error("third section shouldn't have a condition");
|
|
|
|
}
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
if (split.size() > 3)
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
if (result.first.has_condition)
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
|
|
|
throw std::runtime_error("too many parts");
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-17 06:35:11 +08:00
|
|
|
result.fourth = parse_section(split[3]);
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
if (split.size() > 4)
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
|
|
|
throw std::runtime_error("too many parts");
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-17 06:35:11 +08:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
const std::vector<std::string> MonthNames = { "January", "February", "March", "April", "May", "June",
|
|
|
|
"July", "August", "September", "October", "November", "December" };
|
2015-10-19 03:30:46 +08:00
|
|
|
|
|
|
|
std::string format_section(long double number, const section &format, xlnt::calendar base_date)
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
2015-10-19 03:30:46 +08:00
|
|
|
const std::string unquoted = "$+(:^'{<=-/)!&~}> ";
|
2015-10-26 12:26:48 +08:00
|
|
|
std::string format_temp = format.value;
|
2015-10-19 03:30:46 +08:00
|
|
|
std::string result;
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
if (is_date_format(format.value))
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
2015-10-19 03:30:46 +08:00
|
|
|
const std::string date_unquoted = ",-/: ";
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
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" };
|
|
|
|
|
2015-10-19 03:30:46 +08:00
|
|
|
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;
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
auto lower_string = [](const std::string &s) {
|
2015-10-26 12:26:48 +08:00
|
|
|
std::string lower;
|
|
|
|
lower.resize(s.size());
|
2015-11-01 22:43:01 +08:00
|
|
|
for (std::size_t i = 0; i < s.size(); i++)
|
|
|
|
lower[i] = std::tolower(s[i]);
|
2015-10-26 12:26:48 +08:00
|
|
|
return lower;
|
|
|
|
};
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
for (auto part : split)
|
2015-10-19 03:30:46 +08:00
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
while (format.value.substr(index, part.size()) != part)
|
2015-10-19 03:30:46 +08:00
|
|
|
{
|
|
|
|
index++;
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-19 03:30:46 +08:00
|
|
|
auto between = format.value.substr(prev, index - prev);
|
|
|
|
result.append(between);
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-26 12:26:48 +08:00
|
|
|
part = lower_string(part);
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
if (part == "m" && !processed_month)
|
2015-10-19 03:30:46 +08:00
|
|
|
{
|
|
|
|
result.append(std::to_string(d.month));
|
|
|
|
processed_month = true;
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
else if (part == "mm" && !processed_month)
|
2015-10-19 03:30:46 +08:00
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
if (d.month < 10)
|
2015-10-19 03:30:46 +08:00
|
|
|
{
|
|
|
|
result.append("0");
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-19 03:30:46 +08:00
|
|
|
result.append(std::to_string(d.month));
|
|
|
|
processed_month = true;
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
else if (part == "mmm" && !processed_month)
|
2015-10-19 03:30:46 +08:00
|
|
|
{
|
|
|
|
result.append(MonthNames.at(d.month - 1).substr(0, 3));
|
|
|
|
processed_month = true;
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
else if (part == "mmmm" && !processed_month)
|
2015-10-19 03:30:46 +08:00
|
|
|
{
|
|
|
|
result.append(MonthNames.at(d.month - 1));
|
|
|
|
processed_month = true;
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
else if (part == "d")
|
2015-10-19 03:30:46 +08:00
|
|
|
{
|
|
|
|
result.append(std::to_string(d.day));
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
else if (part == "dd")
|
2015-10-19 03:30:46 +08:00
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
if (d.day < 10)
|
2015-10-19 03:30:46 +08:00
|
|
|
{
|
|
|
|
result.append("0");
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-19 03:30:46 +08:00
|
|
|
result.append(std::to_string(d.day));
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
else if (part == "yyyy")
|
2015-10-19 03:30:46 +08:00
|
|
|
{
|
|
|
|
result.append(std::to_string(d.year));
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
else if (part == "h")
|
2015-10-19 03:30:46 +08:00
|
|
|
{
|
|
|
|
result.append(std::to_string(d.hour));
|
|
|
|
processed_month = true;
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
else if (part == "hh")
|
2015-10-19 03:30:46 +08:00
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
if (d.hour < 10)
|
2015-10-19 03:30:46 +08:00
|
|
|
{
|
|
|
|
result.append("0");
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-19 03:30:46 +08:00
|
|
|
result.append(std::to_string(d.hour));
|
|
|
|
processed_month = true;
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
else if (part == "m")
|
2015-10-19 03:30:46 +08:00
|
|
|
{
|
|
|
|
result.append(std::to_string(d.minute));
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
else if (part == "mm")
|
2015-10-19 03:30:46 +08:00
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
if (d.minute < 10)
|
2015-10-19 03:30:46 +08:00
|
|
|
{
|
|
|
|
result.append("0");
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-19 03:30:46 +08:00
|
|
|
result.append(std::to_string(d.minute));
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
else if (part == "s")
|
2015-10-19 03:30:46 +08:00
|
|
|
{
|
|
|
|
result.append(std::to_string(d.second));
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
else if (part == "ss")
|
2015-10-19 03:30:46 +08:00
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
if (d.second < 10)
|
2015-10-19 03:30:46 +08:00
|
|
|
{
|
|
|
|
result.append("0");
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-19 03:30:46 +08:00
|
|
|
result.append(std::to_string(d.second));
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
else if (part == "am/pm" || part == "a/p")
|
2015-10-26 12:26:48 +08:00
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
if (d.hour < 12)
|
2015-10-26 12:26:48 +08:00
|
|
|
{
|
|
|
|
result.append("AM");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result.append("PM");
|
|
|
|
}
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-19 03:30:46 +08:00
|
|
|
index += part.size();
|
|
|
|
prev = index;
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
if (index < format.value.size())
|
2015-10-19 03:30:46 +08:00
|
|
|
{
|
|
|
|
result.append(format.value.substr(index));
|
|
|
|
}
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
else if (format.value == "General" || format.value == "0")
|
2015-10-19 03:30:46 +08:00
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
if (number == static_cast<long long int>(number))
|
2015-10-26 12:26:48 +08:00
|
|
|
{
|
|
|
|
result = std::to_string(static_cast<long long int>(number));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result = std::to_string(number);
|
|
|
|
}
|
2015-10-19 03:30:46 +08:00
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
else if (format.value.substr(0, 8) == "#,##0.00" || format.value.substr(0, 9) == "-#,##0.00")
|
2015-10-19 03:30:46 +08:00
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
if (format.value[0] == '-')
|
2015-10-26 12:26:48 +08:00
|
|
|
{
|
|
|
|
result = "-";
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
if (format.has_locale && format.locale == "$$-1009")
|
2015-10-26 12:26:48 +08:00
|
|
|
{
|
|
|
|
result += "CA$";
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
else if (format.has_locale && format.locale == "$€-407")
|
2015-10-26 12:26:48 +08:00
|
|
|
{
|
|
|
|
result += "€";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result += "$";
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-26 12:26:48 +08:00
|
|
|
result += std::to_string(number < 0 ? -number : number);
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-26 12:26:48 +08:00
|
|
|
auto decimal_pos = result.find('.');
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
if (decimal_pos != std::string::npos)
|
2015-10-26 12:26:48 +08:00
|
|
|
{
|
|
|
|
result[decimal_pos] = ',';
|
|
|
|
decimal_pos += 3;
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
while (decimal_pos < result.size())
|
2015-10-26 12:26:48 +08:00
|
|
|
{
|
|
|
|
result.pop_back();
|
|
|
|
}
|
|
|
|
}
|
2015-10-17 06:35:11 +08:00
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-19 03:30:46 +08:00
|
|
|
return result;
|
2015-10-17 06:35:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string format_section(const std::string &text, const section &format)
|
|
|
|
{
|
|
|
|
auto arobase_index = format.value.find('@');
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-17 06:35:11 +08:00
|
|
|
std::string first_part, middle_part, last_part;
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
if (arobase_index != std::string::npos)
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
|
|
|
first_part = format.value.substr(0, arobase_index);
|
|
|
|
middle_part = text;
|
|
|
|
last_part = format.value.substr(arobase_index + 1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
first_part = format.value;
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
auto unquote = [](std::string &s) {
|
|
|
|
if (!s.empty())
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
if (s.front() != '"' || s.back() != '"') return false;
|
2015-10-17 06:35:11 +08:00
|
|
|
s = s.substr(0, s.size() - 2);
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-17 06:35:11 +08:00
|
|
|
return true;
|
|
|
|
};
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
if (!unquote(first_part) || !unquote(last_part))
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
|
|
|
throw std::runtime_error(std::string("additional text must be enclosed in quotes: ") + format.value);
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-17 06:35:11 +08:00
|
|
|
return first_part + middle_part + last_part;
|
|
|
|
}
|
|
|
|
|
2015-10-19 03:30:46 +08:00
|
|
|
std::string format_number(long double number, const std::string &format, xlnt::calendar base_date)
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
|
|
|
auto sections = parse_format_sections(format);
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
if (number > 0)
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
2015-10-19 03:30:46 +08:00
|
|
|
return format_section(number, sections.first, base_date);
|
2015-10-17 06:35:11 +08:00
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
else if (number < 0)
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
2015-10-19 03:30:46 +08:00
|
|
|
return format_section(number, sections.second, base_date);
|
2015-10-17 06:35:11 +08:00
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-17 06:35:11 +08:00
|
|
|
// number == 0
|
2015-10-19 03:30:46 +08:00
|
|
|
return format_section(number, sections.third, base_date);
|
2015-10-17 06:35:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string format_text(const std::string &text, const std::string &format)
|
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
if (format == "General") return text;
|
2015-10-17 06:35:11 +08:00
|
|
|
auto sections = parse_format_sections(format);
|
|
|
|
return format_section(text, sections.fourth);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-26 04:39:25 +08:00
|
|
|
namespace xlnt {
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-11-03 03:22:13 +08:00
|
|
|
const std::unordered_map<std::string, int> &cell::error_codes()
|
2015-10-30 01:46:56 +08:00
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
static const std::unordered_map<std::string, int> codes = { { "#NULL!", 0 }, { "#DIV/0!", 1 }, { "#VALUE!", 2 },
|
|
|
|
{ "#REF!", 3 }, { "#NAME?", 4 }, { "#NUM!", 5 },
|
|
|
|
{ "#N/A!", 6 } };
|
|
|
|
|
2015-10-30 01:46:56 +08:00
|
|
|
return codes;
|
2014-07-26 04:39:25 +08:00
|
|
|
};
|
2014-05-21 22:20:30 +08:00
|
|
|
|
2014-07-26 04:39:25 +08:00
|
|
|
cell::cell() : d_(nullptr)
|
2014-07-20 04:59:05 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2014-07-26 04:39:25 +08:00
|
|
|
cell::cell(detail::cell_impl *d) : d_(d)
|
2014-05-21 22:20:30 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2014-07-26 04:39:25 +08:00
|
|
|
cell::cell(worksheet worksheet, const cell_reference &reference) : d_(nullptr)
|
2014-05-21 22:20:30 +08:00
|
|
|
{
|
2014-07-26 04:39:25 +08:00
|
|
|
cell self = worksheet.get_cell(reference);
|
|
|
|
d_ = self.d_;
|
2014-05-21 22:20:30 +08:00
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
template <typename T>
|
2015-10-14 01:56:07 +08:00
|
|
|
cell::cell(worksheet worksheet, const cell_reference &reference, const T &initial_value) : cell(worksheet, reference)
|
2014-05-21 22:20:30 +08:00
|
|
|
{
|
2014-07-26 04:39:25 +08:00
|
|
|
set_value(initial_value);
|
2014-05-21 22:20:30 +08:00
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2014-07-26 04:39:25 +08:00
|
|
|
bool cell::garbage_collectible() const
|
2014-05-21 22:20:30 +08:00
|
|
|
{
|
2015-10-24 02:42:36 +08:00
|
|
|
return !(get_data_type() != type::null || is_merged() || has_comment() || has_formula() || has_style());
|
2014-05-21 22:20:30 +08:00
|
|
|
}
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2014-07-26 04:39:25 +08:00
|
|
|
void cell::set_value(bool b)
|
2014-05-21 22:20:30 +08:00
|
|
|
{
|
2015-10-14 01:56:07 +08:00
|
|
|
d_->value_numeric_ = b ? 1 : 0;
|
|
|
|
d_->type_ = type::boolean;
|
2014-05-21 22:20:30 +08:00
|
|
|
}
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-02 06:14:42 +08:00
|
|
|
void cell::set_value(std::int8_t i)
|
2014-05-21 22:20:30 +08:00
|
|
|
{
|
2015-10-14 01:56:07 +08:00
|
|
|
d_->value_numeric_ = static_cast<long double>(i);
|
|
|
|
d_->type_ = type::numeric;
|
2014-05-21 22:20:30 +08:00
|
|
|
}
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-02 06:14:42 +08:00
|
|
|
void cell::set_value(std::int16_t i)
|
2014-05-31 06:42:25 +08:00
|
|
|
{
|
2015-10-14 01:56:07 +08:00
|
|
|
d_->value_numeric_ = static_cast<long double>(i);
|
|
|
|
d_->type_ = type::numeric;
|
2014-05-31 06:42:25 +08:00
|
|
|
}
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-02 06:14:42 +08:00
|
|
|
void cell::set_value(std::int32_t i)
|
|
|
|
{
|
2015-10-14 01:56:07 +08:00
|
|
|
d_->value_numeric_ = static_cast<long double>(i);
|
|
|
|
d_->type_ = type::numeric;
|
2015-10-02 06:14:42 +08:00
|
|
|
}
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-02 06:14:42 +08:00
|
|
|
void cell::set_value(std::int64_t i)
|
|
|
|
{
|
2015-10-14 01:56:07 +08:00
|
|
|
d_->value_numeric_ = static_cast<long double>(i);
|
|
|
|
d_->type_ = type::numeric;
|
2015-10-02 06:14:42 +08:00
|
|
|
}
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-02 06:14:42 +08:00
|
|
|
void cell::set_value(std::uint8_t i)
|
|
|
|
{
|
2015-10-14 01:56:07 +08:00
|
|
|
d_->value_numeric_ = static_cast<long double>(i);
|
|
|
|
d_->type_ = type::numeric;
|
2015-10-02 06:14:42 +08:00
|
|
|
}
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-02 06:14:42 +08:00
|
|
|
void cell::set_value(std::uint16_t i)
|
|
|
|
{
|
2015-10-14 01:56:07 +08:00
|
|
|
d_->value_numeric_ = static_cast<long double>(i);
|
|
|
|
d_->type_ = type::numeric;
|
2015-10-02 06:14:42 +08:00
|
|
|
}
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-02 06:14:42 +08:00
|
|
|
void cell::set_value(std::uint32_t i)
|
|
|
|
{
|
2015-10-14 01:56:07 +08:00
|
|
|
d_->value_numeric_ = static_cast<long double>(i);
|
|
|
|
d_->type_ = type::numeric;
|
2015-10-02 06:14:42 +08:00
|
|
|
}
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-02 06:14:42 +08:00
|
|
|
void cell::set_value(std::uint64_t i)
|
|
|
|
{
|
2015-10-14 01:56:07 +08:00
|
|
|
d_->value_numeric_ = static_cast<long double>(i);
|
|
|
|
d_->type_ = type::numeric;
|
2015-10-02 06:14:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-02 06:14:42 +08:00
|
|
|
void cell::set_value(unsigned long i)
|
|
|
|
{
|
2015-10-14 01:56:07 +08:00
|
|
|
d_->value_numeric_ = static_cast<long double>(i);
|
|
|
|
d_->type_ = type::numeric;
|
2015-10-02 06:14:42 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-10-17 07:46:21 +08:00
|
|
|
#ifdef __linux
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-02 13:57:39 +08:00
|
|
|
void cell::set_value(long long i)
|
|
|
|
{
|
2015-10-14 01:56:07 +08:00
|
|
|
d_->value_numeric_ = static_cast<long double>(i);
|
|
|
|
d_->type_ = type::numeric;
|
2015-10-02 13:57:39 +08:00
|
|
|
}
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-02 13:57:39 +08:00
|
|
|
void cell::set_value(unsigned long long i)
|
|
|
|
{
|
2015-10-14 01:56:07 +08:00
|
|
|
d_->value_numeric_ = static_cast<long double>(i);
|
|
|
|
d_->type_ = type::numeric;
|
2015-10-02 13:57:39 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-07 00:31:49 +08:00
|
|
|
void cell::set_value(float f)
|
|
|
|
{
|
2015-10-14 01:56:07 +08:00
|
|
|
d_->value_numeric_ = static_cast<long double>(f);
|
|
|
|
d_->type_ = type::numeric;
|
2015-10-07 00:31:49 +08:00
|
|
|
}
|
2015-10-14 01:56:07 +08:00
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2014-07-26 04:39:25 +08:00
|
|
|
void cell::set_value(double d)
|
2014-05-31 06:42:25 +08:00
|
|
|
{
|
2015-10-14 01:56:07 +08:00
|
|
|
d_->value_numeric_ = static_cast<long double>(d);
|
|
|
|
d_->type_ = type::numeric;
|
2014-05-31 06:42:25 +08:00
|
|
|
}
|
2015-10-14 01:56:07 +08:00
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-07 00:31:49 +08:00
|
|
|
void cell::set_value(long double d)
|
|
|
|
{
|
2015-10-14 01:56:07 +08:00
|
|
|
d_->value_numeric_ = static_cast<long double>(d);
|
|
|
|
d_->type_ = type::numeric;
|
2015-10-07 00:31:49 +08:00
|
|
|
}
|
2014-05-31 06:42:25 +08:00
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-14 01:56:07 +08:00
|
|
|
void cell::set_value(std::string s)
|
|
|
|
{
|
2015-10-14 04:35:22 +08:00
|
|
|
d_->set_string(s, get_parent().get_parent().get_guess_types());
|
2015-11-03 03:22:13 +08:00
|
|
|
|
|
|
|
if (get_data_type() == type::string && !s.empty())
|
|
|
|
{
|
|
|
|
get_parent().get_parent().add_shared_string(s);
|
|
|
|
}
|
2015-10-14 01:56:07 +08:00
|
|
|
}
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-14 01:56:07 +08:00
|
|
|
void cell::set_value(char const *c)
|
|
|
|
{
|
|
|
|
set_value(std::string(c));
|
|
|
|
}
|
2015-10-14 04:35:22 +08:00
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-14 04:35:22 +08:00
|
|
|
void cell::set_value(cell c)
|
|
|
|
{
|
2015-10-15 06:05:13 +08:00
|
|
|
d_->type_ = c.d_->type_;
|
|
|
|
d_->value_numeric_ = c.d_->value_numeric_;
|
|
|
|
d_->value_string_ = c.d_->value_string_;
|
|
|
|
d_->hyperlink_ = c.d_->hyperlink_;
|
|
|
|
d_->has_hyperlink_ = c.d_->has_hyperlink_;
|
|
|
|
d_->formula_ = c.d_->formula_;
|
2015-10-19 03:30:46 +08:00
|
|
|
d_->style_id_ = c.d_->style_id_;
|
2015-10-15 06:05:13 +08:00
|
|
|
set_comment(c.get_comment());
|
2015-10-14 04:35:22 +08:00
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
template <>
|
2015-10-14 01:56:07 +08:00
|
|
|
void cell::set_value(date d)
|
2014-05-21 22:20:30 +08:00
|
|
|
{
|
2015-10-19 03:30:46 +08:00
|
|
|
d_->type_ = type::numeric;
|
|
|
|
d_->value_numeric_ = d.to_number(get_base_date());
|
2015-10-24 02:42:36 +08:00
|
|
|
set_number_format(number_format::date_yyyymmdd2());
|
2014-05-21 22:20:30 +08:00
|
|
|
}
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-14 01:56:07 +08:00
|
|
|
void cell::set_value(datetime d)
|
2014-05-21 22:20:30 +08:00
|
|
|
{
|
2015-10-19 03:30:46 +08:00
|
|
|
d_->type_ = type::numeric;
|
|
|
|
d_->value_numeric_ = d.to_number(get_base_date());
|
2015-10-24 02:42:36 +08:00
|
|
|
set_number_format(number_format::date_datetime());
|
2014-05-21 22:20:30 +08:00
|
|
|
}
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-14 01:56:07 +08:00
|
|
|
void cell::set_value(time t)
|
2014-05-21 22:20:30 +08:00
|
|
|
{
|
2015-10-19 03:30:46 +08:00
|
|
|
d_->type_ = type::numeric;
|
|
|
|
d_->value_numeric_ = t.to_number();
|
2015-10-24 02:42:36 +08:00
|
|
|
set_number_format(number_format::date_time6());
|
2014-05-21 22:20:30 +08:00
|
|
|
}
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-14 01:56:07 +08:00
|
|
|
void cell::set_value(timedelta t)
|
2014-05-21 22:20:30 +08:00
|
|
|
{
|
2015-10-19 03:30:46 +08:00
|
|
|
d_->type_ = type::numeric;
|
|
|
|
d_->value_numeric_ = t.to_number();
|
2015-10-24 02:42:36 +08:00
|
|
|
set_number_format(number_format::date_timedelta());
|
2014-05-21 22:20:30 +08:00
|
|
|
}
|
|
|
|
|
2014-07-26 04:39:25 +08:00
|
|
|
row_t cell::get_row() const
|
2014-05-21 22:20:30 +08:00
|
|
|
{
|
2015-10-14 01:56:07 +08:00
|
|
|
return d_->row_;
|
2014-05-21 22:20:30 +08:00
|
|
|
}
|
|
|
|
|
2014-07-26 04:39:25 +08:00
|
|
|
std::string cell::get_column() const
|
2014-05-21 22:20:30 +08:00
|
|
|
{
|
2015-10-14 01:56:07 +08:00
|
|
|
return cell_reference::column_string_from_index(d_->column_);
|
2014-05-21 22:20:30 +08:00
|
|
|
}
|
|
|
|
|
2014-07-26 04:39:25 +08:00
|
|
|
void cell::set_merged(bool merged)
|
2014-06-05 06:42:17 +08:00
|
|
|
{
|
2015-10-14 01:56:07 +08:00
|
|
|
d_->is_merged_ = merged;
|
2014-06-05 06:42:17 +08:00
|
|
|
}
|
|
|
|
|
2014-07-26 04:39:25 +08:00
|
|
|
bool cell::is_merged() const
|
2014-06-11 05:12:15 +08:00
|
|
|
{
|
2015-10-14 01:56:07 +08:00
|
|
|
return d_->is_merged_;
|
2014-06-11 05:12:15 +08:00
|
|
|
}
|
|
|
|
|
2014-07-26 04:39:25 +08:00
|
|
|
bool cell::is_date() const
|
2014-06-05 06:42:17 +08:00
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
if (get_data_type() == type::numeric)
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
2015-10-19 03:30:46 +08:00
|
|
|
auto number_format = get_number_format().get_format_string();
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
if (number_format != "General")
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
auto sections = parse_format_sections(number_format);
|
|
|
|
return is_date_format(sections.first.value);
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
catch (std::exception)
|
2015-10-17 06:35:11 +08:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-17 06:35:11 +08:00
|
|
|
return false;
|
2014-06-05 06:42:17 +08:00
|
|
|
}
|
|
|
|
|
2014-07-26 04:39:25 +08:00
|
|
|
cell_reference cell::get_reference() const
|
2014-05-21 22:20:30 +08:00
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
return { d_->column_, d_->row_ };
|
2014-05-21 22:20:30 +08:00
|
|
|
}
|
|
|
|
|
2014-07-26 04:39:25 +08:00
|
|
|
bool cell::operator==(std::nullptr_t) const
|
2014-07-25 05:31:46 +08:00
|
|
|
{
|
2014-07-26 04:39:25 +08:00
|
|
|
return d_ == nullptr;
|
2014-07-25 05:31:46 +08:00
|
|
|
}
|
2014-05-21 22:20:30 +08:00
|
|
|
|
2014-07-26 04:39:25 +08:00
|
|
|
bool cell::operator==(const cell &comparand) const
|
2014-05-21 22:20:30 +08:00
|
|
|
{
|
2015-10-14 01:56:07 +08:00
|
|
|
return d_ == comparand.d_;
|
2014-05-21 22:20:30 +08:00
|
|
|
}
|
|
|
|
|
2014-07-26 04:39:25 +08:00
|
|
|
cell &cell::operator=(const cell &rhs)
|
2014-05-31 06:42:25 +08:00
|
|
|
{
|
2015-10-14 01:56:07 +08:00
|
|
|
*d_ = *rhs.d_;
|
2014-05-21 22:20:30 +08:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2014-07-26 04:39:25 +08:00
|
|
|
bool operator<(cell left, cell right)
|
2014-07-20 04:59:05 +08:00
|
|
|
{
|
2014-07-26 04:39:25 +08:00
|
|
|
return left.get_reference() < right.get_reference();
|
2014-07-20 04:59:05 +08:00
|
|
|
}
|
|
|
|
|
2015-10-17 06:35:11 +08:00
|
|
|
std::string cell::to_repr() const
|
2014-05-21 22:20:30 +08:00
|
|
|
{
|
2014-06-06 05:42:15 +08:00
|
|
|
return "<Cell " + worksheet(d_->parent_).get_title() + "." + get_reference().to_string() + ">";
|
2014-05-21 22:20:30 +08:00
|
|
|
}
|
|
|
|
|
2014-06-11 05:12:15 +08:00
|
|
|
relationship cell::get_hyperlink() const
|
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
if (!d_->has_hyperlink_)
|
2014-06-11 05:12:15 +08:00
|
|
|
{
|
|
|
|
throw std::runtime_error("no hyperlink set");
|
|
|
|
}
|
|
|
|
|
|
|
|
return d_->hyperlink_;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool cell::has_hyperlink() const
|
|
|
|
{
|
|
|
|
return d_->has_hyperlink_;
|
|
|
|
}
|
2014-05-21 22:20:30 +08:00
|
|
|
|
2014-06-11 05:12:15 +08:00
|
|
|
void cell::set_hyperlink(const std::string &hyperlink)
|
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
if (hyperlink.length() == 0 || std::find(hyperlink.begin(), hyperlink.end(), ':') == hyperlink.end())
|
2014-06-11 05:12:15 +08:00
|
|
|
{
|
|
|
|
throw data_type_exception();
|
|
|
|
}
|
|
|
|
|
|
|
|
d_->has_hyperlink_ = true;
|
2014-07-20 02:43:48 +08:00
|
|
|
d_->hyperlink_ = worksheet(d_->parent_).create_relationship(relationship::type::hyperlink, hyperlink);
|
2014-06-11 05:12:15 +08:00
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
if (get_data_type() == type::null)
|
2014-06-11 05:12:15 +08:00
|
|
|
{
|
2014-07-26 04:39:25 +08:00
|
|
|
set_value(hyperlink);
|
2014-06-11 05:12:15 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cell::set_formula(const std::string &formula)
|
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
if (formula.length() == 0)
|
2014-07-25 05:31:46 +08:00
|
|
|
{
|
|
|
|
throw data_type_exception();
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
if (formula[0] == '=')
|
2015-10-26 12:26:48 +08:00
|
|
|
{
|
|
|
|
d_->formula_ = formula.substr(1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
d_->formula_ = formula;
|
|
|
|
}
|
2014-07-25 05:31:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool cell::has_formula() const
|
|
|
|
{
|
2014-07-26 04:39:25 +08:00
|
|
|
return !d_->formula_.empty();
|
2014-07-25 05:31:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string cell::get_formula() const
|
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
if (d_->formula_.empty())
|
2014-06-11 05:12:15 +08:00
|
|
|
{
|
|
|
|
throw data_type_exception();
|
|
|
|
}
|
|
|
|
|
2014-07-26 04:39:25 +08:00
|
|
|
return d_->formula_;
|
2014-07-25 05:31:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void cell::clear_formula()
|
|
|
|
{
|
2014-07-26 04:39:25 +08:00
|
|
|
d_->formula_.clear();
|
2014-06-11 05:12:15 +08:00
|
|
|
}
|
2014-05-31 06:42:25 +08:00
|
|
|
|
2014-07-27 04:19:15 +08:00
|
|
|
void cell::set_comment(const xlnt::comment &c)
|
2014-07-20 02:43:48 +08:00
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
if (c.d_ != d_->comment_.get())
|
2015-10-14 01:56:07 +08:00
|
|
|
{
|
|
|
|
throw xlnt::attribute_error();
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
if (!has_comment())
|
2014-07-21 21:34:57 +08:00
|
|
|
{
|
|
|
|
get_parent().increment_comments();
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-14 01:56:07 +08:00
|
|
|
*get_comment().d_ = *c.d_;
|
2014-07-20 02:43:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void cell::clear_comment()
|
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
if (has_comment())
|
2014-07-20 02:43:48 +08:00
|
|
|
{
|
2014-07-21 21:34:57 +08:00
|
|
|
get_parent().decrement_comments();
|
2014-07-20 02:43:48 +08:00
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-14 01:56:07 +08:00
|
|
|
d_->comment_ = nullptr;
|
2014-07-20 02:43:48 +08:00
|
|
|
}
|
|
|
|
|
2014-07-25 05:31:46 +08:00
|
|
|
bool cell::has_comment() const
|
|
|
|
{
|
2015-10-14 01:56:07 +08:00
|
|
|
return d_->comment_ != nullptr;
|
2014-07-25 05:31:46 +08:00
|
|
|
}
|
|
|
|
|
2014-06-11 05:12:15 +08:00
|
|
|
void cell::set_error(const std::string &error)
|
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
if (error.length() == 0 || error[0] != '#')
|
2014-06-11 05:12:15 +08:00
|
|
|
{
|
|
|
|
throw data_type_exception();
|
|
|
|
}
|
|
|
|
|
2015-10-14 01:56:07 +08:00
|
|
|
d_->value_string_ = error;
|
|
|
|
d_->type_ = type::error;
|
2014-06-11 05:12:15 +08:00
|
|
|
}
|
2014-05-31 06:42:25 +08:00
|
|
|
|
2014-07-20 02:43:48 +08:00
|
|
|
cell cell::offset(column_t column, row_t row)
|
|
|
|
{
|
2014-07-26 04:39:25 +08:00
|
|
|
return get_parent().get_cell(cell_reference(d_->column_ + column, d_->row_ + row));
|
2014-07-20 02:43:48 +08:00
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2014-07-20 02:43:48 +08:00
|
|
|
worksheet cell::get_parent()
|
|
|
|
{
|
|
|
|
return worksheet(d_->parent_);
|
|
|
|
}
|
|
|
|
|
2014-07-26 04:39:25 +08:00
|
|
|
const worksheet cell::get_parent() const
|
|
|
|
{
|
|
|
|
return worksheet(d_->parent_);
|
|
|
|
}
|
|
|
|
|
2015-10-14 01:56:07 +08:00
|
|
|
comment cell::get_comment()
|
2014-07-20 02:43:48 +08:00
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
if (d_->comment_ == nullptr)
|
2015-10-14 01:56:07 +08:00
|
|
|
{
|
|
|
|
d_->comment_.reset(new detail::comment_impl());
|
|
|
|
get_parent().increment_comments();
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-14 01:56:07 +08:00
|
|
|
return comment(d_->comment_.get());
|
2014-07-20 02:43:48 +08:00
|
|
|
}
|
|
|
|
|
2014-07-26 04:39:25 +08:00
|
|
|
std::pair<int, int> cell::get_anchor() const
|
|
|
|
{
|
|
|
|
static const double DefaultColumnWidth = 51.85;
|
|
|
|
static const double DefaultRowHeight = 15.0;
|
|
|
|
|
|
|
|
auto points_to_pixels = [](double value, double dpi) { return (int)std::ceil(value * dpi / 72); };
|
|
|
|
|
2015-10-14 01:56:07 +08:00
|
|
|
auto left_columns = d_->column_ - 1;
|
2014-07-26 04:39:25 +08:00
|
|
|
int left_anchor = 0;
|
|
|
|
auto default_width = points_to_pixels(DefaultColumnWidth, 96.0);
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
for (column_t column_index = 1; column_index <= left_columns; column_index++)
|
2014-07-26 04:39:25 +08:00
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
if (get_parent().has_column_properties(column_index))
|
2014-07-26 04:39:25 +08:00
|
|
|
{
|
2015-10-29 03:08:54 +08:00
|
|
|
auto cdw = get_parent().get_column_properties(column_index).width;
|
2014-07-26 04:39:25 +08:00
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
if (cdw > 0)
|
2014-07-26 04:39:25 +08:00
|
|
|
{
|
|
|
|
left_anchor += points_to_pixels(cdw, 96.0);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
left_anchor += default_width;
|
|
|
|
}
|
|
|
|
|
2015-10-14 01:56:07 +08:00
|
|
|
auto top_rows = d_->row_ - 1;
|
2014-07-26 04:39:25 +08:00
|
|
|
int top_anchor = 0;
|
|
|
|
auto default_height = points_to_pixels(DefaultRowHeight, 96.0);
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
for (int row_index = 1; row_index <= (int)top_rows; row_index++)
|
2014-07-26 04:39:25 +08:00
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
if (get_parent().has_row_properties(row_index))
|
2014-07-26 04:39:25 +08:00
|
|
|
{
|
2015-10-29 03:08:54 +08:00
|
|
|
auto rdh = get_parent().get_row_properties(row_index).height;
|
2014-07-26 04:39:25 +08:00
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
if (rdh > 0)
|
2014-07-26 04:39:25 +08:00
|
|
|
{
|
|
|
|
top_anchor += points_to_pixels(rdh, 96.0);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
top_anchor += default_height;
|
|
|
|
}
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
return { left_anchor, top_anchor };
|
2014-07-26 04:39:25 +08:00
|
|
|
}
|
|
|
|
|
2015-10-14 01:56:07 +08:00
|
|
|
cell::type cell::get_data_type() const
|
|
|
|
{
|
|
|
|
return d_->type_;
|
|
|
|
}
|
|
|
|
|
|
|
|
void cell::set_data_type(type t)
|
|
|
|
{
|
|
|
|
d_->type_ = t;
|
|
|
|
}
|
|
|
|
|
2015-10-19 03:30:46 +08:00
|
|
|
const number_format &cell::get_number_format() const
|
2015-10-14 04:35:22 +08:00
|
|
|
{
|
2015-10-24 02:42:36 +08:00
|
|
|
static const number_format default_format;
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
if (d_->has_style_)
|
2015-10-21 01:53:47 +08:00
|
|
|
{
|
|
|
|
return get_parent().get_parent().get_number_format(d_->style_id_);
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
else if (get_parent().get_parent().get_number_formats().empty())
|
2015-10-21 01:53:47 +08:00
|
|
|
{
|
2015-10-24 02:42:36 +08:00
|
|
|
return default_format;
|
2015-10-21 01:53:47 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return get_parent().get_parent().get_number_formats().front();
|
|
|
|
}
|
2015-10-14 04:35:22 +08:00
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-19 03:30:46 +08:00
|
|
|
const font &cell::get_font() const
|
2015-10-14 01:56:07 +08:00
|
|
|
{
|
2015-10-19 03:30:46 +08:00
|
|
|
return get_parent().get_parent().get_font(d_->style_id_);
|
2015-10-14 01:56:07 +08:00
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-14 01:56:07 +08:00
|
|
|
const fill &cell::get_fill() const
|
|
|
|
{
|
2015-10-19 03:30:46 +08:00
|
|
|
return get_parent().get_parent().get_fill(d_->style_id_);
|
2015-10-14 01:56:07 +08:00
|
|
|
}
|
|
|
|
|
2015-10-19 03:30:46 +08:00
|
|
|
const border &cell::get_border() const
|
2015-10-14 01:56:07 +08:00
|
|
|
{
|
2015-10-19 03:30:46 +08:00
|
|
|
return get_parent().get_parent().get_border(d_->style_id_);
|
2015-10-14 01:56:07 +08:00
|
|
|
}
|
|
|
|
|
2015-10-19 03:30:46 +08:00
|
|
|
const alignment &cell::get_alignment() const
|
2015-10-14 01:56:07 +08:00
|
|
|
{
|
2015-10-19 03:30:46 +08:00
|
|
|
return get_parent().get_parent().get_alignment(d_->style_id_);
|
2015-10-14 01:56:07 +08:00
|
|
|
}
|
|
|
|
|
2015-10-19 03:30:46 +08:00
|
|
|
const protection &cell::get_protection() const
|
2015-10-14 01:56:07 +08:00
|
|
|
{
|
2015-10-19 03:30:46 +08:00
|
|
|
return get_parent().get_parent().get_protection(d_->style_id_);
|
2015-10-14 01:56:07 +08:00
|
|
|
}
|
|
|
|
|
2015-10-19 03:30:46 +08:00
|
|
|
bool cell::pivot_button() const
|
2015-10-14 01:56:07 +08:00
|
|
|
{
|
2015-10-19 03:30:46 +08:00
|
|
|
return get_parent().get_parent().get_pivot_button(d_->style_id_);
|
2015-10-14 01:56:07 +08:00
|
|
|
}
|
|
|
|
|
2015-10-19 03:30:46 +08:00
|
|
|
bool cell::quote_prefix() const
|
2015-10-14 01:56:07 +08:00
|
|
|
{
|
2015-10-19 03:30:46 +08:00
|
|
|
return get_parent().get_parent().get_quote_prefix(d_->style_id_);
|
2015-10-14 01:56:07 +08:00
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-14 01:56:07 +08:00
|
|
|
void cell::clear_value()
|
|
|
|
{
|
|
|
|
d_->value_numeric_ = 0;
|
|
|
|
d_->value_string_.clear();
|
|
|
|
d_->formula_.clear();
|
|
|
|
d_->type_ = cell::type::null;
|
|
|
|
}
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-14 02:19:46 +08:00
|
|
|
bool cell::get_value() const
|
2015-10-14 01:56:07 +08:00
|
|
|
{
|
|
|
|
return d_->value_numeric_ != 0;
|
|
|
|
}
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-14 02:19:46 +08:00
|
|
|
std::int8_t cell::get_value() const
|
2015-10-14 01:56:07 +08:00
|
|
|
{
|
|
|
|
return static_cast<std::int8_t>(d_->value_numeric_);
|
|
|
|
}
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-14 02:19:46 +08:00
|
|
|
std::int16_t cell::get_value() const
|
2015-10-14 01:56:07 +08:00
|
|
|
{
|
|
|
|
return static_cast<std::int16_t>(d_->value_numeric_);
|
|
|
|
}
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-14 02:19:46 +08:00
|
|
|
std::int32_t cell::get_value() const
|
2015-10-14 01:56:07 +08:00
|
|
|
{
|
|
|
|
return static_cast<std::int32_t>(d_->value_numeric_);
|
|
|
|
}
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-14 02:19:46 +08:00
|
|
|
std::int64_t cell::get_value() const
|
2015-10-14 01:56:07 +08:00
|
|
|
{
|
|
|
|
return static_cast<std::int64_t>(d_->value_numeric_);
|
|
|
|
}
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-14 02:19:46 +08:00
|
|
|
std::uint8_t cell::get_value() const
|
2015-10-14 01:56:07 +08:00
|
|
|
{
|
|
|
|
return static_cast<std::uint8_t>(d_->value_numeric_);
|
|
|
|
}
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-14 02:19:46 +08:00
|
|
|
std::uint16_t cell::get_value() const
|
2015-10-14 01:56:07 +08:00
|
|
|
{
|
|
|
|
return static_cast<std::uint16_t>(d_->value_numeric_);
|
|
|
|
}
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-14 02:19:46 +08:00
|
|
|
std::uint32_t cell::get_value() const
|
2015-10-14 01:56:07 +08:00
|
|
|
{
|
|
|
|
return static_cast<std::uint32_t>(d_->value_numeric_);
|
|
|
|
}
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-14 02:19:46 +08:00
|
|
|
std::uint64_t cell::get_value() const
|
2015-10-14 01:56:07 +08:00
|
|
|
{
|
|
|
|
return static_cast<std::uint64_t>(d_->value_numeric_);
|
|
|
|
}
|
2015-10-17 07:46:21 +08:00
|
|
|
|
|
|
|
#ifdef __linux
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-17 07:46:21 +08:00
|
|
|
long long int cell::get_value() const
|
|
|
|
{
|
|
|
|
return static_cast<long long int>(d_->value_numeric_);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-14 02:19:46 +08:00
|
|
|
float cell::get_value() const
|
2015-10-14 01:56:07 +08:00
|
|
|
{
|
|
|
|
return static_cast<float>(d_->value_numeric_);
|
|
|
|
}
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-14 02:19:46 +08:00
|
|
|
double cell::get_value() const
|
2015-10-14 01:56:07 +08:00
|
|
|
{
|
|
|
|
return static_cast<double>(d_->value_numeric_);
|
|
|
|
}
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-14 02:19:46 +08:00
|
|
|
long double cell::get_value() const
|
2015-10-14 01:56:07 +08:00
|
|
|
{
|
|
|
|
return d_->value_numeric_;
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
template <>
|
2015-10-14 02:19:46 +08:00
|
|
|
time cell::get_value() const
|
2015-10-14 01:56:07 +08:00
|
|
|
{
|
|
|
|
return time::from_number(d_->value_numeric_);
|
|
|
|
}
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-14 02:19:46 +08:00
|
|
|
datetime cell::get_value() const
|
2015-10-14 01:56:07 +08:00
|
|
|
{
|
2015-10-19 03:30:46 +08:00
|
|
|
return datetime::from_number(d_->value_numeric_, get_base_date());
|
2015-10-14 01:56:07 +08:00
|
|
|
}
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-14 02:19:46 +08:00
|
|
|
date cell::get_value() const
|
2015-10-14 01:56:07 +08:00
|
|
|
{
|
2015-10-19 03:30:46 +08:00
|
|
|
return date::from_number(static_cast<int>(d_->value_numeric_), get_base_date());
|
2015-10-14 01:56:07 +08:00
|
|
|
}
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-14 02:19:46 +08:00
|
|
|
timedelta cell::get_value() const
|
2015-10-14 01:56:07 +08:00
|
|
|
{
|
2015-10-19 03:30:46 +08:00
|
|
|
return timedelta::from_number(d_->value_numeric_);
|
2015-10-14 01:56:07 +08:00
|
|
|
}
|
2015-10-14 02:19:46 +08:00
|
|
|
|
2015-10-19 03:30:46 +08:00
|
|
|
void cell::set_number_format(const number_format &number_format_)
|
2015-10-14 02:19:46 +08:00
|
|
|
{
|
2015-10-21 01:53:47 +08:00
|
|
|
d_->has_style_ = true;
|
2015-10-19 03:30:46 +08:00
|
|
|
d_->style_id_ = get_parent().get_parent().set_number_format(number_format_, d_->style_id_);
|
2015-10-14 02:19:46 +08:00
|
|
|
}
|
|
|
|
|
2015-11-01 22:43:01 +08:00
|
|
|
template <>
|
2015-10-14 02:19:46 +08:00
|
|
|
std::string cell::get_value() const
|
|
|
|
{
|
|
|
|
return d_->value_string_;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool cell::has_value() const
|
|
|
|
{
|
|
|
|
return d_->type_ != cell::type::null;
|
|
|
|
}
|
|
|
|
|
2015-10-17 06:35:11 +08:00
|
|
|
std::string cell::to_string() const
|
2015-10-14 02:19:46 +08:00
|
|
|
{
|
2015-10-19 03:30:46 +08:00
|
|
|
auto nf = get_number_format();
|
2015-11-01 22:43:01 +08:00
|
|
|
|
|
|
|
switch (get_data_type())
|
2015-10-14 01:56:07 +08:00
|
|
|
{
|
2015-11-01 22:43:01 +08:00
|
|
|
case cell::type::null:
|
|
|
|
return "";
|
|
|
|
case cell::type::numeric:
|
|
|
|
return format_number(get_value<long double>(), nf.get_format_string(), 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());
|
|
|
|
case cell::type::boolean:
|
|
|
|
return get_value<long double>() == 0 ? "FALSE" : "TRUE";
|
|
|
|
default:
|
|
|
|
return "";
|
2015-10-14 01:56:07 +08:00
|
|
|
}
|
2015-10-14 02:19:46 +08:00
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-19 03:30:46 +08:00
|
|
|
std::size_t cell::get_style_id() const
|
|
|
|
{
|
|
|
|
return d_->style_id_;
|
|
|
|
}
|
2015-10-24 02:42:36 +08:00
|
|
|
|
|
|
|
bool cell::has_style() const
|
|
|
|
{
|
|
|
|
return d_->has_style_;
|
|
|
|
}
|
|
|
|
|
|
|
|
void cell::set_style_id(std::size_t style_id)
|
|
|
|
{
|
|
|
|
d_->style_id_ = style_id;
|
|
|
|
d_->has_style_ = true;
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2015-10-19 03:30:46 +08:00
|
|
|
calendar cell::get_base_date() const
|
|
|
|
{
|
|
|
|
return get_parent().get_parent().get_properties().excel_base_date;
|
|
|
|
}
|
2015-11-01 22:43:01 +08:00
|
|
|
|
2014-05-31 06:42:25 +08:00
|
|
|
} // namespace xlnt
|