diff options
Diffstat (limited to 'lib/roo/utils.rb')
| -rw-r--r-- | lib/roo/utils.rb | 67 |
1 files changed, 48 insertions, 19 deletions
diff --git a/lib/roo/utils.rb b/lib/roo/utils.rb index 17b672d..dcaedde 100644 --- a/lib/roo/utils.rb +++ b/lib/roo/utils.rb @@ -4,27 +4,39 @@ module Roo LETTERS = ('A'..'Z').to_a - def split_coordinate(str) - @split_coordinate ||= {} + def extract_coordinate(s) + num = letter_num = 0 + num_only = false - @split_coordinate[str] ||= begin - letter, number = split_coord(str) - x = letter_to_number(letter) - y = number - [y, x] + s.each_byte do |b| + if !num_only && (index = char_index(b)) + letter_num *= 26 + letter_num += index + elsif index = num_index(b) + num_only = true + num *= 10 + num += index + else + fail ArgumentError + end end + fail ArgumentError if letter_num == 0 || !num_only + + Excelx::Coordinate.new(num, letter_num) end - alias_method :ref_to_key, :split_coordinate + alias_method :ref_to_key, :extract_coordinate - def split_coord(s) - if s =~ /([a-zA-Z]+)([0-9]+)/ - letter = Regexp.last_match[1] - number = Regexp.last_match[2].to_i - else - fail ArgumentError - end - [letter, number] + def split_coordinate(str) + warn "[DEPRECATION] `Roo::Utils.split_coordinate` is deprecated. Please use `Roo::Utils.extract_coordinate` instead." + extract_coordinate(str) + end + + + + def split_coord(str) + coord = extract_coordinate(str) + [number_to_letter(coord.column), coord.row] end # convert a number to something like 'AB' (1 => 'A', 2 => 'B', ...) @@ -56,8 +68,8 @@ module Roo cells = str.split(':') return 1 if cells.count == 1 raise ArgumentError.new("invalid range string: #{str}. Supported range format 'A1:B2'") if cells.count != 2 - x1, y1 = split_coordinate(cells[0]) - x2, y2 = split_coordinate(cells[1]) + x1, y1 = extract_coordinate(cells[0]) + x2, y2 = extract_coordinate(cells[1]) (x2 - (x1 - 1)) * (y2 - (y1 - 1)) end @@ -69,10 +81,27 @@ module Roo # Yield each element of a given type ('row', 'c', etc.) to caller def each_element(path, elements) + elements = Array(elements) Nokogiri::XML::Reader(::File.open(path, 'rb'), nil, nil, Nokogiri::XML::ParseOptions::NOBLANKS).each do |node| - next unless node.node_type == Nokogiri::XML::Reader::TYPE_ELEMENT && Array(elements).include?(node.name) + next unless node.node_type == Nokogiri::XML::Reader::TYPE_ELEMENT && elements.include?(node.name) yield Nokogiri::XML(node.outer_xml).root if block_given? end end + + private + + def char_index(byte) + if byte >= 65 && byte <= 90 + byte - 64 + elsif byte >= 97 && byte <= 122 + byte - 96 + end + end + + def num_index(byte) + if byte >= 48 && byte <= 57 + byte - 48 + end + end end end |
