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 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