excel_to_code 0.2.10 → 0.2.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/excel_to_c +1 -0
- data/src/commands/excel_to_x.rb +12 -3
- data/src/compile/c/a.out +0 -0
- data/src/compile/c/excel_to_c_runtime.c +108 -22
- data/src/compile/c/excel_to_c_runtime_test.c +77 -0
- data/src/compile/c/map_formulae_to_c.rb +6 -0
- data/src/compile/ruby/map_formulae_to_ruby.rb +2 -0
- data/src/excel/excel_functions.rb +4 -0
- data/src/excel/excel_functions/averageifs.rb +76 -0
- data/src/excel/excel_functions/forecast.rb +44 -0
- data/src/excel_to_code.rb +5 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a444173d8318385277afd731b47cedcb7fe2b783
|
4
|
+
data.tar.gz: 13c5f6fa4d20cc45730c9c15f736c68c17a810af
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 201c1f56ae3807bce72ca38c48f78300f2c1c6a2857e2ddf58e111dfe9a64660d0cfc4bf453fe9eb817a8d5c1719e60fb19943b998f5342aea9f9d0873c5d79e
|
7
|
+
data.tar.gz: 9945c873cfc1d3e76f6fff18c8fd43ad38f3862efcd24c16e8eccc53670d247fe8d00792d920fd86efe8732f86c2be1b2cdb0db998af112f68ed10081bd6e358
|
data/bin/excel_to_c
CHANGED
data/src/commands/excel_to_x.rb
CHANGED
@@ -112,6 +112,8 @@ class ExcelToX
|
|
112
112
|
def go!
|
113
113
|
# This sorts out the settings
|
114
114
|
set_defaults
|
115
|
+
|
116
|
+
log.info "Excel to Code version #{ExcelToCode.version}\n\n"
|
115
117
|
|
116
118
|
# These turn the excel into xml on disk
|
117
119
|
sort_out_output_directories
|
@@ -480,10 +482,17 @@ class ExcelToX
|
|
480
482
|
functions_that_are_removed_during_compilation.each do |f|
|
481
483
|
functions_used.delete(f)
|
482
484
|
end
|
485
|
+
|
483
486
|
unless functions_used.empty?
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
+
|
488
|
+
log.fatal "The following functions have not been implemented in excel_to_code #{ExcelToCode.version}:"
|
489
|
+
|
490
|
+
functions_used.each do |f|
|
491
|
+
log.fatal f.to_s
|
492
|
+
end
|
493
|
+
|
494
|
+
log.fatal "Check for a new version of excel_to_code at https://github.com/tamc/excel_to_code"
|
495
|
+
log.fatal "Or follow the instractions at https://github.com/tamc/excel_to_code/blob/master/doc/How_to_add_a_missing_function.md to implement the function yourself"
|
487
496
|
exit
|
488
497
|
end
|
489
498
|
end
|
data/src/compile/c/a.out
CHANGED
Binary file
|
@@ -55,6 +55,8 @@ static ExcelValue more_than_or_equal(ExcelValue a_v, ExcelValue b_v);
|
|
55
55
|
static ExcelValue not_equal(ExcelValue a_v, ExcelValue b_v);
|
56
56
|
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
|
+
static ExcelValue average(int array_size, ExcelValue *array);
|
59
|
+
static ExcelValue averageifs(ExcelValue average_range_v, int number_of_arguments, ExcelValue *arguments);
|
58
60
|
static ExcelValue find_2(ExcelValue string_to_look_for_v, ExcelValue string_to_look_in_v);
|
59
61
|
static ExcelValue find(ExcelValue string_to_look_for_v, ExcelValue string_to_look_in_v, ExcelValue position_to_start_at_v);
|
60
62
|
static ExcelValue hlookup_3(ExcelValue lookup_value_v,ExcelValue lookup_table_v, ExcelValue row_number_v);
|
@@ -64,6 +66,7 @@ static ExcelValue excel_index(ExcelValue array_v, ExcelValue row_number_v, Excel
|
|
64
66
|
static ExcelValue excel_index_2(ExcelValue array_v, ExcelValue row_number_v);
|
65
67
|
static ExcelValue excel_isnumber(ExcelValue number);
|
66
68
|
static ExcelValue excel_isblank(ExcelValue value);
|
69
|
+
static ExcelValue forecast(ExcelValue required_x, ExcelValue known_y, ExcelValue known_x);
|
67
70
|
static ExcelValue large(ExcelValue array_v, ExcelValue k_v);
|
68
71
|
static ExcelValue left(ExcelValue string_v, ExcelValue number_of_characters_v);
|
69
72
|
static ExcelValue left_1(ExcelValue string_v);
|
@@ -399,6 +402,74 @@ static ExcelValue average(int array_size, ExcelValue *array) {
|
|
399
402
|
return new_excel_number(r.sum/r.count);
|
400
403
|
}
|
401
404
|
|
405
|
+
static ExcelValue forecast(ExcelValue required_x_v, ExcelValue known_y, ExcelValue known_x) {
|
406
|
+
CHECK_FOR_PASSED_ERROR(required_x_v)
|
407
|
+
|
408
|
+
NUMBER(required_x_v, required_x)
|
409
|
+
CHECK_FOR_CONVERSION_ERROR
|
410
|
+
|
411
|
+
if(known_x.type != ExcelRange) { return NA; }
|
412
|
+
if(known_y.type != ExcelRange) { return NA; }
|
413
|
+
|
414
|
+
int known_x_size = known_x.rows * known_x.columns;
|
415
|
+
int known_y_size = known_y.rows * known_y.columns;
|
416
|
+
|
417
|
+
int i;
|
418
|
+
ExcelValue *x_array, *y_array;
|
419
|
+
ExcelValue vx, vy;
|
420
|
+
|
421
|
+
x_array = known_x.array;
|
422
|
+
y_array = known_y.array;
|
423
|
+
|
424
|
+
for(i=0; i<known_x_size; i++) {
|
425
|
+
vx = x_array[i];
|
426
|
+
if(vx.type == ExcelError) {
|
427
|
+
return vx;
|
428
|
+
}
|
429
|
+
}
|
430
|
+
|
431
|
+
for(i=0; i<known_x_size; i++) {
|
432
|
+
vy = y_array[i];
|
433
|
+
if(vy.type == ExcelError) {
|
434
|
+
return vy;
|
435
|
+
}
|
436
|
+
}
|
437
|
+
|
438
|
+
if(known_x_size != known_y_size) { return NA; }
|
439
|
+
if(known_x_size == 0) { return NA; }
|
440
|
+
|
441
|
+
ExcelValue mean_y = average(1, &known_y);
|
442
|
+
ExcelValue mean_x = average(1, &known_x);
|
443
|
+
|
444
|
+
if(mean_y.type == ExcelError) { return mean_y; }
|
445
|
+
if(mean_x.type == ExcelError) { return mean_x; }
|
446
|
+
|
447
|
+
float mx = mean_x.number;
|
448
|
+
float my = mean_y.number;
|
449
|
+
|
450
|
+
float b_numerator, b_denominator, b, a;
|
451
|
+
|
452
|
+
b_denominator = 0;
|
453
|
+
b_numerator = 0;
|
454
|
+
|
455
|
+
for(i=0; i<known_x_size; i++) {
|
456
|
+
vx = x_array[i];
|
457
|
+
vy = y_array[i];
|
458
|
+
if(vx.type != ExcelNumber) { continue; }
|
459
|
+
if(vy.type != ExcelNumber) { continue; }
|
460
|
+
|
461
|
+
b_denominator = b_denominator + pow(vx.number - mx, 2);
|
462
|
+
b_numerator = b_numerator + ((vx.number - mx)*(vy.number-my));
|
463
|
+
}
|
464
|
+
|
465
|
+
if(b_denominator == 0) { return DIV0; }
|
466
|
+
|
467
|
+
b = b_numerator / b_denominator;
|
468
|
+
a = mean_y.number - (b*mean_x.number);
|
469
|
+
|
470
|
+
return new_excel_number(a + (b*required_x));
|
471
|
+
}
|
472
|
+
|
402
473
|
static ExcelValue choose(ExcelValue index_v, int array_size, ExcelValue *array) {
|
403
474
|
CHECK_FOR_PASSED_ERROR(index_v)
|
404
475
|
|
@@ -1419,24 +1490,29 @@ static ExcelValue subtotal(ExcelValue subtotal_type_v, int number_of_arguments,
|
|
1419
1490
|
}
|
1420
1491
|
}
|
1421
1492
|
|
1422
|
-
|
1423
|
-
|
1424
|
-
|
1493
|
+
|
1494
|
+
static ExcelValue filter_range(ExcelValue original_range_v, int number_of_arguments, ExcelValue *arguments) {
|
1495
|
+
// First, set up the original_range
|
1496
|
+
CHECK_FOR_PASSED_ERROR(original_range_v);
|
1425
1497
|
|
1426
1498
|
// Set up the sum range
|
1427
|
-
ExcelValue *
|
1428
|
-
int
|
1499
|
+
ExcelValue *original_range;
|
1500
|
+
int original_range_rows, original_range_columns;
|
1429
1501
|
|
1430
|
-
if(
|
1431
|
-
|
1432
|
-
|
1433
|
-
|
1502
|
+
if(original_range_v.type == ExcelRange) {
|
1503
|
+
original_range = original_range_v.array;
|
1504
|
+
original_range_rows = original_range_v.rows;
|
1505
|
+
original_range_columns = original_range_v.columns;
|
1434
1506
|
} else {
|
1435
|
-
|
1436
|
-
|
1437
|
-
|
1438
|
-
|
1507
|
+
original_range = (ExcelValue*) new_excel_value_array(1);
|
1508
|
+
original_range[0] = original_range_v;
|
1509
|
+
original_range_rows = 1;
|
1510
|
+
original_range_columns = 1;
|
1439
1511
|
}
|
1512
|
+
|
1513
|
+
// This is the filtered range
|
1514
|
+
ExcelValue *filtered_range = new_excel_value_array(original_range_rows*original_range_columns);
|
1515
|
+
int number_of_filtered_values = 0;
|
1440
1516
|
|
1441
1517
|
// Then go through and set up the check ranges
|
1442
1518
|
if(number_of_arguments % 2 != 0) return VALUE;
|
@@ -1448,11 +1524,11 @@ static ExcelValue sumifs(ExcelValue sum_range_v, int number_of_arguments, ExcelV
|
|
1448
1524
|
current_value = arguments[i*2];
|
1449
1525
|
if(current_value.type == ExcelRange) {
|
1450
1526
|
criteria_range[i] = current_value;
|
1451
|
-
if(current_value.rows !=
|
1452
|
-
if(current_value.columns !=
|
1527
|
+
if(current_value.rows != original_range_rows) return VALUE;
|
1528
|
+
if(current_value.columns != original_range_columns) return VALUE;
|
1453
1529
|
} else {
|
1454
|
-
if(
|
1455
|
-
if(
|
1530
|
+
if(original_range_rows != 1) return VALUE;
|
1531
|
+
if(original_range_columns != 1) return VALUE;
|
1456
1532
|
ExcelValue *tmp_array2 = (ExcelValue*) new_excel_value_array(1);
|
1457
1533
|
tmp_array2[0] = current_value;
|
1458
1534
|
criteria_range[i] = new_excel_range(tmp_array2,1,1);
|
@@ -1503,8 +1579,7 @@ static ExcelValue sumifs(ExcelValue sum_range_v, int number_of_arguments, ExcelV
|
|
1503
1579
|
}
|
1504
1580
|
}
|
1505
1581
|
|
1506
|
-
|
1507
|
-
int size = sum_range_columns * sum_range_rows;
|
1582
|
+
int size = original_range_columns * original_range_rows;
|
1508
1583
|
int j;
|
1509
1584
|
int passed = 0;
|
1510
1585
|
ExcelValue value_to_be_checked;
|
@@ -1628,17 +1703,28 @@ static ExcelValue sumifs(ExcelValue sum_range_v, int number_of_arguments, ExcelV
|
|
1628
1703
|
if(passed == 0) break;
|
1629
1704
|
}
|
1630
1705
|
if(passed == 1) {
|
1631
|
-
current_value =
|
1706
|
+
current_value = original_range[j];
|
1632
1707
|
if(current_value.type == ExcelError) {
|
1633
1708
|
return current_value;
|
1634
1709
|
} else if(current_value.type == ExcelNumber) {
|
1635
|
-
|
1710
|
+
filtered_range[number_of_filtered_values] = current_value;
|
1711
|
+
number_of_filtered_values += 1;
|
1636
1712
|
}
|
1637
1713
|
}
|
1638
1714
|
}
|
1639
1715
|
// Tidy up
|
1640
1716
|
free(criteria);
|
1641
|
-
return
|
1717
|
+
return new_excel_range(filtered_range, number_of_filtered_values, 1);
|
1718
|
+
}
|
1719
|
+
|
1720
|
+
static ExcelValue sumifs(ExcelValue sum_range_v, int number_of_arguments, ExcelValue *arguments) {
|
1721
|
+
ExcelValue filtered_range = filter_range(sum_range_v, number_of_arguments, arguments);
|
1722
|
+
return sum(1,&filtered_range);
|
1723
|
+
}
|
1724
|
+
|
1725
|
+
static ExcelValue averageifs(ExcelValue average_range_v, int number_of_arguments, ExcelValue *arguments) {
|
1726
|
+
ExcelValue filtered_range = filter_range(average_range_v, number_of_arguments, arguments);
|
1727
|
+
return average(1,&filtered_range);
|
1642
1728
|
}
|
1643
1729
|
|
1644
1730
|
static ExcelValue sumif(ExcelValue check_range_v, ExcelValue criteria_v, ExcelValue sum_range_v ) {
|
@@ -762,6 +762,83 @@ int test_functions() {
|
|
762
762
|
assert(excel_isblank(TRUE).number == false);
|
763
763
|
assert(excel_isblank(FALSE).number == false);
|
764
764
|
assert(excel_isblank(new_excel_string("")).number == false);
|
765
|
+
|
766
|
+
// Test AVERAGEIFS function
|
767
|
+
ExcelValue averageifs_array_1[] = {new_excel_number(10),new_excel_number(100),BLANK};
|
768
|
+
ExcelValue averageifs_array_1_v = new_excel_range(averageifs_array_1,3,1);
|
769
|
+
ExcelValue averageifs_array_2[] = {new_excel_string("pear"),new_excel_string("bear"),new_excel_string("apple")};
|
770
|
+
ExcelValue averageifs_array_2_v = new_excel_range(averageifs_array_2,3,1);
|
771
|
+
ExcelValue averageifs_array_3[] = {new_excel_number(1),new_excel_number(2),new_excel_number(3),new_excel_number(4),new_excel_number(5),new_excel_number(5)};
|
772
|
+
ExcelValue averageifs_array_3_v = new_excel_range(averageifs_array_3,6,1);
|
773
|
+
ExcelValue averageifs_array_4[] = {new_excel_string("CO2"),new_excel_string("CH4"),new_excel_string("N2O"),new_excel_string("CH4"),new_excel_string("N2O"),new_excel_string("CO2")};
|
774
|
+
ExcelValue averageifs_array_4_v = new_excel_range(averageifs_array_4,6,1);
|
775
|
+
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
|
+
ExcelValue averageifs_array_5_v = new_excel_range(averageifs_array_5,6,1);
|
777
|
+
|
778
|
+
// ... should only average values that meet all of the criteria
|
779
|
+
ExcelValue averageifs_array_6[] = { averageifs_array_1_v, new_excel_number(10), averageifs_array_2_v, new_excel_string("Bear") };
|
780
|
+
assert(averageifs(averageifs_array_1_v,4,averageifs_array_6).type == ExcelError);
|
781
|
+
|
782
|
+
ExcelValue averageifs_array_7[] = { averageifs_array_1_v, new_excel_number(10), averageifs_array_2_v, new_excel_string("Pear") };
|
783
|
+
assert(averageifs(averageifs_array_1_v,4,averageifs_array_7).number == 10.0);
|
784
|
+
|
785
|
+
// ... should work when single cells are given where ranges expected
|
786
|
+
ExcelValue averageifs_array_8[] = { new_excel_string("CAR"), new_excel_string("CAR"), new_excel_string("FCV"), new_excel_string("FCV")};
|
787
|
+
assert(averageifs(new_excel_number(0.143897265452564), 4, averageifs_array_8).number == 0.143897265452564);
|
788
|
+
|
789
|
+
// ... should match numbers with strings that contain numbers
|
790
|
+
ExcelValue averageifs_array_9[] = { new_excel_number(10), new_excel_string("10.0")};
|
791
|
+
assert(averageifs(new_excel_number(100),2,averageifs_array_9).number == 100);
|
792
|
+
|
793
|
+
ExcelValue averageifs_array_10[] = { averageifs_array_4_v, new_excel_string("CO2"), averageifs_array_5_v, new_excel_number(2)};
|
794
|
+
assert(averageifs(averageifs_array_3_v,4, averageifs_array_10).type == ExcelError);
|
795
|
+
|
796
|
+
// ... should match with strings that contain criteria
|
797
|
+
ExcelValue averageifs_array_10a[] = { averageifs_array_3_v, new_excel_string("=5")};
|
798
|
+
assert(averageifs(averageifs_array_3_v,2, averageifs_array_10a).number == 5);
|
799
|
+
|
800
|
+
ExcelValue averageifs_array_10b[] = { averageifs_array_3_v, new_excel_string("<>3")};
|
801
|
+
assert(averageifs(averageifs_array_3_v,2, averageifs_array_10b).number == 3.4);
|
802
|
+
|
803
|
+
ExcelValue averageifs_array_10c[] = { averageifs_array_3_v, new_excel_string("<3")};
|
804
|
+
assert(averageifs(averageifs_array_3_v,2, averageifs_array_10c).number == 1.5);
|
805
|
+
|
806
|
+
ExcelValue averageifs_array_10d[] = { averageifs_array_3_v, new_excel_string("<=3")};
|
807
|
+
assert(averageifs(averageifs_array_3_v,2, averageifs_array_10d).number == 2);
|
808
|
+
|
809
|
+
ExcelValue averageifs_array_10e[] = { averageifs_array_3_v, new_excel_string(">3")};
|
810
|
+
assert(averageifs(averageifs_array_3_v,2, averageifs_array_10e).number == 14.0/3.0);
|
811
|
+
|
812
|
+
ExcelValue averageifs_array_10f[] = { averageifs_array_3_v, new_excel_string(">=3")};
|
813
|
+
assert(averageifs(averageifs_array_3_v,2, averageifs_array_10f).number == (3.0+4.0+5.0+5.0)/4.0);
|
814
|
+
|
815
|
+
// ... should treat BLANK as an empty string when in the check_range, but not in the criteria
|
816
|
+
ExcelValue averageifs_array_11[] = { BLANK, new_excel_number(20)};
|
817
|
+
assert(averageifs(new_excel_number(100),2,averageifs_array_11).type == ExcelError);
|
818
|
+
|
819
|
+
ExcelValue averageifs_array_12[] = {BLANK, new_excel_string("")};
|
820
|
+
assert(averageifs(new_excel_number(100),2,averageifs_array_12).number == 100);
|
821
|
+
|
822
|
+
ExcelValue averageifs_array_13[] = {BLANK, BLANK};
|
823
|
+
assert(averageifs(new_excel_number(100),2,averageifs_array_13).type == ExcelError);
|
824
|
+
|
825
|
+
// ... should return an error if range argument is an error
|
826
|
+
assert(averageifs(REF,2,averageifs_array_13).type == ExcelError);
|
827
|
+
|
828
|
+
// Tests for the FORECAST function
|
829
|
+
ExcelValue forecast_array1[] = { new_excel_number(1), new_excel_number(2), new_excel_number(3), new_excel_number(4), new_excel_number(5)};
|
830
|
+
ExcelValue forecast_array2[] = { new_excel_number(2), new_excel_number(3), new_excel_number(4), new_excel_number(5), new_excel_number(6)};
|
831
|
+
ExcelValue forecast_array1_v = new_excel_range(forecast_array1,5,1);
|
832
|
+
ExcelValue forecast_array2_v = new_excel_range(forecast_array2,5,1);
|
833
|
+
|
834
|
+
assert(forecast(new_excel_number(0), forecast_array2_v, forecast_array1_v).number == 1);
|
835
|
+
assert(forecast(new_excel_number(1), forecast_array2_v, forecast_array1_v).number == 2);
|
836
|
+
assert(forecast(new_excel_number(6), forecast_array2_v, forecast_array1_v).number == 7);
|
837
|
+
|
838
|
+
ExcelValue forecast_array3[] = { BLANK, new_excel_number(2), new_excel_number(3), new_excel_number(4), BLANK};
|
839
|
+
ExcelValue forecast_array3_v = new_excel_range(forecast_array3,5,1);
|
840
|
+
|
841
|
+
assert(forecast(new_excel_number(6), forecast_array2_v, forecast_array3_v).number == 7);
|
765
842
|
|
766
843
|
// Release memory
|
767
844
|
free_all_allocated_memory();
|
@@ -30,6 +30,7 @@ class MapFormulaeToC < MapValuesToC
|
|
30
30
|
:'ABS' => 'excel_abs',
|
31
31
|
:'AND' => 'excel_and',
|
32
32
|
:'AVERAGE' => 'average',
|
33
|
+
:'AVERAGEIFS' => 'averageifs',
|
33
34
|
:'CHOOSE' => 'choose',
|
34
35
|
:'CONCATENATE' => 'string_join',
|
35
36
|
:'COSH' => 'cosh',
|
@@ -38,6 +39,7 @@ class MapFormulaeToC < MapValuesToC
|
|
38
39
|
:'EXP' => 'excel_exp',
|
39
40
|
:'FIND2' => 'find_2',
|
40
41
|
:'FIND3' => 'find',
|
42
|
+
:'FORECAST' => 'forecast',
|
41
43
|
:'HLOOKUP3' => 'hlookup_3',
|
42
44
|
:'HLOOKUP4' => 'hlookup',
|
43
45
|
:'IF2' => 'excel_if_2',
|
@@ -142,6 +144,10 @@ class MapFormulaeToC < MapValuesToC
|
|
142
144
|
"#{FUNCTIONS[:SUMIFS]}(#{map(sum_range)}, #{map_arguments_to_array(criteria)})"
|
143
145
|
end
|
144
146
|
|
147
|
+
def function_averageifs(average_range,*criteria)
|
148
|
+
"#{FUNCTIONS[:AVERAGEIFS]}(#{map(average_range)}, #{map_arguments_to_array(criteria)})"
|
149
|
+
end
|
150
|
+
|
145
151
|
|
146
152
|
def any_number_of_argument_function(function_name,arguments)
|
147
153
|
"#{FUNCTIONS[function_name.to_sym]}(#{map_arguments_to_array(arguments)})"
|
@@ -19,6 +19,7 @@ class MapFormulaeToRuby < MapValuesToRuby
|
|
19
19
|
:'ABS' => 'abs',
|
20
20
|
:'AND' => 'excel_and',
|
21
21
|
:'AVERAGE' => 'average',
|
22
|
+
:'AVERAGEIFS' => 'averageifs',
|
22
23
|
:'CELL' => 'cell',
|
23
24
|
:'CHOOSE' => 'choose',
|
24
25
|
:'CONCATENATE' => 'string_join',
|
@@ -27,6 +28,7 @@ class MapFormulaeToRuby < MapValuesToRuby
|
|
27
28
|
:'COUNTA' => 'counta',
|
28
29
|
:'EXP' => 'exp',
|
29
30
|
:'FIND' => 'find',
|
31
|
+
:'FORECAST' => 'forecast',
|
30
32
|
:'HLOOKUP' => 'hlookup',
|
31
33
|
:'IF' => 'excel_if',
|
32
34
|
:'IFERROR' => 'iferror',
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module ExcelFunctions
|
2
|
+
|
3
|
+
def averageifs(average_range, *criteria)
|
4
|
+
# First, get rid of the errors
|
5
|
+
return average_range if average_range.is_a?(Symbol)
|
6
|
+
error = criteria.find { |a| a.is_a?(Symbol) }
|
7
|
+
return error if error
|
8
|
+
|
9
|
+
# Sort out the average range
|
10
|
+
average_range = [average_range] unless average_range.is_a?(Array)
|
11
|
+
average_range = average_range.flatten
|
12
|
+
|
13
|
+
# Sort out the criteria
|
14
|
+
0.step(criteria.length-1,2).each do |i|
|
15
|
+
if criteria[i].is_a?(Array)
|
16
|
+
criteria[i] = criteria[i].flatten
|
17
|
+
else
|
18
|
+
criteria[i] = [criteria[i]]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# This will hold the items that pass the test
|
23
|
+
accumulator = []
|
24
|
+
|
25
|
+
# Work through each part of the average range
|
26
|
+
average_range.each_with_index do |potential_average,index|
|
27
|
+
next unless potential_average.is_a?(Numeric)
|
28
|
+
|
29
|
+
# If a criteria fails, this is set to false and no further criteria are evaluated
|
30
|
+
pass = true
|
31
|
+
|
32
|
+
0.step(criteria.length-1,2).each do |i|
|
33
|
+
check_range = criteria[i]
|
34
|
+
required_value = criteria[i+1]
|
35
|
+
return :value if index >= check_range.length
|
36
|
+
check_value = check_range[index]
|
37
|
+
|
38
|
+
pass = case check_value
|
39
|
+
when String
|
40
|
+
check_value.downcase == required_value.to_s.downcase
|
41
|
+
when true, false
|
42
|
+
check_value == required_value
|
43
|
+
when nil
|
44
|
+
required_value == ""
|
45
|
+
when Numeric
|
46
|
+
case required_value
|
47
|
+
when Numeric
|
48
|
+
check_value == required_value
|
49
|
+
when String
|
50
|
+
required_value =~ /^(<=|>=|<|>)?([-+]?[0-9]+\.?[0-9]*([eE][-+]?[0-9]+)?)$/
|
51
|
+
if $1 && $2
|
52
|
+
check_value.send($1,$2.to_f)
|
53
|
+
elsif $2
|
54
|
+
check_value == $2.to_f
|
55
|
+
else
|
56
|
+
false
|
57
|
+
end
|
58
|
+
else
|
59
|
+
check_value == required_value
|
60
|
+
end
|
61
|
+
end # case check_value
|
62
|
+
|
63
|
+
break unless pass
|
64
|
+
end # criteria loop
|
65
|
+
|
66
|
+
accumulator << potential_average if pass
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
accumulator.delete_if { |a| !a.is_a?(Numeric) }
|
71
|
+
return :div0 if accumulator.empty?
|
72
|
+
accumulator.inject(0.0) { |m,i| m + i.to_f } / accumulator.size.to_f
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module ExcelFunctions
|
2
|
+
|
3
|
+
def forecast(required_x, known_y, known_x)
|
4
|
+
required_x = number_argument(required_x)
|
5
|
+
return required_x if required_x.is_a?(Symbol)
|
6
|
+
return :na unless known_y.is_a?(Array)
|
7
|
+
return :na unless known_x.is_a?(Array)
|
8
|
+
known_y = known_y.flatten
|
9
|
+
known_x = known_x.flatten
|
10
|
+
known_y.each { |y| return y if y.is_a?(Symbol) }
|
11
|
+
known_x.each { |x| return x if x.is_a?(Symbol) }
|
12
|
+
return :na unless known_x.length == known_y.length
|
13
|
+
return :na if known_y.empty?
|
14
|
+
return :na if known_x.empty?
|
15
|
+
|
16
|
+
0.upto(known_x.length-1).each do |i|
|
17
|
+
known_x[i] = nil unless known_y[i].is_a?(Numeric)
|
18
|
+
known_y[i] = nil unless known_x[i].is_a?(Numeric)
|
19
|
+
end
|
20
|
+
|
21
|
+
known_x.compact!
|
22
|
+
known_y.compact!
|
23
|
+
|
24
|
+
mean_y = known_y.inject(0.0) { |m,i| m + i.to_f } / known_y.size.to_f
|
25
|
+
mean_x = known_x.inject(0.0) { |m,i| m + i.to_f } / known_x.size.to_f
|
26
|
+
|
27
|
+
b_denominator = known_x.inject(0.0) { |s,x| x.is_a?(Numeric) ? (s + (x-mean_x)**2 ) : s }
|
28
|
+
return :div0 if b_denominator == 0
|
29
|
+
b_numerator = 0.0
|
30
|
+
known_x.each.with_index do |x,i|
|
31
|
+
y = known_y[i]
|
32
|
+
next unless x.is_a?(Numeric)
|
33
|
+
next unless y.is_a?(Numeric)
|
34
|
+
b_numerator = b_numerator + ((x-mean_x)*(y-mean_y))
|
35
|
+
end
|
36
|
+
|
37
|
+
b = b_numerator / b_denominator
|
38
|
+
|
39
|
+
a = mean_y - (b * mean_x)
|
40
|
+
|
41
|
+
return a + (b*required_x)
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
data/src/excel_to_code.rb
CHANGED
@@ -1,7 +1,11 @@
|
|
1
|
+
class ExcelToCode
|
2
|
+
def self.version() "0.2.11" end
|
3
|
+
end
|
4
|
+
|
1
5
|
require_relative 'commands'
|
2
6
|
require_relative 'compile'
|
3
7
|
require_relative 'excel'
|
4
8
|
require_relative 'extract'
|
5
9
|
require_relative 'rewrite'
|
6
10
|
require_relative 'simplify'
|
7
|
-
require_relative 'util'
|
11
|
+
require_relative 'util'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: excel_to_code
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thomas Counsell, Green on Black Ltd
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-02-
|
11
|
+
date: 2014-02-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubypeg
|
@@ -142,6 +142,7 @@ files:
|
|
142
142
|
- src/excel/excel_functions/and.rb
|
143
143
|
- src/excel/excel_functions/apply_to_range.rb
|
144
144
|
- src/excel/excel_functions/average.rb
|
145
|
+
- src/excel/excel_functions/averageifs.rb
|
145
146
|
- src/excel/excel_functions/cell.rb
|
146
147
|
- src/excel/excel_functions/choose.rb
|
147
148
|
- src/excel/excel_functions/cosh.rb
|
@@ -153,6 +154,7 @@ files:
|
|
153
154
|
- src/excel/excel_functions/excel_match.rb
|
154
155
|
- src/excel/excel_functions/exp.rb
|
155
156
|
- src/excel/excel_functions/find.rb
|
157
|
+
- src/excel/excel_functions/forecast.rb
|
156
158
|
- src/excel/excel_functions/hlookup.rb
|
157
159
|
- src/excel/excel_functions/iferror.rb
|
158
160
|
- src/excel/excel_functions/index.rb
|