excel_to_code 0.3.17 → 0.3.18.beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +67 -34
  3. data/bin/excel_to_c +8 -78
  4. data/bin/excel_to_go +41 -0
  5. data/bin/excel_to_ruby +2 -69
  6. data/src/commands.rb +2 -0
  7. data/src/commands/common_command_line_options.rb +81 -0
  8. data/src/commands/excel_to_c.rb +3 -0
  9. data/src/commands/excel_to_go.rb +91 -0
  10. data/src/commands/excel_to_x.rb +77 -11
  11. data/src/compile.rb +1 -0
  12. data/src/compile/c/a.out +0 -0
  13. data/src/compile/c/a.out.dSYM/Contents/Resources/DWARF/a.out +0 -0
  14. data/src/compile/c/compile_to_c.rb +2 -0
  15. data/src/compile/c/excel_to_c_runtime.c +691 -145
  16. data/src/compile/c/excel_to_c_runtime_test.c +226 -20
  17. data/src/compile/c/map_formulae_to_c.rb +62 -23
  18. data/src/compile/c/run_c_unit_tests +3 -0
  19. data/src/compile/cd.rb +6 -0
  20. data/src/compile/go.rb +3 -0
  21. data/src/compile/go/compile_to_go.rb +85 -0
  22. data/src/compile/go/compile_to_go_test.rb +73 -0
  23. data/src/compile/go/excel.go +171 -0
  24. data/src/compile/go/excel_test.go +54 -0
  25. data/src/compile/go/map_values_to_go.rb +67 -0
  26. data/src/compile/ruby/map_formulae_to_ruby.rb +30 -12
  27. data/src/excel/excel_functions.rb +26 -1
  28. data/src/excel/excel_functions/ceiling.rb +23 -0
  29. data/src/excel/excel_functions/countif.rb +15 -0
  30. data/src/excel/excel_functions/countifs.rb +10 -0
  31. data/src/excel/excel_functions/floor.rb +14 -0
  32. data/src/excel/excel_functions/hyperlink.rb +9 -0
  33. data/src/excel/excel_functions/na.rb +7 -0
  34. data/src/excel/excel_functions/not.rb +13 -0
  35. data/src/excel/excel_functions/or.rb +30 -0
  36. data/src/excel/excel_functions/product.rb +8 -0
  37. data/src/excel/excel_functions/rate.rb +16 -0
  38. data/src/excel/excel_functions/replace.rb +13 -0
  39. data/src/excel/excel_functions/scurve.rb +73 -0
  40. data/src/excel/excel_functions/sqrt.rb +11 -0
  41. data/src/excel/excel_functions/string_argument.rb +37 -0
  42. data/src/excel/excel_functions/sumifs.rb +19 -8
  43. data/src/excel/excel_functions/text.rb +3 -3
  44. data/src/excel/formula_peg.rb +1 -1
  45. data/src/excel/formula_peg.txt +2 -3
  46. data/src/excel/table.rb +15 -15
  47. data/src/excel_to_code.rb +1 -4
  48. data/src/extract/extract_data_from_worksheet.rb +8 -1
  49. data/src/rewrite/ast_expand_array_formulae.rb +4 -0
  50. data/src/rewrite/caching_formula_parser.rb +16 -11
  51. data/src/simplify.rb +1 -0
  52. data/src/simplify/inline_formulae.rb +16 -0
  53. data/src/simplify/replace_arithmetic_on_ranges.rb +14 -1
  54. data/src/simplify/replace_arrays_with_single_cells.rb +42 -15
  55. data/src/simplify/replace_cell_addresses_with_references.rb +70 -0
  56. data/src/simplify/replace_column_with_column_number.rb +8 -1
  57. data/src/simplify/replace_table_references.rb +40 -19
  58. data/src/simplify/simplify_arithmetic.rb +15 -10
  59. data/src/version.rb +4 -0
  60. metadata +115 -43
  61. data/TODO +0 -25
@@ -4,7 +4,7 @@ module ExcelFunctions
4
4
  # Sort out the sum range
5
5
  range = [range] unless range.is_a?(Array)
6
6
  range = range.flatten
7
-
7
+
8
8
  indexes = _filtered_range_indexes(range, *criteria)
9
9
  return indexes if indexes.is_a?(Symbol)
10
10
  range.values_at(*indexes)
@@ -21,17 +21,26 @@ module ExcelFunctions
21
21
  end
22
22
 
23
23
  filtered = []
24
-
24
+
25
25
  # Work through each part of the sum range
26
26
  range.each_with_index do |potential,index|
27
27
  #next unless potential.is_a?(Numeric)
28
-
28
+
29
29
  # If a criteria fails, this is set to false and no further criteria are evaluated
30
30
  pass = true
31
-
31
+
32
32
  0.step(criteria.length-1,2).each do |i|
33
33
  check_range = criteria[i]
34
34
  required_value = criteria[i+1] || 0
35
+ if required_value.is_a?(String)
36
+ any_start = required_value.start_with?('*')
37
+ any_end = required_value.end_with?('*')
38
+ if any_start || any_end
39
+ required_value = ".*"+required_value[1..-1] if any_start
40
+ required_value = required_value[0..-2]+".*" if any_end
41
+ required_value = /^#{required_value}$/i
42
+ end
43
+ end
35
44
  return :value if index >= check_range.length
36
45
  check_value = check_range[index]
37
46
 
@@ -40,6 +49,8 @@ module ExcelFunctions
40
49
  case required_value
41
50
  when String
42
51
  check_value.downcase == required_value.downcase
52
+ when Regexp
53
+ check_value =~ required_value
43
54
  when Numeric
44
55
  begin
45
56
  Float(check_value) == required_value.to_f
@@ -72,19 +83,19 @@ module ExcelFunctions
72
83
  when Symbol
73
84
  check_value == required_value
74
85
  end # case check_value
75
-
86
+
76
87
  break unless pass
77
88
  end # criteria loop
78
-
89
+
79
90
  filtered << index if pass
80
91
  end
81
92
 
82
93
  return filtered
83
94
  end
84
-
95
+
85
96
  def sumifs(range,*criteria)
86
97
  filtered = _filtered_range(range,*criteria)
87
98
  sum(*filtered)
88
99
  end
89
-
100
+
90
101
  end
@@ -16,16 +16,16 @@ module ExcelFunctions
16
16
  return format if format.is_a?(Symbol)
17
17
 
18
18
  case format
19
- when /^(0(\.0*)?)%/
19
+ when /^(0([.,]0*)?)%/
20
20
  text(number*100, $1)+"%"
21
21
  when /^(0+)$/
22
22
  sprintf("%0#{$1.length}.0f", number)
23
- when /#,#+(0\.0+)?/
23
+ when /#[,.]#+(0[.,]0+)?/
24
24
  formated_with_decimals = text(number, $1 || "0")
25
25
  parts = formated_with_decimals.split('.')
26
26
  parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1,")
27
27
  parts.join('.')
28
- when /0\.(0+)/
28
+ when /0[.,](0+)/
29
29
  sprintf("%.#{$1.length}f", number)
30
30
  else
31
31
  raise ExcelToCodeException.new("in TEXT function format #{format} not yet supported by excel_to_code")
@@ -27,7 +27,7 @@ class Formula < RubyPeg
27
27
 
28
28
  def function
29
29
  node :function do
30
- terminal(/(LOG10)|[A-Z]+/) && ignore { terminal("(") } && space && optional { argument } && any_number_of { (space && ignore { terminal(",") } && space && argument) } && space && ignore { terminal(")") }
30
+ terminal(/[a-zA-Z_][a-zA-Z0-9.]+/) && ignore { terminal("(") } && space && optional { argument } && any_number_of { (space && ignore { terminal(",") } && space && argument) } && space && ignore { terminal(")") }
31
31
  end
32
32
  end
33
33
 
@@ -1,8 +1,8 @@
1
1
  formula := space? expression+
2
2
  expression = string_join | comparison | arithmetic | thing
3
- thing = percentage | function | array | brackets | any_reference | string | number | boolean | prefix | error | named_reference
3
+ thing = percentage | function | array | brackets | any_reference | string | number | boolean | prefix | error | named_reference
4
4
  argument = expression | null
5
- function := /(LOG10)|[A-Z]+/ `'(' space argument? (space `',' space argument)* space `')'
5
+ function := /[a-zA-Z_][a-zA-Z0-9.]+/ `'(' space argument? (space `',' space argument)* space `')'
6
6
  brackets := `'(' space expression+ space `')'
7
7
  array := `'{' space row ( space `';' space row )* space `'}'
8
8
  row := basic_type ( space `',' space basic_type )*
@@ -44,4 +44,3 @@ prefix := /[-+]/ thing
44
44
  space = `/[ \n\r]*/
45
45
  null := &','
46
46
  error := '#REF!' | '#NAME?' | '#VALUE!' | '#DIV/0!' | '#N/A' | '#NUM!'
47
-
data/src/excel/table.rb CHANGED
@@ -2,17 +2,17 @@ require_relative '../excel'
2
2
  require_relative '../util'
3
3
 
4
4
  class Table
5
-
5
+
6
6
  attr_accessor :name
7
-
7
+
8
8
  def initialize(name,worksheet,reference,number_of_total_rows,*column_name_array)
9
9
  @name, @worksheet, @area, @number_of_total_rows, @column_name_array = name, worksheet.to_sym, Area.for(reference), number_of_total_rows.to_i, column_name_array.map { |c| c.strip.downcase }
10
- @area.calculate_excel_variables
10
+ @area.calculate_excel_variables
11
11
  @data_area = Area.for("#{@area.excel_start.offset(1,0)}:#{@area.excel_finish.offset(-@number_of_total_rows,0)}")
12
12
  @data_area.calculate_excel_variables
13
13
  end
14
-
15
- def reference_for(table_name,structured_reference,calling_worksheet,calling_cell)
14
+
15
+ def reference_for(table_name,structured_reference,calling_worksheet,calling_cell, must_be_area = false)
16
16
  raise NotSupportedException.new("Local table reference not supported in #{structured_reference.inspect}") unless table_name
17
17
 
18
18
  case structured_reference
@@ -45,7 +45,7 @@ class Table
45
45
 
46
46
  when /\[#Headers\],\[(.*?)\]/io
47
47
  column_number = column_number_for($1)
48
- return ref_error unless column_number
48
+ return ref_error unless column_number
49
49
  ast_for_cell @area.excel_start.offset(0,column_number)
50
50
 
51
51
  when /\[#Totals\],\[(.*?)\]/io
@@ -59,7 +59,7 @@ class Table
59
59
  row = r.excel_row_number
60
60
  column_number = column_number_for($1)
61
61
  return ref_error unless column_number
62
- ast_for_cell @area.excel_start.offset(row - @area.excel_start.excel_row_number,column_number)
62
+ ast_for_cell @area.excel_start.offset(row - @area.excel_start.excel_row_number,column_number)
63
63
 
64
64
  when /#Headers/io
65
65
  if calling_worksheet == @worksheet && @data_area.includes?(calling_cell)
@@ -92,14 +92,14 @@ class Table
92
92
  ast_for_area "#{@area.excel_start.excel_column}#{row}", "#{@area.excel_finish.excel_column}#{row}"
93
93
 
94
94
  else
95
- if calling_worksheet == @worksheet && @data_area.includes?(calling_cell)
95
+ if !must_be_area && (calling_worksheet == @worksheet) && @data_area.includes?(calling_cell)
96
96
  r = Reference.for(calling_cell)
97
97
  r.calculate_excel_variables
98
98
  row = r.excel_row_number
99
99
  column_number = column_number_for(structured_reference)
100
100
  return ref_error unless column_number
101
- ast_for_cell @area.excel_start.offset(row - @area.excel_start.excel_row_number,column_number)
102
- else
101
+ ast_for_cell @area.excel_start.offset(row - @area.excel_start.excel_row_number,column_number)
102
+ else
103
103
  column_number = column_number_for(structured_reference)
104
104
  return ref_error unless column_number
105
105
  ast_for_area @area.excel_start.offset(1,column_number), @area.excel_start.offset(@area.height - @number_of_total_rows,column_number)
@@ -114,15 +114,15 @@ class Table
114
114
  def data
115
115
  ast_for_area @data_area.excel_start, @data_area.excel_finish
116
116
  end
117
-
117
+
118
118
  def ast_for_area(start,finish)
119
119
  [:sheet_reference,@worksheet,[:area,start.to_sym,finish.to_sym]]
120
120
  end
121
-
121
+
122
122
  def ast_for_cell(ref)
123
123
  [:sheet_reference,@worksheet,[:cell,ref.to_sym]]
124
124
  end
125
-
125
+
126
126
  def ref_error
127
127
  [:error,"#REF!"]
128
128
  end
@@ -131,10 +131,10 @@ class Table
131
131
  name = name.strip.downcase.gsub("'#","#")
132
132
  @column_name_array.find_index(name)
133
133
  end
134
-
134
+
135
135
  def includes?(sheet,reference)
136
136
  return false unless @worksheet == sheet
137
137
  @area.includes?(reference)
138
138
  end
139
-
139
+
140
140
  end
data/src/excel_to_code.rb CHANGED
@@ -1,7 +1,4 @@
1
- class ExcelToCode
2
- def self.version() "0.3.17" end
3
- end
4
-
1
+ require_relative 'version'
5
2
  require_relative 'commands'
6
3
  require_relative 'compile'
7
4
  require_relative 'excel'
@@ -3,6 +3,7 @@ require 'ox'
3
3
  class ExtractDataFromWorksheet < ::Ox::Sax
4
4
 
5
5
  attr_accessor :only_extract_values
6
+ attr_accessor :persevere
6
7
 
7
8
  attr_accessor :table_rids
8
9
  attr_accessor :worksheets_dimensions
@@ -85,7 +86,13 @@ class ExtractDataFromWorksheet < ::Ox::Sax
85
86
  ast = @fp.parse(formula_text)
86
87
  rescue ExcelToCodeException => e
87
88
  e.ref = key if e.respond_to?(:ref) # Attach the sheet and reference to the exception
88
- raise
89
+ if persevere
90
+ $stderr.puts e.message
91
+ $stderr.puts "--persevere true, so setting #{key} to '#NAME?'"
92
+ ast = [:error, '#NAME?']
93
+ else
94
+ raise
95
+ end
89
96
  end
90
97
  unless ast
91
98
  $stderr.puts "Could not parse #{@sheet_name} #{@ref} #{formula_text}"
@@ -111,6 +111,10 @@ class AstExpandArrayFormulae
111
111
  def map_sumif(ast)
112
112
  array_map ast, true, false, true
113
113
  end
114
+
115
+ def map_countif(*args)
116
+ array_map args, 'COUNTIF', true, true
117
+ end
114
118
 
115
119
  def map_sumifs(ast)
116
120
  if ast.length > 5
@@ -21,8 +21,8 @@ class ExternalReferenceException < ExcelToCodeException
21
21
  The formula was #{formula_text}
22
22
  Which was parsed to #{full_ast}
23
23
  Which seemed to have an external reference at #{reference_ast}
24
- Note, the [0], [1], [2] ... are the way Excel stores the names of the external files.
25
-
24
+ Note, the [0], [1], [2] ... are the way Excel stores the names of the external files.
25
+
26
26
  Please remove the external reference from the Excel and try again.
27
27
 
28
28
  END
@@ -77,9 +77,11 @@ class CachingFormulaParser
77
77
  @comparator_cache = {}
78
78
  @sheet_reference_cache = {}
79
79
  @functions_used = {}
80
+ @treat_external_references_as_local = false
80
81
  end
81
82
 
82
- def parse(text)
83
+ def parse(text, treat_external_references_as_local = false)
84
+ @treat_external_references_as_local = treat_external_references_as_local
83
85
  ast = Formula.parse(text)
84
86
  @text = text # Kept in case of Exception below
85
87
  if ast
@@ -95,17 +97,17 @@ class CachingFormulaParser
95
97
  def map(ast)
96
98
  return ast unless ast.is_a?(Array)
97
99
  if ast[0] == :function
98
- ast[1] = ast[1].to_sym
100
+ ast[1] = ast[1].to_sym
99
101
  @functions_used[ast[1]] = true
100
102
  end
101
103
  if respond_to?(ast[0])
102
- ast = send(ast[0], ast)
104
+ ast = send(ast[0], ast)
103
105
  else
104
- ast.each.with_index do |a,i|
106
+ ast.each.with_index do |a,i|
105
107
  next unless a.is_a?(Array)
106
-
108
+
107
109
  if a[0] == :function
108
- a[1] = a[1].to_sym
110
+ a[1] = a[1].to_sym
109
111
  @functions_used[a[1]] = true
110
112
  end
111
113
 
@@ -117,14 +119,17 @@ class CachingFormulaParser
117
119
 
118
120
  # We can't deal with external references at the moment
119
121
  def external_reference(ast)
120
- raise ExternalReferenceException.new(ast, @full_ast, @text)
122
+ raise ExternalReferenceException.new(ast, @full_ast, @text) unless @treat_external_references_as_local
123
+ # We sometimes treat the external reference as local in order to move on
124
+ return ast[2]
121
125
  end
122
126
 
123
127
  def sheet_reference(ast)
124
- # Sheet names shouldn't start with [1], because those are
128
+ # Sheet names shouldn't start with [1], because those are
125
129
  # external references
126
130
  if ast[1] =~ /^\[\d+\]/
127
- raise ExternalReferenceException.new(ast, @full_ast, @text)
131
+ raise ExternalReferenceException.new(ast, @full_ast, @text) unless @treat_external_references_as_local
132
+ ast[1] = ast[1].gsub(/^\[\d+\]/,'')
128
133
  end
129
134
  ast[1] = ast[1].to_sym
130
135
  ast[2] = map(ast[2])
data/src/simplify.rb CHANGED
@@ -6,6 +6,7 @@ require_relative "simplify/inline_formulae"
6
6
  require_relative "simplify/map_formulae_to_values"
7
7
  require_relative "simplify/replace_indirects_with_references"
8
8
  require_relative "simplify/replace_offsets_with_references"
9
+ require_relative "simplify/replace_cell_addresses_with_references"
9
10
  require_relative "simplify/replace_column_with_column_number"
10
11
  require_relative "simplify/simplify_arithmetic"
11
12
  require_relative "simplify/identify_dependencies"
@@ -1,3 +1,19 @@
1
+ class Array
2
+
3
+ def original
4
+ @original || self
5
+ end
6
+
7
+ alias_method :original_replace, :replace
8
+
9
+ def replace(new_array)
10
+ @original = self.dup
11
+ original_replace(new_array)
12
+ end
13
+ end
14
+
15
+
16
+
1
17
  class InlineFormulaeAst
2
18
 
3
19
  attr_accessor :references, :current_sheet_name, :inline_ast
@@ -5,7 +5,7 @@ class ReplaceArithmeticOnRangesAst
5
5
  ast.each do |a|
6
6
  next unless a.is_a?(Array)
7
7
  case ast.first
8
- when :error, :null, :space, :prefix, :boolean_true, :boolean_false, :number, :string
8
+ when :error, :null, :space, :boolean_true, :boolean_false, :number, :string
9
9
  next
10
10
  when :sheet_reference, :table_reference, :local_table_reference
11
11
  next
@@ -15,6 +15,7 @@ class ReplaceArithmeticOnRangesAst
15
15
  map(a)
16
16
  end
17
17
  end
18
+ prefix(ast) if ast.first == :prefix
18
19
  arithmetic(ast) if ast.first == :arithmetic
19
20
  comparison(ast) if ast.first == :comparison
20
21
  ast
@@ -121,6 +122,18 @@ class ReplaceArithmeticOnRangesAst
121
122
  )
122
123
  end
123
124
  end
125
+
126
+ # Format [:prefix, symbol, array]
127
+ def prefix(ast)
128
+ symbol, array = ast[1], ast[2]
129
+ # array on the right next
130
+ return unless array.first == :array
131
+ ast.replace(
132
+ array_map(array) do |cell|
133
+ [:prefix, symbol, map(cell)]
134
+ end
135
+ )
136
+ end
124
137
 
125
138
  def array_map(array)
126
139
  array.map do |row|
@@ -10,6 +10,7 @@ class ReplaceArraysWithSingleCellsAst
10
10
  def map(ast)
11
11
  @need_to_replace = false
12
12
  return unless ast.is_a?(Array)
13
+ map_if_required(ast)
13
14
  if ast.first == :array
14
15
  @need_to_replace = true
15
16
  new_ast = try_and_convert_array(ast)
@@ -29,6 +30,7 @@ class ReplaceArraysWithSingleCellsAst
29
30
 
30
31
  def do_map(ast)
31
32
  return ast unless ast.is_a?(Array)
33
+ map_if_required(ast)
32
34
  case ast.first
33
35
  when :arithmetic
34
36
  left, op, right = ast[1], ast[2], ast[3]
@@ -36,16 +38,25 @@ class ReplaceArraysWithSingleCellsAst
36
38
  left = try_and_convert_array(left)
37
39
  right = try_and_convert_array(right)
38
40
  ast.replace([:arithmetic, left, op, right])
39
- else
40
- map_if_required(ast)
41
+ end
42
+ when :comparison
43
+ left, op, right = ast[1], ast[2], ast[3]
44
+ if left.first == :array || right.first == :array
45
+ left = try_and_convert_array(left)
46
+ right = try_and_convert_array(right)
47
+ ast.replace([:comparison, left, op, right])
48
+ end
49
+ when :prefix
50
+ op, left = ast[1], ast[2]
51
+ if left.first == :array
52
+ left = try_and_convert_array(left)
53
+ ast.replace([:prefix, op, left])
41
54
  end
42
55
  when :string_join
43
56
  strings = ast[1..-1]
44
57
  if strings.any? { |s| s.first == :array }
45
58
  strings = strings.map { |s| try_and_convert_array(s) }
46
59
  ast.replace([:string_join, *strings])
47
- else
48
- map_if_required(strings)
49
60
  end
50
61
  when :function
51
62
  if ast[1] == :SUMIF && ast[3].first == :array
@@ -56,11 +67,9 @@ class ReplaceArraysWithSingleCellsAst
56
67
  # Replacement made in check_match function
57
68
  elsif ast[1] == :INDIRECT && check_indirect(ast)
58
69
  # Replacement made in check function
59
- else
60
- map_if_required(ast)
70
+ elsif ast[0] == :function && ast[1] == :INDEX && check_index(ast)
71
+ # Replacement made in check
61
72
  end
62
- else
63
- map_if_required(ast)
64
73
  end
65
74
  end
66
75
 
@@ -71,7 +80,7 @@ class ReplaceArraysWithSingleCellsAst
71
80
  arguments.each do |a|
72
81
  next unless a.is_a?(Array)
73
82
  case a.first
74
- when :error, :null, :space, :prefix, :boolean_true, :boolean_false, :number, :string
83
+ when :error, :null, :space, :boolean_true, :boolean_false, :number, :string
75
84
  next
76
85
  when :sheet_reference, :table_reference, :local_table_reference
77
86
  next
@@ -94,17 +103,35 @@ class ReplaceArraysWithSingleCellsAst
94
103
  replacement_made
95
104
  end
96
105
 
106
+ def check_index(ast)
107
+ replacement_made = false
108
+ if ast[3] && ast[3].first == :array
109
+ replacement_made = true
110
+ ast[3] = try_and_convert_array(ast[3])
111
+ end
112
+ if ast[4] && ast[4].first == :array
113
+ replacement_made = true
114
+ ast[4] = try_and_convert_array(ast[4])
115
+ end
116
+ replacement_made
117
+ end
118
+
97
119
  def check_if(ast)
98
120
  replacement_made = false
121
+ if ast[2] && ast[2].first == :array
122
+ replacement_made = true
123
+ ast[2] = try_and_convert_array(ast[2])
124
+ end
99
125
  if ast[3] && ast[3].first == :array
100
126
  replacement_made = true
101
127
  ast[3] = try_and_convert_array(ast[3])
102
128
  end
103
129
  if ast[4] && ast[4].first == :array
104
130
  replacement_made = true
105
- ast[4] = try_and_convert_array(ast[3])
131
+ ast[4] = try_and_convert_array(ast[4])
106
132
  end
107
133
  replacement_made
134
+
108
135
  end
109
136
 
110
137
  def check_match(ast)
@@ -149,7 +176,7 @@ class ReplaceArraysWithSingleCellsAst
149
176
  def all_references?(ast)
150
177
  ast[1..-1].all? do |row|
151
178
  row[1..-1].all? do |cell|
152
- cell.first == :sheet_reference
179
+ cell.original.first == :sheet_reference
153
180
  end
154
181
  end
155
182
  end
@@ -162,8 +189,8 @@ class ReplaceArraysWithSingleCellsAst
162
189
 
163
190
  cells = ast[1][1..-1]
164
191
  match = cells.find do |cell|
165
- s = cell[1]
166
- c = cell[2][1][/([A-Za-z]{1,3})/,1]
192
+ s = cell.original[1]
193
+ c = cell.original[2][1][/([A-Za-z]{1,3})/,1]
167
194
  sheet == s && column == c
168
195
  end
169
196
 
@@ -178,8 +205,8 @@ class ReplaceArraysWithSingleCellsAst
178
205
 
179
206
  cells = ast[1..-1].map { |row| row.last }
180
207
  match = cells.find do |cell|
181
- s = cell[1]
182
- r = cell[2][1][/([A-Za-z]{1,3})(\d+)/,2]
208
+ s = cell.original[1]
209
+ r = cell.original[2][1][/([A-Za-z]{1,3})(\d+)/,2]
183
210
  sheet == s && row == r
184
211
  end
185
212