From 8280a21a23d44aa90177e2bc041d0b8dc8556f4b Mon Sep 17 00:00:00 2001 From: Unit 193 Date: Mon, 12 Jun 2017 03:37:11 -0400 Subject: Import Upstream version 2.7.1 --- lib/roo/excelx/cell/base.rb | 94 ++++++++++++++++++++++++++++++++++ lib/roo/excelx/cell/boolean.rb | 27 ++++++++++ lib/roo/excelx/cell/date.rb | 28 ++++++++++ lib/roo/excelx/cell/datetime.rb | 111 ++++++++++++++++++++++++++++++++++++++++ lib/roo/excelx/cell/empty.rb | 19 +++++++ lib/roo/excelx/cell/number.rb | 87 +++++++++++++++++++++++++++++++ lib/roo/excelx/cell/string.rb | 19 +++++++ lib/roo/excelx/cell/time.rb | 43 ++++++++++++++++ 8 files changed, 428 insertions(+) create mode 100644 lib/roo/excelx/cell/base.rb create mode 100644 lib/roo/excelx/cell/boolean.rb create mode 100644 lib/roo/excelx/cell/date.rb create mode 100644 lib/roo/excelx/cell/datetime.rb create mode 100644 lib/roo/excelx/cell/empty.rb create mode 100644 lib/roo/excelx/cell/number.rb create mode 100644 lib/roo/excelx/cell/string.rb create mode 100644 lib/roo/excelx/cell/time.rb (limited to 'lib/roo/excelx/cell') diff --git a/lib/roo/excelx/cell/base.rb b/lib/roo/excelx/cell/base.rb new file mode 100644 index 0000000..aea8808 --- /dev/null +++ b/lib/roo/excelx/cell/base.rb @@ -0,0 +1,94 @@ +module Roo + class Excelx + class Cell + class Base + attr_reader :cell_type, :cell_value, :value + + # FIXME: I think style should be deprecated. Having a style attribute + # for a cell doesn't really accomplish much. It seems to be used + # when you want to export to excelx. + attr_reader :style + + + # FIXME: Updating a cell's value should be able tochange the cell's type, + # but that isn't currently possible. This will cause weird bugs + # when one changes the value of a Number cell to a String. e.g. + # + # cell = Cell::Number(*args) + # cell.value = 'Hello' + # cell.formatted_value # => Some unexpected value + # + # Here are two possible solutions to such issues: + # 1. Don't allow a cell's value to be updated. Use a method like + # `Sheet.update_cell` instead. The simple solution. + # 2. When `cell.value = ` is called, use injection to try and + # change the type of cell on the fly. But deciding what type + # of value to pass to `cell.value=`. isn't always obvious. e.g. + # `cell.value = Time.now` should convert a cell to a DateTime, + # not a Time cell. Time cells would be hard to recognize because + # they are integers. This approach would require a significant + # change to the code as written. The complex solution. + # + # If the first solution is used, then this method should be + # deprecated. + attr_writer :value + + def initialize(value, formula, excelx_type, style, link, coordinate) + @link = !!link + @cell_value = value + @cell_type = excelx_type + @formula = formula + @style = style + @coordinate = coordinate + @type = :base + @value = link? ? Roo::Link.new(link, value) : value + end + + def type + if formula? + :formula + elsif link? + :link + else + @type + end + end + + def formula? + !!@formula + end + + def link? + !!@link + end + + alias_method :formatted_value, :value + + def to_s + formatted_value + end + + # DEPRECATED: Please use link instead. + def hyperlink + warn '[DEPRECATION] `hyperlink` is deprecated. Please use `link` instead.' + end + + # DEPRECATED: Please use cell_value instead. + def excelx_value + warn '[DEPRECATION] `excelx_value` is deprecated. Please use `cell_value` instead.' + cell_value + end + + # DEPRECATED: Please use cell_type instead. + def excelx_type + warn '[DEPRECATION] `excelx_type` is deprecated. Please use `cell_type` instead.' + cell_type + end + + def empty? + false + end + end + end + end +end diff --git a/lib/roo/excelx/cell/boolean.rb b/lib/roo/excelx/cell/boolean.rb new file mode 100644 index 0000000..fe1f691 --- /dev/null +++ b/lib/roo/excelx/cell/boolean.rb @@ -0,0 +1,27 @@ +module Roo + class Excelx + class Cell + class Boolean < Cell::Base + attr_reader :value, :formula, :format, :cell_type, :cell_value, :link, :coordinate + + def initialize(value, formula, style, link, coordinate) + super(value, formula, nil, style, link, coordinate) + @type = @cell_type = :boolean + @value = link? ? Roo::Link.new(link, value) : create_boolean(value) + end + + def formatted_value + value ? 'TRUE'.freeze : 'FALSE'.freeze + end + + private + + def create_boolean(value) + # FIXME: Using a boolean will cause methods like Base#to_csv to fail. + # Roo is using some method to ignore false/nil values. + value.to_i == 1 ? true : false + end + end + end + end +end diff --git a/lib/roo/excelx/cell/date.rb b/lib/roo/excelx/cell/date.rb new file mode 100644 index 0000000..8e2c6cb --- /dev/null +++ b/lib/roo/excelx/cell/date.rb @@ -0,0 +1,28 @@ +require 'date' + +module Roo + class Excelx + class Cell + class Date < Roo::Excelx::Cell::DateTime + attr_reader :value, :formula, :format, :cell_type, :cell_value, :link, :coordinate + + def initialize(value, formula, excelx_type, style, link, base_date, coordinate) + # NOTE: Pass all arguments to the parent class, DateTime. + super + @type = :date + @format = excelx_type.last + @value = link? ? Roo::Link.new(link, value) : create_date(base_date, value) + end + + private + + def create_date(base_date, value) + date = base_date + value.to_i + yyyy, mm, dd = date.strftime('%Y-%m-%d').split('-') + + ::Date.new(yyyy.to_i, mm.to_i, dd.to_i) + end + end + end + end +end diff --git a/lib/roo/excelx/cell/datetime.rb b/lib/roo/excelx/cell/datetime.rb new file mode 100644 index 0000000..35d93ac --- /dev/null +++ b/lib/roo/excelx/cell/datetime.rb @@ -0,0 +1,111 @@ +require 'date' + +module Roo + class Excelx + class Cell + class DateTime < Cell::Base + attr_reader :value, :formula, :format, :cell_value, :link, :coordinate + + def initialize(value, formula, excelx_type, style, link, base_date, coordinate) + super(value, formula, excelx_type, style, link, coordinate) + @type = :datetime + @format = excelx_type.last + @value = link? ? Roo::Link.new(link, value) : create_datetime(base_date, value) + end + + # Public: Returns formatted value for a datetime. Format's can be an + # standard excel format, or a custom format. + # + # Standard formats follow certain conventions. Date fields for + # days, months, and years are separated with hyhens or + # slashes ("-", /") (e.g. 01-JAN, 1/13/15). Time fields for + # hours, minutes, and seconds are separated with a colon (e.g. + # 12:45:01). + # + # If a custom format follows those conventions, then the custom + # format will be used for the a cell's formatted value. + # Otherwise, the formatted value will be in the following + # format: 'YYYY-mm-dd HH:MM:SS' (e.g. "2015-07-10 20:33:15"). + # + # Examples + # formatted_value #=> '01-JAN' + # + # Returns a String representation of a cell's value. + def formatted_value + formatter = @format.downcase.split(' ').map do |part| + if (parsed_format = parse_date_or_time_format(part)) + parsed_format + else + warn 'Unable to parse custom format. Using "YYYY-mm-dd HH:MM:SS" format.' + return @value.strftime('%F %T') + end + end.join(' ') + + @value.strftime(formatter) + end + + private + + def parse_date_or_time_format(part) + date_regex = /(?[dmy]+[\-\/][dmy]+([\-\/][dmy]+)?)/ + time_regex = /(?