Class: Xlsxrb::Elements::Cell

Inherits:
Data
  • Object
show all
Defined in:
lib/xlsxrb/elements/cell.rb

Overview

Represents a single cell in a worksheet. All indices are 0-based.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(row_index:, column_index:, value: nil, formula: nil, style_index: nil, unmapped_data: {}, errors: nil) ⇒ Cell

Returns a new instance of Cell.



10
11
12
13
14
15
# File 'lib/xlsxrb/elements/cell.rb', line 10

def initialize(row_index:, column_index:, value: nil, formula: nil, style_index: nil, unmapped_data: {}, errors: nil)
  computed_errors = errors || self.class.validate(row_index, column_index, value)
  computed_errors = computed_errors.freeze unless computed_errors.frozen?
  super(row_index: row_index, column_index: column_index, value: value, formula: formula,
        style_index: style_index, unmapped_data: unmapped_data, errors: computed_errors)
end

Instance Attribute Details

#column_indexObject (readonly)

Returns the value of attribute column_index

Returns:

  • (Object)

    the current value of column_index



9
10
11
# File 'lib/xlsxrb/elements/cell.rb', line 9

def column_index
  @column_index
end

#errorsObject (readonly)

Returns the value of attribute errors

Returns:

  • (Object)

    the current value of errors



9
10
11
# File 'lib/xlsxrb/elements/cell.rb', line 9

def errors
  @errors
end

#formulaObject (readonly)

Returns the value of attribute formula

Returns:

  • (Object)

    the current value of formula



9
10
11
# File 'lib/xlsxrb/elements/cell.rb', line 9

def formula
  @formula
end

#row_indexObject (readonly)

Returns the value of attribute row_index

Returns:

  • (Object)

    the current value of row_index



9
10
11
# File 'lib/xlsxrb/elements/cell.rb', line 9

def row_index
  @row_index
end

#style_indexObject (readonly)

Returns the value of attribute style_index

Returns:

  • (Object)

    the current value of style_index



9
10
11
# File 'lib/xlsxrb/elements/cell.rb', line 9

def style_index
  @style_index
end

#unmapped_dataObject (readonly)

Returns the value of attribute unmapped_data

Returns:

  • (Object)

    the current value of unmapped_data



9
10
11
# File 'lib/xlsxrb/elements/cell.rb', line 9

def unmapped_data
  @unmapped_data
end

#valueObject (readonly)

Returns the value of attribute value

Returns:

  • (Object)

    the current value of value



9
10
11
# File 'lib/xlsxrb/elements/cell.rb', line 9

def value
  @value
end

Class Method Details

.column_index(letter) ⇒ Object

Converts a column letter (e.g. "A", :AA) to a 0-based column index. If passed an integer or string/symbol representing an integer, it validates and returns the integer.

Raises:

  • (ArgumentError)


103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/xlsxrb/elements/cell.rb', line 103

def self.column_index(letter)
  if letter.is_a?(Integer)
    raise ArgumentError, "Column index must be >= 0, got #{letter}" if letter.negative?

    return letter
  end

  str = letter.to_s
  if str.match?(/\A-?\d+\z/)
    val = str.to_i
    raise ArgumentError, "Column index must be >= 0, got #{val}" if val.negative?

    return val
  end

  raise ArgumentError, "Invalid column letter: #{letter.inspect}" unless str.match?(/\A[a-zA-Z]+\z/)

  str.upcase.chars.reduce(0) { |acc, c| (acc * 26) + (c.ord - "A".ord + 1) } - 1
end

.column_letter(index) ⇒ Object

Converts a 0-based column index to a letter (0 -> "A", 25 -> "Z", 26 -> "AA").

Raises:

  • (ArgumentError)


86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/xlsxrb/elements/cell.rb', line 86

def self.column_letter(index)
  raise ArgumentError, "Column index must be a non-negative Integer, got #{index.inspect}" unless index.is_a?(Integer) && index >= 0

  @column_letters[index] || begin
    result = +""
    i = index
    loop do
      result.prepend(("A".ord + (i % 26)).chr)
      i = (i / 26) - 1
      break if i.negative?
    end
    result
  end
end

.parse_ref(ref) ⇒ Object

Parses an Excel-style reference to [row_index, col_index] (both 0-based).



124
125
126
127
128
129
130
131
# File 'lib/xlsxrb/elements/cell.rb', line 124

def self.parse_ref(ref)
  match = ref.match(/\A([A-Z]+)(\d+)\z/)
  return nil unless match

  col = match[1].chars.reduce(0) { |acc, c| (acc * 26) + (c.ord - "A".ord + 1) } - 1
  row = match[2].to_i - 1
  [row, col]
end

.validate(row_index, column_index, value) ⇒ Object



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/xlsxrb/elements/cell.rb', line 133

def self.validate(row_index, column_index, value)
  if row_index.is_a?(Integer) && row_index >= 0 && row_index < 1_048_576 &&
     column_index.is_a?(Integer) && column_index >= 0 && column_index < 16_384 &&
     (value.nil? || value.is_a?(String) || value.is_a?(Numeric) || value == true || value == false || value.is_a?(Date) || value.is_a?(Time) || value.is_a?(Formula) || (value.is_a?(Hash) && value.key?(:formula)) || value.is_a?(RichText) || value.is_a?(CellError))
    return [].freeze
  end

  errs = []
  errs << "row_index must be a non-negative Integer (got #{row_index.inspect})" if !row_index.is_a?(Integer) || row_index.negative?
  errs << "column_index must be a non-negative Integer (got #{column_index.inspect})" if !column_index.is_a?(Integer) || column_index.negative?
  errs << "row_index must be < 1048576 (got #{row_index}, max row is 1048575)" if row_index.is_a?(Integer) && row_index >= 1_048_576
  errs << "column_index must be < 16384 (got #{column_index}, max column is XFD=16383)" if column_index.is_a?(Integer) && column_index >= 16_384
  errs << "unsupported value type: #{value.class} (#{value.inspect}) — supported types: String, Numeric, true/false, Date, Time, or nil" unless value.nil? || value.is_a?(String) || value.is_a?(Numeric) || value == true || value == false || value.is_a?(Date) || value.is_a?(Time)
  errs
end

Instance Method Details

#contentObject



26
27
28
# File 'lib/xlsxrb/elements/cell.rb', line 26

def content
  value
end

#refObject

Excel-style reference (e.g. "A1").



22
23
24
# File 'lib/xlsxrb/elements/cell.rb', line 22

def ref
  "#{self.class.column_letter(column_index)}#{row_index + 1}"
end

#to_dateObject



42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/xlsxrb/elements/cell.rb', line 42

def to_date
  return value if value.is_a?(Date)

  # Excel epoch is 1899-12-30
  if value.is_a?(Numeric)
    Date.new(1899, 12, 30) + value.to_i
  else
    begin
      Date.parse(value.to_s)
    rescue StandardError
      nil
    end
  end
end

#to_fObject



38
39
40
# File 'lib/xlsxrb/elements/cell.rb', line 38

def to_f
  value.to_f
end

#to_iObject



34
35
36
# File 'lib/xlsxrb/elements/cell.rb', line 34

def to_i
  value.to_i
end

#to_sObject



30
31
32
# File 'lib/xlsxrb/elements/cell.rb', line 30

def to_s
  value.to_s
end

#to_timeObject



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/xlsxrb/elements/cell.rb', line 57

def to_time
  return value if value.is_a?(Time)

  if value.is_a?(Numeric)
    days = value.to_f
    base_time = Time.utc(1899, 12, 30)
    base_time + (days * 86_400)
  else
    begin
      Time.parse(value.to_s)
    rescue StandardError
      nil
    end
  end
end

#valid?Boolean

Returns:

  • (Boolean)


17
18
19
# File 'lib/xlsxrb/elements/cell.rb', line 17

def valid?
  errors.empty?
end