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 +4 -4
- data/bin/excel_to_c +4 -0
- data/src/commands/excel_to_c.rb +2 -2
- data/src/commands/excel_to_x.rb +25 -6
- data/src/compile/c/a.out +0 -0
- data/src/compile/c/compile_to_c.rb +6 -0
- data/src/compile/c/excel_to_c_runtime.c +131 -8
- data/src/compile/c/excel_to_c_runtime_test.c +475 -434
- data/src/compile/c/map_formulae_to_c.rb +4 -0
- data/src/compile/c/map_values_to_c.rb +4 -0
- data/src/compile/ruby/map_formulae_to_ruby.rb +7 -1
- data/src/compile/ruby/map_values_to_ruby.rb +4 -0
- data/src/excel/area.rb +6 -1
- data/src/excel/excel_functions.rb +2 -0
- data/src/excel/excel_functions/ensure_is_number.rb +7 -0
- data/src/excel/excel_functions/excel_if.rb +1 -0
- data/src/excel/excel_functions/left.rb +1 -0
- data/src/excel/excel_functions/right.rb +2 -1
- data/src/excel/formula_peg.rb +2 -2
- data/src/excel/formula_peg.txt +2 -2
- data/src/excel/reference.rb +1 -0
- data/src/excel_to_code.rb +1 -1
- data/src/extract/extract_data_from_worksheet.rb +4 -0
- data/src/simplify/inline_formulae.rb +3 -1
- data/src/simplify/map_formulae_to_values.rb +52 -17
- data/src/simplify/replace_arithmetic_on_ranges.rb +51 -2
- data/src/simplify/replace_arrays_with_single_cells.rb +60 -4
- data/src/simplify/replace_ranges_with_array_literals.rb +2 -2
- data/src/simplify/simplify_arithmetic.rb +3 -8
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1cae4231d0e0d0c80b485f2a0fc87d565f226c11
|
4
|
+
data.tar.gz: 625f3ef6ec924295ee2e3f5cba56868381f4f404
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
data/src/commands/excel_to_c.rb
CHANGED
@@ -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 -
|
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 =
|
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
|
data/src/commands/excel_to_x.rb
CHANGED
@@ -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
|
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
|
-
|
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,"%
|
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
|
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
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
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
|
-
|
63
|
-
|
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
|
-
|
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
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
656
|
-
|
657
|
-
|
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
|
-
|
660
|
-
|
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
|
-
|
894
|
+
return test_functions();
|
854
895
|
}
|