excel_to_code 0.3.15 → 0.3.16
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/src/commands/excel_to_x.rb +4 -1
- data/src/compile/c/a.out +0 -0
- data/src/compile/c/a.out.dSYM/Contents/Resources/DWARF/a.out +0 -0
- data/src/compile/c/excel_to_c_runtime.c +25 -0
- data/src/compile/c/excel_to_c_runtime_test.c +2 -0
- data/src/compile/c/map_formulae_to_c.rb +3 -1
- data/src/compile/ruby/compile_to_ruby_unit_test.rb +2 -0
- data/src/compile/ruby/map_formulae_to_ruby.rb +1 -0
- data/src/excel/excel_functions.rb +2 -0
- data/src/excel/excel_functions/address.rb +57 -0
- data/src/excel/excel_functions/pmt.rb +11 -2
- data/src/excel/formula_peg.rb +1 -1
- data/src/excel/formula_peg.txt +1 -1
- data/src/excel/reference.rb +4 -0
- data/src/excel_to_code.rb +1 -1
- data/src/extract/extract_data_from_worksheet.rb +3 -3
- data/src/extract/extract_shared_strings.rb +1 -1
- data/src/rewrite/caching_formula_parser.rb +29 -2
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 17eac22412740a67afd06333f437ce950c03c32d
|
4
|
+
data.tar.gz: 1117fdcb2343478712dc0a72649c429d1b9dc8dd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5023ee51c9f7a3909c7768ca58da98c368e3bec955a50e67c33df96387e2052e8c3c734f062c894b9102629509582232c7c08d62fd21b9fe718d1f678d6558fa
|
7
|
+
data.tar.gz: e34fd8293696f90562080eeb0f07db35a131d4132883baf62a5edf57f2fa37e36a699a16d355899e27c65c0a13dc262e143e30917593aed1a358868cc6108783
|
data/src/commands/excel_to_x.rb
CHANGED
@@ -917,6 +917,8 @@ class ExcelToX
|
|
917
917
|
@sheetless_cell_reference_replacer ||= RewriteCellReferencesToIncludeSheetAst.new
|
918
918
|
@replace_references_to_blanks_with_zeros ||= ReplaceReferencesToBlanksWithZeros.new(@formulae, nil, inline_ast_decision)
|
919
919
|
@fix_subtotal_of_subtotals ||= FixSubtotalOfSubtotals.new(@formulae)
|
920
|
+
# FIXME: Bodge to put it here as well, but seems to be required
|
921
|
+
column_and_row_function_replacement = ReplaceColumnAndRowFunctionsAST.new
|
920
922
|
|
921
923
|
#require 'pry'; binding.pry
|
922
924
|
|
@@ -939,6 +941,8 @@ class ExcelToX
|
|
939
941
|
@replace_arithmetic_on_ranges_replacer.map(ast)
|
940
942
|
@replace_string_joins_on_ranges_replacer.map(ast)
|
941
943
|
@wrap_formulae_that_return_arrays_replacer.map(ast)
|
944
|
+
column_and_row_function_replacement.current_reference = ref.last
|
945
|
+
column_and_row_function_replacement.replace(ast)
|
942
946
|
@replace_references_to_blanks_with_zeros.current_sheet_name = ref.first
|
943
947
|
@replace_references_to_blanks_with_zeros.map(ast)
|
944
948
|
@fix_subtotal_of_subtotals.map(ast)
|
@@ -947,7 +951,6 @@ class ExcelToX
|
|
947
951
|
raise
|
948
952
|
end
|
949
953
|
end
|
950
|
-
#require 'pry'; binding.pry
|
951
954
|
end
|
952
955
|
|
953
956
|
# These types of cells don't conatain formulae and can therefore be skipped
|
data/src/compile/c/a.out
CHANGED
Binary file
|
Binary file
|
@@ -87,6 +87,8 @@ static ExcelValue mod(ExcelValue a_v, ExcelValue b_v);
|
|
87
87
|
static ExcelValue negative(ExcelValue a_v);
|
88
88
|
static ExcelValue npv(ExcelValue rate, int number_of_arguments, ExcelValue *arguments);
|
89
89
|
static ExcelValue pmt(ExcelValue rate_v, ExcelValue number_of_periods_v, ExcelValue present_value_v);
|
90
|
+
static ExcelValue pmt_4(ExcelValue rate_v, ExcelValue number_of_periods_v, ExcelValue present_value_v, ExcelValue final_value_v);
|
91
|
+
static ExcelValue pmt_5(ExcelValue rate_v, ExcelValue number_of_periods_v, ExcelValue present_value_v, ExcelValue final_value_v, ExcelValue type_v);
|
90
92
|
static ExcelValue power(ExcelValue a_v, ExcelValue b_v);
|
91
93
|
static ExcelValue pv_3(ExcelValue a_v, ExcelValue b_v, ExcelValue c_v);
|
92
94
|
static ExcelValue pv_4(ExcelValue a_v, ExcelValue b_v, ExcelValue c_v, ExcelValue d_v);
|
@@ -1527,6 +1529,29 @@ static ExcelValue pmt(ExcelValue rate_v, ExcelValue number_of_periods_v, ExcelVa
|
|
1527
1529
|
return EXCEL_NUMBER(-present_value*(rate*(pow((1+rate),number_of_periods)))/((pow((1+rate),number_of_periods))-1));
|
1528
1530
|
}
|
1529
1531
|
|
1532
|
+
static ExcelValue pmt_4(ExcelValue rate_v, ExcelValue number_of_periods_v, ExcelValue present_value_v, ExcelValue final_value_v) {
|
1533
|
+
CHECK_FOR_PASSED_ERROR(final_value_v)
|
1534
|
+
|
1535
|
+
NUMBER(final_value_v, final_value)
|
1536
|
+
CHECK_FOR_CONVERSION_ERROR
|
1537
|
+
|
1538
|
+
if(final_value == 0) return pmt(rate_v, number_of_periods_v, present_value_v);
|
1539
|
+
printf("PMT with non-zero final_value not implemented. halting.");
|
1540
|
+
exit(-1);
|
1541
|
+
}
|
1542
|
+
|
1543
|
+
static ExcelValue pmt_5(ExcelValue rate_v, ExcelValue number_of_periods_v, ExcelValue present_value_v, ExcelValue final_value_v, ExcelValue type_v) {
|
1544
|
+
CHECK_FOR_PASSED_ERROR(type_v)
|
1545
|
+
|
1546
|
+
NUMBER(type_v, type)
|
1547
|
+
CHECK_FOR_CONVERSION_ERROR
|
1548
|
+
|
1549
|
+
if(type == 0) return pmt(rate_v, number_of_periods_v, present_value_v);
|
1550
|
+
printf("PMT with non-zero type not implemented. halting.");
|
1551
|
+
exit(-1);
|
1552
|
+
}
|
1553
|
+
|
1554
|
+
|
1530
1555
|
static ExcelValue pv_3(ExcelValue rate_v, ExcelValue nper_v, ExcelValue pmt_v) {
|
1531
1556
|
return pv_4(rate_v, nper_v, pmt_v, ZERO);
|
1532
1557
|
}
|
@@ -425,6 +425,8 @@ int test_functions() {
|
|
425
425
|
assert((pmt(EXCEL_NUMBER(0.1),EXCEL_NUMBER(10),EXCEL_NUMBER(100)).number - -16.27) < 0.01);
|
426
426
|
assert((pmt(EXCEL_NUMBER(0.0123),EXCEL_NUMBER(99.1),EXCEL_NUMBER(123.32)).number - -2.159) < 0.01);
|
427
427
|
assert((pmt(EXCEL_NUMBER(0),EXCEL_NUMBER(2),EXCEL_NUMBER(10)).number - -5) < 0.01);
|
428
|
+
assert((pmt_4(EXCEL_NUMBER(0),EXCEL_NUMBER(2),EXCEL_NUMBER(10), EXCEL_NUMBER(0)).number - -5) < 0.01);
|
429
|
+
assert((pmt_5(EXCEL_NUMBER(0),EXCEL_NUMBER(2),EXCEL_NUMBER(10), EXCEL_NUMBER(0), EXCEL_NUMBER(0)).number - -5) < 0.01);
|
428
430
|
|
429
431
|
// Test power
|
430
432
|
// ... should return power of its arguments
|
@@ -37,6 +37,8 @@ class CompileToRubyUnitTest
|
|
37
37
|
else
|
38
38
|
o.puts " def #{test_name}; assert_equal(#{value}, #{full_reference}); end"
|
39
39
|
end
|
40
|
+
when :string
|
41
|
+
o.puts " def #{test_name}; assert_equal(#{value.gsub(/(\\n|\\r|\r|\n)+/,'')}, #{full_reference}.to_s.gsub(/[\\n\\r]+/,'')); end"
|
40
42
|
when :number
|
41
43
|
if sloppy
|
42
44
|
if value.to_f.abs <= 1
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module ExcelFunctions
|
2
|
+
|
3
|
+
# ADDRESS(row_num,column_num,abs_num,a1,sheet_text)
|
4
|
+
# row_num
|
5
|
+
# The row number to use in the cell reference.
|
6
|
+
# column_num
|
7
|
+
# The column number to use in the cell reference.
|
8
|
+
# abs_num
|
9
|
+
# Specifies the type of reference to return.
|
10
|
+
# 1 or omitted returns the following type of reference: absolute.
|
11
|
+
# 2 returns the following type of reference: absolute row; relative column.
|
12
|
+
# 3 returns the following type of reference: relative row; absolute column.
|
13
|
+
# 4 returns the following type of reference: relative.
|
14
|
+
# a1
|
15
|
+
# A logical value that specifies the A1 or R1C1 reference style.
|
16
|
+
# If a1 is TRUE or omitted, ADDRESS returns an A1-style reference.
|
17
|
+
# If a1 is FALSE, ADDRESS returns an R1C1-style reference.
|
18
|
+
# sheet_text
|
19
|
+
# Text specifying the name of the sheet to be used as the external reference.
|
20
|
+
# If sheet_text is omitted, no sheet name is used.
|
21
|
+
def address(row_num, column_num, abs_num = 1, a1 = true, sheet_text = nil)
|
22
|
+
raise NotSupportedException.new("address() function R1C1 references not implemented") if a1 == false
|
23
|
+
|
24
|
+
return row_num if row_num.is_a?(Symbol)
|
25
|
+
return column_num if column_num.is_a?(Symbol)
|
26
|
+
return abs_num if abs_num.is_a?(Symbol)
|
27
|
+
return a1 if a1.is_a?(Symbol)
|
28
|
+
return sheet_text if sheet_text.is_a?(Symbol)
|
29
|
+
|
30
|
+
row_num = number_argument(row_num)
|
31
|
+
column_num = number_argument(column_num)
|
32
|
+
abs_num = number_argument(abs_num)
|
33
|
+
|
34
|
+
return :value if row_num < 1
|
35
|
+
return :value if column_num < 1
|
36
|
+
return :value if abs_num < 1
|
37
|
+
return :value if abs_num > 4
|
38
|
+
|
39
|
+
row = row_num.to_i.to_s
|
40
|
+
column = Reference.column_letters_for_column_number[column_num.to_i].to_s
|
41
|
+
|
42
|
+
ref = case abs_num
|
43
|
+
when 1; "$"+column+"$"+row
|
44
|
+
when 2; "" +column+"$" +row
|
45
|
+
when 3; "$"+column+"" +row
|
46
|
+
when 4; ""+column+"" +row
|
47
|
+
end
|
48
|
+
|
49
|
+
if sheet_text
|
50
|
+
ref = "'#{sheet_text}'!"+ref
|
51
|
+
end
|
52
|
+
|
53
|
+
ref
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
@@ -1,14 +1,23 @@
|
|
1
1
|
module ExcelFunctions
|
2
2
|
|
3
|
-
def pmt(rate,number_of_periods,present_value)
|
3
|
+
def pmt(rate,number_of_periods,present_value, final_value = 0, type = 0)
|
4
|
+
|
4
5
|
rate = number_argument(rate)
|
5
6
|
number_of_periods = number_argument(number_of_periods)
|
6
7
|
present_value = number_argument(present_value)
|
7
|
-
|
8
|
+
final_value = number_argument(final_value)
|
9
|
+
type = number_argument(type)
|
10
|
+
|
8
11
|
return rate if rate.is_a?(Symbol)
|
9
12
|
return number_of_periods if number_of_periods.is_a?(Symbol)
|
10
13
|
return present_value if present_value.is_a?(Symbol)
|
14
|
+
return final_value if final_value.is_a?(Symbol)
|
15
|
+
return type if type.is_a?(Symbol)
|
16
|
+
|
11
17
|
return :num if number_of_periods == 0
|
18
|
+
|
19
|
+
raise NotSupportedException.new("pmt() function non zero final value not implemented") unless final_value == 0
|
20
|
+
raise NotSupportedException.new("pmt() function non zero type not implemented") unless type == 0
|
12
21
|
|
13
22
|
return -(present_value / number_of_periods) if rate == 0
|
14
23
|
-present_value*(rate*((1+rate)**number_of_periods))/(((1+rate)**number_of_periods)-1)
|
data/src/excel/formula_peg.rb
CHANGED
data/src/excel/formula_peg.txt
CHANGED
data/src/excel/reference.rb
CHANGED
@@ -32,6 +32,10 @@ class Reference < String
|
|
32
32
|
letters
|
33
33
|
end
|
34
34
|
|
35
|
+
def self.column_letters_for_column_number
|
36
|
+
@@column_letters_for_column_number
|
37
|
+
end
|
38
|
+
|
35
39
|
attr_reader :excel_row_number, :excel_column_number, :excel_column, :excel_row
|
36
40
|
|
37
41
|
def calculate_excel_variables
|
data/src/excel_to_code.rb
CHANGED
@@ -81,10 +81,10 @@ class ExtractDataFromWorksheet < ::Ox::Sax
|
|
81
81
|
|
82
82
|
unless @formula.empty?
|
83
83
|
begin
|
84
|
-
formula_text = @formula.join
|
84
|
+
formula_text = @formula.join
|
85
85
|
ast = @fp.parse(formula_text)
|
86
|
-
rescue
|
87
|
-
e.ref = key # Attach the sheet and reference to the exception
|
86
|
+
rescue ExcelToCodeException => e
|
87
|
+
e.ref = key if e.respond_to?(:ref) # Attach the sheet and reference to the exception
|
88
88
|
raise
|
89
89
|
end
|
90
90
|
unless ast
|
@@ -17,7 +17,7 @@ class ExternalReferenceException < ExcelToCodeException
|
|
17
17
|
|
18
18
|
Sorry, ExcelToCode can't handle external references
|
19
19
|
|
20
|
-
It found one in #{ref.join("!")}
|
20
|
+
It found one in #{ref && ref.join("!")}
|
21
21
|
The formula was #{formula_text}
|
22
22
|
Which was parsed to #{full_ast}
|
23
23
|
Which seemed to have an external reference at #{reference_ast}
|
@@ -29,6 +29,32 @@ class ExternalReferenceException < ExcelToCodeException
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
+
class ParseFailedException < ExcelToCodeException
|
33
|
+
|
34
|
+
attr_accessor :formula_text
|
35
|
+
attr_accessor :ref
|
36
|
+
|
37
|
+
def initialize(formula_text)
|
38
|
+
@formula_text = formula_text
|
39
|
+
end
|
40
|
+
|
41
|
+
def message
|
42
|
+
<<-END
|
43
|
+
|
44
|
+
|
45
|
+
Sorry, ExcelToCode couldn't parse one of the formulae
|
46
|
+
|
47
|
+
It was in #{ref && ref.join("!")}
|
48
|
+
The formula was #{formula_text}
|
49
|
+
|
50
|
+
Please report the problem at http://github.com/tamc/excel_to_code/issues
|
51
|
+
|
52
|
+
END
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
|
32
58
|
class CachingFormulaParser
|
33
59
|
include Singleton
|
34
60
|
|
@@ -56,10 +82,11 @@ class CachingFormulaParser
|
|
56
82
|
def parse(text)
|
57
83
|
ast = Formula.parse(text)
|
58
84
|
@text = text # Kept in case of Exception below
|
59
|
-
@full_ast = ast.to_ast[1] # Kept in case of Exception below
|
60
85
|
if ast
|
86
|
+
@full_ast = ast.to_ast[1] # Kept in case of Exception below
|
61
87
|
map(ast.to_ast[1])
|
62
88
|
else
|
89
|
+
raise ParseFailedException.new(text)
|
63
90
|
nil
|
64
91
|
end
|
65
92
|
end
|
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.
|
4
|
+
version: 0.3.16
|
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: 2015-
|
11
|
+
date: 2015-05-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubypeg
|
@@ -150,6 +150,7 @@ files:
|
|
150
150
|
- src/excel/excel_functions.rb
|
151
151
|
- src/excel/excel_functions/abs.rb
|
152
152
|
- src/excel/excel_functions/add.rb
|
153
|
+
- src/excel/excel_functions/address.rb
|
153
154
|
- src/excel/excel_functions/and.rb
|
154
155
|
- src/excel/excel_functions/apply_to_range.rb
|
155
156
|
- src/excel/excel_functions/average.rb
|