excel_to_code 0.3.3 → 0.3.4

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: 0663c5e494db3faed27a118aa4cce8b2b5095655
4
- data.tar.gz: 0aab1b24a30a1cea9a91ebdc0fed82f84bc3ec59
3
+ metadata.gz: 9a337c16718282fa8bbce1da4a51cb81d2ad6651
4
+ data.tar.gz: fbfa6de417b5b4f8fe626244b234876cd00f430c
5
5
  SHA512:
6
- metadata.gz: 401103eb0a1c639486412b7c735d322bbb060ddb1ebdc83d973a810e330e1e412070dd4b96f423ab9b5502c1ba2eb02ba73f19634fe4a176a443243d3802a66b
7
- data.tar.gz: c746f24035da13f0e34581b48df68ae7fe7f4ddb2ccae54a320692a729cf8c0ae0cf9cc95a89ba5cfd98bba5f0e26aa8a8acbf8f474a21e963a111fa858932e3
6
+ metadata.gz: cf150004e0ad6ad4cf8d17d4abc740c4b5e33e3224c39091a2d9b9edc65d4e66de2ba047446c9cbc04fe7c33f680ed156300dc10ca568f38e7c6e97a70896a7e
7
+ data.tar.gz: 28bbe1191e5da2bbcbc63d4bda866f6f1720c619212659d6aeaece6c9e21baa7597b95ec7e6d77718895ff9bed54f9cc07c4cd5674a8918fb73874ebfbd12044
data/README.md CHANGED
@@ -48,3 +48,4 @@ There are some how to guides in the doc folder.
48
48
  7. Newlines are removed from strings
49
49
  8. The generated code uses floating point, rather than fully precise arithmetic, so results can differ slightly
50
50
  9. The generated code uses the sprintf approach to rounding (even-odd) rather than excel's 0.5 rounds away from zero.
51
+ 10. Ranges like this: Sheet1!A10:Sheet1!B20 and 3D ranges don't work
@@ -380,9 +380,8 @@ END
380
380
  return unless actually_compile_code || actually_run_tests
381
381
  name = output_name.downcase
382
382
  log.info "Compiling"
383
- puts `cd #{output_directory}`
384
- puts `gcc -fPIC -o #{name}.o -c #{name}.c`
385
- puts `gcc -shared -fPIC -o #{FFI.map_library_name(name)} #{name}.o`
383
+ puts `gcc -fPIC -o #{File.join(output_directory, name)}.o -c #{File.join(output_directory, name)}.c`
384
+ puts `gcc -shared -fPIC -o #{File.join(output_directory, FFI.map_library_name(name))} #{File.join(output_directory, name)}.o`
386
385
  end
387
386
 
388
387
  def run_tests
@@ -142,6 +142,7 @@ class ExcelToX
142
142
  # format and refer to sheets and references that actually exist
143
143
  clean_cells_that_can_be_set_at_runtime
144
144
  clean_cells_to_keep
145
+ convert_named_references_into_simple_form
145
146
  clean_named_references_to_keep
146
147
  clean_named_references_that_can_be_set_at_runtime
147
148
 
@@ -308,11 +309,22 @@ class ExcelToX
308
309
  raise
309
310
  end
310
311
  end
312
+
313
+ end
314
+
315
+ # Named references can be simple cell references,
316
+ # or they can be ranges, or errors, or table references
317
+ # this function converts all the different types into
318
+ # arrays of cell references
319
+ def convert_named_references_into_simple_form
311
320
  # Replace A$1:B2 with [A1, A2, B1, B2]
312
321
  @replace_ranges_with_array_literals_replacer ||= ReplaceRangesWithArrayLiteralsAst.new
322
+ table_reference_replacer = ReplaceTableReferenceAst.new(@tables)
313
323
 
314
324
  @named_references.each do |name, reference|
315
- @named_references[name] = @replace_ranges_with_array_literals_replacer.map(reference)
325
+ reference = table_reference_replacer.map(reference)
326
+ reference = @replace_ranges_with_array_literals_replacer.map(reference)
327
+ @named_references[name] = reference
316
328
  end
317
329
 
318
330
  end
data/src/compile/c/a.out CHANGED
Binary file
@@ -83,6 +83,7 @@ static ExcelValue min(int number_of_arguments, ExcelValue *arguments);
83
83
  static ExcelValue mmult(ExcelValue a_v, ExcelValue b_v);
84
84
  static ExcelValue mod(ExcelValue a_v, ExcelValue b_v);
85
85
  static ExcelValue negative(ExcelValue a_v);
86
+ static ExcelValue npv(ExcelValue rate, int number_of_arguments, ExcelValue *arguments);
86
87
  static ExcelValue pmt(ExcelValue rate_v, ExcelValue number_of_periods_v, ExcelValue present_value_v);
87
88
  static ExcelValue power(ExcelValue a_v, ExcelValue b_v);
88
89
  static ExcelValue pv_3(ExcelValue a_v, ExcelValue b_v, ExcelValue c_v);
@@ -1310,6 +1311,44 @@ static ExcelValue sum(int array_size, ExcelValue *array) {
1310
1311
  return new_excel_number(total);
1311
1312
  }
1312
1313
 
1314
+ static ExcelValue npv(ExcelValue rate_v, int number_of_arguments, ExcelValue *arguments) {
1315
+ CHECK_FOR_PASSED_ERROR(rate_v)
1316
+ NUMBER(rate_v, rate)
1317
+ CHECK_FOR_CONVERSION_ERROR
1318
+ if(rate == -1) { return DIV0; }
1319
+
1320
+ double npv = 0;
1321
+ int n = 1;
1322
+ int i;
1323
+ int j;
1324
+ double v;
1325
+ ExcelValue r;
1326
+ ExcelValue r2;
1327
+ ExcelValue *range;
1328
+
1329
+ for(i=0;i<number_of_arguments;i++) {
1330
+ r = arguments[i];
1331
+ if(r.type == ExcelError) { return r; }
1332
+ if(r.type == ExcelRange) {
1333
+ range = r.array;
1334
+ for(j=0;j<(r.columns*r.rows);j++) {
1335
+ r2 = range[j];
1336
+ if(r2.type == ExcelError) { return r2; }
1337
+ v = number_from(r2);
1338
+ if(conversion_error) { conversion_error = 0; return VALUE; }
1339
+ npv = npv + (v/pow(1+rate, n));
1340
+ n++;
1341
+ }
1342
+ } else {
1343
+ v = number_from(r);
1344
+ if(conversion_error) { conversion_error = 0; return VALUE; }
1345
+ npv = npv + (v/pow(1+rate, n));
1346
+ n++;
1347
+ }
1348
+ }
1349
+ return new_excel_number(npv);
1350
+ }
1351
+
1313
1352
  static ExcelValue max(int number_of_arguments, ExcelValue *arguments) {
1314
1353
  double biggest_number_found;
1315
1354
  int any_number_found = 0;
@@ -959,6 +959,27 @@ int test_functions() {
959
959
  assert(value(new_excel_string("1")).number == 1);
960
960
  assert(value(new_excel_string("A1A")).type == ExcelError);
961
961
 
962
+
963
+ // NPV(rate, flow1, flow2)
964
+ ExcelValue npv_array1[] = { new_excel_number(110) };
965
+ assert(npv(new_excel_number(0.1), 1, npv_array1).type == ExcelNumber);
966
+ assert(npv(new_excel_number(0.1), 1, npv_array1).number-100 < 0.001);
967
+
968
+ ExcelValue npv_array2[] = { new_excel_number(110), new_excel_number(121) };
969
+ assert((npv(new_excel_number(0.1), 2, npv_array2).number - 200) < 0.001);
970
+
971
+ ExcelValue npv_array3[] = { new_excel_number(110), new_excel_number(121)};
972
+ ExcelValue npv_array3_v = new_excel_range(npv_array3,2,1);
973
+ ExcelValue npv_array4[] = { npv_array3_v };
974
+
975
+ assert((npv(new_excel_number(0.1), 1, npv_array4).number - 200) < 0.001);
976
+
977
+ assert(npv(new_excel_number(-1.0), 1, npv_array1).type == ExcelError);
978
+ assert(npv(BLANK, 1, npv_array1).number == 110);
979
+
980
+ ExcelValue npv_array5[] = { BLANK };
981
+ assert(npv(new_excel_number(0.1), 1, npv_array5).number == 0);
982
+
962
983
  // Release memory
963
984
  free_all_allocated_memory();
964
985
 
@@ -66,6 +66,7 @@ class MapFormulaeToC < MapValuesToC
66
66
  :'MIN' => 'min',
67
67
  :'MMULT' => 'mmult',
68
68
  :'MOD' => 'mod',
69
+ :'NPV' => 'npv',
69
70
  :'PMT' => 'pmt',
70
71
  :'PV3' => 'pv_3',
71
72
  :'PV4' => 'pv_4',
@@ -156,6 +157,10 @@ class MapFormulaeToC < MapValuesToC
156
157
  "#{FUNCTIONS[:AVERAGEIFS]}(#{map(average_range)}, #{map_arguments_to_array(criteria)})"
157
158
  end
158
159
 
160
+ def function_npv(rate,*cash_flows)
161
+ "#{FUNCTIONS[:NPV]}(#{map(rate)}, #{map_arguments_to_array(cash_flows)})"
162
+ end
163
+
159
164
  def function_if(condition, true_case, false_case = [:boolean_false])
160
165
  true_code = map(true_case)
161
166
  false_code = map(false_case)
@@ -51,6 +51,7 @@ class MapFormulaeToRuby < MapValuesToRuby
51
51
  :'MIN' => 'min',
52
52
  :'MMULT' => 'mmult',
53
53
  :'MOD' => 'mod',
54
+ :'NPV' => 'npv',
54
55
  :'PI' => 'pi',
55
56
  :'PMT' => 'pmt',
56
57
  :'POWER' => 'power',
@@ -113,3 +113,5 @@ require_relative 'excel_functions/value'
113
113
  require_relative 'excel_functions/ln'
114
114
 
115
115
  require_relative 'excel_functions/iserr'
116
+
117
+ require_relative 'excel_functions/npv'
@@ -0,0 +1,20 @@
1
+ module ExcelFunctions
2
+
3
+ def npv(rate, *values)
4
+ # Turn the arguments into numbers
5
+ rate = number_argument(rate)
6
+ values = values.flatten.map { |v| number_argument(v) }
7
+
8
+ # Check for errors
9
+ return rate if rate.is_a?(Symbol)
10
+ return :div0 if rate == -1
11
+ values.each { |v| return v if v.is_a?(Symbol) }
12
+
13
+ npv = 0
14
+
15
+ values.each.with_index { |v, i| npv = npv + (v/((1+rate)**(i+1))) }
16
+
17
+ npv
18
+ end
19
+
20
+ end
data/src/excel_to_code.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  class ExcelToCode
2
- def self.version() "0.3.3" end
2
+ def self.version() "0.3.4" end
3
3
  end
4
4
 
5
5
  require_relative 'commands'
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.3.3
4
+ version: 0.3.4
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-10-08 00:00:00.000000000 Z
11
+ date: 2014-12-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubypeg
@@ -105,7 +105,8 @@ description: "# excel_to_code\n\nConverts some excel spreadsheets (.xlsx, not .x
105
105
  multithread and will give bad results if you try\n7. Newlines are removed from strings\n8.
106
106
  The generated code uses floating point, rather than fully precise arithmetic, so
107
107
  results can differ slightly\n9. The generated code uses the sprintf approach to
108
- rounding (even-odd) rather than excel's 0.5 rounds away from zero.\n"
108
+ rounding (even-odd) rather than excel's 0.5 rounds away from zero.\n10. Ranges like
109
+ this: Sheet1!A10:Sheet1!B20 and 3D ranges don't work\n"
109
110
  email: tamc@greenonblack.com
110
111
  executables:
111
112
  - excel_to_c
@@ -189,6 +190,7 @@ files:
189
190
  - src/excel/excel_functions/multiply.rb
190
191
  - src/excel/excel_functions/negative.rb
191
192
  - src/excel/excel_functions/not_equal.rb
193
+ - src/excel/excel_functions/npv.rb
192
194
  - src/excel/excel_functions/number_argument.rb
193
195
  - src/excel/excel_functions/pi.rb
194
196
  - src/excel/excel_functions/pmt.rb