aboutsummaryrefslogtreecommitdiffstats
path: root/lib/roo/excelx/cell/number.rb
diff options
context:
space:
mode:
authorLibravatarUnit 193 <unit193@ubuntu.com>2017-06-12 03:37:11 -0400
committerLibravatarUnit 193 <unit193@ubuntu.com>2017-06-12 03:37:11 -0400
commit8280a21a23d44aa90177e2bc041d0b8dc8556f4b (patch)
treedadef7ee085c0e990a5070bd41b6a5b98c97f4fd /lib/roo/excelx/cell/number.rb
Import Upstream version 2.7.1upstream/2.7.1
Diffstat (limited to 'lib/roo/excelx/cell/number.rb')
-rw-r--r--lib/roo/excelx/cell/number.rb87
1 files changed, 87 insertions, 0 deletions
diff --git a/lib/roo/excelx/cell/number.rb b/lib/roo/excelx/cell/number.rb
new file mode 100644
index 0000000..2015562
--- /dev/null
+++ b/lib/roo/excelx/cell/number.rb
@@ -0,0 +1,87 @@
+module Roo
+ class Excelx
+ class Cell
+ class Number < Cell::Base
+ attr_reader :value, :formula, :format, :cell_value, :link, :coordinate
+
+ 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)
+ end
+
+ def create_numeric(number)
+ return number if Excelx::ERROR_VALUES.include?(number)
+ case @format
+ when /%/
+ Float(number)
+ when /\.0/
+ Float(number)
+ else
+ (number.include?('.') || (/\A[-+]?\d+E[-+]\d+\z/i =~ number)) ? Float(number) : Integer(number)
+ end
+ end
+
+ def formatted_value
+ return @cell_value if Excelx::ERROR_VALUES.include?(@cell_value)
+
+ formatter = formats[@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
+ # 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)'),
+ # FIXME: not quite sure what the format should look like in this case.
+ '##0.0E+0' => '%.1E',
+ '@' => proc { |number| number }
+ }
+ end
+
+ private
+
+ def number_format(formatter, negative_formatter = nil)
+ proc do |number|
+ if negative_formatter
+ formatter = number.to_i > 0 ? formatter : negative_formatter
+ number = number.to_f.abs
+ end
+
+ Kernel.format(formatter, number).reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse
+ end
+ end
+
+ def zero_padded_number?
+ @format[/0+/] == @format
+ end
+ end
+ end
+ end
+end