excel_to_code 0.2.10 → 0.2.11
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 +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
|