From 28f7e6fa69ee5fe1275deb4c7cf2ecac18a370ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Bourbonnais?= Date: Wed, 8 Dec 2021 15:49:14 -0500 Subject: [PATCH] Add has_value to cell_iterator When iterating over a range that doesn't ignore null rows/columns, the operator*() throws when dereferencing an iterator to a null cell. Add has_value() to cell_iterator to be able to make a check without relying on exceptions. And add a test case. --- include/xlnt/worksheet/cell_iterator.hpp | 14 +++++++++++++ source/worksheet/cell_iterator.cpp | 8 ++++++++ tests/worksheet/worksheet_test_suite.cpp | 26 ++++++++++++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/include/xlnt/worksheet/cell_iterator.hpp b/include/xlnt/worksheet/cell_iterator.hpp index e0770448..0e324d09 100644 --- a/include/xlnt/worksheet/cell_iterator.hpp +++ b/include/xlnt/worksheet/cell_iterator.hpp @@ -136,6 +136,13 @@ public: /// cell_iterator operator++(int); + /// + /// When iterating over a range that doesn't ignore null cells, operator*() + /// will throw when trying to access the cells that are null. This method + /// checks the existence of a cell. + /// + bool has_value() const; + private: /// /// If true, cells that don't exist in the worksheet will be skipped during iteration. @@ -263,6 +270,13 @@ public: /// const_cell_iterator operator++(int); + /// + /// When iterating over a range that doesn't ignore null cells, operator*() + /// will throw when trying to access the cells that are null. This method + /// checks the existence of a cell. + /// + bool has_value() const; + private: /// /// If true, cells that don't exist in the worksheet will be skipped during iteration. diff --git a/source/worksheet/cell_iterator.cpp b/source/worksheet/cell_iterator.cpp index 1d950a5b..b89863e5 100644 --- a/source/worksheet/cell_iterator.cpp +++ b/source/worksheet/cell_iterator.cpp @@ -278,4 +278,12 @@ const const_cell_iterator::reference const_cell_iterator::operator*() const { return ws_.cell(cursor_); } + +bool cell_iterator::has_value() const{ + return ws_.has_cell(cursor_); +} + +bool const_cell_iterator::has_value() const{ + return ws_.has_cell(cursor_); +} } // namespace xlnt diff --git a/tests/worksheet/worksheet_test_suite.cpp b/tests/worksheet/worksheet_test_suite.cpp index 64b47da1..6580142f 100644 --- a/tests/worksheet/worksheet_test_suite.cpp +++ b/tests/worksheet/worksheet_test_suite.cpp @@ -78,6 +78,7 @@ public: register_test(test_lowest_row_or_props); register_test(test_highest_row); register_test(test_highest_row_or_props); + register_test(test_iterator_has_value); register_test(test_const_iterators); register_test(test_const_reverse_iterators); register_test(test_column_major_iterators); @@ -584,6 +585,31 @@ public: xlnt_assert_equals(ws.highest_row_or_props(), 11); } + void test_iterator_has_value() + { + xlnt::workbook wb; + auto ws = wb.active_sheet(); + + // make a worksheet with a blank row and column + ws.cell("A1").value("A1"); + ws.cell("A3").value("A3"); + ws.cell("C1").value("C1"); + + xlnt_assert_equals(ws.columns(false)[0].begin().has_value(), true); + xlnt_assert_equals(ws.rows(false)[0].begin().has_value(), true); + + xlnt_assert_equals(ws.columns(false)[1].begin().has_value(), false); + xlnt_assert_equals(ws.rows(false)[1].begin().has_value(), false); + + // also test const interators. + xlnt_assert_equals(ws.columns(false)[0].cbegin().has_value(), true); + xlnt_assert_equals(ws.rows(false)[0].cbegin().has_value(), true); + + xlnt_assert_equals(ws.columns(false)[1].cbegin().has_value(), false); + xlnt_assert_equals(ws.rows(false)[1].cbegin().has_value(), false); + + } + void test_const_iterators() { xlnt::workbook wb;