mirror of
https://github.com/tfussell/xlnt.git
synced 2024-03-22 13:11:17 +08:00
clean up and document cell_reference
This commit is contained in:
parent
3e99225652
commit
d2d669d6c5
|
@ -42,20 +42,23 @@ struct cell_reference_hash
|
||||||
std::size_t operator()(const cell_reference &k) const;
|
std::size_t operator()(const cell_reference &k) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An object used to refer to a cell.
|
||||||
|
/// References have two parts, the column and the row.
|
||||||
|
/// In Excel, the reference string A1 refers to the top-left-most cell. A cell_reference
|
||||||
|
/// can be initialized from a string of this form or a 1-indexed ordered pair of the form
|
||||||
|
/// column, row.
|
||||||
|
/// </summary>
|
||||||
class cell_reference
|
class cell_reference
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// <summary>
|
|
||||||
/// Convert a coordinate to an absolute coordinate string (B12 -> $B$12)
|
|
||||||
/// </summary>
|
|
||||||
static cell_reference make_absolute(const cell_reference &relative_reference);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Convert a column letter into a column number (e.g. B -> 2)
|
/// Convert a column letter into a column number (e.g. B -> 2)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Excel only supports 1 - 3 letter column names from A->ZZZ, so we
|
/// Excel only supports 1 - 3 letter column names from A->ZZZ, so we
|
||||||
/// restrict our column names to 1 - 3 characters, each in the range A - Z.
|
/// restrict our column names to 1 - 3 characters, each in the range A - Z.
|
||||||
|
/// Strings outside this range and malformed strings will throw xlnt::column_string_index_exception.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
static column_t column_index_from_string(const std::string &column_string);
|
static column_t column_index_from_string(const std::string &column_string);
|
||||||
|
|
||||||
|
@ -63,8 +66,8 @@ class cell_reference
|
||||||
/// Convert a column number into a column letter (3 -> 'C')
|
/// Convert a column number into a column letter (3 -> 'C')
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Right shift the column col_idx by 26 to find column letters in reverse
|
/// Right shift the column, column_index, by 26 to find column letters in reverse
|
||||||
/// order.These numbers are 1 - based, and can be converted to ASCII
|
/// order. These indices are 1-based, and can be converted to ASCII
|
||||||
/// ordinals by adding 64.
|
/// ordinals by adding 64.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
static std::string column_string_from_index(column_t column_index);
|
static std::string column_string_from_index(column_t column_index);
|
||||||
|
@ -72,52 +75,144 @@ class cell_reference
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Split a coordinate string like "A1" into an equivalent pair like {"A", 1}.
|
/// Split a coordinate string like "A1" into an equivalent pair like {"A", 1}.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
static std::pair<std::string, row_t> split_reference(const std::string &reference_string);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Split a coordinate string like "A1" into an equivalent pair like {"A", 1}.
|
||||||
|
/// Reference parameters absolute_column and absolute_row will be set to true
|
||||||
|
/// if column part or row part are prefixed by a dollar-sign indicating they
|
||||||
|
/// are absolute, otherwise false.
|
||||||
|
/// </summary>
|
||||||
static std::pair<std::string, row_t> split_reference(const std::string &reference_string, bool &absolute_column,
|
static std::pair<std::string, row_t> split_reference(const std::string &reference_string, bool &absolute_column,
|
||||||
bool &absolute_row);
|
bool &absolute_row);
|
||||||
|
|
||||||
// constructors
|
// constructors
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Default constructor makes a reference to the top-left-most cell, "A1".
|
/// Default constructor makes a reference to the top-left-most cell, "A1".
|
||||||
/// </summary>
|
/// </summary>
|
||||||
cell_reference();
|
cell_reference();
|
||||||
|
|
||||||
|
//TODO: should these be explicit? The implicit conversion is nice sometimes.
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a cell_reference from a string reprenting a cell coordinate (e.g. $B14).
|
||||||
|
/// </summary>
|
||||||
cell_reference(const char *reference_string);
|
cell_reference(const char *reference_string);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a cell_reference from a string reprenting a cell coordinate (e.g. $B14).
|
||||||
|
/// </summary>
|
||||||
cell_reference(const std::string &reference_string);
|
cell_reference(const std::string &reference_string);
|
||||||
cell_reference(const std::string &column, row_t row, bool absolute = false);
|
|
||||||
cell_reference(column_t column, row_t row, bool absolute = false);
|
/// <summary>
|
||||||
|
/// Constructs a cell_reference from a string reprenting a column (e.g. A) and
|
||||||
|
/// a 1-indexed row.
|
||||||
|
/// </summary>
|
||||||
|
cell_reference(const std::string &column, row_t row);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a cell_reference from a 1-indexed column index and row index.
|
||||||
|
/// </summary>
|
||||||
|
cell_reference(column_t column, row_t row);
|
||||||
|
|
||||||
// absoluateness
|
// absoluateness
|
||||||
bool is_absolute() const
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convert a coordinate to an absolute coordinate string (e.g. B12 -> $B$12)
|
||||||
|
/// Defaulting to true, absolute_column and absolute_row can optionally control
|
||||||
|
/// whether the resulting cell_reference has an absolute column (e.g. B12 -> $B12)
|
||||||
|
/// and absolute row (e.g. B12 -> B$12) respectively.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This is functionally equivalent to:
|
||||||
|
/// cell_reference copy(*this);
|
||||||
|
/// copy.column_absolute(absolute_column);
|
||||||
|
/// copy.row_absolute(absolute_row);
|
||||||
|
/// return copy;
|
||||||
|
/// </remarks>
|
||||||
|
cell_reference &make_absolute(bool absolute_column = true, bool absolute_row = true);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return true if the reference refers to an absolute column, otherwise false.
|
||||||
|
/// </summary>
|
||||||
|
bool column_absolute() const
|
||||||
{
|
{
|
||||||
return absolute_;
|
return absolute_column_;
|
||||||
}
|
}
|
||||||
void set_absolute(bool absolute)
|
|
||||||
|
/// <summary>
|
||||||
|
/// Make this reference have an absolute column if absolute_column is true,
|
||||||
|
/// otherwise not absolute.
|
||||||
|
/// </summary>
|
||||||
|
void column_absolute(bool absolute_column)
|
||||||
{
|
{
|
||||||
absolute_ = absolute;
|
absolute_column_ = absolute_column;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return true if the reference refers to an absolute row, otherwise false.
|
||||||
|
/// </summary>
|
||||||
|
bool row_absolute() const
|
||||||
|
{
|
||||||
|
return absolute_row_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Make this reference have an absolute row if absolute_row is true,
|
||||||
|
/// otherwise not absolute.
|
||||||
|
/// </summary>
|
||||||
|
void row_absolute(bool absolute_row)
|
||||||
|
{
|
||||||
|
absolute_row_ = absolute_row;
|
||||||
}
|
}
|
||||||
|
|
||||||
// getters/setters
|
// getters/setters
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return a string that identifies the column of this reference
|
||||||
|
/// (e.g. second column from left is "B")
|
||||||
|
/// </summary>
|
||||||
std::string get_column() const
|
std::string get_column() const
|
||||||
{
|
{
|
||||||
return column_string_from_index(column_);
|
return column_string_from_index(column_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the column of this reference from a string that identifies a particular column.
|
||||||
|
/// </summary>
|
||||||
void set_column(const std::string &column_string)
|
void set_column(const std::string &column_string)
|
||||||
{
|
{
|
||||||
column_ = column_index_from_string(column_string);
|
column_ = column_index_from_string(column_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return a 1-indexed numeric index of the column of this reference.
|
||||||
|
/// </summary>
|
||||||
column_t get_column_index() const
|
column_t get_column_index() const
|
||||||
{
|
{
|
||||||
return column_;
|
return column_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the column of this reference from a 1-indexed number that identifies a particular column.
|
||||||
|
/// </summary>
|
||||||
void set_column_index(column_t column)
|
void set_column_index(column_t column)
|
||||||
{
|
{
|
||||||
column_ = column;
|
column_ = column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return a 1-indexed numeric index of the row of this reference.
|
||||||
|
/// </summary>
|
||||||
row_t get_row() const
|
row_t get_row() const
|
||||||
{
|
{
|
||||||
return row_;
|
return row_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the row of this reference from a 1-indexed number that identifies a particular row.
|
||||||
|
/// </summary>
|
||||||
void set_row(row_t row)
|
void set_row(row_t row)
|
||||||
{
|
{
|
||||||
row_ = row;
|
row_ = row;
|
||||||
|
@ -137,11 +232,12 @@ class cell_reference
|
||||||
std::string to_string() const;
|
std::string to_string() const;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Return a range_reference containing only this cell_reference.
|
/// Return a 1x1 range_reference containing only this cell_reference.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
range_reference to_range() const;
|
range_reference to_range() const;
|
||||||
|
|
||||||
// operators
|
// operators
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// I've always wanted to overload the comma operator.
|
/// I've always wanted to overload the comma operator.
|
||||||
/// cell_reference("A", 1), cell_reference("B", 1) will return
|
/// cell_reference("A", 1), cell_reference("B", 1) will return
|
||||||
|
@ -149,28 +245,58 @@ class cell_reference
|
||||||
/// </summary>
|
/// </summary>
|
||||||
range_reference operator, (const cell_reference &other) const;
|
range_reference operator, (const cell_reference &other) const;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return true if this reference is identical to comparand including
|
||||||
|
/// in absoluteness of column and row.
|
||||||
|
/// </summary>
|
||||||
bool operator==(const cell_reference &comparand) const;
|
bool operator==(const cell_reference &comparand) const;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Construct a cell_reference from reference_string and return the result
|
||||||
|
/// of their comparison.
|
||||||
|
/// </summary>
|
||||||
bool operator==(const std::string &reference_string) const
|
bool operator==(const std::string &reference_string) const
|
||||||
{
|
{
|
||||||
return *this == cell_reference(reference_string);
|
return *this == cell_reference(reference_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Construct a cell_reference from reference_string and return the result
|
||||||
|
/// of their comparison.
|
||||||
|
/// </summary>
|
||||||
bool operator==(const char *reference_string) const
|
bool operator==(const char *reference_string) const
|
||||||
{
|
{
|
||||||
return *this == std::string(reference_string);
|
return *this == std::string(reference_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return true if this reference is not identical to comparand including
|
||||||
|
/// in absoluteness of column and row.
|
||||||
|
/// </summary>
|
||||||
bool operator!=(const cell_reference &comparand) const
|
bool operator!=(const cell_reference &comparand) const
|
||||||
{
|
{
|
||||||
return !(*this == comparand);
|
return !(*this == comparand);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Construct a cell_reference from reference_string and return the result
|
||||||
|
/// of their comparison.
|
||||||
|
/// </summary>
|
||||||
bool operator!=(const std::string &reference_string) const
|
bool operator!=(const std::string &reference_string) const
|
||||||
{
|
{
|
||||||
return *this != cell_reference(reference_string);
|
return *this != cell_reference(reference_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Construct a cell_reference from reference_string and return the result
|
||||||
|
/// of their comparison.
|
||||||
|
/// </summary>
|
||||||
bool operator!=(const char *reference_string) const
|
bool operator!=(const char *reference_string) const
|
||||||
{
|
{
|
||||||
return *this != std::string(reference_string);
|
return *this != std::string(reference_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: are these useful? maybe get rid of them
|
||||||
bool operator<(const cell_reference &other);
|
bool operator<(const cell_reference &other);
|
||||||
bool operator>(const cell_reference &other);
|
bool operator>(const cell_reference &other);
|
||||||
bool operator<=(const cell_reference &other);
|
bool operator<=(const cell_reference &other);
|
||||||
|
@ -190,9 +316,14 @@ class cell_reference
|
||||||
row_t row_;
|
row_t row_;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// True if the reference is absolute. This looks like "$A$1" in Excel.
|
/// True if the reference's row is absolute. This looks like "A$1" in Excel.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool absolute_;
|
bool absolute_row_;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// True if the reference's column is absolute. This looks like "$A1" in Excel.
|
||||||
|
/// </summary>
|
||||||
|
bool absolute_column_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace xlnt
|
} // namespace xlnt
|
||||||
|
|
|
@ -13,39 +13,38 @@ std::size_t cell_reference_hash::operator()(const cell_reference &k) const
|
||||||
return k.get_row() * constants::MaxColumn + k.get_column_index();
|
return k.get_row() * constants::MaxColumn + k.get_column_index();
|
||||||
}
|
}
|
||||||
|
|
||||||
cell_reference cell_reference::make_absolute(const cell_reference &relative_reference)
|
cell_reference &cell_reference::make_absolute(bool absolute_column, bool absolute_row)
|
||||||
{
|
{
|
||||||
cell_reference copy = relative_reference;
|
column_absolute(absolute_column);
|
||||||
copy.absolute_ = true;
|
row_absolute(absolute_row);
|
||||||
return copy;
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
cell_reference::cell_reference() : cell_reference(1, 1, false)
|
cell_reference::cell_reference() : cell_reference(1, 1)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
cell_reference::cell_reference(const std::string &string)
|
cell_reference::cell_reference(const std::string &string)
|
||||||
{
|
{
|
||||||
bool absolute = false;
|
auto split = split_reference(string, absolute_column_, absolute_row_);
|
||||||
auto split = split_reference(string, absolute, absolute);
|
|
||||||
*this = cell_reference(split.first, split.second, absolute);
|
set_column(split.first);
|
||||||
|
set_row(split.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
cell_reference::cell_reference(const char *reference_string) : cell_reference(std::string(reference_string))
|
cell_reference::cell_reference(const char *reference_string)
|
||||||
|
: cell_reference(std::string(reference_string))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
cell_reference::cell_reference(const std::string &column, row_t row, bool absolute)
|
cell_reference::cell_reference(const std::string &column, row_t row)
|
||||||
: column_(column_index_from_string(column)), row_(row), absolute_(absolute)
|
: cell_reference(column_index_from_string(column), row)
|
||||||
{
|
{
|
||||||
if (row == 0 || row_ >= constants::MaxRow || column_ == 0 || column_ >= constants::MaxColumn)
|
|
||||||
{
|
|
||||||
throw cell_coordinates_exception(column_, row_);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cell_reference::cell_reference(column_t column_index, row_t row, bool absolute)
|
cell_reference::cell_reference(column_t column_index, row_t row)
|
||||||
: column_(column_index), row_(row), absolute_(absolute)
|
: column_(column_index), row_(row), absolute_column_(false), absolute_row_(false)
|
||||||
{
|
{
|
||||||
if (row_ == 0 || row_ >= constants::MaxRow || column_ == 0 || column_ >= constants::MaxColumn)
|
if (row_ == 0 || row_ >= constants::MaxRow || column_ == 0 || column_ >= constants::MaxColumn)
|
||||||
{
|
{
|
||||||
|
@ -60,12 +59,23 @@ range_reference cell_reference::operator, (const xlnt::cell_reference &other) co
|
||||||
|
|
||||||
std::string cell_reference::to_string() const
|
std::string cell_reference::to_string() const
|
||||||
{
|
{
|
||||||
if (absolute_)
|
std::string string_representation;
|
||||||
|
|
||||||
|
if (absolute_column_)
|
||||||
{
|
{
|
||||||
return std::string("$") + column_string_from_index(column_) + "$" + std::to_string(row_);
|
string_representation.append("$");
|
||||||
}
|
}
|
||||||
|
|
||||||
return column_string_from_index(column_) + std::to_string(row_);
|
string_representation.append(column_string_from_index(column_));
|
||||||
|
|
||||||
|
if (absolute_row_)
|
||||||
|
{
|
||||||
|
string_representation.append("$");
|
||||||
|
}
|
||||||
|
|
||||||
|
string_representation.append(std::to_string(row_));
|
||||||
|
|
||||||
|
return string_representation;
|
||||||
}
|
}
|
||||||
|
|
||||||
range_reference cell_reference::to_range() const
|
range_reference cell_reference::to_range() const
|
||||||
|
@ -150,13 +160,17 @@ std::pair<std::string, row_t> cell_reference::split_reference(const std::string
|
||||||
|
|
||||||
cell_reference cell_reference::make_offset(int column_offset, int row_offset) const
|
cell_reference cell_reference::make_offset(int column_offset, int row_offset) const
|
||||||
{
|
{
|
||||||
|
//TODO: check for overflow/underflow
|
||||||
return cell_reference(static_cast<column_t>(static_cast<int>(column_) + column_offset),
|
return cell_reference(static_cast<column_t>(static_cast<int>(column_) + column_offset),
|
||||||
static_cast<row_t>(static_cast<int>(row_) + row_offset));
|
static_cast<row_t>(static_cast<int>(row_) + row_offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cell_reference::operator==(const cell_reference &comparand) const
|
bool cell_reference::operator==(const cell_reference &comparand) const
|
||||||
{
|
{
|
||||||
return comparand.column_ == column_ && comparand.row_ == row_ && absolute_ == comparand.absolute_;
|
return comparand.column_ == column_ &&
|
||||||
|
comparand.row_ == row_ &&
|
||||||
|
absolute_column_ == comparand.absolute_column_ &&
|
||||||
|
absolute_row_ == comparand.absolute_row_;
|
||||||
}
|
}
|
||||||
|
|
||||||
column_t cell_reference::column_index_from_string(const std::string &column_string)
|
column_t cell_reference::column_index_from_string(const std::string &column_string)
|
||||||
|
|
|
@ -7,8 +7,8 @@ namespace xlnt {
|
||||||
range_reference range_reference::make_absolute(const xlnt::range_reference &relative_reference)
|
range_reference range_reference::make_absolute(const xlnt::range_reference &relative_reference)
|
||||||
{
|
{
|
||||||
range_reference copy = relative_reference;
|
range_reference copy = relative_reference;
|
||||||
copy.top_left_.set_absolute(true);
|
copy.top_left_.make_absolute(true, true);
|
||||||
copy.bottom_right_.set_absolute(true);
|
copy.bottom_right_.make_absolute(true, true);
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user