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.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/TODO +0 -1
  3. data/src/commands/excel_to_c.rb +6 -5
  4. data/src/commands/excel_to_ruby.rb +2 -1
  5. data/src/commands/excel_to_x.rb +69 -37
  6. data/src/compile/c/a.out +0 -0
  7. data/src/compile/c/compile_named_reference_setters.rb +1 -1
  8. data/src/compile/c/compile_to_c.rb +1 -1
  9. data/src/compile/c/compile_to_c_header.rb +1 -1
  10. data/src/compile/c/excel_to_c_runtime.c +117 -1
  11. data/src/compile/c/map_formulae_to_c.rb +4 -0
  12. data/src/compile/c/map_sheet_names_to_c_names.rb +1 -1
  13. data/src/compile/c/map_values_to_c.rb +2 -1
  14. data/src/compile/ruby/compile_to_ruby.rb +2 -2
  15. data/src/compile/ruby/compile_to_ruby_unit_test.rb +1 -1
  16. data/src/compile/ruby/map_formulae_to_ruby.rb +5 -0
  17. data/src/compile/ruby/map_values_to_ruby.rb +2 -1
  18. data/src/excel/excel_functions.rb +10 -0
  19. data/src/excel/excel_functions/cell.rb +14 -0
  20. data/src/excel/excel_functions/mid.rb +20 -0
  21. data/src/excel/excel_functions/negative.rb +2 -0
  22. data/src/excel/excel_functions/pv.rb +37 -0
  23. data/src/excel/excel_functions/text.rb +25 -0
  24. data/src/excel/excel_functions/trim.rb +8 -0
  25. data/src/excel/table.rb +1 -0
  26. data/src/extract/check_for_unknown_functions.rb +1 -1
  27. data/src/rewrite/ast_expand_array_formulae.rb +4 -6
  28. data/src/rewrite/rewrite_array_formulae.rb +2 -2
  29. data/src/rewrite/rewrite_array_formulae_to_arrays.rb +1 -1
  30. data/src/rewrite/rewrite_cell_references_to_include_sheet.rb +1 -1
  31. data/src/rewrite/rewrite_formulae_to_ast.rb +1 -1
  32. data/src/rewrite/rewrite_merge_formulae_and_values.rb +2 -2
  33. data/src/rewrite/rewrite_named_reference_names.rb +1 -1
  34. data/src/rewrite/rewrite_relationship_id_to_filename.rb +1 -1
  35. data/src/rewrite/rewrite_shared_formulae.rb +2 -2
  36. data/src/rewrite/rewrite_values_to_ast.rb +1 -1
  37. data/src/rewrite/rewrite_whole_row_column_references_to_areas.rb +2 -2
  38. data/src/rewrite/rewrite_worksheet_names.rb +6 -3
  39. data/src/simplify.rb +2 -0
  40. data/src/simplify/inline_formulae.rb +18 -1
  41. data/src/simplify/map_formulae_to_values.rb +18 -6
  42. data/src/simplify/remove_cells.rb +1 -1
  43. data/src/simplify/replace_arrays_with_single_cells.rb +1 -1
  44. data/src/simplify/replace_column_with_column_number.rb +58 -0
  45. data/src/simplify/replace_common_elements_in_formulae.rb +1 -1
  46. data/src/simplify/replace_formulae_with_calculated_values.rb +7 -1
  47. data/src/simplify/replace_indirects_with_references.rb +16 -3
  48. data/src/simplify/replace_named_references.rb +1 -1
  49. data/src/simplify/replace_offsets_with_references.rb +66 -0
  50. data/src/simplify/replace_ranges_with_array_literals.rb +1 -1
  51. data/src/simplify/replace_shared_strings.rb +1 -1
  52. data/src/simplify/replace_table_references.rb +2 -2
  53. data/src/simplify/replace_values_with_constants.rb +1 -1
  54. data/src/simplify/simplify_arithmetic.rb +1 -1
  55. 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) unless result.is_a?(Array)
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) unless result.is_a?(Array)
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]
@@ -8,7 +8,7 @@ class RemoveCells
8
8
  end
9
9
 
10
10
  def rewrite(input,output)
11
- input.lines do |line|
11
+ input.each_line do |line|
12
12
  ref = line[/^(.*?)\t/,1]
13
13
  if cells_to_keep.has_key?(ref)
14
14
  output.puts line
@@ -8,7 +8,7 @@ class ReplaceArraysWithSingleCells
8
8
 
9
9
  def replace(input,output)
10
10
 
11
- input.lines do |line|
11
+ input.each_line do |line|
12
12
  # Looks to match shared string lines
13
13
  if line =~ /\[:array/
14
14
  content = line.split("\t")
@@ -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.lines do |line|
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
- input.lines do |line|
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.size == 1 && args[0][0] == :string
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.lines do |line|
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.lines do |line|
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.lines do |line|
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.lines do |line|
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.lines do |line|
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.lines do |line|
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}"
@@ -40,7 +40,7 @@ class SimplifyArithmetic
40
40
 
41
41
  def replace(input,output)
42
42
  rewriter = SimplifyArithmeticAst.new
43
- input.lines do |line|
43
+ input.each_line do |line|
44
44
  # Looks to match lines with references
45
45
  if line =~ /:arithmetic/
46
46
  content = line.split("\t")
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.8
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-05 00:00:00.000000000 Z
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