module Xlsxrb::NumberFormatter
Formats cell values according to OpenXML formatCode strings. Evaluates and converts numeric, currency, percentage, date/time, scientific, and accounting format patterns into string representations.
@api public
Constants
- DATE_PATTERNS
-
Built-in date and time format code strings.
Public Class Methods
(String? format_code, ?Integer? num_fmt_id) → bool
Source
# File lib/xlsxrb/number_formatter.rb, line 136 def date_format?(format_code, num_fmt_id = nil) code = format_code code = Ooxml::Utils::BUILTIN_NUM_FMT_CODES[num_fmt_id] if (code.nil? || code.empty?) && num_fmt_id return false if code.nil? || code.empty? type = format_type(code) %i[date datetime time].include?(type) end
Checks whether a format code string represents a date, datetime, or time pattern.
@param format_code [String, nil] @param num_fmt_id [Integer, nil] @return [Boolean]
(Integer? style_index, untyped styles) → bool
Source
# File lib/xlsxrb/number_formatter.rb, line 211 def date_format_for?(style_index, styles) return styles.date_format?(style_index) if styles.respond_to?(:date_format?) code = format_code_for(style_index, styles) date_format?(code) end
Checks whether a style index represents a date, datetime, or time format.
@param style_index [Integer, nil] @param styles [untyped] @return [Boolean] @api public
(String? format_code, ?Integer? num_fmt_id) → bool
Source
# File lib/xlsxrb/number_formatter.rb, line 152 def date_only_format?(format_code, num_fmt_id = nil) code = format_code code = Ooxml::Utils::BUILTIN_NUM_FMT_CODES[num_fmt_id] if (code.nil? || code.empty?) && num_fmt_id return false if code.nil? || code.empty? format_type(code) == :date end
Checks whether a format code string represents a date-only pattern.
@param format_code [String, nil] @param num_fmt_id [Integer, nil] @return [Boolean] @api public
(Integer? style_index, untyped styles) → bool
Source
# File lib/xlsxrb/number_formatter.rb, line 253 def date_only_format_for?(style_index, styles) return styles.date_only_format?(style_index) if styles.respond_to?(:date_only_format?) code = format_code_for(style_index, styles) date_only_format?(code) end
Checks whether a style index represents a date-only format.
@param style_index [Integer, nil] @param styles [untyped] @return [Boolean] @api public
(String? format_code, ?Integer? num_fmt_id) → bool
Source
# File lib/xlsxrb/number_formatter.rb, line 167 def datetime_format?(format_code, num_fmt_id = nil) code = format_code code = Ooxml::Utils::BUILTIN_NUM_FMT_CODES[num_fmt_id] if (code.nil? || code.empty?) && num_fmt_id return false if code.nil? || code.empty? format_type(code) == :datetime end
Checks whether a format code string represents a datetime pattern.
@param format_code [String, nil] @param num_fmt_id [Integer, nil] @return [Boolean] @api public
(Integer? style_index, untyped styles) → bool
Source
# File lib/xlsxrb/number_formatter.rb, line 225 def datetime_format_for?(style_index, styles) return styles.datetime_format?(style_index) if styles.respond_to?(:datetime_format?) code = format_code_for(style_index, styles) datetime_format?(code) end
Checks whether a style index represents a datetime format.
@param style_index [Integer, nil] @param styles [untyped] @return [Boolean] @api public
(untyped value, ?String? format_code, ?date1904: bool) → String
Source
# File lib/xlsxrb/number_formatter.rb, line 29 def format(value, format_code = nil, date1904: false) return "" if value.nil? return value.code.to_s if value.respond_to?(:code) return value ? "TRUE" : "FALSE" if [true, false].include?(value) code = format_code.to_s.strip return default_format(value) if code.empty? || code.casecmp("general").zero? return format_datetime(value, code) if value.is_a?(Date) || value.is_a?(DateTime) || value.is_a?(Time) if value.is_a?(Numeric) && date_format?(code) dt = if value.is_a?(Float) && (value % 1).positive? Ooxml::Utils.serial_to_datetime(value, date1904: date1904) else Ooxml::Utils.serial_to_date(value.to_i, date1904: date1904) end return format_datetime(dt, code) end return format_number(value, code) if value.is_a?(Numeric) if code.include?("@") sections = split_sections(code) pattern = sections[3] || sections[0] pattern.gsub("@", value.to_s) else value.to_s end end
Formats a cell value according to an Excel format code string.
@param value [Object, nil] The cellโs raw or typed value. @param format_code [String, nil] Excel format code pattern. @param date1904 [Boolean] Whether the 1904 date system is active. @return [String] Formatted string representation. @api public
(Integer? style_index, untyped styles) → String?
Source
# File lib/xlsxrb/number_formatter.rb, line 66 def format_code_for(style_index, styles) return nil unless style_index && styles return styles.number_format(style_index) if styles.respond_to?(:number_format) cell_xfs = styles[:cell_xfs] return nil unless cell_xfs.is_a?(Array) && style_index < cell_xfs.size xf = cell_xfs[style_index] return nil unless xf.is_a?(Hash) num_fmt_id = xf[:num_fmt_id] if (num_fmt_id.nil? || num_fmt_id.zero?) && xf[:xf_id] && styles[:cell_style_xfs].is_a?(Array) parent_xf = styles[:cell_style_xfs][xf[:xf_id]] num_fmt_id = parent_xf[:num_fmt_id] if parent_xf.is_a?(Hash) end return nil unless num_fmt_id num_fmts = styles[:num_fmts] || {} num_fmts[num_fmt_id] || Ooxml::Utils::BUILTIN_NUM_FMT_CODES[num_fmt_id] end
Resolves the format code string for a given style index from a styles definition hash.
@param style_index [Integer, nil] 0-based style index in cellXfs. @param styles [Hash, nil] Parsed styles hash. @return [String, nil] Format code string, or nil if not found. @api public
(String? format_code) → Symbol?
Source
# File lib/xlsxrb/number_formatter.rb, line 94 def format_type(format_code) return nil if format_code.nil? code = format_code.to_s.strip return :general if code.empty? || code.casecmp("general").zero? return :text if code == "@" case code when "mm-dd-yy", "d-mmm-yy", "d-mmm", "mmm-yy", "yyyy\\-mm\\-dd", "yyyy-mm-dd", "m/d/yy", "m/d/yyyy" return :date when "m/d/yy h:mm", "m/d/yyyy h:mm", "yyyy\\-mm\\-dd\\ hh:mm:ss", "yyyy-mm-dd hh:mm:ss" return :datetime when "h:mm AM/PM", "h:mm:ss AM/PM", "h:mm", "h:mm:ss", "mm:ss", "[h]:mm:ss", "mmss.0" return :time end stripped = code.gsub(/"[^"]*"/, "") .gsub(/\\[.]/, "") .gsub(/\[(?!h\]|m\]|s\]|hh\]|mm\]|ss\])[^\]]*\]/i, "") has_date = stripped.match?(/[ydYD]/) || (stripped.match?(/[mM]/) && !stripped.match?(/[hsHS]/)) has_time = stripped.match?(/[hsHS]/) if has_date && has_time :datetime elsif has_date :date elsif has_time :time elsif stripped.include?("@") :text else :number end end
Returns the classified format category for a format code string.
@param format_code [String, nil] Format code string. @return [Symbol, nil] :date, :datetime, :time, :number, :text, :general, or nil. @api public
(Integer? style_index, untyped styles) → Symbol?
Source
# File lib/xlsxrb/number_formatter.rb, line 197 def format_type_for(style_index, styles) return styles.format_type(style_index) if styles.respond_to?(:format_type) code = format_code_for(style_index, styles) format_type(code) end
Returns the format category Symbol for a style index and styles definition.
@param style_index [Integer, nil] @param styles [untyped] @return [Symbol, nil] @api public
(String? format_code, ?Integer? num_fmt_id) → bool
Source
# File lib/xlsxrb/number_formatter.rb, line 182 def time_format?(format_code, num_fmt_id = nil) code = format_code code = Ooxml::Utils::BUILTIN_NUM_FMT_CODES[num_fmt_id] if (code.nil? || code.empty?) && num_fmt_id return false if code.nil? || code.empty? format_type(code) == :time end
Checks whether a format code string represents a time-only pattern.
@param format_code [String, nil] @param num_fmt_id [Integer, nil] @return [Boolean] @api public
(Integer? style_index, untyped styles) → bool
Source
# File lib/xlsxrb/number_formatter.rb, line 239 def time_format_for?(style_index, styles) return styles.time_format?(style_index) if styles.respond_to?(:time_format?) code = format_code_for(style_index, styles) time_format?(code) end
Checks whether a style index represents a time format.
@param style_index [Integer, nil] @param styles [untyped] @return [Boolean] @api public