excel_to_code 0.1.20 → 0.1.21

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dbfac77ee7c479c1e3608dac1dad7892a8156e92
4
- data.tar.gz: f474343c232b69a7b91a05a51fad658253af9991
3
+ metadata.gz: e4ebae76600b8d182956b7c1f6a0d98617cb7aeb
4
+ data.tar.gz: 07751fc9af519871db9f60f6011b8de21ee0e6f8
5
5
  SHA512:
6
- metadata.gz: 20fe12e945146c0d0740e00b534a8474848231cf3d938f71a85fafff43ef977b233ba12cafc53d165a440ce0a3ed950d316ff70a53239af0a314ba1dace6884a
7
- data.tar.gz: e6efe0d22d6f042633ea7885d83ba0319bcddda0ea00adb874784a8e05e7b90b115c6cd02c218b9d62960a99f3e0a9b6136054df623afddb048e123ebbb3e27d
6
+ metadata.gz: 46b666e419461ce012bf8e2f84e2c6b97996943c4d41590c3260e10bbf3de827b4ca6e96caa10f99d16afa80785fea8c6179dc36b0e7f3c58b1a3886f1853daf
7
+ data.tar.gz: e694dff8476a31eea15131fadb9fa44ddf8d77839ce3ab5e525d40a4ba4307d97ebbfa485a4b9bb4847a05663cbe2970db576d92ab52d21c327904f4f6df97d4
@@ -415,7 +415,7 @@ class ExcelToX
415
415
  return @named_references if @named_references
416
416
  @named_references = {}
417
417
  i = input('Named references')
418
- i.lines.each do |line|
418
+ i.each_line do |line|
419
419
  sheet, name, ref = *line.split("\t")
420
420
  key = sheet.size != 0 ? [sheet, name] : name
421
421
  @named_references[key] = eval(ref)
@@ -616,6 +616,7 @@ class ExcelToX
616
616
  # The result of the indirect might be a range, which we need to simplify
617
617
  replace ReplaceRangesWithArrayLiterals, [name, 'Formulae'], [name, 'Formulae']
618
618
  replace ReplaceArithmeticOnRanges, [name, 'Formulae'], [name, 'Formulae']
619
+ replace ReplaceStringJoinOnRanges, [name, 'Formulae'], [name, 'Formulae']
619
620
  replace ReplaceArraysWithSingleCells, [name, 'Formulae'], [name, 'Formulae']
620
621
  replace WrapFormulaeThatReturnArraysAndAReNotInArrays, [name, 'Formulae'], [name, 'Formulae']
621
622
  end
data/src/compile/c/a.out CHANGED
Binary file
@@ -60,6 +60,7 @@ static ExcelValue hlookup(ExcelValue lookup_value_v,ExcelValue lookup_table_v, E
60
60
  static ExcelValue iferror(ExcelValue value, ExcelValue value_if_error);
61
61
  static ExcelValue excel_index(ExcelValue array_v, ExcelValue row_number_v, ExcelValue column_number_v);
62
62
  static ExcelValue excel_index_2(ExcelValue array_v, ExcelValue row_number_v);
63
+ static ExcelValue excel_isnumber(ExcelValue number);
63
64
  static ExcelValue large(ExcelValue array_v, ExcelValue k_v);
64
65
  static ExcelValue left(ExcelValue string_v, ExcelValue number_of_characters_v);
65
66
  static ExcelValue left_1(ExcelValue string_v);
@@ -503,6 +504,14 @@ static ExcelValue not_equal(ExcelValue a_v, ExcelValue b_v) {
503
504
  return result;
504
505
  }
505
506
 
507
+ static ExcelValue excel_isnumber(ExcelValue potential_number) {
508
+ if(potential_number.type == ExcelNumber) {
509
+ return TRUE;
510
+ } else {
511
+ return FALSE;
512
+ }
513
+ }
514
+
506
515
  static ExcelValue excel_if(ExcelValue condition, ExcelValue true_case, ExcelValue false_case ) {
507
516
  CHECK_FOR_PASSED_ERROR(condition)
508
517
 
@@ -2588,6 +2597,15 @@ int test_functions() {
2588
2597
  assert(rank(THREE, rank_2_v, ZERO).type == ExcelError);
2589
2598
 
2590
2599
 
2600
+ // Test the ISNUMBER function
2601
+ assert(excel_isnumber(ONE).type == ExcelBoolean);
2602
+ assert(excel_isnumber(ONE).number == 1);
2603
+ assert(excel_isnumber(BLANK).type == ExcelBoolean);
2604
+ assert(excel_isnumber(BLANK).number == 0);
2605
+ assert(excel_isnumber(new_excel_string("Hello")).type == ExcelBoolean);
2606
+ assert(excel_isnumber(new_excel_string("Hello")).number == 0);
2607
+ assert(excel_isnumber(TRUE).type == ExcelBoolean);
2608
+ assert(excel_isnumber(TRUE).number == 0);
2591
2609
 
2592
2610
  // Release memory
2593
2611
  free_all_allocated_memory();
@@ -45,6 +45,7 @@ class MapFormulaeToC < MapValuesToC
45
45
  'INDEX2' => 'excel_index_2',
46
46
  'INDEX3' => 'excel_index',
47
47
  'INT' => 'excel_int',
48
+ 'ISNUMBER' => 'excel_isnumber',
48
49
  'LARGE' => 'large',
49
50
  'LEFT1' => 'left_1',
50
51
  'LEFT2' => 'left',
@@ -31,6 +31,7 @@ class MapFormulaeToRuby < MapValuesToRuby
31
31
  'IFERROR' => 'iferror',
32
32
  'INDEX' => 'index',
33
33
  'INT' => 'int',
34
+ 'ISNUMBER' => 'isnumber',
34
35
  'LARGE' => 'large',
35
36
  'LEFT' => 'left',
36
37
  'LOG' => 'log',
@@ -87,3 +87,5 @@ require_relative 'excel_functions/log'
87
87
  require_relative 'excel_functions/mmult'
88
88
 
89
89
  require_relative 'excel_functions/rank'
90
+
91
+ require_relative 'excel_functions/isnumber'
@@ -0,0 +1,8 @@
1
+ module ExcelFunctions
2
+
3
+ def isnumber(a)
4
+ return true if a.is_a?(Numeric)
5
+ false
6
+ end
7
+
8
+ end
@@ -117,13 +117,13 @@ class Formula < RubyPeg
117
117
 
118
118
  def table_reference
119
119
  node :table_reference do
120
- table_name && ignore { terminal("[") } && (range_structured_reference || complex_structured_reference || simple_structured_reference) && ignore { terminal("]") }
120
+ table_name && ignore { terminal("[") } && (range_structured_reference || short_range_structured_reference || complex_structured_reference || overly_structured_reference || simple_structured_reference) && ignore { terminal("]") }
121
121
  end
122
122
  end
123
123
 
124
124
  def local_table_reference
125
125
  node :local_table_reference do
126
- ignore { terminal("[") } && (range_structured_reference || complex_structured_reference || overly_structured_reference || simple_structured_reference) && ignore { terminal("]") }
126
+ ignore { terminal("[") } && (range_structured_reference || short_range_structured_reference || complex_structured_reference || overly_structured_reference || simple_structured_reference) && ignore { terminal("]") }
127
127
  end
128
128
  end
129
129
 
@@ -135,6 +135,10 @@ class Formula < RubyPeg
135
135
  terminal(/\[[^\u005d]*\],\[[^\u005d]*\]:\[[^\u005d]*\]/)
136
136
  end
137
137
 
138
+ def short_range_structured_reference
139
+ terminal(/\[[^\u005d]*\]:\[[^\u005d]*\]/)
140
+ end
141
+
138
142
  def complex_structured_reference
139
143
  terminal(/\[[^\u005d]*\],\[[^\u005d]*\]/)
140
144
  end
@@ -18,10 +18,11 @@ percentage := /[-+]?[0-9]+\.?[0-9]*/ `'%'
18
18
  number := /[-+]?[0-9]+\.?[0-9]*([eE][-+]?[0-9]+)?/
19
19
  operator := '+' | '-' | '/' | '*' | '^'
20
20
  external_reference := /\[\d+\]!?/ any_internal_reference
21
- table_reference := table_name `'[' (range_structured_reference | complex_structured_reference | simple_structured_reference) `']'
22
- local_table_reference := `'[' (range_structured_reference | complex_structured_reference | overly_structured_reference | simple_structured_reference) `']'
21
+ table_reference := table_name `'[' (range_structured_reference | short_range_structured_reference | complex_structured_reference | overly_structured_reference | simple_structured_reference) `']'
22
+ local_table_reference := `'[' (range_structured_reference | short_range_structured_reference | complex_structured_reference | overly_structured_reference | simple_structured_reference) `']'
23
23
  table_name = /[.\p{Word}_]+/
24
24
  range_structured_reference = /\[[^\u005d]*\],\[[^\u005d]*\]:\[[^\u005d]*\]/
25
+ short_range_structured_reference = /\[[^\u005d]*\]:\[[^\u005d]*\]/
25
26
  complex_structured_reference = /\[[^\u005d]*\],\[[^\u005d]*\]/
26
27
  overly_structured_reference = `'[' simple_structured_reference `']'
27
28
  simple_structured_reference = /[^\u005d]*/
data/src/excel/table.rb CHANGED
@@ -14,17 +14,20 @@ class Table
14
14
 
15
15
  def reference_for(table_name,structured_reference,calling_worksheet,calling_cell)
16
16
  raise NotSupportedException.new("Local table reference not supported in #{structured_reference.inspect}") unless table_name
17
+
17
18
  case structured_reference
18
19
  when /\[#Headers\],\[(.*?)\]:\[(.*?)\]/io
19
20
  column_number_start = @column_name_array.find_index($1.strip.downcase)
20
21
  column_number_finish = @column_name_array.find_index($2.strip.downcase)
21
22
  return ref_error unless column_number_start && column_number_finish
22
23
  ast_for_area @area.excel_start.offset(0,column_number_start), @area.excel_start.offset(0,column_number_finish)
24
+
23
25
  when /\[#Totals\],\[(.*?)\]:\[(.*?)\]/io
24
26
  column_number_start = @column_name_array.find_index($1.strip.downcase)
25
27
  column_number_finish = @column_name_array.find_index($2.strip.downcase)
26
28
  return ref_error unless column_number_start && column_number_finish
27
29
  ast_for_area @area.excel_start.offset(@area.height,column_number_start), @area.excel_start.offset(@area.height,column_number_finish)
30
+
28
31
  when /\[#This Row\],\[(.*?)\]:\[(.*?)\]/io
29
32
  r = Reference.for(calling_cell)
30
33
  r.calculate_excel_variables
@@ -32,15 +35,24 @@ class Table
32
35
  column_number_start = @column_name_array.find_index($1.strip.downcase)
33
36
  column_number_finish = @column_name_array.find_index($2.strip.downcase)
34
37
  return ref_error unless column_number_start && column_number_finish
35
- ast_for_area @area.excel_start.offset(row - @area.excel_start.excel_row_number,column_number_start), @area.excel_start.offset(row - @area.excel_start.excel_row_number,column_number_finish)
38
+ ast_for_area @area.excel_start.offset(row - @area.excel_start.excel_row_number,column_number_start), @area.excel_start.offset(row - @area.excel_start.excel_row_number,column_number_finish)
39
+
40
+ when /\[(.*?)\]:\[(.*?)\]/io
41
+ column_number_start = @column_name_array.find_index($1.strip.downcase)
42
+ column_number_finish = @column_name_array.find_index($2.strip.downcase)
43
+ return ref_error unless column_number_start && column_number_finish
44
+ ast_for_area @area.excel_start.offset(1,column_number_start), @area.excel_start.offset(@area.height - @number_of_total_rows,column_number_finish)
45
+
36
46
  when /\[#Headers\],\[(.*?)\]/io
37
47
  column_number = @column_name_array.find_index($1.strip.downcase)
38
48
  return ref_error unless column_number
39
49
  ast_for_cell @area.excel_start.offset(0,column_number)
50
+
40
51
  when /\[#Totals\],\[(.*?)\]/io
41
52
  column_number = @column_name_array.find_index($1.strip.downcase)
42
53
  return ref_error unless column_number
43
54
  ast_for_cell @area.excel_start.offset(@area.height,column_number)
55
+
44
56
  when /\[#This Row\],\[(.*?)\]/io
45
57
  r = Reference.for(calling_cell)
46
58
  r.calculate_excel_variables
@@ -48,6 +60,7 @@ class Table
48
60
  column_number = @column_name_array.find_index($1.strip.downcase)
49
61
  return ref_error unless column_number
50
62
  ast_for_cell @area.excel_start.offset(row - @area.excel_start.excel_row_number,column_number)
63
+
51
64
  when /#Headers/io
52
65
  if calling_worksheet == @worksheet && @data_area.includes?(calling_cell)
53
66
  r = Reference.for(calling_cell)
@@ -56,6 +69,7 @@ class Table
56
69
  else
57
70
  ast_for_area @area.excel_start.offset(0,0), @area.excel_start.offset(0,@area.width)
58
71
  end
72
+
59
73
  when /#Totals/io
60
74
  if calling_worksheet == @worksheet && @data_area.includes?(calling_cell)
61
75
  r = Reference.for(calling_cell)
@@ -64,15 +78,19 @@ class Table
64
78
  else
65
79
  ast_for_area @area.excel_start.offset(@area.height,0), @area.excel_start.offset(@area.height,@area.width)
66
80
  end
81
+
67
82
  when /#Data/io, ""
68
83
  ast_for_area @data_area.excel_start, @data_area.excel_finish
84
+
69
85
  when /#All/io, ""
70
86
  ast_for_area @area.excel_start, @area.excel_finish
87
+
71
88
  when /#This Row/io
72
89
  r = Reference.for(calling_cell)
73
90
  r.calculate_excel_variables
74
91
  row = r.excel_row_number
75
92
  ast_for_area "#{@area.excel_start.excel_column}#{row}", "#{@area.excel_finish.excel_column}#{row}"
93
+
76
94
  else
77
95
  if calling_worksheet == @worksheet && @data_area.includes?(calling_cell)
78
96
  r = Reference.for(calling_cell)
data/src/simplify.rb CHANGED
@@ -18,3 +18,4 @@ require_relative "simplify/replace_values_with_constants"
18
18
  require_relative "simplify/sort_into_calculation_order"
19
19
  require_relative "simplify/replace_arithmetic_on_ranges"
20
20
  require_relative "simplify/wrap_formulae_that_return_arrays_and_are_not_in_arrays"
21
+ require_relative "simplify/replace_string_join_on_ranges"
@@ -17,19 +17,39 @@ class ReplaceOffsetsWithReferencesAst
17
17
  end
18
18
 
19
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])
20
+ if name == "OFFSET"
21
+ try_to_replace_offset(*args)
24
22
  else
25
- puts "offset in #{[:function,name,*args.map { |a| map(a) }].inspect} not replaced" if name == "INDIRECT"
26
23
  [:function,name,*args.map { |a| map(a) }]
27
24
  end
28
25
  end
29
26
 
30
- def replace_offset(reference, row_offset, column_offset, height = 1, width = 1)
27
+ def try_to_replace_offset(reference, row_offset, column_offset, height = [:number, 1], width = [:number, 1])
28
+ if [row_offset, column_offset, height, width].all? { |a| a.first == :number }
29
+ if reference.first == :cell
30
+ offset_cell(reference, row_offset, column_offset, height, width)
31
+ elsif reference.first == :sheet_reference && reference[2].first == :cell
32
+ [:sheet_reference, reference[1], offset_cell(reference[2], row_offset, column_offset, height, width)]
33
+ else
34
+ puts "#{[:function, "OFFSET", reference, row_offset, column_offset, height, width]} not replaced"
35
+ [:function, "OFFSET", reference, row_offset, column_offset, height, width]
36
+ end
37
+ else
38
+ puts "#{[:function, "OFFSET", reference, row_offset, column_offset, height, width]} not replaced"
39
+ [:function, "OFFSET", reference, row_offset, column_offset, height, width]
40
+ end
41
+ end
42
+
43
+ def offset_cell(reference, row_offset, column_offset, height, width)
44
+
45
+ reference = reference[1]
46
+ row_offset = row_offset[1].to_i
47
+ column_offset = column_offset[1].to_i
48
+ height = height[1].to_i
49
+ width = width[1].to_i
50
+
31
51
  @replacements_made_in_the_last_pass += 1
32
- reference = Reference.for(reference.gsub!("$",""))
52
+ reference = Reference.for(reference.gsub("$",""))
33
53
  start_reference = reference.offset(row_offset.to_i, column_offset.to_i)
34
54
  end_reference = reference.offset(row_offset.to_i + height.to_i - 1, column_offset.to_i + width.to_i - 1)
35
55
  if start_reference == end_reference
@@ -0,0 +1,75 @@
1
+ class ReplaceStringJoinOnRangesAST
2
+
3
+ def map(ast)
4
+ return ast unless ast.is_a?(Array)
5
+ operator = ast[0]
6
+ if respond_to?(operator)
7
+ send(operator,*ast[1..-1])
8
+ else
9
+ [operator,*ast[1..-1].map {|a| map(a) }]
10
+ end
11
+ end
12
+
13
+ def string_join(*strings)
14
+ # Make sure there is actually a conversion to do
15
+ return [:string_join, *strings] unless strings.any? { |s| s.first == :array }
16
+ # Now work out the largest dimensions
17
+ # Arrays look like this [:array, [:row, 1, 2, 3], [:row, 4, 5, 6]]
18
+ max_rows = 0
19
+ max_columns = 0
20
+ strings.each do |s|
21
+ next unless s.first == :array
22
+ r = s.length - 1 # -1 beause first element is :array
23
+ c = r > 0 ? s[1].length - 1 : 0 # check if rows, if there are, columns is length of that array -1 for initial :row symbol
24
+ max_columns = c if c > max_columns
25
+ max_rows = r if r > max_rows
26
+ end
27
+
28
+ result = [:array]
29
+ (0...max_rows).each do |row_index|
30
+ row = [:row]
31
+ (0...max_columns).each do |column_index|
32
+ column = [:string_join]
33
+ strings.each do |string|
34
+ column << select_from(string, row_index, column_index)
35
+ end
36
+ row << column
37
+ end
38
+ result << row
39
+ end
40
+ result
41
+ end
42
+
43
+ def select_from(maybe_array, row_index, column_index)
44
+ return map(maybe_array) unless maybe_array.first == :array
45
+ row = maybe_array[row_index+1]
46
+ return [:error, "#VALUE!"] unless row
47
+ cell = row[column_index+1]
48
+ return [:error, "#VALUE!"] unless cell
49
+ map(cell)
50
+ end
51
+
52
+
53
+ end
54
+
55
+
56
+ class ReplaceStringJoinOnRanges
57
+
58
+ def self.replace(*args)
59
+ self.new.replace(*args)
60
+ end
61
+
62
+ def replace(input,output)
63
+ rewriter = ReplaceStringJoinOnRangesAST.new
64
+ input.each_line do |line|
65
+ # Looks to match lines with references
66
+ if line =~ /:string_join/ && line =~ /:array/
67
+ content = line.split("\t")
68
+ ast = eval(content.pop)
69
+ output.puts "#{content.join("\t")}\t#{rewriter.map(ast).inspect}"
70
+ else
71
+ output.puts line
72
+ end
73
+ end
74
+ end
75
+ end
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.20
4
+ version: 0.1.21
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-08-28 00:00:00.000000000 Z
11
+ date: 2013-11-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubypeg
@@ -137,6 +137,7 @@ files:
137
137
  - src/excel/excel_functions/iferror.rb
138
138
  - src/excel/excel_functions/index.rb
139
139
  - src/excel/excel_functions/int.rb
140
+ - src/excel/excel_functions/isnumber.rb
140
141
  - src/excel/excel_functions/large.rb
141
142
  - src/excel/excel_functions/left.rb
142
143
  - src/excel/excel_functions/less_than.rb
@@ -224,6 +225,7 @@ files:
224
225
  - src/simplify/replace_offsets_with_references.rb
225
226
  - src/simplify/replace_ranges_with_array_literals.rb
226
227
  - src/simplify/replace_shared_strings.rb
228
+ - src/simplify/replace_string_join_on_ranges.rb
227
229
  - src/simplify/replace_table_references.rb
228
230
  - src/simplify/replace_values_with_constants.rb
229
231
  - src/simplify/simplify_arithmetic.rb