2014-05-22 05:48:51 +08:00
|
|
|
#include <algorithm>
|
|
|
|
#include <locale>
|
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/relationship.hpp>
|
|
|
|
#include <xlnt/worksheet/worksheet.hpp>
|
|
|
|
#include <xlnt/common/exceptions.hpp>
|
|
|
|
#include <xlnt/workbook/workbook.hpp>
|
|
|
|
#include <xlnt/workbook/document_properties.hpp>
|
2015-10-14 01:56:07 +08:00
|
|
|
#include <xlnt/common/exceptions.hpp>
|
2014-08-14 06:56:34 +08:00
|
|
|
|
2014-06-06 04:19:31 +08:00
|
|
|
#include "detail/cell_impl.hpp"
|
2015-10-14 01:56:07 +08:00
|
|
|
#include "detail/comment_impl.hpp"
|
2014-05-21 22:20:30 +08:00
|
|
|
|
2014-07-26 04:39:25 +08:00
|
|
|
namespace {
|
2014-05-21 22:20:30 +08:00
|
|
|
|
2015-10-02 22:02:54 +08:00
|
|
|
// return s after checking encoding, size, and illegal characters
|
|
|
|
std::string check_string(std::string s)
|
2014-05-21 22:20:30 +08:00
|
|
|
{
|
2015-10-02 22:02:54 +08:00
|
|
|
if (s.size() == 0)
|
2014-05-21 22:20:30 +08:00
|
|
|
{
|
2015-10-02 22:02:54 +08:00
|
|
|
return s;
|
2014-05-21 22:20:30 +08:00
|
|
|
}
|
|
|
|
|
2015-10-02 22:02:54 +08:00
|
|
|
// check encoding?
|
|
|
|
|
|
|
|
if (s.size() > 32767)
|
2014-05-21 22:20:30 +08:00
|
|
|
{
|
2015-10-02 22:02:54 +08:00
|
|
|
s = s.substr(0, 32767); // max string length in Excel
|
2014-05-21 22:20:30 +08:00
|
|
|
}
|
2014-07-26 04:39:25 +08:00
|
|
|
|
2015-10-02 22:02:54 +08:00
|
|
|
for (unsigned char c : s)
|
2014-05-21 22:20:30 +08:00
|
|
|
{
|
2015-10-02 22:02:54 +08:00
|
|
|
if (c <= 8 || c == 11 || c == 12 || (c >= 14 && c <= 31))
|
2014-05-21 22:20:30 +08:00
|
|
|
{
|
2015-10-14 01:56:07 +08:00
|
|
|
throw xlnt::illegal_character_error(static_cast<char>(c));
|
2014-05-21 22:20:30 +08:00
|
|
|
}
|
|
|
|
}
|
2015-10-02 22:02:54 +08:00
|
|
|
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::pair<bool, long double> cast_numeric(const std::string &s)
|
|
|
|
{
|
|
|
|
const char *str = s.c_str();
|
|
|
|
char *str_end = nullptr;
|
|
|
|
auto result = std::strtold(str, &str_end);
|
|
|
|
if (str_end != str + s.size()) return{ false, 0 };
|
|
|
|
return{ true, result };
|
|
|
|
}
|
|
|
|
|
|
|
|
std::pair<bool, long double> cast_percentage(const std::string &s)
|
|
|
|
{
|
|
|
|
if (s.back() == '%')
|
2014-05-21 22:20:30 +08:00
|
|
|
{
|
2015-10-02 22:02:54 +08:00
|
|
|
auto number = cast_numeric(s.substr(0, s.size() - 1));
|
|
|
|
|
|
|
|
if (number.first)
|
|
|
|
{
|
|
|
|
return{ true, number.second / 100 };
|
|
|
|
}
|
2014-05-21 22:20:30 +08:00
|
|
|
}
|
2015-10-02 22:02:54 +08:00
|
|
|
|
|
|
|
return { false, 0 };
|
|
|
|
}
|
|
|
|
|
|
|
|
std::pair<bool, xlnt::time> cast_time(const std::string &s)
|
|
|
|
{
|
|
|
|
xlnt::time result;
|
|
|
|
|
|
|
|
try
|
2014-05-21 22:20:30 +08:00
|
|
|
{
|
2015-10-02 22:02:54 +08:00
|
|
|
auto last_colon = s.find_last_of(':');
|
|
|
|
if (last_colon == std::string::npos) return { false, result };
|
|
|
|
double seconds = std::stod(s.substr(last_colon + 1));
|
|
|
|
result.second = static_cast<int>(seconds);
|
|
|
|
result.microsecond = static_cast<int>((seconds - static_cast<double>(result.second)) * 1e6);
|
|
|
|
|
|
|
|
auto first_colon = s.find_first_of(':');
|
|
|
|
|
|
|
|
if (first_colon == last_colon)
|
2014-05-21 22:20:30 +08:00
|
|
|
{
|
2015-10-02 22:02:54 +08:00
|
|
|
auto decimal_pos = s.find('.');
|
|
|
|
if (decimal_pos != std::string::npos)
|
2014-05-21 22:20:30 +08:00
|
|
|
{
|
2015-10-02 22:02:54 +08:00
|
|
|
result.minute = std::stoi(s.substr(0, first_colon));
|
2014-05-21 22:20:30 +08:00
|
|
|
}
|
2015-10-02 22:02:54 +08:00
|
|
|
else
|
2014-06-11 06:36:31 +08:00
|
|
|
{
|
2015-10-02 22:02:54 +08:00
|
|
|
result.hour = std::stoi(s.substr(0, first_colon));
|
|
|
|
result.minute = result.second;
|
|
|
|
result.second = 0;
|
2014-06-11 06:36:31 +08:00
|
|
|
}
|
2014-05-21 22:20:30 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-10-02 22:02:54 +08:00
|
|
|
result.hour = std::stoi(s.substr(0, first_colon));
|
|
|
|
result.minute = std::stoi(s.substr(first_colon + 1, last_colon - first_colon - 1));
|
2014-07-25 05:31:46 +08:00
|
|
|
}
|
2014-05-31 06:42:25 +08:00
|
|
|
}
|
2015-10-02 22:02:54 +08:00
|
|
|
catch (std::invalid_argument)
|
|
|
|
{
|
|
|
|
return{ false, result };
|
|
|
|
}
|
|
|
|
|
|
|
|
return { true, result };
|
2014-05-21 22:20:30 +08:00
|
|
|
}
|
|
|
|
|
2014-07-26 04:39:25 +08:00
|
|
|
} // namespace
|
2014-05-21 22:20:30 +08:00
|
|
|
|
2014-07-26 04:39:25 +08:00
|
|
|
namespace xlnt {
|
|
|
|
|
|
|
|
const xlnt::color xlnt::color::black(0);
|
|
|
|
const xlnt::color xlnt::color::white(1);
|
|
|
|
|
|
|
|
const std::unordered_map<std::string, int> cell::ErrorCodes =
|
2014-05-21 22:20:30 +08:00
|
|
|
{
|
2014-07-26 04:39:25 +08:00
|
|
|
{"#NULL!", 0},
|
|
|
|
{"#DIV/0!", 1},
|
|
|
|
{"#VALUE!", 2},
|
|
|
|
{"#REF!", 3},
|
|
|
|
{"#NAME?", 4},
|
|
|
|
{"#NUM!", 5},
|
|
|
|
{"#N/A!", 6}
|
|
|
|
};
|
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-10-14 01:56:07 +08:00
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
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-10-14 01:56:07 +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-14 01:56:07 +08:00
|
|
|
return !(get_data_type() != type::null || is_merged() || has_comment() || has_formula());
|
2014-05-21 22:20:30 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-10-14 01:56:07 +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_->is_date_ = false;
|
|
|
|
d_->value_numeric_ = b ? 1 : 0;
|
|
|
|
d_->type_ = type::boolean;
|
2014-05-21 22:20:30 +08:00
|
|
|
}
|
|
|
|
|
2015-10-14 01:56:07 +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_->is_date_ = false;
|
|
|
|
d_->value_numeric_ = static_cast<long double>(i);
|
|
|
|
d_->type_ = type::numeric;
|
2014-05-21 22:20:30 +08:00
|
|
|
}
|
|
|
|
|
2015-10-14 01:56:07 +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_->is_date_ = false;
|
|
|
|
d_->value_numeric_ = static_cast<long double>(i);
|
|
|
|
d_->type_ = type::numeric;
|
2014-05-31 06:42:25 +08:00
|
|
|
}
|
|
|
|
|
2015-10-14 01:56:07 +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_->is_date_ = false;
|
|
|
|
d_->value_numeric_ = static_cast<long double>(i);
|
|
|
|
d_->type_ = type::numeric;
|
2015-10-02 06:14:42 +08:00
|
|
|
}
|
|
|
|
|
2015-10-14 01:56:07 +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_->is_date_ = false;
|
|
|
|
d_->value_numeric_ = static_cast<long double>(i);
|
|
|
|
d_->type_ = type::numeric;
|
2015-10-02 06:14:42 +08:00
|
|
|
}
|
|
|
|
|
2015-10-14 01:56:07 +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_->is_date_ = false;
|
|
|
|
d_->value_numeric_ = static_cast<long double>(i);
|
|
|
|
d_->type_ = type::numeric;
|
2015-10-02 06:14:42 +08:00
|
|
|
}
|
|
|
|
|
2015-10-14 01:56:07 +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_->is_date_ = false;
|
|
|
|
d_->value_numeric_ = static_cast<long double>(i);
|
|
|
|
d_->type_ = type::numeric;
|
2015-10-02 06:14:42 +08:00
|
|
|
}
|
|
|
|
|
2015-10-14 01:56:07 +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_->is_date_ = false;
|
|
|
|
d_->value_numeric_ = static_cast<long double>(i);
|
|
|
|
d_->type_ = type::numeric;
|
2015-10-02 06:14:42 +08:00
|
|
|
}
|
|
|
|
|
2015-10-14 01:56:07 +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_->is_date_ = false;
|
|
|
|
d_->value_numeric_ = static_cast<long double>(i);
|
|
|
|
d_->type_ = type::numeric;
|
2015-10-02 06:14:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
void cell::set_value(unsigned long i)
|
|
|
|
{
|
2015-10-14 01:56:07 +08:00
|
|
|
d_->is_date_ = false;
|
|
|
|
d_->value_numeric_ = static_cast<long double>(i);
|
|
|
|
d_->type_ = type::numeric;
|
2015-10-02 06:14:42 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-10-02 13:57:39 +08:00
|
|
|
#ifdef __linux__
|
|
|
|
void cell::set_value(long long i)
|
|
|
|
{
|
2015-10-14 01:56:07 +08:00
|
|
|
d_->is_date_ = false;
|
|
|
|
d_->value_numeric_ = static_cast<long double>(i);
|
|
|
|
d_->type_ = type::numeric;
|
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_->is_date_ = false;
|
|
|
|
d_->value_numeric_ = static_cast<long double>(i);
|
|
|
|
d_->type_ = type::numeric;
|
2015-10-02 13:57:39 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-10-14 01:56:07 +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_->is_date_ = false;
|
|
|
|
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
|
|
|
|
|
|
|
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_->is_date_ = false;
|
|
|
|
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
|
|
|
|
|
|
|
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_->is_date_ = false;
|
|
|
|
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-10-14 01:56:07 +08:00
|
|
|
template<>
|
|
|
|
void cell::set_value(std::string s)
|
|
|
|
{
|
|
|
|
set_value_guess_type(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
|
|
|
void cell::set_value(char const *c)
|
|
|
|
{
|
|
|
|
set_value(std::string(c));
|
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
|
|
|
void cell::set_value(date d)
|
2014-05-21 22:20:30 +08:00
|
|
|
{
|
2014-07-26 04:39:25 +08:00
|
|
|
d_->is_date_ = true;
|
2015-10-07 00:31:49 +08:00
|
|
|
auto code = xlnt::number_format::format::date_yyyymmdd2;
|
|
|
|
auto number_format = xlnt::number_format(code);
|
2014-08-02 04:46:54 +08:00
|
|
|
get_style().set_number_format(number_format);
|
2014-07-26 04:39:25 +08:00
|
|
|
auto base_date = get_parent().get_parent().get_properties().excel_base_date;
|
2015-10-14 01:56:07 +08:00
|
|
|
d_->value_numeric_ = d.to_number(base_date);
|
|
|
|
d_->type_ = type::numeric;
|
2014-05-21 22:20:30 +08:00
|
|
|
}
|
|
|
|
|
2015-10-14 01:56:07 +08:00
|
|
|
template<>
|
|
|
|
void cell::set_value(datetime d)
|
2014-05-21 22:20:30 +08:00
|
|
|
{
|
2014-07-26 04:39:25 +08:00
|
|
|
d_->is_date_ = true;
|
2015-10-07 00:31:49 +08:00
|
|
|
auto code = xlnt::number_format::format::date_datetime;
|
|
|
|
auto number_format = xlnt::number_format(code);
|
2014-08-02 04:46:54 +08:00
|
|
|
get_style().set_number_format(number_format);
|
2014-07-26 04:39:25 +08:00
|
|
|
auto base_date = get_parent().get_parent().get_properties().excel_base_date;
|
2015-10-14 01:56:07 +08:00
|
|
|
d_->value_numeric_ = d.to_number(base_date);
|
|
|
|
d_->type_ = type::numeric;
|
2014-05-21 22:20:30 +08:00
|
|
|
}
|
|
|
|
|
2015-10-14 01:56:07 +08:00
|
|
|
template<>
|
|
|
|
void cell::set_value(time t)
|
2014-05-21 22:20:30 +08:00
|
|
|
{
|
2014-07-26 04:39:25 +08:00
|
|
|
d_->is_date_ = true;
|
2015-10-07 00:31:49 +08:00
|
|
|
auto code = xlnt::number_format::format::date_time6;
|
|
|
|
auto number_format = xlnt::number_format(code);
|
|
|
|
get_style().set_number_format(number_format);
|
2015-10-14 01:56:07 +08:00
|
|
|
d_->value_numeric_ = t.to_number();
|
|
|
|
d_->type_ = type::numeric;
|
2014-05-21 22:20:30 +08:00
|
|
|
}
|
|
|
|
|
2015-10-14 01:56:07 +08:00
|
|
|
template<>
|
|
|
|
void cell::set_value(timedelta t)
|
2014-05-21 22:20:30 +08:00
|
|
|
{
|
2015-10-14 01:56:07 +08:00
|
|
|
auto code = xlnt::number_format::format::date_timedelta;
|
|
|
|
auto number_format = xlnt::number_format(code);
|
|
|
|
get_style().set_number_format(number_format);
|
|
|
|
d_->value_numeric_ = t.to_number();
|
|
|
|
d_->type_ = type::numeric;
|
|
|
|
}
|
|
|
|
|
|
|
|
void cell::set_value_guess_type(const std::string &s)
|
|
|
|
{
|
|
|
|
d_->is_date_ = false;
|
|
|
|
auto temp = check_string(s);
|
|
|
|
d_->value_string_ = temp;
|
|
|
|
d_->type_ = type::string;
|
|
|
|
|
|
|
|
if (temp.size() > 1 && temp.front() == '=')
|
|
|
|
{
|
|
|
|
d_->formula_ = temp;
|
|
|
|
d_->type_ = type::formula;
|
|
|
|
d_->value_string_.clear();
|
|
|
|
}
|
|
|
|
else if(ErrorCodes.find(s) != ErrorCodes.end())
|
|
|
|
{
|
|
|
|
d_->value_string_ = s;
|
|
|
|
d_->type_ = type::error;
|
|
|
|
}
|
|
|
|
else if(get_parent().get_parent().get_guess_types())
|
|
|
|
{
|
|
|
|
auto percentage = cast_percentage(s);
|
|
|
|
|
|
|
|
if (percentage.first)
|
|
|
|
{
|
|
|
|
d_->value_numeric_ = percentage.second;
|
|
|
|
d_->type_ = type::numeric;
|
|
|
|
get_style().get_number_format().set_format_code(xlnt::number_format::format::percentage);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
auto time = cast_time(s);
|
|
|
|
|
|
|
|
if (time.first)
|
|
|
|
{
|
|
|
|
set_value(time.second);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
auto numeric = cast_numeric(s);
|
|
|
|
|
|
|
|
if (numeric.first)
|
|
|
|
{
|
|
|
|
set_value(numeric.second);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-05-21 22:20:30 +08:00
|
|
|
}
|
|
|
|
|
2014-07-26 04:39:25 +08:00
|
|
|
bool cell::has_style() const
|
2014-05-21 22:20:30 +08:00
|
|
|
{
|
2014-07-26 04:39:25 +08:00
|
|
|
return d_->style_ != nullptr;
|
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
|
|
|
{
|
2014-07-26 04:39:25 +08:00
|
|
|
return d_->is_date_ || (d_->style_ != nullptr && get_style().get_number_format().get_format_code() == number_format::format::date_xlsx14);
|
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
|
|
|
{
|
2014-07-26 04:39:25 +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
|
|
|
style &cell::get_style()
|
2014-05-31 06:42:25 +08:00
|
|
|
{
|
2014-07-26 04:39:25 +08:00
|
|
|
if(d_->style_ == nullptr)
|
|
|
|
{
|
2015-10-14 01:56:07 +08:00
|
|
|
d_->style_.reset(new style());
|
2014-07-26 04:39:25 +08:00
|
|
|
}
|
2015-10-14 01:56:07 +08:00
|
|
|
|
2014-07-26 04:39:25 +08:00
|
|
|
return *d_->style_;
|
2014-05-31 06:42:25 +08:00
|
|
|
}
|
|
|
|
|
2014-07-26 04:39:25 +08:00
|
|
|
const style &cell::get_style() const
|
2014-05-21 22:20:30 +08:00
|
|
|
{
|
2014-07-26 04:39:25 +08:00
|
|
|
if(d_->style_ == nullptr)
|
|
|
|
{
|
2015-10-14 01:56:07 +08:00
|
|
|
d_->style_.reset(new style());
|
2014-07-26 04:39:25 +08:00
|
|
|
}
|
2015-10-14 01:56:07 +08:00
|
|
|
|
2014-07-26 04:39:25 +08:00
|
|
|
return *d_->style_;
|
2014-05-31 06:42:25 +08:00
|
|
|
}
|
2014-07-27 04:19:15 +08:00
|
|
|
|
|
|
|
void cell::set_style(const xlnt::style &s)
|
|
|
|
{
|
|
|
|
get_style() = s;
|
|
|
|
}
|
2014-05-31 06:42:25 +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
|
|
|
}
|
|
|
|
|
2014-05-21 22:20:30 +08:00
|
|
|
std::string cell::to_string() const
|
|
|
|
{
|
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
|
|
|
|
{
|
|
|
|
if(!d_->has_hyperlink_)
|
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
2014-06-06 05:42:15 +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-10-14 01:56:07 +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)
|
|
|
|
{
|
2014-07-25 05:31:46 +08:00
|
|
|
if(formula.length() == 0)
|
|
|
|
{
|
|
|
|
throw data_type_exception();
|
|
|
|
}
|
|
|
|
|
2014-07-26 04:39:25 +08:00
|
|
|
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
|
|
|
|
{
|
2014-07-26 04:39:25 +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-10-14 01:56:07 +08:00
|
|
|
if(c.d_ != d_->comment_.get())
|
|
|
|
{
|
|
|
|
throw xlnt::attribute_error();
|
|
|
|
}
|
|
|
|
|
2014-07-27 04:19:15 +08:00
|
|
|
if(!has_comment())
|
2014-07-21 21:34:57 +08:00
|
|
|
{
|
|
|
|
get_parent().increment_comments();
|
|
|
|
}
|
|
|
|
|
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()
|
|
|
|
{
|
2014-07-27 04:19:15 +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-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)
|
|
|
|
{
|
2014-06-06 05:42:15 +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
|
|
|
}
|
|
|
|
|
|
|
|
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-10-14 01:56:07 +08:00
|
|
|
if(d_->comment_ == nullptr)
|
|
|
|
{
|
|
|
|
d_->comment_.reset(new detail::comment_impl());
|
|
|
|
get_parent().increment_comments();
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
auto &column_dimensions = get_parent().get_column_dimensions();
|
|
|
|
int left_anchor = 0;
|
|
|
|
auto default_width = points_to_pixels(DefaultColumnWidth, 96.0);
|
|
|
|
|
|
|
|
for(int column_index = 1; column_index <= (int)left_columns; column_index++)
|
|
|
|
{
|
|
|
|
if(column_dimensions.find(column_index) != column_dimensions.end())
|
|
|
|
{
|
|
|
|
auto cdw = column_dimensions.at(column_index);
|
|
|
|
|
|
|
|
if(cdw > 0)
|
|
|
|
{
|
|
|
|
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
|
|
|
auto &row_dimensions = get_parent().get_row_dimensions();
|
|
|
|
int top_anchor = 0;
|
|
|
|
auto default_height = points_to_pixels(DefaultRowHeight, 96.0);
|
|
|
|
|
|
|
|
for(int row_index = 1; row_index <= (int)top_rows; row_index++)
|
|
|
|
{
|
|
|
|
if(row_dimensions.find(row_index) != row_dimensions.end())
|
|
|
|
{
|
|
|
|
auto rdh = row_dimensions.at(row_index);
|
|
|
|
|
|
|
|
if(rdh > 0)
|
|
|
|
{
|
|
|
|
top_anchor += points_to_pixels(rdh, 96.0);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
top_anchor += default_height;
|
|
|
|
}
|
|
|
|
|
|
|
|
return {left_anchor, top_anchor};
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::size_t cell::get_xf_index() const
|
|
|
|
{
|
|
|
|
return d_->xf_index_;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string cell::get_number_format() const
|
|
|
|
{
|
|
|
|
return get_style().get_number_format().get_format_code_string();
|
|
|
|
}
|
|
|
|
|
|
|
|
font cell::get_font() const
|
|
|
|
{
|
|
|
|
return get_style().get_font();
|
|
|
|
}
|
|
|
|
|
|
|
|
fill &cell::get_fill()
|
|
|
|
{
|
|
|
|
return get_style().get_fill();
|
|
|
|
}
|
|
|
|
|
|
|
|
const fill &cell::get_fill() const
|
|
|
|
{
|
|
|
|
return get_style().get_fill();
|
|
|
|
}
|
|
|
|
|
|
|
|
border cell::get_border() const
|
|
|
|
{
|
|
|
|
return get_style().get_border();
|
|
|
|
}
|
|
|
|
|
|
|
|
alignment cell::get_alignment() const
|
|
|
|
{
|
|
|
|
return get_style().get_alignment();
|
|
|
|
}
|
|
|
|
|
|
|
|
protection cell::get_protection() const
|
|
|
|
{
|
|
|
|
return get_style().get_protection();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool cell::pivot_button() const
|
|
|
|
{
|
|
|
|
return get_style().pivot_button();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool cell::quote_prefix() const
|
|
|
|
{
|
|
|
|
return get_style().quote_prefix();
|
|
|
|
}
|
|
|
|
|
|
|
|
void cell::clear_value()
|
|
|
|
{
|
|
|
|
d_->value_numeric_ = 0;
|
|
|
|
d_->value_string_.clear();
|
|
|
|
d_->formula_.clear();
|
|
|
|
d_->type_ = cell::type::null;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
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_);
|
|
|
|
}
|
|
|
|
|
|
|
|
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_);
|
|
|
|
}
|
|
|
|
|
|
|
|
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_);
|
|
|
|
}
|
|
|
|
|
|
|
|
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_);
|
|
|
|
}
|
|
|
|
|
|
|
|
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_);
|
|
|
|
}
|
|
|
|
|
|
|
|
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_);
|
|
|
|
}
|
|
|
|
|
|
|
|
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_);
|
|
|
|
}
|
|
|
|
|
|
|
|
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_);
|
|
|
|
}
|
|
|
|
|
|
|
|
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_);
|
|
|
|
}
|
|
|
|
|
|
|
|
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_);
|
|
|
|
}
|
|
|
|
|
|
|
|
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_;
|
|
|
|
}
|
|
|
|
|
|
|
|
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_);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
2015-10-14 02:19:46 +08:00
|
|
|
datetime cell::get_value() const
|
2015-10-14 01:56:07 +08:00
|
|
|
{
|
|
|
|
return datetime::from_number(d_->value_numeric_, xlnt::calendar::windows_1900);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
2015-10-14 02:19:46 +08:00
|
|
|
date cell::get_value() const
|
2015-10-14 01:56:07 +08:00
|
|
|
{
|
|
|
|
return date::from_number(d_->value_numeric_, xlnt::calendar::windows_1900);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
2015-10-14 02:19:46 +08:00
|
|
|
timedelta cell::get_value() const
|
2015-10-14 01:56:07 +08:00
|
|
|
{
|
|
|
|
return timedelta(0, 0);
|
|
|
|
//return timedelta::from_number(d_->value_numeric_);
|
|
|
|
}
|
2015-10-14 02:19:46 +08:00
|
|
|
|
|
|
|
void cell::set_number_format(const std::string &format_string)
|
|
|
|
{
|
|
|
|
get_style().get_number_format().set_format_code_string(format_string);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
|
|
|
std::string cell::get_value() const
|
|
|
|
{
|
|
|
|
return d_->value_string_;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool cell::has_value() const
|
|
|
|
{
|
|
|
|
return d_->type_ != cell::type::null;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::ostream &cell::print(std::ostream &stream, bool convert) const
|
|
|
|
{
|
|
|
|
if(!convert)
|
2015-10-14 01:56:07 +08:00
|
|
|
{
|
2015-10-14 02:19:46 +08:00
|
|
|
return stream << get_value<std::string>();
|
2015-10-14 01:56:07 +08:00
|
|
|
}
|
2015-10-14 02:19:46 +08:00
|
|
|
else
|
2015-10-14 01:56:07 +08:00
|
|
|
{
|
2015-10-14 02:19:46 +08:00
|
|
|
switch(get_data_type())
|
|
|
|
{
|
|
|
|
case type::null:
|
|
|
|
return stream << "";
|
|
|
|
case type::string:
|
|
|
|
return stream << get_value<std::string>();
|
|
|
|
case type::numeric:
|
|
|
|
if(is_date())
|
|
|
|
{
|
|
|
|
return stream << get_value<datetime>().to_string(get_parent().get_parent().get_properties().excel_base_date);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return stream << get_value<long double>();
|
|
|
|
}
|
|
|
|
case type::error:
|
|
|
|
return stream << get_value<std::string>();
|
|
|
|
case type::formula:
|
|
|
|
return stream << d_->formula_;
|
|
|
|
default:
|
|
|
|
return stream;
|
|
|
|
}
|
2015-10-14 01:56:07 +08:00
|
|
|
}
|
2015-10-14 02:19:46 +08:00
|
|
|
}
|
2015-10-14 01:56:07 +08:00
|
|
|
|
2014-05-31 06:42:25 +08:00
|
|
|
} // namespace xlnt
|