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 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: EMPTY_HASH, 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: 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



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)


119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/xlsxrb/elements/cell.rb', line 119

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)


102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/xlsxrb/elements/cell.rb', line 102

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 ])


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

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)


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

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

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



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/xlsxrb/elements/cell.rb', line 140

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



165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/xlsxrb/elements/cell.rb', line 165

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



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/xlsxrb/elements/cell.rb', line 26

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



42
43
44
# File 'lib/xlsxrb/elements/cell.rb', line 42

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 ])


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

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

#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



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

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



54
55
56
# File 'lib/xlsxrb/elements/cell.rb', line 54

def to_f
  value.to_f
end

#to_iObject



50
51
52
# File 'lib/xlsxrb/elements/cell.rb', line 50

def to_i
  value.to_i
end

#to_sObject



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

def to_s
  value.to_s
end

#to_timeObject



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/xlsxrb/elements/cell.rb', line 73

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