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.
- checksums.yaml +5 -5
- data/README.md +67 -34
- data/bin/excel_to_c +8 -78
- data/bin/excel_to_go +41 -0
- data/bin/excel_to_ruby +2 -69
- data/src/commands.rb +2 -0
- data/src/commands/common_command_line_options.rb +81 -0
- data/src/commands/excel_to_c.rb +3 -0
- data/src/commands/excel_to_go.rb +91 -0
- data/src/commands/excel_to_x.rb +77 -11
- data/src/compile.rb +1 -0
- data/src/compile/c/a.out +0 -0
- data/src/compile/c/a.out.dSYM/Contents/Resources/DWARF/a.out +0 -0
- data/src/compile/c/compile_to_c.rb +2 -0
- data/src/compile/c/excel_to_c_runtime.c +691 -145
- data/src/compile/c/excel_to_c_runtime_test.c +226 -20
- data/src/compile/c/map_formulae_to_c.rb +62 -23
- data/src/compile/c/run_c_unit_tests +3 -0
- data/src/compile/cd.rb +6 -0
- data/src/compile/go.rb +3 -0
- data/src/compile/go/compile_to_go.rb +85 -0
- data/src/compile/go/compile_to_go_test.rb +73 -0
- data/src/compile/go/excel.go +171 -0
- data/src/compile/go/excel_test.go +54 -0
- data/src/compile/go/map_values_to_go.rb +67 -0
- data/src/compile/ruby/map_formulae_to_ruby.rb +30 -12
- data/src/excel/excel_functions.rb +26 -1
- data/src/excel/excel_functions/ceiling.rb +23 -0
- data/src/excel/excel_functions/countif.rb +15 -0
- data/src/excel/excel_functions/countifs.rb +10 -0
- data/src/excel/excel_functions/floor.rb +14 -0
- data/src/excel/excel_functions/hyperlink.rb +9 -0
- data/src/excel/excel_functions/na.rb +7 -0
- data/src/excel/excel_functions/not.rb +13 -0
- data/src/excel/excel_functions/or.rb +30 -0
- data/src/excel/excel_functions/product.rb +8 -0
- data/src/excel/excel_functions/rate.rb +16 -0
- data/src/excel/excel_functions/replace.rb +13 -0
- data/src/excel/excel_functions/scurve.rb +73 -0
- data/src/excel/excel_functions/sqrt.rb +11 -0
- data/src/excel/excel_functions/string_argument.rb +37 -0
- data/src/excel/excel_functions/sumifs.rb +19 -8
- data/src/excel/excel_functions/text.rb +3 -3
- data/src/excel/formula_peg.rb +1 -1
- data/src/excel/formula_peg.txt +2 -3
- data/src/excel/table.rb +15 -15
- data/src/excel_to_code.rb +1 -4
- data/src/extract/extract_data_from_worksheet.rb +8 -1
- data/src/rewrite/ast_expand_array_formulae.rb +4 -0
- data/src/rewrite/caching_formula_parser.rb +16 -11
- data/src/simplify.rb +1 -0
- data/src/simplify/inline_formulae.rb +16 -0
- data/src/simplify/replace_arithmetic_on_ranges.rb +14 -1
- data/src/simplify/replace_arrays_with_single_cells.rb +42 -15
- data/src/simplify/replace_cell_addresses_with_references.rb +70 -0
- data/src/simplify/replace_column_with_column_number.rb +8 -1
- data/src/simplify/replace_table_references.rb +40 -19
- data/src/simplify/simplify_arithmetic.rb +15 -10
- data/src/version.rb +4 -0
- metadata +115 -43
- 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(
|
19
|
+
when /^(0([.,]0*)?)%/
|
20
20
|
text(number*100, $1)+"%"
|
21
21
|
when /^(0+)$/
|
22
22
|
sprintf("%0#{$1.length}.0f", number)
|
23
|
-
when
|
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
|
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")
|
data/src/excel/formula_peg.rb
CHANGED
@@ -27,7 +27,7 @@ class Formula < RubyPeg
|
|
27
27
|
|
28
28
|
def function
|
29
29
|
node :function do
|
30
|
-
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
|
|
data/src/excel/formula_peg.txt
CHANGED
@@ -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 := /
|
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
@@ -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
|
-
|
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}"
|
@@ -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, :
|
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
|
-
|
40
|
-
|
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
|
-
|
60
|
-
|
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, :
|
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[
|
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
|
|