lib/rspreadsheet/cell.rb in rspreadsheet-0.2.0 vs lib/rspreadsheet/cell.rb in rspreadsheet-0.2.3
- old
+ new
@@ -1,47 +1,109 @@
require 'andand'
+require 'rspreadsheet/xml_tied'
module Rspreadsheet
-
-class RowOrNode
- def mode
- case
- when xmlnode.nil? then :outbound
- when repeated>1 then :repeated
- else :regular
- end
- end
-end
-
-class Cell < RowOrNode
- attr_accessor :worksheet, :rowi, :coli
+
+class Cell < XMLTiedItem
+ attr_accessor :worksheet, :coli, :rowi
+ def xml_repeated_attribute; 'number-columns-repeated' end
+ def xml_items_node_name; 'table-cell' end
+ def xml_options; {:xml_items_node_name => xml_items_node_name, :xml_repeated_attribute => xml_repeated_attribute} end
+ def parent; row end
+ def index; @coli end
+ def set_index(value); @coli=value end
+ def set_rowi(arowi); @rowi = arowi end # this should ONLY be used by parent row
def initialize(aworksheet,arowi,acoli)
+ raise "First parameter should be Worksheet object not #{aworksheet.class}" unless aworksheet.kind_of?(Rspreadsheet::Worksheet)
@worksheet = aworksheet
@rowi = arowi
@coli = acoli
end
def row; @worksheet.rows(rowi) end
def coordinates; [rowi,coli] end
-
- def xmlnode; @worksheet.cellxmlnode(@rowi,@coli) end
+ def to_s; value.to_s end
+ def valuexml; self.valuexmlnode.andand.inner_xml end
+ def valuexmlnode; self.xmlnode.children.first end
+ # use this to find node in cell xml. ex. xmlfind('.//text:a') finds all link nodes
+ def valuexmlfindall(path)
+ valuexmlnode.nil? ? [] : valuexmlnode.find(path)
+ end
+ def valuexmlfindfirst(path)
+ valuexmlfindall(path).first
+ end
+ def inspect
+ "#<Rspreadsheet::Cell:Cell\n row:#{rowi}, col:#{coli} address:#{address}\n type: #{guess_cell_type.to_s}, value:#{value}\n mode: #{mode}\n>"
+ end
def value
gt = guess_cell_type
if (self.mode == :regular) or (self.mode == :repeated)
case
when gt == nil then nil
when gt == Float then xmlnode.attributes['value'].to_f
when gt == String then xmlnode.elements.first.andand.content.to_s
when gt == Date then Date.strptime(xmlnode.attributes['date-value'].to_s, '%Y-%m-%d')
- when gt == 'percentage' then xmlnode.attributes['value'].to_f
+ when gt == :percentage then xmlnode.attributes['value'].to_f
end
elsif self.mode == :outbound
nil
else
raise "Unknown cell mode #{self.mode}"
end
end
- def repeated; (Tools.get_ns_attribute_value(xmlnode, 'table', 'number-columns-repeated') || 1 ).to_i end
+ def value=(avalue)
+ detach_if_needed
+ if self.mode == :regular
+ gt = guess_cell_type(avalue)
+ case
+ when gt == nil then raise 'This value type is not storable to cell'
+ when gt == Float
+ set_type_attribute('float')
+ remove_all_value_attributes_and_content(xmlnode)
+ Tools.set_ns_attribute(xmlnode,'office','value', avalue.to_s)
+ xmlnode << Tools.create_ns_node('text','p', avalue.to_f.to_s)
+ when gt == String then
+ set_type_attribute('string')
+ remove_all_value_attributes_and_content(xmlnode)
+ xmlnode << Tools.create_ns_node('text','p', avalue.to_s)
+ when gt == Date then
+ set_type_attribute('date')
+ remove_all_value_attributes_and_content(xmlnode)
+ Tools.set_ns_attribute(xmlnode,'office','date-value', avalue.strftime('%Y-%m-%d'))
+ xmlnode << Tools.create_ns_node('text','p', avalue.strftime('%Y-%m-%d'))
+ when gt == :percentage
+ set_type_attribute('percentage')
+ remove_all_value_attributes_and_content(xmlnode)
+ Tools.set_ns_attribute(xmlnode,'office','value', '%0.2d%' % avalue.to_f)
+ xmlnode << Tools.create_ns_node('text','p', (avalue.to_f*100).round.to_s+'%')
+ end
+ else
+ raise "Unknown cell mode #{self.mode}"
+ end
+ end
+ def set_type_attribute(typestring)
+ Tools.set_ns_attribute(xmlnode,'office','value-type',typestring)
+ end
+ def remove_all_value_attributes_and_content(node)
+ if att = Tools.get_ns_attribute(node, 'office','value') then att.remove! end
+ if att = Tools.get_ns_attribute(node, 'office','date-value') then att.remove! end
+ node.content=''
+ end
+ def relative(rowdiff,coldiff)
+ @worksheet.cells(self.rowi+rowdiff, self.coli+coldiff)
+ end
+ def type
+ gct = guess_cell_type
+ case
+ when gct == Float then :float
+ when gct == String then :string
+ when gct == Date then :date
+ when gct == :percentage then :percentage
+ when gct == :unassigned then :unassigned
+ when gct == nil then :unknown
+ else :unknown
+ end
+ end
def guess_cell_type(avalue=nil)
# try guessing by value
valueguess = case avalue
when Numeric then Float
when Date then Date
@@ -86,119 +148,59 @@
String
else
nil
end
end
+ elsif valueguess == Float and xmlnode.andand.attributes['value-type'] == 'percentage'
+ result = :percentage
end
result
end
- def detach_if_needed
- if (self.mode == :repeated) or (self.mode == :outbound ) # Cell did not exist individually yet, detach row and create editable cell
- @worksheet.detach_cell_in_xml(rowi,coli)
- end
- end
- def value=(avalue)
- detach_if_needed
- if self.mode == :regular
- gt = guess_cell_type(avalue)
- case
- when gt == nil then raise 'This value type is not storable to cell'
- when gt == Float
- set_type_attribute('float')
- remove_all_value_attributes_and_content(xmlnode)
- Tools.set_ns_attribute(xmlnode,'office','value', avalue.to_s)
- xmlnode << LibXML::XML::Node.new('p', avalue.to_f.to_s, ns_text)
- when gt == String then
- set_type_attribute('string')
- remove_all_value_attributes_and_content(xmlnode)
- xmlnode << LibXML::XML::Node.new('p', avalue.to_s, ns_text)
- when gt == Date then
- set_type_attribute('date')
- remove_all_value_attributes_and_content(xmlnode)
- Tools.set_ns_attribute(xmlnode,'office','date-value', avalue.strftime('%Y-%m-%d'))
- xmlnode << LibXML::XML::Node.new('p', avalue.strftime('%Y-%m-%d'), ns_text)
- when gt == 'percentage'
- set_type_attribute('float')
- remove_all_value_attributes_and_content(xmlnode)
- Tools.set_ns_attribute(xmlnode,'office','value', avalue.to_f.to_s)
- xmlnode << LibXML::XML::Node.new('p', (avalue.to_f*100).round.to_s+'%', ns_text)
- end
- else
- raise "Unknown cell mode #{self.mode}"
- end
+ def format
+ @format ||= CellFormat.new(self)
end
- def set_type_attribute(typestring)
- Tools.set_ns_attribute(xmlnode,'office','value-type',typestring)
+ def address
+ Tools.convert_cell_coordinates_to_address(coordinates)
end
- def remove_all_value_attributes_and_content(node)
- if att = Tools.get_ns_attribute(node, 'office','value') then att.remove! end
- if att = Tools.get_ns_attribute(node, 'office','date-value') then att.remove! end
- node.content=''
+
+end
+
+# proxy object to allow cell.format syntax. Also handles all logic for formats.
+class CellFormat
+ attr_reader :bold
+ def initialize(cell)
+ @bold = false
+ @cell = cell
end
- def ns_table; xmlnode.doc.root.namespaces.find_by_prefix('table') end
- def ns_office; xmlnode.doc.root.namespaces.find_by_prefix('office') end
- def ns_text; xmlnode.doc.root.namespaces.find_by_prefix('text') end
- def relative(rowdiff,coldiff)
- @worksheet.cells(self.rowi+rowdiff, self.coli+coldiff)
+ def cellnode; @cell.xmlnode end
+ def bold=(value)
+ Rspreadsheet::Tools.set_ns_attribute(cellnode,'table','style-name','ce99')
end
- def is_repeated?; mode == :repeated end
- def type
- gct = guess_cell_type
- case
- when gct == Float then :float
- when gct == String then :string
- when gct == Date then :date
- when gct == :percentage then :percentage
- when gct == :unassigned then :unassigned
- when gct == nil then :unknown
- else :unknown
- end
+ def bold; Tools.get_ns_attribute_value(text_style_node,'fo','font-weight') == 'bold' end
+ def italic; Tools.get_ns_attribute_value(text_style_node,'fo','font-style') == 'italic' end
+ def color; Tools.get_ns_attribute_value(text_style_node,'fo','color') end
+ def font_size; Tools.get_ns_attribute_value(text_style_node,'fo','font-size') end
+ def background_color; Tools.get_ns_attribute_value(cell_style_node,'fo','background-color') end
+
+ def unused_cell_style_name
+ last = cellnode.doc.root.find('./office:automatic-styles/style:style').
+ collect {|node| node['name']}.
+ collect{ |name| /^ce(\d*)$/.match(name); $1.andand.to_i}.
+ compact.max
+ "ce#{last+1}"
end
+ def style_name; Tools.get_ns_attribute_value(cellnode,'table','style-name') end
+ def style_node; cellnode.doc.root.find("./office:automatic-styles/style:style[@style:name=\"#{style_name}\"]").first end
+ def text_style_node; cellnode.doc.root.find("./office:automatic-styles/style:style[@style:name=\"#{style_name}\"]/style:text-properties").first end
+ def cell_style_node; cellnode.doc.root.find("./office:automatic-styles/style:style[@style:name=\"#{style_name}\"]/style:table-cell-properties").first end
end
-
-
-# class Cell
-# attr_reader :col, :xmlnode
-# attr_reader :parent_row # for debug only
-# attr_accessor :mode
-# def self.empty_cell_node
-# LibXML::XML::Node.new('table-cell',nil, Tools.get_namespace('table'))
-# end
-# def initialize(aparent_row,coli,axmlnode=nil)
-# raise "First parameter should be Row object not #{aparent_row.class}" unless aparent_row.kind_of?(Rspreadsheet::Row)
-# @parent_row = aparent_row
-# if axmlnode.nil?
-# axmlnode = Cell.empty_cell_node
-# end
-# @xmlnode = axmlnode
-# @col = coli
-# # set @mode
-# @mode = case
-# when !@parent_row.used_col_range.include?(coli) then :outbound
-# when Tools.get_ns_attribute_value(@xmlnode, 'table', 'number-columns-repeated').to_i>1 then :repeated
-# else:regular
-# end
-# end
-# def to_s; value end
-# def cell_xml; self.xmlnode.to_s end
-# def xml; self.xmlnode.children.first.andand.inner_xml end
-# def address; Rspreadsheet::Tools.c2a(row,col) end
-# def row; @parent_row.row end
-# def worksheet; @parent_row.worksheet end
-# # use this to find node in cell xml. ex. xmlfind('.//text:a') finds all link nodes
-# def xmlfindall(path)
-# xmlnode.find(path)
-# end
-# def xmlfindfirst(path)
-# xmlfindall(path).first
-# end
-# # based on @xmlnode and optionally value which is about to be assigned, guesses which type the result should be
-# def inspect
-# "#<Rspreadsheet::Cell:Cell\n row:#{row}, col:#{col} address:#{address}\n type: #{guess_cell_type.to_s}, value:#{value}\n mode: #{mode}\n>"
-# end
-# end
end
+
+
+
+
+