lib/axlsx/workbook/worksheet/cell.rb in axlsx-1.3.4 vs lib/axlsx/workbook/worksheet/cell.rb in axlsx-1.3.5
- old
+ new
@@ -26,23 +26,29 @@
# @option options [Boolean] extend
# @option options [Boolean] u
# @option options [Symbol] vertAlign must be one of :baseline, :subscript, :superscript
# @option options [Integer] sz
# @option options [String] color an 8 letter rgb specification
+ # @option options [Number] formula_value The value to cache for a formula cell.
# @option options [Symbol] scheme must be one of :none, major, :minor
def initialize(row, value="", options={})
self.row=row
- @value = @font_name = @charset = @family = @b = @i = @strike = @outline = @shadow = nil
- @condense = @u = @vertAlign = @sz = @color = @scheme = @extend = @ssti = nil
+ @value = nil
+ #@value = @font_name = @charset = @family = @b = @i = @strike = @outline = @shadow = nil
+ #@formula_value = @condense = @u = @vertAlign = @sz = @color = @scheme = @extend = @ssti = nil
@styles = row.worksheet.workbook.styles
@row.cells << self
parse_options options
@style ||= 0
@type ||= cell_type_from_value(value)
@value = cast_value(value)
end
+ # this is the cached value for formula cells. If you want the values to render in iOS/Mac OSX preview
+ # you need to set this.
+ attr_accessor :formula_value
+
# An array of available inline styes.
# TODO change this to a hash where each key defines attr name and validator (and any info the validator requires)
# then move it out to a module so we can re-use in in other classes.
# needs to define bla=(v) and bla methods on the class that hook into a
# set_attr method that kicks the suplied validator and updates the instance_variable
@@ -73,18 +79,18 @@
# :string, :integer, or :float to :time conversions always return the original value as a string and set the cells type to :string.
# No support is currently implemented for parsing time strings.
attr_reader :type
# @see type
def type=(v)
- RestrictionValidator.validate "Cell.type", [:date, :time, :float, :integer, :string, :boolean], v
+ RestrictionValidator.validate "Cell.type", [:date, :time, :float, :integer, :string, :boolean, :iso_8601], v
@type=v
self.value = @value unless @value.nil?
end
# The value of this cell.
- # @return [String, Integer, Float, Time] casted value based on cell's type attribute.
+ # @return [String, Integer, Float, Time, Boolean] casted value based on cell's type attribute.
attr_reader :value
# @see value
def value=(v)
#TODO: consider doing value based type determination first?
@value = cast_value(v)
@@ -212,11 +218,11 @@
@color = v.is_a?(Color) ? v : Color.new(:rgb=>v)
@is_text_run = true
end
# The inline sz property for the cell
- # @return [Boolean]
+ # @return [Inteter]
attr_reader :sz
# @see sz
def sz=(v) set_run_style :validate_unsigned_int, :sz, v; end
# The inline vertical alignment property for the cell
@@ -286,71 +292,19 @@
target.r
end
self.row.worksheet.merge_cells "#{self.r}:#{range_end}" unless range_end.nil?
end
- # builds an xml text run based on this cells attributes.
- # @param [String] str The string instance this run will be concated to.
- # @return [String]
- def run_xml_string(str = '')
- if is_text_run?
- data = instance_values.reject{|key, value| value == nil || key == 'value' || key == 'type' }
- keys = data.keys & INLINE_STYLES
- str << "<r><rPr>"
- keys.each do |key|
- case key
- when 'font_name'
- str << "<rFont val='"<< @font_name << "'/>"
- when 'color'
- str << data[key].to_xml_string
- else
- str << "<" << key.to_s << " val='" << data[key].to_s << "'/>"
- end
- end
- str << "</rPr>" << "<t>" << value.to_s << "</t></r>"
- else
- str << "<t>" << value.to_s << "</t>"
- end
- str
- end
-
# Serializes the cell
# @param [Integer] r_index The row index for the cell
# @param [Integer] c_index The cell index in the row.
# @param [String] str The string index the cell content will be appended to. Defaults to empty string.
# @return [String] xml text for the cell
def to_xml_string(r_index, c_index, str = '')
- str << '<c r="' << Axlsx::cell_r(c_index, r_index) << '" s="' << @style.to_s << '" '
- return str << '/>' if @value.nil?
-
- case @type
-
- when :string
- #parse formula
- if @value.start_with?('=')
- str << 't="str"><f>' << @value.to_s.sub('=', '') << '</f>'
- else
- #parse shared
- if @ssti
- str << 't="s"><v>' << @ssti.to_s << '</v>'
- else
- str << 't="inlineStr"><is>' << run_xml_string << '</is>'
- end
- end
- when :date
- # TODO: See if this is subject to the same restriction as Time below
- str << '><v>' << DateTimeConverter::date_to_serial(@value).to_s << '</v>'
- when :time
- str << '><v>' << DateTimeConverter::time_to_serial(@value).to_s << '</v>'
- when :boolean
- str << 't="b"><v>' << @value.to_s << '</v>'
- else
- str << '><v>' << @value.to_s << '</v>'
- end
- str << '</c>'
+ CellSerializer.to_xml_string r_index, c_index, self, str
end
-
+
def is_formula?
@type == :string && @value.to_s.start_with?('=')
end
# This is still not perfect...
@@ -413,22 +367,27 @@
:date
elsif v.is_a?(Time)
:time
elsif v.is_a?(TrueClass) || v.is_a?(FalseClass)
:boolean
- elsif v.to_s.match(/\A[+-]?\d+?\Z/) #numeric
+ elsif v.to_s =~ /\A[+-]?\d+?\Z/ #numeric
:integer
- elsif v.to_s.match(/\A[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?\Z/) #float
+ elsif v.to_s =~ /\A[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?\Z/ #float
:float
+ # \A(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[0-1]|0[1-9]|[1-2][0-9])
+ # T(2[0-3]|[0-1][0-9]):([0-5][0-9]):([0-5][0-9])(\.[0-9]+)?
+ # (Z|[+-](?:2[0-3]|[0-1][0-9]):[0-5][0-9])?\Z
+ elsif v.to_s =~/\A(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[0-1]|0[1-9]|[1-2][0-9])T(2[0-3]|[0-1][0-9]):([0-5][0-9]):([0-5][0-9])(\.[0-9]+)?(Z|[+-](?:2[0-3]|[0-1][0-9]):[0-5][0-9])?\Z/
+ :iso_8601
else
:string
end
end
# Cast the value into this cells data type.
# @note
- # About Time - Time in OOXML is *different* from what you might expect. The history as to why is interesting, but you can safely assume that if you are generating docs on a mac, you will want to specify Workbook.1904 as true when using time typed values.
+ # About Time - Time in OOXML is *different* from what you might expect. The history as to why is interesting, but you can safely assume that if you are generating docs on a mac, you will want to specify Workbook.1904 as true when using time typed values.
# @see Axlsx#date1904
def cast_value(v)
return nil if v.nil?
if @type == :date
self.style = STYLE_DATE if self.style == 0
@@ -440,15 +399,18 @@
v.to_f
elsif @type == :integer
v.to_i
elsif @type == :boolean
v ? 1 : 0
+ elsif @type == :iso_8601
+ #consumer is responsible for ensuring the iso_8601 format when specifying this type
+ v
else
@type = :string
- v.to_s
# TODO find a better way to do this as it accounts for 30% of
# processing time in benchmarking...
- ::CGI.escapeHTML(v.to_s)
+ Axlsx::trust_input ? v.to_s : ::CGI.escapeHTML(v.to_s)
end
end
+
end
end