Skip to content

Commit 93b5ca0

Browse files
committed
Remove empty rows/columns from the range returned by worksheet::rows(true)
Note that the iterator already skipped those empty rows/cells, but those rows/columns were included in the returned range.reference(). If someone is interested in the old range_reference (i.e. the envolope of all non-empty cells or rows with properties), calculate_dimension(true) can be called directly. Note that Google Sheets sometimes add empty rows (with only properties being defined). This results in a different range being returned by rows/columns before or after the file is saved by Google Sheets. Note that the (old) default behaviour of calculate_dimension is kept, as this is how the dimensions are stored in the worksheet. Changing this behaviour results in failed unit tests. Fixes #5
1 parent 6e39730 commit 93b5ca0

3 files changed

Lines changed: 34 additions & 10 deletions

File tree

include/xlnt/worksheet/worksheet.hpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,27 +229,31 @@ class XLNT_API worksheet
229229
/// <summary>
230230
/// Returns a range encompassing all cells in this sheet which will
231231
/// be iterated upon in row-major order. If skip_null is true (default),
232+
/// the range does not contain empty rows/columns at its boundaries and
232233
/// empty rows and cells will be skipped during iteration of the range.
233234
/// </summary>
234235
class range rows(bool skip_null = true);
235236

236237
/// <summary>
237238
/// Returns a range encompassing all cells in this sheet which will
238239
/// be iterated upon in row-major order. If skip_null is true (default),
240+
/// the range does not contain empty rows/columns at its boundaries and
239241
/// empty rows and cells will be skipped during iteration of the range.
240242
/// </summary>
241243
const class range rows(bool skip_null = true) const;
242244

243245
/// <summary>
244246
/// Returns a range ecompassing all cells in this sheet which will
245247
/// be iterated upon in column-major order. If skip_null is true (default),
248+
/// the range does not contain empty rows/columns at its boundaries and
246249
/// empty columns and cells will be skipped during iteration of the range.
247250
/// </summary>
248251
class range columns(bool skip_null = true);
249252

250253
/// <summary>
251254
/// Returns a range ecompassing all cells in this sheet which will
252255
/// be iterated upon in column-major order. If skip_null is true (default),
256+
/// the range does not contain empty rows/columns at its boundaries and
253257
/// empty columns and cells will be skipped during iteration of the range.
254258
/// </summary>
255259
const class range columns(bool skip_null = true) const;
@@ -436,8 +440,9 @@ class XLNT_API worksheet
436440
/// Returns a range_reference pointing to the full range of cells in the worksheet.
437441
/// If skip_null is true (default), empty cells (For example if the first row or column is empty)
438442
/// will not be included in upper left bound of range.
443+
/// If skip_row_props is false (default), rows with only properties being defined will be returned too.
439444
/// </summary>
440-
range_reference calculate_dimension(bool skip_null=true) const;
445+
range_reference calculate_dimension(bool skip_null=true, bool skip_row_props=false) const;
441446

442447
// cell merge
443448

source/worksheet/worksheet.cpp

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,7 @@ column_t worksheet::highest_column_or_props() const
577577
return highest;
578578
}
579579

580-
range_reference worksheet::calculate_dimension(bool skip_null) const
580+
range_reference worksheet::calculate_dimension(bool skip_null, bool skip_row_props) const
581581
{
582582
// partially optimised version of:
583583
// return range_reference(lowest_column(), lowest_row_or_props(),
@@ -593,12 +593,15 @@ range_reference worksheet::calculate_dimension(bool skip_null) const
593593
// in order to include first empty rows and columns
594594
row_t min_row_prop = skip_null? constants::max_row() : constants::min_row();
595595
row_t max_row_prop = constants::min_row();
596-
for (const auto &row_prop : d_->row_properties_)
596+
if (!skip_row_props)
597597
{
598-
if(skip_null){
599-
min_row_prop = std::min(min_row_prop, row_prop.first);
598+
for (const auto &row_prop : d_->row_properties_)
599+
{
600+
if(skip_null){
601+
min_row_prop = std::min(min_row_prop, row_prop.first);
602+
}
603+
max_row_prop = std::max(max_row_prop, row_prop.first);
600604
}
601-
max_row_prop = std::max(max_row_prop, row_prop.first);
602605
}
603606
if (d_->cell_map_.empty())
604607
{
@@ -724,22 +727,22 @@ row_t worksheet::next_row() const
724727

725728
xlnt::range worksheet::rows(bool skip_null)
726729
{
727-
return xlnt::range(*this, calculate_dimension(skip_null), major_order::row, skip_null);
730+
return xlnt::range(*this, calculate_dimension(skip_null, skip_null), major_order::row, skip_null);
728731
}
729732

730733
const xlnt::range worksheet::rows(bool skip_null) const
731734
{
732-
return xlnt::range(*this, calculate_dimension(skip_null), major_order::row, skip_null);
735+
return xlnt::range(*this, calculate_dimension(skip_null, skip_null), major_order::row, skip_null);
733736
}
734737

735738
xlnt::range worksheet::columns(bool skip_null)
736739
{
737-
return xlnt::range(*this, calculate_dimension(skip_null), major_order::column, skip_null);
740+
return xlnt::range(*this, calculate_dimension(skip_null, skip_null), major_order::column, skip_null);
738741
}
739742

740743
const xlnt::range worksheet::columns(bool skip_null) const
741744
{
742-
return xlnt::range(*this, calculate_dimension(skip_null), major_order::column, skip_null);
745+
return xlnt::range(*this, calculate_dimension(skip_null, skip_null), major_order::column, skip_null);
743746
}
744747

745748
/*

tests/worksheet/worksheet_test_suite.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ class worksheet_test_suite : public test_suite
111111
register_test(test_hidden_sheet);
112112
register_test(test_xlsm_read_write);
113113
register_test(test_issue_484);
114+
register_test(test_issue_5_empty_bottom_rows);
114115
}
115116

116117
void test_new_worksheet()
@@ -1674,6 +1675,21 @@ class worksheet_test_suite : public test_suite
16741675
xlnt_assert_equals("B12:B12", ws.columns(true).reference());
16751676
xlnt_assert_equals("A1:B12", ws.columns(false).reference());
16761677
}
1678+
1679+
void test_issue_5_empty_bottom_rows()
1680+
{
1681+
xlnt::workbook wb;
1682+
auto ws = wb.active_sheet();
1683+
1684+
ws.cell("B12").value("AAA");
1685+
ws.row_properties(15).height = 1.0;
1686+
1687+
xlnt_assert_equals("B12:B12", ws.rows(true).reference());
1688+
xlnt_assert_equals("A1:B15", ws.rows(false).reference());
1689+
1690+
xlnt_assert_equals("B12:B12", ws.columns(true).reference());
1691+
xlnt_assert_equals("A1:B15", ws.columns(false).reference());
1692+
}
16771693
};
16781694

16791695
static worksheet_test_suite x;

0 commit comments

Comments
 (0)