excel_to_code 0.1.23 → 0.2.0
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/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
|