class ExcelParser::Sheet

Attributes

name[R]
workbook[R]

Public Class Methods

column_name_to_index(name) click to toggle source
# File lib/excel_parser.rb, line 273
def self.column_name_to_index(name)
  if not @column_names_to_indices
    @column_names_to_indices = {}
    self.column_names.each_with_index do |name, i|
      @column_names_to_indices[name] = i
    end
  end
  @column_names_to_indices[name]
end
column_names() click to toggle source

Returns A to ZZZ.

# File lib/excel_parser.rb, line 259
def self.column_names
  if @column_names
    @column_names
  else
    proc = Proc.new do |prev|
      ("#{prev}A".."#{prev}Z").to_a
    end
    x = proc.call("")
    y = x.map(&proc).flatten
    z = y.map(&proc).flatten
    @column_names = x + y + z
  end
end
new(workbook, name, id, index) click to toggle source
# File lib/excel_parser.rb, line 163
def initialize(workbook, name, id, index)
  @workbook = workbook
  @name = name
  @id = id
  @index = index
  begin
    @file = @workbook.zipfs.file.open(path) if @workbook.zipfs.file.exist?(path)
  rescue Zip::Error => e
    raise ExcelParser::Error, "Couldn't open sheet #{index}: #{e.message}"
  end
end

Public Instance Methods

parse_time(float) click to toggle source
# File lib/excel_parser.rb, line 236
def parse_time(float)
  hours = (float * 24).floor
  minutes = (float * 24 * 60).floor % 60
  seconds = (float * 24 * 60 * 60).floor % 60
  ExcelParser::Time.new(hours, minutes, seconds)
end
process_row(cell_map) click to toggle source
# File lib/excel_parser.rb, line 243
def process_row(cell_map)
  max = cell_map.keys.map {|c| self.class.column_name_to_index c }.max
  row = []
  self.class.column_names[0..max].each do |col|
    if self.class.column_name_to_index(col) > max
      break
    else
      row << cell_map[col]
    end
  end
  row
end
row_count() click to toggle source
# File lib/excel_parser.rb, line 283
def row_count
  if defined? @row_count
    @row_count
  elsif @file
    @file.rewind
    Nokogiri::XML::Reader(@file).each do |node|
      if node.node_type == Nokogiri::XML::Reader::TYPE_ELEMENT
        case node.name
        when 'dimension'
          if ref = node.attributes["ref"]
            break @row_count = ref.scan(/\d+$/).first.to_i
          end
        when 'sheetData'
          break @row_count = nil
        end
      end
    end
  end
end
rows() click to toggle source
# File lib/excel_parser.rb, line 179
def rows
  Enumerator.new(row_count) do |y|
    next unless @file
    @file.rewind
    shared = false
    row = nil
    cell_map = nil # Map of column letter to cell value for a row
    column = nil
    cell_type = nil
    Nokogiri::XML::Reader(@file).each do |node|
      case node.node_type
      when Nokogiri::XML::Reader::TYPE_ELEMENT
        case node.name
        when "row"
          cell_map = {}
          next
        when 'c'
          node_type = node.attributes['t']
          node_style = node.attributes['s']
          cell_index = node.attributes['r']
          if !cell_index
            raise ExcelParser::Error, 'Invalid spreadsheet XML.'
          end
          column = cell_index.delete('0-9')
          cell_type = @workbook.attribute_to_type(node_type, node_style)
          shared = (node_type == 's')
          next
        end
      when Nokogiri::XML::Reader::TYPE_END_ELEMENT
        if node.name == 'row'
          y << process_row(cell_map)
        end
        next
      end

      if node.value
        value = case cell_type
          when :shared
            string_lookup(node.value.to_i)
          when :boolean
            node.value.to_i != 0
          when :datetime, :date
            ExcelParser::OOXMLEpoch + node.value.to_f
          when :time
            parse_time(node.value.to_f)
          when :float
            node.value.to_f
          else
            # leave as string
            node.value
          end
        cell_map[column] = value
      end
    end
  end
end
string_lookup(i) click to toggle source
# File lib/excel_parser.rb, line 175
def string_lookup(i)
  @workbook.string_table[i] || (raise ExcelParser::Error, 'File invalid, invalid string table.')
end

Private Instance Methods

path() click to toggle source
# File lib/excel_parser.rb, line 304
def path
  "xl/worksheets/sheet#{@index}.xml"
end