class Xlsxrb::Ooxml::WorksheetParser
Streaming parser for xl/worksheets/sheetN.xml. Uses a fast string-scanning approach for row/cell extraction, falling back to REXML SAX only for column definitions and unmapped data.
Constants
- EMPTY_ARRAY
- EMPTY_HASH
- XML_ENTITIES
Public Class Methods
(String, ?shared_strings: Array[String], ?part_name: String) ?{ (Event) → void } → void
(String, ?shared_strings: Array[String], ?part_name: String) → Enumerator[Event, void]
Source
# File lib/xlsxrb/ooxml/worksheet_parser.rb, line 73 def self.each_event(xml_string, shared_strings: [], part_name: "xl/worksheets/sheet1.xml", &block) return enum_for(:each_event, xml_string, shared_strings: shared_strings, part_name: part_name) unless block return if xml_string.nil? || xml_string.empty? # 1. Parse and yield column events if xml_string.include?("<cols") listener = ColumnsListener.new XmlParser.parse(xml_string, listener) listener.columns.each do |col| block.call(Event.new( type: :column, args: [col[:min], col[:max], col[:width], col[:hidden], col[:custom_width], col[:outline_level]], source: { part: part_name } )) end end # 2. Parse and yield row/cell events fast_scan_events(xml_string, shared_strings, part_name, &block) # 3. Parse and yield hyperlink events return unless xml_string.include?("hyperlink") xml = xml_string.b hpos_term = xml.index("hyperlinks") return unless hpos_term hpos = xml.rindex("<", hpos_term) return unless hpos h_end_term = xml.index("/hyperlinks", hpos) h_end = h_end_term ? xml.index(">", h_end_term) : xml.size h_end ||= xml.size pos = hpos while pos < h_end hl_start_term = xml.index("hyperlink", pos) break unless hl_start_term && hl_start_term < h_end hl_start = xml.rindex("<", hl_start_term) break unless hl_start && hl_start < h_end hl_tag_end = xml.index(">", hl_start + 1) break unless hl_tag_end hl_tag = xml.byteslice(hl_start, hl_tag_end - hl_start) ref = tag_attr(hl_tag, ' ref="') rid = tag_attr(hl_tag, ' r:id="') || tag_attr(hl_tag, ' id="') display = tag_attr(hl_tag, ' display="') tooltip = tag_attr(hl_tag, ' tooltip="') location = tag_attr(hl_tag, ' location="') if ref block.call(Event.new( type: :hyperlink, args: [ref, rid, display, tooltip, location], source: { part: part_name, cell: ref } )) end pos = hl_tag_end + 1 end end
Yields Event objects for columns, rows, cells, and hyperlinks.
# File lib/xlsxrb/ooxml/worksheet_parser.rb, line 26 def self.each_row(xml_string, shared_strings: [], part_name: "xl/worksheets/sheet1.xml", &block) return enum_for(:each_row, xml_string, shared_strings: shared_strings, part_name: part_name) unless block current_row = nil each_event(xml_string, shared_strings: shared_strings, part_name: part_name) do |event| case event.type when :row_start index, attrs = event.args current_row = { index: index, cells: [], attrs: attrs, unmapped: EMPTY_ARRAY, source: event.source } when :cell ref, type, style_index, value, formula = event.args if current_row cell = { ref: ref, type: type, style_index: style_index, value: value, source: event.source } cell[:formula] = formula if formula current_row[:cells] << cell end when :row_end if current_row block.call(current_row) current_row = nil end end end end
Streaming parse: yields one raw row hash at a time.
# File lib/xlsxrb/ooxml/worksheet_parser.rb, line 17 def self.parse(xml_string, shared_strings: []) return [] if xml_string.nil? || xml_string.empty? rows = [] each_row(xml_string, shared_strings: shared_strings) { |row| rows << row } rows end
Parses all rows from a worksheet XML string. Returns an Array of raw row hashes:
{ index:, cells: [{ ref:, type:, style_index:, value:, formula: }], attrs:, unmapped: }
# File lib/xlsxrb/ooxml/worksheet_parser.rb, line 52 def self.parse_columns(xml_string, part_name: "xl/worksheets/sheet1.xml") return [] if xml_string.nil? || xml_string.empty? columns = [] each_event(xml_string, part_name: part_name) do |event| next unless event.type == :column min, max, width, hidden, custom_width, outline_level = event.args columns << { min: min, max: max, width: width, hidden: hidden, custom_width: custom_width, outline_level: outline_level } end columns end
Parses column definitions (<cols>) from a worksheet.