Class: CSVPlusPlus::A1Reference

Inherits:
Object
  • Object
show all
Extended by:
T::Sig
Defined in:
lib/csv_plus_plus/a1_reference.rb

Overview

A reference to a cell. Internally it is represented by a simple cell_index and row_index but there are functions for converting to and from A1-style formats. Supported formats are:

  • ‘1` - A reference to the entire first row

  • ‘A` - A reference to the entire first column

  • ‘A1` - A reference to the first cell (top left)

  • ‘A1:D10` - The range defined between A1 and D10

  • ‘Sheet1!B2` - Cell B2 on the sheet “Sheet1”

rubocop:disable Metrics/ClassLength

Constant Summary collapse

A1_NOTATION_REGEXP =

TODO: this is getting gross, maybe define an actual parser

/
  ^
    (?:
      (?:
        (?:'([^'\\]|\\.)*') # allow for a single-quoted sheet name
        |
        (\w+)               # or if it's not quoted, just allow \w+
      )
      !                     # if a sheet name is specified, it's always followed by a !
    )?
    ([a-zA-Z0-9]+)          # the only part required - something alphanumeric
    (?: :([a-zA-Z0-9]+))?   # and they might make it a range
  $
/x

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(ref: nil, cell_index: nil, row_index: nil, scoped_to_expand: nil) ⇒ A1Reference

Either ref, cell_index or row_index must be specified. If ref is supplied it will be parsed to calculate row_index and +cell_index.

Parameters:

  • ref (String, nil) (defaults to: nil)

    A raw user-inputted reference

  • cell_index (Integer, nil) (defaults to: nil)

    The index of the cell being referenced.

  • row_index (Integer, nil) (defaults to: nil)

    The index of the row being referenced.

  • scoped_to_expand (Expand) (defaults to: nil)

    The [[expand]] that this cell reference will be scoped to. In other words, it will only be able to be resolved if the position is within the bounds of the expand (it can’t be referenced outside of the expand.)

Raises:

  • (::ArgumentError)


93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/csv_plus_plus/a1_reference.rb', line 93

def initialize(ref: nil, cell_index: nil, row_index: nil, scoped_to_expand: nil)
  raise(::ArgumentError, 'Must specify :cell_index or :row_index') unless ref || cell_index || row_index

  @scoped_to_expand = scoped_to_expand

  if ref
    from_a1_ref!(ref)
  else
    @cell_index = ::T.let(cell_index, ::T.nilable(::Integer))
    @row_index = ::T.let(row_index, ::T.nilable(::Integer))

    @upper_cell_index = ::T.let(nil, ::T.nilable(::Integer))
    @upper_row_index = ::T.let(nil, ::T.nilable(::Integer))
  end
end

Instance Attribute Details

#cell_indexInteger? (readonly)

The cell index of the cell being referenced

Returns:

  • (Integer, nil)

    the current value of cell_index



22
23
24
# File 'lib/csv_plus_plus/a1_reference.rb', line 22

def cell_index
  @cell_index
end

#row_indexInteger? (readonly)

The row index of the cell being referenced

Returns:

  • (Integer, nil)

    the current value of row_index



22
23
24
# File 'lib/csv_plus_plus/a1_reference.rb', line 22

def row_index
  @row_index
end

#scoped_to_expandObject (readonly)

Returns the value of attribute scoped_to_expand.



41
42
43
# File 'lib/csv_plus_plus/a1_reference.rb', line 41

def scoped_to_expand
  @scoped_to_expand
end

#sheet_nameString?

The name of the sheet reference

Returns:

  • (String, nil)

    the current value of sheet_name



22
23
24
# File 'lib/csv_plus_plus/a1_reference.rb', line 22

def sheet_name
  @sheet_name
end

#upper_cell_indexInteger? (readonly)

If set, the cell reference is a range and this is the upper cell index of it

Returns:

  • (Integer, nil)

    the current value of upper_cell_index



22
23
24
# File 'lib/csv_plus_plus/a1_reference.rb', line 22

def upper_cell_index
  @upper_cell_index
end

#upper_row_indexInteger? (readonly)

If set, the cell reference is a range and this is the upper row index of in

Returns:

  • (Integer, nil)

    the current value of upper_row_index



22
23
24
# File 'lib/csv_plus_plus/a1_reference.rb', line 22

def upper_row_index
  @upper_row_index
end

Class Method Details

.valid_cell_reference?(cell_reference_string) ⇒ ::T::Boolean

Does the given cell_reference_string conform to a valid cell reference?

https://developers.google.com/sheets/api/guides/concepts

Parameters:

  • cell_reference_string (::String)

    The string to check if it is a valid cell reference (we assume it’s in A1 notation but maybe can support R1C1)

Returns:

  • (::T::Boolean)


72
73
74
# File 'lib/csv_plus_plus/a1_reference.rb', line 72

def self.valid_cell_reference?(cell_reference_string)
  !(cell_reference_string =~ ::CSVPlusPlus::A1Reference::A1_NOTATION_REGEXP).nil?
end

Instance Method Details

#==(other) ⇒ boolean

Parameters:

  • other (BasicObject)

Returns:

  • (boolean)


113
114
115
116
117
118
119
120
121
# File 'lib/csv_plus_plus/a1_reference.rb', line 113

def ==(other)
  case other
  when self.class
    @cell_index == other.cell_index && @row_index == other.row_index && @sheet_name == other.sheet_name \
      && @upper_cell_index == other.upper_cell_index && @upper_row_index == other.upper_row_index
  else
    false
  end
end

#to_a1_ref(position) ⇒ ::String?

Turns index-based/X,Y coordinates into a A1 format

Parameters:

  • position (Position)

Returns:

  • (::String, nil)


129
130
131
132
133
134
135
136
# File 'lib/csv_plus_plus/a1_reference.rb', line 129

def to_a1_ref(position)
  row_index = position_row_index(position)
  return unless row_index || @cell_index

  rowref = row_index ? (row_index + 1).to_s : ''
  cellref = @cell_index ? to_a1_cell_ref : ''
  [cellref, rowref].join
end