lib/roo/xls/excel.rb in roo-xls-1.0.0 vs lib/roo/xls/excel.rb in roo-xls-1.1.0
- old
+ new
@@ -1,13 +1,14 @@
require 'roo/xls/version'
require 'roo/base'
require 'spreadsheet'
+require 'tmpdir'
module Roo
# Class for handling Excel-Spreadsheets
class Excel < Roo::Base
- FORMULAS_MESSAGE = 'the spreadsheet gem does not support forumulas, so roo can not.'
+ FORMULAS_MESSAGE = 'the spreadsheet gem does not support formulas, so roo can not.'
CHARGUESS =
begin
require 'charguess'
true
rescue LoadError
@@ -21,22 +22,29 @@
def initialize(filename, options = {})
packed = options[:packed]
file_warning = options[:file_warning] || :error
mode = options[:mode] || 'rb+'
- file_type_check(filename, '.xls', 'an Excel', file_warning, packed)
- make_tmpdir do |tmpdir|
- filename = download_uri(filename, tmpdir) if uri?(filename)
- filename = open_from_stream(filename[7..-1], tmpdir) if filename.is_a?(::String) && filename[0, 7] == 'stream:'
- filename = unzip(filename, tmpdir) if packed == :zip
+ if is_stream?(filename)
+ @workbook = ::Spreadsheet.open(filename, mode)
+ else
+ file_type_check(filename, '.xls', 'an Excel', file_warning, packed)
+ Dir.mktmpdir do |tmpdir|
+ filename = download_uri(filename, tmpdir) if uri?(filename)
+ if filename.is_a?(::String) && filename[0, 7] == 'stream:'
+ filename = open_from_stream(filename[7..-1], tmpdir)
+ end
+ filename = unzip(filename, tmpdir) if packed == :zip
- @filename = filename
- unless File.file?(@filename)
- fail IOError, "file #{@filename} does not exist"
+ @filename = filename
+ unless File.file?(@filename)
+ raise IOError, "file #{@filename} does not exist"
+ end
+ @workbook = ::Spreadsheet.open(filename, mode)
end
- @workbook = ::Spreadsheet.open(filename, mode)
end
+
super(filename, options)
@formula = {}
@fonts = {}
end
@@ -55,34 +63,30 @@
@sheets ||= worksheets.collect { |worksheet| normalize_string(worksheet.name) }
end
# this method lets you find the worksheet with the most data
def longest_sheet
- sheet(worksheets.inject do|m, o|
+ sheet(worksheets.inject do |m, o|
o.row_count > m.row_count ? o : m
end.name)
end
# returns the content of a cell. The upper left corner is (1,1) or ('A',1)
def cell(row, col, sheet = default_sheet)
validate_sheet!(sheet)
read_cells(sheet)
- fail 'should be read' unless @cells_read[sheet]
+ raise 'should be read' unless @cells_read[sheet]
row, col = normalize(row, col)
if celltype(row, col, sheet) == :date
yyyy, mm, dd = @cell[sheet][[row, col]].split('-')
return Date.new(yyyy.to_i, mm.to_i, dd.to_i)
end
if celltype(row, col, sheet) == :string
- return platform_specific_encoding(@cell[sheet][[row, col]])
+ platform_specific_encoding(@cell[sheet][[row, col]])
else
- if @cell[sheet] && @cell[sheet][[row, col]]
- return @cell[sheet][[row, col]]
- else
- return nil
- end
+ @cell[sheet] && @cell[sheet][[row, col]]
end
end
# returns the type of a cell:
# * :float
@@ -107,17 +111,17 @@
end
end
# returns NO formula in excel spreadsheets
def formula(_row, _col, _sheet = nil)
- fail NotImplementedError, FORMULAS_MESSAGE
+ raise NotImplementedError, FORMULAS_MESSAGE
end
alias_method :formula?, :formula
# returns NO formulas in excel spreadsheets
def formulas(_sheet = nil)
- fail NotImplementedError, FORMULAS_MESSAGE
+ raise NotImplementedError, FORMULAS_MESSAGE
end
# Given a cell, return the cell's font
def font(row, col, sheet = default_sheet)
read_cells(sheet)
@@ -134,22 +138,22 @@
private
# converts name of a sheet to index (0,1,2,..)
def sheet_no(name)
- return name - 1 if name.is_a?(Fixnum)
+ return name - 1 if name.is_a?(Integer)
i = 0
worksheets.each do |worksheet|
return i if name == normalize_string(worksheet.name)
i += 1
end
- fail StandardError, "sheet '#{name}' not found"
+ raise StandardError, "sheet '#{name}' not found"
end
def normalize_string(value)
value = every_second_null?(value) ? remove_every_second_null(value) : value
- if CHARGUESS && encoding = CharGuess.guess(value)
+ if CHARGUESS && (encoding = CharGuess.guess(value))
encoding.encode Encoding::UTF_8
else
platform_specific_encoding(value)
end
end
@@ -162,13 +166,11 @@
when /mswin32/
value.encode Encoding::ISO_8859_1
else
value
end
- if every_second_null?(result)
- result = remove_every_second_null(result)
- end
+ result = remove_every_second_null(result) if every_second_null?(result)
result
end
def every_second_null?(str)
result = true
@@ -196,12 +198,12 @@
# key = "#{y},#{x+i}"
key = [row, col + i]
@cell_type[sheet] = {} unless @cell_type[sheet]
@cell_type[sheet][key] = value_type
@formula[sheet] = {} unless @formula[sheet]
- @formula[sheet][key] = formula if formula
- @cell[sheet] = {} unless @cell[sheet]
+ @formula[sheet][key] = formula if formula
+ @cell[sheet] = {} unless @cell[sheet]
@fonts[sheet] = {} unless @fonts[sheet]
@fonts[sheet][key] = font
@cell[sheet][key] =
case value_type
@@ -248,11 +250,11 @@
worksheet = @workbook.worksheet(sheet_no(sheet))
row_index = 1
worksheet.each(0) do |row|
(0..row.size).each do |cell_index|
cell = row.at(cell_index)
- next if cell.nil? # skip empty cells
+ next if cell.nil? # skip empty cells
next if cell.class == ::Spreadsheet::Formula && cell.value.nil? # skip empty formula cells
value_type, v =
if date_or_time?(row, cell_index)
read_cell_date_or_time(row, cell_index)
else
@@ -297,33 +299,35 @@
if cell < 1.0
value_type = :time
f = cell * 24.0 * 60.0 * 60.0
secs = f.round
h = (secs / 3600.0).floor
- secs = secs - 3600 * h
+ secs -= 3600 * h
m = (secs / 60.0).floor
- secs = secs - 60 * m
+ secs -= 60 * m
s = secs
value = h * 3600 + m * 60 + s
else
- if row.at(idx).class == ::Spreadsheet::Formula
- datetime = row.send(:_datetime, cell)
- else
- datetime = row.datetime(idx)
- end
+ datetime =
+ if row.at(idx).class == ::Spreadsheet::Formula
+ row.send(:_datetime, cell)
+ else
+ row.datetime(idx)
+ end
if datetime.hour != 0 ||
datetime.min != 0 ||
datetime.sec != 0
value_type = :datetime
value = datetime
else
value_type = :date
- if row.at(idx).class == ::Spreadsheet::Formula
- value = row.send(:_date, cell)
- else
- value = row.date(idx)
- end
+ value =
+ if row.at(idx).class == ::Spreadsheet::Formula
+ row.send(:_date, cell)
+ else
+ row.date(idx)
+ end
value = sprintf('%04d-%02d-%02d', value.year, value.month, value.day)
end
end
[value_type, value]
end
@@ -331,10 +335,10 @@
# Read the cell and based on the class,
# return the values for Roo
def read_cell(row, idx)
cell = read_cell_content(row, idx)
case cell
- when Float, Integer, Fixnum, Bignum
+ when Float, Integer
value_type = :float
value = cell.to_f
when ::Spreadsheet::Link
value_type = :link
value = cell