aboutsummaryrefslogtreecommitdiffstats
path: root/lib/roo/excelx/cell
diff options
context:
space:
mode:
Diffstat (limited to 'lib/roo/excelx/cell')
-rw-r--r--lib/roo/excelx/cell/base.rb38
-rw-r--r--lib/roo/excelx/cell/boolean.rb15
-rw-r--r--lib/roo/excelx/cell/date.rb14
-rw-r--r--lib/roo/excelx/cell/datetime.rb32
-rw-r--r--lib/roo/excelx/cell/empty.rb5
-rw-r--r--lib/roo/excelx/cell/number.rb69
-rw-r--r--lib/roo/excelx/cell/string.rb6
-rw-r--r--lib/roo/excelx/cell/time.rb7
8 files changed, 101 insertions, 85 deletions
diff --git a/lib/roo/excelx/cell/base.rb b/lib/roo/excelx/cell/base.rb
index aea8808..51fc75f 100644
--- a/lib/roo/excelx/cell/base.rb
+++ b/lib/roo/excelx/cell/base.rb
@@ -1,13 +1,18 @@
+# frozen_string_literal: true
+
+require "roo/helpers/default_attr_reader"
+
module Roo
class Excelx
class Cell
class Base
+ extend Roo::Helpers::DefaultAttrReader
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
+ attr_reader_with_default default_type: :base, style: 1
# FIXME: Updating a cell's value should be able tochange the cell's type,
@@ -34,14 +39,12 @@ module Roo
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
+ @cell_type = excelx_type if excelx_type
+ @formula = formula if formula
+ @style = style unless style == 1
@coordinate = coordinate
- @type = :base
- @value = link? ? Roo::Link.new(link, value) : value
+ @value = link ? Roo::Link.new(link, value) : value
end
def type
@@ -50,16 +53,16 @@ module Roo
elsif link?
:link
else
- @type
+ default_type
end
end
def formula?
- !!@formula
+ !!(defined?(@formula) && @formula)
end
def link?
- !!@link
+ Roo::Link === @value
end
alias_method :formatted_value, :value
@@ -68,9 +71,16 @@ module Roo
formatted_value
end
- # DEPRECATED: Please use link instead.
+ # DEPRECATED: Please use link? instead.
def hyperlink
- warn '[DEPRECATION] `hyperlink` is deprecated. Please use `link` instead.'
+ warn '[DEPRECATION] `hyperlink` is deprecated. Please use `link?` instead.'
+ link?
+ end
+
+ # DEPRECATED: Please use link? instead.
+ def link
+ warn '[DEPRECATION] `link` is deprecated. Please use `link?` instead.'
+ link?
end
# DEPRECATED: Please use cell_value instead.
@@ -88,6 +98,10 @@ module Roo
def empty?
false
end
+
+ def presence
+ empty? ? nil : self
+ end
end
end
end
diff --git a/lib/roo/excelx/cell/boolean.rb b/lib/roo/excelx/cell/boolean.rb
index fe1f691..2cdfc22 100644
--- a/lib/roo/excelx/cell/boolean.rb
+++ b/lib/roo/excelx/cell/boolean.rb
@@ -1,17 +1,20 @@
+# frozen_string_literal: true
+
module Roo
class Excelx
class Cell
class Boolean < Cell::Base
- attr_reader :value, :formula, :format, :cell_type, :cell_value, :link, :coordinate
+ attr_reader :value, :formula, :format, :cell_value, :coordinate
+
+ attr_reader_with_default default_type: :boolean, cell_type: :boolean
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)
+ super(value, formula, nil, style, nil, coordinate)
+ @value = link ? Roo::Link.new(link, value) : create_boolean(value)
end
def formatted_value
- value ? 'TRUE'.freeze : 'FALSE'.freeze
+ value ? 'TRUE' : 'FALSE'
end
private
@@ -19,7 +22,7 @@ module Roo
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
+ value.to_i == 1
end
end
end
diff --git a/lib/roo/excelx/cell/date.rb b/lib/roo/excelx/cell/date.rb
index 8e2c6cb..8627bc5 100644
--- a/lib/roo/excelx/cell/date.rb
+++ b/lib/roo/excelx/cell/date.rb
@@ -4,23 +4,23 @@ module Roo
class Excelx
class Cell
class Date < Roo::Excelx::Cell::DateTime
- attr_reader :value, :formula, :format, :cell_type, :cell_value, :link, :coordinate
+ attr_reader :value, :formula, :format, :cell_type, :cell_value, :coordinate
+
+ attr_reader_with_default default_type: :date
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)
+ @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('-')
+ def create_datetime(_,_); end
- ::Date.new(yyyy.to_i, mm.to_i, dd.to_i)
+ def create_date(base_date, value)
+ base_date + value.to_i
end
end
end
diff --git a/lib/roo/excelx/cell/datetime.rb b/lib/roo/excelx/cell/datetime.rb
index 35d93ac..63f3260 100644
--- a/lib/roo/excelx/cell/datetime.rb
+++ b/lib/roo/excelx/cell/datetime.rb
@@ -1,16 +1,21 @@
+# frozen_string_literal: true
+
require 'date'
module Roo
class Excelx
class Cell
class DateTime < Cell::Base
- attr_reader :value, :formula, :format, :cell_value, :link, :coordinate
+ SECONDS_IN_DAY = 60 * 60 * 24
+
+ attr_reader :value, :formula, :format, :cell_value, :coordinate
- def initialize(value, formula, excelx_type, style, link, base_date, coordinate)
- super(value, formula, excelx_type, style, link, coordinate)
- @type = :datetime
+ attr_reader_with_default default_type: :datetime
+
+ def initialize(value, formula, excelx_type, style, link, base_timestamp, coordinate)
+ super(value, formula, excelx_type, style, nil, coordinate)
@format = excelx_type.last
- @value = link? ? Roo::Link.new(link, value) : create_datetime(base_date, value)
+ @value = link ? Roo::Link.new(link, value) : create_datetime(base_timestamp, value)
end
# Public: Returns formatted value for a datetime. Format's can be an
@@ -78,7 +83,7 @@ module Roo
TIME_FORMATS = {
'hh' => '%H', # Hour (24): 01
- 'h' => '%-k'.freeze, # Hour (24): 1
+ 'h' => '%-k', # Hour (24): 1
# 'hh'.freeze => '%I'.freeze, # Hour (12): 08
# 'h'.freeze => '%-l'.freeze, # Hour (12): 8
'mm' => '%M', # Minute: 01
@@ -92,18 +97,9 @@ module Roo
'0' => '%1N' # Fractional Seconds: tenths.
}
- def create_datetime(base_date, value)
- date = base_date + value.to_f.round(6)
- datetime_string = date.strftime('%Y-%m-%d %H:%M:%S.%N')
- t = round_datetime(datetime_string)
-
- ::DateTime.civil(t.year, t.month, t.day, t.hour, t.min, t.sec)
- end
-
- def round_datetime(datetime_string)
- /(?<yyyy>\d+)-(?<mm>\d+)-(?<dd>\d+) (?<hh>\d+):(?<mi>\d+):(?<ss>\d+.\d+)/ =~ datetime_string
-
- ::Time.new(yyyy, mm, dd, hh, mi, ss.to_r).round(0)
+ def create_datetime(base_timestamp, value)
+ timestamp = (base_timestamp + (value.to_f.round(6) * SECONDS_IN_DAY)).round(0)
+ ::Time.at(timestamp).utc.to_datetime
end
end
end
diff --git a/lib/roo/excelx/cell/empty.rb b/lib/roo/excelx/cell/empty.rb
index 49a20e7..f0c683c 100644
--- a/lib/roo/excelx/cell/empty.rb
+++ b/lib/roo/excelx/cell/empty.rb
@@ -3,10 +3,11 @@ module Roo
class Excelx
class Cell
class Empty < Cell::Base
- attr_reader :value, :formula, :format, :cell_type, :cell_value, :hyperlink, :coordinate
+ attr_reader :value, :formula, :format, :cell_type, :cell_value, :coordinate
+
+ attr_reader_with_default default_type: nil, style: nil
def initialize(coordinate)
- @value = @formula = @format = @cell_type = @cell_value = @hyperlink = nil
@coordinate = coordinate
end
diff --git a/lib/roo/excelx/cell/number.rb b/lib/roo/excelx/cell/number.rb
index 2015562..9f23c4f 100644
--- a/lib/roo/excelx/cell/number.rb
+++ b/lib/roo/excelx/cell/number.rb
@@ -1,16 +1,19 @@
+# frozen_string_literal: true
+
module Roo
class Excelx
class Cell
class Number < Cell::Base
- attr_reader :value, :formula, :format, :cell_value, :link, :coordinate
+ attr_reader :value, :formula, :format, :cell_value, :coordinate
+
+ # FIXME: change default_type to number. This will break brittle tests.
+ attr_reader_with_default default_type: :float
def initialize(value, formula, excelx_type, style, link, coordinate)
super
- # FIXME: change @type to number. This will break brittle tests.
# FIXME: Excelx_type is an array, but the first value isn't used.
- @type = :float
@format = excelx_type.last
- @value = link? ? Roo::Link.new(link, value) : create_numeric(value)
+ @value = link ? Roo::Link.new(link, value) : create_numeric(value)
end
def create_numeric(number)
@@ -21,48 +24,50 @@ module Roo
when /\.0/
Float(number)
else
- (number.include?('.') || (/\A[-+]?\d+E[-+]\d+\z/i =~ number)) ? Float(number) : Integer(number)
+ (number.include?('.') || (/\A[-+]?\d+E[-+]?\d+\z/i =~ number)) ? Float(number) : Integer(number, 10)
end
end
def formatted_value
return @cell_value if Excelx::ERROR_VALUES.include?(@cell_value)
- formatter = formats[@format]
+ formatter = generate_formatter(@format)
if formatter.is_a? Proc
formatter.call(@cell_value)
- elsif zero_padded_number?
- "%0#{@format.size}d" % @cell_value
else
Kernel.format(formatter, @cell_value)
end
end
- def formats
+ def generate_formatter(format)
# FIXME: numbers can be other colors besides red:
# [BLACK], [BLUE], [CYAN], [GREEN], [MAGENTA], [RED], [WHITE], [YELLOW], [COLOR n]
- {
- 'General' => '%.0f',
- '0' => '%.0f',
- '0.00' => '%.2f',
- '0.000000' => '%.6f',
- '#,##0' => number_format('%.0f'),
- '#,##0.00' => number_format('%.2f'),
- '0%' => proc do |number|
- Kernel.format('%d%', number.to_f * 100)
- end,
- '0.00%' => proc do |number|
- Kernel.format('%.2f%', number.to_f * 100)
- end,
- '0.00E+00' => '%.2E',
- '#,##0 ;(#,##0)' => number_format('%.0f', '(%.0f)'),
- '#,##0 ;[Red](#,##0)' => number_format('%.0f', '[Red](%.0f)'),
- '#,##0.00;(#,##0.00)' => number_format('%.2f', '(%.2f)'),
- '#,##0.00;[Red](#,##0.00)' => number_format('%.2f', '[Red](%.2f)'),
+ case format
+ when /^General$/i then '%.0f'
+ when '0' then '%.0f'
+ when /^(0+)$/ then "%0#{$1.size}d"
+ when /^0\.(0+)$/ then "%.#{$1.size}f"
+ when '#,##0' then number_format('%.0f')
+ when '#,##0.00' then number_format('%.2f')
+ when '0%'
+ proc do |number|
+ Kernel.format('%d%%', number.to_f * 100)
+ end
+ when '0.00%'
+ proc do |number|
+ Kernel.format('%.2f%%', number.to_f * 100)
+ end
+ when '0.00E+00' then '%.2E'
+ when '#,##0 ;(#,##0)' then number_format('%.0f', '(%.0f)')
+ when '#,##0 ;[Red](#,##0)' then number_format('%.0f', '[Red](%.0f)')
+ when '#,##0.00;(#,##0.00)' then number_format('%.2f', '(%.2f)')
+ when '#,##0.00;[Red](#,##0.00)' then number_format('%.2f', '[Red](%.2f)')
# FIXME: not quite sure what the format should look like in this case.
- '##0.0E+0' => '%.1E',
- '@' => proc { |number| number }
- }
+ when '##0.0E+0' then '%.1E'
+ when '@' then proc { |number| number }
+ else
+ raise "Unknown format: #{format.inspect}"
+ end
end
private
@@ -77,10 +82,6 @@ module Roo
Kernel.format(formatter, number).reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse
end
end
-
- def zero_padded_number?
- @format[/0+/] == @format
- end
end
end
end
diff --git a/lib/roo/excelx/cell/string.rb b/lib/roo/excelx/cell/string.rb
index 7967806..dacf0b6 100644
--- a/lib/roo/excelx/cell/string.rb
+++ b/lib/roo/excelx/cell/string.rb
@@ -2,12 +2,12 @@ module Roo
class Excelx
class Cell
class String < Cell::Base
- attr_reader :value, :formula, :format, :cell_type, :cell_value, :link, :coordinate
+ attr_reader :value, :formula, :format, :cell_value, :coordinate
+
+ attr_reader_with_default default_type: :string, cell_type: :string
def initialize(value, formula, style, link, coordinate)
super(value, formula, nil, style, link, coordinate)
- @type = @cell_type = :string
- @value = link? ? Roo::Link.new(link, value) : value
end
def empty?
diff --git a/lib/roo/excelx/cell/time.rb b/lib/roo/excelx/cell/time.rb
index d661ab8..a1f0864 100644
--- a/lib/roo/excelx/cell/time.rb
+++ b/lib/roo/excelx/cell/time.rb
@@ -4,15 +4,16 @@ module Roo
class Excelx
class Cell
class Time < Roo::Excelx::Cell::DateTime
- attr_reader :value, :formula, :format, :cell_value, :link, :coordinate
+ attr_reader :value, :formula, :format, :cell_value, :coordinate
+
+ attr_reader_with_default default_type: :time
def initialize(value, formula, excelx_type, style, link, base_date, coordinate)
# NOTE: Pass all arguments to DateTime super class.
super
- @type = :time
@format = excelx_type.last
@datetime = create_datetime(base_date, value)
- @value = link? ? Roo::Link.new(link, value) : (value.to_f * 86_400).to_i
+ @value = link ? Roo::Link.new(link, value) : (value.to_f * 86_400).to_i
end
def formatted_value