excel_to_code 0.2.15 → 0.2.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml 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
  }