class Dullard::Sheet

Attributes

name[R]
workbook[R]

Public Class Methods

column_name_to_index(name) click to toggle source
# File lib/dullard/reader.rb, line 302
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/dullard/reader.rb, line 288
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/dullard/reader.rb, line 198
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 Dullard::Error, "Couldn't open sheet #{index}: #{e.message}"
  end
end

Public Instance Methods

process_row(cell_map) click to toggle source
# File lib/dullard/reader.rb, line 272
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/dullard/reader.rb, line 312
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/dullard/reader.rb, line 214
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']
          cell_index = node.attributes['r']
          if !cell_index
            raise Dullard::Error, 'Invalid spreadsheet XML.'
          end

          if node_type != 's' && node_type != 'b'
            cell_format_index = node.attributes['s'].to_i
            cell_type = @workbook.format2type(@workbook.attribute2format(cell_format_index))
          end

          column = cell_index.delete('0-9')
          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 = (shared ? string_lookup(value.to_i) : value)
        case cell_type
          when :datetime
          when :time
          when :date
            value = (Dullard::OOXMLEpoch + node.value.to_f)
          when :float
            value = node.value.to_f
          else
            # leave as string
        end
        cell_type = nil
        cell_map[column] = value
      end
    end
  end
end
string_lookup(i) click to toggle source
# File lib/dullard/reader.rb, line 210
def string_lookup(i)
  @workbook.string_table[i] || (raise Dullard::Error, 'File invalid, invalid string table.')
end

Private Instance Methods

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