excel_to_code 0.1.8 → 0.1.10
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 +4 -4
- data/TODO +0 -1
- data/src/commands/excel_to_c.rb +6 -5
- data/src/commands/excel_to_ruby.rb +2 -1
- data/src/commands/excel_to_x.rb +69 -37
- data/src/compile/c/a.out +0 -0
- data/src/compile/c/compile_named_reference_setters.rb +1 -1
- data/src/compile/c/compile_to_c.rb +1 -1
- data/src/compile/c/compile_to_c_header.rb +1 -1
- data/src/compile/c/excel_to_c_runtime.c +117 -1
- data/src/compile/c/map_formulae_to_c.rb +4 -0
- data/src/compile/c/map_sheet_names_to_c_names.rb +1 -1
- data/src/compile/c/map_values_to_c.rb +2 -1
- data/src/compile/ruby/compile_to_ruby.rb +2 -2
- data/src/compile/ruby/compile_to_ruby_unit_test.rb +1 -1
- data/src/compile/ruby/map_formulae_to_ruby.rb +5 -0
- data/src/compile/ruby/map_values_to_ruby.rb +2 -1
- data/src/excel/excel_functions.rb +10 -0
- data/src/excel/excel_functions/cell.rb +14 -0
- data/src/excel/excel_functions/mid.rb +20 -0
- data/src/excel/excel_functions/negative.rb +2 -0
- data/src/excel/excel_functions/pv.rb +37 -0
- data/src/excel/excel_functions/text.rb +25 -0
- data/src/excel/excel_functions/trim.rb +8 -0
- data/src/excel/table.rb +1 -0
- data/src/extract/check_for_unknown_functions.rb +1 -1
- data/src/rewrite/ast_expand_array_formulae.rb +4 -6
- data/src/rewrite/rewrite_array_formulae.rb +2 -2
- data/src/rewrite/rewrite_array_formulae_to_arrays.rb +1 -1
- data/src/rewrite/rewrite_cell_references_to_include_sheet.rb +1 -1
- data/src/rewrite/rewrite_formulae_to_ast.rb +1 -1
- data/src/rewrite/rewrite_merge_formulae_and_values.rb +2 -2
- data/src/rewrite/rewrite_named_reference_names.rb +1 -1
- data/src/rewrite/rewrite_relationship_id_to_filename.rb +1 -1
- data/src/rewrite/rewrite_shared_formulae.rb +2 -2
- data/src/rewrite/rewrite_values_to_ast.rb +1 -1
- data/src/rewrite/rewrite_whole_row_column_references_to_areas.rb +2 -2
- data/src/rewrite/rewrite_worksheet_names.rb +6 -3
- data/src/simplify.rb +2 -0
- data/src/simplify/inline_formulae.rb +18 -1
- data/src/simplify/map_formulae_to_values.rb +18 -6
- data/src/simplify/remove_cells.rb +1 -1
- data/src/simplify/replace_arrays_with_single_cells.rb +1 -1
- data/src/simplify/replace_column_with_column_number.rb +58 -0
- data/src/simplify/replace_common_elements_in_formulae.rb +1 -1
- data/src/simplify/replace_formulae_with_calculated_values.rb +7 -1
- data/src/simplify/replace_indirects_with_references.rb +16 -3
- data/src/simplify/replace_named_references.rb +1 -1
- data/src/simplify/replace_offsets_with_references.rb +66 -0
- data/src/simplify/replace_ranges_with_array_literals.rb +1 -1
- data/src/simplify/replace_shared_strings.rb +1 -1
- data/src/simplify/replace_table_references.rb +2 -2
- data/src/simplify/replace_values_with_constants.rb +1 -1
- data/src/simplify/simplify_arithmetic.rb +1 -1
- metadata +9 -2
@@ -4,13 +4,18 @@ require_relative '../util'
|
|
4
4
|
|
5
5
|
class FormulaeCalculator
|
6
6
|
include ExcelFunctions
|
7
|
+
attr_accessor :original_excel_filename
|
7
8
|
end
|
8
9
|
|
9
10
|
class MapFormulaeToValues
|
10
11
|
|
12
|
+
attr_accessor :original_excel_filename
|
13
|
+
attr_accessor :replacements_made_in_the_last_pass
|
14
|
+
|
11
15
|
def initialize
|
12
16
|
@value_for_ast = MapValuesToRuby.new
|
13
17
|
@calculator = FormulaeCalculator.new
|
18
|
+
@replacements_made_in_the_last_pass = 0
|
14
19
|
@cache = {}
|
15
20
|
end
|
16
21
|
|
@@ -21,6 +26,7 @@ class MapFormulaeToValues
|
|
21
26
|
# FIXME: Caching works in the odd edge cases of long formula
|
22
27
|
# but I really need to find the root cause of the problem
|
23
28
|
def map(ast)
|
29
|
+
@calculator.original_excel_filename = original_excel_filename
|
24
30
|
@cache[ast] ||= do_map(ast)
|
25
31
|
end
|
26
32
|
|
@@ -33,7 +39,7 @@ class MapFormulaeToValues
|
|
33
39
|
[operator,*ast[1..-1].map {|a| map(a) }]
|
34
40
|
end
|
35
41
|
end
|
36
|
-
|
42
|
+
|
37
43
|
def prefix(operator,argument)
|
38
44
|
argument_value = value(map(argument))
|
39
45
|
return [:prefix, operator, map(argument)] if argument_value == :not_a_value
|
@@ -52,7 +58,7 @@ class MapFormulaeToValues
|
|
52
58
|
end
|
53
59
|
|
54
60
|
alias :comparison :arithmetic
|
55
|
-
|
61
|
+
|
56
62
|
def percentage(number)
|
57
63
|
ast_for_value(value([:percentage, number]))
|
58
64
|
end
|
@@ -82,6 +88,12 @@ class MapFormulaeToValues
|
|
82
88
|
end
|
83
89
|
end
|
84
90
|
end
|
91
|
+
|
92
|
+
def map_count(range)
|
93
|
+
return [:function, "COUNT", range] unless [:array, :cell, :sheet_reference].include?(range.first)
|
94
|
+
range = array_as_values(range)
|
95
|
+
ast_for_value(range.size * range.first.size)
|
96
|
+
end
|
85
97
|
|
86
98
|
def map_index(array,row_number,column_number = :not_specified)
|
87
99
|
return map_index_with_only_two_arguments(array,row_number) if column_number == :not_specified
|
@@ -96,7 +108,7 @@ class MapFormulaeToValues
|
|
96
108
|
return [:function, "INDEX", array_mapped, map(row_number), map(column_number)] unless array_as_values
|
97
109
|
|
98
110
|
result = @calculator.send(MapFormulaeToRuby::FUNCTIONS["INDEX"],array_as_values,row_as_number,column_as_number)
|
99
|
-
result = ast_for_value(result)
|
111
|
+
result = ast_for_value(result)
|
100
112
|
result
|
101
113
|
end
|
102
114
|
|
@@ -107,7 +119,7 @@ class MapFormulaeToValues
|
|
107
119
|
array_as_values = array_as_values(array)
|
108
120
|
return [:function, "INDEX", array_mapped, map(row_number)] unless array_as_values
|
109
121
|
result = @calculator.send(MapFormulaeToRuby::FUNCTIONS["INDEX"],array_as_values,row_as_number)
|
110
|
-
result = ast_for_value(result)
|
122
|
+
result = ast_for_value(result)
|
111
123
|
result
|
112
124
|
end
|
113
125
|
|
@@ -125,8 +137,6 @@ class MapFormulaeToValues
|
|
125
137
|
nil
|
126
138
|
end
|
127
139
|
end
|
128
|
-
|
129
|
-
|
130
140
|
|
131
141
|
def value(ast)
|
132
142
|
return extract_values_from_array(ast) if ast.first == :array
|
@@ -150,6 +160,8 @@ class MapFormulaeToValues
|
|
150
160
|
end
|
151
161
|
|
152
162
|
def ast_for_value(value)
|
163
|
+
return value if value.is_a?(Array) && value.first.is_a?(Symbol)
|
164
|
+
@replacements_made_in_the_last_pass += 1
|
153
165
|
case value
|
154
166
|
when Numeric; [:number,value.inspect]
|
155
167
|
when true; [:boolean_true]
|
@@ -0,0 +1,58 @@
|
|
1
|
+
class ReplaceColumnWithColumnNumberAST
|
2
|
+
|
3
|
+
attr_accessor :replacements_made_in_the_last_pass
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@replacements_made_in_the_last_pass = 0
|
7
|
+
end
|
8
|
+
|
9
|
+
def map(ast)
|
10
|
+
return ast unless ast.is_a?(Array)
|
11
|
+
operator = ast[0]
|
12
|
+
if respond_to?(operator)
|
13
|
+
send(operator,*ast[1..-1])
|
14
|
+
else
|
15
|
+
[operator,*ast[1..-1].map {|a| map(a) }]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def function(name,*args)
|
20
|
+
if name == "COLUMN" && args.size == 1 && [:cell, :sheet_reference].include?(args[0][0])
|
21
|
+
if args[0][0] == :cell
|
22
|
+
reference = Reference.for(args[0][1])
|
23
|
+
elsif args[0][0] == :sheet_reference
|
24
|
+
reference = Reference.for(args[0][2][1])
|
25
|
+
end
|
26
|
+
reference.calculate_excel_variables
|
27
|
+
@replacements_made_in_the_last_pass += 1
|
28
|
+
[:number, reference.excel_column_number.to_s]
|
29
|
+
else
|
30
|
+
[:function,name,*args.map { |a| map(a) }]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
class ReplaceColumnWithColumnNumber
|
38
|
+
|
39
|
+
def self.replace(*args)
|
40
|
+
self.new.replace(*args)
|
41
|
+
end
|
42
|
+
|
43
|
+
attr_accessor :replacements_made_in_the_last_pass
|
44
|
+
|
45
|
+
def replace(input,output)
|
46
|
+
rewriter = ReplaceColumnWithColumnNumberAST.new
|
47
|
+
input.each_line do |line|
|
48
|
+
# Looks to match lines with references
|
49
|
+
if line =~ /"COLUMN"/
|
50
|
+
ref, ast = line.split("\t")
|
51
|
+
output.puts "#{ref}\t#{rewriter.map(eval(ast)).inspect}"
|
52
|
+
else
|
53
|
+
output.puts line
|
54
|
+
end
|
55
|
+
end
|
56
|
+
@replacements_made_in_the_last_pass = rewriter.replacements_made_in_the_last_pass
|
57
|
+
end
|
58
|
+
end
|
@@ -12,7 +12,7 @@ class ReplaceCommonElementsInFormulae
|
|
12
12
|
ref, element = a.split("\t")
|
13
13
|
@common_elements[element.strip] = [:cell, ref]
|
14
14
|
end
|
15
|
-
input.
|
15
|
+
input.each_line do |line|
|
16
16
|
ref, formula = line.split("\t")
|
17
17
|
output.puts "#{ref}\t#{replace_repeated_formulae(eval(formula)).inspect}"
|
18
18
|
end
|
@@ -2,13 +2,18 @@ require_relative 'map_formulae_to_values'
|
|
2
2
|
|
3
3
|
class ReplaceFormulaeWithCalculatedValues
|
4
4
|
|
5
|
+
attr_accessor :excel_file
|
6
|
+
|
5
7
|
def self.replace(*args)
|
6
8
|
self.new.replace(*args)
|
7
9
|
end
|
10
|
+
|
11
|
+
attr_accessor :replacements_made_in_the_last_pass
|
8
12
|
|
9
13
|
def replace(input,output)
|
10
14
|
rewriter = MapFormulaeToValues.new
|
11
|
-
|
15
|
+
rewriter.original_excel_filename = excel_file
|
16
|
+
input.each_line do |line|
|
12
17
|
begin
|
13
18
|
ref, ast = line.split("\t")
|
14
19
|
output.puts "#{ref}\t#{rewriter.map(eval(ast)).inspect}"
|
@@ -18,5 +23,6 @@ class ReplaceFormulaeWithCalculatedValues
|
|
18
23
|
raise
|
19
24
|
end
|
20
25
|
end
|
26
|
+
@replacements_made_in_the_last_pass = rewriter.replacements_made_in_the_last_pass
|
21
27
|
end
|
22
28
|
end
|
@@ -1,7 +1,13 @@
|
|
1
1
|
require_relative '../excel/formula_peg'
|
2
2
|
|
3
3
|
class ReplaceIndirectsWithReferencesAst
|
4
|
-
|
4
|
+
|
5
|
+
attr_accessor :replacements_made_in_the_last_pass
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@replacements_made_in_the_last_pass = 0
|
9
|
+
end
|
10
|
+
|
5
11
|
def map(ast)
|
6
12
|
return ast unless ast.is_a?(Array)
|
7
13
|
operator = ast[0]
|
@@ -13,8 +19,12 @@ class ReplaceIndirectsWithReferencesAst
|
|
13
19
|
end
|
14
20
|
|
15
21
|
def function(name,*args)
|
16
|
-
if name == "INDIRECT" && args
|
22
|
+
if name == "INDIRECT" && args[0][0] == :string
|
23
|
+
@replacements_made_in_the_last_pass += 1
|
17
24
|
Formula.parse(args[0][1]).to_ast[1]
|
25
|
+
elsif name == "INDIRECT" && args[0][0] == :error
|
26
|
+
@replacements_made_in_the_last_pass += 1
|
27
|
+
args[0]
|
18
28
|
else
|
19
29
|
puts "indirect #{[:function,name,*args.map { |a| map(a) }].inspect} not replaced" if name == "INDIRECT"
|
20
30
|
[:function,name,*args.map { |a| map(a) }]
|
@@ -28,10 +38,12 @@ class ReplaceIndirectsWithReferences
|
|
28
38
|
def self.replace(*args)
|
29
39
|
self.new.replace(*args)
|
30
40
|
end
|
41
|
+
|
42
|
+
attr_accessor :replacements_made_in_the_last_pass
|
31
43
|
|
32
44
|
def replace(input,output)
|
33
45
|
rewriter = ReplaceIndirectsWithReferencesAst.new
|
34
|
-
input.
|
46
|
+
input.each_line do |line|
|
35
47
|
# Looks to match lines with references
|
36
48
|
if line =~ /"INDIRECT"/
|
37
49
|
ref, ast = line.split("\t")
|
@@ -40,5 +52,6 @@ class ReplaceIndirectsWithReferences
|
|
40
52
|
output.puts line
|
41
53
|
end
|
42
54
|
end
|
55
|
+
@replacements_made_in_the_last_pass = rewriter.replacements_made_in_the_last_pass
|
43
56
|
end
|
44
57
|
end
|
@@ -68,7 +68,7 @@ class ReplaceNamedReferences
|
|
68
68
|
def replace(values,named_references,output)
|
69
69
|
named_references = NamedReferences.new(named_references.readlines)
|
70
70
|
rewriter = ReplaceNamedReferencesAst.new(named_references,sheet_name)
|
71
|
-
values.
|
71
|
+
values.each_line do |line|
|
72
72
|
# Looks to match shared string lines
|
73
73
|
if line =~ /\[:named_reference/
|
74
74
|
cols = line.split("\t")
|
@@ -0,0 +1,66 @@
|
|
1
|
+
class ReplaceOffsetsWithReferencesAst
|
2
|
+
|
3
|
+
attr_accessor :replacements_made_in_the_last_pass
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@replacements_made_in_the_last_pass = 0
|
7
|
+
end
|
8
|
+
|
9
|
+
def map(ast)
|
10
|
+
return ast unless ast.is_a?(Array)
|
11
|
+
operator = ast[0]
|
12
|
+
if respond_to?(operator)
|
13
|
+
send(operator,*ast[1..-1])
|
14
|
+
else
|
15
|
+
[operator,*ast[1..-1].map {|a| map(a) }]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def function(name,*args)
|
20
|
+
if name == "OFFSET" && args.size == 5 && args[0][0] == :cell && args[1][0] == :number && args[2][0] == :number && args[3][0] == :number && args[4][0] == :number
|
21
|
+
replace_offset(args[0][1], args[1][1], args[2][1], args[3][1], args[4][1])
|
22
|
+
elsif name == "OFFSET" && args.size == 3 && args[0][0] == :cell && args[1][0] == :number && args[2][0] == :number
|
23
|
+
replace_offset(args[0][1], args[1][1], args[2][1])
|
24
|
+
else
|
25
|
+
puts "offset in #{[:function,name,*args.map { |a| map(a) }].inspect} not replaced" if name == "INDIRECT"
|
26
|
+
[:function,name,*args.map { |a| map(a) }]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def replace_offset(reference, row_offset, column_offset, height = 1, width = 1)
|
31
|
+
@replacements_made_in_the_last_pass += 1
|
32
|
+
reference = Reference.for(reference.gsub!("$",""))
|
33
|
+
start_reference = reference.offset(row_offset.to_i, column_offset.to_i)
|
34
|
+
end_reference = reference.offset(row_offset.to_i + height.to_i - 1, column_offset.to_i + width.to_i - 1)
|
35
|
+
if start_reference == end_reference
|
36
|
+
[:cell, start_reference]
|
37
|
+
else
|
38
|
+
[:area, start_reference, end_reference]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
class ReplaceOffsetsWithReferences
|
46
|
+
|
47
|
+
def self.replace(*args)
|
48
|
+
self.new.replace(*args)
|
49
|
+
end
|
50
|
+
|
51
|
+
attr_accessor :replacements_made_in_the_last_pass
|
52
|
+
|
53
|
+
def replace(input,output)
|
54
|
+
rewriter = ReplaceOffsetsWithReferencesAst.new
|
55
|
+
input.each_line do |line|
|
56
|
+
# Looks to match lines with references
|
57
|
+
if line =~ /"OFFSET"/
|
58
|
+
ref, ast = line.split("\t")
|
59
|
+
output.puts "#{ref}\t#{rewriter.map(eval(ast)).inspect}"
|
60
|
+
else
|
61
|
+
output.puts line
|
62
|
+
end
|
63
|
+
end
|
64
|
+
@replacements_made_in_the_last_pass = rewriter.replacements_made_in_the_last_pass
|
65
|
+
end
|
66
|
+
end
|
@@ -39,7 +39,7 @@ class ReplaceRangesWithArrayLiterals
|
|
39
39
|
def replace(input,output)
|
40
40
|
rewriter = ReplaceRangesWithArrayLiteralsAst.new
|
41
41
|
|
42
|
-
input.
|
42
|
+
input.each_line do |line|
|
43
43
|
# Looks to match shared string lines
|
44
44
|
if line =~ /\[:area/
|
45
45
|
content = line.split("\t")
|
@@ -36,7 +36,7 @@ class ReplaceSharedStrings
|
|
36
36
|
# Rewrites ast with shared strings to strings
|
37
37
|
def replace(values,shared_strings,output)
|
38
38
|
rewriter = ReplaceSharedStringAst.new(shared_strings.readlines)
|
39
|
-
values.
|
39
|
+
values.each_line do |line|
|
40
40
|
# Looks to match shared string lines
|
41
41
|
if line =~ /\[:shared_string/
|
42
42
|
ref, ast = line.split("\t")
|
@@ -49,7 +49,7 @@ class ReplaceTableReferences
|
|
49
49
|
|
50
50
|
rewriter = ReplaceTableReferenceAst.new(tables,sheet_name)
|
51
51
|
|
52
|
-
input.
|
52
|
+
input.each_line do |line|
|
53
53
|
# Looks to match shared string lines
|
54
54
|
begin
|
55
55
|
if line =~ /\[(:table_reference|:local_table_reference)/
|
@@ -68,4 +68,4 @@ class ReplaceTableReferences
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
|
-
end
|
71
|
+
end
|
@@ -33,7 +33,7 @@ class ReplaceValuesWithConstants
|
|
33
33
|
|
34
34
|
def replace(input,output)
|
35
35
|
@rewriter ||= MapValuesToConstants.new
|
36
|
-
input.
|
36
|
+
input.each_line do |line|
|
37
37
|
begin
|
38
38
|
ref, ast = line.split("\t")
|
39
39
|
output.puts "#{ref}\t#{rewriter.map(eval(ast)).inspect}"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: excel_to_code
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thomas Counsell, Green on Black Ltd
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-06-
|
11
|
+
date: 2013-06-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubypeg
|
@@ -123,6 +123,7 @@ files:
|
|
123
123
|
- src/excel/excel_functions/and.rb
|
124
124
|
- src/excel/excel_functions/apply_to_range.rb
|
125
125
|
- src/excel/excel_functions/average.rb
|
126
|
+
- src/excel/excel_functions/cell.rb
|
126
127
|
- src/excel/excel_functions/choose.rb
|
127
128
|
- src/excel/excel_functions/cosh.rb
|
128
129
|
- src/excel/excel_functions/count.rb
|
@@ -140,6 +141,7 @@ files:
|
|
140
141
|
- src/excel/excel_functions/less_than.rb
|
141
142
|
- src/excel/excel_functions/less_than_or_equal.rb
|
142
143
|
- src/excel/excel_functions/max.rb
|
144
|
+
- src/excel/excel_functions/mid.rb
|
143
145
|
- src/excel/excel_functions/min.rb
|
144
146
|
- src/excel/excel_functions/mod.rb
|
145
147
|
- src/excel/excel_functions/more_than.rb
|
@@ -151,6 +153,7 @@ files:
|
|
151
153
|
- src/excel/excel_functions/pi.rb
|
152
154
|
- src/excel/excel_functions/pmt.rb
|
153
155
|
- src/excel/excel_functions/power.rb
|
156
|
+
- src/excel/excel_functions/pv.rb
|
154
157
|
- src/excel/excel_functions/round.rb
|
155
158
|
- src/excel/excel_functions/rounddown.rb
|
156
159
|
- src/excel/excel_functions/roundup.rb
|
@@ -161,6 +164,8 @@ files:
|
|
161
164
|
- src/excel/excel_functions/sumif.rb
|
162
165
|
- src/excel/excel_functions/sumifs.rb
|
163
166
|
- src/excel/excel_functions/sumproduct.rb
|
167
|
+
- src/excel/excel_functions/text.rb
|
168
|
+
- src/excel/excel_functions/trim.rb
|
164
169
|
- src/excel/excel_functions/vlookup.rb
|
165
170
|
- src/excel/excel_functions.rb
|
166
171
|
- src/excel/formula_peg.rb
|
@@ -206,10 +211,12 @@ files:
|
|
206
211
|
- src/simplify/map_formulae_to_values.rb
|
207
212
|
- src/simplify/remove_cells.rb
|
208
213
|
- src/simplify/replace_arrays_with_single_cells.rb
|
214
|
+
- src/simplify/replace_column_with_column_number.rb
|
209
215
|
- src/simplify/replace_common_elements_in_formulae.rb
|
210
216
|
- src/simplify/replace_formulae_with_calculated_values.rb
|
211
217
|
- src/simplify/replace_indirects_with_references.rb
|
212
218
|
- src/simplify/replace_named_references.rb
|
219
|
+
- src/simplify/replace_offsets_with_references.rb
|
213
220
|
- src/simplify/replace_ranges_with_array_literals.rb
|
214
221
|
- src/simplify/replace_shared_strings.rb
|
215
222
|
- src/simplify/replace_table_references.rb
|