From ccb62cbf6451f27c4d1bf75b00eebd103024366b Mon Sep 17 00:00:00 2001 From: Martins Polakovs Date: Thu, 21 Sep 2023 17:49:51 +0300 Subject: [PATCH] Add support for implicit cell coordinates when using #each_row_streaming --- lib/roo/excelx/sheet.rb | 6 +++--- lib/roo/excelx/sheet_doc.rb | 20 ++++++++++---------- test/roo/test_excelx.rb | 15 +++++++++++++++ 3 files changed, 28 insertions(+), 13 deletions(-) diff --git a/lib/roo/excelx/sheet.rb b/lib/roo/excelx/sheet.rb index 840a0533..fe843300 100644 --- a/lib/roo/excelx/sheet.rb +++ b/lib/roo/excelx/sheet.rb @@ -42,7 +42,7 @@ def each_row(options = {}, &block) @sheet.each_row_streaming do |row| break if options[:max_rows] && row_count == options[:max_rows] + options[:offset] + 1 if block_given? && !(options[:offset] && row_count < options[:offset]) - block.call(cells_for_row_element(row, options)) + block.call(cells_for_row_element(row, row_count + 1, options)) end row_count += 1 end @@ -101,11 +101,11 @@ def dimensions # Take an xml row and return an array of Excelx::Cell objects # optionally pad array to header width(assumed 1st row). # takes option pad_cells (boolean) defaults false - def cells_for_row_element(row_element, options = {}) + def cells_for_row_element(row_element, row_index, options = {}) return [] unless row_element cell_col = 0 cells = [] - @sheet.each_cell(row_element) do |cell| + @sheet.each_cell(row_element, row_index) do |cell| cells.concat(pad_cells(cell, cell_col)) if options[:pad_cells] cells << cell cell_col = cell.coordinate.column diff --git a/lib/roo/excelx/sheet_doc.rb b/lib/roo/excelx/sheet_doc.rb index 7a09725a..f36bce0b 100755 --- a/lib/roo/excelx/sheet_doc.rb +++ b/lib/roo/excelx/sheet_doc.rb @@ -43,10 +43,10 @@ def each_row_streaming(&block) # Yield each cell as Excelx::Cell to caller for given # row xml - def each_cell(row_xml) + def each_cell(row_xml, row_index = nil) return [] unless row_xml - row_xml.children.each do |cell_element| - coordinate = ::Roo::Utils.extract_coordinate(cell_element["r"]) + row_xml.children.each.with_index(1) do |cell_element, col_index| + coordinate = cell_coordinate(cell_element["r"], row_index, col_index) hyperlinks = hyperlinks(@relationships)[coordinate] yield cell_from_xml(cell_element, hyperlinks, coordinate) @@ -213,13 +213,7 @@ def extract_cells(relationships) doc.xpath('/worksheet/sheetData/row').each.with_index(1) do |row_xml, ycoord| row_xml.xpath('c').each.with_index(1) do |cell_xml, xcoord| - r = cell_xml['r'] - coordinate = - if r.nil? - ::Roo::Excelx::Coordinate.new(ycoord, xcoord) - else - ::Roo::Utils.extract_coordinate(r) - end + coordinate = cell_coordinate(cell_xml['r'], ycoord, xcoord) cell = cell_from_xml(cell_xml, hyperlinks(relationships)[coordinate], coordinate, empty_cell) extracted_cells[coordinate] = cell if cell @@ -252,6 +246,12 @@ def base_timestamp def shared_strings @shared.shared_strings end + + def cell_coordinate(r, row_index, col_index) + return ::Roo::Excelx::Coordinate.new(row_index, col_index) if r.nil? + + ::Roo::Utils.extract_coordinate(r) + end end end end diff --git a/test/roo/test_excelx.rb b/test/roo/test_excelx.rb index c90cd8c0..939aa15c 100644 --- a/test/roo/test_excelx.rb +++ b/test/roo/test_excelx.rb @@ -350,6 +350,21 @@ def test_implicit_coordinates assert_equal 'C2', xlsx.cell('c', 2) end + def test_implicit_coordinates_with_streaming_rows + xlsx = roo_class.new(File.join(TESTDIR, 'implicit_coordinates.xlsx')) + + expected_rows = [ + ['Test'], + ['A2', 'B2', 'C2'] + ] + + index = 0 + xlsx.each_row_streaming do |row| + assert_equal expected_rows[index], row.map(&:value) + index += 1 + end + end + def roo_class Roo::Excelx end