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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d131943e44d296b38b2b2f52d4e710fb72b3290c
4
- data.tar.gz: 1ced79386e0e176fb515794fb5026a4779d56c2a
3
+ metadata.gz: a444173d8318385277afd731b47cedcb7fe2b783
4
+ data.tar.gz: 13c5f6fa4d20cc45730c9c15f736c68c17a810af
5
5
  SHA512:
6
- metadata.gz: 90c8c2c66e70b2beb0073a904d02c70444d3881bce4b570fe681a99098597319cee266611282f6789326efaf9a69198c85750633392c5aeae4fed329bfc7c521
7
- data.tar.gz: 39325a065501520c32b29be75d0af212c498c8d8d2baf580e1a0e585b2841fa6610679a1298d2dbe86ab5bf6269821612b97ce969b1d178a514ea16ef4831e94
6
+ metadata.gz: 201c1f56ae3807bce72ca38c48f78300f2c1c6a2857e2ddf58e111dfe9a64660d0cfc4bf453fe9eb817a8d5c1719e60fb19943b998f5342aea9f9d0873c5d79e
7
+ data.tar.gz: 9945c873cfc1d3e76f6fff18c8fd43ad38f3862efcd24c16e8eccc53670d247fe8d00792d920fd86efe8732f86c2be1b2cdb0db998af112f68ed10081bd6e358
@@ -4,6 +4,7 @@ require_relative '../src/excel_to_code'
4
4
 
5
5
  command = ExcelToC.new
6
6
 
7
+ #FIXME: Add a version option
7
8
  opts = OptionParser.new do |opts|
8
9
  opts.banner = <<-END
9
10
 
@@ -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
- puts
485
- puts "The following functions have not been implemented in excel_to_code. Please see https://github.com/tamc/excel_to_code/blob/master/doc/How_to_add_a_missing_function.md"
486
- puts functions_used
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
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
- static ExcelValue sumifs(ExcelValue sum_range_v, int number_of_arguments, ExcelValue *arguments) {
1423
- // First, set up the sum_range
1424
- CHECK_FOR_PASSED_ERROR(sum_range_v);
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 *sum_range;
1428
- int sum_range_rows, sum_range_columns;
1499
+ ExcelValue *original_range;
1500
+ int original_range_rows, original_range_columns;
1429
1501
 
1430
- if(sum_range_v.type == ExcelRange) {
1431
- sum_range = sum_range_v.array;
1432
- sum_range_rows = sum_range_v.rows;
1433
- sum_range_columns = sum_range_v.columns;
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
- sum_range = (ExcelValue*) new_excel_value_array(1);
1436
- sum_range[0] = sum_range_v;
1437
- sum_range_rows = 1;
1438
- sum_range_columns = 1;
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 != sum_range_rows) return VALUE;
1452
- if(current_value.columns != sum_range_columns) return VALUE;
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(sum_range_rows != 1) return VALUE;
1455
- if(sum_range_columns != 1) return VALUE;
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
- double total = 0;
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 = sum_range[j];
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
- total += current_value.number;
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 new_excel_number(total);
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',
@@ -100,3 +100,7 @@ require_relative 'excel_functions/lower'
100
100
  require_relative 'excel_functions/exp'
101
101
 
102
102
  require_relative 'excel_functions/isblank'
103
+
104
+ require_relative 'excel_functions/averageifs'
105
+
106
+ require_relative 'excel_functions/forecast'
@@ -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
@@ -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.10
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-01 00:00:00.000000000 Z
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