excel_to_code 0.1.23 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/src/commands/excel_to_c.rb +39 -92
- data/src/commands/excel_to_ruby.rb +9 -35
- data/src/commands/excel_to_x.rb +515 -536
- data/src/compile/c/a.out +0 -0
- data/src/compile/c/compile_named_reference_setters.rb +4 -6
- data/src/compile/c/compile_to_c.rb +34 -21
- data/src/compile/c/compile_to_c_header.rb +7 -7
- data/src/compile/c/excel_to_c_runtime.c +8 -4
- data/src/compile/c/map_formulae_to_c.rb +85 -86
- data/src/compile/c/map_values_to_c.rb +7 -1
- data/src/compile/c/map_values_to_c_structs.rb +1 -1
- data/src/compile/ruby/compile_to_ruby.rb +14 -11
- data/src/compile/ruby/compile_to_ruby_unit_test.rb +17 -10
- data/src/compile/ruby/map_formulae_to_ruby.rb +56 -56
- data/src/compile/ruby/map_values_to_ruby.rb +14 -2
- data/src/excel/area.rb +6 -8
- data/src/excel/excel_functions/hlookup.rb +1 -1
- data/src/excel/excel_functions/vlookup.rb +1 -1
- data/src/excel/formula_peg.rb +1 -1
- data/src/excel/formula_peg.txt +1 -1
- data/src/excel/reference.rb +4 -3
- data/src/excel/table.rb +4 -4
- data/src/extract.rb +1 -0
- data/src/extract/check_for_unknown_functions.rb +2 -2
- data/src/extract/extract_array_formulae.rb +9 -9
- data/src/extract/extract_everything.rb +140 -0
- data/src/extract/extract_formulae.rb +30 -20
- data/src/extract/extract_named_references.rb +37 -22
- data/src/extract/extract_relationships.rb +16 -3
- data/src/extract/extract_shared_formulae.rb +8 -11
- data/src/extract/extract_shared_formulae_targets.rb +1 -6
- data/src/extract/extract_shared_strings.rb +21 -8
- data/src/extract/extract_simple_formulae.rb +11 -6
- data/src/extract/extract_table.rb +26 -13
- data/src/extract/extract_values.rb +35 -11
- data/src/extract/extract_worksheet_dimensions.rb +13 -3
- data/src/extract/extract_worksheet_names.rb +16 -3
- data/src/extract/extract_worksheet_table_relationships.rb +16 -4
- data/src/extract/simple_extract_from_xml.rb +9 -11
- data/src/rewrite.rb +3 -0
- data/src/rewrite/ast_copy_formula.rb +5 -1
- data/src/rewrite/ast_expand_array_formulae.rb +71 -59
- data/src/rewrite/caching_formula_parser.rb +110 -0
- data/src/rewrite/rewrite_array_formulae.rb +21 -14
- data/src/rewrite/rewrite_cell_references_to_include_sheet.rb +41 -13
- data/src/rewrite/rewrite_shared_formulae.rb +17 -18
- data/src/rewrite/rewrite_values_to_ast.rb +2 -0
- data/src/rewrite/rewrite_whole_row_column_references_to_areas.rb +28 -25
- data/src/simplify.rb +1 -0
- data/src/simplify/count_formula_references.rb +22 -23
- data/src/simplify/emergency_array_formula_replace_indirect_bodge.rb +44 -0
- data/src/simplify/identify_dependencies.rb +7 -8
- data/src/simplify/identify_repeated_formula_elements.rb +5 -6
- data/src/simplify/inline_formulae.rb +48 -48
- data/src/simplify/map_formulae_to_values.rb +197 -79
- data/src/simplify/remove_cells.rb +13 -6
- data/src/simplify/replace_arithmetic_on_ranges.rb +42 -28
- data/src/simplify/replace_arrays_with_single_cells.rb +11 -5
- data/src/simplify/replace_column_with_column_number.rb +31 -23
- data/src/simplify/replace_common_elements_in_formulae.rb +16 -17
- data/src/simplify/replace_indirects_with_references.rb +26 -21
- data/src/simplify/replace_named_references.rb +26 -31
- data/src/simplify/replace_offsets_with_references.rb +33 -34
- data/src/simplify/replace_ranges_with_array_literals.rb +48 -20
- data/src/simplify/replace_shared_strings.rb +15 -13
- data/src/simplify/replace_string_join_on_ranges.rb +7 -9
- data/src/simplify/replace_table_references.rb +16 -11
- data/src/simplify/replace_values_with_constants.rb +6 -4
- data/src/simplify/simplify_arithmetic.rb +33 -19
- data/src/simplify/sort_into_calculation_order.rb +13 -13
- data/src/simplify/wrap_formulae_that_return_arrays_and_are_not_in_arrays.rb +21 -13
- metadata +19 -2
data/src/compile/c/a.out
CHANGED
Binary file
|
@@ -25,7 +25,7 @@ class MapNamedReferenceToCSetter
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def cell(reference)
|
28
|
-
reference.downcase.
|
28
|
+
Reference.for(reference).unfix.downcase.to_s
|
29
29
|
end
|
30
30
|
|
31
31
|
def sheet_reference(sheet,reference)
|
@@ -56,7 +56,7 @@ class MapNamedReferenceToCSetter
|
|
56
56
|
settable_refs = cells_that_can_be_set_at_runtime[sheet]
|
57
57
|
return false unless settable_refs
|
58
58
|
return true if settable_refs == :all
|
59
|
-
settable_refs.include?(reference.upcase)
|
59
|
+
settable_refs.include?(reference.upcase.to_sym)
|
60
60
|
end
|
61
61
|
|
62
62
|
end
|
@@ -71,12 +71,10 @@ class CompileNamedReferenceSetters
|
|
71
71
|
|
72
72
|
def rewrite(named_references, sheet_names, output)
|
73
73
|
mapper = MapNamedReferenceToCSetter.new
|
74
|
-
mapper.sheet_names =
|
74
|
+
mapper.sheet_names = sheet_names
|
75
75
|
mapper.cells_that_can_be_set_at_runtime = cells_that_can_be_set_at_runtime
|
76
76
|
|
77
|
-
named_references.
|
78
|
-
name, reference = line.split("\t")
|
79
|
-
ast = eval(reference)
|
77
|
+
named_references.each do |name, ast|
|
80
78
|
output.puts "void set_#{name}(ExcelValue newValue) {"
|
81
79
|
output.puts mapper.map(ast)
|
82
80
|
output.puts "}"
|
@@ -4,28 +4,32 @@ class CompileToC
|
|
4
4
|
|
5
5
|
attr_accessor :settable
|
6
6
|
attr_accessor :gettable
|
7
|
-
attr_accessor :worksheet
|
8
7
|
attr_accessor :variable_set_counter
|
9
8
|
|
10
9
|
def self.rewrite(*args)
|
11
10
|
self.new.rewrite(*args)
|
12
11
|
end
|
13
12
|
|
14
|
-
def rewrite(
|
13
|
+
def rewrite(formulae, sheet_names, output)
|
15
14
|
self.settable ||= lambda { |ref| false }
|
16
15
|
self.gettable ||= lambda { |ref| true }
|
17
16
|
@variable_set_counter ||= 0
|
17
|
+
|
18
18
|
mapper = MapFormulaeToC.new
|
19
|
-
mapper.
|
20
|
-
|
21
|
-
c_name = mapper.sheet_names[worksheet] || worksheet
|
22
|
-
input.each_line do |line|
|
19
|
+
mapper.sheet_names = sheet_names
|
20
|
+
formulae.each do |ref, ast|
|
23
21
|
begin
|
24
|
-
|
25
|
-
|
22
|
+
worksheet = ref.first
|
23
|
+
cell = ref.last
|
24
|
+
mapper.worksheet = worksheet
|
25
|
+
worksheet_c_name = mapper.sheet_names[worksheet.to_s] || worksheet.to_s
|
26
26
|
calculation = mapper.map(ast)
|
27
|
-
name =
|
27
|
+
name = worksheet_c_name.length > 0 ? "#{worksheet_c_name}_#{cell.downcase}" : cell.downcase
|
28
|
+
|
29
|
+
# Declare function as static so it can be inlined where possible
|
28
30
|
static_or_not = gettable.call(ref) ? "" : "static "
|
31
|
+
|
32
|
+
# Settable functions need a default value and then a function for getting and setting
|
29
33
|
if settable.call(ref)
|
30
34
|
output.puts "ExcelValue #{name}_default() {"
|
31
35
|
mapper.initializers.each do |i|
|
@@ -34,25 +38,34 @@ class CompileToC
|
|
34
38
|
output.puts " return #{calculation};"
|
35
39
|
output.puts "}"
|
36
40
|
output.puts "static ExcelValue #{name}_variable;"
|
37
|
-
output.puts "ExcelValue #{name}() { if(variable_set[#{@variable_set_counter}] == 1) { return #{name}_variable; } else { return #{
|
41
|
+
output.puts "ExcelValue #{name}() { if(variable_set[#{@variable_set_counter}] == 1) { return #{name}_variable; } else { return #{name}_default(); } }"
|
38
42
|
output.puts "void set_#{name}(ExcelValue newValue) { variable_set[#{@variable_set_counter}] = 1; #{name}_variable = newValue; }"
|
43
|
+
output.puts
|
44
|
+
# Other functions just have a getter
|
39
45
|
else
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
output.puts "
|
46
|
+
# In simple cases, don't bother memoizing the result
|
47
|
+
simple = (ast[0] == :constant) || (ast[0] == :cell && ast[1] =~ /common\d+/) || (ast[0] == :blank) || (ast[0] == :error)
|
48
|
+
|
49
|
+
if simple
|
50
|
+
output.puts "#{static_or_not}ExcelValue #{name}() { return #{calculation}; }"
|
51
|
+
else
|
52
|
+
output.puts "#{static_or_not}ExcelValue #{name}() {"
|
53
|
+
output.puts " static ExcelValue result;"
|
54
|
+
output.puts " if(variable_set[#{@variable_set_counter}] == 1) { return result;}"
|
55
|
+
mapper.initializers.each do |i|
|
56
|
+
output.puts " #{i}"
|
57
|
+
end
|
58
|
+
output.puts " result = #{calculation};"
|
59
|
+
output.puts " variable_set[#{@variable_set_counter}] = 1;"
|
60
|
+
output.puts " return result;"
|
61
|
+
output.puts "}"
|
62
|
+
output.puts
|
45
63
|
end
|
46
|
-
output.puts " result = #{calculation};"
|
47
|
-
output.puts " variable_set[#{@variable_set_counter}] = 1;"
|
48
|
-
output.puts " return result;"
|
49
|
-
output.puts "}"
|
50
64
|
end
|
51
|
-
output.puts
|
52
65
|
@variable_set_counter += 1
|
53
66
|
mapper.reset
|
54
67
|
rescue Exception => e
|
55
|
-
puts "Exception at
|
68
|
+
puts "Exception at #{ref} #{ast}"
|
56
69
|
raise
|
57
70
|
end
|
58
71
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
class CompileToCHeader
|
2
2
|
|
3
|
-
attr_accessor :worksheet
|
4
3
|
attr_accessor :gettable
|
5
4
|
attr_accessor :settable
|
6
5
|
|
@@ -8,17 +7,18 @@ class CompileToCHeader
|
|
8
7
|
self.new.rewrite(*args)
|
9
8
|
end
|
10
9
|
|
11
|
-
def rewrite(
|
12
|
-
c_name = Hash[sheet_names_file.readlines.map { |line| line.strip.split("\t")}][worksheet]
|
10
|
+
def rewrite(formulae, c_name_for_worksheet_name, output)
|
13
11
|
self.gettable ||= lambda { |ref| true }
|
14
12
|
self.settable ||= lambda { |ref| false }
|
15
|
-
|
13
|
+
formulae.each do |ref, ast|
|
16
14
|
begin
|
17
|
-
ref, formula = line.split("\t")
|
18
15
|
static_or_not = (gettable.call(ref) || settable.call(ref)) ? "" : "static "
|
19
|
-
|
16
|
+
worksheet = c_name_for_worksheet_name[ref.first.to_s] || ref.first.to_s
|
17
|
+
ref = ref.last.downcase
|
18
|
+
name = worksheet.length > 0 ? "#{worksheet}_#{ref}" : ref
|
19
|
+
output.puts "#{static_or_not}ExcelValue #{name}();"
|
20
20
|
rescue Exception => e
|
21
|
-
puts "Exception at
|
21
|
+
puts "Exception at #{ref} #{ast}"
|
22
22
|
raise
|
23
23
|
end
|
24
24
|
end
|
@@ -755,7 +755,7 @@ static ExcelValue excel_match(ExcelValue lookup_value, ExcelValue lookup_array,
|
|
755
755
|
}
|
756
756
|
|
757
757
|
static ExcelValue excel_match_2(ExcelValue lookup_value, ExcelValue lookup_array ) {
|
758
|
-
return excel_match(lookup_value,lookup_array,
|
758
|
+
return excel_match(lookup_value, lookup_array, ZERO);
|
759
759
|
}
|
760
760
|
|
761
761
|
static ExcelValue find(ExcelValue find_text_v, ExcelValue within_text_v, ExcelValue start_number_v) {
|
@@ -843,12 +843,12 @@ static ExcelValue left(ExcelValue string_v, ExcelValue number_of_characters_v) {
|
|
843
843
|
printf("Out of memory");
|
844
844
|
exit(-1);
|
845
845
|
}
|
846
|
-
free_later(left_string);
|
847
846
|
memcpy(left_string,string,number_of_characters);
|
848
847
|
left_string[number_of_characters] = '\0';
|
849
848
|
if(string_must_be_freed == 1) {
|
850
849
|
free(string);
|
851
850
|
}
|
851
|
+
free_later(left_string);
|
852
852
|
return new_excel_string(left_string);
|
853
853
|
}
|
854
854
|
|
@@ -1331,7 +1331,6 @@ static ExcelValue string_join(int number_of_arguments, ExcelValue *arguments) {
|
|
1331
1331
|
printf("Out of memory");
|
1332
1332
|
exit(-1);
|
1333
1333
|
}
|
1334
|
-
free_later(string);
|
1335
1334
|
char *current_string;
|
1336
1335
|
int current_string_length;
|
1337
1336
|
int must_free_current_string;
|
@@ -1381,6 +1380,7 @@ static ExcelValue string_join(int number_of_arguments, ExcelValue *arguments) {
|
|
1381
1380
|
}
|
1382
1381
|
string = realloc(string,used_length+1);
|
1383
1382
|
string[used_length] = '\0';
|
1383
|
+
free_later(string);
|
1384
1384
|
return new_excel_string(string);
|
1385
1385
|
}
|
1386
1386
|
|
@@ -1750,8 +1750,8 @@ static ExcelValue text(ExcelValue number_v, ExcelValue format_v) {
|
|
1750
1750
|
if(strcmp(format_v.string,"0%") == 0) {
|
1751
1751
|
// FIXME: Too little?
|
1752
1752
|
s = malloc(100);
|
1753
|
-
free_later(s);
|
1754
1753
|
sprintf(s, "%d%%",(int) round(number_v.number*100));
|
1754
|
+
free_later(s);
|
1755
1755
|
result = new_excel_string(s);
|
1756
1756
|
} else {
|
1757
1757
|
return format_v;
|
@@ -2283,6 +2283,10 @@ int test_functions() {
|
|
2283
2283
|
assert(string_join(2, string_join_array_4).string[8] == '\0');
|
2284
2284
|
// ... should convert TRUE and FALSE into strings
|
2285
2285
|
assert(string_join(3,string_join_array_5).string[4] == 'T');
|
2286
|
+
// Should deal with very long string joins
|
2287
|
+
ExcelValue string_join_array_6[] = {new_excel_string("0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"), new_excel_string("012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789")};
|
2288
|
+
assert(string_join(2, string_join_array_6).string[0] == '0');
|
2289
|
+
free_all_allocated_memory();
|
2286
2290
|
|
2287
2291
|
// Test SUBTOTAL function
|
2288
2292
|
ExcelValue subtotal_array_1[] = {new_excel_number(10),new_excel_number(100),BLANK};
|
@@ -17,67 +17,67 @@ class MapFormulaeToC < MapValuesToC
|
|
17
17
|
end
|
18
18
|
|
19
19
|
FUNCTIONS = {
|
20
|
-
'*' => 'multiply',
|
21
|
-
'+' => 'add',
|
22
|
-
'-' => 'subtract',
|
23
|
-
'/' => 'divide',
|
24
|
-
'<' => 'less_than',
|
25
|
-
'<=' => 'less_than_or_equal',
|
26
|
-
'<>' => 'not_equal',
|
27
|
-
'=' => 'excel_equal',
|
28
|
-
'>' => 'more_than',
|
29
|
-
'>=' => 'more_than_or_equal',
|
30
|
-
'ABS' => 'excel_abs',
|
31
|
-
'AND' => 'excel_and',
|
32
|
-
'AVERAGE' => 'average',
|
33
|
-
'CHOOSE' => 'choose',
|
34
|
-
'CONCATENATE' => 'string_join',
|
35
|
-
'COSH' => 'cosh',
|
36
|
-
'COUNT' => 'count',
|
37
|
-
'COUNTA' => 'counta',
|
38
|
-
'FIND2' => 'find_2',
|
39
|
-
'FIND3' => 'find',
|
40
|
-
'HLOOKUP3' => 'hlookup_3',
|
41
|
-
'HLOOKUP4' => 'hlookup',
|
42
|
-
'IF2' => 'excel_if_2',
|
43
|
-
'IF3' => 'excel_if',
|
44
|
-
'IFERROR' => 'iferror',
|
45
|
-
'INDEX2' => 'excel_index_2',
|
46
|
-
'INDEX3' => 'excel_index',
|
47
|
-
'INT' => 'excel_int',
|
48
|
-
'ISNUMBER' => 'excel_isnumber',
|
49
|
-
'LARGE' => 'large',
|
50
|
-
'LEFT1' => 'left_1',
|
51
|
-
'LEFT2' => 'left',
|
52
|
-
'LOG1' => 'excel_log',
|
53
|
-
'LOG2' => 'excel_log_2',
|
54
|
-
'MATCH2' => 'excel_match_2',
|
55
|
-
'MATCH3' => 'excel_match',
|
56
|
-
'MAX' => 'max',
|
57
|
-
'MIN' => 'min',
|
58
|
-
'MMULT' => 'mmult',
|
59
|
-
'MOD' => 'mod',
|
60
|
-
'PMT' => 'pmt',
|
61
|
-
'PV3' => 'pv_3',
|
62
|
-
'PV4' => 'pv_4',
|
63
|
-
'PV5' => 'pv_5',
|
64
|
-
'RANK2' => 'rank_2',
|
65
|
-
'RANK3' => 'rank',
|
66
|
-
'ROUND' => 'excel_round',
|
67
|
-
'ROUNDDOWN' => 'rounddown',
|
68
|
-
'ROUNDUP' => 'roundup',
|
69
|
-
'string_join' => 'string_join',
|
70
|
-
'SUBTOTAL' => 'subtotal',
|
71
|
-
'SUM' => 'sum',
|
72
|
-
'SUMIF2' => 'sumif_2',
|
73
|
-
'SUMIF3' => 'sumif',
|
74
|
-
'SUMIFS' => 'sumifs',
|
75
|
-
'TEXT2' => 'text',
|
76
|
-
'SUMPRODUCT' => 'sumproduct',
|
77
|
-
'VLOOKUP3' => 'vlookup_3',
|
78
|
-
'VLOOKUP4' => 'vlookup',
|
79
|
-
'^' => 'power',
|
80
|
-
'POWER' => 'power'
|
20
|
+
:'*' => 'multiply',
|
21
|
+
:'+' => 'add',
|
22
|
+
:'-' => 'subtract',
|
23
|
+
:'/' => 'divide',
|
24
|
+
:'<' => 'less_than',
|
25
|
+
:'<=' => 'less_than_or_equal',
|
26
|
+
:'<>' => 'not_equal',
|
27
|
+
:'=' => 'excel_equal',
|
28
|
+
:'>' => 'more_than',
|
29
|
+
:'>=' => 'more_than_or_equal',
|
30
|
+
:'ABS' => 'excel_abs',
|
31
|
+
:'AND' => 'excel_and',
|
32
|
+
:'AVERAGE' => 'average',
|
33
|
+
:'CHOOSE' => 'choose',
|
34
|
+
:'CONCATENATE' => 'string_join',
|
35
|
+
:'COSH' => 'cosh',
|
36
|
+
:'COUNT' => 'count',
|
37
|
+
:'COUNTA' => 'counta',
|
38
|
+
:'FIND2' => 'find_2',
|
39
|
+
:'FIND3' => 'find',
|
40
|
+
:'HLOOKUP3' => 'hlookup_3',
|
41
|
+
:'HLOOKUP4' => 'hlookup',
|
42
|
+
:'IF2' => 'excel_if_2',
|
43
|
+
:'IF3' => 'excel_if',
|
44
|
+
:'IFERROR' => 'iferror',
|
45
|
+
:'INDEX2' => 'excel_index_2',
|
46
|
+
:'INDEX3' => 'excel_index',
|
47
|
+
:'INT' => 'excel_int',
|
48
|
+
:'ISNUMBER' => 'excel_isnumber',
|
49
|
+
:'LARGE' => 'large',
|
50
|
+
:'LEFT1' => 'left_1',
|
51
|
+
:'LEFT2' => 'left',
|
52
|
+
:'LOG1' => 'excel_log',
|
53
|
+
:'LOG2' => 'excel_log_2',
|
54
|
+
:'MATCH2' => 'excel_match_2',
|
55
|
+
:'MATCH3' => 'excel_match',
|
56
|
+
:'MAX' => 'max',
|
57
|
+
:'MIN' => 'min',
|
58
|
+
:'MMULT' => 'mmult',
|
59
|
+
:'MOD' => 'mod',
|
60
|
+
:'PMT' => 'pmt',
|
61
|
+
:'PV3' => 'pv_3',
|
62
|
+
:'PV4' => 'pv_4',
|
63
|
+
:'PV5' => 'pv_5',
|
64
|
+
:'RANK2' => 'rank_2',
|
65
|
+
:'RANK3' => 'rank',
|
66
|
+
:'ROUND' => 'excel_round',
|
67
|
+
:'ROUNDDOWN' => 'rounddown',
|
68
|
+
:'ROUNDUP' => 'roundup',
|
69
|
+
:'string_join' => 'string_join',
|
70
|
+
:'SUBTOTAL' => 'subtotal',
|
71
|
+
:'SUM' => 'sum',
|
72
|
+
:'SUMIF2' => 'sumif_2',
|
73
|
+
:'SUMIF3' => 'sumif',
|
74
|
+
:'SUMIFS' => 'sumifs',
|
75
|
+
:'TEXT2' => 'text',
|
76
|
+
:'SUMPRODUCT' => 'sumproduct',
|
77
|
+
:'VLOOKUP3' => 'vlookup_3',
|
78
|
+
:'VLOOKUP4' => 'vlookup',
|
79
|
+
:'^' => 'power',
|
80
|
+
:'POWER' => 'power'
|
81
81
|
}
|
82
82
|
|
83
83
|
def prefix(symbol,ast)
|
@@ -103,19 +103,19 @@ class MapFormulaeToC < MapValuesToC
|
|
103
103
|
|
104
104
|
def function(function_name,*arguments)
|
105
105
|
# Some functions are special cases
|
106
|
-
if self.respond_to?("function_#{function_name.downcase}")
|
107
|
-
send("function_#{function_name.downcase}",*arguments)
|
106
|
+
if self.respond_to?("function_#{function_name.to_s.downcase}")
|
107
|
+
send("function_#{function_name.to_s.downcase}",*arguments)
|
108
108
|
# Some arguments can take any number of arguments, which we need to treat separately
|
109
|
-
elsif FUNCTIONS_WITH_ANY_NUMBER_OF_ARGUMENTS.include?(function_name)
|
109
|
+
elsif FUNCTIONS_WITH_ANY_NUMBER_OF_ARGUMENTS.include?(function_name.to_s)
|
110
110
|
any_number_of_argument_function(function_name,arguments)
|
111
111
|
|
112
112
|
# Check for whether this function has variants based on the number of arguments
|
113
|
-
elsif FUNCTIONS.has_key?("#{function_name}#{arguments.size}")
|
114
|
-
"#{FUNCTIONS["#{function_name}#{arguments.size}"]}(#{arguments.map { |a| map(a) }.join(",")})"
|
113
|
+
elsif FUNCTIONS.has_key?("#{function_name.to_s}#{arguments.size}".to_sym)
|
114
|
+
"#{FUNCTIONS["#{function_name.to_s}#{arguments.size}".to_sym]}(#{arguments.map { |a| map(a) }.join(",")})"
|
115
115
|
|
116
116
|
# Then check for whether it is just a standard type
|
117
|
-
elsif FUNCTIONS.has_key?(function_name)
|
118
|
-
"#{FUNCTIONS[function_name]}(#{arguments.map { |a| map(a) }.join(",")})"
|
117
|
+
elsif FUNCTIONS.has_key?(function_name.to_sym)
|
118
|
+
"#{FUNCTIONS[function_name.to_sym]}(#{arguments.map { |a| map(a) }.join(",")})"
|
119
119
|
|
120
120
|
else
|
121
121
|
raise NotSupportedException.new("Function #{function_name} with #{arguments.size} arguments not supported")
|
@@ -129,20 +129,20 @@ class MapFormulaeToC < MapValuesToC
|
|
129
129
|
end
|
130
130
|
|
131
131
|
def function_choose(index,*arguments)
|
132
|
-
"#{FUNCTIONS[
|
132
|
+
"#{FUNCTIONS[:CHOOSE]}(#{map(index)}, #{map_arguments_to_array(arguments)})"
|
133
133
|
end
|
134
134
|
|
135
135
|
def function_subtotal(type,*arguments)
|
136
|
-
"#{FUNCTIONS[
|
136
|
+
"#{FUNCTIONS[:SUBTOTAL]}(#{map(type)}, #{map_arguments_to_array(arguments)})"
|
137
137
|
end
|
138
138
|
|
139
139
|
def function_sumifs(sum_range,*criteria)
|
140
|
-
"#{FUNCTIONS[
|
140
|
+
"#{FUNCTIONS[:SUMIFS]}(#{map(sum_range)}, #{map_arguments_to_array(criteria)})"
|
141
141
|
end
|
142
142
|
|
143
143
|
|
144
144
|
def any_number_of_argument_function(function_name,arguments)
|
145
|
-
"#{FUNCTIONS[function_name]}(#{map_arguments_to_array(arguments)})"
|
145
|
+
"#{FUNCTIONS[function_name.to_sym]}(#{map_arguments_to_array(arguments)})"
|
146
146
|
end
|
147
147
|
|
148
148
|
def map_arguments_to_array(arguments)
|
@@ -158,35 +158,34 @@ class MapFormulaeToC < MapValuesToC
|
|
158
158
|
def cell(reference)
|
159
159
|
# FIXME: What a cludge.
|
160
160
|
if reference =~ /common\d+/
|
161
|
-
"
|
161
|
+
"#{reference}()"
|
162
162
|
else
|
163
|
-
reference.downcase.gsub('$','')
|
163
|
+
reference.to_s.downcase.gsub('$','')
|
164
164
|
end
|
165
165
|
end
|
166
166
|
|
167
167
|
def sheet_reference(sheet,reference)
|
168
|
-
"#{sheet_names[sheet]}_#{map(reference).downcase}()"
|
168
|
+
"#{sheet_names[sheet]}_#{map(reference).to_s.downcase}()"
|
169
169
|
end
|
170
170
|
|
171
171
|
def array(*rows)
|
172
172
|
# Make sure we get the right dimensions
|
173
173
|
number_of_rows = rows.size
|
174
|
-
number_of_columns = rows.
|
175
|
-
|
174
|
+
number_of_columns = rows[0].size - 1
|
175
|
+
size = number_of_rows * number_of_columns
|
176
|
+
|
176
177
|
# First we have to create an excel array
|
177
178
|
array_name = "array#{@counter}"
|
178
179
|
@counter +=1
|
179
180
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
181
|
+
initializers << "static ExcelValue #{array_name}[#{size}];"
|
182
|
+
i = 0
|
183
|
+
rows.each do |row|
|
184
|
+
row.each do |cell|
|
185
|
+
next if cell.is_a?(Symbol)
|
186
|
+
initializers << "#{array_name}[#{i}] = #{map(cell)};"
|
187
|
+
i += 1
|
184
188
|
end
|
185
|
-
end.flatten
|
186
|
-
|
187
|
-
initializers << "static ExcelValue #{array_name}[#{cells.size}];"
|
188
|
-
cells.each_with_index do |c,i|
|
189
|
-
initializers << "#{array_name}[#{i}] = #{c};"
|
190
189
|
end
|
191
190
|
|
192
191
|
# Then we need to assign it to an excel value
|
@@ -66,7 +66,13 @@ class MapValuesToC
|
|
66
66
|
"#DIV/0!" => "DIV0",
|
67
67
|
"#REF!" => "REF",
|
68
68
|
"#N/A" => "NA",
|
69
|
-
"#NUM!" => "NUM"
|
69
|
+
"#NUM!" => "NUM",
|
70
|
+
:"#NAME?" => "NAME",
|
71
|
+
:"#VALUE!" => "VALUE",
|
72
|
+
:"#DIV/0!" => "DIV0",
|
73
|
+
:"#REF!" => "REF",
|
74
|
+
:"#N/A" => "NA",
|
75
|
+
:"#NUM!" => "NUM"
|
70
76
|
}
|
71
77
|
|
72
78
|
REVERSE_ERRORS = ERRORS.invert
|