mirror of
https://github.com/tfussell/xlnt.git
synced 2024-03-22 13:11:17 +08:00
finish documenting all classes in cell module and clean up their APIs
This commit is contained in:
parent
d2d669d6c5
commit
7ec6e2d4df
|
@ -140,8 +140,7 @@ class cell
|
|||
|
||||
// position
|
||||
cell_reference get_reference() const;
|
||||
std::string get_column() const;
|
||||
column_t get_column_index() const;
|
||||
column_t get_column() const;
|
||||
row_t get_row() const;
|
||||
std::pair<int, int> get_anchor() const;
|
||||
|
||||
|
@ -203,7 +202,7 @@ class cell
|
|||
std::string get_error() const;
|
||||
void set_error(const std::string &error);
|
||||
|
||||
cell offset(row_t row, column_t column);
|
||||
cell offset(int column, int row);
|
||||
|
||||
worksheet get_parent();
|
||||
const worksheet get_parent() const;
|
||||
|
|
|
@ -52,26 +52,6 @@ struct cell_reference_hash
|
|||
class cell_reference
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Convert a column letter into a column number (e.g. B -> 2)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 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.
|
||||
/// Strings outside this range and malformed strings will throw xlnt::column_string_index_exception.
|
||||
/// </remarks>
|
||||
static column_t column_index_from_string(const std::string &column_string);
|
||||
|
||||
/// <summary>
|
||||
/// Convert a column number into a column letter (3 -> 'C')
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Right shift the column, column_index, by 26 to find column letters in reverse
|
||||
/// order. These indices are 1-based, and can be converted to ASCII
|
||||
/// ordinals by adding 64.
|
||||
/// </remarks>
|
||||
static std::string column_string_from_index(column_t column_index);
|
||||
|
||||
/// <summary>
|
||||
/// Split a coordinate string like "A1" into an equivalent pair like {"A", 1}.
|
||||
/// </summary>
|
||||
|
@ -173,9 +153,9 @@ class cell_reference
|
|||
/// Return a string that identifies the column of this reference
|
||||
/// (e.g. second column from left is "B")
|
||||
/// </summary>
|
||||
std::string get_column() const
|
||||
column_t get_column() const
|
||||
{
|
||||
return column_string_from_index(column_);
|
||||
return column_;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -183,7 +163,7 @@ class cell_reference
|
|||
/// </summary>
|
||||
void set_column(const std::string &column_string)
|
||||
{
|
||||
column_ = column_index_from_string(column_string);
|
||||
column_ = column_t(column_string);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -5,12 +5,7 @@
|
|||
namespace xlnt {
|
||||
|
||||
class cell;
|
||||
|
||||
namespace detail {
|
||||
|
||||
struct comment_impl;
|
||||
|
||||
} // namespace detail
|
||||
namespace detail { struct comment_impl; }
|
||||
|
||||
/// <summary>
|
||||
/// A comment can be applied to a cell to provide extra information.
|
||||
|
@ -22,22 +17,45 @@ class comment
|
|||
/// The default constructor makes an invalid comment without a parent cell.
|
||||
/// </summary>
|
||||
comment();
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a comment applied to the given cell, parent, and with the comment
|
||||
/// text and author set to the provided respective values.
|
||||
comment(cell parent, const std::string &text, const std::string &auth);
|
||||
|
||||
~comment();
|
||||
|
||||
/// <summary>
|
||||
/// Return the text that will be displayed for this comment.
|
||||
/// </summary>
|
||||
std::string get_text() const;
|
||||
|
||||
/// <summary>
|
||||
/// Return the author of this comment.
|
||||
/// </summary>
|
||||
std::string get_author() const;
|
||||
|
||||
/// <summary>
|
||||
/// True if the comments point to the same sell.
|
||||
/// Note that a cell can only have one comment and a comment
|
||||
/// True if the comments point to the same sell (false if
|
||||
/// they are different cells but identical comments). Note
|
||||
/// that a cell can only have one comment and a comment
|
||||
/// can only be applied to one cell.
|
||||
/// </summary>
|
||||
bool operator==(const comment &other) const;
|
||||
|
||||
private:
|
||||
friend class cell;
|
||||
friend class cell; // cell needs access to private constructor
|
||||
|
||||
/// <summary>
|
||||
/// Construct a comment from an implementation of a comment.
|
||||
/// </summary>
|
||||
comment(detail::comment_impl *d);
|
||||
|
||||
/// <summary>
|
||||
/// Pointer to the implementation of this comment.
|
||||
/// This allows comments to be passed by value while
|
||||
/// retaining the ability to modify the parent cell.
|
||||
/// </summary>
|
||||
detail::comment_impl *d_;
|
||||
};
|
||||
|
||||
|
|
|
@ -22,10 +22,317 @@
|
|||
// @author: see AUTHORS file
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
// We might want to change these types for various optimizations in the future
|
||||
// so use typedefs.
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
/// <summary>
|
||||
/// All rows should be referred to by an instance of this type.
|
||||
/// </summary>
|
||||
using row_t = std::uint32_t;
|
||||
using column_t = std::uint32_t;
|
||||
|
||||
/// <summary>
|
||||
/// Columns can be referred to as a string A,B,...Z,AA,AB,..,ZZ,AAA,...,ZZZ
|
||||
/// or as a 1-indexed index. This class encapsulates both of these forms of
|
||||
/// column referencing and allows for convertions between them.
|
||||
/// </summary>
|
||||
class column_t
|
||||
{
|
||||
public:
|
||||
using index_t = std::uint32_t;
|
||||
|
||||
/// <summary>
|
||||
/// Convert a column letter into a column number (e.g. B -> 2)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 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.
|
||||
/// Strings outside this range and malformed strings will throw xlnt::column_string_index_exception.
|
||||
/// </remarks>
|
||||
static index_t column_index_from_string(const std::string &column_string);
|
||||
|
||||
/// <summary>
|
||||
/// Convert a column number into a column letter (3 -> 'C')
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Right shift the column, column_index, by 26 to find column letters in reverse
|
||||
/// order. These indices are 1-based, and can be converted to ASCII
|
||||
/// ordinals by adding 64.
|
||||
/// </remarks>
|
||||
static std::string column_string_from_index(index_t column_index);
|
||||
|
||||
/// <summary>
|
||||
/// Default column_t is the first (left-most) column.
|
||||
/// </summary>
|
||||
column_t() : index(1) {}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a column from a number.
|
||||
/// </summary>
|
||||
column_t(index_t column_index) : index(column_index) {}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a column from a string.
|
||||
/// </summary>
|
||||
explicit column_t(const std::string &column_string) : index(column_index_from_string(column_string)) {}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a column from a string.
|
||||
/// </summary>
|
||||
explicit column_t(const char *column_string) : column_t(std::string(column_string)) {}
|
||||
|
||||
/// <summary>
|
||||
/// Copy constructor
|
||||
/// </summary>
|
||||
column_t(const column_t &other) : column_t(other.index) {}
|
||||
|
||||
/// <summary>
|
||||
/// Move constructor
|
||||
/// </summary>
|
||||
column_t(column_t &&other) { swap(*this, other); }
|
||||
|
||||
/// <summary>
|
||||
/// Return a string representation of this column index.
|
||||
/// </summary>
|
||||
std::string column_string() const { return column_string_from_index(index); }
|
||||
|
||||
/// <summary>
|
||||
/// Set this column to be the same as rhs's and return reference to self.
|
||||
/// </summary>
|
||||
column_t &operator=(column_t rhs) { swap(*this, rhs); return *this; }
|
||||
|
||||
/// <summary>
|
||||
/// Set this column to be equal to rhs and return reference to self.
|
||||
/// </summary>
|
||||
column_t &operator=(const std::string &rhs) { return *this = column_t(rhs); }
|
||||
|
||||
/// <summary>
|
||||
/// Set this column to be equal to rhs and return reference to self.
|
||||
/// </summary>
|
||||
column_t &operator=(const char *rhs) { return *this = column_t(rhs); }
|
||||
|
||||
/// <summary>
|
||||
/// Return true if this column refers to the same column as other.
|
||||
/// </summary>
|
||||
bool operator==(const column_t &other) const { return index == other.index; }
|
||||
|
||||
/// <summary>
|
||||
/// Return true if this column doesn't refer to the same column as other.
|
||||
/// </summary>
|
||||
bool operator!=(const column_t &other) const { return !(*this == other); }
|
||||
|
||||
/// <summary>
|
||||
/// Return true if this column refers to the same column as other.
|
||||
/// </summary>
|
||||
bool operator==(int other) const { return *this == column_t(other); }
|
||||
|
||||
/// <summary>
|
||||
/// Return true if this column refers to the same column as other.
|
||||
/// </summary>
|
||||
bool operator==(index_t other) const { return *this == column_t(other); }
|
||||
|
||||
/// <summary>
|
||||
/// Return true if this column refers to the same column as other.
|
||||
/// </summary>
|
||||
bool operator==(const std::string &other) const { return *this == column_t(other); }
|
||||
|
||||
/// <summary>
|
||||
/// Return true if this column refers to the same column as other.
|
||||
/// </summary>
|
||||
bool operator==(const char *other) const { return *this == column_t(other); }
|
||||
|
||||
/// <summary>
|
||||
/// Return true if this column doesn't refer to the same column as other.
|
||||
/// </summary>
|
||||
bool operator!=(int other) const { return !(*this == other); }
|
||||
|
||||
/// <summary>
|
||||
/// Return true if this column doesn't refer to the same column as other.
|
||||
/// </summary>
|
||||
bool operator!=(index_t other) const { return !(*this == other); }
|
||||
|
||||
/// <summary>
|
||||
/// Return true if this column doesn't refer to the same column as other.
|
||||
/// </summary>
|
||||
bool operator!=(const std::string &other) const { return !(*this == other); }
|
||||
|
||||
/// <summary>
|
||||
/// Return true if this column doesn't refer to the same column as other.
|
||||
/// </summary>
|
||||
bool operator!=(const char *other) const { return !(*this == other); }
|
||||
|
||||
/// <summary>
|
||||
/// Return true if other is to the right of this column.
|
||||
/// </summary>
|
||||
bool operator>(const column_t &other) const { return index > other.index; }
|
||||
|
||||
/// <summary>
|
||||
/// Return true if other is to the right of or equal to this column.
|
||||
/// </summary>
|
||||
bool operator>=(const column_t &other) const { return index >= other.index; }
|
||||
|
||||
/// <summary>
|
||||
/// Return true if other is to the left of this column.
|
||||
/// </summary>
|
||||
bool operator<(const column_t &other) const { return index < other.index; }
|
||||
|
||||
/// <summary>
|
||||
/// Return true if other is to the left of or equal to this column.
|
||||
/// </summary>
|
||||
bool operator<=(const column_t &other) const { return index <= other.index; }
|
||||
|
||||
/// <summary>
|
||||
/// Return true if other is to the right of this column.
|
||||
/// </summary>
|
||||
bool operator>(const column_t::index_t &other) const { return index > other; }
|
||||
|
||||
/// <summary>
|
||||
/// Return true if other is to the right of or equal to this column.
|
||||
/// </summary>
|
||||
bool operator>=(const column_t::index_t &other) const { return index >= other; }
|
||||
|
||||
/// <summary>
|
||||
/// Return true if other is to the left of this column.
|
||||
/// </summary>
|
||||
bool operator<(const column_t::index_t &other) const { return index < other; }
|
||||
|
||||
/// <summary>
|
||||
/// Return true if other is to the left of or equal to this column.
|
||||
/// </summary>
|
||||
bool operator<=(const column_t::index_t &other) const { return index <= other; }
|
||||
|
||||
/// <summary>
|
||||
/// Pre-increment this column, making it point to the column one to the right.
|
||||
/// </summary>
|
||||
column_t &operator++() { index++; return *this; }
|
||||
|
||||
/// <summary>
|
||||
/// Pre-deccrement this column, making it point to the column one to the left.
|
||||
/// </summary>
|
||||
column_t &operator--() { index--; return *this; }
|
||||
|
||||
/// <summary>
|
||||
/// Post-increment this column, making it point to the column one to the right and returning the old column.
|
||||
/// </summary>
|
||||
column_t operator++(int) { column_t copy(index); ++(*this); return copy; }
|
||||
|
||||
/// <summary>
|
||||
/// Post-decrement this column, making it point to the column one to the left and returning the old column.
|
||||
/// </summary>
|
||||
column_t operator--(int) { column_t copy(index); --(*this); return copy; }
|
||||
|
||||
/// <summary>
|
||||
/// Return the result of adding rhs to this column.
|
||||
/// </summary>
|
||||
column_t operator+(const column_t &rhs) { column_t copy(*this); copy.index += rhs.index; return copy; }
|
||||
|
||||
/// <summary>
|
||||
/// Return the result of adding rhs to this column.
|
||||
/// </summary>
|
||||
column_t operator-(const column_t &rhs) { column_t copy(*this); copy.index -= rhs.index; return copy; }
|
||||
|
||||
/// <summary>
|
||||
/// Return the result of adding rhs to this column.
|
||||
/// </summary>
|
||||
column_t operator*(const column_t &rhs) { column_t copy(*this); copy.index *= rhs.index; return copy; }
|
||||
|
||||
/// <summary>
|
||||
/// Return the result of adding rhs to this column.
|
||||
/// </summary>
|
||||
column_t operator/(const column_t &rhs) { column_t copy(*this); copy.index /= rhs.index; return copy; }
|
||||
|
||||
/// <summary>
|
||||
/// Return the result of adding rhs to this column.
|
||||
/// </summary>
|
||||
column_t operator%(const column_t &rhs) { column_t copy(*this); copy.index %= rhs.index; return copy; }
|
||||
|
||||
/// <summary>
|
||||
/// Add rhs to this column and return a reference to this column.
|
||||
/// </summary>
|
||||
column_t &operator+=(const column_t &rhs) { return *this = (*this + rhs); }
|
||||
|
||||
/// <summary>
|
||||
/// Subtrac rhs from this column and return a reference to this column.
|
||||
/// </summary>
|
||||
column_t &operator-=(const column_t &rhs) { return *this = (*this - rhs); }
|
||||
|
||||
/// <summary>
|
||||
/// Multiply this column by rhs and return a reference to this column.
|
||||
/// </summary>
|
||||
column_t &operator*=(const column_t &rhs) { return *this = (*this * rhs); }
|
||||
|
||||
/// <summary>
|
||||
/// Divide this column by rhs and return a reference to this column.
|
||||
/// </summary>
|
||||
column_t &operator/=(const column_t &rhs) { return *this = (*this / rhs); }
|
||||
|
||||
/// <summary>
|
||||
/// Mod this column by rhs and return a reference to this column.
|
||||
/// </summary>
|
||||
column_t &operator%=(const column_t &rhs) { return *this = (*this % rhs); }
|
||||
|
||||
/// <summary>
|
||||
/// Return true if other is to the right of this column.
|
||||
/// </summary>
|
||||
friend bool operator>(const column_t::index_t &left, const column_t &right) { return column_t(left) > right; }
|
||||
|
||||
/// <summary>
|
||||
/// Return true if other is to the right of or equal to this column.
|
||||
/// </summary>
|
||||
friend bool operator>=(const column_t::index_t &left, const column_t &right) { return column_t(left) >= right; }
|
||||
|
||||
/// <summary>
|
||||
/// Return true if other is to the left of this column.
|
||||
/// </summary>
|
||||
friend bool operator<(const column_t::index_t &left, const column_t &right) { return column_t(left) < right; }
|
||||
|
||||
/// <summary>
|
||||
/// Return true if other is to the left of or equal to this column.
|
||||
/// </summary>
|
||||
friend bool operator<=(const column_t::index_t &left, const column_t &right) { return column_t(left) <= right; }
|
||||
|
||||
/// <summary>
|
||||
/// Swap the columns that left and right refer to.
|
||||
/// </summary>
|
||||
friend void swap(column_t &left, column_t &right)
|
||||
{
|
||||
using std::swap;
|
||||
swap(left.index, right.index);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal numeric value of this column index.
|
||||
/// </summary>
|
||||
index_t index;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Functor for hashing a cell reference.
|
||||
/// Allows for use of std::unordered_set<cell_reference, cel_reference_hash> and similar.
|
||||
/// </summary>
|
||||
struct column_hash
|
||||
{
|
||||
std::size_t operator()(const column_t &k) const;
|
||||
};
|
||||
|
||||
} // namespace xlnt
|
||||
|
||||
namespace std {
|
||||
|
||||
template <>
|
||||
struct hash<xlnt::column_t>
|
||||
{
|
||||
size_t operator()(const xlnt::column_t &k) const
|
||||
{
|
||||
return hasher(k);
|
||||
}
|
||||
|
||||
xlnt::column_hash hasher;
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
|
|
|
@ -44,4 +44,5 @@ enum class limit_style
|
|||
/// See limit_style for more information.
|
||||
/// </summary>
|
||||
const limit_style LimitStyle = limit_style::openpyxl;
|
||||
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace xlnt {
|
|||
class cell_coordinates_exception : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
cell_coordinates_exception(row_t row, column_t column);
|
||||
cell_coordinates_exception(column_t column, row_t row);
|
||||
cell_coordinates_exception(const std::string &coord_string);
|
||||
};
|
||||
|
||||
|
|
|
@ -42,8 +42,11 @@ class range_reference
|
|||
range_reference(column_t column_index_start, row_t row_index_start, column_t column_index_end, row_t row_index_end);
|
||||
|
||||
bool is_single_cell() const;
|
||||
column_t get_width() const;
|
||||
row_t get_height() const;
|
||||
|
||||
std::size_t get_width() const;
|
||||
|
||||
std::size_t get_height() const;
|
||||
|
||||
cell_reference get_top_left() const
|
||||
{
|
||||
return top_left_;
|
||||
|
|
|
@ -992,9 +992,9 @@ row_t cell::get_row() const
|
|||
return d_->row_;
|
||||
}
|
||||
|
||||
std::string cell::get_column() const
|
||||
column_t cell::get_column() const
|
||||
{
|
||||
return cell_reference::column_string_from_index(d_->column_);
|
||||
return d_->column_;
|
||||
}
|
||||
|
||||
void cell::set_merged(bool merged)
|
||||
|
@ -1170,7 +1170,7 @@ void cell::set_error(const std::string &error)
|
|||
d_->type_ = type::error;
|
||||
}
|
||||
|
||||
cell cell::offset(column_t column, row_t row)
|
||||
cell cell::offset(int column, int row)
|
||||
{
|
||||
return get_parent().get_cell(cell_reference(d_->column_ + column, d_->row_ + row));
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace xlnt {
|
|||
|
||||
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().index + k.get_column_index().index;
|
||||
}
|
||||
|
||||
cell_reference &cell_reference::make_absolute(bool absolute_column, bool absolute_row)
|
||||
|
@ -39,14 +39,14 @@ cell_reference::cell_reference(const char *reference_string)
|
|||
}
|
||||
|
||||
cell_reference::cell_reference(const std::string &column, row_t row)
|
||||
: cell_reference(column_index_from_string(column), row)
|
||||
: cell_reference(column_t(column), row)
|
||||
{
|
||||
}
|
||||
|
||||
cell_reference::cell_reference(column_t column_index, row_t row)
|
||||
: column_(column_index), row_(row), absolute_column_(false), absolute_row_(false)
|
||||
: column_(column_index), row_(row), absolute_row_(false), absolute_column_(false)
|
||||
{
|
||||
if (row_ == 0 || row_ >= constants::MaxRow || column_ == 0 || column_ >= constants::MaxColumn)
|
||||
if (row_ == 0 || !(row_ <= constants::MaxRow()) || column_ == 0 || !(column_ <= constants::MaxColumn()))
|
||||
{
|
||||
throw cell_coordinates_exception(column_, row_);
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ std::string cell_reference::to_string() const
|
|||
string_representation.append("$");
|
||||
}
|
||||
|
||||
string_representation.append(column_string_from_index(column_));
|
||||
string_representation.append(column_.column_string());
|
||||
|
||||
if (absolute_row_)
|
||||
{
|
||||
|
@ -161,7 +161,7 @@ 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
|
||||
{
|
||||
//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_.index) + column_offset),
|
||||
static_cast<row_t>(static_cast<int>(row_) + row_offset));
|
||||
}
|
||||
|
||||
|
@ -173,66 +173,6 @@ bool cell_reference::operator==(const cell_reference &comparand) const
|
|||
absolute_row_ == comparand.absolute_row_;
|
||||
}
|
||||
|
||||
column_t cell_reference::column_index_from_string(const std::string &column_string)
|
||||
{
|
||||
if (column_string.length() > 3 || column_string.empty())
|
||||
{
|
||||
throw column_string_index_exception();
|
||||
}
|
||||
|
||||
column_t column_index = 0;
|
||||
int place = 1;
|
||||
|
||||
for (int i = static_cast<int>(column_string.length()) - 1; i >= 0; i--)
|
||||
{
|
||||
if (!std::isalpha(column_string[static_cast<std::size_t>(i)], std::locale::classic()))
|
||||
{
|
||||
throw column_string_index_exception();
|
||||
}
|
||||
|
||||
column_index += static_cast<column_t>(
|
||||
(std::toupper(column_string[static_cast<std::size_t>(i)], std::locale::classic()) - 'A' + 1) * place);
|
||||
place *= 26;
|
||||
}
|
||||
|
||||
return column_index;
|
||||
}
|
||||
|
||||
// Convert a column number into a column letter (3 -> 'C')
|
||||
// Right shift the column col_idx by 26 to find column letters in reverse
|
||||
// order.These numbers are 1 - based, and can be converted to ASCII
|
||||
// ordinals by adding 64.
|
||||
std::string cell_reference::column_string_from_index(column_t column_index)
|
||||
{
|
||||
// these indicies corrospond to A->ZZZ and include all allowed
|
||||
// columns
|
||||
if (column_index < 1 || column_index > constants::MaxColumn)
|
||||
{
|
||||
// auto msg = "Column index out of bounds: " + std::to_string(column_index);
|
||||
throw column_string_index_exception();
|
||||
}
|
||||
|
||||
int temp = static_cast<int>(column_index);
|
||||
std::string column_letter = "";
|
||||
|
||||
while (temp > 0)
|
||||
{
|
||||
int quotient = temp / 26, remainder = temp % 26;
|
||||
|
||||
// check for exact division and borrow if needed
|
||||
if (remainder == 0)
|
||||
{
|
||||
quotient -= 1;
|
||||
remainder = 26;
|
||||
}
|
||||
|
||||
column_letter = std::string(1, char(remainder + 64)) + column_letter;
|
||||
temp = quotient;
|
||||
}
|
||||
|
||||
return column_letter;
|
||||
}
|
||||
|
||||
bool cell_reference::operator<(const cell_reference &other)
|
||||
{
|
||||
if (row_ != other.row_)
|
||||
|
|
77
source/cell/types.cpp
Normal file
77
source/cell/types.cpp
Normal file
|
@ -0,0 +1,77 @@
|
|||
#include <locale>
|
||||
|
||||
#include <xlnt/cell/types.hpp>
|
||||
#include <xlnt/utils/exceptions.hpp>
|
||||
|
||||
#include <detail/constants.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
column_t::index_t column_t::column_index_from_string(const std::string &column_string)
|
||||
{
|
||||
if (column_string.length() > 3 || column_string.empty())
|
||||
{
|
||||
throw column_string_index_exception();
|
||||
}
|
||||
|
||||
column_t::index_t column_index = 0;
|
||||
int place = 1;
|
||||
|
||||
for (int i = static_cast<int>(column_string.length()) - 1; i >= 0; i--)
|
||||
{
|
||||
if (!std::isalpha(column_string[static_cast<std::size_t>(i)], std::locale::classic()))
|
||||
{
|
||||
throw column_string_index_exception();
|
||||
}
|
||||
|
||||
auto char_index = std::toupper(column_string[static_cast<std::size_t>(i)], std::locale::classic()) - 'A';
|
||||
|
||||
column_index += static_cast<column_t::index_t>((char_index + 1) * place);
|
||||
place *= 26;
|
||||
}
|
||||
|
||||
return column_index;
|
||||
}
|
||||
|
||||
// Convert a column number into a column letter (3 -> 'C')
|
||||
// Right shift the column col_idx by 26 to find column letters in reverse
|
||||
// order.These numbers are 1 - based, and can be converted to ASCII
|
||||
// ordinals by adding 64.
|
||||
std::string column_t::column_string_from_index(column_t::index_t column_index)
|
||||
{
|
||||
// these indicies corrospond to A->ZZZ and include all allowed
|
||||
// columns
|
||||
if (column_index < constants::MinColumn() || column_index > constants::MaxColumn())
|
||||
{
|
||||
// auto msg = "Column index out of bounds: " + std::to_string(column_index);
|
||||
throw column_string_index_exception();
|
||||
}
|
||||
|
||||
int temp = static_cast<int>(column_index);
|
||||
std::string column_letter = "";
|
||||
|
||||
while (temp > 0)
|
||||
{
|
||||
int quotient = temp / 26, remainder = temp % 26;
|
||||
|
||||
// check for exact division and borrow if needed
|
||||
if (remainder == 0)
|
||||
{
|
||||
quotient -= 1;
|
||||
remainder = 26;
|
||||
}
|
||||
|
||||
column_letter = std::string(1, char(remainder + 64)) + column_letter;
|
||||
temp = quotient;
|
||||
}
|
||||
|
||||
return column_letter;
|
||||
}
|
||||
|
||||
std::size_t column_hash::operator()(const column_t &k) const
|
||||
{
|
||||
static std::hash<column_t::index_t> hasher;
|
||||
return hasher(k.index);
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
|
@ -6,7 +6,7 @@
|
|||
namespace xlnt {
|
||||
namespace detail {
|
||||
|
||||
cell_impl::cell_impl() : cell_impl(1, 1)
|
||||
cell_impl::cell_impl() : cell_impl(column_t(1), 1)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -6,11 +6,40 @@
|
|||
|
||||
namespace xlnt {
|
||||
|
||||
const row_t constants::MinRow = 1;
|
||||
const row_t constants::MaxRow = LimitStyle == limit_style::excel ? (1u << 20) : UINT32_MAX;
|
||||
const column_t constants::MinColumn = 1;
|
||||
const column_t constants::MaxColumn =
|
||||
LimitStyle == limit_style::excel ? (1u << 14) : LimitStyle == limit_style::openpyxl ? 18278 : UINT32_MAX;
|
||||
const row_t constants::MinRow()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
const row_t constants::MaxRow()
|
||||
{
|
||||
if(LimitStyle == limit_style::excel)
|
||||
{
|
||||
return 1u << 20;
|
||||
}
|
||||
|
||||
return std::numeric_limits<row_t>::max();
|
||||
}
|
||||
|
||||
const column_t constants::MinColumn()
|
||||
{
|
||||
return column_t(1);
|
||||
}
|
||||
|
||||
const column_t constants::MaxColumn()
|
||||
{
|
||||
if(LimitStyle == limit_style::excel)
|
||||
{
|
||||
return column_t(1u << 14);
|
||||
}
|
||||
|
||||
if(LimitStyle == limit_style::openpyxl)
|
||||
{
|
||||
return column_t(18278);
|
||||
}
|
||||
|
||||
return column_t(std::numeric_limits<column_t::index_t>::max());
|
||||
}
|
||||
|
||||
// constants
|
||||
const std::string constants::PackageProps() { return "docProps"; }
|
||||
|
|
|
@ -9,10 +9,10 @@ namespace xlnt {
|
|||
|
||||
struct constants
|
||||
{
|
||||
static const row_t MinRow;
|
||||
static const row_t MaxRow;
|
||||
static const column_t MinColumn;
|
||||
static const column_t MaxColumn;
|
||||
static const row_t MinRow();
|
||||
static const row_t MaxRow();
|
||||
static const column_t MinColumn();
|
||||
static const column_t MaxColumn();
|
||||
|
||||
// constants
|
||||
static const std::string PackageProps();
|
||||
|
|
|
@ -96,7 +96,7 @@ bool worksheet_serializer::read_worksheet(const xml_document &xml)
|
|||
|
||||
for (column_t i = min_column; i <= max_column; i++)
|
||||
{
|
||||
std::string address = xlnt::cell_reference::column_string_from_index(i) + std::to_string(row_index);
|
||||
std::string address = i.column_string() + std::to_string(row_index);
|
||||
|
||||
xml_node cell_node;
|
||||
bool cell_found = false;
|
||||
|
@ -253,7 +253,7 @@ xml_document worksheet_serializer::write_worksheet() const
|
|||
|
||||
if (sheet_.get_frozen_panes().get_column_index() > 1)
|
||||
{
|
||||
pane_node.add_attribute("xSplit", std::to_string(sheet_.get_frozen_panes().get_column_index() - 1));
|
||||
pane_node.add_attribute("xSplit", std::to_string(sheet_.get_frozen_panes().get_column_index().index - 1));
|
||||
active_pane = "topRight";
|
||||
}
|
||||
|
||||
|
@ -329,8 +329,8 @@ xml_document worksheet_serializer::write_worksheet() const
|
|||
|
||||
auto col_node = cols_node.add_child("col");
|
||||
|
||||
col_node.add_attribute("min", std::to_string(column));
|
||||
col_node.add_attribute("max", std::to_string(column));
|
||||
col_node.add_attribute("min", std::to_string(column.index));
|
||||
col_node.add_attribute("max", std::to_string(column.index));
|
||||
col_node.add_attribute("width", std::to_string(props.width));
|
||||
col_node.add_attribute("style", std::to_string(props.style));
|
||||
col_node.add_attribute("customWidth", props.custom ? "1" : "0");
|
||||
|
@ -350,8 +350,8 @@ xml_document worksheet_serializer::write_worksheet() const
|
|||
|
||||
for (auto cell : row)
|
||||
{
|
||||
min = std::min(min, cell_reference::column_index_from_string(cell.get_column()));
|
||||
max = std::max(max, cell_reference::column_index_from_string(cell.get_column()));
|
||||
min = std::min(min, cell.get_column().index);
|
||||
max = std::max(max, cell.get_column().index);
|
||||
|
||||
if (!cell.garbage_collectible())
|
||||
{
|
||||
|
|
|
@ -29,14 +29,14 @@ invalid_file_exception::invalid_file_exception(const std::string &filename)
|
|||
{
|
||||
}
|
||||
|
||||
cell_coordinates_exception::cell_coordinates_exception(row_t row, column_t column)
|
||||
: std::runtime_error(std::string("bad cell coordinates: (") + std::to_string(row) + "," + std::to_string(column) +
|
||||
cell_coordinates_exception::cell_coordinates_exception(column_t column, row_t row)
|
||||
: std::runtime_error(std::string("bad cell coordinates: (") + std::to_string(column.index) + ", " + std::to_string(row) +
|
||||
")")
|
||||
{
|
||||
}
|
||||
|
||||
cell_coordinates_exception::cell_coordinates_exception(const std::string &coord_string)
|
||||
: std::runtime_error(std::string("bad cell coordinates: (") + coord_string + ")")
|
||||
: std::runtime_error(std::string("bad cell coordinates: (") + (coord_string.empty() ? "<empty>" : coord_string) + ")")
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -73,7 +73,7 @@ cell cell_vector::front()
|
|||
{
|
||||
if (order_ == major_order::row)
|
||||
{
|
||||
return get_cell(ref_.get_top_left().get_column_index());
|
||||
return get_cell(ref_.get_top_left().get_column().index);
|
||||
}
|
||||
|
||||
return get_cell(ref_.get_top_left().get_row());
|
||||
|
@ -83,7 +83,7 @@ cell cell_vector::back()
|
|||
{
|
||||
if (order_ == major_order::row)
|
||||
{
|
||||
return get_cell(ref_.get_bottom_right().get_column_index());
|
||||
return get_cell(ref_.get_bottom_right().get_column().index);
|
||||
}
|
||||
|
||||
return get_cell(ref_.get_top_left().get_row());
|
||||
|
@ -125,7 +125,7 @@ std::size_t range::length() const
|
|||
return ref_.get_bottom_right().get_row() - ref_.get_top_left().get_row() + 1;
|
||||
}
|
||||
|
||||
return ref_.get_bottom_right().get_column_index() - ref_.get_top_left().get_column_index() + 1;
|
||||
return (ref_.get_bottom_right().get_column() - ref_.get_top_left().get_column()).index + 1;
|
||||
}
|
||||
|
||||
bool range::operator==(const range &comparand) const
|
||||
|
@ -147,9 +147,9 @@ cell_vector range::get_vector(std::size_t vector_index)
|
|||
}
|
||||
|
||||
range_reference reference(
|
||||
static_cast<column_t>(static_cast<std::size_t>(ref_.get_top_left().get_column_index()) + vector_index),
|
||||
static_cast<column_t>(static_cast<std::size_t>(ref_.get_top_left().get_column().index) + vector_index),
|
||||
ref_.get_top_left().get_row(),
|
||||
static_cast<column_t>(static_cast<std::size_t>(ref_.get_top_left().get_column_index()) + vector_index),
|
||||
static_cast<column_t>(static_cast<std::size_t>(ref_.get_top_left().get_column().index) + vector_index),
|
||||
ref_.get_bottom_right().get_row());
|
||||
|
||||
return cell_vector(ws_, reference, order_);
|
||||
|
@ -164,7 +164,7 @@ bool range::contains(const cell_reference &ref)
|
|||
|
||||
cell range::get_cell(const cell_reference &ref)
|
||||
{
|
||||
return (*this)[ref.get_row()][ref.get_column_index()];
|
||||
return (*this)[ref.get_row()][ref.get_column().index];
|
||||
}
|
||||
|
||||
range::iterator range::begin()
|
||||
|
|
|
@ -53,14 +53,14 @@ range_reference range_reference::make_offset(int column_offset, int row_offset)
|
|||
bottom_right_.make_offset(column_offset, row_offset));
|
||||
}
|
||||
|
||||
row_t range_reference::get_height() const
|
||||
std::size_t range_reference::get_height() const
|
||||
{
|
||||
return bottom_right_.get_row() - top_left_.get_row();
|
||||
}
|
||||
|
||||
column_t range_reference::get_width() const
|
||||
std::size_t range_reference::get_width() const
|
||||
{
|
||||
return bottom_right_.get_column_index() - top_left_.get_column_index();
|
||||
return (bottom_right_.get_column() - top_left_.get_column()).index;
|
||||
}
|
||||
|
||||
bool range_reference::is_single_cell() const
|
||||
|
|
|
@ -62,8 +62,8 @@ public:
|
|||
|
||||
void test_iter_rows_1()
|
||||
{
|
||||
row_t row = 0;
|
||||
column_t column = 0;
|
||||
std::size_t row = 0;
|
||||
std::size_t column = 0;
|
||||
std::string coordinate = "A1";
|
||||
|
||||
xlnt::worksheet ws(wb_);
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <xlnt/worksheet/worksheet.hpp>
|
||||
|
||||
#include <detail/cell_impl.hpp>
|
||||
#include <detail/constants.hpp>
|
||||
#include <detail/worksheet_impl.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
|
@ -249,16 +250,16 @@ column_t worksheet::get_lowest_column() const
|
|||
{
|
||||
if (d_->cell_map_.empty())
|
||||
{
|
||||
return 1;
|
||||
return constants::MinColumn();
|
||||
}
|
||||
|
||||
column_t lowest = std::numeric_limits<column_t>::max();
|
||||
column_t lowest = constants::MaxColumn();
|
||||
|
||||
for (auto &row : d_->cell_map_)
|
||||
{
|
||||
for (auto &c : row.second)
|
||||
{
|
||||
lowest = std::min(lowest, (column_t)c.first);
|
||||
lowest = std::min(lowest, c.first);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -269,14 +270,14 @@ row_t worksheet::get_lowest_row() const
|
|||
{
|
||||
if (d_->cell_map_.empty())
|
||||
{
|
||||
return 1;
|
||||
return constants::MinRow();
|
||||
}
|
||||
|
||||
row_t lowest = std::numeric_limits<row_t>::max();
|
||||
row_t lowest = constants::MaxRow();
|
||||
|
||||
for (auto &row : d_->cell_map_)
|
||||
{
|
||||
lowest = std::min(lowest, (row_t)row.first);
|
||||
lowest = std::min(lowest, row.first);
|
||||
}
|
||||
|
||||
return lowest;
|
||||
|
@ -284,11 +285,11 @@ row_t worksheet::get_lowest_row() const
|
|||
|
||||
row_t worksheet::get_highest_row() const
|
||||
{
|
||||
row_t highest = 1;
|
||||
row_t highest = constants::MinRow();
|
||||
|
||||
for (auto &row : d_->cell_map_)
|
||||
{
|
||||
highest = std::max(highest, (row_t)row.first);
|
||||
highest = std::max(highest, row.first);
|
||||
}
|
||||
|
||||
return highest;
|
||||
|
@ -296,13 +297,13 @@ row_t worksheet::get_highest_row() const
|
|||
|
||||
column_t worksheet::get_highest_column() const
|
||||
{
|
||||
column_t highest = 1;
|
||||
column_t highest = constants::MinColumn();
|
||||
|
||||
for (auto &row : d_->cell_map_)
|
||||
{
|
||||
for (auto &c : row.second)
|
||||
{
|
||||
highest = std::max(highest, (column_t)c.first);
|
||||
highest = std::max(highest, c.first);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user