Class: Xlsxrb::Elements::Cell

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

Overview

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

Examples:

Access cell properties

cell = sheet["A1"]
cell.value       # raw value
cell.ref         # "A1"
cell.to_i        # integer value
cell.to_date     # Date value

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: EMPTY_HASH, errors: nil) ⇒ Cell

Returns a new instance of Cell.

Signature:

  • (row_index: Integer, column_index: Integer, ?value: untyped, ?formula: Elements::Formula?, ?style_index: Integer | String | nil, ?unmapped_data: Hash[untyped, untyped], ?errors: Array[String]?) -> void

Parameters:

  • row_index (Integer)

    0-based row index.

  • column_index (Integer)

    0-based column index.

  • value (Object, nil) (defaults to: nil)

    The cell's value.

  • formula (Elements::Formula, nil) (defaults to: nil)

    Optional formula.

  • style_index (Integer, String, nil) (defaults to: nil)

    Style identifier.

  • unmapped_data (Hash) (defaults to: EMPTY_HASH)

    Additional metadata.

  • errors (Array<String>, nil) (defaults to: nil)

    Validation errors.



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

def initialize(row_index:, column_index:, value: nil, formula: nil, style_index: nil, unmapped_data: EMPTY_HASH, 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



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

def column_index
  @column_index
end

#errorsObject (readonly)

Returns the value of attribute errors

Returns:

  • (Object)

    the current value of errors



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

def errors
  @errors
end

#formulaObject (readonly)

Returns the value of attribute formula

Returns:

  • (Object)

    the current value of formula



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

def formula
  @formula
end

#row_indexObject (readonly)

Returns the value of attribute row_index

Returns:

  • (Object)

    the current value of row_index



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

def row_index
  @row_index
end

#style_indexObject (readonly)

Returns the value of attribute style_index

Returns:

  • (Object)

    the current value of style_index



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

def style_index
  @style_index
end

#unmapped_dataObject (readonly)

Returns the value of attribute unmapped_data

Returns:

  • (Object)

    the current value of unmapped_data



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

def unmapped_data
  @unmapped_data
end

#valueObject (readonly)

Returns the value of attribute value

Returns:

  • (Object)

    the current value of value



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

def value
  @value
end

Class Method Details

.column_index(letter) ⇒ Integer

Converts a column letter (e.g. "A", :AA) to a 0-based column index.

Examples:

Cell.column_index("A")  #=> 0
Cell.column_index(:AA)  #=> 26

Signature:

  • (String | Symbol | Integer letter) -> Integer

Parameters:

  • letter (String, Symbol, Integer)

    Column letter or integer index.

Returns:

  • (Integer)

    0-based column index.

Raises:

  • (ArgumentError)


197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/xlsxrb/elements/cell.rb', line 197

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) ⇒ String

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

Examples:

Cell.column_letter(0)  #=> "A"
Cell.column_letter(26) #=> "AA"

Signature:

  • (Integer index) -> String

Parameters:

  • index (Integer)

    0-based column index.

Returns:

  • (String)

    Excel column letter.

Raises:

  • (ArgumentError)


172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/xlsxrb/elements/cell.rb', line 172

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

.members[ :row_index, :column_index, :value, :formula, :style_index, :unmapped_data, :errors ]

Returns:

  • ([ :row_index, :column_index, :value, :formula, :style_index, :unmapped_data, :errors ])


34
# File 'sig/generated/xlsxrb/elements/cell.rbs', line 34

def self.members: () -> [ :row_index, :column_index, :value, :formula, :style_index, :unmapped_data, :errors ]

.new(row_index, column_index, value, formula, style_index, unmapped_data, errors) ⇒ instance .new(row_index:, column_index:, value:, formula:, style_index:, unmapped_data:, errors:) ⇒ instance

Overloads:

  • .new(row_index, column_index, value, formula, style_index, unmapped_data, errors) ⇒ instance

    Parameters:

    • row_index (Object)
    • column_index (Object)
    • value (Object)
    • formula (Object)
    • style_index (Object)
    • unmapped_data (Object)
    • errors (Object)

    Returns:

    • (instance)
  • .new(row_index:, column_index:, value:, formula:, style_index:, unmapped_data:, errors:) ⇒ instance

    Parameters:

    • row_index: (Object)
    • column_index: (Object)
    • value: (Object)
    • formula: (Object)
    • style_index: (Object)
    • unmapped_data: (Object)
    • errors: (Object)

    Returns:

    • (instance)


31
32
# File 'sig/generated/xlsxrb/elements/cell.rbs', line 31

def self.new: (untyped row_index, untyped column_index, untyped value, untyped formula, untyped style_index, untyped unmapped_data, untyped errors) -> instance
| (row_index: untyped, column_index: untyped, value: untyped, formula: untyped, style_index: untyped, unmapped_data: untyped, errors: untyped) -> instance

.parse_ref(ref) ⇒ Array(Integer, Integer)?

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

Examples:

Cell.parse_ref("A1")  #=> [0, 0]
Cell.parse_ref("C10") #=> [9, 2]

Signature:

  • (String? ref) -> [Integer, Integer]?

Parameters:

  • ref (String, nil)

    Excel cell reference.

Returns:

  • (Array(Integer, Integer), nil)

    0-based [row_index, col_index].



227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
# File 'lib/xlsxrb/elements/cell.rb', line 227

def self.parse_ref(ref)
  return nil unless ref

  bytes = ref.b
  len = bytes.bytesize
  col = 0
  i = 0
  while i < len
    b = bytes.getbyte(i)
    if b.between?(65, 90)
      col = (col * 26) + (b - 64)
      i += 1
    elsif b.between?(97, 122)
      col = (col * 26) + (b - 96)
      i += 1
    else
      break
    end
  end
  return nil if i.zero? || i == len

  row = bytes.byteslice(i, len - i).to_i - 1
  [row, col - 1]
end

.validate(row_index, column_index, value) ⇒ Array<String>

Validates cell coordinates and value type against OOXML specifications.

Signature:

  • (untyped row_index, untyped column_index, untyped value) -> Array[String]

Parameters:

  • row_index (Integer)
  • column_index (Integer)
  • value (Object)

Returns:

  • (Array<String>)

    List of errors.



259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
# File 'lib/xlsxrb/elements/cell.rb', line 259

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 EMPTY_ERRORS
  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

#[](key) ⇒ Object?

Access cell attributes by Symbol key.

Signature:

  • (Symbol key) -> untyped

Parameters:

  • key (Symbol)

    Attribute key (:value, :formula, :style_index, :ref, :column_index, :row_index, :type).

Returns:

  • (Object, nil)


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

def [](key)
  case key
  when :value then value
  when :formula then formula
  when :style_index then style_index
  when :ref then ref
  when :column_index then column_index
  when :row_index then row_index
  when :type
    case value
    when String then "s"
    when true, false then "b"
    end
  end
end

#contentObject?

Returns the cell value.

Signature:

  • () -> untyped

Returns:

  • (Object, nil)


78
79
80
# File 'lib/xlsxrb/elements/cell.rb', line 78

def content
  value
end

#members[ :row_index, :column_index, :value, :formula, :style_index, :unmapped_data, :errors ]

Returns:

  • ([ :row_index, :column_index, :value, :formula, :style_index, :unmapped_data, :errors ])


36
# File 'sig/generated/xlsxrb/elements/cell.rbs', line 36

def members: () -> [ :row_index, :column_index, :value, :formula, :style_index, :unmapped_data, :errors ]

#refString

Returns the Excel-style reference (e.g. "A1", "B2").

Signature:

  • () -> String

Returns:

  • (String)


47
48
49
# File 'lib/xlsxrb/elements/cell.rb', line 47

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

#to_dateDate?

Converts the cell value (numeric serial date or date string) to Date.

Signature:

  • () -> Date?

Returns:

  • (Date, nil)


114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/xlsxrb/elements/cell.rb', line 114

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_fFloat

Converts the cell value to Float.

Signature:

  • () -> Float

Returns:

  • (Float)


105
106
107
# File 'lib/xlsxrb/elements/cell.rb', line 105

def to_f
  value.to_f
end

#to_iInteger

Converts the cell value to Integer.

Signature:

  • () -> Integer

Returns:

  • (Integer)


96
97
98
# File 'lib/xlsxrb/elements/cell.rb', line 96

def to_i
  value.to_i
end

#to_sString

Returns the string representation of the cell value.

Signature:

  • () -> String

Returns:

  • (String)


87
88
89
# File 'lib/xlsxrb/elements/cell.rb', line 87

def to_s
  value.to_s
end

#to_timeTime?

Converts the cell value (numeric serial datetime or datetime string) to Time.

Signature:

  • () -> Time?

Returns:

  • (Time, nil)


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

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 whether the cell is valid according to OOXML specifications.

Signature:

  • () -> bool

Returns:

  • (Boolean)


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

def valid?
  errors.empty?
end