lib/roo/excelx.rb in roo-1.3.11 vs lib/roo/excelx.rb in roo-1.9.0
- old
+ new
@@ -1,13 +1,17 @@
-require 'xml'
+#TODO: require 'xml'
require 'fileutils'
require 'zip/zipfilesystem'
require 'date'
+require 'rubygems'
+require 'nokogiri'
-class String
- def end_with?(str)
- self[-str.length,str.length] == str
+if RUBY_VERSION < '1.9.0'
+ class String
+ def end_with?(str)
+ self[-str.length,str.length] == str
+ end
end
end
class Excelx < GenericSpreadsheet
FORMATS = {
@@ -98,31 +102,37 @@
end
@@nr += 1
@file_nr = @@nr
extract_content(@filename)
file = File.new(File.join(@tmpdir, @file_nr.to_s+"_roo_workbook.xml"))
- @workbook_doc = XML::Parser.io(file).parse
+ # TODO: @workbook_doc = XML::Parser.io(file).parse
+ @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 = XML::Parser.io(file).parse
+ #TODO: @sharedstring_doc = XML::Parser.io(file).parse
+ @sharedstring_doc = Nokogiri::XML(file)
file.close
read_shared_strings(@sharedstring_doc)
end
@styles_table = []
- @style_definitions = Array.new { |h,k| h[k] = {} }
+ @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 = XML::Parser.io(file).parse
+ #TODO: @styles_doc = XML::Parser.io(file).parse
+ @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] = XML::Parser.io(file).parse
+ #TODO: @sheet_doc[i] = XML::Parser.io(file).parse
+ @sheet_doc[i] = Nokogiri::XML(file)
file.close
end
ensure
#if ENV["roo_local"] != "thomas-p"
FileUtils::rm_r(@tmpdir)
@@ -190,27 +200,27 @@
def bold?
@bold == true
end
def italic?
- @italic == true
+ @italic == true
end
def underline?
@underline == true
end
end
# Given a cell, return the cell's style
def font(row, col, sheet=nil)
- sheet = @default_sheet unless 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]
+ sheet = @default_sheet unless 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:
@@ -279,12 +289,14 @@
end
# returns an array of sheet names in the spreadsheet
def sheets
return_sheets = []
- @workbook_doc.find("//*[local-name()='sheet']").each do |sheet|
- return_sheets << sheet.attributes.to_h['name']
+ #TODO: @workbook_doc.find("//*[local-name()='sheet']").each do |sheet|
+ @workbook_doc.xpath("//*[local-name()='sheet']").each do |sheet|
+ #TODO: return_sheets << sheet.attributes.to_h['name']
+ return_sheets << sheet['name']
end
return_sheets
end
# shows the internal representation of all cells
# for debugging purposes
@@ -372,12 +384,12 @@
x = GenericSpreadsheet.letter_to_number(letter)
y = number
return x,y
end
- # read all cells in the selected sheet
def format2type(format)
+ format = format.to_s # weil von Typ Nokogiri::XML::Attr
if FORMATS.has_key? format
FORMATS[format]
else
:float
end
@@ -388,26 +400,38 @@
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].find("//*[local-name()='c']").each do |c|
- s_attribute = c.attributes.to_h['s'].to_i # should be here
- if (c.attributes.to_h['t'] == 's')
- tmp_type = :shared
- elsif (c.attributes.to_h['t'] == 'b')
- tmp_type = :boolean
- else
- # s_attribute = c.attributes.to_h['s'].to_i # was here
- format = attribute2format(s_attribute)
- tmp_type = format2type(format)
- end
+ #TODO: @sheet_doc[n].find("//*[local-name()='c']").each do |c|
+ @sheet_doc[n].xpath("//*[local-name()='c']").each do |c|
+ #TODO: s_attribute = c.attributes.to_h['s'].to_i # should be here
+ s_attribute = c['s'].to_i # should be here
+ #TODO: if (c.attributes.to_h['t'] == 's')
+ # c: <c r="A5" s="2">
+ # <v>22606</v>
+ # </c>, format: , tmp_type: float
+
+ if c['t'] == 's'
+ tmp_type = :shared
+ #TODO: elsif (c.attributes.to_h['t'] == 'b')
+ elsif c['t'] == 'b'
+ tmp_type = :boolean
+ else
+ #s_attribute = c.attributes.to_h['s'].to_i # was here
+ s_attribute = c['s'].to_i # was here
+ format = attribute2format(s_attribute)
+ tmp_type = format2type(format)
+ end
formula = nil
- c.each_element do |cell|
+ #TODO: c.each_element do |cell|
+ c.children.each do |cell|
+ #TODO: if cell.name == 'f'
if cell.name == 'f'
formula = cell.content
end
+ #TODO: if cell.name == 'v'
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
@@ -415,11 +439,11 @@
tmp_type = :date
end
else
end
end
- excelx_type = [:numeric_or_formula,format]
+ 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
@@ -441,11 +465,12 @@
else
vt = :float
v = cell.content
end
#puts "vt: #{vt}" if cell.text.include? "22606.5120"
- x,y = split_coordinate(c.attributes.to_h['r'])
+ #TODO: x,y = split_coordinate(c.attributes.to_h['r'])
+ x,y = 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)
end
end
end
@@ -521,21 +546,23 @@
@cell_type[sheet][[row,col]] = type
end
# read the shared strings xml document
def read_shared_strings(doc)
- doc.find("//*[local-name()='si']").each do |si|
+ #TODO: doc.find("//*[local-name()='si']").each do |si|
+ doc.xpath("//*[local-name()='si']").each do |si|
shared_table_entry = ''
- si.each_element do |elem|
- if (elem.name == 'r')
+ #TODO: si.each_element do |elem|
+ si.children.each do |elem|
+ if elem.name == 'r'
elem.each_element do |r_elem|
- if (r_elem.name == 't')
+ if r_elem.name == 't'
shared_table_entry << r_elem.content
end
end
end
- if (elem.name == 't')
+ if elem.name == 't'
shared_table_entry = elem.content
end
end
@shared_table << shared_table_entry
end
@@ -545,48 +572,60 @@
def read_styles(doc)
@numFmts = []
@cellXfs = []
fonts = []
- doc.find("//*[local-name()='numFmt']").each do |numFmt|
- numFmtId = numFmt.attributes.to_h['numFmtId']
- formatCode = numFmt.attributes.to_h['formatCode']
+ #TODO: doc.find("//*[local-name()='numFmt']").each do |numFmt|
+ doc.xpath("//*[local-name()='numFmt']").each do |numFmt|
+ # TODO: numFmtId = numFmt.attributes.to_h['numFmtId']
+ numFmtId = numFmt.attributes['numFmtId']
+ #TODO: formatCode = numFmt.attributes.to_h['formatCode']
+ formatCode = numFmt.attributes['formatCode']
@numFmts << [numFmtId, formatCode]
end
- doc.find("//*[local-name()='fonts']").each do |fonts_el|
- fonts_el.each_element do |font_el|
- if font_el.name == 'font'
+ #TODO: doc.find("//*[local-name()='fonts']").each do |fonts_el|
+ doc.xpath("//*[local-name()='fonts']").each do |fonts_el|
+ #TODO: fonts_el.each_element do |font_el|
+ fonts_el.children.each do |font_el|
+ #TODO: if font_el.name == 'font'
+ 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
+ when 'b'
+ font.bold = true
+ when 'i'
+ font.italic = true
+ when 'u'
+ font.underline = true
+ end
end
fonts << font
end
end
end
- doc.find("//*[local-name()='cellXfs']").each do |xfs|
- xfs.each do |xf|
- numFmtId = xf.attributes.to_h['numFmtId']
- @cellXfs << [numFmtId]
- fontId = xf.attributes.to_h['fontId'].to_i
- @style_definitions << fonts[fontId]
- end
+ #TODO: doc.find("//*[local-name()='cellXfs']").each do |xfs|
+ doc.xpath("//*[local-name()='cellXfs']").each do |xfs|
+ xfs.children.each do |xf|
+ #TODO: numFmtId = xf.attributes.to_h['numFmtId']
+ numFmtId = xf['numFmtId']
+ @cellXfs << [numFmtId]
+ #TODO: fontId = xf.attributes.to_h['fontId'].to_i
+ fontId = xf['fontId'].to_i
+ @style_definitions << fonts[fontId]
+ end
end
end
# convert internal excelx attribute to a format
def attribute2format(s)
result = nil
@numFmts.each {|nf|
- if nf.first == @cellXfs[s.to_i].first
+ #TODO: if nf.first == @cellXfs[s.to_i].first
+ # 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