improve 1d and 2d cell iteration for #135, including making empty cell skipping optional

This commit is contained in:
Thomas Fussell 2017-03-23 20:05:25 -04:00
parent c7f61e38c1
commit 0d82aba640
18 changed files with 827 additions and 433 deletions

View File

@ -1393,59 +1393,107 @@ Post-increment the iterator's internal workseet index. Returns a copy of the ite
Pre-increment the iterator's internal workseet index. Returns a refernce to the same iterator.
## Worksheet Module
### cell_iterator
#### ```xlnt::cell_iterator::cell_iterator(worksheet ws, const cell_reference &start_cell, const range_reference &limits)```
#### ```xlnt::cell_iterator::cell_iterator(worksheet ws, const cell_reference &start_cell, const range_reference &limits, major_order order)```
#### ```xlnt::cell_iterator::cell_iterator(worksheet ws, const cell_reference &start_cell, const range_reference &limits, major_order order, bool skip_null, bool wrap)```
Constructs a cell_iterator from a worksheet, range, and iteration settings.
#### ```xlnt::cell_iterator::cell_iterator(const cell_iterator &other)```
Constructs a cell_iterator as a copy of an existing cell_iterator.
#### ```cell_iterator& xlnt::cell_iterator::operator=(const cell_iterator &rhs)=default```
Assigns this iterator to match the data in rhs.
#### ```cell xlnt::cell_iterator::operator*()```
#### ```cell_iterator& xlnt::cell_iterator::operator=(const cell_iterator &)=default```
Dereferences this iterator to return the cell it points to.
#### ```bool xlnt::cell_iterator::operator==(const cell_iterator &other) const```
Returns true if this iterator is equivalent to other.
#### ```bool xlnt::cell_iterator::operator!=(const cell_iterator &other) const```
Returns true if this iterator isn't equivalent to other.
#### ```cell_iterator& xlnt::cell_iterator::operator--()```
Pre-decrements the iterator to point to the previous cell and returns a reference to the iterator.
#### ```cell_iterator xlnt::cell_iterator::operator--(int)```
Post-decrements the iterator to point to the previous cell and return a copy of the iterator before the decrement.
#### ```cell_iterator& xlnt::cell_iterator::operator++()```
Pre-increments the iterator to point to the previous cell and returns a reference to the iterator.
#### ```cell_iterator xlnt::cell_iterator::operator++(int)```
Post-increments the iterator to point to the previous cell and return a copy of the iterator before the decrement.
### const_cell_iterator
#### ```xlnt::const_cell_iterator::const_cell_iterator(worksheet ws, const cell_reference &start_cell)```
#### ```xlnt::const_cell_iterator::const_cell_iterator(worksheet ws, const cell_reference &start_cell, major_order order)```
#### ```xlnt::const_cell_iterator::const_cell_iterator(worksheet ws, const cell_reference &start_cell, const range_reference &limits, major_order order, bool skip_null, bool wrap)```
Constructs a cell_iterator from a worksheet, range, and iteration settings.
#### ```xlnt::const_cell_iterator::const_cell_iterator(const const_cell_iterator &other)```
Constructs a cell_iterator as a copy of an existing cell_iterator.
#### ```const_cell_iterator& xlnt::const_cell_iterator::operator=(const const_cell_iterator &)=default```
Assigns this iterator to match the data in rhs.
#### ```const cell xlnt::const_cell_iterator::operator*() const```
Dereferences this iterator to return the cell it points to.
#### ```bool xlnt::const_cell_iterator::operator==(const const_cell_iterator &other) const```
Returns true if this iterator is equivalent to other.
#### ```bool xlnt::const_cell_iterator::operator!=(const const_cell_iterator &other) const```
Returns true if this iterator isn't equivalent to other.
#### ```const_cell_iterator& xlnt::const_cell_iterator::operator--()```
Pre-decrements the iterator to point to the previous cell and returns a reference to the iterator.
#### ```const_cell_iterator xlnt::const_cell_iterator::operator--(int)```
Post-decrements the iterator to point to the previous cell and return a copy of the iterator before the decrement.
#### ```const_cell_iterator& xlnt::const_cell_iterator::operator++()```
Pre-increments the iterator to point to the previous cell and returns a reference to the iterator.
#### ```const_cell_iterator xlnt::const_cell_iterator::operator++(int)```
Post-increments the iterator to point to the previous cell and return a copy of the iterator before the decrement.
### cell_vector
#### ```using xlnt::cell_vector::iterator = cell_iteratorundefined```
Iterate over cells in a cell_vector with an iterator of this type.
#### ```using xlnt::cell_vector::const_iterator = const_cell_iteratorundefined```
Iterate over const cells in a const cell_vector with an iterator of this type.
#### ```using xlnt::cell_vector::reverse_iterator = std::reverse_iterator<iterator>undefined```
Iterate over cells in a cell_vector in reverse oreder with an iterator of this type.
#### ```using xlnt::cell_vector::const_reverse_iterator = std::reverse_iterator<const_iterator>undefined```
#### ```xlnt::cell_vector::cell_vector(worksheet ws, const range_reference &ref, major_order order=major_order::row)```
Iterate over const cells in a const cell_vector in reverse order with an iterator of this type.
#### ```xlnt::cell_vector::cell_vector(worksheet ws, const cell_reference &cursor, const range_reference &ref, major_order order, bool skip_null, bool wrap)```
Constructs a cell vector pointing to a given range in a given worksheet. order determines whether this vector is a row or a column. If skip_null is true, iterating over this vector will skip empty cells.
#### ```bool xlnt::cell_vector::empty() const```
Returns true if every cell in this vector is null (i.e. the cell doesn't exist in the worksheet).
#### ```cell xlnt::cell_vector::front()```
Returns the first cell in this vector.
#### ```const cell xlnt::cell_vector::front() const```
Returns the first cell in this vector.
#### ```cell xlnt::cell_vector::back()```
Returns the last cell in this vector.
#### ```const cell xlnt::cell_vector::back() const```
#### ```cell xlnt::cell_vector::operator[](std::size_t column_index)```
#### ```const cell xlnt::cell_vector::operator[](std::size_t column_index) const```
Returns the last cell in this vector.
#### ```std::size_t xlnt::cell_vector::length() const```
Returns the distance between the first and last cells in this vector.
#### ```iterator xlnt::cell_vector::begin()```
Returns an iterator to the first cell in this vector.
#### ```iterator xlnt::cell_vector::end()```
Returns an iterator to a cell one-past-the-end of this vector.
#### ```const_iterator xlnt::cell_vector::begin() const```
Returns an iterator to the first cell in this vector.
#### ```const_iterator xlnt::cell_vector::cbegin() const```
Returns an iterator to the first cell in this vector.
#### ```const_iterator xlnt::cell_vector::end() const```
Returns an iterator to a cell one-past-the-end of this vector.
#### ```const_iterator xlnt::cell_vector::cend() const```
Returns an iterator to a cell one-past-the-end of this vector.
#### ```reverse_iterator xlnt::cell_vector::rbegin()```
Returns a reverse iterator to the first cell of this reversed vector.
#### ```reverse_iterator xlnt::cell_vector::rend()```
Returns a reverse iterator to to a cell one-past-the-end of this reversed vector.
#### ```const_reverse_iterator xlnt::cell_vector::rbegin() const```
Returns a reverse iterator to the first cell of this reversed vector.
#### ```const_reverse_iterator xlnt::cell_vector::rend() const```
Returns a reverse iterator to to a cell one-past-the-end of this reversed vector.
#### ```const_reverse_iterator xlnt::cell_vector::crbegin() const```
Returns a reverse iterator to the first cell of this reversed vector.
#### ```const_reverse_iterator xlnt::cell_vector::crend() const```
Returns a reverse iterator to to a cell one-past-the-end of this reversed vector.
#### ```cell xlnt::cell_vector::operator[](std::size_t column_index)```
Returns the cell column_index distance away from the first cell in this vector.
#### ```const cell xlnt::cell_vector::operator[](std::size_t column_index) const```
Returns the cell column_index distance away from the first cell in this vector.
### column_properties
#### ```optional<double> xlnt::column_properties::widthundefined```
The optional width of the column
#### ```bool xlnt::column_properties::custom_widthundefined```
If true, this is a custom width
#### ```optional<std::size_t> xlnt::column_properties::styleundefined```
The style index of this column. This shouldn't be used since style indices aren't supposed to be used directly in xlnt. (TODO)
#### ```bool xlnt::column_properties::hiddenundefined```
If true, this column will be hidden
### header_footer
#### ```undefinedundefined```
Enumerates the three possible locations of a header or footer.
@ -1543,18 +1591,31 @@ Get the text of the odd page footer at the given location. If no odd page footer
Get the text of the even page footer at the given location. If no even page footer has been set, the general footer for that location will be returned.
### page_margins
#### ```xlnt::page_margins::page_margins()```
Constructs a page margins objects with Excel-default margins.
#### ```double xlnt::page_margins::top() const```
Returns the top margin
#### ```void xlnt::page_margins::top(double top)```
Sets the top margin to top
#### ```double xlnt::page_margins::left() const```
Returns the left margin
#### ```void xlnt::page_margins::left(double left)```
Sets the left margin to left
#### ```double xlnt::page_margins::bottom() const```
Returns the bottom margin
#### ```void xlnt::page_margins::bottom(double bottom)```
Sets the bottom margin to bottom
#### ```double xlnt::page_margins::right() const```
Returns the right margin
#### ```void xlnt::page_margins::right(double right)```
Sets the right margin to right
#### ```double xlnt::page_margins::header() const```
Returns the header margin
#### ```void xlnt::page_margins::header(double header)```
Sets the header margin to header
#### ```double xlnt::page_margins::footer() const```
Returns the footer margin
#### ```void xlnt::page_margins::footer(double footer)```
Sets the footer margin to footer
### page_setup
#### ```xlnt::page_setup::page_setup()```
#### ```xlnt::page_break xlnt::page_setup::page_break() const```
@ -1614,6 +1675,10 @@ Returns true if this pane is equal to rhs based on its top-left cell, state, act
Sets the named style applied to all cells in this range to a style named style_name.
#### ```range xlnt::range::style(const std::string &style_name)```
Sets the named style applied to all cells in this range to a style named style_name. If this style has not been previously created in the workbook, a key_not_found exception will be thrown.
#### ```cell_vector xlnt::range::front()```
#### ```const cell_vector xlnt::range::front() const```
#### ```cell_vector xlnt::range::back()```
#### ```const cell_vector xlnt::range::back() const```
#### ```iterator xlnt::range::begin()```
#### ```iterator xlnt::range::end()```
#### ```const_iterator xlnt::range::begin() const```
@ -1628,7 +1693,7 @@ Sets the named style applied to all cells in this range to a style named style_n
#### ```const_reverse_iterator xlnt::range::crend() const```
#### ```void xlnt::range::apply(std::function< void(class cell)> f)```
### range_iterator
#### ```xlnt::range_iterator::range_iterator(worksheet &ws, const range_reference &start_cell, const range_reference &limits, major_order order=major_order::row)```
#### ```xlnt::range_iterator::range_iterator(worksheet &ws, const cell_reference &cursor, const range_reference &bounds, major_order order, bool skip_null)```
#### ```xlnt::range_iterator::range_iterator(const range_iterator &other)```
#### ```cell_vector xlnt::range_iterator::operator*() const```
#### ```range_iterator& xlnt::range_iterator::operator=(const range_iterator &)=default```
@ -1639,7 +1704,7 @@ Sets the named style applied to all cells in this range to a style named style_n
#### ```range_iterator& xlnt::range_iterator::operator++()```
#### ```range_iterator xlnt::range_iterator::operator++(int)```
### const_range_iterator
#### ```xlnt::const_range_iterator::const_range_iterator(const worksheet &ws, const range_reference &start_cell, major_order order=major_order::row)```
#### ```xlnt::const_range_iterator::const_range_iterator(const worksheet &ws, const cell_reference &cursor, const range_reference &bounds, major_order order, bool skip_null)```
#### ```xlnt::const_range_iterator::const_range_iterator(const const_range_iterator &other)```
#### ```const cell_vector xlnt::const_range_iterator::operator*() const```
#### ```const_range_iterator& xlnt::const_range_iterator::operator=(const const_range_iterator &)=default```
@ -1661,10 +1726,14 @@ Convert a coordinate to an absolute coordinate string (B12 -> $B$12)
#### ```bool xlnt::range_reference::is_single_cell() const```
#### ```std::size_t xlnt::range_reference::width() const```
#### ```std::size_t xlnt::range_reference::height() const```
#### ```cell_reference xlnt::range_reference::top_left()```
#### ```cell_reference xlnt::range_reference::top_left() const```
#### ```cell_reference xlnt::range_reference::top_right()```
#### ```cell_reference xlnt::range_reference::top_right() const```
#### ```cell_reference xlnt::range_reference::bottom_left()```
#### ```cell_reference xlnt::range_reference::bottom_left() const```
#### ```cell_reference xlnt::range_reference::bottom_right()```
#### ```cell_reference xlnt::range_reference::bottom_right() const```
#### ```cell_reference& xlnt::range_reference::top_left()```
#### ```cell_reference& xlnt::range_reference::bottom_right()```
#### ```range_reference xlnt::range_reference::make_offset(int column_offset, int row_offset) const```
#### ```std::string xlnt::range_reference::to_string() const```
#### ```bool xlnt::range_reference::operator==(const range_reference &comparand) const```
@ -1775,10 +1844,14 @@ Returns the range defined by reference string. If reference string is the name o
Returns the range defined by reference.
#### ```const class range xlnt::worksheet::range(const range_reference &reference) const```
Returns the range defined by reference.
#### ```class range xlnt::worksheet::rows() const```
Returns a range encompassing all cells in this sheet which will be iterated upon in row-major order.
#### ```class range xlnt::worksheet::columns() const```
Returns a range ecompassing all cells in this sheet which will be iterated upon in column-major order.
#### ```class range xlnt::worksheet::rows(bool skip_null=true)```
Returns a range encompassing all cells in this sheet which will be iterated upon in row-major order. If skip_null is true (default), empty rows and cells will be skipped during iteration of the range.
#### ```const class range xlnt::worksheet::rows(bool skip_null=true) const```
Returns a range encompassing all cells in this sheet which will be iterated upon in row-major order. If skip_null is true (default), empty rows and cells will be skipped during iteration of the range.
#### ```class range xlnt::worksheet::columns(bool skip_null=true)```
Returns a range ecompassing all cells in this sheet which will be iterated upon in column-major order. If skip_null is true (default), empty columns and cells will be skipped during iteration of the range.
#### ```const class range xlnt::worksheet::columns(bool skip_null=true) const```
Returns a range ecompassing all cells in this sheet which will be iterated upon in column-major order. If skip_null is true (default), empty columns and cells will be skipped during iteration of the range.
#### ```xlnt::column_properties& xlnt::worksheet::column_properties(column_t column)```
Returns the column properties for the given column.
#### ```const xlnt::column_properties& xlnt::worksheet::column_properties(column_t column) const```
@ -1882,8 +1955,6 @@ Returns a constant iterator to one past the last row in this sheet.
Return a constant iterator to the first row in this sheet.
#### ```const_iterator xlnt::worksheet::cend() const```
Returns a constant iterator to one past the last row in this sheet.
#### ```class range xlnt::worksheet::iter_cells(bool skip_null)```
Returns a range containing all of the cells in this sheet. If skip_null is true, iterating over the range will only return rows and cells that are non-null.
#### ```void xlnt::worksheet::print_title_rows(row_t first_row, row_t last_row)```
Sets rows to repeat at top during printing.
#### ```void xlnt::worksheet::print_title_rows(row_t last_row)```

View File

@ -47,86 +47,101 @@ using c_iter_type = std::iterator<std::bidirectional_iterator_tag,
cell, std::ptrdiff_t, cell *, cell>;
/// <summary>
///
/// A cell iterator iterates over a 1D range by row or by column.
/// </summary>
class XLNT_API cell_iterator : public c_iter_type
{
public:
/// <summary>
///
/// Constructs a cell_iterator from a worksheet, range, and iteration settings.
/// </summary>
cell_iterator(worksheet ws, const cell_reference &start_cell, const range_reference &limits);
cell_iterator(worksheet ws, const cell_reference &start_cell,
const range_reference &limits, major_order order, bool skip_null, bool wrap);
/// <summary>
///
/// </summary>
cell_iterator(worksheet ws, const cell_reference &start_cell, const range_reference &limits, major_order order);
/// <summary>
///
/// Constructs a cell_iterator as a copy of an existing cell_iterator.
/// </summary>
cell_iterator(const cell_iterator &other);
/// <summary>
///
/// Assigns this iterator to match the data in rhs.
/// </summary>
cell_iterator &operator=(const cell_iterator &rhs) = default;
/// <summary>
/// Dereferences this iterator to return the cell it points to.
/// </summary>
cell operator*();
/// <summary>
///
/// </summary>
cell_iterator &operator=(const cell_iterator &) = default;
/// <summary>
///
/// Returns true if this iterator is equivalent to other.
/// </summary>
bool operator==(const cell_iterator &other) const;
/// <summary>
///
/// Returns true if this iterator isn't equivalent to other.
/// </summary>
bool operator!=(const cell_iterator &other) const;
/// <summary>
///
/// Pre-decrements the iterator to point to the previous cell and
/// returns a reference to the iterator.
/// </summary>
cell_iterator &operator--();
/// <summary>
///
/// Post-decrements the iterator to point to the previous cell and
/// return a copy of the iterator before the decrement.
/// </summary>
cell_iterator operator--(int);
/// <summary>
///
/// Pre-increments the iterator to point to the previous cell and
/// returns a reference to the iterator.
/// </summary>
cell_iterator &operator++();
/// <summary>
///
/// Post-increments the iterator to point to the previous cell and
/// return a copy of the iterator before the decrement.
/// </summary>
cell_iterator operator++(int);
private:
/// <summary>
///
/// The worksheet this iterator will return cells from.
/// </summary>
worksheet ws_;
/// <summary>
///
/// The current cell the iterator points to
/// </summary>
cell_reference current_cell_;
cell_reference cursor_;
/// <summary>
///
/// The range of cells this iterator is restricted to
/// </summary>
range_reference range_;
range_reference bounds_;
/// <summary>
///
/// The order this iterator will move, by column or by row. Note that
/// this has the opposite meaning as in a range_iterator because after
/// getting a row-major range_iterator, the row-major cell_iterator will
/// iterate over a column and vice versa.
/// </summary>
major_order order_;
/// <summary>
/// If true, cells that don't exist in the worksheet will be skipped during iteration.
/// </summary>
bool skip_null_;
/// <summary>
/// If true, when on the last column, the cursor will continue to the next row
/// (and vice versa when iterating in column-major order) until reaching the
/// bottom right corner of the range.
/// </summary>
bool wrap_;
};
/// <summary>
@ -136,86 +151,101 @@ using cc_iter_type = std::iterator<std::bidirectional_iterator_tag,
const cell, std::ptrdiff_t, const cell *, const cell>;
/// <summary>
///
/// A cell iterator iterates over a 1D range by row or by column.
/// </summary>
class XLNT_API const_cell_iterator : public cc_iter_type
{
public:
/// <summary>
///
/// Constructs a cell_iterator from a worksheet, range, and iteration settings.
/// </summary>
const_cell_iterator(worksheet ws, const cell_reference &start_cell);
const_cell_iterator(worksheet ws, const cell_reference &start_cell,
const range_reference &limits, major_order order, bool skip_null, bool wrap);
/// <summary>
///
/// </summary>
const_cell_iterator(worksheet ws, const cell_reference &start_cell, major_order order);
/// <summary>
///
/// Constructs a cell_iterator as a copy of an existing cell_iterator.
/// </summary>
const_cell_iterator(const const_cell_iterator &other);
/// <summary>
///
/// Assigns this iterator to match the data in rhs.
/// </summary>
const_cell_iterator &operator=(const const_cell_iterator &) = default;
/// <summary>
///
/// Dereferences this iterator to return the cell it points to.
/// </summary>
const cell operator*() const;
/// <summary>
///
/// Returns true if this iterator is equivalent to other.
/// </summary>
bool operator==(const const_cell_iterator &other) const;
/// <summary>
///
/// Returns true if this iterator isn't equivalent to other.
/// </summary>
bool operator!=(const const_cell_iterator &other) const;
/// <summary>
///
/// Pre-decrements the iterator to point to the previous cell and
/// returns a reference to the iterator.
/// </summary>
const_cell_iterator &operator--();
/// <summary>
///
/// Post-decrements the iterator to point to the previous cell and
/// return a copy of the iterator before the decrement.
/// </summary>
const_cell_iterator operator--(int);
/// <summary>
///
/// Pre-increments the iterator to point to the previous cell and
/// returns a reference to the iterator.
/// </summary>
const_cell_iterator &operator++();
/// <summary>
///
/// Post-increments the iterator to point to the previous cell and
/// return a copy of the iterator before the decrement.
/// </summary>
const_cell_iterator operator++(int);
private:
/// <summary>
///
/// The worksheet this iterator will return cells from.
/// </summary>
worksheet ws_;
/// <summary>
///
/// The current cell the iterator points to
/// </summary>
cell_reference current_cell_;
cell_reference cursor_;
/// <summary>
///
/// The range of cells this iterator is restricted to
/// </summary>
range_reference range_;
range_reference bounds_;
/// <summary>
///
/// The order this iterator will move, by column or by row. Note that
/// this has the opposite meaning as in a range_iterator because after
/// getting a row-major range_iterator, the row-major cell_iterator will
/// iterate over a column and vice versa.
/// </summary>
major_order order_;
/// <summary>
/// If true, cells that don't exist in the worksheet will be skipped during iteration.
/// </summary>
bool skip_null_;
/// <summary>
/// If true, when on the last column, the cursor will continue to the next row
/// (and vice versa when iterating in column-major order) until reaching the
/// bottom right corner of the range.
/// </summary>
bool wrap_;
};
} // namespace xlnt

View File

@ -47,140 +47,170 @@ class XLNT_API cell_vector
{
public:
/// <summary>
///
/// Iterate over cells in a cell_vector with an iterator of this type.
/// </summary>
using iterator = cell_iterator;
/// <summary>
///
/// Iterate over const cells in a const cell_vector with an iterator of this type.
/// </summary>
using const_iterator = const_cell_iterator;
/// <summary>
///
/// Iterate over cells in a cell_vector in reverse oreder with an iterator
/// of this type.
/// </summary>
using reverse_iterator = std::reverse_iterator<iterator>;
/// <summary>
///
/// Iterate over const cells in a const cell_vector in reverse order with
/// an iterator of this type.
/// </summary>
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
/// <summary>
///
/// Constructs a cell vector pointing to a given range in a given worksheet.
/// order determines whether this vector is a row or a column. If skip_null is
/// true, iterating over this vector will skip empty cells.
/// </summary>
cell_vector(worksheet ws, const range_reference &ref, major_order order = major_order::row);
cell_vector(worksheet ws, const cell_reference &cursor,
const range_reference &ref, major_order order, bool skip_null, bool wrap);
/// <summary>
///
/// Returns true if every cell in this vector is null (i.e. the cell doesn't exist in the worksheet).
/// </summary>
bool empty() const;
/// <summary>
/// Returns the first cell in this vector.
/// </summary>
cell front();
/// <summary>
///
/// Returns the first cell in this vector.
/// </summary>
const cell front() const;
/// <summary>
///
/// Returns the last cell in this vector.
/// </summary>
cell back();
/// <summary>
///
/// Returns the last cell in this vector.
/// </summary>
const cell back() const;
/// <summary>
///
/// </summary>
cell operator[](std::size_t column_index);
/// <summary>
///
/// </summary>
const cell operator[](std::size_t column_index) const;
/// <summary>
///
/// Returns the distance between the first and last cells in this vector.
/// </summary>
std::size_t length() const;
/// <summary>
///
/// Returns an iterator to the first cell in this vector.
/// </summary>
iterator begin();
/// <summary>
///
/// Returns an iterator to a cell one-past-the-end of this vector.
/// </summary>
iterator end();
/// <summary>
///
/// Returns an iterator to the first cell in this vector.
/// </summary>
const_iterator begin() const;
/// <summary>
///
/// Returns an iterator to the first cell in this vector.
/// </summary>
const_iterator cbegin() const;
/// <summary>
///
/// Returns an iterator to a cell one-past-the-end of this vector.
/// </summary>
const_iterator end() const;
/// <summary>
///
/// Returns an iterator to a cell one-past-the-end of this vector.
/// </summary>
const_iterator cend() const;
/// <summary>
///
/// Returns a reverse iterator to the first cell of this reversed vector.
/// </summary>
reverse_iterator rbegin();
/// <summary>
///
/// Returns a reverse iterator to to a cell one-past-the-end of this reversed vector.
/// </summary>
reverse_iterator rend();
/// <summary>
///
/// Returns a reverse iterator to the first cell of this reversed vector.
/// </summary>
const_reverse_iterator rbegin() const;
/// <summary>
///
/// Returns a reverse iterator to to a cell one-past-the-end of this reversed vector.
/// </summary>
const_reverse_iterator rend() const;
/// <summary>
///
/// Returns a reverse iterator to the first cell of this reversed vector.
/// </summary>
const_reverse_iterator crbegin() const;
/// <summary>
///
/// Returns a reverse iterator to to a cell one-past-the-end of this reversed vector.
/// </summary>
const_reverse_iterator crend() const;
/// <summary>
/// Returns the cell column_index distance away from the first cell in this vector.
/// </summary>
cell operator[](std::size_t column_index);
/// <summary>
/// Returns the cell column_index distance away from the first cell in this vector.
/// </summary>
const cell operator[](std::size_t column_index) const;
private:
/// <summary>
///
/// The worksheet this vector points to cells from
/// </summary>
worksheet ws_;
/// <summary>
///
/// The reference of the first cell in this vector
/// </summary>
range_reference ref_;
cell_reference cursor_;
/// <summary>
///
/// The range of cells this vector can point to
/// </summary>
range_reference bounds_;
/// <summary>
/// The direction that iteration over this vector will move. Note that
/// this has the opposite meaning as in a range_iterator because after
/// getting a row-major range_iterator, the row-major cell_iterator will
/// iterate over a column and vice versa.
/// </summary>
major_order order_;
/// <summary>
/// If true, cells that don't exist in the worksheet will be skipped during iteration.
/// </summary>
bool skip_null_;
/// <summary>
/// If true, when on the last column, the cursor will continue to the next row
/// (and vice versa when iterating in column-major order) until reaching the
/// bottom right corner of the range.
/// </summary>
bool wrap_;
};
} // namespace xlnt

View File

@ -36,22 +36,23 @@ class XLNT_API column_properties
{
public:
/// <summary>
///
/// The optional width of the column
/// </summary>
optional<double> width;
/// <summary>
///
/// If true, this is a custom width
/// </summary>
bool custom_width = false;
/// <summary>
///
/// The style index of this column. This shouldn't be used since style indices
/// aren't supposed to be used directly in xlnt. (TODO)
/// </summary>
optional<std::size_t> style;
/// <summary>
///
/// If true, this column will be hidden
/// </summary>
bool hidden = false;
};

View File

@ -35,98 +35,98 @@ class XLNT_API page_margins
{
public:
/// <summary>
///
/// Constructs a page margins objects with Excel-default margins.
/// </summary>
page_margins();
/// <summary>
///
/// Returns the top margin
/// </summary>
double top() const;
/// <summary>
///
/// Sets the top margin to top
/// </summary>
void top(double top);
/// <summary>
///
/// Returns the left margin
/// </summary>
double left() const;
/// <summary>
///
/// Sets the left margin to left
/// </summary>
void left(double left);
/// <summary>
///
/// Returns the bottom margin
/// </summary>
double bottom() const;
/// <summary>
///
/// Sets the bottom margin to bottom
/// </summary>
void bottom(double bottom);
/// <summary>
///
/// Returns the right margin
/// </summary>
double right() const;
/// <summary>
///
/// Sets the right margin to right
/// </summary>
void right(double right);
/// <summary>
///
/// Returns the header margin
/// </summary>
double header() const;
/// <summary>
///
/// Sets the header margin to header
/// </summary>
void header(double header);
/// <summary>
///
/// Returns the footer margin
/// </summary>
double footer() const;
/// <summary>
///
/// Sets the footer margin to footer
/// </summary>
void footer(double footer);
private:
/// <summary>
///
/// The top margin
/// </summary>
double top_ = 1;
/// <summary>
///
/// The left margin
/// </summary>
double left_ = 0.75;
/// <summary>
///
/// The bottom margin
/// </summary>
double bottom_ = 1;
/// <summary>
///
/// The right margin
/// </summary>
double right_ = 0.75;
/// <summary>
///
/// The header margin
/// </summary>
double header_ = 0.5;
/// <summary>
///
/// The footer margin
/// </summary>
double footer_ = 0.5;
};

View File

@ -87,8 +87,11 @@ struct XLNT_API pane
/// </summary>
bool operator==(const pane &rhs) const
{
return top_left_cell == rhs.top_left_cell && state == rhs.state && active_pane == rhs.active_pane
&& y_split == rhs.y_split && x_split == rhs.x_split;
return top_left_cell == rhs.top_left_cell
&& state == rhs.state
&& active_pane == rhs.active_pane
&& y_split == rhs.y_split
&& x_split == rhs.x_split;
}
};

View File

@ -179,6 +179,26 @@ public:
/// </summary>
range style(const std::string &style_name);
/// <summary>
///
/// </summary>
cell_vector front();
/// <summary>
///
/// </summary>
const cell_vector front() const;
/// <summary>
///
/// </summary>
cell_vector back();
/// <summary>
///
/// </summary>
const cell_vector back() const;
/// <summary>
///
/// </summary>

View File

@ -51,8 +51,8 @@ public:
/// <summary>
///
/// </summary>
range_iterator(worksheet &ws, const range_reference &start_cell, const range_reference &limits,
major_order order = major_order::row);
range_iterator(worksheet &ws, const cell_reference &cursor,
const range_reference &bounds, major_order order, bool skip_null);
/// <summary>
///
@ -108,17 +108,22 @@ private:
/// <summary>
///
/// </summary>
cell_reference current_cell_;
cell_reference cursor_;
/// <summary>
///
/// </summary>
range_reference range_;
range_reference bounds_;
/// <summary>
///
/// </summary>
major_order order_;
/// <summary>
/// If true, empty rows and cells will be skipped when iterating with this iterator
/// </summary>
bool skip_null_;
};
/// <summary>
@ -137,7 +142,8 @@ public:
/// <summary>
///
/// </summary>
const_range_iterator(const worksheet &ws, const range_reference &start_cell, major_order order = major_order::row);
const_range_iterator(const worksheet &ws, const cell_reference &cursor,
const range_reference &bounds, major_order order, bool skip_null);
/// <summary>
///
@ -193,17 +199,22 @@ private:
/// <summary>
///
/// </summary>
cell_reference current_cell_;
cell_reference cursor_;
/// <summary>
///
/// </summary>
range_reference range_;
range_reference bounds_;
/// <summary>
///
/// </summary>
major_order order_;
/// <summary>
/// If true, empty rows and cells will be skipped when iterating with this iterator
/// </summary>
bool skip_null_;
};
} // namespace xlnt

View File

@ -85,26 +85,46 @@ public:
/// </summary>
std::size_t height() const;
/// <summary>
///
/// </summary>
cell_reference top_left();
/// <summary>
///
/// </summary>
cell_reference top_left() const;
/// <summary>
///
/// </summary>
cell_reference top_right();
/// <summary>
///
/// </summary>
cell_reference top_right() const;
/// <summary>
///
/// </summary>
cell_reference bottom_left();
/// <summary>
///
/// </summary>
cell_reference bottom_left() const;
/// <summary>
///
/// </summary>
cell_reference bottom_right();
/// <summary>
///
/// </summary>
cell_reference bottom_right() const;
/// <summary>
///
/// </summary>
cell_reference &top_left();
/// <summary>
///
/// </summary>
cell_reference &bottom_right();
/// <summary>
///
/// </summary>

View File

@ -224,15 +224,37 @@ public:
/// <summary>
/// Returns a range encompassing all cells in this sheet which will
/// be iterated upon in row-major order.
/// be iterated upon in row-major order. If skip_null is true (default),
/// empty rows and cells will be skipped during iteration of the range.
/// </summary>
class range rows() const;
class range rows(bool skip_null = true);
/// <summary>
/// Returns a range encompassing all cells in this sheet which will
/// be iterated upon in row-major order. If skip_null is true (default),
/// empty rows and cells will be skipped during iteration of the range.
/// </summary>
const class range rows(bool skip_null = true) const;
/// <summary>
/// Returns a range ecompassing all cells in this sheet which will
/// be iterated upon in column-major order.
/// be iterated upon in column-major order. If skip_null is true (default),
/// empty columns and cells will be skipped during iteration of the range.
/// </summary>
class range columns() const;
class range columns(bool skip_null = true);
/// <summary>
/// Returns a range ecompassing all cells in this sheet which will
/// be iterated upon in column-major order. If skip_null is true (default),
/// empty columns and cells will be skipped during iteration of the range.
/// </summary>
const class range columns(bool skip_null = true) const;
//TODO: finish implementing cell_iterator wrapping before uncommenting
//class cell_vector cells(bool skip_null = true);
//TODO: finish implementing cell_iterator wrapping before uncommenting
//const class cell_vector cells(bool skip_null = true) const;
// properties
@ -566,12 +588,6 @@ public:
/// </summary>
const_iterator cend() const;
/// <summary>
/// Returns a range containing all of the cells in this sheet. If skip_null is true,
/// iterating over the range will only return rows and cells that are non-null.
/// </summary>
class range iter_cells(bool skip_null);
/// <summary>
/// Sets rows to repeat at top during printing.
/// </summary>

View File

@ -1482,7 +1482,7 @@ void workbook::garbage_collect_formulae()
for (auto ws : *this)
{
for (auto row : ws.iter_cells(true))
for (auto row : ws.rows(true))
{
for (auto cell : row)
{

View File

@ -20,6 +20,7 @@
//
// @license: http://www.opensource.org/licenses/mit-license.php
// @author: see AUTHORS file
#include <xlnt/cell/cell.hpp>
#include <xlnt/cell/cell_reference.hpp>
#include <xlnt/worksheet/cell_iterator.hpp>
@ -27,14 +28,31 @@
namespace xlnt {
cell_iterator::cell_iterator(worksheet ws, const cell_reference &start_cell,
const range_reference &limits, major_order order)
cell_iterator::cell_iterator(worksheet ws, const cell_reference &cursor,
const range_reference &bounds, major_order order, bool skip_null, bool wrap)
: ws_(ws),
current_cell_(start_cell),
range_(limits),
order_(order)
cursor_(cursor),
bounds_(bounds),
order_(order),
skip_null_(skip_null),
wrap_(wrap)
{
if (!ws.has_cell(current_cell_))
if (skip_null && !ws.has_cell(cursor_))
{
(*this)++; // move to the next non-empty cell or one past the end if none exists
}
}
const_cell_iterator::const_cell_iterator(worksheet ws, const cell_reference &cursor,
const range_reference &bounds, major_order order, bool skip_null, bool wrap)
: ws_(ws),
cursor_(cursor),
bounds_(bounds),
order_(order),
skip_null_(skip_null),
wrap_(wrap)
{
if (skip_null && !ws.has_cell(cursor_))
{
(*this)++; // move to the next non-empty cell or one past the end if none exists
}
@ -45,11 +63,29 @@ cell_iterator::cell_iterator(const cell_iterator &other)
*this = other;
}
const_cell_iterator::const_cell_iterator(const const_cell_iterator &other)
{
*this = other;
}
bool cell_iterator::operator==(const cell_iterator &other) const
{
return ws_ == other.ws_
&& current_cell_ == other.current_cell_
&& order_ == other.order_;
&& cursor_ == other.cursor_
&& bounds_ == other.bounds_
&& order_ == other.order_
&& skip_null_ == other.skip_null_
&& wrap_ == other.wrap_;
}
bool const_cell_iterator::operator==(const const_cell_iterator &other) const
{
return ws_ == other.ws_
&& cursor_ == other.cursor_
&& bounds_ == other.bounds_
&& order_ == other.order_
&& skip_null_ == other.skip_null_
&& wrap_ == other.wrap_;
}
bool cell_iterator::operator!=(const cell_iterator &other) const
@ -57,24 +93,78 @@ bool cell_iterator::operator!=(const cell_iterator &other) const
return !(*this == other);
}
bool const_cell_iterator::operator!=(const const_cell_iterator &other) const
{
return !(*this == other);
}
cell_iterator &cell_iterator::operator--()
{
if (order_ == major_order::row)
{
current_cell_.column_index(current_cell_.column_index() - 1);
while (!ws_.has_cell(current_cell_) && current_cell_.column() > range_.top_left().column())
if (cursor_.column() > bounds_.top_left().column())
{
current_cell_.column_index(current_cell_.column_index() - 1);
cursor_.column_index(cursor_.column_index() - 1);
}
if (skip_null_)
{
while (!ws_.has_cell(cursor_) && cursor_.column() > bounds_.top_left().column())
{
cursor_.column_index(cursor_.column_index() - 1);
}
}
}
else
{
current_cell_.row(current_cell_.row() - 1);
while (!ws_.has_cell(current_cell_) && current_cell_.row() > range_.top_left().row())
if (cursor_.row() > bounds_.top_left().row())
{
current_cell_.row(current_cell_.row() - 1);
cursor_.row(cursor_.row() - 1);
}
if (skip_null_)
{
while (!ws_.has_cell(cursor_) && cursor_.row() > bounds_.top_left().row())
{
cursor_.row(cursor_.row() - 1);
}
}
}
return *this;
}
const_cell_iterator &const_cell_iterator::operator--()
{
if (order_ == major_order::row)
{
if (cursor_.column() > bounds_.top_left().column())
{
cursor_.column_index(cursor_.column_index() - 1);
}
if (skip_null_)
{
while (!ws_.has_cell(cursor_) && cursor_.column() > bounds_.top_left().column())
{
cursor_.column_index(cursor_.column_index() - 1);
}
}
}
else
{
if (cursor_.row() > bounds_.top_left().row())
{
cursor_.row(cursor_.row() - 1);
}
if (skip_null_)
{
while (!ws_.has_cell(cursor_) && cursor_.row() > bounds_.top_left().row())
{
cursor_.row(cursor_.row() - 1);
}
}
}
@ -85,6 +175,15 @@ cell_iterator cell_iterator::operator--(int)
{
cell_iterator old = *this;
--*this;
return old;
}
const_cell_iterator const_cell_iterator::operator--(int)
{
const_cell_iterator old = *this;
--*this;
return old;
}
@ -92,32 +191,74 @@ cell_iterator &cell_iterator::operator++()
{
if (order_ == major_order::row)
{
if (current_cell_.column() <= range_.bottom_right().column())
if (cursor_.column() <= bounds_.bottom_right().column())
{
current_cell_.column_index(current_cell_.column_index() + 1);
cursor_.column_index(cursor_.column_index() + 1);
}
while (!ws_.has_cell(current_cell_) && current_cell_.column() <= range_.bottom_right().column())
if (skip_null_)
{
current_cell_.column_index(current_cell_.column_index() + 1);
while (!ws_.has_cell(cursor_) && cursor_.column() <= bounds_.bottom_right().column())
{
cursor_.column_index(cursor_.column_index() + 1);
}
}
}
else
{
if (current_cell_.row() <= range_.bottom_right().row())
if (cursor_.row() <= bounds_.bottom_right().row())
{
current_cell_.row(current_cell_.row() + 1);
cursor_.row(cursor_.row() + 1);
}
while (!ws_.has_cell(current_cell_) && current_cell_.row() <= range_.bottom_right().row())
if (skip_null_)
{
current_cell_.row(current_cell_.row() + 1);
while (!ws_.has_cell(cursor_) && cursor_.row() <= bounds_.bottom_right().row())
{
cursor_.row(cursor_.row() + 1);
}
}
}
return *this;
}
const_cell_iterator &const_cell_iterator::operator++()
{
if (order_ == major_order::row)
{
if (cursor_.column() <= bounds_.bottom_right().column())
{
cursor_.column_index(cursor_.column_index() + 1);
}
if (skip_null_)
{
while (!ws_.has_cell(cursor_) && cursor_.column() <= bounds_.bottom_right().column())
{
cursor_.column_index(cursor_.column_index() + 1);
}
}
}
else
{
if (cursor_.row() <= bounds_.bottom_right().row())
{
cursor_.row(cursor_.row() + 1);
}
if (skip_null_)
{
while (!ws_.has_cell(cursor_) && cursor_.row() <= bounds_.bottom_right().row())
{
cursor_.row(cursor_.row() + 1);
}
}
}
return *this;
}
cell_iterator cell_iterator::operator++(int)
{
cell_iterator old = *this;
@ -126,71 +267,6 @@ cell_iterator cell_iterator::operator++(int)
return old;
}
cell cell_iterator::operator*()
{
return ws_[current_cell_];
}
const_cell_iterator::const_cell_iterator(worksheet ws, const cell_reference &start_cell, major_order order)
: ws_(ws),
current_cell_(start_cell),
range_(start_cell.to_range()),
order_(order)
{
}
const_cell_iterator::const_cell_iterator(const const_cell_iterator &other)
{
*this = other;
}
bool const_cell_iterator::operator==(const const_cell_iterator &other) const
{
return ws_ == other.ws_ && current_cell_ == other.current_cell_ && order_ == other.order_;
}
bool const_cell_iterator::operator!=(const const_cell_iterator &other) const
{
return !(*this == other);
}
const_cell_iterator &const_cell_iterator::operator--()
{
if (order_ == major_order::row)
{
current_cell_.column_index(current_cell_.column_index() - 1);
}
else
{
current_cell_.row(current_cell_.row() - 1);
}
return *this;
}
const_cell_iterator const_cell_iterator::operator--(int)
{
const_cell_iterator old = *this;
--*this;
return old;
}
const_cell_iterator &const_cell_iterator::operator++()
{
if (order_ == major_order::row)
{
current_cell_.column_index(current_cell_.column_index() + 1);
}
else
{
current_cell_.row(current_cell_.row() + 1);
}
return *this;
}
const_cell_iterator const_cell_iterator::operator++(int)
{
const_cell_iterator old = *this;
@ -199,9 +275,14 @@ const_cell_iterator const_cell_iterator::operator++(int)
return old;
}
cell cell_iterator::operator*()
{
return ws_.cell(cursor_);
}
const cell const_cell_iterator::operator*() const
{
return ws_.cell(current_cell_);
return ws_.cell(cursor_);
}
} // namespace xlnt

View File

@ -21,92 +21,95 @@
// @license: http://www.opensource.org/licenses/mit-license.php
// @author: see AUTHORS file
#include <algorithm> // std::all_of
#include <xlnt/cell/cell.hpp>
#include <xlnt/worksheet/cell_iterator.hpp>
#include <xlnt/worksheet/cell_vector.hpp>
namespace xlnt {
cell_vector::cell_vector(worksheet ws, const cell_reference &cursor,
const range_reference &bounds, major_order order, bool skip_null, bool wrap)
: ws_(ws),
cursor_(cursor),
bounds_(bounds),
order_(order),
skip_null_(skip_null),
wrap_(wrap)
{
}
cell_vector::iterator cell_vector::begin()
{
return iterator(ws_, ref_.top_left(), ref_, order_);
return iterator(ws_, cursor_, bounds_, order_, skip_null_, wrap_);
}
cell_vector::iterator cell_vector::end()
{
auto past_end = cursor_;
if (order_ == major_order::row)
{
auto past_end = ref_.bottom_right();
past_end.column_index(past_end.column_index() + 1);
return iterator(ws_, past_end, ref_, order_);
past_end.column_index(bounds_.bottom_right().column_index() + 1);
}
else
{
past_end.row(bounds_.bottom_right().row() + 1);
}
auto past_end = ref_.bottom_right();
past_end.row(past_end.row() + 1);
return iterator(ws_, past_end, ref_, order_);
return iterator(ws_, past_end, bounds_, order_, skip_null_, wrap_);
}
cell_vector::const_iterator cell_vector::cbegin() const
{
return const_iterator(ws_, ref_.top_left(), order_);
return const_iterator(ws_, cursor_, bounds_, order_, skip_null_, wrap_);
}
cell_vector::const_iterator cell_vector::cend() const
{
auto past_end = cursor_;
if (order_ == major_order::row)
{
auto past_end = ref_.bottom_right();
past_end.column_index(past_end.column_index() + 1);
return const_iterator(ws_, past_end, order_);
past_end.column_index(bounds_.bottom_right().column_index() + 1);
}
auto past_end = ref_.bottom_right();
past_end.row(past_end.row() + 1);
return const_iterator(ws_, past_end, order_);
}
cell cell_vector::operator[](std::size_t cell_index)
{
if (order_ == major_order::row)
else
{
return ws_.cell(ref_.top_left().make_offset(static_cast<int>(cell_index), 0));
past_end.row(bounds_.bottom_right().row() + 1);
}
return ws_.cell(ref_.top_left().make_offset(0, static_cast<int>(cell_index)));
return const_iterator(ws_, past_end, bounds_, order_, skip_null_, wrap_);
}
cell_vector::cell_vector(worksheet ws, const range_reference &reference, major_order order)
: ws_(ws), ref_(reference), order_(order)
bool cell_vector::empty() const
{
return begin() == end();
}
cell cell_vector::front()
{
if (order_ == major_order::row)
{
return ws_.cell(ref_.top_left());
}
return *begin();
}
return ws_.cell(ref_.top_left());
const cell cell_vector::front() const
{
return *cbegin();
}
cell cell_vector::back()
{
if (order_ == major_order::row)
{
return ws_.cell(ref_.bottom_right());
}
return *(--end());
}
return ws_.cell(ref_.bottom_right());
const cell cell_vector::back() const
{
return *(--cend());
}
std::size_t cell_vector::length() const
{
return order_ == major_order::row ? ref_.width() + 1 : ref_.height() + 1;
return order_ == major_order::row ? bounds_.width() + 1 : bounds_.height() + 1;
}
cell_vector::const_iterator cell_vector::begin() const
@ -148,4 +151,14 @@ cell_vector::const_reverse_iterator cell_vector::rend() const
return crend();
}
cell cell_vector::operator[](std::size_t cell_index)
{
if (order_ == major_order::row)
{
return ws_.cell(cursor_.make_offset(static_cast<int>(cell_index), 0));
}
return ws_.cell(cursor_.make_offset(0, static_cast<int>(cell_index)));
}
} // namespace xlnt

View File

@ -72,22 +72,18 @@ bool range::operator==(const range &comparand) const
cell_vector range::vector(std::size_t vector_index)
{
range_reference vector_ref = ref_;
auto cursor = ref_.top_left();
if (order_ == major_order::row)
{
auto row = ref_.top_left().row() + static_cast<row_t>(vector_index);
vector_ref.top_left().row(row);
vector_ref.bottom_right().row(row);
cursor.row(cursor.row() + vector_index);
}
else
{
auto column = ref_.top_left().column() + static_cast<column_t::index_t>(vector_index);
vector_ref.top_left().column_index(column);
vector_ref.bottom_right().column_index(column);
cursor.column_index(cursor.column_index() + vector_index);
}
return cell_vector(ws_, vector_ref, order_);
return cell_vector(ws_, cursor, ref_, order_, skip_null_, false);
}
bool range::contains(const cell_reference &ref)
@ -161,64 +157,66 @@ cell range::cell(const cell_reference &ref)
return (*this)[ref.row() - 1][ref.column().index - 1];
}
cell_vector range::front()
{
return *begin();
}
const cell_vector range::front() const
{
return *cbegin();
}
cell_vector range::back()
{
return *(--end());
}
const cell_vector range::back() const
{
return *(--cend());
}
range::iterator range::begin()
{
if (order_ == major_order::row)
{
cell_reference top_right(ref_.bottom_right().column_index(), ref_.top_left().row());
range_reference row_range(ref_.top_left(), top_right);
return iterator(ws_, row_range, ref_, order_);
}
cell_reference bottom_left(ref_.top_left().column_index(), ref_.bottom_right().row());
range_reference row_range(ref_.top_left(), bottom_left);
return iterator(ws_, row_range, ref_, order_);
return iterator(ws_, ref_.top_left(), ref_, order_, skip_null_);
}
range::iterator range::end()
{
auto cursor = ref_.top_left();
if (order_ == major_order::row)
{
auto past_end_row_index = ref_.bottom_right().row() + 1;
cell_reference bottom_left(ref_.top_left().column_index(), past_end_row_index);
cell_reference bottom_right(ref_.bottom_right().column_index(), past_end_row_index);
return iterator(ws_, range_reference(bottom_left, bottom_right), ref_, order_);
cursor.row(ref_.bottom_right().row() + 1);
}
else
{
cursor.column_index(ref_.bottom_right().column_index() + 1);
}
auto past_end_column_index = ref_.bottom_right().column_index() + 1;
cell_reference top_right(past_end_column_index, ref_.top_left().row());
cell_reference bottom_right(past_end_column_index, ref_.bottom_right().row());
return iterator(ws_, range_reference(top_right, bottom_right), ref_, order_);
return iterator(ws_, cursor, ref_, order_, skip_null_);
}
range::const_iterator range::cbegin() const
{
if (order_ == major_order::row)
{
cell_reference top_right(ref_.bottom_right().column_index(), ref_.top_left().row());
range_reference row_range(ref_.top_left(), top_right);
return const_iterator(ws_, row_range, order_);
}
cell_reference bottom_left(ref_.top_left().column_index(), ref_.bottom_right().row());
range_reference row_range(ref_.top_left(), bottom_left);
return const_iterator(ws_, row_range, order_);
return const_iterator(ws_, ref_.top_left(), ref_, order_, skip_null_);
}
range::const_iterator range::cend() const
{
auto cursor = ref_.top_left();
if (order_ == major_order::row)
{
auto past_end_row_index = ref_.bottom_right().row() + 1;
cell_reference bottom_left(ref_.top_left().column_index(), past_end_row_index);
cell_reference bottom_right(ref_.bottom_right().column_index(), past_end_row_index);
return const_iterator(ws_, range_reference(bottom_left, bottom_right), order_);
cursor.row(ref_.bottom_right().row() + 1);
}
else
{
cursor.column_index(ref_.bottom_right().column_index() + 1);
}
auto past_end_column_index = ref_.bottom_right().column_index() + 1;
cell_reference top_right(past_end_column_index, ref_.top_left().row());
cell_reference bottom_right(past_end_column_index, ref_.bottom_right().row());
return const_iterator(ws_, range_reference(top_right, bottom_right), order_);
return const_iterator(ws_, cursor, ref_, order_, skip_null_);
}
bool range::operator!=(const range &comparand) const

View File

@ -30,25 +30,21 @@ namespace xlnt {
cell_vector range_iterator::operator*() const
{
if (order_ == major_order::row)
{
range_reference reference(range_.top_left().column_index(), current_cell_.row(),
range_.bottom_right().column_index(), current_cell_.row());
return cell_vector(ws_, reference, order_);
}
range_reference reference(current_cell_.column_index(), range_.top_left().row(),
current_cell_.column_index(), range_.bottom_right().row());
return cell_vector(ws_, reference, order_);
return cell_vector(ws_, cursor_, bounds_, order_, skip_null_, false);
}
range_iterator::range_iterator(worksheet &ws, const range_reference &start_cell,
const range_reference &limits, major_order order)
range_iterator::range_iterator(worksheet &ws, const cell_reference &cursor,
const range_reference &bounds, major_order order, bool skip_null)
: ws_(ws),
current_cell_(start_cell.top_left()),
range_(limits),
order_(order)
cursor_(cursor),
bounds_(bounds),
order_(order),
skip_null_(skip_null)
{
if (skip_null_ && (**this).empty())
{
++(*this);
}
}
range_iterator::range_iterator(const range_iterator &other)
@ -59,8 +55,9 @@ range_iterator::range_iterator(const range_iterator &other)
bool range_iterator::operator==(const range_iterator &other) const
{
return ws_ == other.ws_
&& current_cell_ == other.current_cell_
&& order_ == other.order_;
&& cursor_ == other.cursor_
&& order_ == other.order_
&& skip_null_ == other.skip_null_;
}
bool range_iterator::operator!=(const range_iterator &other) const
@ -72,11 +69,33 @@ range_iterator &range_iterator::operator--()
{
if (order_ == major_order::row)
{
current_cell_.row(current_cell_.row() - 1);
if (cursor_.row() > bounds_.top_left().row())
{
cursor_.row(cursor_.row() - 1);
}
if (skip_null_)
{
while ((**this).empty() && cursor_.row() > bounds_.top_left().row())
{
cursor_.row(cursor_.row() - 1);
}
}
}
else
{
current_cell_.column_index(current_cell_.column_index() - 1);
if (cursor_.column() > bounds_.top_left().column())
{
cursor_.column_index(cursor_.column_index() - 1);
}
if (skip_null_)
{
while ((**this).empty() && cursor_.row() > bounds_.top_left().column())
{
cursor_.column_index(cursor_.column_index() - 1);
}
}
}
return *this;
@ -94,26 +113,33 @@ range_iterator &range_iterator::operator++()
{
if (order_ == major_order::row)
{
bool any_non_null = false;
do
if (cursor_.row() <= bounds_.bottom_right().row())
{
current_cell_.row(current_cell_.row() + 1);
any_non_null = false;
for (auto column = current_cell_.column(); column <= range_.bottom_right().column(); column++)
cursor_.row(cursor_.row() + 1);
}
if (skip_null_)
{
while ((**this).empty() && cursor_.row() <= bounds_.bottom_right().row())
{
if (ws_.has_cell(cell_reference(column, current_cell_.row())))
{
any_non_null = true;
break;
}
cursor_.row(cursor_.row() + 1);
}
} while (!any_non_null && current_cell_.row() <= range_.bottom_right().row());
}
}
else
{
current_cell_.column_index(current_cell_.column_index() + 1);
if (cursor_.column() <= bounds_.bottom_right().column())
{
cursor_.column_index(cursor_.column_index() + 1);
}
if (skip_null_)
{
while ((**this).empty() && cursor_.column() <= bounds_.bottom_right().column())
{
cursor_.column_index(cursor_.column_index() + 1);
}
}
}
return *this;
@ -128,13 +154,18 @@ range_iterator range_iterator::operator++(int)
}
const_range_iterator::const_range_iterator(const worksheet &ws,
const range_reference &start_cell, major_order order)
const_range_iterator::const_range_iterator(const worksheet &ws, const cell_reference &cursor,
const range_reference &bounds, major_order order, bool skip_null)
: ws_(ws.d_),
current_cell_(start_cell.top_left()),
range_(start_cell),
order_(order)
cursor_(cursor),
bounds_(bounds),
order_(order),
skip_null_(skip_null)
{
if (skip_null_ && (**this).empty())
{
++(*this);
}
}
const_range_iterator::const_range_iterator(const const_range_iterator &other)
@ -145,8 +176,9 @@ const_range_iterator::const_range_iterator(const const_range_iterator &other)
bool const_range_iterator::operator==(const const_range_iterator &other) const
{
return ws_ == other.ws_
&& current_cell_ == other.current_cell_
&& order_ == other.order_;
&& cursor_ == other.cursor_
&& order_ == other.order_
&& skip_null_ == other.skip_null_;
}
bool const_range_iterator::operator!=(const const_range_iterator &other) const
@ -158,11 +190,33 @@ const_range_iterator &const_range_iterator::operator--()
{
if (order_ == major_order::row)
{
current_cell_.row(current_cell_.row() - 1);
if (cursor_.row() > bounds_.top_left().row())
{
cursor_.row(cursor_.row() - 1);
}
if (skip_null_)
{
while ((**this).empty() && cursor_.row() > bounds_.top_left().row())
{
cursor_.row(cursor_.row() - 1);
}
}
}
else
{
current_cell_.column_index(current_cell_.column_index() - 1);
if (cursor_.column() > bounds_.top_left().column())
{
cursor_.column_index(cursor_.column_index() - 1);
}
if (skip_null_)
{
while ((**this).empty() && cursor_.row() > bounds_.top_left().column())
{
cursor_.column_index(cursor_.column_index() - 1);
}
}
}
return *this;
@ -180,11 +234,33 @@ const_range_iterator &const_range_iterator::operator++()
{
if (order_ == major_order::row)
{
current_cell_.row(current_cell_.row() + 1);
if (cursor_.row() <= bounds_.bottom_right().row())
{
cursor_.row(cursor_.row() + 1);
}
if (skip_null_)
{
while ((**this).empty() && cursor_.row() <= bounds_.bottom_right().row())
{
cursor_.row(cursor_.row() + 1);
}
}
}
else
{
current_cell_.column_index(current_cell_.column_index() + 1);
if (cursor_.column() <= bounds_.bottom_right().column())
{
cursor_.column_index(cursor_.column_index() + 1);
}
if (skip_null_)
{
while ((**this).empty() && cursor_.column() <= bounds_.bottom_right().column())
{
cursor_.column_index(cursor_.column_index() + 1);
}
}
}
return *this;
@ -200,16 +276,7 @@ const_range_iterator const_range_iterator::operator++(int)
const cell_vector const_range_iterator::operator*() const
{
if (order_ == major_order::row)
{
range_reference reference(range_.top_left().column_index(), current_cell_.row(),
range_.bottom_right().column_index(), current_cell_.row());
return cell_vector(ws_, reference, order_);
}
range_reference reference(current_cell_.column_index(), range_.top_left().row(),
current_cell_.column_index(), range_.bottom_right().row());
return cell_vector(ws_, reference, order_);
return cell_vector(ws_, cursor_, bounds_, order_, skip_null_, false);
}
} // namespace xlnt

View File

@ -63,14 +63,19 @@ range_reference::range_reference(const std::string &range_string)
}
}
range_reference::range_reference(const cell_reference &top_left, const cell_reference &bottom_right)
: top_left_(top_left), bottom_right_(bottom_right)
range_reference::range_reference(const cell_reference &top_left,
const cell_reference &bottom_right)
: top_left_(top_left),
bottom_right_(bottom_right)
{
}
range_reference::range_reference(
column_t column_index_start, row_t row_index_start, column_t column_index_end, row_t row_index_end)
: top_left_(column_index_start, row_index_start), bottom_right_(column_index_end, row_index_end)
range_reference::range_reference(column_t column_index_start,
row_t row_index_start,
column_t column_index_end,
row_t row_index_end)
: top_left_(column_index_start, row_index_start),
bottom_right_(column_index_end, row_index_end)
{
}
@ -113,19 +118,42 @@ bool range_reference::operator!=(const range_reference &comparand) const
return comparand.top_left_ != top_left_ || comparand.bottom_right_ != bottom_right_;
}
cell_reference range_reference::top_left()
{
return top_left_;
}
cell_reference range_reference::top_left() const
{
return top_left_;
}
cell_reference range_reference::bottom_right() const
cell_reference range_reference::top_right()
{
return cell_reference(bottom_right_.column(), top_left_.row());
}
cell_reference range_reference::top_right() const
{
return cell_reference(bottom_right_.column(), top_left_.row());
}
cell_reference range_reference::bottom_left()
{
return cell_reference(top_left_.column(), bottom_right_.row());
}
cell_reference range_reference::bottom_left() const
{
return cell_reference(top_left_.column(), bottom_right_.row());
}
cell_reference range_reference::bottom_right()
{
return bottom_right_;
}
cell_reference &range_reference::top_left()
{
return top_left_;
}
cell_reference &range_reference::bottom_right()
cell_reference range_reference::bottom_right() const
{
return bottom_right_;
}

View File

@ -54,13 +54,13 @@ public:
ws.cell("C9").value("last");
TS_ASSERT_EQUALS(ws.calculate_dimension(), "A1:C9");
TS_ASSERT_EQUALS(ws.rows()[row][column].reference(), coordinate);
TS_ASSERT_EQUALS(ws.rows(false)[row][column].reference(), coordinate);
row = 8;
column = 2;
coordinate = "C9";
TS_ASSERT_EQUALS(ws.rows()[row][column].reference(), coordinate);
TS_ASSERT_EQUALS(ws.rows(false)[row][column].reference(), coordinate);
}
void test_get_named_range()
@ -481,12 +481,14 @@ public:
const xlnt::worksheet ws_const = ws;
const auto rows = ws_const.rows();
const auto first_row = *rows.begin();
const auto first_cell = *first_row.begin();
const auto first_row = rows.front();
const auto first_cell = first_row.front();
TS_ASSERT_EQUALS(first_cell.reference(), "A1");
TS_ASSERT_EQUALS(first_cell.value<std::string>(), "A1");
const auto last_row = *(--rows.end());
const auto last_cell = *(--last_row.end());
const auto last_row = rows.back();
const auto last_cell = last_row.back();
TS_ASSERT_EQUALS(last_cell.reference(), "C2");
TS_ASSERT_EQUALS(last_cell.value<std::string>(), "C2");
for (const auto row : rows)

View File

@ -610,16 +610,42 @@ row_t worksheet::next_row() const
return row;
}
xlnt::range worksheet::rows() const
xlnt::range worksheet::rows(bool skip_null)
{
return range(calculate_dimension());
return xlnt::range(*this, calculate_dimension(), major_order::row, skip_null);
}
xlnt::range worksheet::columns() const
const xlnt::range worksheet::rows(bool skip_null) const
{
return xlnt::range(*this, calculate_dimension(), major_order::column);
return xlnt::range(*this, calculate_dimension(), major_order::row, skip_null);
}
xlnt::range worksheet::columns(bool skip_null)
{
return xlnt::range(*this, calculate_dimension(), major_order::column, skip_null);
}
const xlnt::range worksheet::columns(bool skip_null) const
{
return xlnt::range(*this, calculate_dimension(), major_order::column, skip_null);
}
/*
//TODO: finish implementing cell_iterator wrapping before uncommenting
cell_vector worksheet::cells(bool skip_null)
{
const auto dimension = calculate_dimension();
return cell_vector(*this, dimension.top_left(), dimension, major_order::row, skip_null, true);
}
const cell_vector worksheet::cells(bool skip_null) const
{
const auto dimension = calculate_dimension();
return cell_vector(*this, dimension.top_left(), dimension, major_order::row, skip_null, true);
}
*/
bool worksheet::operator==(const worksheet &other) const
{
return compare(other, true);
@ -793,40 +819,22 @@ void worksheet::add_row_properties(row_t row, const xlnt::row_properties &props)
worksheet::iterator worksheet::begin()
{
auto dimensions = calculate_dimension();
cell_reference top_right(dimensions.bottom_right().column_index(), dimensions.top_left().row());
range_reference row_range(dimensions.top_left(), top_right);
return iterator(*this, row_range, dimensions, major_order::row);
return rows().begin();
}
worksheet::iterator worksheet::end()
{
auto dimensions = calculate_dimension();
auto past_end_row_index = dimensions.bottom_right().row() + 1;
cell_reference bottom_left(dimensions.top_left().column_index(), past_end_row_index);
cell_reference bottom_right(dimensions.bottom_right().column_index(), past_end_row_index);
return iterator(*this, range_reference(bottom_left, bottom_right), dimensions, major_order::row);
return rows().end();
}
worksheet::const_iterator worksheet::cbegin() const
{
auto dimensions = calculate_dimension();
cell_reference top_right(dimensions.bottom_right().column_index(), dimensions.top_left().row());
range_reference row_range(dimensions.top_left(), top_right);
return const_iterator(*this, row_range, major_order::row);
return rows().cbegin();
}
worksheet::const_iterator worksheet::cend() const
{
auto dimensions = calculate_dimension();
auto past_end_row_index = dimensions.bottom_right().row() + 1;
cell_reference bottom_left(dimensions.top_left().column_index(), past_end_row_index);
cell_reference bottom_right(dimensions.bottom_right().column_index(), past_end_row_index);
return const_iterator(*this, range_reference(bottom_left, bottom_right), major_order::row);
return rows().cend();
}
worksheet::const_iterator worksheet::begin() const
@ -839,11 +847,6 @@ worksheet::const_iterator worksheet::end() const
return cend();
}
range worksheet::iter_cells(bool skip_null)
{
return xlnt::range(*this, calculate_dimension(), major_order::row, skip_null);
}
void worksheet::print_title_rows(row_t last_row)
{
print_title_rows(1, last_row);