excel_to_code 0.2.17 → 0.2.18

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: dcc23d2c3bc1b795812df13662b81933f5c7f063
4
- data.tar.gz: d62a97bca9808a673114f2169aeaa9e129a681fd
3
+ metadata.gz: 337fc100f3818bf193414bcd8fb3aaec557e1a6b
4
+ data.tar.gz: 34218ff7c787a63a1e0081b688ff328d1235316e
5
5
  SHA512:
6
- metadata.gz: f3d4e6502be8a144b705bdc4848b174fca86136f8e59d96b1cbc1e70605ec96e6034542f336fff212df4fd818e63ad841567285d95e0569443d68dd5f1e5fbed
7
- data.tar.gz: ef7aac9705e55a267e129a160a29614f1d24926fec23b4686e8eecca0d5c82a51ab8c91d8f3fdb68aee42de2686c86a075ca14403f43b6021f3fcb09bab5a751
6
+ metadata.gz: 10b5b04a5fe6ae0b5df092a010b5cbf0cad48025db71b99350da7a040e2992c5301c08f23652040b4eb340fcb2f064aa7bae7c02b765c53c8849e11480a66a71
7
+ data.tar.gz: 3ec3fbfbad7b341990559ae40d121dfdbd46839aa3f92f5a1b41b58ce597e43606d91de146bc940d5976b682320b593925bea0619463f9e183b98800f0b15a5c
@@ -838,6 +838,7 @@ class ExcelToX
838
838
  @replace_arrays_with_single_cells_replacer ||= ReplaceArraysWithSingleCellsAst.new
839
839
  @replace_string_joins_on_ranges_replacer ||= ReplaceStringJoinOnRangesAST.new
840
840
  @sheetless_cell_reference_replacer ||= RewriteCellReferencesToIncludeSheetAst.new
841
+ @replace_references_to_blanks_with_zeros ||= ReplaceReferencesToBlanksWithZeros.new(@formulae, nil, inline_ast_decision)
841
842
 
842
843
  cells.each do |ref, ast|
843
844
  begin
@@ -858,6 +859,8 @@ class ExcelToX
858
859
  @replace_arithmetic_on_ranges_replacer.map(ast)
859
860
  @replace_string_joins_on_ranges_replacer.map(ast)
860
861
  @wrap_formulae_that_return_arrays_replacer.map(ast)
862
+ @replace_references_to_blanks_with_zeros.current_sheet_name = ref.first
863
+ @replace_references_to_blanks_with_zeros.map(ast)
861
864
  rescue Exception => e
862
865
  log.fatal "Exception when simplifying #{ref}: #{ast}"
863
866
  raise
data/src/compile/c/a.out CHANGED
Binary file
@@ -100,6 +100,7 @@ static ExcelValue sumif(ExcelValue check_range_v, ExcelValue criteria_v, ExcelVa
100
100
  static ExcelValue sumif_2(ExcelValue check_range_v, ExcelValue criteria_v);
101
101
  static ExcelValue sumproduct(int number_of_arguments, ExcelValue *arguments);
102
102
  static ExcelValue text(ExcelValue number_v, ExcelValue format_v);
103
+ static ExcelValue value(ExcelValue string_v);
103
104
  static ExcelValue vlookup_3(ExcelValue lookup_value_v,ExcelValue lookup_table_v, ExcelValue column_number_v);
104
105
  static ExcelValue vlookup(ExcelValue lookup_value_v,ExcelValue lookup_table_v, ExcelValue column_number_v, ExcelValue match_type_v);
105
106
 
@@ -1716,6 +1717,11 @@ static ExcelValue filter_range(ExcelValue original_range_v, int number_of_argume
1716
1717
  value_to_be_checked = ((ExcelValue *) ((ExcelValue) criteria_range[i]).array)[j];
1717
1718
  comparison = criteria[i];
1718
1719
  comparator = comparison.comparator;
1720
+
1721
+ // For the purposes of comparison, treates a blank criteria as matching zeros.
1722
+ if(comparator.type == ExcelEmpty) {
1723
+ comparator = ZERO;
1724
+ }
1719
1725
 
1720
1726
  switch(value_to_be_checked.type) {
1721
1727
  case ExcelError: // Errors match only errors
@@ -1737,7 +1743,6 @@ static ExcelValue filter_range(ExcelValue original_range_v, int number_of_argume
1737
1743
  if(strlen(comparator.string) != 0) passed = 0; // Empty strings match blanks.
1738
1744
  break;
1739
1745
  }
1740
- break;
1741
1746
  case ExcelNumber:
1742
1747
  if(comparator.type == ExcelNumber) {
1743
1748
  number = comparator.number;
@@ -1781,6 +1786,13 @@ static ExcelValue filter_range(ExcelValue original_range_v, int number_of_argume
1781
1786
  passed = 0;
1782
1787
  break;
1783
1788
  }
1789
+
1790
+ // Special case, empty strings don't match zeros here
1791
+ if(strlen(value_to_be_checked.string) == 0) {
1792
+ passed = 0;
1793
+ break;
1794
+ }
1795
+
1784
1796
  number = number_from(value_to_be_checked);
1785
1797
  if(conversion_error == 1) {
1786
1798
  conversion_error = 0;
@@ -2080,3 +2092,11 @@ static ExcelValue hlookup(ExcelValue lookup_value_v,ExcelValue lookup_table_v, E
2080
2092
  }
2081
2093
  return NA;
2082
2094
  }
2095
+
2096
+
2097
+ static ExcelValue value(ExcelValue string_v) {
2098
+ CHECK_FOR_PASSED_ERROR(string_v)
2099
+ NUMBER(string_v, a)
2100
+ CHECK_FOR_CONVERSION_ERROR
2101
+ return new_excel_number(a);
2102
+ }
@@ -492,16 +492,25 @@ int test_functions() {
492
492
  ExcelValue sumifs_array_10f[] = { sumifs_array_3_v, new_excel_string(">=3")};
493
493
  assert(sumifs(sumifs_array_3_v,2, sumifs_array_10f).number == 17);
494
494
 
495
- // ... should treat BLANK as an empty string when in the check_range, but not in the criteria
496
- ExcelValue sumifs_array_11[] = { BLANK, new_excel_number(20)};
495
+ // ... BLANK in check range should match empty strings, BLANK in criteria should match zero
496
+ ExcelValue sumifs_array_11[] = { BLANK, new_excel_number(0)};
497
497
  assert(sumifs(new_excel_number(100),2,sumifs_array_11).number == 0);
498
498
 
499
- ExcelValue sumifs_array_12[] = {BLANK, new_excel_string("")};
499
+ ExcelValue sumifs_array_11b[] = { BLANK, new_excel_string("")};
500
+ assert(sumifs(new_excel_number(100),2,sumifs_array_11b).number == 100);
501
+
502
+ ExcelValue sumifs_array_11c[] = { new_excel_string(""), BLANK};
503
+ assert(sumifs(new_excel_number(100),2,sumifs_array_11c).number == 0);
504
+
505
+ ExcelValue sumifs_array_12[] = {new_excel_number(0), BLANK};
500
506
  assert(sumifs(new_excel_number(100),2,sumifs_array_12).number == 100);
501
507
 
502
508
  ExcelValue sumifs_array_13[] = {BLANK, BLANK};
503
509
  assert(sumifs(new_excel_number(100),2,sumifs_array_13).number == 0);
504
510
 
511
+ ExcelValue sumifs_array_14[] = {new_excel_number(10), BLANK};
512
+ assert(sumifs(new_excel_number(100),2,sumifs_array_14).number == 0);
513
+
505
514
  // ... should return an error if range argument is an error
506
515
  assert(sumifs(REF,2,sumifs_array_13).type == ExcelError);
507
516
 
@@ -817,7 +826,7 @@ int test_functions() {
817
826
  ExcelValue averageifs_array_11[] = { BLANK, new_excel_number(20)};
818
827
  assert(averageifs(new_excel_number(100),2,averageifs_array_11).type == ExcelError);
819
828
 
820
- ExcelValue averageifs_array_12[] = {BLANK, new_excel_string("")};
829
+ ExcelValue averageifs_array_12[] = {new_excel_number(0), BLANK};
821
830
  assert(averageifs(new_excel_number(100),2,averageifs_array_12).number == 100);
822
831
 
823
832
  ExcelValue averageifs_array_13[] = {BLANK, BLANK};
@@ -881,6 +890,16 @@ int test_functions() {
881
890
  assert(len(TRUE).number == 4);
882
891
  assert(len(FALSE).number == 5);
883
892
 
893
+
894
+ // VALUE(something)
895
+ assert(value(BLANK).type == ExcelNumber);
896
+ assert(value(BLANK).number == 0);
897
+ assert(value(ONE).type == ExcelNumber);
898
+ assert(value(ONE).number == 1);
899
+ assert(value(new_excel_string("1")).type == ExcelNumber);
900
+ assert(value(new_excel_string("1")).number == 1);
901
+ assert(value(new_excel_string("A1A")).type == ExcelError);
902
+
884
903
  // Release memory
885
904
  free_all_allocated_memory();
886
905
 
@@ -82,6 +82,7 @@ class MapFormulaeToC < MapValuesToC
82
82
  :'SUMIFS' => 'sumifs',
83
83
  :'TEXT2' => 'text',
84
84
  :'SUMPRODUCT' => 'sumproduct',
85
+ :'VALUE' => 'value',
85
86
  :'VLOOKUP3' => 'vlookup_3',
86
87
  :'VLOOKUP4' => 'vlookup',
87
88
  :'^' => 'power',
@@ -65,6 +65,7 @@ class MapFormulaeToRuby < MapValuesToRuby
65
65
  :'SUMPRODUCT' => 'sumproduct',
66
66
  :'TEXT' => 'text',
67
67
  :'TRIM' => 'trim',
68
+ :'VALUE' => 'value',
68
69
  :'VLOOKUP' => 'vlookup',
69
70
  :'^' => 'power'
70
71
  }
@@ -106,3 +106,5 @@ require_relative 'excel_functions/averageifs'
106
106
  require_relative 'excel_functions/forecast'
107
107
 
108
108
  require_relative 'excel_functions/ensure_is_number'
109
+
110
+ require_relative 'excel_functions/value'
@@ -31,10 +31,10 @@ module ExcelFunctions
31
31
 
32
32
  0.step(criteria.length-1,2).each do |i|
33
33
  check_range = criteria[i]
34
- required_value = criteria[i+1]
34
+ required_value = criteria[i+1] || 0
35
35
  return :value if index >= check_range.length
36
36
  check_value = check_range[index]
37
-
37
+
38
38
  pass = case check_value
39
39
  when String
40
40
  check_value.downcase == required_value.to_s.downcase
@@ -0,0 +1,7 @@
1
+ module ExcelFunctions
2
+
3
+ def value(a)
4
+ number_argument(a)
5
+ end
6
+
7
+ end
@@ -159,7 +159,7 @@ class Formula < RubyPeg
159
159
 
160
160
  def sheet_reference
161
161
  node :sheet_reference do
162
- (single_quoted_string || terminal(/[\p{word}][\p{word}_.]+/)) && ignore { terminal("!") } && (sheetless_reference || named_reference)
162
+ (single_quoted_string || terminal(/[\p{word}][\p{word}_.]+/)) && ignore { terminal("!") } && (sheetless_reference || error || named_reference)
163
163
  end
164
164
  end
165
165
 
@@ -27,7 +27,7 @@ complex_structured_reference = /\[[^\u005d]*\],\[[^\u005d]*\]/
27
27
  overly_structured_reference = `'[' simple_structured_reference `']'
28
28
  simple_structured_reference = /[^\u005d]*/
29
29
  named_reference := /[#\p{word}][\p{word}_.!]+/
30
- sheet_reference := (single_quoted_string | /[\p{word}][\p{word}_.]+/) `'!' (sheetless_reference | named_reference)
30
+ sheet_reference := (single_quoted_string | /[\p{word}][\p{word}_.]+/) `'!' (sheetless_reference | error | named_reference)
31
31
  single_quoted_string = `"'" /[^']*/ `"'"
32
32
  sheetless_reference = column_range | row_range | area | cell
33
33
  column_range := column `':' column
data/src/excel_to_code.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  class ExcelToCode
2
- def self.version() "0.2.17" end
2
+ def self.version() "0.2.18" end
3
3
  end
4
4
 
5
5
  require_relative 'commands'
@@ -64,7 +64,13 @@ class CachingFormulaParser
64
64
  def sheet_reference(ast)
65
65
  ast[1] = ast[1].to_sym
66
66
  ast[2] = map(ast[2])
67
- @sheet_reference_cache[ast] ||= ast
67
+ # We do this to deal with Control!#REF! style rerferences
68
+ # that occasionally pop up in named references
69
+ if ast[2].first == :error
70
+ return ast[2]
71
+ else
72
+ @sheet_reference_cache[ast] ||= ast
73
+ end
68
74
  end
69
75
 
70
76
  def cell(ast)
data/src/simplify.rb CHANGED
@@ -21,3 +21,4 @@ require_relative "simplify/wrap_formulae_that_return_arrays_and_are_not_in_array
21
21
  require_relative "simplify/replace_string_join_on_ranges"
22
22
  require_relative "simplify/emergency_array_formula_replace_indirect_bodge.rb"
23
23
  require_relative "simplify/replace_transpose_function"
24
+ require_relative "simplify/replace_references_to_blanks_with_zeros"
@@ -2,8 +2,6 @@ module BlankCell; end
2
2
 
3
3
  class InlineFormulaeAst
4
4
 
5
- BLANK = [:inlined_blank]
6
-
7
5
  attr_accessor :references, :current_sheet_name, :inline_ast
8
6
  attr_accessor :count_replaced
9
7
 
@@ -48,10 +46,9 @@ class InlineFormulaeAst
48
46
  ref = ast[2][1].to_s.upcase.gsub('$','').to_sym
49
47
  # FIXME: Need to check if valid worksheet and return [:error, "#REF!"] if not
50
48
  # Now check user preference on this
49
+ ast_to_inline = ast_to_inline(sheet, ref)
51
50
  return unless inline_ast.call(sheet,ref, references)
52
51
  @count_replaced += 1
53
- ast_to_inline = references[[sheet, ref]]
54
- return ast.replace(BLANK) unless ast_to_inline
55
52
  current_sheet_name.push(sheet)
56
53
  map(ast_to_inline)
57
54
  current_sheet_name.pop
@@ -62,10 +59,9 @@ class InlineFormulaeAst
62
59
  def cell(ast)
63
60
  sheet = current_sheet_name.last
64
61
  ref = ast[1].to_s.upcase.gsub('$', '').to_sym
62
+ ast_to_inline = ast_to_inline(sheet, ref)
65
63
  if inline_ast.call(sheet, ref, references)
66
64
  @count_replaced += 1
67
- ast_to_inline = references[[sheet, ref]]
68
- return ast.replace(BLANK) unless ast_to_inline
69
65
  map(ast_to_inline)
70
66
  ast.replace(ast_to_inline)
71
67
  # FIXME: Check - is this right? does it work recursively enough?
@@ -73,6 +69,14 @@ class InlineFormulaeAst
73
69
  ast.replace([:sheet_reference, sheet, ast.dup])
74
70
  end
75
71
  end
72
+
73
+ def ast_to_inline(sheet, ref)
74
+ ast_to_inline = references[[sheet, ref]]
75
+ return ast_to_inline if ast_to_inline
76
+ # Need to add a new blank cell and return ast for an inlined blank
77
+ references[[sheet, ref]] = [:blank]
78
+ [:inlined_blank]
79
+ end
76
80
 
77
81
  end
78
82
 
@@ -0,0 +1,43 @@
1
+ class ReplaceReferencesToBlanksWithZeros
2
+
3
+ attr_accessor :references, :current_sheet_name, :inline_ast
4
+ attr_accessor :count_replaced
5
+
6
+ def initialize(references = nil, current_sheet_name = nil, inline_ast = nil)
7
+ @references, @current_sheet_name, @inline_ast = references, [current_sheet_name], inline_ast
8
+ @count_replaced = 0
9
+ @inline_ast ||= lambda { |sheet, ref, references| true } # Default is to always inline
10
+ end
11
+
12
+ def map(ast)
13
+ return ast unless ast.is_a?(Array)
14
+
15
+ sheet = nil
16
+ ref = nil
17
+
18
+ case ast.first
19
+ when :sheet_reference
20
+ return ast unless ast[2][0] == :cell
21
+ sheet = ast[1].to_sym
22
+ ref = ast[2][1].to_s.upcase.gsub('$','').to_sym
23
+ when :cell
24
+ sheet = current_sheet_name.last
25
+ ref = ast[1].to_s.upcase.gsub('$', '').to_sym
26
+ else
27
+ # We aren't interested
28
+ return ast
29
+ end
30
+
31
+ ast_to_inline = references[[sheet, ref]] || [:blank]
32
+
33
+ return ast unless ast_to_inline == [:blank]
34
+
35
+ if inline_ast.call(sheet, ref, references)
36
+ ast.replace([:number, 0])
37
+ else
38
+ reference = [:sheet_reference, sheet, [:cell, ref]]
39
+ ast.replace([:function, :IF, [:function, :ISBLANK, reference], [:number, 0], reference])
40
+ end
41
+ ast
42
+ end
43
+ 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.2.17
4
+ version: 0.2.18
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: 2014-02-11 00:00:00.000000000 Z
11
+ date: 2014-03-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubypeg
@@ -199,6 +199,7 @@ files:
199
199
  - src/excel/excel_functions/sumproduct.rb
200
200
  - src/excel/excel_functions/text.rb
201
201
  - src/excel/excel_functions/trim.rb
202
+ - src/excel/excel_functions/value.rb
202
203
  - src/excel/excel_functions/vlookup.rb
203
204
  - src/excel/formula_peg.rb
204
205
  - src/excel/formula_peg.txt
@@ -244,6 +245,7 @@ files:
244
245
  - src/simplify/replace_named_references.rb
245
246
  - src/simplify/replace_offsets_with_references.rb
246
247
  - src/simplify/replace_ranges_with_array_literals.rb
248
+ - src/simplify/replace_references_to_blanks_with_zeros.rb
247
249
  - src/simplify/replace_shared_strings.rb
248
250
  - src/simplify/replace_string_join_on_ranges.rb
249
251
  - src/simplify/replace_table_references.rb