xlnt/source/cell/cell.cpp

1055 lines
22 KiB
C++
Raw Normal View History

2015-12-25 06:10:02 +08:00
// Copyright (c) 2014-2016 Thomas Fussell
// Copyright (c) 2010-2015 openpyxl
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, WRISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE
//
// @license: http://www.opensource.org/licenses/mit-license.php
// @author: see AUTHORS file
2016-11-20 05:50:35 +08:00
2014-05-22 05:48:51 +08:00
#include <algorithm>
2016-06-11 22:09:29 +08:00
#include <cmath>
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>
2016-10-29 22:23:04 +08:00
#include <xlnt/cell/formatted_text.hpp>
#include <xlnt/packaging/relationship.hpp>
#include <xlnt/styles/alignment.hpp>
#include <xlnt/styles/border.hpp>
#include <xlnt/styles/color.hpp>
#include <xlnt/styles/fill.hpp>
#include <xlnt/styles/font.hpp>
2016-06-11 01:40:50 +08:00
#include <xlnt/styles/format.hpp>
#include <xlnt/styles/number_format.hpp>
#include <xlnt/styles/protection.hpp>
2016-06-11 01:40:50 +08:00
#include <xlnt/styles/style.hpp>
#include <xlnt/utils/date.hpp>
#include <xlnt/utils/datetime.hpp>
2016-11-20 05:50:35 +08:00
#include <xlnt/utils/exceptions.hpp>
#include <xlnt/utils/time.hpp>
#include <xlnt/utils/timedelta.hpp>
2014-08-14 06:56:34 +08:00
#include <xlnt/workbook/workbook.hpp>
#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>
2014-08-14 06:56:34 +08:00
2016-12-04 20:29:10 +08:00
#include <detail/cell_impl.hpp>
#include <detail/stylesheet.hpp>
2016-05-12 07:24:53 +08:00
namespace {
std::pair<bool, long double> cast_numeric(const std::string &s)
{
2016-11-20 05:50:35 +08:00
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};
2016-05-12 07:24:53 +08:00
}
std::pair<bool, long double> cast_percentage(const std::string &s)
{
2016-11-20 05:50:35 +08:00
if (s.back() == '%')
{
auto number = cast_numeric(s.substr(0, s.size() - 1));
2016-05-12 07:24:53 +08:00
2016-11-20 05:50:35 +08:00
if (number.first)
{
return {true, number.second / 100};
}
}
2016-05-12 07:24:53 +08:00
2016-11-20 05:50:35 +08:00
return {false, 0};
2016-05-12 07:24:53 +08:00
}
std::pair<bool, xlnt::time> cast_time(const std::string &s)
{
2016-11-20 05:50:35 +08:00
xlnt::time result;
2016-05-12 07:24:53 +08:00
2016-11-20 05:50:35 +08:00
std::vector<std::string> time_components;
std::size_t prev = 0;
auto colon_index = s.find(':');
2016-11-20 05:50:35 +08:00
while (colon_index != std::string::npos)
{
time_components.push_back(s.substr(prev, colon_index - prev));
prev = colon_index + 1;
colon_index = s.find(':', colon_index + 1);
}
2016-11-20 05:50:35 +08:00
time_components.push_back(s.substr(prev, colon_index - prev));
2016-11-20 05:50:35 +08:00
if (time_components.size() < 2 || time_components.size() > 3)
{
return {false, result};
}
2016-05-12 07:24:53 +08:00
2016-11-20 05:50:35 +08:00
std::vector<double> numeric_components;
2016-05-12 07:24:53 +08:00
2016-11-20 05:50:35 +08:00
for (auto component : time_components)
{
if (component.empty() || (component.substr(0, component.find('.')).size() > 2))
{
return {false, result};
}
2016-11-20 05:50:35 +08:00
for (auto d : component)
{
if (!(d >= '0' && d <= '9') && d != '.')
{
return {false, result};
}
}
2016-11-20 05:50:35 +08:00
auto without_leading_zero = component.front() == '0' ? component.substr(1) : component;
auto numeric = std::stod(without_leading_zero);
2016-11-20 05:50:35 +08:00
numeric_components.push_back(numeric);
}
2016-11-20 05:50:35 +08:00
result.hour = static_cast<int>(numeric_components[0]);
result.minute = static_cast<int>(numeric_components[1]);
2016-11-20 05:50:35 +08:00
if (std::fabs(static_cast<double>(result.minute) - numeric_components[1]) > std::numeric_limits<double>::epsilon())
{
result.minute = result.hour;
result.hour = 0;
result.second = static_cast<int>(numeric_components[1]);
result.microsecond = static_cast<int>((numeric_components[1] - result.second) * 1E6);
}
else if (numeric_components.size() > 2)
{
result.second = static_cast<int>(numeric_components[2]);
result.microsecond = static_cast<int>((numeric_components[2] - result.second) * 1E6);
}
2016-05-12 07:24:53 +08:00
2016-11-20 05:50:35 +08:00
return {true, result};
2016-05-12 07:24:53 +08:00
}
} // namespace
2014-07-26 04:39:25 +08:00
namespace xlnt {
const std::unordered_map<std::string, int> &cell::error_codes()
2015-10-30 01:46:56 +08:00
{
2016-11-20 05:50:35 +08:00
static const auto *codes = new std::unordered_map<std::string, int>
{
{"#NULL!", 0},
{"#DIV/0!", 1},
{"#VALUE!", 2},
{"#REF!", 3},
{"#NAME?", 4},
{"#NUM!", 5},
{"#N/A!", 6}
};
2015-11-03 05:45:05 +08:00
return *codes;
}
2014-05-21 22:20:30 +08:00
2015-11-23 01:41:27 +08:00
std::string cell::check_string(const std::string &to_check)
{
// so we can modify it
std::string s = to_check;
if (s.size() == 0)
{
return s;
}
else if (s.size() > 32767)
2015-11-23 01:41:27 +08:00
{
s = s.substr(0, 32767); // max string length in Excel
}
for (char c : s)
{
if (c >= 0 && (c <= 8 || c == 11 || c == 12 || (c >= 14 && c <= 31)))
{
throw illegal_character(c);
2015-11-23 01:41:27 +08:00
}
}
return s;
}
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
bool cell::garbage_collectible() const
2014-05-21 22:20:30 +08:00
{
return !(data_type() != type::null || is_merged() || has_formula() || has_format());
2014-05-21 22:20:30 +08:00
}
2016-08-18 19:34:18 +08:00
template <>
XLNT_API void cell::value(std::nullptr_t)
2016-08-18 19:34:18 +08:00
{
2016-11-20 05:50:35 +08:00
d_->type_ = type::null;
2016-08-18 19:34:18 +08:00
}
template <>
XLNT_API void cell::value(bool b)
2014-05-21 22:20:30 +08:00
{
d_->value_numeric_ = b ? 1 : 0;
d_->type_ = type::boolean;
2014-05-21 22:20:30 +08:00
}
template <>
XLNT_API void cell::value(std::int8_t i)
2014-05-21 22:20:30 +08:00
{
d_->value_numeric_ = static_cast<long double>(i);
d_->type_ = type::numeric;
2014-05-21 22:20:30 +08:00
}
template <>
XLNT_API void cell::value(std::int16_t i)
2014-05-31 06:42:25 +08:00
{
d_->value_numeric_ = static_cast<long double>(i);
d_->type_ = type::numeric;
2014-05-31 06:42:25 +08:00
}
template <>
XLNT_API void cell::value(std::int32_t i)
{
d_->value_numeric_ = static_cast<long double>(i);
d_->type_ = type::numeric;
}
template <>
XLNT_API void cell::value(std::int64_t i)
{
d_->value_numeric_ = static_cast<long double>(i);
d_->type_ = type::numeric;
}
template <>
XLNT_API void cell::value(std::uint8_t i)
{
d_->value_numeric_ = static_cast<long double>(i);
d_->type_ = type::numeric;
}
template <>
XLNT_API void cell::value(std::uint16_t i)
{
d_->value_numeric_ = static_cast<long double>(i);
d_->type_ = type::numeric;
}
template <>
XLNT_API void cell::value(std::uint32_t i)
{
d_->value_numeric_ = static_cast<long double>(i);
d_->type_ = type::numeric;
}
template <>
XLNT_API void cell::value(std::uint64_t i)
{
d_->value_numeric_ = static_cast<long double>(i);
d_->type_ = type::numeric;
}
2015-11-11 09:47:07 +08:00
#ifdef _MSC_VER
template <>
XLNT_API void cell::value(unsigned long i)
{
d_->value_numeric_ = static_cast<long double>(i);
d_->type_ = type::numeric;
}
#endif
2015-10-17 07:46:21 +08:00
#ifdef __linux
template <>
XLNT_API void cell::value(long long i)
2015-10-02 13:57:39 +08:00
{
d_->value_numeric_ = static_cast<long double>(i);
d_->type_ = type::numeric;
2015-10-02 13:57:39 +08:00
}
template <>
XLNT_API void cell::value(unsigned long long i)
2015-10-02 13:57:39 +08:00
{
d_->value_numeric_ = static_cast<long double>(i);
d_->type_ = type::numeric;
2015-10-02 13:57:39 +08:00
}
#endif
2015-10-02 13:57:39 +08:00
template <>
XLNT_API void cell::value(float f)
{
d_->value_numeric_ = static_cast<long double>(f);
d_->type_ = type::numeric;
}
template <>
XLNT_API void cell::value(double d)
2014-05-31 06:42:25 +08:00
{
d_->value_numeric_ = static_cast<long double>(d);
d_->type_ = type::numeric;
2014-05-31 06:42:25 +08:00
}
template <>
XLNT_API void cell::value(long double d)
{
d_->value_numeric_ = static_cast<long double>(d);
d_->type_ = type::numeric;
}
2014-05-31 06:42:25 +08:00
template <>
XLNT_API void cell::value(std::string s)
{
2016-11-20 05:50:35 +08:00
s = check_string(s);
if (s.size() > 1 && s.front() == '=')
{
d_->type_ = type::formula;
formula(s);
2016-11-20 05:50:35 +08:00
}
else if (cell::error_codes().find(s) != cell::error_codes().end())
{
error(s);
2016-11-20 05:50:35 +08:00
}
else
{
d_->type_ = type::string;
d_->value_text_.plain_text(s);
if (s.size() > 0)
{
workbook().add_shared_string(d_->value_text_);
2016-11-20 05:50:35 +08:00
}
}
}
template <>
XLNT_API void cell::value(formatted_text text)
{
2016-10-29 22:23:04 +08:00
if (text.runs().size() == 1 && !text.runs().front().has_formatting())
{
value(text.plain_text());
}
else
{
d_->type_ = type::string;
2016-10-29 22:23:04 +08:00
d_->value_text_ = text;
workbook().add_shared_string(text);
}
}
template <>
XLNT_API void cell::value(char const *c)
{
value(std::string(c));
}
template <>
XLNT_API void cell::value(cell c)
{
2015-10-15 06:05:13 +08:00
d_->type_ = c.d_->type_;
d_->value_numeric_ = c.d_->value_numeric_;
2016-05-12 07:24:53 +08:00
d_->value_text_ = c.d_->value_text_;
2015-10-15 06:05:13 +08:00
d_->hyperlink_ = c.d_->hyperlink_;
d_->formula_ = c.d_->formula_;
d_->format_ = c.d_->format_;
}
template <>
XLNT_API void cell::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(base_date());
number_format(number_format::date_yyyymmdd2());
2014-05-21 22:20:30 +08:00
}
template <>
XLNT_API void cell::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(base_date());
number_format(number_format::date_datetime());
2014-05-21 22:20:30 +08:00
}
template <>
XLNT_API void cell::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();
number_format(number_format::date_time6());
2014-05-21 22:20:30 +08:00
}
template <>
XLNT_API void cell::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();
number_format(xlnt::number_format("[hh]:mm:ss"));
2014-05-21 22:20:30 +08:00
}
row_t cell::row() const
2014-05-21 22:20:30 +08:00
{
return d_->row_;
2014-05-21 22:20:30 +08:00
}
column_t cell::column() const
2014-05-21 22:20:30 +08:00
{
return d_->column_;
2014-05-21 22:20:30 +08:00
}
void cell::merged(bool merged)
2014-06-05 06:42:17 +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
{
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
{
return data_type() == type::numeric && has_format() && number_format().is_date_format();
2014-06-05 06:42:17 +08:00
}
cell_reference cell::reference() const
2014-05-21 22:20:30 +08:00
{
2016-11-20 05:50:35 +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
{
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
{
2016-11-20 05:50:35 +08:00
d_->column_ = rhs.d_->column_;
d_->format_ = rhs.d_->format_;
d_->formula_ = rhs.d_->formula_;
d_->hyperlink_ = rhs.d_->hyperlink_;
d_->is_merged_ = rhs.d_->is_merged_;
d_->parent_ = rhs.d_->parent_;
d_->row_ = rhs.d_->row_;
d_->type_ = rhs.d_->type_;
d_->value_numeric_ = rhs.d_->value_numeric_;
d_->value_text_ = rhs.d_->value_text_;
2014-05-21 22:20:30 +08:00
return *this;
}
std::string cell::hyperlink() const
2014-06-11 05:12:15 +08:00
{
2016-11-20 05:50:35 +08:00
return d_->hyperlink_.get();
2014-06-11 05:12:15 +08:00
}
2014-05-21 22:20:30 +08:00
void cell::hyperlink(const std::string &hyperlink)
2014-06-11 05:12:15 +08:00
{
if (hyperlink.length() == 0 || std::find(hyperlink.begin(), hyperlink.end(), ':') == hyperlink.end())
2014-06-11 05:12:15 +08:00
{
throw invalid_parameter();
2014-06-11 05:12:15 +08:00
}
2016-11-20 05:50:35 +08:00
d_->hyperlink_ = hyperlink;
2014-06-11 05:12:15 +08:00
if (data_type() == type::null)
2014-06-11 05:12:15 +08:00
{
value(hyperlink);
2014-06-11 05:12:15 +08:00
}
}
void cell::formula(const std::string &formula)
2014-06-11 05:12:15 +08:00
{
if (formula.empty())
2014-07-25 05:31:46 +08:00
{
throw invalid_parameter();
2014-07-25 05:31:46 +08:00
}
if (formula[0] == '=')
{
d_->formula_ = formula.substr(1);
}
else
{
d_->formula_ = formula;
}
2014-07-25 05:31:46 +08:00
}
bool cell::has_formula() const
{
return d_->formula_.is_set();
2014-07-25 05:31:46 +08:00
}
std::string cell::formula() const
2014-07-25 05:31:46 +08:00
{
return d_->formula_.get();
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
void cell::error(const std::string &error)
2014-06-11 05:12:15 +08:00
{
if (error.length() == 0 || error[0] != '#')
2014-06-11 05:12:15 +08:00
{
2016-07-30 06:55:49 +08:00
throw invalid_data_type();
2014-06-11 05:12:15 +08:00
}
2016-10-29 22:23:04 +08:00
d_->value_text_.plain_text(error);
d_->type_ = type::error;
2014-06-11 05:12:15 +08:00
}
2014-05-31 06:42:25 +08:00
cell cell::offset(int column, int row)
2014-07-20 02:43:48 +08:00
{
return worksheet().cell(reference().make_offset(column, row));
2014-07-20 02:43:48 +08:00
}
worksheet cell::worksheet()
2014-07-20 02:43:48 +08:00
{
return xlnt::worksheet(d_->parent_);
2014-07-20 02:43:48 +08:00
}
const worksheet cell::worksheet() const
2014-07-26 04:39:25 +08:00
{
return xlnt::worksheet(d_->parent_);
2014-07-26 04:39:25 +08:00
}
workbook &cell::workbook()
2016-05-12 07:24:53 +08:00
{
return worksheet().workbook();
2016-05-12 07:24:53 +08:00
}
const workbook &cell::workbook() const
2016-05-12 07:24:53 +08:00
{
return worksheet().workbook();
2016-05-12 07:24:53 +08:00
}
2014-07-20 02:43:48 +08:00
// TODO: this shares a lot of code with worksheet::point_pos, try to reduce repetion
std::pair<int, int> cell::anchor() const
2014-07-26 04:39:25 +08:00
{
static const auto DefaultColumnWidth = 51.85L;
static const auto DefaultRowHeight = 15.0L;
2014-07-26 04:39:25 +08:00
2016-11-20 05:50:35 +08:00
auto points_to_pixels = [](
long double value, long double dpi) { return static_cast<int>(std::ceil(value * dpi / 72)); };
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.0L);
2014-07-26 04:39:25 +08:00
for (column_t column_index = 1; column_index <= left_columns; column_index++)
2014-07-26 04:39:25 +08:00
{
if (worksheet().has_column_properties(column_index))
2014-07-26 04:39:25 +08:00
{
auto cdw = worksheet().column_properties(column_index).width;
2014-07-26 04:39:25 +08:00
if (cdw > 0)
2014-07-26 04:39:25 +08:00
{
left_anchor += points_to_pixels(cdw, 96.0L);
2014-07-26 04:39:25 +08:00
continue;
}
}
left_anchor += default_width;
}
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.0L);
2014-07-26 04:39:25 +08:00
2015-11-03 05:45:05 +08:00
for (row_t row_index = 1; row_index <= top_rows; row_index++)
2014-07-26 04:39:25 +08:00
{
if (worksheet().has_row_properties(row_index))
2014-07-26 04:39:25 +08:00
{
auto rdh = worksheet().row_properties(row_index).height;
2014-07-26 04:39:25 +08:00
if (rdh > 0)
2014-07-26 04:39:25 +08:00
{
top_anchor += points_to_pixels(rdh, 96.0L);
2014-07-26 04:39:25 +08:00
continue;
}
}
top_anchor += default_height;
}
2016-11-20 05:50:35 +08:00
return {left_anchor, top_anchor};
2014-07-26 04:39:25 +08:00
}
cell::type cell::data_type() const
{
return d_->type_;
}
void cell::data_type(type t)
{
d_->type_ = t;
}
number_format cell::computed_number_format() const
{
2016-11-20 05:50:35 +08:00
return xlnt::number_format();
}
font cell::computed_font() const
{
2016-11-20 05:50:35 +08:00
return xlnt::font();
}
fill cell::computed_fill() const
{
2016-11-20 05:50:35 +08:00
return xlnt::fill();
}
border cell::computed_border() const
{
2016-11-20 05:50:35 +08:00
return xlnt::border();
}
alignment cell::computed_alignment() const
{
2016-11-20 05:50:35 +08:00
return xlnt::alignment();
}
protection cell::computed_protection() const
{
2016-11-20 05:50:35 +08:00
return xlnt::protection();
}
void cell::clear_value()
{
d_->value_numeric_ = 0;
2016-05-12 07:24:53 +08:00
d_->value_text_.clear();
d_->formula_.clear();
d_->type_ = cell::type::null;
}
template <>
XLNT_API bool cell::value() const
{
return d_->value_numeric_ != 0.L;
}
template <>
XLNT_API std::int8_t cell::value() const
{
return static_cast<std::int8_t>(d_->value_numeric_);
}
template <>
XLNT_API std::int16_t cell::value() const
{
return static_cast<std::int16_t>(d_->value_numeric_);
}
template <>
XLNT_API std::int32_t cell::value() const
{
return static_cast<std::int32_t>(d_->value_numeric_);
}
template <>
XLNT_API std::int64_t cell::value() const
{
return static_cast<std::int64_t>(d_->value_numeric_);
}
template <>
XLNT_API std::uint8_t cell::value() const
{
return static_cast<std::uint8_t>(d_->value_numeric_);
}
template <>
XLNT_API std::uint16_t cell::value() const
{
return static_cast<std::uint16_t>(d_->value_numeric_);
}
template <>
XLNT_API std::uint32_t cell::value() const
{
return static_cast<std::uint32_t>(d_->value_numeric_);
}
template <>
XLNT_API std::uint64_t cell::value() const
{
return static_cast<std::uint64_t>(d_->value_numeric_);
}
2015-10-17 07:46:21 +08:00
#ifdef __linux
template <>
XLNT_API long long cell::value() const
2015-10-17 07:46:21 +08:00
{
return static_cast<long long>(d_->value_numeric_);
}
template <>
XLNT_API unsigned long long cell::value() const
{
return static_cast<unsigned long long>(d_->value_numeric_);
2015-10-17 07:46:21 +08:00
}
#endif
template <>
XLNT_API float cell::value() const
{
return static_cast<float>(d_->value_numeric_);
}
template <>
XLNT_API double cell::value() const
{
return static_cast<double>(d_->value_numeric_);
}
template <>
XLNT_API long double cell::value() const
{
return d_->value_numeric_;
}
template <>
XLNT_API time cell::value() const
{
return time::from_number(d_->value_numeric_);
}
template <>
XLNT_API datetime cell::value() const
{
return datetime::from_number(d_->value_numeric_, base_date());
}
template <>
XLNT_API date cell::value() const
{
return date::from_number(static_cast<int>(d_->value_numeric_), base_date());
}
template <>
XLNT_API timedelta cell::value() const
{
2015-10-19 03:30:46 +08:00
return timedelta::from_number(d_->value_numeric_);
}
void cell::alignment(const class alignment &alignment_)
{
auto new_format = has_format() ? modifiable_format() : workbook().create_format();
format(new_format.alignment(alignment_, true));
}
void cell::border(const class border &border_)
2016-03-14 11:46:01 +08:00
{
auto new_format = has_format() ? modifiable_format() : workbook().create_format();
format(new_format.border(border_, true));
2016-03-14 11:46:01 +08:00
}
void cell::fill(const class fill &fill_)
2016-03-14 11:46:01 +08:00
{
auto new_format = has_format() ? modifiable_format() : workbook().create_format();
format(new_format.fill(fill_, true));
2016-03-14 11:46:01 +08:00
}
void cell::font(const class font &font_)
2015-11-23 01:41:27 +08:00
{
auto new_format = has_format() ? modifiable_format() : workbook().create_format();
format(new_format.font(font_, true));
2015-11-23 01:41:27 +08:00
}
void cell::number_format(const class number_format &number_format_)
{
auto new_format = has_format() ? modifiable_format() : workbook().create_format();
format(new_format.number_format(number_format_, true));
2016-03-14 11:46:01 +08:00
}
void cell::protection(const class protection &protection_)
2016-03-14 11:46:01 +08:00
{
auto new_format = has_format() ? modifiable_format() : workbook().create_format();
format(new_format.protection(protection_, true));
2016-03-14 11:46:01 +08:00
}
template <>
XLNT_API std::string cell::value() const
{
2016-10-29 22:23:04 +08:00
return d_->value_text_.plain_text();
}
template <>
XLNT_API formatted_text cell::value() const
{
return d_->value_text_;
}
bool cell::has_value() const
{
return d_->type_ != cell::type::null;
}
std::string cell::to_string() const
{
2016-11-20 05:50:35 +08:00
auto nf = computed_number_format();
switch (data_type())
{
case cell::type::null:
return "";
case cell::type::numeric:
return nf.format(value<long double>(), base_date());
case cell::type::string:
case cell::type::formula:
case cell::type::error:
return nf.format(value<std::string>());
case cell::type::boolean:
return value<long double>() == 0.L ? "FALSE" : "TRUE";
}
2016-12-11 02:39:51 +08:00
return "";
}
2016-05-15 01:57:07 +08:00
bool cell::has_format() const
2015-10-24 02:42:36 +08:00
{
2016-11-20 05:50:35 +08:00
return d_->format_.is_set();
2015-10-24 02:42:36 +08:00
}
void cell::format(const class format new_format)
2015-10-24 02:42:36 +08:00
{
if (has_format())
{
format().d_->references -= format().d_->references > 0 ? 1 : 0;
}
++new_format.d_->references;
2016-11-20 05:50:35 +08:00
d_->format_ = new_format.d_;
2016-08-05 13:52:05 +08:00
}
calendar cell::base_date() const
2015-10-19 03:30:46 +08:00
{
return workbook().base_date();
2015-10-19 03:30:46 +08:00
}
XLNT_API std::ostream &operator<<(std::ostream &stream, const xlnt::cell &cell)
{
return stream << cell.to_string();
}
void cell::value(const std::string &value_string, bool infer_type)
2016-05-12 07:24:53 +08:00
{
value(value_string);
if (!infer_type)
{
return;
}
auto percentage = cast_percentage(value_string);
2016-11-20 05:50:35 +08:00
if (percentage.first)
{
d_->value_numeric_ = percentage.second;
d_->type_ = cell::type::numeric;
number_format(xlnt::number_format::percentage());
2016-11-20 05:50:35 +08:00
}
else
{
auto time = cast_time(value_string);
2016-11-20 05:50:35 +08:00
if (time.first)
{
d_->type_ = cell::type::numeric;
number_format(number_format::date_time6());
2016-11-20 05:50:35 +08:00
d_->value_numeric_ = time.second.to_number();
}
else
{
auto numeric = cast_numeric(value_string);
2016-11-20 05:50:35 +08:00
if (numeric.first)
{
d_->value_numeric_ = numeric.second;
d_->type_ = cell::type::numeric;
}
}
}
2016-05-12 07:24:53 +08:00
}
2016-06-11 01:40:50 +08:00
void cell::clear_format()
{
format().d_->references -= format().d_->references > 0 ? 1 : 0;
2016-11-20 05:50:35 +08:00
d_->format_.clear();
2016-06-11 01:40:50 +08:00
}
void cell::clear_style()
{
if (has_format())
{
modifiable_format().clear_style();
}
2016-06-11 01:40:50 +08:00
}
void cell::style(const class style &new_style)
2016-06-11 01:40:50 +08:00
{
auto new_format = has_format() ? format() : workbook().create_format();
format(new_format.style(new_style));
2016-06-11 01:40:50 +08:00
}
void cell::style(const std::string &style_name)
2016-06-11 01:40:50 +08:00
{
style(workbook().style(style_name));
2016-06-11 01:40:50 +08:00
}
const style cell::style() const
2016-06-20 02:43:41 +08:00
{
if (!has_format() || !format().has_style())
2016-06-20 02:43:41 +08:00
{
2016-11-20 05:50:35 +08:00
throw invalid_attribute();
2016-06-20 02:43:41 +08:00
}
return format().style();
2016-06-20 02:43:41 +08:00
}
bool cell::has_style() const
{
return has_format() && format().has_style();
}
format cell::modifiable_format()
{
2016-11-20 05:50:35 +08:00
if (!d_->format_)
{
throw invalid_attribute();
}
2016-08-18 19:34:18 +08:00
2016-11-20 05:50:35 +08:00
return xlnt::format(*d_->format_);
}
const format cell::format() const
2016-08-18 19:34:18 +08:00
{
2016-11-20 05:50:35 +08:00
if (!d_->format_)
{
throw invalid_attribute();
}
2016-08-18 19:34:18 +08:00
2016-11-20 05:50:35 +08:00
return xlnt::format(*d_->format_);
2016-08-18 19:34:18 +08:00
}
alignment cell::alignment() const
2016-08-18 19:34:18 +08:00
{
2016-11-20 05:50:35 +08:00
return format().alignment();
2016-08-18 19:34:18 +08:00
}
border cell::border() const
2016-08-18 19:34:18 +08:00
{
2016-11-20 05:50:35 +08:00
return format().border();
2016-08-18 19:34:18 +08:00
}
fill cell::fill() const
2016-08-18 19:34:18 +08:00
{
2016-11-20 05:50:35 +08:00
return format().fill();
2016-08-18 19:34:18 +08:00
}
font cell::font() const
2016-08-18 19:34:18 +08:00
{
2016-11-20 05:50:35 +08:00
return format().font();
2016-08-18 19:34:18 +08:00
}
number_format cell::number_format() const
2016-08-18 19:34:18 +08:00
{
2016-11-20 05:50:35 +08:00
return format().number_format();
2016-08-18 19:34:18 +08:00
}
protection cell::protection() const
2016-08-18 19:34:18 +08:00
{
2016-11-20 05:50:35 +08:00
return format().protection();
2016-08-18 19:34:18 +08:00
}
bool cell::has_hyperlink() const
{
2016-11-20 05:50:35 +08:00
return d_->hyperlink_;
2016-08-18 19:34:18 +08:00
}
2016-10-29 22:23:04 +08:00
// comment
bool cell::has_comment()
{
return d_->comment_.is_set();
2016-10-29 22:23:04 +08:00
}
void cell::clear_comment()
{
d_->comment_.clear();
}
2016-10-29 22:36:46 +08:00
class comment cell::comment()
2016-10-29 22:23:04 +08:00
{
if (!has_comment())
{
2016-11-20 05:50:35 +08:00
throw xlnt::exception("cell has no comment");
2016-10-29 22:23:04 +08:00
}
return d_->comment_.get();
}
void cell::comment(const std::string &text, const std::string &author)
{
comment(xlnt::comment(text, author));
}
2016-10-29 22:23:04 +08:00
void cell::comment(const class comment &new_comment)
{
d_->comment_.set(new_comment);
// offset comment 5 pixels down and 5 pixels right of the top right corner of the cell
auto cell_position = anchor();
2016-11-20 05:50:35 +08:00
// todo: make this cell_position.first += width() instead
if (worksheet().has_column_properties(column()))
{
cell_position.first += static_cast<int>(worksheet().column_properties(column()).width);
}
else
{
static const auto DefaultColumnWidth = 51.85L;
auto points_to_pixels = [](long double value, long double dpi)
{
return static_cast<int>(std::ceil(value * dpi / 72));
};
cell_position.first += points_to_pixels(DefaultColumnWidth, 96.0L);
}
cell_position.first += 5;
cell_position.second += 5;
2016-11-20 05:50:35 +08:00
d_->comment_.get().position(cell_position.first, cell_position.second);
d_->comment_.get().size(200, 100);
worksheet().register_comments_in_manifest();
2016-10-29 22:23:04 +08:00
}
2014-05-31 06:42:25 +08:00
} // namespace xlnt