lib/roo/excelx.rb in roo-2.1.1 vs lib/roo/excelx.rb in roo-2.2.0
- old
+ new
@@ -1,82 +1,28 @@
require 'nokogiri'
require 'zip/filesystem'
require 'roo/link'
require 'roo/utils'
+require 'forwardable'
module Roo
class Excelx < Roo::Base
+ extend Forwardable
+
+ require 'roo/excelx/shared'
require 'roo/excelx/workbook'
require 'roo/excelx/shared_strings'
require 'roo/excelx/styles'
require 'roo/excelx/cell'
require 'roo/excelx/sheet'
require 'roo/excelx/relationships'
require 'roo/excelx/comments'
require 'roo/excelx/sheet_doc'
-
- module Format
- EXCEPTIONAL_FORMATS = {
- 'h:mm am/pm' => :date,
- 'h:mm:ss am/pm' => :date
- }
+ require 'roo/excelx/coordinate'
+ require 'roo/excelx/format'
- STANDARD_FORMATS = {
- 0 => 'General'.freeze,
- 1 => '0'.freeze,
- 2 => '0.00'.freeze,
- 3 => '#,##0'.freeze,
- 4 => '#,##0.00'.freeze,
- 9 => '0%'.freeze,
- 10 => '0.00%'.freeze,
- 11 => '0.00E+00'.freeze,
- 12 => '# ?/?'.freeze,
- 13 => '# ??/??'.freeze,
- 14 => 'mm-dd-yy'.freeze,
- 15 => 'd-mmm-yy'.freeze,
- 16 => 'd-mmm'.freeze,
- 17 => 'mmm-yy'.freeze,
- 18 => 'h:mm AM/PM'.freeze,
- 19 => 'h:mm:ss AM/PM'.freeze,
- 20 => 'h:mm'.freeze,
- 21 => 'h:mm:ss'.freeze,
- 22 => 'm/d/yy h:mm'.freeze,
- 37 => '#,##0 ;(#,##0)'.freeze,
- 38 => '#,##0 ;[Red](#,##0)'.freeze,
- 39 => '#,##0.00;(#,##0.00)'.freeze,
- 40 => '#,##0.00;[Red](#,##0.00)'.freeze,
- 45 => 'mm:ss'.freeze,
- 46 => '[h]:mm:ss'.freeze,
- 47 => 'mmss.0'.freeze,
- 48 => '##0.0E+0'.freeze,
- 49 => '@'.freeze
- }
-
- def to_type(format)
- format = format.to_s.downcase
- if (type = EXCEPTIONAL_FORMATS[format])
- type
- elsif format.include?('#')
- :float
- elsif !format.match(/d+(?![\]])/).nil? || format.include?('y')
- if format.include?('h') || format.include?('s')
- :datetime
- else
- :date
- end
- elsif format.include?('h') || format.include?('s')
- :time
- elsif format.include?('%')
- :percentage
- else
- :float
- end
- end
-
- module_function :to_type
- end
-
+ delegate [:styles, :workbook, :shared_strings, :rels_files, :sheet_files, :comments_files] => :@shared
ExceedsMaxError = Class.new(StandardError)
# initialization and opening of a spreadsheet file
# values for packed: :zip
# optional cell_max (int) parameter for early aborting attempts to parse
@@ -92,23 +38,22 @@
file_type_check(filename_or_stream, %w[.xlsx .xlsm], 'an Excel 2007', file_warning, packed)
basename = File.basename(filename_or_stream)
end
@tmpdir = make_tmpdir(basename, options[:tmpdir_root])
+ @shared = Shared.new(@tmpdir)
@filename = local_filename(filename_or_stream, @tmpdir, packed)
- @comments_files = []
- @rels_files = []
process_zipfile(@filename || filename_or_stream)
@sheet_names = workbook.sheets.map do |sheet|
unless options[:only_visible_sheets] && sheet['state'] == 'hidden'
sheet['name']
end
end.compact
@sheets = []
@sheets_by_name = Hash[@sheet_names.map.with_index do |sheet_name, n|
- @sheets[n] = Sheet.new(sheet_name, @rels_files[n], @sheet_files[n], @comments_files[n], styles, shared_strings, workbook, sheet_options)
+ @sheets[n] = Sheet.new(sheet_name, @shared, n, sheet_options)
[sheet_name, @sheets[n]]
end]
if cell_max
cell_count = ::Roo::Utils.num_cells_in_range(sheet_for(options.delete(:sheet)).dimensions)
@@ -185,11 +130,11 @@
# set a cell to a certain value
# (this will not be saved back to the spreadsheet file!)
def set(row, col, value, sheet = nil) #:nodoc:
key = normalize(row, col)
cell_type = cell_type_by_value(value)
- sheet_for(sheet).cells[key] = Cell.new(value, cell_type, nil, cell_type, value, nil, nil, nil, Cell::Coordinate.new(row, col))
+ sheet_for(sheet).cells[key] = Cell.new(value, cell_type, nil, cell_type, value, nil, nil, nil, Coordinate.new(row, col))
end
# Returns the formula at (row,col).
# Returns nil if there is no formula.
# The method #formula? checks if there is a formula.
@@ -237,18 +182,18 @@
# * :numeric_or_formula
# * :string
# Note: this is only available within the Excelx class
def excelx_type(row, col, sheet = nil)
key = normalize(row, col)
- safe_send(sheet_for(sheet).cells[key], :excelx_type)
+ safe_send(sheet_for(sheet).cells[key], :cell_type)
end
# returns the internal value of an excelx cell
# Note: this is only available within the Excelx class
def excelx_value(row, col, sheet = nil)
key = normalize(row, col)
- safe_send(sheet_for(sheet).cells[key], :excelx_value)
+ safe_send(sheet_for(sheet).cells[key], :cell_value)
end
# returns the internal format of an excel cell
def excelx_format(row, col, sheet = nil)
key = normalize(row, col)
@@ -257,12 +202,12 @@
def empty?(row, col, sheet = nil)
sheet = sheet_for(sheet)
key = normalize(row, col)
cell = sheet.cells[key]
- !cell || !cell.value || (cell.type == :string && cell.value.empty?) \
- || (row < sheet.first_row || row > sheet.last_row || col < sheet.first_column || col > sheet.last_column)
+ !cell || cell.empty? || (cell.type == :string && cell.value.empty?) ||
+ (row < sheet.first_row || row > sheet.last_row || col < sheet.first_column || col > sheet.last_column)
end
# shows the internal representation of all cells
# for debugging purposes
def to_s(sheet = nil)
@@ -402,10 +347,11 @@
def extract_sheets_in_order(entries, sheet_ids, sheets, tmpdir)
sheet_ids.each_with_index do |id, i|
name = sheets[id]
entry = entries.find { |e| e.name =~ /#{name}$/ }
path = "#{tmpdir}/roo_sheet#{i + 1}"
+ sheet_files << path
@sheet_files << path
entry.extract(path)
end
end
@@ -455,22 +401,24 @@
# the sheet order, i.e. sheet1.xml's comments are in comments1.xml.
# In some situations, this isn't true. The true location of a
# sheet's comment file is in the sheet1.xml.rels file. SEE
# ECMA-376 12.3.3 in "Ecma Office Open XML Part 1".
nr = Regexp.last_match[1].to_i
- @comments_files[nr - 1] = "#{@tmpdir}/roo_comments#{nr}"
+ comments_files[nr - 1] = "#{@tmpdir}/roo_comments#{nr}"
when /sheet([0-9]+).xml.rels$/
# FIXME: Roo seems to use sheet[\d].xml.rels for hyperlinks only, but
# it also stores the location for sharedStrings, comments,
# drawings, etc.
nr = Regexp.last_match[1].to_i
- @rels_files[nr - 1] = "#{@tmpdir}/roo_rels#{nr}"
+ rels_files[nr - 1] = "#{@tmpdir}/roo_rels#{nr}"
end
entry.extract(path) if path
end
end
+ # NOTE: To reduce memory, styles, shared_strings, workbook can be class
+ # variables in a Shared module.
def styles
@styles ||= Styles.new(File.join(@tmpdir, 'roo_styles.xml'))
end
def shared_strings