xlnt/source/cell/cell_reference.cpp

217 lines
5.1 KiB
C++
Raw Normal View History

2014-05-21 22:20:30 +08:00
#include <locale>
2014-08-14 06:56:34 +08:00
#include <xlnt/cell/cell_reference.hpp>
#include <xlnt/utils/exceptions.hpp>
2014-08-14 06:56:34 +08:00
#include <xlnt/worksheet/range_reference.hpp>
#include <detail/constants.hpp>
2014-05-21 22:20:30 +08:00
namespace xlnt {
2014-05-21 22:20:30 +08:00
std::size_t cell_reference_hash::operator()(const cell_reference &k) const
{
return k.get_row() * constants::MaxColumn().index + k.get_column_index().index;
2014-05-21 22:20:30 +08:00
}
2015-11-03 22:51:23 +08:00
cell_reference &cell_reference::make_absolute(bool absolute_column, bool absolute_row)
2014-05-21 22:20:30 +08:00
{
2015-11-03 22:51:23 +08:00
column_absolute(absolute_column);
row_absolute(absolute_row);
return *this;
2014-05-21 22:20:30 +08:00
}
2015-11-03 22:51:23 +08:00
cell_reference::cell_reference() : cell_reference(1, 1)
{
}
2014-05-21 22:20:30 +08:00
cell_reference::cell_reference(const std::string &string)
{
2015-11-03 22:51:23 +08:00
auto split = split_reference(string, absolute_column_, absolute_row_);
set_column(split.first);
set_row(split.second);
2014-05-21 22:20:30 +08:00
}
2015-11-03 22:51:23 +08:00
cell_reference::cell_reference(const char *reference_string)
: cell_reference(std::string(reference_string))
2014-05-21 22:20:30 +08:00
{
}
2015-11-03 22:51:23 +08:00
cell_reference::cell_reference(const std::string &column, row_t row)
: cell_reference(column_t(column), row)
2014-05-21 22:20:30 +08:00
{
}
2015-11-03 22:51:23 +08:00
cell_reference::cell_reference(column_t column_index, row_t row)
: column_(column_index), row_(row), absolute_row_(false), absolute_column_(false)
2014-05-21 22:20:30 +08:00
{
if (row_ == 0 || !(row_ <= constants::MaxRow()) || column_ == 0 || !(column_ <= constants::MaxColumn()))
2014-05-21 22:20:30 +08:00
{
throw cell_coordinates_exception(column_, row_);
2014-05-21 22:20:30 +08:00
}
}
range_reference cell_reference::operator, (const xlnt::cell_reference &other) const
{
return range_reference(*this, other);
}
2014-05-21 22:20:30 +08:00
std::string cell_reference::to_string() const
{
2015-11-03 22:51:23 +08:00
std::string string_representation;
if (absolute_column_)
{
string_representation.append("$");
}
string_representation.append(column_.column_string());
2015-11-03 22:51:23 +08:00
if (absolute_row_)
2014-05-21 22:20:30 +08:00
{
2015-11-03 22:51:23 +08:00
string_representation.append("$");
2014-05-21 22:20:30 +08:00
}
2015-11-03 22:51:23 +08:00
string_representation.append(std::to_string(row_));
2015-11-03 22:51:23 +08:00
return string_representation;
2014-05-21 22:20:30 +08:00
}
2014-05-22 05:48:51 +08:00
range_reference cell_reference::to_range() const
{
return range_reference(column_, row_, column_, row_);
2014-05-22 05:48:51 +08:00
}
std::pair<std::string, row_t> cell_reference::split_reference(const std::string &reference_string,
bool &absolute_column, bool &absolute_row)
2014-05-21 22:20:30 +08:00
{
absolute_column = false;
absolute_row = false;
2014-05-21 22:20:30 +08:00
// Convert a coordinate string like 'B12' to a tuple ('B', 12)
bool column_part = true;
2014-05-21 22:20:30 +08:00
std::string column_string;
for (auto character : reference_string)
2014-05-21 22:20:30 +08:00
{
char upper = std::toupper(character, std::locale::classic());
if (std::isalpha(character, std::locale::classic()))
2014-05-21 22:20:30 +08:00
{
if (column_part)
2014-05-21 22:20:30 +08:00
{
column_string.append(1, upper);
}
else
{
2014-05-31 06:42:25 +08:00
throw cell_coordinates_exception(reference_string);
2014-05-21 22:20:30 +08:00
}
}
else if (character == '$')
2015-10-14 12:03:48 +08:00
{
if (column_part)
2015-10-14 12:03:48 +08:00
{
if (column_string.empty())
2015-10-14 12:03:48 +08:00
{
column_string.append(1, upper);
}
else
{
column_part = false;
}
}
}
2014-05-21 22:20:30 +08:00
else
{
if (column_part)
2014-05-21 22:20:30 +08:00
{
column_part = false;
}
else if (!std::isdigit(character, std::locale::classic()))
2014-05-21 22:20:30 +08:00
{
2014-05-31 06:42:25 +08:00
throw cell_coordinates_exception(reference_string);
2014-05-21 22:20:30 +08:00
}
}
}
2014-05-21 22:20:30 +08:00
std::string row_string = reference_string.substr(column_string.length());
if (row_string.length() == 0)
2014-06-06 05:42:15 +08:00
{
throw cell_coordinates_exception(reference_string);
}
if (column_string[0] == '$')
2014-05-21 22:20:30 +08:00
{
absolute_row = true;
column_string = column_string.substr(1);
}
if (row_string[0] == '$')
2014-05-21 22:20:30 +08:00
{
absolute_column = true;
row_string = row_string.substr(1);
}
return { column_string, std::stoi(row_string) };
2014-05-21 22:20:30 +08:00
}
cell_reference cell_reference::make_offset(int column_offset, int row_offset) const
{
2015-11-03 22:51:23 +08:00
//TODO: check for overflow/underflow
return cell_reference(static_cast<column_t>(static_cast<int>(column_.index) + column_offset),
static_cast<row_t>(static_cast<int>(row_) + row_offset));
2014-05-21 22:20:30 +08:00
}
bool cell_reference::operator==(const cell_reference &comparand) const
{
2015-11-03 22:51:23 +08:00
return comparand.column_ == column_ &&
comparand.row_ == row_ &&
absolute_column_ == comparand.absolute_column_ &&
absolute_row_ == comparand.absolute_row_;
2014-05-21 22:20:30 +08:00
}
bool cell_reference::operator<(const cell_reference &other)
2014-07-25 05:31:46 +08:00
{
if (row_ != other.row_)
2014-07-25 05:31:46 +08:00
{
return row_ < other.row_;
2014-07-25 05:31:46 +08:00
}
return column_ < other.column_;
2014-07-25 05:31:46 +08:00
}
bool cell_reference::operator>(const cell_reference &other)
{
if (row_ != other.row_)
{
return row_ > other.row_;
}
return column_ > other.column_;
2014-05-22 06:13:32 +08:00
}
bool cell_reference::operator<=(const cell_reference &other)
{
if (row_ != other.row_)
{
return row_ < other.row_;
}
return column_ <= other.column_;
}
bool cell_reference::operator>=(const cell_reference &other)
{
if (row_ != other.row_)
{
return row_ > other.row_;
}
return column_ >= other.column_;
}
} // namespace xlnt