Class: RubyXL::Reference

Inherits:
Object
  • Object
show all
Defined in:
lib/rubyXL/objects/reference.rb

Constant Summary collapse

ROW_MAX =
1024 * 1024
COL_MAX =
16393

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*params) ⇒ Reference

RubyXL::Reference.new(row, col) RubyXL::Reference.new(row_from, row_to, col_from, col_to) RubyXL::Reference.new(reference_string) RubyXL::Reference.new(row_from:, row_to:, col_from:, col_to:)



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/rubyXL/objects/reference.rb', line 13

def initialize(*params)
  row_from = row_to = col_from = col_to = nil
  @row_from_absolute = @row_to_absolute = @col_from_absolute = @col_to_absolute = false

  case params.size
  when 4 then row_from, row_to, col_from, col_to = params
  when 2 then row_from, col_from = params
  when 1 then
    case params.first
    when Hash then
      row_from, row_to, col_from, col_to = params.first.fetch_values(:row_from, :row_to, :col_from, :col_to)
    when String then
      str = params.first
      match_data = str.match(/^('(?<sheet_name1>[^']+)'|(?<sheet_name2>[^']+))!/)
      if match_data then
        @sheet_name = match_data['sheet_name1'] || match_data['sheet_name2']
        str = str[match_data[0].size..-1]
      end

      from, to = str.split(':')
      row_from, col_from, @row_from_absolute, @col_from_absolute = self.class.ref2ind(from)
      row_to, col_to, @row_to_absolute, @col_to_absolute = self.class.ref2ind(to) unless to.nil?
    else
      raise ArgumentError.new("invalid value for #{self.class}: #{params[0].inspect}") unless params[0].is_a?(String)
    end
  end

  @row_range = Range.new(row_from || 0, row_to || row_from || ROW_MAX)
  @col_range = Range.new(col_from || 0, col_to || col_from || COL_MAX)
end

Instance Attribute Details

#col_from_absoluteObject (readonly)

Returns the value of attribute col_from_absolute.



7
8
9
# File 'lib/rubyXL/objects/reference.rb', line 7

def col_from_absolute
  @col_from_absolute
end

#col_rangeObject (readonly)

Returns the value of attribute col_range.



6
7
8
# File 'lib/rubyXL/objects/reference.rb', line 6

def col_range
  @col_range
end

#col_to_absoluteObject (readonly)

Returns the value of attribute col_to_absolute.



7
8
9
# File 'lib/rubyXL/objects/reference.rb', line 7

def col_to_absolute
  @col_to_absolute
end

#row_from_absoluteObject (readonly)

Returns the value of attribute row_from_absolute.



7
8
9
# File 'lib/rubyXL/objects/reference.rb', line 7

def row_from_absolute
  @row_from_absolute
end

#row_rangeObject (readonly)

Returns the value of attribute row_range.



6
7
8
# File 'lib/rubyXL/objects/reference.rb', line 6

def row_range
  @row_range
end

#row_to_absoluteObject (readonly)

Returns the value of attribute row_to_absolute.



7
8
9
# File 'lib/rubyXL/objects/reference.rb', line 7

def row_to_absolute
  @row_to_absolute
end

#sheet_nameObject (readonly)

Returns the value of attribute sheet_name.



6
7
8
# File 'lib/rubyXL/objects/reference.rb', line 6

def sheet_name
  @sheet_name
end

Class Method Details

.ind2ref(row = 0, col = 0, row_abs = false, col_abs = false) ⇒ Object

Converts row and col zero-based indices to Excel-style cell reference <0> A…Z, AA…AZ, BA… …ZZ, AAA… …AZZ, BAA… …XFD <16383>



111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/rubyXL/objects/reference.rb', line 111

def self.ind2ref(row = 0, col = 0, row_abs = false, col_abs = false)
  col_ref = ''

  loop do
    x = col % 26
    col_ref = ('A'.ord + x).chr + col_ref
    col = (col / 26).floor - 1
    break if col < 0
  end

  "#{col_abs ? '$' : ''}#{col_ref}#{row_abs ? '$' : ''}#{row + 1}"
end

.ref2ind(str) ⇒ Object

Converts Excel-style cell reference to row and col zero-based indices.



125
126
127
128
129
130
131
132
# File 'lib/rubyXL/objects/reference.rb', line 125

def self.ref2ind(str)
  matchdata = str.match(/\A(?<cabs>\$?)(?<col>[A-Z]+)(?<rabs>\$?)(?<row>\d+)\Z/)
  return [ -1, -1 ] unless matchdata
  [  matchdata['row'].to_i - 1,
     matchdata['col'].each_byte.inject(0) { |col, chr| (col * 26) + (chr - 64) } - 1,
     !matchdata['rabs'].empty?,
     !matchdata['cabs'].empty? ]
end

Instance Method Details

#==(other) ⇒ Object



68
69
70
71
# File 'lib/rubyXL/objects/reference.rb', line 68

def ==(other)
  !other.nil? && (@sheet_name == other.sheet_name) &&
    (@row_range == other.row_range) && (@col_range == other.col_range)
end

#cover?(other) ⇒ Boolean

Returns:

  • (Boolean)


73
74
75
76
77
78
# File 'lib/rubyXL/objects/reference.rb', line 73

def cover?(other)
  !other.nil? && (@row_range.cover?(other.row_range.begin) &&
                  @row_range.cover?(other.row_range.end) &&
                  @col_range.cover?(other.col_range.begin) &&
                  @col_range.cover?(other.col_range.end))
end

#first_colObject



60
61
62
# File 'lib/rubyXL/objects/reference.rb', line 60

def first_col
  @col_range.begin
end

#first_rowObject



52
53
54
# File 'lib/rubyXL/objects/reference.rb', line 52

def first_row
  @row_range.begin
end

#inspectObject



101
102
103
104
105
106
107
# File 'lib/rubyXL/objects/reference.rb', line 101

def inspect
  if single_cell? then
    "#<#{self.class} @sheet_name=#{@sheet_name} @row=#{@row_range.begin} @col=#{@col_range.begin}>"
  else
    "#<#{self.class} @sheet_name=#{@sheet_name} @row_range=#{@row_range} @col_range=#{@col_range}>"
  end
end

#last_colObject



64
65
66
# File 'lib/rubyXL/objects/reference.rb', line 64

def last_col
  @col_range.end
end

#last_rowObject



56
57
58
# File 'lib/rubyXL/objects/reference.rb', line 56

def last_row
  @row_range.end
end

#single_cell?Boolean

Returns:

  • (Boolean)


44
45
46
# File 'lib/rubyXL/objects/reference.rb', line 44

def single_cell?
  (@row_range.begin == @row_range.end) && (@col_range.begin == @col_range.end)
end

#to_sObject



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/rubyXL/objects/reference.rb', line 80

def to_s
  result = +''

  if @sheet_name then
    if @sheet_name.index(' ') then
      result << "'#{@sheet_name}'"
    else
      result << @sheet_name
    end
    result << '!'
  end

  if single_cell? then
    result << self.class.ind2ref(@row_range.begin, @col_range.begin, @row_from_absolute, @col_from_absolute)
  else
    result << self.class.ind2ref(@row_range.begin, @col_range.begin, @row_from_absolute, @col_from_absolute)
    result << ':'
    result << self.class.ind2ref(@row_range.end, @col_range.end, @row_to_absolute, @col_to_absolute)
  end
end

#valid?Boolean

Returns:

  • (Boolean)


48
49
50
# File 'lib/rubyXL/objects/reference.rb', line 48

def valid?
  !(row_range.begin.negative? || col_range.begin.negative?)
end