lib/roo/xls/excel_2003_xml.rb in roo-xls-1.1.0 vs lib/roo/xls/excel_2003_xml.rb in roo-xls-1.2.0

- old
+ new

@@ -19,11 +19,11 @@ unless File.file?(@filename) raise IOError, "file #{@filename} does not exist" end @doc = ::Roo::Utils.load_xml(@filename) end - namespace = @doc.namespaces.select{|xmlns, urn| urn == 'urn:schemas-microsoft-com:office:spreadsheet'}.keys.last + namespace = @doc.namespaces.select { |_, urn| urn == 'urn:schemas-microsoft-com:office:spreadsheet' }.keys.last @namespace = (namespace.nil? || namespace.empty?) ? 'ss' : namespace.split(':').last super(filename, options) @formula = {} @style = {} @style_defaults = Hash.new { |h, k| h[k] = [] } @@ -56,11 +56,11 @@ @formula[sheet][[row, col]] && @formula[sheet][[row, col]]['oooc:'.length..-1] end alias_method :formula?, :formula class Font - attr_accessor :bold, :italic, :underline + attr_accessor :bold, :italic, :underline, :color, :name, :size def bold? @bold == '1' end @@ -189,35 +189,53 @@ def read_cells(sheet = nil) sheet ||= @default_sheet validate_sheet!(sheet) return if @cells_read[sheet] sheet_found = false + @doc.xpath("/#{@namespace}:Workbook/#{@namespace}:Worksheet[@#{@namespace}:Name='#{sheet}']").each do |ws| sheet_found = true - row = 1 + column_styles = {} + + # Column Styles col = 1 - column_attributes = {} - idx = 0 ws.xpath("./#{@namespace}:Table/#{@namespace}:Column").each do |c| - column_attributes[(idx += 1).to_s] = c['StyleID'] + skip_to_col = c["#{@namespace}:Index"].to_i + col = skip_to_col if skip_to_col > 0 + col_style_name = c["#{@namespace}:StyleID"] + column_styles[col] = col_style_name unless col_style_name.nil? + col += 1 end + + # Rows + row = 1 ws.xpath("./#{@namespace}:Table/#{@namespace}:Row").each do |r| - skip_to_row = r['Index'].to_i + skip_to_row = r["#{@namespace}:Index"].to_i row = skip_to_row if skip_to_row > 0 - style_name = r['StyleID'] if r['StyleID'] + + # Excel uses a 'Span' attribute on a 'Row' to indicate the presence of + # empty rows to skip. + skip_next_rows = r["#{@namespace}:Span"].to_i + + row_style_name = r["#{@namespace}:StyleID"] + + # Cells + col = 1 r.xpath("./#{@namespace}:Cell").each do |c| - skip_to_col = c['Index'].to_i + skip_to_col = c["#{@namespace}:Index"].to_i col = skip_to_col if skip_to_col > 0 - if c['StyleID'] - style_name = c['StyleID'] - elsif - style_name ||= column_attributes[c['Index']] - end + + skip_next_cols = c["#{@namespace}:MergeAcross"].to_i + + cell_style_name = c["#{@namespace}:StyleID"] + style_name = cell_style_name || row_style_name || column_styles[col] + + # Cell Data c.xpath("./#{@namespace}:Data").each do |cell| formula = cell['Formula'] value_type = cell["#{@namespace}:Type"].downcase.to_sym - v = cell.content + v = cell.content str_v = v case value_type when :number v = v.to_f value_type = :float @@ -232,29 +250,32 @@ when :boolean v = cell['boolean-value'] end set_cell_values(sheet, col, row, 0, v, value_type, formula, cell, str_v, style_name) end - col += 1 + col += (skip_next_cols + 1) end - row += 1 - col = 1 + row += (skip_next_rows + 1) end end unless sheet_found raise RangeError, "Unable to find sheet #{sheet} for reading" end @cells_read[sheet] = true end def read_styles @doc.xpath("/#{@namespace}:Workbook/#{@namespace}:Styles/#{@namespace}:Style").each do |style| - style_id = style['ID'] - @style_definitions[style_id] = Roo::Excel2003XML::Font.new - if font = style.at_xpath("./#{@namespace}:Font") - @style_definitions[style_id].bold = font['Bold'] - @style_definitions[style_id].italic = font['Italic'] - @style_definitions[style_id].underline = font['Underline'] + style_id = style["#{@namespace}:ID"] + font = style.at_xpath("./#{@namespace}:Font") + unless font.nil? + @style_definitions[style_id] = Roo::Excel2003XML::Font.new + @style_definitions[style_id].bold = font["#{@namespace}:Bold"] + @style_definitions[style_id].italic = font["#{@namespace}:Italic"] + @style_definitions[style_id].underline = font["#{@namespace}:Underline"] + @style_definitions[style_id].color = font["#{@namespace}:Color"] + @style_definitions[style_id].name = font["#{@namespace}:FontName"] + @style_definitions[style_id].size = font["#{@namespace}:Size"] end end end A_ROO_TYPE = {