excel_to_code 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README +41 -0
- data/bin/excel_to_c +63 -0
- data/bin/excel_to_ruby +9 -0
- data/src/commands.rb +2 -0
- data/src/commands/excel_to_c.rb +858 -0
- data/src/commands/excel_to_ruby.rb +620 -0
- data/src/compile.rb +2 -0
- data/src/compile/c.rb +5 -0
- data/src/compile/c/compile_to_c.rb +62 -0
- data/src/compile/c/compile_to_c_header.rb +26 -0
- data/src/compile/c/compile_to_c_unit_test.rb +42 -0
- data/src/compile/c/excel_to_c_runtime.c +2029 -0
- data/src/compile/c/map_formulae_to_c.rb +184 -0
- data/src/compile/c/map_sheet_names_to_c_names.rb +19 -0
- data/src/compile/c/map_values_to_c.rb +85 -0
- data/src/compile/c/map_values_to_c_structs.rb +37 -0
- data/src/compile/ruby.rb +3 -0
- data/src/compile/ruby/compile_to_ruby.rb +33 -0
- data/src/compile/ruby/compile_to_ruby_unit_test.rb +28 -0
- data/src/compile/ruby/excel_to_ruby_runtime.rb +1 -0
- data/src/compile/ruby/map_formulae_to_ruby.rb +95 -0
- data/src/compile/ruby/map_sheet_names_to_ruby_names.rb +19 -0
- data/src/compile/ruby/map_values_to_ruby.rb +65 -0
- data/src/excel.rb +5 -0
- data/src/excel/area.rb +93 -0
- data/src/excel/excel_functions.rb +84 -0
- data/src/excel/excel_functions/abs.rb +14 -0
- data/src/excel/excel_functions/add.rb +18 -0
- data/src/excel/excel_functions/and.rb +30 -0
- data/src/excel/excel_functions/apply_to_range.rb +17 -0
- data/src/excel/excel_functions/average.rb +12 -0
- data/src/excel/excel_functions/choose.rb +18 -0
- data/src/excel/excel_functions/cosh.rb +9 -0
- data/src/excel/excel_functions/count.rb +9 -0
- data/src/excel/excel_functions/counta.rb +8 -0
- data/src/excel/excel_functions/divide.rb +23 -0
- data/src/excel/excel_functions/excel_equal.rb +20 -0
- data/src/excel/excel_functions/excel_if.rb +8 -0
- data/src/excel/excel_functions/excel_match.rb +51 -0
- data/src/excel/excel_functions/find.rb +39 -0
- data/src/excel/excel_functions/iferror.rb +10 -0
- data/src/excel/excel_functions/index.rb +48 -0
- data/src/excel/excel_functions/left.rb +12 -0
- data/src/excel/excel_functions/less_than.rb +26 -0
- data/src/excel/excel_functions/less_than_or_equal.rb +26 -0
- data/src/excel/excel_functions/max.rb +12 -0
- data/src/excel/excel_functions/min.rb +12 -0
- data/src/excel/excel_functions/mod.rb +15 -0
- data/src/excel/excel_functions/more_than.rb +26 -0
- data/src/excel/excel_functions/more_than_or_equal.rb +26 -0
- data/src/excel/excel_functions/multiply.rb +24 -0
- data/src/excel/excel_functions/negative.rb +12 -0
- data/src/excel/excel_functions/not_equal.rb +19 -0
- data/src/excel/excel_functions/number_argument.rb +30 -0
- data/src/excel/excel_functions/pi.rb +7 -0
- data/src/excel/excel_functions/pmt.rb +16 -0
- data/src/excel/excel_functions/power.rb +18 -0
- data/src/excel/excel_functions/round.rb +13 -0
- data/src/excel/excel_functions/rounddown.rb +14 -0
- data/src/excel/excel_functions/roundup.rb +17 -0
- data/src/excel/excel_functions/string_join.rb +19 -0
- data/src/excel/excel_functions/subtotal.rb +13 -0
- data/src/excel/excel_functions/subtract.rb +18 -0
- data/src/excel/excel_functions/sum.rb +8 -0
- data/src/excel/excel_functions/sumif.rb +7 -0
- data/src/excel/excel_functions/sumifs.rb +74 -0
- data/src/excel/excel_functions/sumproduct.rb +32 -0
- data/src/excel/excel_functions/vlookup.rb +49 -0
- data/src/excel/formula_peg.rb +238 -0
- data/src/excel/formula_peg.txt +45 -0
- data/src/excel/reference.rb +56 -0
- data/src/excel/table.rb +108 -0
- data/src/excel_to_code.rb +7 -0
- data/src/extract.rb +13 -0
- data/src/extract/check_for_unknown_functions.rb +20 -0
- data/src/extract/extract_array_formulae.rb +23 -0
- data/src/extract/extract_formulae.rb +36 -0
- data/src/extract/extract_named_references.rb +38 -0
- data/src/extract/extract_relationships.rb +10 -0
- data/src/extract/extract_shared_formulae.rb +23 -0
- data/src/extract/extract_shared_strings.rb +20 -0
- data/src/extract/extract_simple_formulae.rb +18 -0
- data/src/extract/extract_table.rb +24 -0
- data/src/extract/extract_values.rb +29 -0
- data/src/extract/extract_worksheet_dimensions.rb +11 -0
- data/src/extract/extract_worksheet_names.rb +10 -0
- data/src/extract/extract_worksheet_table_relationships.rb +10 -0
- data/src/extract/simple_extract_from_xml.rb +19 -0
- data/src/rewrite.rb +10 -0
- data/src/rewrite/ast_copy_formula.rb +42 -0
- data/src/rewrite/ast_expand_array_formulae.rb +180 -0
- data/src/rewrite/rewrite_array_formulae.rb +71 -0
- data/src/rewrite/rewrite_array_formulae_to_arrays.rb +18 -0
- data/src/rewrite/rewrite_cell_references_to_include_sheet.rb +56 -0
- data/src/rewrite/rewrite_formulae_to_ast.rb +24 -0
- data/src/rewrite/rewrite_merge_formulae_and_values.rb +18 -0
- data/src/rewrite/rewrite_relationship_id_to_filename.rb +22 -0
- data/src/rewrite/rewrite_shared_formulae.rb +38 -0
- data/src/rewrite/rewrite_values_to_ast.rb +28 -0
- data/src/rewrite/rewrite_whole_row_column_references_to_areas.rb +90 -0
- data/src/rewrite/rewrite_worksheet_names.rb +20 -0
- data/src/simplify.rb +16 -0
- data/src/simplify/count_formula_references.rb +58 -0
- data/src/simplify/identify_dependencies.rb +56 -0
- data/src/simplify/identify_repeated_formula_elements.rb +37 -0
- data/src/simplify/inline_formulae.rb +77 -0
- data/src/simplify/map_formulae_to_values.rb +157 -0
- data/src/simplify/remove_cells.rb +18 -0
- data/src/simplify/replace_arrays_with_single_cells.rb +27 -0
- data/src/simplify/replace_blanks.rb +58 -0
- data/src/simplify/replace_common_elements_in_formulae.rb +19 -0
- data/src/simplify/replace_formulae_with_calculated_values.rb +21 -0
- data/src/simplify/replace_indirects_with_references.rb +44 -0
- data/src/simplify/replace_named_references.rb +82 -0
- data/src/simplify/replace_ranges_with_array_literals.rb +54 -0
- data/src/simplify/replace_shared_strings.rb +49 -0
- data/src/simplify/replace_table_references.rb +71 -0
- data/src/simplify/replace_values_with_constants.rb +47 -0
- data/src/simplify/simplify_arithmetic.rb +54 -0
- data/src/util.rb +2 -0
- data/src/util/not_supported_exception.rb +2 -0
- data/src/util/try.rb +9 -0
- metadata +207 -0
@@ -0,0 +1,19 @@
|
|
1
|
+
class MapSheetNamesToRubyNames
|
2
|
+
|
3
|
+
def self.rewrite(*args)
|
4
|
+
self.new.rewrite(*args)
|
5
|
+
end
|
6
|
+
|
7
|
+
def rewrite(input,output)
|
8
|
+
ruby_names_assigned = {}
|
9
|
+
input.lines do |line|
|
10
|
+
excel_worksheet_name = line.split("\t").first
|
11
|
+
ruby_name = excel_worksheet_name.downcase.gsub(/[^a-z0-9]+/,'_')
|
12
|
+
ruby_name = "s"+ruby_name if ruby_name[0] !~ /[a-z]/
|
13
|
+
ruby_name = ruby_name + "2" if ruby_names_assigned.has_key?(ruby_name)
|
14
|
+
ruby_name.succ! while ruby_names_assigned.has_key?(ruby_name)
|
15
|
+
output.puts "#{excel_worksheet_name}\t#{ruby_name}"
|
16
|
+
ruby_names_assigned[ruby_name] = excel_worksheet_name
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require_relative '../../util/not_supported_exception'
|
2
|
+
|
3
|
+
class MapValuesToRuby
|
4
|
+
|
5
|
+
def map(ast)
|
6
|
+
if ast.is_a?(Array)
|
7
|
+
operator = ast[0]
|
8
|
+
if respond_to?(operator)
|
9
|
+
send(operator,*ast[1..-1])
|
10
|
+
else
|
11
|
+
raise NotSupportedException.new("#{operator} in #{ast.inspect} not supported")
|
12
|
+
end
|
13
|
+
else
|
14
|
+
raise NotSupportedException.new("#{ast} not supported")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def blank
|
19
|
+
"nil"
|
20
|
+
end
|
21
|
+
|
22
|
+
alias :null :blank
|
23
|
+
|
24
|
+
def number(text)
|
25
|
+
case text
|
26
|
+
when /\./
|
27
|
+
text.to_f.to_s
|
28
|
+
when /e/i
|
29
|
+
text.to_f.to_s
|
30
|
+
else
|
31
|
+
text.to_i.to_s
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def percentage(text)
|
36
|
+
(text.to_f / 100.0).to_s
|
37
|
+
end
|
38
|
+
|
39
|
+
def string(text)
|
40
|
+
text.inspect
|
41
|
+
end
|
42
|
+
|
43
|
+
ERRORS = {
|
44
|
+
"#NAME?" => ":name",
|
45
|
+
"#VALUE!" => ":value",
|
46
|
+
"#DIV/0!" => ":div0",
|
47
|
+
"#REF!" => ":ref",
|
48
|
+
"#N/A" => ":na"
|
49
|
+
}
|
50
|
+
|
51
|
+
REVERSE_ERRORS = ERRORS.invert
|
52
|
+
|
53
|
+
def error(text)
|
54
|
+
ERRORS[text] || (raise NotSupportedException.new("#{text.inspect} error not recognised"))
|
55
|
+
end
|
56
|
+
|
57
|
+
def boolean_true
|
58
|
+
"true"
|
59
|
+
end
|
60
|
+
|
61
|
+
def boolean_false
|
62
|
+
"false"
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
data/src/excel.rb
ADDED
data/src/excel/area.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
require_relative 'reference'
|
2
|
+
|
3
|
+
class Area < String
|
4
|
+
|
5
|
+
# This is so that we only have one instance for a given area
|
6
|
+
@@areas_for_text ||= Hash.new do |hash,text|
|
7
|
+
hash[text] = area = Area.new(text)
|
8
|
+
area
|
9
|
+
end
|
10
|
+
|
11
|
+
# This is so that we only have one instance of a given reference specified by its variables
|
12
|
+
def Area.for(text)
|
13
|
+
@@areas_for_text[text]
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :excel_start, :excel_finish
|
17
|
+
|
18
|
+
def calculate_excel_variables
|
19
|
+
return if @excel_variables_calculated
|
20
|
+
if self =~ /([^:]+):(.*)/
|
21
|
+
@excel_start = Reference.for($1)
|
22
|
+
@excel_finish = Reference.for($2)
|
23
|
+
else
|
24
|
+
@excel_start = @excel_finish = Reference.for(self)
|
25
|
+
end
|
26
|
+
@excel_start.calculate_excel_variables
|
27
|
+
@excel_finish.calculate_excel_variables
|
28
|
+
end
|
29
|
+
|
30
|
+
def offset(row,column)
|
31
|
+
calculate_excel_variables
|
32
|
+
Area.for([
|
33
|
+
@excel_start.offset(row,column),
|
34
|
+
':',
|
35
|
+
@excel_finish.offset(row,column),
|
36
|
+
].join)
|
37
|
+
end
|
38
|
+
|
39
|
+
def offsets
|
40
|
+
Enumerator.new do |yielder|
|
41
|
+
0.upto(width).each do |c|
|
42
|
+
0.upto(height).each do |r|
|
43
|
+
yielder.yield([r,c])
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def height
|
50
|
+
calculate_excel_variables
|
51
|
+
@excel_finish.excel_row_number - @excel_start.excel_row_number
|
52
|
+
end
|
53
|
+
|
54
|
+
def width
|
55
|
+
calculate_excel_variables
|
56
|
+
@excel_finish.excel_column_number - @excel_start.excel_column_number
|
57
|
+
end
|
58
|
+
|
59
|
+
def to_array_literal(sheet = nil)
|
60
|
+
calculate_excel_variables
|
61
|
+
unfixed_start = @excel_start.unfix
|
62
|
+
[:array,
|
63
|
+
*(0.upto(height).map do |row|
|
64
|
+
[:row,
|
65
|
+
*(0.upto(width).map do |column|
|
66
|
+
if sheet
|
67
|
+
[:sheet_reference,
|
68
|
+
sheet,
|
69
|
+
[:cell,
|
70
|
+
unfixed_start.offset(row,column)
|
71
|
+
]
|
72
|
+
]
|
73
|
+
else
|
74
|
+
[:cell,
|
75
|
+
unfixed_start.offset(row,column)
|
76
|
+
]
|
77
|
+
end
|
78
|
+
end)
|
79
|
+
]
|
80
|
+
end)
|
81
|
+
]
|
82
|
+
end
|
83
|
+
|
84
|
+
def includes?(reference)
|
85
|
+
calculate_excel_variables
|
86
|
+
r = Reference.for(reference)
|
87
|
+
r.calculate_excel_variables
|
88
|
+
return false if r.excel_row_number < @excel_start.excel_row_number || r.excel_row_number > @excel_finish.excel_row_number
|
89
|
+
return false if r.excel_column_number < @excel_start.excel_column_number || r.excel_column_number > @excel_finish.excel_column_number
|
90
|
+
true
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module ExcelFunctions
|
2
|
+
end
|
3
|
+
|
4
|
+
# Support functions
|
5
|
+
require_relative 'excel_functions/number_argument'
|
6
|
+
|
7
|
+
# Constants
|
8
|
+
require_relative 'excel_functions/pi'
|
9
|
+
|
10
|
+
# Comparators
|
11
|
+
require_relative 'excel_functions/excel_equal'
|
12
|
+
require_relative 'excel_functions/less_than'
|
13
|
+
require_relative 'excel_functions/more_than'
|
14
|
+
require_relative 'excel_functions/less_than_or_equal'
|
15
|
+
require_relative 'excel_functions/more_than_or_equal'
|
16
|
+
require_relative 'excel_functions/not_equal'
|
17
|
+
|
18
|
+
require_relative 'excel_functions/excel_if'
|
19
|
+
require_relative 'excel_functions/iferror'
|
20
|
+
|
21
|
+
# Basic arithmetic
|
22
|
+
require_relative 'excel_functions/add'
|
23
|
+
require_relative 'excel_functions/subtract'
|
24
|
+
require_relative 'excel_functions/multiply'
|
25
|
+
require_relative 'excel_functions/divide'
|
26
|
+
require_relative 'excel_functions/power'
|
27
|
+
|
28
|
+
# More advanced arithmetic
|
29
|
+
require_relative 'excel_functions/abs'
|
30
|
+
require_relative 'excel_functions/and'
|
31
|
+
require_relative 'excel_functions/mod'
|
32
|
+
|
33
|
+
# Array arithmetic
|
34
|
+
require_relative 'excel_functions/sum'
|
35
|
+
require_relative 'excel_functions/average'
|
36
|
+
require_relative 'excel_functions/max'
|
37
|
+
require_relative 'excel_functions/min'
|
38
|
+
|
39
|
+
# Financial functions
|
40
|
+
require_relative 'excel_functions/pmt'
|
41
|
+
|
42
|
+
# Geometry functions
|
43
|
+
require_relative 'excel_functions/cosh'
|
44
|
+
|
45
|
+
# String functions
|
46
|
+
require_relative 'excel_functions/string_join'
|
47
|
+
require_relative 'excel_functions/excel_match'
|
48
|
+
require_relative 'excel_functions/find'
|
49
|
+
|
50
|
+
# Search functions
|
51
|
+
require_relative 'excel_functions/choose'
|
52
|
+
|
53
|
+
# Other functions
|
54
|
+
|
55
|
+
|
56
|
+
|
57
|
+
|
58
|
+
|
59
|
+
|
60
|
+
require_relative 'excel_functions/round'
|
61
|
+
|
62
|
+
require_relative 'excel_functions/subtotal'
|
63
|
+
|
64
|
+
require_relative 'excel_functions/count'
|
65
|
+
|
66
|
+
require_relative 'excel_functions/counta'
|
67
|
+
|
68
|
+
require_relative 'excel_functions/sumif'
|
69
|
+
|
70
|
+
require_relative 'excel_functions/sumifs'
|
71
|
+
|
72
|
+
require_relative 'excel_functions/sumproduct'
|
73
|
+
|
74
|
+
require_relative 'excel_functions/vlookup'
|
75
|
+
|
76
|
+
require_relative 'excel_functions/index'
|
77
|
+
|
78
|
+
require_relative 'excel_functions/left'
|
79
|
+
|
80
|
+
require_relative 'excel_functions/roundup'
|
81
|
+
|
82
|
+
require_relative 'excel_functions/rounddown'
|
83
|
+
|
84
|
+
require_relative 'excel_functions/negative'
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative 'number_argument'
|
2
|
+
require_relative 'apply_to_range'
|
3
|
+
|
4
|
+
module ExcelFunctions
|
5
|
+
|
6
|
+
def add(a,b)
|
7
|
+
# return apply_to_range(a,b) { |a,b| add(a,b) } if a.is_a?(Array) || b.is_a?(Array)
|
8
|
+
|
9
|
+
a = number_argument(a)
|
10
|
+
b = number_argument(b)
|
11
|
+
|
12
|
+
return a if a.is_a?(Symbol)
|
13
|
+
return b if b.is_a?(Symbol)
|
14
|
+
|
15
|
+
a + b
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module ExcelFunctions
|
2
|
+
|
3
|
+
def excel_and(*args)
|
4
|
+
# Flatten arrays
|
5
|
+
args = args.flatten
|
6
|
+
|
7
|
+
# If an argument is an error, return that
|
8
|
+
error = args.find {|a| a.is_a?(Symbol)}
|
9
|
+
return error if error
|
10
|
+
|
11
|
+
# Replace 1 and 0 with true and false
|
12
|
+
args.map! do |a|
|
13
|
+
case a
|
14
|
+
when 1; true
|
15
|
+
when 0; false
|
16
|
+
else; a
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Remove anything not boolean
|
21
|
+
args.delete_if { |a| !(a.is_a?(TrueClass) || a.is_a?(FalseClass)) }
|
22
|
+
|
23
|
+
# Return an error if nothing less
|
24
|
+
return :value if args.empty?
|
25
|
+
|
26
|
+
# Now calculate and return
|
27
|
+
args.all? {|a| a == true }
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module ExcelFunctions
|
2
|
+
|
3
|
+
def apply_to_range(a,b)
|
4
|
+
a = Array.new(b.length,Array.new(b.first.length,a)) unless a.is_a?(Array)
|
5
|
+
b = Array.new(a.length,Array.new(a.first.length,b)) unless b.is_a?(Array)
|
6
|
+
|
7
|
+
return :value unless b.length == a.length
|
8
|
+
return :value unless b.first.length == a.first.length
|
9
|
+
|
10
|
+
a.map.with_index do |row,i|
|
11
|
+
row.map.with_index do |cell,j|
|
12
|
+
yield cell, b[i][j]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module ExcelFunctions
|
2
|
+
|
3
|
+
def average(*args)
|
4
|
+
args = args.flatten
|
5
|
+
error = args.find {|a| a.is_a?(Symbol)}
|
6
|
+
return error if error
|
7
|
+
args.delete_if { |a| !a.is_a?(Numeric) }
|
8
|
+
return :div0 if args.empty?
|
9
|
+
args.inject(0.0) { |m,i| m + i.to_f } / args.size.to_f
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module ExcelFunctions
|
2
|
+
|
3
|
+
def choose(index,*args)
|
4
|
+
# If an argument is an error, return that
|
5
|
+
return index if index.is_a?(Symbol)
|
6
|
+
error = args.find {|a| a.is_a?(Symbol)}
|
7
|
+
return error if error
|
8
|
+
|
9
|
+
# If the index is out of bounds, return an error
|
10
|
+
return :value unless index
|
11
|
+
return :value if index < 1
|
12
|
+
return :value if index > args.length
|
13
|
+
|
14
|
+
return args[index-1] || 0
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require_relative 'number_argument'
|
2
|
+
require_relative 'apply_to_range'
|
3
|
+
|
4
|
+
module ExcelFunctions
|
5
|
+
|
6
|
+
def divide(a,b)
|
7
|
+
# return apply_to_range(a,b) { |a,b| divide(a,b) } if a.is_a?(Array) || b.is_a?(Array)
|
8
|
+
|
9
|
+
a = number_argument(a)
|
10
|
+
b = number_argument(b)
|
11
|
+
|
12
|
+
return a if a.is_a?(Symbol)
|
13
|
+
return b if b.is_a?(Symbol)
|
14
|
+
|
15
|
+
return :div0 if b == 0
|
16
|
+
|
17
|
+
a / b.to_f
|
18
|
+
|
19
|
+
rescue ZeroDivisionError
|
20
|
+
:div0
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|