excel_to_code 0.2.15 → 0.2.16

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: f02167c81fefd0532b50c1fc9c9014a4398306f5
4
- data.tar.gz: ec0ce7e9de3c7ed214052a9a45bad36c02e1c763
3
+ metadata.gz: 1cae4231d0e0d0c80b485f2a0fc87d565f226c11
4
+ data.tar.gz: 625f3ef6ec924295ee2e3f5cba56868381f4f404
5
5
  SHA512:
6
- metadata.gz: 52fd6998dddf65a826c6bb3a014d5b915342845ab5a1801dfc3c4fc7572f446aedd2f8662c92aa186be8c0b5dd9719ffcc2f90f1b71842df6cb5c97e886cbc8f
7
- data.tar.gz: 7725a362a6049b3533e1db2c1be5c256581fb915519d274b89d3c9790f83e654d9470deb6c9148549fe905cf51e3ff6ee35794f6d4026feb357d23e2c07a1d74
6
+ metadata.gz: 6cd4db1bfcf22fbea826c79c02f61d8e414ae7b58aec81e4f6a19d64c0ffa5fa4afd1d60a33b1326c6e86a49ce8f43bca36679abf8545039f0d99fcab05afe81
7
+ data.tar.gz: 2b9f571923590f5a66dda004568a968cfd6add015b85e9bed0bb18a752295e96299f5aa020e75a6e5c85ba56684b788436e7667c11ddc38f3f62cd02dff1140a
data/bin/excel_to_c CHANGED
@@ -47,6 +47,10 @@ END
47
47
  opts.on('--precise-tests',"The generated tests treat blanks and zeros as different and requires numbers to be exactly the same.") do
48
48
  command.sloppy_tests = false
49
49
  end
50
+
51
+ opts.on('--isolate WORKSHEET', "Only performs translation and optimiation of that one worksheet. Useful for debugging an incorrect translation of a large worksheet") do |sheet|
52
+ command.isolate = sheet
53
+ end
50
54
 
51
55
  opts.on("-h", "--help", "Show this message") do
52
56
  puts opts
@@ -110,7 +110,7 @@ class ExcelToC < ExcelToX
110
110
 
111
111
  # Target for compiled version
112
112
  o.puts "#{name}.o:"
113
- o.puts "\tgcc -Wall -fPIC -c #{name}.c"
113
+ o.puts "\tgcc -fPIC -c #{name}.c"
114
114
  o.puts
115
115
 
116
116
  # Target for cleaning
@@ -256,7 +256,7 @@ END
256
256
  # Put in place the setters, if any
257
257
  settable_refs = @cells_that_can_be_set_at_runtime[name]
258
258
  if settable_refs
259
- settable_refs = all_formulae[name].keys if settable_refs == :all
259
+ settable_refs = @formulae.keys.select { |k| k.first == name }.map { |k| k.last } if settable_refs == :all
260
260
  settable_refs.each do |ref|
261
261
  o.puts " attach_function 'set_#{c_name}_#{ref.downcase}', [ExcelValue.by_value], :void"
262
262
  end
@@ -103,6 +103,13 @@ class ExcelToX
103
103
  # * false - the compiler leaves calculations fully expanded. This may make debugging easier
104
104
  attr_accessor :extract_repeated_parts_of_formulae
105
105
 
106
+ # Optional attribute, Array. Default nil
107
+ # This is used to help debug large spreadsheets that aren't working correctly.
108
+ # If set to the name of a worksheet then ONLY that worksheet will be run through the
109
+ # optimisation and simplification code. Will also override cells_to_keep to keep all
110
+ # cells on tha sheet and nothing else.
111
+ attr_accessor :isolate
112
+
106
113
  # Deprecated
107
114
  def run_in_memory=(boolean)
108
115
  $stderr.puts "The run_in_memory switch is deprecated (it is now always true). Please remove calls to it"
@@ -146,7 +153,7 @@ class ExcelToX
146
153
  transfer_named_references_to_keep_into_cells_to_keep
147
154
  transfer_named_references_that_can_be_set_at_runtime_into_cells_that_can_be_set_at_runtime
148
155
 
149
- # These perform some translations to simplify the excel
156
+ # These perform some translations to tsimplify the excel
150
157
  # Including:
151
158
  # * Turning row and column references (e.g., A:A) to areas, based on the size of the worksheet
152
159
  # * Turning range references (e.g., A1:B2) into array litterals (e.g., {A1,B1;A2,B2})
@@ -221,6 +228,11 @@ class ExcelToX
221
228
 
222
229
  # Setting this to false may make it easier to figure out errors
223
230
  self.extract_repeated_parts_of_formulae = true if @extract_repeated_parts_of_formulae == nil
231
+ if self.isolate
232
+ self.cells_to_keep = { isolate.to_s => :all }
233
+ self.isolate = self.isolate.to_sym
234
+ log.warn "Isolating #{@isolate} worksheet. No other sheets will be converted"
235
+ end
224
236
  end
225
237
 
226
238
 
@@ -440,6 +452,13 @@ class ExcelToX
440
452
  # Loop through the worksheets
441
453
  # FIXME: make xml_filename be the IO object?
442
454
  worksheets do |name, xml_filename|
455
+
456
+ # This is used in debugging large worksheets to limit
457
+ # the optimisation to a particular worksheet
458
+ if isolate
459
+ extractor.only_extract_values = (isolate != name)
460
+ end
461
+
443
462
  log.info "Extracting data from #{name}"
444
463
  xml(xml_filename) do |input|
445
464
  extractor.extract(name, input)
@@ -643,6 +662,8 @@ class ExcelToX
643
662
  @replace_ranges_with_array_literals_replacer.map(details.last)
644
663
  transpose_function_replacer.map(details.last)
645
664
  simplify_arithmetic_replacer.map(details.last)
665
+ # FIXME: Seem to need to do this twice, second time to eliminate brackets?!
666
+ simplify_arithmetic_replacer.map(details.last)
646
667
  expand_array_formulae_replacer.map(details.last)
647
668
  end
648
669
 
@@ -829,15 +850,13 @@ class ExcelToX
829
850
  @table_reference_replacer.referring_cell = ref.last
830
851
  @table_reference_replacer.map(ast)
831
852
  @replace_ranges_with_array_literals_replacer.map(ast)
832
- #@replace_arithmetic_on_ranges_replacer.map(ast)
833
-
834
853
  @replace_arrays_with_single_cells_replacer.ref = ref
835
854
  a = @replace_arrays_with_single_cells_replacer.map(ast)
836
855
  if @replace_arrays_with_single_cells_replacer.need_to_replace
837
- cells[ref] = a
856
+ cells[ref] = @formulae[ref] = a
838
857
  end
839
-
840
- #@replace_string_joins_on_ranges_replacer.map(ast)
858
+ @replace_arithmetic_on_ranges_replacer.map(ast)
859
+ @replace_string_joins_on_ranges_replacer.map(ast)
841
860
  @wrap_formulae_that_return_arrays_replacer.map(ast)
842
861
  rescue Exception => e
843
862
  log.fatal "Exception when simplifying #{ref}: #{ast}"
data/src/compile/c/a.out CHANGED
Binary file
@@ -66,6 +66,12 @@ class CompileToC
66
66
  mapper.reset
67
67
  rescue Exception => e
68
68
  puts "Exception at #{ref} #{ast}"
69
+ if ref.first == "" # Then it is a common method, helpful to indicate where it comes from
70
+ s = /#{ref.last}/io
71
+ formulae.each do |r, a|
72
+ puts "Referenced in #{r}" if a.to_s =~ s
73
+ end
74
+ end
69
75
  raise
70
76
  end
71
77
  end
@@ -57,6 +57,7 @@ static ExcelValue less_than(ExcelValue a_v, ExcelValue b_v);
57
57
  static ExcelValue less_than_or_equal(ExcelValue a_v, ExcelValue b_v);
58
58
  static ExcelValue average(int array_size, ExcelValue *array);
59
59
  static ExcelValue averageifs(ExcelValue average_range_v, int number_of_arguments, ExcelValue *arguments);
60
+ static ExcelValue ensure_is_number(ExcelValue maybe_number_v);
60
61
  static ExcelValue find_2(ExcelValue string_to_look_for_v, ExcelValue string_to_look_in_v);
61
62
  static ExcelValue find(ExcelValue string_to_look_for_v, ExcelValue string_to_look_in_v, ExcelValue position_to_start_at_v);
62
63
  static ExcelValue hlookup_3(ExcelValue lookup_value_v,ExcelValue lookup_table_v, ExcelValue row_number_v);
@@ -70,6 +71,7 @@ static ExcelValue forecast(ExcelValue required_x, ExcelValue known_y, ExcelValue
70
71
  static ExcelValue large(ExcelValue array_v, ExcelValue k_v);
71
72
  static ExcelValue left(ExcelValue string_v, ExcelValue number_of_characters_v);
72
73
  static ExcelValue left_1(ExcelValue string_v);
74
+ static ExcelValue len(ExcelValue string_v);
73
75
  static ExcelValue excel_log(ExcelValue number);
74
76
  static ExcelValue excel_log_2(ExcelValue number, ExcelValue base);
75
77
  static ExcelValue excel_exp(ExcelValue number);
@@ -86,6 +88,8 @@ static ExcelValue pv_5(ExcelValue a_v, ExcelValue b_v, ExcelValue c_v, ExcelValu
86
88
  static ExcelValue excel_round(ExcelValue number_v, ExcelValue decimal_places_v);
87
89
  static ExcelValue rank(ExcelValue number_v, ExcelValue range_v, ExcelValue order_v);
88
90
  static ExcelValue rank_2(ExcelValue number_v, ExcelValue range_v);
91
+ static ExcelValue right(ExcelValue string_v, ExcelValue number_of_characters_v);
92
+ static ExcelValue right_1(ExcelValue string_v);
89
93
  static ExcelValue rounddown(ExcelValue number_v, ExcelValue decimal_places_v);
90
94
  static ExcelValue roundup(ExcelValue number_v, ExcelValue decimal_places_v);
91
95
  static ExcelValue excel_int(ExcelValue number_v);
@@ -147,7 +151,7 @@ void reset() {
147
151
  static void * new_excel_value_array(int size) {
148
152
  ExcelValue *pointer = malloc(sizeof(ExcelValue)*size); // Freed later
149
153
  if(pointer == 0) {
150
- printf("Out of memory\n");
154
+ printf("Out of memory in new_excel_value_array\n");
151
155
  exit(-1);
152
156
  }
153
157
  free_later(pointer);
@@ -299,6 +303,15 @@ static ExcelValue add(ExcelValue a_v, ExcelValue b_v) {
299
303
  return new_excel_number(a + b);
300
304
  }
301
305
 
306
+ static ExcelValue ensure_is_number(ExcelValue maybe_number_v) {
307
+ if(maybe_number_v.type == ExcelNumber) {
308
+ return maybe_number_v;
309
+ }
310
+ NUMBER(maybe_number_v, maybe_number)
311
+ CHECK_FOR_CONVERSION_ERROR
312
+ return new_excel_number(maybe_number);
313
+ }
314
+
302
315
  static ExcelValue excel_log(ExcelValue number) {
303
316
  return excel_log_2(number, TEN);
304
317
  }
@@ -888,6 +901,10 @@ static ExcelValue left(ExcelValue string_v, ExcelValue number_of_characters_v) {
888
901
  int number_of_characters = (int) number_from(number_of_characters_v);
889
902
  CHECK_FOR_CONVERSION_ERROR
890
903
 
904
+ if(number_of_characters < 0) {
905
+ return VALUE;
906
+ }
907
+
891
908
  char *string;
892
909
  int string_must_be_freed = 0;
893
910
  switch (string_v.type) {
@@ -897,11 +914,11 @@ static ExcelValue left(ExcelValue string_v, ExcelValue number_of_characters_v) {
897
914
  case ExcelNumber:
898
915
  string = malloc(20); // Freed
899
916
  if(string == 0) {
900
- printf("Out of memory");
917
+ printf("Out of memory in left");
901
918
  exit(-1);
902
919
  }
903
920
  string_must_be_freed = 1;
904
- snprintf(string,20,"%f",string_v.number);
921
+ snprintf(string,20,"%0.0f",string_v.number);
905
922
  break;
906
923
  case ExcelBoolean:
907
924
  if(string_v.number == true) {
@@ -918,7 +935,7 @@ static ExcelValue left(ExcelValue string_v, ExcelValue number_of_characters_v) {
918
935
 
919
936
  char *left_string = malloc(number_of_characters+1); // Freed
920
937
  if(left_string == 0) {
921
- printf("Out of memory");
938
+ printf("Out of memoryn in left");
922
939
  exit(-1);
923
940
  }
924
941
  memcpy(left_string,string,number_of_characters);
@@ -934,6 +951,112 @@ static ExcelValue left_1(ExcelValue string_v) {
934
951
  return left(string_v, ONE);
935
952
  }
936
953
 
954
+ static ExcelValue len(ExcelValue string_v) {
955
+ CHECK_FOR_PASSED_ERROR(string_v)
956
+ if(string_v.type == ExcelEmpty) return ZERO;
957
+
958
+ char *string;
959
+ int string_must_be_freed = 0;
960
+ switch (string_v.type) {
961
+ case ExcelString:
962
+ string = string_v.string;
963
+ break;
964
+ case ExcelNumber:
965
+ string = malloc(20); // Freed
966
+ if(string == 0) {
967
+ printf("Out of memory in len");
968
+ exit(-1);
969
+ }
970
+ snprintf(string,20,"%0.0f",string_v.number);
971
+ string_must_be_freed = 1;
972
+ break;
973
+ case ExcelBoolean:
974
+ if(string_v.number == true) {
975
+ string = "TRUE";
976
+ } else {
977
+ string = "FALSE";
978
+ }
979
+ break;
980
+ case ExcelEmpty:
981
+ case ExcelError:
982
+ case ExcelRange:
983
+ return string_v;
984
+ }
985
+
986
+ int length = strlen(string);
987
+ if(string_must_be_freed == 1) {
988
+ free(string);
989
+ }
990
+ return new_excel_number(length);
991
+ }
992
+
993
+ static ExcelValue right(ExcelValue string_v, ExcelValue number_of_characters_v) {
994
+ CHECK_FOR_PASSED_ERROR(string_v)
995
+ CHECK_FOR_PASSED_ERROR(number_of_characters_v)
996
+ if(string_v.type == ExcelEmpty) return BLANK;
997
+ if(number_of_characters_v.type == ExcelEmpty) return BLANK;
998
+
999
+ int number_of_characters = (int) number_from(number_of_characters_v);
1000
+ CHECK_FOR_CONVERSION_ERROR
1001
+
1002
+ if(number_of_characters < 0) {
1003
+ return VALUE;
1004
+ }
1005
+
1006
+ char *string;
1007
+ int string_must_be_freed = 0;
1008
+ switch (string_v.type) {
1009
+ case ExcelString:
1010
+ string = string_v.string;
1011
+ break;
1012
+ case ExcelNumber:
1013
+ string = malloc(20); // Freed
1014
+ if(string == 0) {
1015
+ printf("Out of memory in right");
1016
+ exit(-1);
1017
+ }
1018
+ string_must_be_freed = 1;
1019
+ snprintf(string,20,"%0.0f",string_v.number);
1020
+ break;
1021
+ case ExcelBoolean:
1022
+ if(string_v.number == true) {
1023
+ string = "TRUE";
1024
+ } else {
1025
+ string = "FALSE";
1026
+ }
1027
+ break;
1028
+ case ExcelEmpty:
1029
+ case ExcelError:
1030
+ case ExcelRange:
1031
+ return string_v;
1032
+ }
1033
+
1034
+ char *right_string = malloc(number_of_characters+1); // Freed
1035
+ if(right_string == 0) {
1036
+ printf("Out of memory in right");
1037
+ exit(-1);
1038
+ }
1039
+ int length = strlen(string);
1040
+ if(length < number_of_characters) {
1041
+ if(string_must_be_freed == 1) {
1042
+ free(string);
1043
+ }
1044
+ return new_excel_string("");
1045
+ } else {
1046
+ memcpy(right_string,string+length-number_of_characters,number_of_characters);
1047
+ right_string[number_of_characters] = '\0';
1048
+ if(string_must_be_freed == 1) {
1049
+ free(string);
1050
+ }
1051
+ free_later(right_string);
1052
+ return new_excel_string(right_string);
1053
+ }
1054
+ }
1055
+
1056
+ static ExcelValue right_1(ExcelValue string_v) {
1057
+ return right(string_v, ONE);
1058
+ }
1059
+
937
1060
  static ExcelValue iferror(ExcelValue value, ExcelValue value_if_error) {
938
1061
  if(value.type == ExcelError) return value_if_error;
939
1062
  return value;
@@ -1406,7 +1529,7 @@ static ExcelValue string_join(int number_of_arguments, ExcelValue *arguments) {
1406
1529
  int used_length = 0;
1407
1530
  char *string = malloc(allocated_length); // Freed later
1408
1531
  if(string == 0) {
1409
- printf("Out of memory");
1532
+ printf("Out of memory in string_join");
1410
1533
  exit(-1);
1411
1534
  }
1412
1535
  char *current_string;
@@ -1424,7 +1547,7 @@ static ExcelValue string_join(int number_of_arguments, ExcelValue *arguments) {
1424
1547
  case ExcelNumber:
1425
1548
  current_string = malloc(20); // Freed
1426
1549
  if(current_string == 0) {
1427
- printf("Out of memory");
1550
+ printf("Out of memory in string join");
1428
1551
  exit(-1);
1429
1552
  }
1430
1553
  must_free_current_string = 1;
@@ -1538,7 +1661,7 @@ static ExcelValue filter_range(ExcelValue original_range_v, int number_of_argume
1538
1661
  // Now go through and set up the criteria
1539
1662
  ExcelComparison *criteria = malloc(sizeof(ExcelComparison)*number_of_criteria); // freed at end of function
1540
1663
  if(criteria == 0) {
1541
- printf("Out of memory\n");
1664
+ printf("Out of memory in filter_range\n");
1542
1665
  exit(-1);
1543
1666
  }
1544
1667
  char *s;
@@ -1748,7 +1871,7 @@ static ExcelValue sumproduct(int number_of_arguments, ExcelValue *arguments) {
1748
1871
  ExcelValue current_value;
1749
1872
  ExcelValue **ranges = malloc(sizeof(ExcelValue *)*number_of_arguments); // Added free statements
1750
1873
  if(ranges == 0) {
1751
- printf("Out of memory\n");
1874
+ printf("Out of memory in sumproduct\n");
1752
1875
  exit(-1);
1753
1876
  }
1754
1877
  double product = 1;
@@ -1,49 +1,49 @@
1
1
  #include "excel_to_c_runtime.c"
2
2
 
3
3
  int test_functions() {
4
- // Test ABS
5
- assert(excel_abs(ONE).number == 1);
6
- assert(excel_abs(new_excel_number(-1)).number == 1);
7
- assert(excel_abs(VALUE).type == ExcelError);
8
-
9
- // Test ADD
10
- assert(add(ONE,new_excel_number(-2.5)).number == -1.5);
11
- assert(add(ONE,VALUE).type == ExcelError);
12
-
13
- // Test AND
14
- ExcelValue true_array1[] = { TRUE, new_excel_number(10)};
15
- ExcelValue true_array2[] = { ONE };
16
- ExcelValue false_array1[] = { FALSE, new_excel_number(10)};
17
- ExcelValue false_array2[] = { TRUE, new_excel_number(0)};
18
- // ExcelValue error_array1[] = { new_excel_number(10)}; // Not implemented
19
- ExcelValue error_array2[] = { TRUE, NA};
20
- assert(excel_and(2,true_array1).number == 1);
21
- assert(excel_and(1,true_array2).number == 1);
22
- assert(excel_and(2,false_array1).number == 0);
23
- assert(excel_and(2,false_array2).number == 0);
24
- // assert(excel_and(1,error_array1).type == ExcelError); // Not implemented
25
- assert(excel_and(2,error_array2).type == ExcelError);
26
-
27
- // Test AVERAGE
28
- ExcelValue array1[] = { new_excel_number(10), new_excel_number(5), TRUE, FALSE};
29
- ExcelValue array1_v = new_excel_range(array1,2,2);
30
- ExcelValue array2[] = { array1_v, new_excel_number(9), new_excel_string("Hello")};
31
- ExcelValue array3[] = { array1_v, new_excel_number(9), new_excel_string("Hello"), VALUE};
32
- assert(average(4, array1).number == 7.5);
33
- assert(average(3, array2).number == 8);
34
- assert(average(4, array3).type == ExcelError);
35
-
36
- // Test CHOOSE
37
- assert(choose(ONE,4,array1).number == 10);
38
- assert(choose(new_excel_number(4),4,array1).type == ExcelBoolean);
39
- assert(choose(new_excel_number(0),4,array1).type == ExcelError);
40
- assert(choose(new_excel_number(5),4,array1).type == ExcelError);
41
- assert(choose(ONE,4,array3).type == ExcelError);
42
-
43
- // Test COUNT
44
- assert(count(4,array1).number == 2);
45
- assert(count(3,array2).number == 3);
46
- assert(count(4,array3).number == 3);
4
+ // Test ABS
5
+ assert(excel_abs(ONE).number == 1);
6
+ assert(excel_abs(new_excel_number(-1)).number == 1);
7
+ assert(excel_abs(VALUE).type == ExcelError);
8
+
9
+ // Test ADD
10
+ assert(add(ONE,new_excel_number(-2.5)).number == -1.5);
11
+ assert(add(ONE,VALUE).type == ExcelError);
12
+
13
+ // Test AND
14
+ ExcelValue true_array1[] = { TRUE, new_excel_number(10)};
15
+ ExcelValue true_array2[] = { ONE };
16
+ ExcelValue false_array1[] = { FALSE, new_excel_number(10)};
17
+ ExcelValue false_array2[] = { TRUE, new_excel_number(0)};
18
+ // ExcelValue error_array1[] = { new_excel_number(10)}; // Not implemented
19
+ ExcelValue error_array2[] = { TRUE, NA};
20
+ assert(excel_and(2,true_array1).number == 1);
21
+ assert(excel_and(1,true_array2).number == 1);
22
+ assert(excel_and(2,false_array1).number == 0);
23
+ assert(excel_and(2,false_array2).number == 0);
24
+ // assert(excel_and(1,error_array1).type == ExcelError); // Not implemented
25
+ assert(excel_and(2,error_array2).type == ExcelError);
26
+
27
+ // Test AVERAGE
28
+ ExcelValue array1[] = { new_excel_number(10), new_excel_number(5), TRUE, FALSE};
29
+ ExcelValue array1_v = new_excel_range(array1,2,2);
30
+ ExcelValue array2[] = { array1_v, new_excel_number(9), new_excel_string("Hello")};
31
+ ExcelValue array3[] = { array1_v, new_excel_number(9), new_excel_string("Hello"), VALUE};
32
+ assert(average(4, array1).number == 7.5);
33
+ assert(average(3, array2).number == 8);
34
+ assert(average(4, array3).type == ExcelError);
35
+
36
+ // Test CHOOSE
37
+ assert(choose(ONE,4,array1).number == 10);
38
+ assert(choose(new_excel_number(4),4,array1).type == ExcelBoolean);
39
+ assert(choose(new_excel_number(0),4,array1).type == ExcelError);
40
+ assert(choose(new_excel_number(5),4,array1).type == ExcelError);
41
+ assert(choose(ONE,4,array3).type == ExcelError);
42
+
43
+ // Test COUNT
44
+ assert(count(4,array1).number == 2);
45
+ assert(count(3,array2).number == 3);
46
+ assert(count(4,array3).number == 3);
47
47
 
48
48
  // Test Large
49
49
  ExcelValue large_test_array_1[] = { new_excel_number(10), new_excel_number(100), new_excel_number(500), BLANK };
@@ -58,380 +58,381 @@ int test_functions() {
58
58
  assert(large(large_test_array_2_v,new_excel_number(2)).type == ExcelError);
59
59
  assert(large(new_excel_number(500),VALUE).type == ExcelError);
60
60
 
61
-
62
- // Test COUNTA
63
- ExcelValue count_a_test_array_1[] = { new_excel_number(10), new_excel_number(5), TRUE, FALSE, new_excel_string("Hello"), VALUE, BLANK};
61
+
62
+ // Test COUNTA
63
+ ExcelValue count_a_test_array_1[] = { new_excel_number(10), new_excel_number(5), TRUE, FALSE, new_excel_string("Hello"), VALUE, BLANK};
64
64
  ExcelValue count_a_test_array_1_v = new_excel_range(count_a_test_array_1,7,1);
65
65
  ExcelValue count_a_test_array_2[] = {new_excel_string("Bye"),count_a_test_array_1_v};
66
- assert(counta(7, count_a_test_array_1).number == 6);
66
+ assert(counta(7, count_a_test_array_1).number == 6);
67
67
  assert(counta(2, count_a_test_array_2).number == 7);
68
-
69
- // Test divide
70
- assert(divide(new_excel_number(12.4),new_excel_number(3.2)).number == 3.875);
71
- assert(divide(new_excel_number(12.4),new_excel_number(0)).type == ExcelError);
72
-
73
- // Test excel_equal
74
- assert(excel_equal(new_excel_number(1.2),new_excel_number(3.4)).type == ExcelBoolean);
75
- assert(excel_equal(new_excel_number(1.2),new_excel_number(3.4)).number == false);
76
- assert(excel_equal(new_excel_number(1.2),new_excel_number(1.2)).number == true);
77
- assert(excel_equal(new_excel_string("hello"), new_excel_string("HELLO")).number == true);
78
- assert(excel_equal(new_excel_string("hello world"), new_excel_string("HELLO")).number == false);
79
- assert(excel_equal(new_excel_string("1"), ONE).number == false);
80
- assert(excel_equal(DIV0, ONE).type == ExcelError);
81
-
82
- // Test not_equal
83
- assert(not_equal(new_excel_number(1.2),new_excel_number(3.4)).type == ExcelBoolean);
84
- assert(not_equal(new_excel_number(1.2),new_excel_number(3.4)).number == true);
85
- assert(not_equal(new_excel_number(1.2),new_excel_number(1.2)).number == false);
86
- assert(not_equal(new_excel_string("hello"), new_excel_string("HELLO")).number == false);
87
- assert(not_equal(new_excel_string("hello world"), new_excel_string("HELLO")).number == true);
88
- assert(not_equal(new_excel_string("1"), ONE).number == true);
89
- assert(not_equal(DIV0, ONE).type == ExcelError);
90
-
91
- // Test excel_if
92
- // Two argument version
93
- assert(excel_if_2(TRUE,new_excel_number(10)).type == ExcelNumber);
94
- assert(excel_if_2(TRUE,new_excel_number(10)).number == 10);
95
- assert(excel_if_2(FALSE,new_excel_number(10)).type == ExcelBoolean);
96
- assert(excel_if_2(FALSE,new_excel_number(10)).number == false);
97
- assert(excel_if_2(NA,new_excel_number(10)).type == ExcelError);
98
- // Three argument version
99
- assert(excel_if(TRUE,new_excel_number(10),new_excel_number(20)).type == ExcelNumber);
100
- assert(excel_if(TRUE,new_excel_number(10),new_excel_number(20)).number == 10);
101
- assert(excel_if(FALSE,new_excel_number(10),new_excel_number(20)).type == ExcelNumber);
102
- assert(excel_if(FALSE,new_excel_number(10),new_excel_number(20)).number == 20);
103
- assert(excel_if(NA,new_excel_number(10),new_excel_number(20)).type == ExcelError);
104
- assert(excel_if(TRUE,new_excel_number(10),NA).type == ExcelNumber);
105
- assert(excel_if(TRUE,new_excel_number(10),NA).number == 10);
106
-
107
- // Test excel_match
108
- ExcelValue excel_match_array_1[] = { new_excel_number(10), new_excel_number(100) };
109
- ExcelValue excel_match_array_1_v = new_excel_range(excel_match_array_1,1,2);
110
- ExcelValue excel_match_array_2[] = { new_excel_string("Pear"), new_excel_string("Bear"), new_excel_string("Apple") };
111
- ExcelValue excel_match_array_2_v = new_excel_range(excel_match_array_2,3,1);
112
- ExcelValue excel_match_array_4[] = { ONE, BLANK, new_excel_number(0) };
113
- ExcelValue excel_match_array_4_v = new_excel_range(excel_match_array_4,1,3);
114
- ExcelValue excel_match_array_5[] = { ONE, new_excel_number(0), BLANK };
115
- ExcelValue excel_match_array_5_v = new_excel_range(excel_match_array_5,1,3);
116
-
117
- // Two argument version
118
- assert(excel_match_2(new_excel_number(10),excel_match_array_1_v).number == 1);
119
- assert(excel_match_2(new_excel_number(100),excel_match_array_1_v).number == 2);
120
- assert(excel_match_2(new_excel_number(1000),excel_match_array_1_v).type == ExcelError);
121
- assert(excel_match_2(new_excel_number(0), excel_match_array_4_v).number == 2);
122
- assert(excel_match_2(BLANK, excel_match_array_5_v).number == 2);
123
-
124
- // Three argument version
125
- assert(excel_match(new_excel_number(10.0), excel_match_array_1_v, new_excel_number(0) ).number == 1);
126
- assert(excel_match(new_excel_number(100.0), excel_match_array_1_v, new_excel_number(0) ).number == 2);
127
- assert(excel_match(new_excel_number(1000.0), excel_match_array_1_v, new_excel_number(0) ).type == ExcelError);
128
- assert(excel_match(new_excel_string("bEAr"), excel_match_array_2_v, new_excel_number(0) ).number == 2);
129
- assert(excel_match(new_excel_number(1000.0), excel_match_array_1_v, ONE ).number == 2);
130
- assert(excel_match(new_excel_number(1.0), excel_match_array_1_v, ONE ).type == ExcelError);
131
- assert(excel_match(new_excel_string("Care"), excel_match_array_2_v, new_excel_number(-1) ).number == 1 );
132
- assert(excel_match(new_excel_string("Zebra"), excel_match_array_2_v, new_excel_number(-1) ).type == ExcelError);
133
- assert(excel_match(new_excel_string("a"), excel_match_array_2_v, new_excel_number(-1) ).number == 2);
134
-
135
- // When not given a range
136
- assert(excel_match(new_excel_number(10.0), new_excel_number(10), new_excel_number(0.0)).number == 1);
137
- assert(excel_match(new_excel_number(20.0), new_excel_number(10), new_excel_number(0.0)).type == ExcelError);
138
- assert(excel_match(new_excel_number(10.0), excel_match_array_1_v, BLANK).number == 1);
139
-
140
- // Test more than on
141
- // .. numbers
142
- assert(more_than(ONE,new_excel_number(2)).number == false);
143
- assert(more_than(ONE,ONE).number == false);
144
- assert(more_than(ONE,new_excel_number(0)).number == true);
145
- // .. booleans
146
- assert(more_than(FALSE,FALSE).number == false);
147
- assert(more_than(FALSE,TRUE).number == false);
148
- assert(more_than(TRUE,FALSE).number == true);
149
- assert(more_than(TRUE,TRUE).number == false);
150
- // ..strings
151
- assert(more_than(new_excel_string("HELLO"),new_excel_string("Ardvark")).number == true);
152
- assert(more_than(new_excel_string("HELLO"),new_excel_string("world")).number == false);
153
- assert(more_than(new_excel_string("HELLO"),new_excel_string("hello")).number == false);
154
- // ..blanks
155
- assert(more_than(BLANK,ONE).number == false);
156
- assert(more_than(BLANK,new_excel_number(-1)).number == true);
157
- assert(more_than(ONE,BLANK).number == true);
158
- assert(more_than(new_excel_number(-1),BLANK).number == false);
159
-
160
- // Test less than on
161
- // .. numbers
162
- assert(less_than(ONE,new_excel_number(2)).number == true);
163
- assert(less_than(ONE,ONE).number == false);
164
- assert(less_than(ONE,new_excel_number(0)).number == false);
165
- // .. booleans
166
- assert(less_than(FALSE,FALSE).number == false);
167
- assert(less_than(FALSE,TRUE).number == true);
168
- assert(less_than(TRUE,FALSE).number == false);
169
- assert(less_than(TRUE,TRUE).number == false);
170
- // ..strings
171
- assert(less_than(new_excel_string("HELLO"),new_excel_string("Ardvark")).number == false);
172
- assert(less_than(new_excel_string("HELLO"),new_excel_string("world")).number == true);
173
- assert(less_than(new_excel_string("HELLO"),new_excel_string("hello")).number == false);
174
- // ..blanks
175
- assert(less_than(BLANK,ONE).number == true);
176
- assert(less_than(BLANK,new_excel_number(-1)).number == false);
177
- assert(less_than(ONE,BLANK).number == false);
178
- assert(less_than(new_excel_number(-1),BLANK).number == true);
179
-
180
- // Test FIND function
181
- // ... should find the first occurrence of one string in another, returning :value if the string doesn't match
182
- assert(find_2(new_excel_string("one"),new_excel_string("onetwothree")).number == 1);
183
- assert(find_2(new_excel_string("one"),new_excel_string("twoonethree")).number == 4);
184
- assert(find_2(new_excel_string("one"),new_excel_string("twoonthree")).type == ExcelError);
185
- // ... should find the first occurrence of one string in another after a given index, returning :value if the string doesn't match
186
- assert(find(new_excel_string("one"),new_excel_string("onetwothree"),ONE).number == 1);
187
- assert(find(new_excel_string("one"),new_excel_string("twoonethree"),new_excel_number(5)).type == ExcelError);
188
- assert(find(new_excel_string("one"),new_excel_string("oneone"),new_excel_number(2)).number == 4);
189
- // ... should be possible for the start_num to be a string, if that string converts to a number
190
- assert(find(new_excel_string("one"),new_excel_string("oneone"),new_excel_string("2")).number == 4);
191
- // ... should return a :value error when given anything but a number as the third argument
192
- assert(find(new_excel_string("one"),new_excel_string("oneone"),new_excel_string("a")).type == ExcelError);
193
- // ... should return a :value error when given a third argument that is less than 1 or greater than the length of the string
194
- assert(find(new_excel_string("one"),new_excel_string("oneone"),new_excel_number(0)).type == ExcelError);
195
- assert(find(new_excel_string("one"),new_excel_string("oneone"),new_excel_number(-1)).type == ExcelError);
196
- assert(find(new_excel_string("one"),new_excel_string("oneone"),new_excel_number(7)).type == ExcelError);
197
- // ... BLANK in the first argument matches any character
198
- assert(find_2(BLANK,new_excel_string("abcdefg")).number == 1);
199
- assert(find(BLANK,new_excel_string("abcdefg"),new_excel_number(4)).number == 4);
200
- // ... should treat BLANK in the second argument as an empty string
201
- assert(find_2(BLANK,BLANK).number == 1);
202
- assert(find_2(new_excel_string("a"),BLANK).type == ExcelError);
203
- // ... should return an error if any argument is an error
204
- assert(find(new_excel_string("one"),new_excel_string("onetwothree"),NA).type == ExcelError);
205
- assert(find(new_excel_string("one"),NA,ONE).type == ExcelError);
206
- assert(find(NA,new_excel_string("onetwothree"),ONE).type == ExcelError);
207
-
208
- // Test the IFERROR function
209
- assert(iferror(new_excel_string("ok"),ONE).type == ExcelString);
210
- assert(iferror(VALUE,ONE).type == ExcelNumber);
211
-
212
- // Test the INDEX function
213
- ExcelValue index_array_1[] = { new_excel_number(10), new_excel_number(20), BLANK };
214
- ExcelValue index_array_1_v_column = new_excel_range(index_array_1,3,1);
215
- ExcelValue index_array_1_v_row = new_excel_range(index_array_1,1,3);
216
- ExcelValue index_array_2[] = { BLANK, ONE, new_excel_number(10), new_excel_number(11), new_excel_number(100), new_excel_number(101) };
217
- ExcelValue index_array_2_v = new_excel_range(index_array_2,3,2);
218
- // ... if given one argument should return the value at that offset in the range
219
- assert(excel_index_2(index_array_1_v_column,new_excel_number(2.0)).number == 20);
220
- assert(excel_index_2(index_array_1_v_row,new_excel_number(2.0)).number == 20);
221
- // ... but not if the range is not a single row or single column
222
- assert(excel_index_2(index_array_2_v,new_excel_number(2.0)).type == ExcelError);
223
- // ... it should return the value in the array at position row_number, column_number
224
- assert(excel_index(new_excel_number(10),ONE,ONE).number == 10);
225
- assert(excel_index(index_array_2_v,new_excel_number(1.0),new_excel_number(2.0)).number == 1);
226
- assert(excel_index(index_array_2_v,new_excel_number(2.0),new_excel_number(1.0)).number == 10);
227
- assert(excel_index(index_array_2_v,new_excel_number(3.0),new_excel_number(1.0)).number == 100);
228
- assert(excel_index(index_array_2_v,new_excel_number(3.0),new_excel_number(3.0)).type == ExcelError);
229
- // ... it should return ZERO not blank, if a blank cell is picked
230
- assert(excel_index(index_array_2_v,new_excel_number(1.0),new_excel_number(1.0)).type == ExcelNumber);
231
- assert(excel_index(index_array_2_v,new_excel_number(1.0),new_excel_number(1.0)).number == 0);
232
- assert(excel_index_2(index_array_1_v_row,new_excel_number(3.0)).type == ExcelNumber);
233
- assert(excel_index_2(index_array_1_v_row,new_excel_number(3.0)).number == 0);
234
- // ... it should return the whole row if given a zero column number
235
- ExcelValue index_result_1_v = excel_index(index_array_2_v,new_excel_number(1.0),new_excel_number(0.0));
236
- assert(index_result_1_v.type == ExcelRange);
237
- assert(index_result_1_v.rows == 1);
238
- assert(index_result_1_v.columns == 2);
239
- ExcelValue *index_result_1_a = index_result_1_v.array;
240
- assert(index_result_1_a[0].number == 0);
241
- assert(index_result_1_a[1].number == 1);
242
- // ... it should return the whole column if given a zero row number
243
- ExcelValue index_result_2_v = excel_index(index_array_2_v,new_excel_number(0),new_excel_number(1.0));
244
- assert(index_result_2_v.type == ExcelRange);
245
- assert(index_result_2_v.rows == 3);
246
- assert(index_result_2_v.columns == 1);
247
- ExcelValue *index_result_2_a = index_result_2_v.array;
248
- assert(index_result_2_a[0].number == 0);
249
- assert(index_result_2_a[1].number == 10);
250
- assert(index_result_2_a[2].number == 100);
251
- // ... it should return a :ref error when given arguments outside array range
252
- assert(excel_index_2(index_array_1_v_row,new_excel_number(-1)).type == ExcelError);
253
- assert(excel_index_2(index_array_1_v_row,new_excel_number(4)).type == ExcelError);
254
- // ... it should treat BLANK as zero if given as a required row or column number
255
- assert(excel_index(index_array_2_v,new_excel_number(1.0),BLANK).type == ExcelRange);
256
- assert(excel_index(index_array_2_v,BLANK,new_excel_number(2.0)).type == ExcelRange);
257
- // ... it should return an error if an argument is an error
258
- assert(excel_index(NA,NA,NA).type == ExcelError);
259
-
260
- // LEFT(string,[characters])
261
- // ... should return the left n characters from a string
262
- assert(strcmp(left_1(new_excel_string("ONE")).string,"O") == 0);
263
- assert(strcmp(left(new_excel_string("ONE"),ONE).string,"O") == 0);
264
- assert(strcmp(left(new_excel_string("ONE"),new_excel_number(3)).string,"ONE") == 0);
265
- // ... should turn numbers into strings before processing
266
- assert(strcmp(left(new_excel_number(1.31e12),new_excel_number(3)).string, "131") == 0);
267
- // ... should turn booleans into the words TRUE and FALSE before processing
268
- assert(strcmp(left(TRUE,new_excel_number(3)).string,"TRU") == 0);
269
- assert(strcmp(left(FALSE,new_excel_number(3)).string,"FAL") == 0);
270
- // ... should return BLANK if given BLANK for either argument
271
- assert(left(BLANK,new_excel_number(3)).type == ExcelEmpty);
272
- assert(left(new_excel_string("ONE"),BLANK).type == ExcelEmpty);
273
- // ... should return an error if an argument is an error
274
- assert(left_1(NA).type == ExcelError);
275
- assert(left(new_excel_string("ONE"),NA).type == ExcelError);
276
-
277
- // Test less than or equal to
278
- // .. numbers
279
- assert(less_than_or_equal(ONE,new_excel_number(2)).number == true);
280
- assert(less_than_or_equal(ONE,ONE).number == true);
281
- assert(less_than_or_equal(ONE,new_excel_number(0)).number == false);
282
- // .. booleans
283
- assert(less_than_or_equal(FALSE,FALSE).number == true);
284
- assert(less_than_or_equal(FALSE,TRUE).number == true);
285
- assert(less_than_or_equal(TRUE,FALSE).number == false);
286
- assert(less_than_or_equal(TRUE,TRUE).number == true);
287
- // ..strings
288
- assert(less_than_or_equal(new_excel_string("HELLO"),new_excel_string("Ardvark")).number == false);
289
- assert(less_than_or_equal(new_excel_string("HELLO"),new_excel_string("world")).number == true);
290
- assert(less_than_or_equal(new_excel_string("HELLO"),new_excel_string("hello")).number == true);
291
- // ..blanks
292
- assert(less_than_or_equal(BLANK,ONE).number == true);
293
- assert(less_than_or_equal(BLANK,new_excel_number(-1)).number == false);
294
- assert(less_than_or_equal(ONE,BLANK).number == false);
295
- assert(less_than_or_equal(new_excel_number(-1),BLANK).number == true);
296
-
297
- // Test MAX
298
- assert(max(4, array1).number == 10);
299
- assert(max(3, array2).number == 10);
300
- assert(max(4, array3).type == ExcelError);
301
-
302
- // Test MIN
303
- assert(min(4, array1).number == 5);
304
- assert(min(3, array2).number == 5);
305
- assert(min(4, array3).type == ExcelError);
306
-
307
- // Test MOD
308
- // ... should return the remainder of a number
309
- assert(mod(new_excel_number(10), new_excel_number(3)).number == 1.0);
310
- assert(mod(new_excel_number(10), new_excel_number(5)).number == 0.0);
311
- // ... should be possible for the the arguments to be strings, if they convert to a number
312
- assert(mod(new_excel_string("3.5"),new_excel_string("2")).number == 1.5);
313
- // ... should treat BLANK as zero
314
- assert(mod(BLANK,new_excel_number(10)).number == 0);
315
- assert(mod(new_excel_number(10),BLANK).type == ExcelError);
316
- assert(mod(BLANK,BLANK).type == ExcelError);
317
- // ... should treat true as 1 and FALSE as 0
318
- assert((mod(new_excel_number(1.1),TRUE).number - 0.1) < 0.001);
319
- assert(mod(new_excel_number(1.1),FALSE).type == ExcelError);
320
- assert(mod(FALSE,new_excel_number(10)).number == 0);
321
- // ... should return an error when given inappropriate arguments
322
- assert(mod(new_excel_string("Asdasddf"),new_excel_string("adsfads")).type == ExcelError);
323
- // ... should return an error if an argument is an error
324
- assert(mod(new_excel_number(1),VALUE).type == ExcelError);
325
- assert(mod(VALUE,new_excel_number(1)).type == ExcelError);
326
- assert(mod(VALUE,VALUE).type == ExcelError);
327
-
328
- // Test more than or equal to on
329
- // .. numbers
330
- assert(more_than_or_equal(ONE,new_excel_number(2)).number == false);
331
- assert(more_than_or_equal(ONE,ONE).number == true);
332
- assert(more_than_or_equal(ONE,new_excel_number(0)).number == true);
333
- // .. booleans
334
- assert(more_than_or_equal(FALSE,FALSE).number == true);
335
- assert(more_than_or_equal(FALSE,TRUE).number == false);
336
- assert(more_than_or_equal(TRUE,FALSE).number == true);
337
- assert(more_than_or_equal(TRUE,TRUE).number == true);
338
- // ..strings
339
- assert(more_than_or_equal(new_excel_string("HELLO"),new_excel_string("Ardvark")).number == true);
340
- assert(more_than_or_equal(new_excel_string("HELLO"),new_excel_string("world")).number == false);
341
- assert(more_than_or_equal(new_excel_string("HELLO"),new_excel_string("hello")).number == true);
342
- // ..blanks
343
- assert(more_than_or_equal(BLANK,BLANK).number == true);
344
- assert(more_than_or_equal(BLANK,ONE).number == false);
345
- assert(more_than_or_equal(BLANK,new_excel_number(-1)).number == true);
346
- assert(more_than_or_equal(ONE,BLANK).number == true);
347
- assert(more_than_or_equal(new_excel_number(-1),BLANK).number == false);
348
-
349
- // Test negative
350
- // ... should return the negative of its arguments
351
- assert(negative(new_excel_number(1)).number == -1);
352
- assert(negative(new_excel_number(-1)).number == 1);
353
- // ... should treat strings that only contain numbers as numbers
354
- assert(negative(new_excel_string("10")).number == -10);
355
- assert(negative(new_excel_string("-1.3")).number == 1.3);
356
- // ... should return an error when given inappropriate arguments
357
- assert(negative(new_excel_string("Asdasddf")).type == ExcelError);
358
- // ... should treat BLANK as zero
359
- assert(negative(BLANK).number == 0);
360
-
361
- // Test PMT(rate,number_of_periods,present_value) - optional arguments not yet implemented
362
- // ... should calculate the monthly payment required for a given principal, interest rate and loan period
363
- assert((pmt(new_excel_number(0.1),new_excel_number(10),new_excel_number(100)).number - -16.27) < 0.01);
364
- assert((pmt(new_excel_number(0.0123),new_excel_number(99.1),new_excel_number(123.32)).number - -2.159) < 0.01);
365
- assert((pmt(new_excel_number(0),new_excel_number(2),new_excel_number(10)).number - -5) < 0.01);
366
-
367
- // Test power
368
- // ... should return power of its arguments
369
- assert(power(new_excel_number(2),new_excel_number(3)).number == 8);
370
- assert(power(new_excel_number(4.0),new_excel_number(0.5)).number == 2.0);
371
- assert(power(new_excel_number(-4.0),new_excel_number(0.5)).type == ExcelError);
372
-
373
- // Test round
374
- assert(excel_round(new_excel_number(1.1), new_excel_number(0)).number == 1.0);
375
- assert(excel_round(new_excel_number(1.5), new_excel_number(0)).number == 2.0);
376
- assert(excel_round(new_excel_number(1.56),new_excel_number(1)).number == 1.6);
377
- assert(excel_round(new_excel_number(-1.56),new_excel_number(1)).number == -1.6);
378
-
379
- // Test rounddown
380
- assert(rounddown(new_excel_number(1.1), new_excel_number(0)).number == 1.0);
381
- assert(rounddown(new_excel_number(1.5), new_excel_number(0)).number == 1.0);
382
- assert(rounddown(new_excel_number(1.56),new_excel_number(1)).number == 1.5);
383
- assert(rounddown(new_excel_number(-1.56),new_excel_number(1)).number == -1.5);
384
-
385
- // Test int
386
- assert(excel_int(new_excel_number(8.9)).number == 8.0);
387
- assert(excel_int(new_excel_number(-8.9)).number == -9.0);
388
-
389
- // Test roundup
390
- assert(roundup(new_excel_number(1.1), new_excel_number(0)).number == 2.0);
391
- assert(roundup(new_excel_number(1.5), new_excel_number(0)).number == 2.0);
392
- assert(roundup(new_excel_number(1.56),new_excel_number(1)).number == 1.6);
393
- assert(roundup(new_excel_number(-1.56),new_excel_number(1)).number == -1.6);
394
-
395
- // Test string joining
396
- ExcelValue string_join_array_1[] = {new_excel_string("Hello "), new_excel_string("world")};
397
- ExcelValue string_join_array_2[] = {new_excel_string("Hello "), new_excel_string("world"), new_excel_string("!")};
398
- ExcelValue string_join_array_3[] = {new_excel_string("Top "), new_excel_number(10.0)};
399
- ExcelValue string_join_array_4[] = {new_excel_string("Top "), new_excel_number(10.5)};
400
- ExcelValue string_join_array_5[] = {new_excel_string("Top "), TRUE, FALSE};
401
- // ... should return a string by combining its arguments
402
- // inspect_excel_value(string_join(2, string_join_array_1));
68
+
69
+ // Test divide
70
+ assert(divide(new_excel_number(12.4),new_excel_number(3.2)).number == 3.875);
71
+ assert(divide(new_excel_number(12.4),new_excel_number(0)).type == ExcelError);
72
+
73
+ // Test excel_equal
74
+ assert(excel_equal(new_excel_number(1.2),new_excel_number(3.4)).type == ExcelBoolean);
75
+ assert(excel_equal(new_excel_number(1.2),new_excel_number(3.4)).number == false);
76
+ assert(excel_equal(new_excel_number(1.2),new_excel_number(1.2)).number == true);
77
+ assert(excel_equal(new_excel_string("hello"), new_excel_string("HELLO")).number == true);
78
+ assert(excel_equal(new_excel_string("hello world"), new_excel_string("HELLO")).number == false);
79
+ assert(excel_equal(new_excel_string("1"), ONE).number == false);
80
+ assert(excel_equal(DIV0, ONE).type == ExcelError);
81
+
82
+ // Test not_equal
83
+ assert(not_equal(new_excel_number(1.2),new_excel_number(3.4)).type == ExcelBoolean);
84
+ assert(not_equal(new_excel_number(1.2),new_excel_number(3.4)).number == true);
85
+ assert(not_equal(new_excel_number(1.2),new_excel_number(1.2)).number == false);
86
+ assert(not_equal(new_excel_string("hello"), new_excel_string("HELLO")).number == false);
87
+ assert(not_equal(new_excel_string("hello world"), new_excel_string("HELLO")).number == true);
88
+ assert(not_equal(new_excel_string("1"), ONE).number == true);
89
+ assert(not_equal(DIV0, ONE).type == ExcelError);
90
+
91
+ // Test excel_if
92
+ // Two argument version
93
+ assert(excel_if_2(TRUE,new_excel_number(10)).type == ExcelNumber);
94
+ assert(excel_if_2(TRUE,new_excel_number(10)).number == 10);
95
+ assert(excel_if_2(FALSE,new_excel_number(10)).type == ExcelBoolean);
96
+ assert(excel_if_2(FALSE,new_excel_number(10)).number == false);
97
+ assert(excel_if_2(NA,new_excel_number(10)).type == ExcelError);
98
+ // Three argument version
99
+ assert(excel_if(TRUE,new_excel_number(10),new_excel_number(20)).type == ExcelNumber);
100
+ assert(excel_if(TRUE,new_excel_number(10),new_excel_number(20)).number == 10);
101
+ assert(excel_if(FALSE,new_excel_number(10),new_excel_number(20)).type == ExcelNumber);
102
+ assert(excel_if(FALSE,new_excel_number(10),new_excel_number(20)).number == 20);
103
+ assert(excel_if(NA,new_excel_number(10),new_excel_number(20)).type == ExcelError);
104
+ assert(excel_if(TRUE,new_excel_number(10),NA).type == ExcelNumber);
105
+ assert(excel_if(TRUE,new_excel_number(10),NA).number == 10);
106
+
107
+ // Test excel_match
108
+ ExcelValue excel_match_array_1[] = { new_excel_number(10), new_excel_number(100) };
109
+ ExcelValue excel_match_array_1_v = new_excel_range(excel_match_array_1,1,2);
110
+ ExcelValue excel_match_array_2[] = { new_excel_string("Pear"), new_excel_string("Bear"), new_excel_string("Apple") };
111
+ ExcelValue excel_match_array_2_v = new_excel_range(excel_match_array_2,3,1);
112
+ ExcelValue excel_match_array_4[] = { ONE, BLANK, new_excel_number(0) };
113
+ ExcelValue excel_match_array_4_v = new_excel_range(excel_match_array_4,1,3);
114
+ ExcelValue excel_match_array_5[] = { ONE, new_excel_number(0), BLANK };
115
+ ExcelValue excel_match_array_5_v = new_excel_range(excel_match_array_5,1,3);
116
+
117
+ // Two argument version
118
+ assert(excel_match_2(new_excel_number(10),excel_match_array_1_v).number == 1);
119
+ assert(excel_match_2(new_excel_number(100),excel_match_array_1_v).number == 2);
120
+ assert(excel_match_2(new_excel_number(1000),excel_match_array_1_v).type == ExcelError);
121
+ assert(excel_match_2(new_excel_number(0), excel_match_array_4_v).number == 2);
122
+ assert(excel_match_2(BLANK, excel_match_array_5_v).number == 2);
123
+
124
+ // Three argument version
125
+ assert(excel_match(new_excel_number(10.0), excel_match_array_1_v, new_excel_number(0) ).number == 1);
126
+ assert(excel_match(new_excel_number(100.0), excel_match_array_1_v, new_excel_number(0) ).number == 2);
127
+ assert(excel_match(new_excel_number(1000.0), excel_match_array_1_v, new_excel_number(0) ).type == ExcelError);
128
+ assert(excel_match(new_excel_string("bEAr"), excel_match_array_2_v, new_excel_number(0) ).number == 2);
129
+ assert(excel_match(new_excel_number(1000.0), excel_match_array_1_v, ONE ).number == 2);
130
+ assert(excel_match(new_excel_number(1.0), excel_match_array_1_v, ONE ).type == ExcelError);
131
+ assert(excel_match(new_excel_string("Care"), excel_match_array_2_v, new_excel_number(-1) ).number == 1 );
132
+ assert(excel_match(new_excel_string("Zebra"), excel_match_array_2_v, new_excel_number(-1) ).type == ExcelError);
133
+ assert(excel_match(new_excel_string("a"), excel_match_array_2_v, new_excel_number(-1) ).number == 2);
134
+
135
+ // When not given a range
136
+ assert(excel_match(new_excel_number(10.0), new_excel_number(10), new_excel_number(0.0)).number == 1);
137
+ assert(excel_match(new_excel_number(20.0), new_excel_number(10), new_excel_number(0.0)).type == ExcelError);
138
+ assert(excel_match(new_excel_number(10.0), excel_match_array_1_v, BLANK).number == 1);
139
+
140
+ // Test more than on
141
+ // .. numbers
142
+ assert(more_than(ONE,new_excel_number(2)).number == false);
143
+ assert(more_than(ONE,ONE).number == false);
144
+ assert(more_than(ONE,new_excel_number(0)).number == true);
145
+ // .. booleans
146
+ assert(more_than(FALSE,FALSE).number == false);
147
+ assert(more_than(FALSE,TRUE).number == false);
148
+ assert(more_than(TRUE,FALSE).number == true);
149
+ assert(more_than(TRUE,TRUE).number == false);
150
+ // ..strings
151
+ assert(more_than(new_excel_string("HELLO"),new_excel_string("Ardvark")).number == true);
152
+ assert(more_than(new_excel_string("HELLO"),new_excel_string("world")).number == false);
153
+ assert(more_than(new_excel_string("HELLO"),new_excel_string("hello")).number == false);
154
+ // ..blanks
155
+ assert(more_than(BLANK,ONE).number == false);
156
+ assert(more_than(BLANK,new_excel_number(-1)).number == true);
157
+ assert(more_than(ONE,BLANK).number == true);
158
+ assert(more_than(new_excel_number(-1),BLANK).number == false);
159
+
160
+ // Test less than on
161
+ // .. numbers
162
+ assert(less_than(ONE,new_excel_number(2)).number == true);
163
+ assert(less_than(ONE,ONE).number == false);
164
+ assert(less_than(ONE,new_excel_number(0)).number == false);
165
+ // .. booleans
166
+ assert(less_than(FALSE,FALSE).number == false);
167
+ assert(less_than(FALSE,TRUE).number == true);
168
+ assert(less_than(TRUE,FALSE).number == false);
169
+ assert(less_than(TRUE,TRUE).number == false);
170
+ // ..strings
171
+ assert(less_than(new_excel_string("HELLO"),new_excel_string("Ardvark")).number == false);
172
+ assert(less_than(new_excel_string("HELLO"),new_excel_string("world")).number == true);
173
+ assert(less_than(new_excel_string("HELLO"),new_excel_string("hello")).number == false);
174
+ // ..blanks
175
+ assert(less_than(BLANK,ONE).number == true);
176
+ assert(less_than(BLANK,new_excel_number(-1)).number == false);
177
+ assert(less_than(ONE,BLANK).number == false);
178
+ assert(less_than(new_excel_number(-1),BLANK).number == true);
179
+
180
+ // Test FIND function
181
+ // ... should find the first occurrence of one string in another, returning :value if the string doesn't match
182
+ assert(find_2(new_excel_string("one"),new_excel_string("onetwothree")).number == 1);
183
+ assert(find_2(new_excel_string("one"),new_excel_string("twoonethree")).number == 4);
184
+ assert(find_2(new_excel_string("one"),new_excel_string("twoonthree")).type == ExcelError);
185
+ // ... should find the first occurrence of one string in another after a given index, returning :value if the string doesn't match
186
+ assert(find(new_excel_string("one"),new_excel_string("onetwothree"),ONE).number == 1);
187
+ assert(find(new_excel_string("one"),new_excel_string("twoonethree"),new_excel_number(5)).type == ExcelError);
188
+ assert(find(new_excel_string("one"),new_excel_string("oneone"),new_excel_number(2)).number == 4);
189
+ // ... should be possible for the start_num to be a string, if that string converts to a number
190
+ assert(find(new_excel_string("one"),new_excel_string("oneone"),new_excel_string("2")).number == 4);
191
+ // ... should return a :value error when given anything but a number as the third argument
192
+ assert(find(new_excel_string("one"),new_excel_string("oneone"),new_excel_string("a")).type == ExcelError);
193
+ // ... should return a :value error when given a third argument that is less than 1 or greater than the length of the string
194
+ assert(find(new_excel_string("one"),new_excel_string("oneone"),new_excel_number(0)).type == ExcelError);
195
+ assert(find(new_excel_string("one"),new_excel_string("oneone"),new_excel_number(-1)).type == ExcelError);
196
+ assert(find(new_excel_string("one"),new_excel_string("oneone"),new_excel_number(7)).type == ExcelError);
197
+ // ... BLANK in the first argument matches any character
198
+ assert(find_2(BLANK,new_excel_string("abcdefg")).number == 1);
199
+ assert(find(BLANK,new_excel_string("abcdefg"),new_excel_number(4)).number == 4);
200
+ // ... should treat BLANK in the second argument as an empty string
201
+ assert(find_2(BLANK,BLANK).number == 1);
202
+ assert(find_2(new_excel_string("a"),BLANK).type == ExcelError);
203
+ // ... should return an error if any argument is an error
204
+ assert(find(new_excel_string("one"),new_excel_string("onetwothree"),NA).type == ExcelError);
205
+ assert(find(new_excel_string("one"),NA,ONE).type == ExcelError);
206
+ assert(find(NA,new_excel_string("onetwothree"),ONE).type == ExcelError);
207
+
208
+ // Test the IFERROR function
209
+ assert(iferror(new_excel_string("ok"),ONE).type == ExcelString);
210
+ assert(iferror(VALUE,ONE).type == ExcelNumber);
211
+
212
+ // Test the INDEX function
213
+ ExcelValue index_array_1[] = { new_excel_number(10), new_excel_number(20), BLANK };
214
+ ExcelValue index_array_1_v_column = new_excel_range(index_array_1,3,1);
215
+ ExcelValue index_array_1_v_row = new_excel_range(index_array_1,1,3);
216
+ ExcelValue index_array_2[] = { BLANK, ONE, new_excel_number(10), new_excel_number(11), new_excel_number(100), new_excel_number(101) };
217
+ ExcelValue index_array_2_v = new_excel_range(index_array_2,3,2);
218
+ // ... if given one argument should return the value at that offset in the range
219
+ assert(excel_index_2(index_array_1_v_column,new_excel_number(2.0)).number == 20);
220
+ assert(excel_index_2(index_array_1_v_row,new_excel_number(2.0)).number == 20);
221
+ // ... but not if the range is not a single row or single column
222
+ assert(excel_index_2(index_array_2_v,new_excel_number(2.0)).type == ExcelError);
223
+ // ... it should return the value in the array at position row_number, column_number
224
+ assert(excel_index(new_excel_number(10),ONE,ONE).number == 10);
225
+ assert(excel_index(index_array_2_v,new_excel_number(1.0),new_excel_number(2.0)).number == 1);
226
+ assert(excel_index(index_array_2_v,new_excel_number(2.0),new_excel_number(1.0)).number == 10);
227
+ assert(excel_index(index_array_2_v,new_excel_number(3.0),new_excel_number(1.0)).number == 100);
228
+ assert(excel_index(index_array_2_v,new_excel_number(3.0),new_excel_number(3.0)).type == ExcelError);
229
+ // ... it should return ZERO not blank, if a blank cell is picked
230
+ assert(excel_index(index_array_2_v,new_excel_number(1.0),new_excel_number(1.0)).type == ExcelNumber);
231
+ assert(excel_index(index_array_2_v,new_excel_number(1.0),new_excel_number(1.0)).number == 0);
232
+ assert(excel_index_2(index_array_1_v_row,new_excel_number(3.0)).type == ExcelNumber);
233
+ assert(excel_index_2(index_array_1_v_row,new_excel_number(3.0)).number == 0);
234
+ // ... it should return the whole row if given a zero column number
235
+ ExcelValue index_result_1_v = excel_index(index_array_2_v,new_excel_number(1.0),new_excel_number(0.0));
236
+ assert(index_result_1_v.type == ExcelRange);
237
+ assert(index_result_1_v.rows == 1);
238
+ assert(index_result_1_v.columns == 2);
239
+ ExcelValue *index_result_1_a = index_result_1_v.array;
240
+ assert(index_result_1_a[0].number == 0);
241
+ assert(index_result_1_a[1].number == 1);
242
+ // ... it should return the whole column if given a zero row number
243
+ ExcelValue index_result_2_v = excel_index(index_array_2_v,new_excel_number(0),new_excel_number(1.0));
244
+ assert(index_result_2_v.type == ExcelRange);
245
+ assert(index_result_2_v.rows == 3);
246
+ assert(index_result_2_v.columns == 1);
247
+ ExcelValue *index_result_2_a = index_result_2_v.array;
248
+ assert(index_result_2_a[0].number == 0);
249
+ assert(index_result_2_a[1].number == 10);
250
+ assert(index_result_2_a[2].number == 100);
251
+ // ... it should return a :ref error when given arguments outside array range
252
+ assert(excel_index_2(index_array_1_v_row,new_excel_number(-1)).type == ExcelError);
253
+ assert(excel_index_2(index_array_1_v_row,new_excel_number(4)).type == ExcelError);
254
+ // ... it should treat BLANK as zero if given as a required row or column number
255
+ assert(excel_index(index_array_2_v,new_excel_number(1.0),BLANK).type == ExcelRange);
256
+ assert(excel_index(index_array_2_v,BLANK,new_excel_number(2.0)).type == ExcelRange);
257
+ // ... it should return an error if an argument is an error
258
+ assert(excel_index(NA,NA,NA).type == ExcelError);
259
+
260
+ // LEFT(string,[characters])
261
+ // ... should return the left n characters from a string
262
+ assert(strcmp(left_1(new_excel_string("ONE")).string,"O") == 0);
263
+ assert(strcmp(left(new_excel_string("ONE"),ONE).string,"O") == 0);
264
+ assert(strcmp(left(new_excel_string("ONE"),new_excel_number(3)).string,"ONE") == 0);
265
+ // ... should turn numbers into strings before processing
266
+ assert(strcmp(left(new_excel_number(1.31e12),new_excel_number(3)).string, "131") == 0);
267
+ // ... should turn booleans into the words TRUE and FALSE before processing
268
+ assert(strcmp(left(TRUE,new_excel_number(3)).string,"TRU") == 0);
269
+ assert(strcmp(left(FALSE,new_excel_number(3)).string,"FAL") == 0);
270
+ // ... should return BLANK if given BLANK for either argument
271
+ assert(left(BLANK,new_excel_number(3)).type == ExcelEmpty);
272
+ assert(left(new_excel_string("ONE"),BLANK).type == ExcelEmpty);
273
+ // ... should return an error if an argument is an error
274
+ assert(left_1(NA).type == ExcelError);
275
+ assert(left(new_excel_string("ONE"),NA).type == ExcelError);
276
+ assert(left(new_excel_string("ONE"),new_excel_number(-10)).type == ExcelError);
277
+
278
+ // Test less than or equal to
279
+ // .. numbers
280
+ assert(less_than_or_equal(ONE,new_excel_number(2)).number == true);
281
+ assert(less_than_or_equal(ONE,ONE).number == true);
282
+ assert(less_than_or_equal(ONE,new_excel_number(0)).number == false);
283
+ // .. booleans
284
+ assert(less_than_or_equal(FALSE,FALSE).number == true);
285
+ assert(less_than_or_equal(FALSE,TRUE).number == true);
286
+ assert(less_than_or_equal(TRUE,FALSE).number == false);
287
+ assert(less_than_or_equal(TRUE,TRUE).number == true);
288
+ // ..strings
289
+ assert(less_than_or_equal(new_excel_string("HELLO"),new_excel_string("Ardvark")).number == false);
290
+ assert(less_than_or_equal(new_excel_string("HELLO"),new_excel_string("world")).number == true);
291
+ assert(less_than_or_equal(new_excel_string("HELLO"),new_excel_string("hello")).number == true);
292
+ // ..blanks
293
+ assert(less_than_or_equal(BLANK,ONE).number == true);
294
+ assert(less_than_or_equal(BLANK,new_excel_number(-1)).number == false);
295
+ assert(less_than_or_equal(ONE,BLANK).number == false);
296
+ assert(less_than_or_equal(new_excel_number(-1),BLANK).number == true);
297
+
298
+ // Test MAX
299
+ assert(max(4, array1).number == 10);
300
+ assert(max(3, array2).number == 10);
301
+ assert(max(4, array3).type == ExcelError);
302
+
303
+ // Test MIN
304
+ assert(min(4, array1).number == 5);
305
+ assert(min(3, array2).number == 5);
306
+ assert(min(4, array3).type == ExcelError);
307
+
308
+ // Test MOD
309
+ // ... should return the remainder of a number
310
+ assert(mod(new_excel_number(10), new_excel_number(3)).number == 1.0);
311
+ assert(mod(new_excel_number(10), new_excel_number(5)).number == 0.0);
312
+ // ... should be possible for the the arguments to be strings, if they convert to a number
313
+ assert(mod(new_excel_string("3.5"),new_excel_string("2")).number == 1.5);
314
+ // ... should treat BLANK as zero
315
+ assert(mod(BLANK,new_excel_number(10)).number == 0);
316
+ assert(mod(new_excel_number(10),BLANK).type == ExcelError);
317
+ assert(mod(BLANK,BLANK).type == ExcelError);
318
+ // ... should treat true as 1 and FALSE as 0
319
+ assert((mod(new_excel_number(1.1),TRUE).number - 0.1) < 0.001);
320
+ assert(mod(new_excel_number(1.1),FALSE).type == ExcelError);
321
+ assert(mod(FALSE,new_excel_number(10)).number == 0);
322
+ // ... should return an error when given inappropriate arguments
323
+ assert(mod(new_excel_string("Asdasddf"),new_excel_string("adsfads")).type == ExcelError);
324
+ // ... should return an error if an argument is an error
325
+ assert(mod(new_excel_number(1),VALUE).type == ExcelError);
326
+ assert(mod(VALUE,new_excel_number(1)).type == ExcelError);
327
+ assert(mod(VALUE,VALUE).type == ExcelError);
328
+
329
+ // Test more than or equal to on
330
+ // .. numbers
331
+ assert(more_than_or_equal(ONE,new_excel_number(2)).number == false);
332
+ assert(more_than_or_equal(ONE,ONE).number == true);
333
+ assert(more_than_or_equal(ONE,new_excel_number(0)).number == true);
334
+ // .. booleans
335
+ assert(more_than_or_equal(FALSE,FALSE).number == true);
336
+ assert(more_than_or_equal(FALSE,TRUE).number == false);
337
+ assert(more_than_or_equal(TRUE,FALSE).number == true);
338
+ assert(more_than_or_equal(TRUE,TRUE).number == true);
339
+ // ..strings
340
+ assert(more_than_or_equal(new_excel_string("HELLO"),new_excel_string("Ardvark")).number == true);
341
+ assert(more_than_or_equal(new_excel_string("HELLO"),new_excel_string("world")).number == false);
342
+ assert(more_than_or_equal(new_excel_string("HELLO"),new_excel_string("hello")).number == true);
343
+ // ..blanks
344
+ assert(more_than_or_equal(BLANK,BLANK).number == true);
345
+ assert(more_than_or_equal(BLANK,ONE).number == false);
346
+ assert(more_than_or_equal(BLANK,new_excel_number(-1)).number == true);
347
+ assert(more_than_or_equal(ONE,BLANK).number == true);
348
+ assert(more_than_or_equal(new_excel_number(-1),BLANK).number == false);
349
+
350
+ // Test negative
351
+ // ... should return the negative of its arguments
352
+ assert(negative(new_excel_number(1)).number == -1);
353
+ assert(negative(new_excel_number(-1)).number == 1);
354
+ // ... should treat strings that only contain numbers as numbers
355
+ assert(negative(new_excel_string("10")).number == -10);
356
+ assert(negative(new_excel_string("-1.3")).number == 1.3);
357
+ // ... should return an error when given inappropriate arguments
358
+ assert(negative(new_excel_string("Asdasddf")).type == ExcelError);
359
+ // ... should treat BLANK as zero
360
+ assert(negative(BLANK).number == 0);
361
+
362
+ // Test PMT(rate,number_of_periods,present_value) - optional arguments not yet implemented
363
+ // ... should calculate the monthly payment required for a given principal, interest rate and loan period
364
+ assert((pmt(new_excel_number(0.1),new_excel_number(10),new_excel_number(100)).number - -16.27) < 0.01);
365
+ assert((pmt(new_excel_number(0.0123),new_excel_number(99.1),new_excel_number(123.32)).number - -2.159) < 0.01);
366
+ assert((pmt(new_excel_number(0),new_excel_number(2),new_excel_number(10)).number - -5) < 0.01);
367
+
368
+ // Test power
369
+ // ... should return power of its arguments
370
+ assert(power(new_excel_number(2),new_excel_number(3)).number == 8);
371
+ assert(power(new_excel_number(4.0),new_excel_number(0.5)).number == 2.0);
372
+ assert(power(new_excel_number(-4.0),new_excel_number(0.5)).type == ExcelError);
373
+
374
+ // Test round
375
+ assert(excel_round(new_excel_number(1.1), new_excel_number(0)).number == 1.0);
376
+ assert(excel_round(new_excel_number(1.5), new_excel_number(0)).number == 2.0);
377
+ assert(excel_round(new_excel_number(1.56),new_excel_number(1)).number == 1.6);
378
+ assert(excel_round(new_excel_number(-1.56),new_excel_number(1)).number == -1.6);
379
+
380
+ // Test rounddown
381
+ assert(rounddown(new_excel_number(1.1), new_excel_number(0)).number == 1.0);
382
+ assert(rounddown(new_excel_number(1.5), new_excel_number(0)).number == 1.0);
383
+ assert(rounddown(new_excel_number(1.56),new_excel_number(1)).number == 1.5);
384
+ assert(rounddown(new_excel_number(-1.56),new_excel_number(1)).number == -1.5);
385
+
386
+ // Test int
387
+ assert(excel_int(new_excel_number(8.9)).number == 8.0);
388
+ assert(excel_int(new_excel_number(-8.9)).number == -9.0);
389
+
390
+ // Test roundup
391
+ assert(roundup(new_excel_number(1.1), new_excel_number(0)).number == 2.0);
392
+ assert(roundup(new_excel_number(1.5), new_excel_number(0)).number == 2.0);
393
+ assert(roundup(new_excel_number(1.56),new_excel_number(1)).number == 1.6);
394
+ assert(roundup(new_excel_number(-1.56),new_excel_number(1)).number == -1.6);
395
+
396
+ // Test string joining
397
+ ExcelValue string_join_array_1[] = {new_excel_string("Hello "), new_excel_string("world")};
398
+ ExcelValue string_join_array_2[] = {new_excel_string("Hello "), new_excel_string("world"), new_excel_string("!")};
399
+ ExcelValue string_join_array_3[] = {new_excel_string("Top "), new_excel_number(10.0)};
400
+ ExcelValue string_join_array_4[] = {new_excel_string("Top "), new_excel_number(10.5)};
401
+ ExcelValue string_join_array_5[] = {new_excel_string("Top "), TRUE, FALSE};
402
+ // ... should return a string by combining its arguments
403
+ // inspect_excel_value(string_join(2, string_join_array_1));
403
404
  assert(string_join(2, string_join_array_1).string[6] == 'w');
404
405
  assert(string_join(2, string_join_array_1).string[11] == '\0');
405
- // ... should cope with an arbitrary number of arguments
406
+ // ... should cope with an arbitrary number of arguments
406
407
  assert(string_join(3, string_join_array_2).string[11] == '!');
407
408
  assert(string_join(3, string_join_array_3).string[12] == '\0');
408
- // ... should convert values to strings as it goes
409
+ // ... should convert values to strings as it goes
409
410
  assert(string_join(2, string_join_array_3).string[4] == '1');
410
411
  assert(string_join(2, string_join_array_3).string[5] == '0');
411
412
  assert(string_join(2, string_join_array_3).string[6] == '\0');
412
- // ... should convert integer values into strings without decimal points, and float values with decimal points
413
+ // ... should convert integer values into strings without decimal points, and float values with decimal points
413
414
  assert(string_join(2, string_join_array_4).string[4] == '1');
414
415
  assert(string_join(2, string_join_array_4).string[5] == '0');
415
416
  assert(string_join(2, string_join_array_4).string[6] == '.');
416
417
  assert(string_join(2, string_join_array_4).string[7] == '5');
417
418
  assert(string_join(2, string_join_array_4).string[8] == '\0');
418
- // ... should convert TRUE and FALSE into strings
419
+ // ... should convert TRUE and FALSE into strings
419
420
  assert(string_join(3,string_join_array_5).string[4] == 'T');
420
421
  // Should deal with very long string joins
421
- ExcelValue string_join_array_6[] = {new_excel_string("0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"), new_excel_string("012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789")};
422
+ ExcelValue string_join_array_6[] = {new_excel_string("0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"), new_excel_string("012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789")};
422
423
  assert(string_join(2, string_join_array_6).string[0] == '0');
423
424
  free_all_allocated_memory();
424
-
425
+
425
426
  // Test SUBTOTAL function
426
427
  ExcelValue subtotal_array_1[] = {new_excel_number(10),new_excel_number(100),BLANK};
427
428
  ExcelValue subtotal_array_1_v = new_excel_range(subtotal_array_1,3,1);
428
429
  ExcelValue subtotal_array_2[] = {new_excel_number(1),new_excel_string("two"),subtotal_array_1_v};
429
-
430
+
430
431
  // new_excel_number(1.0);
431
432
  // inspect_excel_value(new_excel_number(1.0));
432
433
  // inspect_excel_value(new_excel_range(subtotal_array_2,3,1));
433
434
  // inspect_excel_value(subtotal(new_excel_number(1.0),3,subtotal_array_2));
434
-
435
+
435
436
  assert(subtotal(new_excel_number(1.0),3,subtotal_array_2).number == 111.0/3.0);
436
437
  assert(subtotal(new_excel_number(2.0),3,subtotal_array_2).number == 3);
437
438
  assert(subtotal(new_excel_number(3.0),7, count_a_test_array_1).number == 6);
@@ -441,7 +442,7 @@ int test_functions() {
441
442
  assert(subtotal(new_excel_number(102.0),3,subtotal_array_2).number == 3);
442
443
  assert(subtotal(new_excel_number(103.0),3,subtotal_array_2).number == 4);
443
444
  assert(subtotal(new_excel_number(109.0),3,subtotal_array_2).number == 111);
444
-
445
+
445
446
  // Test SUMIFS function
446
447
  ExcelValue sumifs_array_1[] = {new_excel_number(10),new_excel_number(100),BLANK};
447
448
  ExcelValue sumifs_array_1_v = new_excel_range(sumifs_array_1,3,1);
@@ -453,14 +454,14 @@ int test_functions() {
453
454
  ExcelValue sumifs_array_4_v = new_excel_range(sumifs_array_4,6,1);
454
455
  ExcelValue sumifs_array_5[] = {new_excel_string("1A"),new_excel_string("1A"),new_excel_string("1A"),new_excel_number(4),new_excel_number(4),new_excel_number(5)};
455
456
  ExcelValue sumifs_array_5_v = new_excel_range(sumifs_array_5,6,1);
456
-
457
+
457
458
  // ... should only sum values that meet all of the criteria
458
459
  ExcelValue sumifs_array_6[] = { sumifs_array_1_v, new_excel_number(10), sumifs_array_2_v, new_excel_string("Bear") };
459
460
  assert(sumifs(sumifs_array_1_v,4,sumifs_array_6).number == 0.0);
460
-
461
+
461
462
  ExcelValue sumifs_array_7[] = { sumifs_array_1_v, new_excel_number(10), sumifs_array_2_v, new_excel_string("Pear") };
462
463
  assert(sumifs(sumifs_array_1_v,4,sumifs_array_7).number == 10.0);
463
-
464
+
464
465
  // ... should work when single cells are given where ranges expected
465
466
  ExcelValue sumifs_array_8[] = { new_excel_string("CAR"), new_excel_string("CAR"), new_excel_string("FCV"), new_excel_string("FCV")};
466
467
  assert(sumifs(new_excel_number(0.143897265452564), 4, sumifs_array_8).number == 0.143897265452564);
@@ -468,10 +469,10 @@ int test_functions() {
468
469
  // ... should match numbers with strings that contain numbers
469
470
  ExcelValue sumifs_array_9[] = { new_excel_number(10), new_excel_string("10.0")};
470
471
  assert(sumifs(new_excel_number(100),2,sumifs_array_9).number == 100);
471
-
472
+
472
473
  ExcelValue sumifs_array_10[] = { sumifs_array_4_v, new_excel_string("CO2"), sumifs_array_5_v, new_excel_number(2)};
473
474
  assert(sumifs(sumifs_array_3_v,4, sumifs_array_10).number == 0);
474
-
475
+
475
476
  // ... should match with strings that contain criteria
476
477
  ExcelValue sumifs_array_10a[] = { sumifs_array_3_v, new_excel_string("=5")};
477
478
  assert(sumifs(sumifs_array_3_v,2, sumifs_array_10a).number == 10);
@@ -481,7 +482,7 @@ int test_functions() {
481
482
 
482
483
  ExcelValue sumifs_array_10c[] = { sumifs_array_3_v, new_excel_string("<3")};
483
484
  assert(sumifs(sumifs_array_3_v,2, sumifs_array_10c).number == 3);
484
-
485
+
485
486
  ExcelValue sumifs_array_10d[] = { sumifs_array_3_v, new_excel_string("<=3")};
486
487
  assert(sumifs(sumifs_array_3_v,2, sumifs_array_10d).number == 6);
487
488
 
@@ -490,33 +491,33 @@ int test_functions() {
490
491
 
491
492
  ExcelValue sumifs_array_10f[] = { sumifs_array_3_v, new_excel_string(">=3")};
492
493
  assert(sumifs(sumifs_array_3_v,2, sumifs_array_10f).number == 17);
493
-
494
+
494
495
  // ... should treat BLANK as an empty string when in the check_range, but not in the criteria
495
496
  ExcelValue sumifs_array_11[] = { BLANK, new_excel_number(20)};
496
497
  assert(sumifs(new_excel_number(100),2,sumifs_array_11).number == 0);
497
-
498
+
498
499
  ExcelValue sumifs_array_12[] = {BLANK, new_excel_string("")};
499
500
  assert(sumifs(new_excel_number(100),2,sumifs_array_12).number == 100);
500
-
501
+
501
502
  ExcelValue sumifs_array_13[] = {BLANK, BLANK};
502
503
  assert(sumifs(new_excel_number(100),2,sumifs_array_13).number == 0);
503
-
504
+
504
505
  // ... should return an error if range argument is an error
505
506
  assert(sumifs(REF,2,sumifs_array_13).type == ExcelError);
506
-
507
-
507
+
508
+
508
509
  // Test SUMIF
509
510
  // ... where there is only a check range
510
511
  assert(sumif_2(sumifs_array_1_v,new_excel_string(">0")).number == 110.0);
511
512
  assert(sumif_2(sumifs_array_1_v,new_excel_string(">10")).number == 100.0);
512
513
  assert(sumif_2(sumifs_array_1_v,new_excel_string("<100")).number == 10.0);
513
-
514
+
514
515
  // ... where there is a seprate sum range
515
516
  ExcelValue sumif_array_1[] = {new_excel_number(15),new_excel_number(20), new_excel_number(30)};
516
517
  ExcelValue sumif_array_1_v = new_excel_range(sumif_array_1,3,1);
517
518
  assert(sumif(sumifs_array_1_v,new_excel_string("10"),sumif_array_1_v).number == 15);
518
-
519
-
519
+
520
+
520
521
  // Test SUMPRODUCT
521
522
  ExcelValue sumproduct_1[] = { new_excel_number(10), new_excel_number(100), BLANK};
522
523
  ExcelValue sumproduct_2[] = { BLANK, new_excel_number(100), new_excel_number(10), BLANK};
@@ -527,7 +528,7 @@ int test_functions() {
527
528
  ExcelValue sumproduct_7[] = { new_excel_number(10), new_excel_number(20), new_excel_number(40), new_excel_number(50)};
528
529
  ExcelValue sumproduct_8[] = { new_excel_number(11), new_excel_number(21), new_excel_number(41), new_excel_number(51)};
529
530
  ExcelValue sumproduct_9[] = { BLANK, BLANK };
530
-
531
+
531
532
  ExcelValue sumproduct_1_v = new_excel_range( sumproduct_1, 3, 1);
532
533
  ExcelValue sumproduct_2_v = new_excel_range( sumproduct_2, 3, 1);
533
534
  ExcelValue sumproduct_3_v = new_excel_range( sumproduct_3, 1, 1);
@@ -537,7 +538,7 @@ int test_functions() {
537
538
  ExcelValue sumproduct_7_v = new_excel_range( sumproduct_7, 2, 2);
538
539
  ExcelValue sumproduct_8_v = new_excel_range( sumproduct_8, 2, 2);
539
540
  ExcelValue sumproduct_9_v = new_excel_range( sumproduct_9, 2, 1);
540
-
541
+
541
542
  // ... should multiply together and then sum the elements in row or column areas given as arguments
542
543
  ExcelValue sumproducta_1[] = {sumproduct_1_v, sumproduct_2_v};
543
544
  assert(sumproduct(2,sumproducta_1).number == 100*100);
@@ -569,7 +570,7 @@ int test_functions() {
569
570
  // ... should return an error if an argument is an error
570
571
  ExcelValue sumproducta_8[] = {VALUE};
571
572
  assert(sumproduct(1,sumproducta_8).type == ExcelError);
572
-
573
+
573
574
  // Test VLOOKUP
574
575
  ExcelValue vlookup_a1[] = {new_excel_number(1),new_excel_number(10),new_excel_number(2),new_excel_number(20),new_excel_number(3),new_excel_number(30)};
575
576
  ExcelValue vlookup_a2[] = {new_excel_string("hello"),new_excel_number(10),new_excel_number(2),new_excel_number(20),new_excel_number(3),new_excel_number(30)};
@@ -599,7 +600,7 @@ int test_functions() {
599
600
  assert(vlookup(new_excel_number(2.0),vlookup_a1_v,VALUE,FALSE).type == ExcelError);
600
601
  assert(vlookup(new_excel_number(2.0),vlookup_a1_v,new_excel_number(2),VALUE).type == ExcelError);
601
602
  assert(vlookup(VALUE,VALUE,VALUE,VALUE).type == ExcelError);
602
-
603
+
603
604
  // Test HLOOKUP
604
605
  ExcelValue hlookup_a1[] = {new_excel_number(1),new_excel_number(2),new_excel_number(3),new_excel_number(10),new_excel_number(20),new_excel_number(30)};
605
606
  ExcelValue hlookup_a2[] = {new_excel_string("hello"),new_excel_number(2),new_excel_number(3),new_excel_number(10),new_excel_number(20),new_excel_number(30)};
@@ -642,7 +643,7 @@ int test_functions() {
642
643
  assert((int) pv_3(new_excel_number(0.03), new_excel_number(12), new_excel_number(100)).number == -995);
643
644
  assert((int) pv_4(new_excel_number(0.03), new_excel_number(12), new_excel_number(-100), new_excel_number(100)).number == 925);
644
645
  assert((int) pv_5(new_excel_number(0.03), new_excel_number(12), new_excel_number(-100), new_excel_number(-100), new_excel_number(1)).number == 1095);
645
-
646
+
646
647
  // Test TEXT
647
648
  assert(strcmp(text(new_excel_number(1.0), new_excel_string("0%")).string, "100%") == 0);
648
649
  assert(strcmp(text(new_excel_string("1"), new_excel_string("0%")).string, "100%") == 0);
@@ -652,13 +653,13 @@ int test_functions() {
652
653
 
653
654
  // Test LOG
654
655
  // One argument variant assumes LOG base 10
655
- assert(excel_log(new_excel_number(10)).number == 1);
656
- assert(excel_log(new_excel_number(100)).number == 2);
657
- assert(excel_log(new_excel_number(0)).type == ExcelError);
656
+ assert(excel_log(new_excel_number(10)).number == 1);
657
+ assert(excel_log(new_excel_number(100)).number == 2);
658
+ assert(excel_log(new_excel_number(0)).type == ExcelError);
658
659
  // Two argument variant allows LOG base to be specified
659
- assert(excel_log_2(new_excel_number(8),new_excel_number(2)).number == 3.0);
660
- assert(excel_log_2(new_excel_number(8),new_excel_number(0)).type == ExcelError);
661
-
660
+ assert(excel_log_2(new_excel_number(8),new_excel_number(2)).number == 3.0);
661
+ assert(excel_log_2(new_excel_number(8),new_excel_number(0)).type == ExcelError);
662
+
662
663
  // Test MMULT (Matrix multiplication)
663
664
  ExcelValue mmult_1[] = { ONE, TWO, THREE, FOUR};
664
665
  ExcelValue mmult_2[] = { FOUR, THREE, TWO, ONE};
@@ -682,7 +683,7 @@ int test_functions() {
682
683
  assert(mmult_result_1_a[1].number == 5);
683
684
  assert(mmult_result_1_a[2].number == 20);
684
685
  assert(mmult_result_1_a[3].number == 13);
685
-
686
+
686
687
  ExcelValue mmult_result_2_v = mmult(mmult_3_v, mmult_4_v);
687
688
  assert(mmult_result_2_v.type == ExcelRange);
688
689
  assert(mmult_result_2_v.rows == 1);
@@ -700,12 +701,12 @@ int test_functions() {
700
701
  assert(mmult_result_3_a[1].type == ExcelError);
701
702
  assert(mmult_result_3_a[2].type == ExcelError);
702
703
  assert(mmult_result_3_a[3].type == ExcelError);
703
-
704
+
704
705
  // Returns errors if arguments are not ranges
705
706
  // FIXME: Should work in edge case where passed two numbers which excel treats as ranges with one row and column
706
707
  ExcelValue mmult_result_4_v = mmult(ONE, mmult_2_v);
707
708
  assert(mmult_result_4_v.type == ExcelError);
708
-
709
+
709
710
  // Returns errors if the ranges aren't the right size to multiply
710
711
  ExcelValue mmult_result_5_v = mmult(mmult_1_v, mmult_3_v);
711
712
  assert(mmult_result_5_v.type == ExcelRange);
@@ -762,7 +763,7 @@ int test_functions() {
762
763
  assert(excel_isblank(TRUE).number == false);
763
764
  assert(excel_isblank(FALSE).number == false);
764
765
  assert(excel_isblank(new_excel_string("")).number == false);
765
-
766
+
766
767
  // Test AVERAGEIFS function
767
768
  ExcelValue averageifs_array_1[] = {new_excel_number(10),new_excel_number(100),BLANK};
768
769
  ExcelValue averageifs_array_1_v = new_excel_range(averageifs_array_1,3,1);
@@ -774,14 +775,14 @@ int test_functions() {
774
775
  ExcelValue averageifs_array_4_v = new_excel_range(averageifs_array_4,6,1);
775
776
  ExcelValue averageifs_array_5[] = {new_excel_string("1A"),new_excel_string("1A"),new_excel_string("1A"),new_excel_number(4),new_excel_number(4),new_excel_number(5)};
776
777
  ExcelValue averageifs_array_5_v = new_excel_range(averageifs_array_5,6,1);
777
-
778
+
778
779
  // ... should only average values that meet all of the criteria
779
780
  ExcelValue averageifs_array_6[] = { averageifs_array_1_v, new_excel_number(10), averageifs_array_2_v, new_excel_string("Bear") };
780
781
  assert(averageifs(averageifs_array_1_v,4,averageifs_array_6).type == ExcelError);
781
-
782
+
782
783
  ExcelValue averageifs_array_7[] = { averageifs_array_1_v, new_excel_number(10), averageifs_array_2_v, new_excel_string("Pear") };
783
784
  assert(averageifs(averageifs_array_1_v,4,averageifs_array_7).number == 10.0);
784
-
785
+
785
786
  // ... should work when single cells are given where ranges expected
786
787
  ExcelValue averageifs_array_8[] = { new_excel_string("CAR"), new_excel_string("CAR"), new_excel_string("FCV"), new_excel_string("FCV")};
787
788
  assert(averageifs(new_excel_number(0.143897265452564), 4, averageifs_array_8).number == 0.143897265452564);
@@ -789,10 +790,10 @@ int test_functions() {
789
790
  // ... should match numbers with strings that contain numbers
790
791
  ExcelValue averageifs_array_9[] = { new_excel_number(10), new_excel_string("10.0")};
791
792
  assert(averageifs(new_excel_number(100),2,averageifs_array_9).number == 100);
792
-
793
+
793
794
  ExcelValue averageifs_array_10[] = { averageifs_array_4_v, new_excel_string("CO2"), averageifs_array_5_v, new_excel_number(2)};
794
795
  assert(averageifs(averageifs_array_3_v,4, averageifs_array_10).type == ExcelError);
795
-
796
+
796
797
  // ... should match with strings that contain criteria
797
798
  ExcelValue averageifs_array_10a[] = { averageifs_array_3_v, new_excel_string("=5")};
798
799
  assert(averageifs(averageifs_array_3_v,2, averageifs_array_10a).number == 5);
@@ -802,7 +803,7 @@ int test_functions() {
802
803
 
803
804
  ExcelValue averageifs_array_10c[] = { averageifs_array_3_v, new_excel_string("<3")};
804
805
  assert(averageifs(averageifs_array_3_v,2, averageifs_array_10c).number == 1.5);
805
-
806
+
806
807
  ExcelValue averageifs_array_10d[] = { averageifs_array_3_v, new_excel_string("<=3")};
807
808
  assert(averageifs(averageifs_array_3_v,2, averageifs_array_10d).number == 2);
808
809
 
@@ -811,17 +812,17 @@ int test_functions() {
811
812
 
812
813
  ExcelValue averageifs_array_10f[] = { averageifs_array_3_v, new_excel_string(">=3")};
813
814
  assert(averageifs(averageifs_array_3_v,2, averageifs_array_10f).number == (3.0+4.0+5.0+5.0)/4.0);
814
-
815
+
815
816
  // ... should treat BLANK as an empty string when in the check_range, but not in the criteria
816
817
  ExcelValue averageifs_array_11[] = { BLANK, new_excel_number(20)};
817
818
  assert(averageifs(new_excel_number(100),2,averageifs_array_11).type == ExcelError);
818
-
819
+
819
820
  ExcelValue averageifs_array_12[] = {BLANK, new_excel_string("")};
820
821
  assert(averageifs(new_excel_number(100),2,averageifs_array_12).number == 100);
821
-
822
+
822
823
  ExcelValue averageifs_array_13[] = {BLANK, BLANK};
823
824
  assert(averageifs(new_excel_number(100),2,averageifs_array_13).type == ExcelError);
824
-
825
+
825
826
  // ... should return an error if range argument is an error
826
827
  assert(averageifs(REF,2,averageifs_array_13).type == ExcelError);
827
828
 
@@ -840,15 +841,55 @@ int test_functions() {
840
841
 
841
842
  assert(forecast(new_excel_number(6), forecast_array2_v, forecast_array3_v).number == 7);
842
843
 
844
+ // Tests ENSURE_IS_NUMBER function
845
+ assert(ensure_is_number(new_excel_number(1.3)).type == ExcelNumber);
846
+ assert(ensure_is_number(new_excel_number(1.3)).number == 1.3);
847
+ assert(ensure_is_number(BLANK).type == ExcelNumber);
848
+ assert(ensure_is_number(BLANK).number == 0);
849
+ assert(ensure_is_number(TRUE).type == ExcelNumber);
850
+ assert(ensure_is_number(TRUE).number == 1.0);
851
+ assert(ensure_is_number(FALSE).type == ExcelNumber);
852
+ assert(ensure_is_number(FALSE).number == 0.0);
853
+ assert(ensure_is_number(new_excel_string("1.3")).type == ExcelNumber);
854
+ assert(ensure_is_number(new_excel_string("1.3")).number == 1.3);
855
+ assert(ensure_is_number(new_excel_string("BASDASD")).type == ExcelError);
856
+ assert(ensure_is_number(DIV0).type == ExcelError);
857
+
858
+ // RIGHT(string,[characters])
859
+ // ... should return the right n characters from a string
860
+ assert(strcmp(right_1(new_excel_string("ONE")).string,"E") == 0);
861
+ assert(strcmp(right(new_excel_string("ONE"),ONE).string,"E") == 0);
862
+ assert(strcmp(right(new_excel_string("ONE"),new_excel_number(3)).string,"ONE") == 0);
863
+ // ... should turn numbers into strings before processing
864
+ assert(strcmp(right(new_excel_number(1.31e12),new_excel_number(3)).string, "000") == 0);
865
+ // ... should turn booleans into the words TRUE and FALSE before processing
866
+ assert(strcmp(right(TRUE,new_excel_number(3)).string,"RUE") == 0);
867
+ assert(strcmp(right(FALSE,new_excel_number(3)).string,"LSE") == 0);
868
+ // ... should return BLANK if given BLANK for either argument
869
+ assert(right(BLANK,new_excel_number(3)).type == ExcelEmpty);
870
+ assert(right(new_excel_string("ONE"),BLANK).type == ExcelEmpty);
871
+ // ... should return an error if an argument is an error
872
+ assert(right_1(NA).type == ExcelError);
873
+ assert(right(new_excel_string("ONE"),NA).type == ExcelError);
874
+ assert(right(new_excel_string("ONE"),new_excel_number(-10)).type == ExcelError);
875
+
876
+ // LEN(string)
877
+ assert(len(BLANK).type == ExcelNumber);
878
+ assert(len(BLANK).number == 0);
879
+ assert(len(new_excel_string("Hello")).number == 5);
880
+ assert(len(new_excel_number(123)).number == 3);
881
+ assert(len(TRUE).number == 4);
882
+ assert(len(FALSE).number == 5);
883
+
843
884
  // Release memory
844
885
  free_all_allocated_memory();
845
-
886
+
846
887
  // Yay!
847
888
  printf("All tests passed\n");
848
-
889
+
849
890
  return 0;
850
891
  }
851
892
 
852
893
  int main() {
853
- return test_functions();
894
+ return test_functions();
854
895
  }