lib/roo/excelx.rb in roo-1.10.1 vs lib/roo/excelx.rb in roo-1.10.2
- old
+ new
@@ -10,11 +10,11 @@
self[-str.length,str.length] == str
end
end
end
-class Excelx < GenericSpreadsheet
+class Roo::Excelx < Roo::GenericSpreadsheet
FORMATS = {
'General' => :float,
'0' => :float,
'0.00' => :float,
'#,##0' => :float,
@@ -49,11 +49,11 @@
"dd/mm/yy\\ hh:mm" => :datetime,
'dd/mmm/yy' => :date, # 2011-05-21
'yyyy-mm-dd' => :date, # 2011-09-16
# was used in a spreadsheet file from a windows phone
}
- STANDARD_FORMATS = {
+ STANDARD_FORMATS = {
0 => 'General',
1 => '0',
2 => '0.00',
3 => '#,##0',
4 => '#,##0.00',
@@ -79,66 +79,54 @@
46 => '[h]:mm:ss',
47 => 'mmss.0',
48 => '##0.0E+0',
49 => '@',
}
- @@nr = 0
# initialization and opening of a spreadsheet file
# values for packed: :zip
def initialize(filename, packed=nil, file_warning = :error) #, create = false)
- super()
- @file_warning = file_warning
- file_type_check(filename,'.xlsx','an Excel-xlsx',packed)
- @tmpdir = GenericSpreadsheet.next_tmpdir
- @tmpdir = File.join(ENV['ROO_TMP'], @tmpdir) if ENV['ROO_TMP']
- unless File.exists?(@tmpdir)
- FileUtils::mkdir(@tmpdir)
+ file_type_check(filename,'.xlsx','an Excel-xlsx', file_warning, packed)
+ make_tmpdir do |tmpdir|
+ filename = open_from_uri(filename, tmpdir) if uri?(filename)
+ filename = unzip(filename, tmpdir) if packed == :zip
+ @cells_read = Hash.new
+ @filename = filename
+ unless File.file?(@filename)
+ raise IOError, "file #{@filename} does not exist"
+ end
+ @comments_files = Array.new
+ extract_content(tmpdir, @filename)
+ @workbook_doc = File.open(File.join(tmpdir, "roo_workbook.xml")) do |file|
+ Nokogiri::XML(file)
+ end
+ @shared_table = []
+ if File.exist?(File.join(tmpdir, 'roo_sharedStrings.xml'))
+ @sharedstring_doc = File.open(File.join(tmpdir, 'roo_sharedStrings.xml')) do |file|
+ Nokogiri::XML(file)
+ end
+ read_shared_strings(@sharedstring_doc)
+ end
+ @styles_table = []
+ @style_definitions = Array.new # TODO: ??? { |h,k| h[k] = {} }
+ if File.exist?(File.join(tmpdir, 'roo_styles.xml'))
+ @styles_doc = File.open(File.join(tmpdir, 'roo_styles.xml')) do |file|
+ Nokogiri::XML(file)
+ end
+ read_styles(@styles_doc)
+ end
+ @sheet_doc = @sheet_files.map do |item|
+ File.open(item) do |file|
+ Nokogiri::XML(file)
+ end
+ end
+ @comments_doc = @comments_files.map do |item|
+ File.open(item) do |file|
+ Nokogiri::XML(file)
+ end
+ end
end
- filename = open_from_uri(filename) if filename[0,7] == "http://"
- filename = unzip(filename) if packed and packed == :zip
- @cells_read = Hash.new
- @filename = filename
- unless File.file?(@filename)
- FileUtils::rm_r(@tmpdir)
- raise IOError, "file #{@filename} does not exist"
- end
- @@nr += 1
- @file_nr = @@nr
- @comments_files = Array.new
- extract_content(@filename)
- file = File.new(File.join(@tmpdir, @file_nr.to_s+"_roo_workbook.xml"))
- @workbook_doc = Nokogiri::XML(file)
- file.close
- @shared_table = []
- if File.exist?(File.join(@tmpdir, @file_nr.to_s+'_roo_sharedStrings.xml'))
- file = File.new(File.join(@tmpdir, @file_nr.to_s+'_roo_sharedStrings.xml'))
- @sharedstring_doc = Nokogiri::XML(file)
- file.close
- read_shared_strings(@sharedstring_doc)
- end
- @styles_table = []
- @style_definitions = Array.new # TODO: ??? { |h,k| h[k] = {} }
- if File.exist?(File.join(@tmpdir, @file_nr.to_s+'_roo_styles.xml'))
- file = File.new(File.join(@tmpdir, @file_nr.to_s+'_roo_styles.xml'))
- @styles_doc = Nokogiri::XML(file)
- file.close
- read_styles(@styles_doc)
- end
- @sheet_doc = []
- @sheet_files.each_with_index do |item, i|
- file = File.new(item)
- @sheet_doc[i] = Nokogiri::XML(file)
- file.close
- end
- @comments_doc = []
- @comments_files.each_with_index do |item, i|
- file = File.new(item)
- @comments_doc[i] = Nokogiri::XML(file)
- file.close
- end
- FileUtils::rm_r(@tmpdir)
@default_sheet = self.sheets.first
@cell = Hash.new
@cell_type = Hash.new
@formula = Hash.new
@first_row = Hash.new
@@ -147,36 +135,34 @@
@last_column = Hash.new
@header_line = 1
@excelx_type = Hash.new
@excelx_value = Hash.new
@s_attribute = Hash.new # TODO: ggf. wieder entfernen nur lokal benoetigt
- @label = Hash.new
- @labels_read = false
@comment = Hash.new
@comments_read = Hash.new
end
def method_missing(m,*args)
# is method name a label name
- read_labels unless @labels_read
+ read_labels
if @label.has_key?(m.to_s)
- sheet = @default_sheet unless sheet
+ sheet ||= @default_sheet
read_cells(sheet) unless @cells_read[sheet]
row,col = label(m.to_s)
cell(row,col)
else
# call super for methods like #a1
super
end
end
-
+
# Returns the content of a spreadsheet-cell.
# (1,1) is the upper left corner.
# (1,1), (1,'A'), ('A',1), ('a',1) all refers to the
# cell at the first line and first row.
def cell(row, col, sheet=nil)
- sheet = @default_sheet unless sheet
+ sheet ||= @default_sheet
read_cells(sheet) 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)
@@ -191,11 +177,11 @@
# Returns the formula at (row,col).
# Returns nil if there is no formula.
# The method #formula? checks if there is a formula.
def formula(row,col,sheet=nil)
- sheet = @default_sheet unless sheet
+ sheet ||= @default_sheet
read_cells(sheet) unless @cells_read[sheet]
row,col = normalize(row,col)
if @formula[sheet][[row,col]] == nil
return nil
else
@@ -203,20 +189,20 @@
end
end
# true, if there is a formula
def formula?(row,col,sheet=nil)
- sheet = @default_sheet unless sheet
+ sheet ||= @default_sheet
read_cells(sheet) unless @cells_read[sheet]
row,col = normalize(row,col)
formula(row,col) != nil
end
# returns each formula in the selected sheet as an array of elements
# [row, col, formula]
def formulas(sheet=nil)
- sheet = @default_sheet unless sheet
+ sheet ||= @default_sheet
read_cells(sheet) unless @cells_read[sheet]
if @formula[sheet]
@formula[sheet].each.collect do |elem|
[elem[0][0], elem[0][1], elem[1]]
end
@@ -225,51 +211,33 @@
end
end
class Font
attr_accessor :bold, :italic, :underline
-
+
def bold?
@bold == true
end
-
- def italic?
+
+ def italic?
@italic == true
end
-
+
def underline?
@underline == true
- end
+ end
end
-
+
# Given a cell, return the cell's style
def font(row, col, sheet=nil)
- sheet = @default_sheet unless sheet
+ sheet ||= @default_sheet
read_cells(sheet) unless @cells_read[sheet]
row,col = normalize(row,col)
s_attribute = @s_attribute[sheet][[row,col]]
s_attribute ||= 0
s_attribute = s_attribute.to_i
@style_definitions[s_attribute]
- end
-
- # 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:
- sheet = @default_sheet unless sheet
- read_cells(sheet) unless @cells_read[sheet]
- row,col = normalize(row,col)
- set_value(row,col,value,sheet)
- if value.class == Fixnum
- set_type(row,col,:float,sheet)
- elsif value.class == String
- set_type(row,col,:string,sheet)
- elsif value.class == Float
- set_type(row,col,:string,sheet)
- else
- raise ArgumentError, "Type for "+value.to_s+" not set"
- end
end
# returns the type of a cell:
# * :float
# * :string,
@@ -277,11 +245,11 @@
# * :percentage
# * :formula
# * :time
# * :datetime
def celltype(row,col,sheet=nil)
- sheet = @default_sheet unless sheet
+ sheet ||= @default_sheet
read_cells(sheet) unless @cells_read[sheet]
row,col = normalize(row,col)
if @formula[sheet][[row,col]]
return :formula
else
@@ -289,112 +257,104 @@
end
end
# returns the internal type of an excel cell
# * :numeric_or_formula
- # * :string
- # Note: this is only available within the Excelx class
+ # * :string
+ # Note: this is only available within the Excelx class
def excelx_type(row,col,sheet=nil)
- sheet = @default_sheet unless sheet
+ sheet ||= @default_sheet
read_cells(sheet) unless @cells_read[sheet]
row,col = normalize(row,col)
return @excelx_type[sheet][[row,col]]
end
-
+
# returns the internal value of an excelx cell
- # Note: this is only available within the Excelx class
+ # Note: this is only available within the Excelx class
def excelx_value(row,col,sheet=nil)
- sheet = @default_sheet unless sheet
+ sheet ||= @default_sheet
read_cells(sheet) unless @cells_read[sheet]
row,col = normalize(row,col)
return @excelx_value[sheet][[row,col]]
end
-
+
# returns the internal format of an excel cell
def excelx_format(row,col,sheet=nil)
- sheet = @default_sheet unless sheet
+ sheet ||= @default_sheet
read_cells(sheet) unless @cells_read[sheet]
row,col = normalize(row,col)
s = @s_attribute[sheet][[row,col]]
- result = attribute2format(s).to_s
- result
+ attribute2format(s).to_s
end
-
+
# returns an array of sheet names in the spreadsheet
def sheets
- return_sheets = []
- @workbook_doc.xpath("//*[local-name()='sheet']").each do |sheet|
- return_sheets << sheet['name']
+ @workbook_doc.xpath("//xmlns:sheet").map do |sheet|
+ sheet['name']
end
- return_sheets
end
# shows the internal representation of all cells
# for debugging purposes
def to_s(sheet=nil)
- sheet = @default_sheet unless sheet
+ sheet ||= @default_sheet
read_cells(sheet) unless @cells_read[sheet]
@cell[sheet].inspect
end
# returns the row,col values of the labelled cell
# (nil,nil) if label is not defined
def label(labelname)
- read_labels unless @labels_read
- unless @label.size > 0
+ read_labels
+ if @label.empty? || !@label.has_key?(labelname)
return nil,nil,nil
- end
- if @label.has_key? labelname
+ else
return @label[labelname][1].to_i,
- GenericSpreadsheet.letter_to_number(@label[labelname][2]),
+ Roo::GenericSpreadsheet.letter_to_number(@label[labelname][2]),
@label[labelname][0]
- else
- return nil,nil,nil
end
end
# Returns an array which all labels. Each element is an array with
- # [labelname, [sheetname,row,col]]
+ # [labelname, [row,col,sheetname]]
def labels
- # sheet = @default_sheet unless sheet
+ # sheet ||= @default_sheet
# read_cells(sheet) unless @cells_read[sheet]
- read_labels unless @labels_read
- result = []
- @label.each do |label|
- result << [ label[0], # name
+ read_labels
+ @label.map do |label|
+ [ label[0], # name
[ label[1][1].to_i, # row
- GenericSpreadsheet.letter_to_number(label[1][2]), # column
+ Roo::GenericSpreadsheet.letter_to_number(label[1][2]), # column
label[1][0], # sheet
] ]
end
- result
end
# returns the comment at (row/col)
# nil if there is no comment
def comment(row,col,sheet=nil)
- sheet = @default_sheet unless sheet
+ sheet ||= @default_sheet
#read_cells(sheet) unless @cells_read[sheet]
read_comments(sheet) unless @comments_read[sheet]
row,col = normalize(row,col)
return nil unless @comment[sheet]
@comment[sheet][[row,col]]
end
# true, if there is a comment
def comment?(row,col,sheet=nil)
- sheet = @default_sheet unless sheet
+ sheet ||= @default_sheet
# read_cells(sheet) unless @cells_read[sheet]
read_comments(sheet) unless @comments_read[sheet]
row,col = normalize(row,col)
comment(row,col) != nil
end
# returns each comment in the selected sheet as an array of elements
# [row, col, comment]
def comments(sheet=nil)
- sheet = @default_sheet unless sheet
+ sheet ||= @default_sheet
read_comments(sheet) unless @comments_read[sheet]
if @comment[sheet]
@comment[sheet].each.collect do |elem|
[elem[0][0],elem[0][1],elem[1]]
end
@@ -404,41 +364,42 @@
end
private
# helper function to set the internal representation of cells
- def set_cell_values(sheet,x,y,i,v,vt,formula,tr,str_v,
+ def set_cell_values(sheet,x,y,i,v,value_type,formula,
excelx_type=nil,
excelx_value=nil,
s_attribute=nil)
key = [y,x+i]
- @cell_type[sheet] = {} unless @cell_type[sheet]
- @cell_type[sheet][key] = vt
- @formula[sheet] = {} unless @formula[sheet]
+ @cell_type[sheet] ||= {}
+ @cell_type[sheet][key] = value_type
+ @formula[sheet] ||= {}
@formula[sheet][key] = formula if formula
- @cell[sheet] = {} unless @cell[sheet]
- case @cell_type[sheet][key]
- when :float
- @cell[sheet][key] = v.to_f
- when :string
- @cell[sheet][key] = str_v
- when :date
- @cell[sheet][key] = (Date.new(1899,12,30)+v.to_i).strftime("%Y-%m-%d")
- when :datetime
- @cell[sheet][key] = (DateTime.new(1899,12,30)+v.to_f).strftime("%Y-%m-%d %H:%M:%S")
- when :percentage
- @cell[sheet][key] = v.to_f
- when :time
- @cell[sheet][key] = v.to_f*(24*60*60)
- else
- @cell[sheet][key] = v
- end
- @excelx_type[sheet] = {} unless @excelx_type[sheet]
+ @cell[sheet] ||= {}
+ @cell[sheet][key] =
+ case @cell_type[sheet][key]
+ when :float
+ v.to_f
+ when :string
+ v
+ when :date
+ (Date.new(1899,12,30)+v.to_i).strftime("%Y-%m-%d")
+ when :datetime
+ (DateTime.new(1899,12,30)+v.to_f).strftime("%Y-%m-%d %H:%M:%S")
+ when :percentage
+ v.to_f
+ when :time
+ v.to_f*(24*60*60)
+ else
+ v
+ end
+ @excelx_type[sheet] ||= {}
@excelx_type[sheet][key] = excelx_type
- @excelx_value[sheet] = {} unless @excelx_value[sheet]
+ @excelx_value[sheet] ||= {}
@excelx_value[sheet][key] = excelx_value
- @s_attribute[sheet] = {} unless @s_attribute[sheet]
+ @s_attribute[sheet] ||= {}
@s_attribute[sheet][key] = s_attribute
end
def format2type(format)
format = format.to_s # weil von Typ Nokogiri::XML::Attr
@@ -449,111 +410,91 @@
end
end
# read all cells in the selected sheet
def read_cells(sheet=nil)
- sheet = @default_sheet unless sheet
- sheet_found = false
- raise ArgumentError, "Error: sheet '#{sheet||'nil'}' not valid" if @default_sheet == nil and sheet==nil
- raise RangeError unless self.sheets.include? sheet
- n = self.sheets.index(sheet)
- @sheet_doc[n].xpath("//*[local-name()='c']").each do |c|
+ sheet ||= @default_sheet
+ validate_sheet!(sheet)
+ @sheet_doc[sheets.index(sheet)].xpath("/xmlns:worksheet/xmlns:sheetData/xmlns:row/xmlns:c").each do |c|
s_attribute = c['s'].to_i # should be here
# c: <c r="A5" s="2">
# <v>22606</v>
# </c>, format: , tmp_type: float
- if c['t'] == 's'
- tmp_type = :shared
- elsif c['t'] == 'b'
- tmp_type = :boolean
- # 2011-02-25 BEGIN
- elsif c['t'] == 'str'
- tmp_type = :string
- # 2011-02-25 END
- # 2011-09-15 BEGIN
- elsif c['t'] == 'inlineStr'
- tmp_type = :inlinestr
- # 2011-09-15 END
- else
- s_attribute = c['s'].to_i
- format = attribute2format(s_attribute)
- tmp_type = format2type(format)
- end
+ value_type =
+ case c['t']
+ when 's'
+ :shared
+ when 'b'
+ :boolean
+ # 2011-02-25 BEGIN
+ when 'str'
+ :string
+ # 2011-02-25 END
+ # 2011-09-15 BEGIN
+ when 'inlineStr'
+ :inlinestr
+ # 2011-09-15 END
+ else
+ format = attribute2format(s_attribute)
+ format2type(format)
+ end
formula = nil
c.children.each do |cell|
- # 2011-09-15 BEGIN
- if cell.name == 'is'
+ case cell.name
+ when 'is'
cell.children.each do |is|
if is.name == 't'
inlinestr_content = is.content
- vt = :string
- str_v = inlinestr_content
+ value_type = :string
+ v = inlinestr_content
excelx_type = :string
- y, x = GenericSpreadsheet.split_coordinate(c['r'])
- v = nil
- tr=nil #TODO: ???s
+ y, x = Roo::GenericSpreadsheet.split_coordinate(c['r'])
excelx_value = inlinestr_content #cell.content
- set_cell_values(sheet,x,y,0,v,vt,formula,tr,str_v,excelx_type,excelx_value,s_attribute)
+ set_cell_values(sheet,x,y,0,v,value_type,formula,excelx_type,excelx_value,s_attribute)
end
end
- end
- # 2011-09-15 END
- if cell.name == 'f'
+ when 'f'
formula = cell.content
- end
- if cell.name == 'v'
- if tmp_type == :time or tmp_type == :datetime
- if cell.content.to_f >= 1.0
- if (cell.content.to_f - cell.content.to_f.floor).abs > 0.000001
- tmp_type = :datetime
+ when 'v'
+ if [:time, :datetime].include?(value_type) && cell.content.to_f >= 1.0
+ value_type =
+ if (cell.content.to_f - cell.content.to_f.floor).abs > 0.000001
+ :datetime
else
- tmp_type = :date
+ :date
end
- else
- end
end
excelx_type = [:numeric_or_formula,format.to_s]
excelx_value = cell.content
- if tmp_type == :shared
- vt = :string
- str_v = @shared_table[cell.content.to_i]
- excelx_type = :string
- elsif tmp_type == :boolean
- vt = :boolean
- cell.content.to_i == 1 ? v = 'TRUE' : v = 'FALSE'
- elsif tmp_type == :date
- vt = :date
- v = cell.content
- elsif tmp_type == :time
- vt = :time
- v = cell.content
- elsif tmp_type == :datetime
- vt = :datetime
- v = cell.content
- elsif tmp_type == :formula
- vt = :formula
- v = cell.content.to_f #TODO: !!!!
- # 2011-02-25 BEGIN
- elsif tmp_type == :string
- vt = :string
- str_v = cell.content
- excelx_type = :string
- # 2011-02-25 END
- else
- vt = :float
- v = cell.content
- end
- y, x = GenericSpreadsheet.split_coordinate(c['r'])
- tr=nil #TODO: ???s
- set_cell_values(sheet,x,y,0,v,vt,formula,tr,str_v,excelx_type,excelx_value,s_attribute)
+ v =
+ case value_type
+ when :shared
+ value_type = :string
+ excelx_type = :string
+ @shared_table[cell.content.to_i]
+ when :boolean
+ (cell.content.to_i == 1 ? 'TRUE' : 'FALSE')
+ when :date
+ cell.content
+ when :time
+ cell.content
+ when :datetime
+ cell.content
+ when :formula
+ cell.content.to_f #TODO: !!!!
+ when :string
+ excelx_type = :string
+ cell.content
+ else
+ value_type = :float
+ cell.content
+ end
+ y, x = Roo::GenericSpreadsheet.split_coordinate(c['r'])
+ set_cell_values(sheet,x,y,0,v,value_type,formula,excelx_type,excelx_value,s_attribute)
end
end
end
- sheet_found = true #TODO:
- if !sheet_found
- raise RangeError
- end
@cells_read[sheet] = true
# begin comments
=begin
Datei xl/comments1.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
@@ -597,134 +538,88 @@
#end comments
end
# Reads all comments from a sheet
def read_comments(sheet=nil)
- sheet = @default_sheet unless sheet
- #sheet_found = false
- raise ArgumentError, "Error: sheet '#{sheet||'nil'}' not valid" if @default_sheet == nil and sheet==nil
- raise RangeError unless self.sheets.include? sheet
+ sheet ||= @default_sheet
+ validate_sheet!(sheet)
n = self.sheets.index(sheet)
return unless @comments_doc[n] #>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
- @comments_doc[n].xpath("//*[local-name()='comments']").each do |comment|
- comment.children.each do |cc|
- if cc.name == 'commentList'
- cc.children.each do |commentlist|
- if commentlist.name == 'comment'
- ref = commentlist.attributes['ref'].to_s
- row,col = GenericSpreadsheet.split_coordinate(ref)
- commentlist.children.each do |clc|
- if clc.name == 'text'
- clc.children.each do |text|
- if text.name == 'r'
- text.children.each do |r|
- if r.name == 't'
- comment = r.text
- @comment[sheet] = Hash.new unless @comment[sheet]
- @comment[sheet][[row,col]] = comment
- end
- end
- end
- end
- end
- end
- end
- end
- end
+ @comments_doc[n].xpath("//xmlns:comments/xmlns:commentList/xmlns:comment").each do |comment|
+ ref = comment.attributes['ref'].to_s
+ row,col = Roo::GenericSpreadsheet.split_coordinate(ref)
+ comment.xpath('./xmlns:text/xmlns:r/xmlns:t').each do |text|
+ @comment[sheet] ||= {}
+ @comment[sheet][[row,col]] = text.text
end
end
@comments_read[sheet] = true
end
def read_labels
- @workbook_doc.xpath("//*[local-name()='definedName']").each do |defined_name|
+ @label ||= Hash[@workbook_doc.xpath("//xmlns:definedName").map do |defined_name|
# "Sheet1!$C$5"
- sheet = defined_name.text.split('!').first
- coordinates = defined_name.text.split('!')[1]
- dummy,col,row = coordinates.split('$')
- @label[defined_name['name']] = [sheet,row,col]
- end
- @labels_read = true
+ sheet, coordinates = defined_name.text.split('!$', 2)
+ col,row = coordinates.split('$')
+ [defined_name['name'], [sheet,row,col]]
+ end]
end
- # Checks if the default_sheet exists. If not an RangeError exception is
- # raised
- def check_default_sheet
- sheet_found = false
- raise ArgumentError, "Error: default_sheet not set" if @default_sheet == nil
- sheet_found = true if sheets.include?(@default_sheet)
- if ! sheet_found
- raise RangeError, "sheet '#{@default_sheet}' not found"
- end
- end
-
# Extracts all needed files from the zip file
- def process_zipfile(zipfilename, zip, path='')
+ def process_zipfile(tmpdir, zipfilename, zip, path='')
@sheet_files = []
Zip::ZipFile.open(zipfilename) {|zf|
zf.entries.each {|entry|
if entry.to_s.end_with?('workbook.xml')
- open(@tmpdir+'/'+@file_nr.to_s+'_roo_workbook.xml','wb') {|f|
+ open(tmpdir+'/'+'roo_workbook.xml','wb') {|f|
f << zip.read(entry)
}
end
# if entry.to_s.end_with?('sharedStrings.xml')
# at least one application creates this file with another (incorrect?)
# casing. It doesn't hurt, if we ignore here the correct casing - there
# won't be both names in the archive.
# Changed the casing of all the following filenames.
if entry.to_s.downcase.end_with?('sharedstrings.xml')
- open(@tmpdir+'/'+@file_nr.to_s+'_roo_sharedStrings.xml','wb') {|f|
+ open(tmpdir+'/'+'roo_sharedStrings.xml','wb') {|f|
f << zip.read(entry)
}
end
if entry.to_s.downcase.end_with?('styles.xml')
- open(@tmpdir+'/'+@file_nr.to_s+'_roo_styles.xml','wb') {|f|
+ open(tmpdir+'/'+'roo_styles.xml','wb') {|f|
f << zip.read(entry)
}
end
if entry.to_s.downcase =~ /sheet([0-9]+).xml$/
nr = $1
- open(@tmpdir+'/'+@file_nr.to_s+"_roo_sheet#{nr}",'wb') {|f|
+ open(tmpdir+'/'+"roo_sheet#{nr}",'wb') {|f|
f << zip.read(entry)
}
- @sheet_files[nr.to_i-1] = @tmpdir+'/'+@file_nr.to_s+"_roo_sheet#{nr}"
+ @sheet_files[nr.to_i-1] = tmpdir+'/'+"roo_sheet#{nr}"
end
if entry.to_s.downcase =~ /comments([0-9]+).xml$/
nr = $1
- open(@tmpdir+'/'+@file_nr.to_s+"_roo_comments#{nr}",'wb') {|f|
+ open(tmpdir+'/'+"roo_comments#{nr}",'wb') {|f|
f << zip.read(entry)
}
- @comments_files[nr.to_i-1] = @tmpdir+'/'+@file_nr.to_s+"_roo_comments#{nr}"
+ @comments_files[nr.to_i-1] = tmpdir+'/'+"roo_comments#{nr}"
end
}
}
# return
end
# extract files from the zip file
- def extract_content(zipfilename)
+ def extract_content(tmpdir, zipfilename)
Zip::ZipFile.open(@filename) do |zip|
- process_zipfile(zipfilename,zip)
+ process_zipfile(tmpdir, zipfilename,zip)
end
end
- # sets the value of a cell
- def set_value(row,col,value,sheet=nil)
- sheet = @default_value unless sheet
- @cell[sheet][[row,col]] = value
- end
-
- # sets the type of a cell
- def set_type(row,col,type,sheet=nil)
- sheet = @default_value unless sheet
- @cell_type[sheet][[row,col]] = type
- end
-
# read the shared strings xml document
def read_shared_strings(doc)
- doc.xpath("//*[local-name()='si']").each do |si|
+ doc.xpath("/xmlns:sst/xmlns:si").each do |si|
shared_table_entry = ''
si.children.each do |elem|
if elem.name == 'r' and elem.children
elem.children.each do |r_elem|
if r_elem.name == 't'
@@ -740,64 +635,33 @@
end
end
# read the styles elements of an excelx document
def read_styles(doc)
- @numFmts = []
@cellXfs = []
- fonts = []
-
- doc.xpath("//*[local-name()='numFmt']").each do |numFmt|
- numFmtId = numFmt.attributes['numFmtId']
- formatCode = numFmt.attributes['formatCode']
- @numFmts << [numFmtId, formatCode]
- end
- doc.xpath("//*[local-name()='fonts']").each do |fonts_el|
- fonts_el.children.each do |font_el|
- if font_el == 'font'
- font = Excelx::Font.new
- font_el.each_element do |font_sub_el|
- case font_sub_el.name
- when 'b'
- font.bold = true
- when 'i'
- font.italic = true
- when 'u'
- font.underline = true
- end
- end
- fonts << font
- end
+
+ @numFmts = Hash[doc.xpath("//xmlns:numFmt").map do |numFmt|
+ [numFmt['numFmtId'], numFmt['formatCode']]
+ end]
+ fonts = doc.xpath("//xmlns:fonts/xmlns:font").map do |font_el|
+ Font.new.tap do |font|
+ font.bold = !font_el.xpath('./xmlns:b').empty?
+ font.italic = !font_el.xpath('./xmlns:i').empty?
+ font.underline = !font_el.xpath('./xmlns:u').empty?
end
end
-
- doc.xpath("//*[local-name()='cellXfs']").each do |xfs|
+
+ doc.xpath("//xmlns:cellXfs").each do |xfs|
xfs.children.each do |xf|
- numFmtId = xf['numFmtId']
- @cellXfs << [numFmtId]
- fontId = xf['fontId'].to_i
- @style_definitions << fonts[fontId]
+ @cellXfs << xf['numFmtId']
+ @style_definitions << fonts[xf['fontId'].to_i]
end
end
end
# convert internal excelx attribute to a format
def attribute2format(s)
- result = nil
- @numFmts.each {|nf|
- # to_s weil das eine Nokogiri::XML::Attr und das
- # andere ein String ist
- if nf.first.to_s == @cellXfs[s.to_i].first
- result = nf[1]
- break
- end
- }
- unless result
- id = @cellXfs[s.to_i].first.to_i
- if STANDARD_FORMATS.has_key? id
- result = STANDARD_FORMATS[id]
- end
- end
- result
+ id = @cellXfs[s.to_i]
+ @numFmts[id] || STANDARD_FORMATS[id.to_i]
end
end # class