rubyfromexcel 0.0.4
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.
- data/README +22 -0
- data/bin/rubyfromexcel +20 -0
- data/examples/create_and_test_examples.rb +37 -0
- data/examples/ruby-versions/array-formulas-ruby/sheets/sheet1.rb +59 -0
- data/examples/ruby-versions/array-formulas-ruby/sheets/sheet2.rb +9 -0
- data/examples/ruby-versions/array-formulas-ruby/specs/sheet1_rspec.rb +156 -0
- data/examples/ruby-versions/array-formulas-ruby/specs/sheet2_rspec.rb +8 -0
- data/examples/ruby-versions/array-formulas-ruby/spreadsheet.rb +9 -0
- data/examples/ruby-versions/complex-test-ruby/sheets/sheet1.rb +305 -0
- data/examples/ruby-versions/complex-test-ruby/sheets/sheet2.rb +147 -0
- data/examples/ruby-versions/complex-test-ruby/specs/sheet1_rspec.rb +876 -0
- data/examples/ruby-versions/complex-test-ruby/specs/sheet2_rspec.rb +412 -0
- data/examples/ruby-versions/complex-test-ruby/spreadsheet.rb +9 -0
- data/examples/ruby-versions/namedReferenceTest-ruby/sheets/sheet1.rb +9 -0
- data/examples/ruby-versions/namedReferenceTest-ruby/sheets/sheet2.rb +8 -0
- data/examples/ruby-versions/namedReferenceTest-ruby/specs/sheet1_rspec.rb +16 -0
- data/examples/ruby-versions/namedReferenceTest-ruby/specs/sheet2_rspec.rb +16 -0
- data/examples/ruby-versions/namedReferenceTest-ruby/spreadsheet.rb +9 -0
- data/examples/ruby-versions/pruning-ruby/sheets/sheet1.rb +11 -0
- data/examples/ruby-versions/pruning-ruby/sheets/sheet2.rb +14 -0
- data/examples/ruby-versions/pruning-ruby/sheets/sheet3.rb +7 -0
- data/examples/ruby-versions/pruning-ruby/specs/sheet1_rspec.rb +20 -0
- data/examples/ruby-versions/pruning-ruby/specs/sheet2_rspec.rb +20 -0
- data/examples/ruby-versions/pruning-ruby/specs/sheet3_rspec.rb +8 -0
- data/examples/ruby-versions/pruning-ruby/spreadsheet.rb +9 -0
- data/examples/ruby-versions/sharedFormulaTest-ruby/sheets/sheet1.rb +15 -0
- data/examples/ruby-versions/sharedFormulaTest-ruby/specs/sheet1_rspec.rb +44 -0
- data/examples/ruby-versions/sharedFormulaTest-ruby/spreadsheet.rb +9 -0
- data/examples/ruby-versions/table-test-ruby/sheets/sheet1.rb +17 -0
- data/examples/ruby-versions/table-test-ruby/sheets/sheet2.rb +5 -0
- data/examples/ruby-versions/table-test-ruby/sheets/sheet3.rb +5 -0
- data/examples/ruby-versions/table-test-ruby/specs/sheet1_rspec.rb +20 -0
- data/examples/ruby-versions/table-test-ruby/specs/sheet2_rspec.rb +8 -0
- data/examples/ruby-versions/table-test-ruby/specs/sheet3_rspec.rb +8 -0
- data/examples/ruby-versions/table-test-ruby/spreadsheet.rb +9 -0
- data/examples/sheets/array-formulas.xlsx +0 -0
- data/examples/sheets/complex-test.xlsx +0 -0
- data/examples/sheets/namedReferenceTest.xlsx +0 -0
- data/examples/sheets/pruning.xlsx +0 -0
- data/examples/sheets/sharedFormulaTest.xlsx +0 -0
- data/examples/sheets/table-test.xlsx +0 -0
- data/examples/sheets/~$array-formulas.xlsx +0 -0
- data/examples/unzipped-sheets/array-formulas/[Content_Types].xml +2 -0
- data/examples/unzipped-sheets/array-formulas/docProps/app.xml +2 -0
- data/examples/unzipped-sheets/array-formulas/docProps/core.xml +2 -0
- data/examples/unzipped-sheets/array-formulas/docProps/thumbnail.jpeg +0 -0
- data/examples/unzipped-sheets/array-formulas/xl/_rels/workbook.xml.rels +2 -0
- data/examples/unzipped-sheets/array-formulas/xl/calcChain.xml +2 -0
- data/examples/unzipped-sheets/array-formulas/xl/sharedStrings.xml +2 -0
- data/examples/unzipped-sheets/array-formulas/xl/styles.xml +2 -0
- data/examples/unzipped-sheets/array-formulas/xl/theme/theme1.xml +2 -0
- data/examples/unzipped-sheets/array-formulas/xl/workbook.xml +2 -0
- data/examples/unzipped-sheets/array-formulas/xl/worksheets/sheet1.xml +2 -0
- data/examples/unzipped-sheets/array-formulas/xl/worksheets/sheet2.xml +2 -0
- data/examples/unzipped-sheets/complex-test/[Content_Types].xml +2 -0
- data/examples/unzipped-sheets/complex-test/docProps/app.xml +2 -0
- data/examples/unzipped-sheets/complex-test/docProps/core.xml +2 -0
- data/examples/unzipped-sheets/complex-test/xl/_rels/workbook.xml.rels +2 -0
- data/examples/unzipped-sheets/complex-test/xl/calcChain.xml +2 -0
- data/examples/unzipped-sheets/complex-test/xl/charts/chart1.xml +2 -0
- data/examples/unzipped-sheets/complex-test/xl/charts/chart2.xml +2 -0
- data/examples/unzipped-sheets/complex-test/xl/comments1.xml +5 -0
- data/examples/unzipped-sheets/complex-test/xl/comments2.xml +5 -0
- data/examples/unzipped-sheets/complex-test/xl/drawings/_rels/drawing1.xml.rels +2 -0
- data/examples/unzipped-sheets/complex-test/xl/drawings/_rels/drawing2.xml.rels +2 -0
- data/examples/unzipped-sheets/complex-test/xl/drawings/drawing1.xml +2 -0
- data/examples/unzipped-sheets/complex-test/xl/drawings/drawing2.xml +2 -0
- data/examples/unzipped-sheets/complex-test/xl/drawings/vmlDrawing1.vml +46 -0
- data/examples/unzipped-sheets/complex-test/xl/drawings/vmlDrawing2.vml +46 -0
- data/examples/unzipped-sheets/complex-test/xl/sharedStrings.xml +2 -0
- data/examples/unzipped-sheets/complex-test/xl/styles.xml +2 -0
- data/examples/unzipped-sheets/complex-test/xl/theme/theme1.xml +2 -0
- data/examples/unzipped-sheets/complex-test/xl/workbook.xml +2 -0
- data/examples/unzipped-sheets/complex-test/xl/worksheets/_rels/sheet1.xml.rels +2 -0
- data/examples/unzipped-sheets/complex-test/xl/worksheets/_rels/sheet2.xml.rels +2 -0
- data/examples/unzipped-sheets/complex-test/xl/worksheets/sheet1.xml +2 -0
- data/examples/unzipped-sheets/complex-test/xl/worksheets/sheet2.xml +2 -0
- data/examples/unzipped-sheets/namedReferenceTest/[Content_Types].xml +2 -0
- data/examples/unzipped-sheets/namedReferenceTest/docProps/app.xml +2 -0
- data/examples/unzipped-sheets/namedReferenceTest/docProps/core.xml +2 -0
- data/examples/unzipped-sheets/namedReferenceTest/docProps/thumbnail.jpeg +0 -0
- data/examples/unzipped-sheets/namedReferenceTest/xl/_rels/workbook.xml.rels +2 -0
- data/examples/unzipped-sheets/namedReferenceTest/xl/calcChain.xml +2 -0
- data/examples/unzipped-sheets/namedReferenceTest/xl/styles.xml +2 -0
- data/examples/unzipped-sheets/namedReferenceTest/xl/theme/theme1.xml +2 -0
- data/examples/unzipped-sheets/namedReferenceTest/xl/workbook.xml +2 -0
- data/examples/unzipped-sheets/namedReferenceTest/xl/worksheets/sheet1.xml +2 -0
- data/examples/unzipped-sheets/namedReferenceTest/xl/worksheets/sheet2.xml +2 -0
- data/examples/unzipped-sheets/pruning/[Content_Types].xml +2 -0
- data/examples/unzipped-sheets/pruning/docProps/app.xml +2 -0
- data/examples/unzipped-sheets/pruning/docProps/core.xml +2 -0
- data/examples/unzipped-sheets/pruning/docProps/thumbnail.jpeg +0 -0
- data/examples/unzipped-sheets/pruning/xl/_rels/workbook.xml.rels +2 -0
- data/examples/unzipped-sheets/pruning/xl/calcChain.xml +2 -0
- data/examples/unzipped-sheets/pruning/xl/sharedStrings.xml +2 -0
- data/examples/unzipped-sheets/pruning/xl/styles.xml +2 -0
- data/examples/unzipped-sheets/pruning/xl/theme/theme1.xml +2 -0
- data/examples/unzipped-sheets/pruning/xl/workbook.xml +2 -0
- data/examples/unzipped-sheets/pruning/xl/worksheets/sheet1.xml +2 -0
- data/examples/unzipped-sheets/pruning/xl/worksheets/sheet2.xml +2 -0
- data/examples/unzipped-sheets/pruning/xl/worksheets/sheet3.xml +2 -0
- data/examples/unzipped-sheets/sharedFormulaTest/[Content_Types].xml +2 -0
- data/examples/unzipped-sheets/sharedFormulaTest/docProps/app.xml +2 -0
- data/examples/unzipped-sheets/sharedFormulaTest/docProps/core.xml +2 -0
- data/examples/unzipped-sheets/sharedFormulaTest/docProps/thumbnail.jpeg +0 -0
- data/examples/unzipped-sheets/sharedFormulaTest/xl/_rels/workbook.xml.rels +2 -0
- data/examples/unzipped-sheets/sharedFormulaTest/xl/calcChain.xml +2 -0
- data/examples/unzipped-sheets/sharedFormulaTest/xl/styles.xml +2 -0
- data/examples/unzipped-sheets/sharedFormulaTest/xl/theme/theme1.xml +2 -0
- data/examples/unzipped-sheets/sharedFormulaTest/xl/workbook.xml +2 -0
- data/examples/unzipped-sheets/sharedFormulaTest/xl/worksheets/sheet1.xml +2 -0
- data/examples/unzipped-sheets/table-test/[Content_Types].xml +2 -0
- data/examples/unzipped-sheets/table-test/docProps/app.xml +2 -0
- data/examples/unzipped-sheets/table-test/docProps/core.xml +2 -0
- data/examples/unzipped-sheets/table-test/xl/_rels/workbook.xml.rels +2 -0
- data/examples/unzipped-sheets/table-test/xl/calcChain.xml +2 -0
- data/examples/unzipped-sheets/table-test/xl/printerSettings/printerSettings1.bin +0 -0
- data/examples/unzipped-sheets/table-test/xl/sharedStrings.xml +2 -0
- data/examples/unzipped-sheets/table-test/xl/styles.xml +2 -0
- data/examples/unzipped-sheets/table-test/xl/tables/table1.xml +2 -0
- data/examples/unzipped-sheets/table-test/xl/theme/theme1.xml +2 -0
- data/examples/unzipped-sheets/table-test/xl/workbook.xml +2 -0
- data/examples/unzipped-sheets/table-test/xl/worksheets/_rels/sheet1.xml.rels +2 -0
- data/examples/unzipped-sheets/table-test/xl/worksheets/sheet1.xml +2 -0
- data/examples/unzipped-sheets/table-test/xl/worksheets/sheet2.xml +2 -0
- data/examples/unzipped-sheets/table-test/xl/worksheets/sheet3.xml +2 -0
- data/lib/cells/array/array_formula_builder.rb +58 -0
- data/lib/cells/array/array_formula_cell.rb +27 -0
- data/lib/cells/array/arraying_formula_cell.rb +67 -0
- data/lib/cells/array/single_cell_array_formula_builder.rb +9 -0
- data/lib/cells/array/single_cell_array_formula_cell.rb +11 -0
- data/lib/cells/cell.rb +98 -0
- data/lib/cells/cells.rb +9 -0
- data/lib/cells/formula/formula_cell.rb +18 -0
- data/lib/cells/formula/simple_formula_cell.rb +4 -0
- data/lib/cells/shared/shared_formula_builder.rb +15 -0
- data/lib/cells/shared/shared_formula_cell.rb +20 -0
- data/lib/cells/shared/sharing_formula_cell.rb +36 -0
- data/lib/cells/value/value_cell.rb +24 -0
- data/lib/excelfile/excelfile.rb +6 -0
- data/lib/excelfile/relationships.rb +24 -0
- data/lib/excelfile/shared_strings.rb +21 -0
- data/lib/excelfile/sheet_names.rb +6 -0
- data/lib/excelfile/table.rb +116 -0
- data/lib/excelfile/workbook.rb +108 -0
- data/lib/excelfile/worksheet.rb +122 -0
- data/lib/formulae/compile/formula_builder.rb +316 -0
- data/lib/formulae/formulae.rb +6 -0
- data/lib/formulae/parse/formula_peg.rb +213 -0
- data/lib/formulae/parse/formula_peg.txt +40 -0
- data/lib/formulae/run/excel_functions.rb +375 -0
- data/lib/formulae/run/excel_matrix.rb +114 -0
- data/lib/formulae/run/excel_range.rb +256 -0
- data/lib/formulae/run/reference.rb +79 -0
- data/lib/optimiser/dependency_builder.rb +86 -0
- data/lib/optimiser/optimiser.rb +3 -0
- data/lib/optimiser/shared_formula_dependency_builder.rb +43 -0
- data/lib/optimiser/workbook_pruner.rb +80 -0
- data/lib/rubyfromexcel.rb +105 -0
- data/lib/runtime/runtime_formula_builder.rb +32 -0
- data/spec/array_formula_builder_spec.rb +35 -0
- data/spec/array_formula_cell_spec.rb +17 -0
- data/spec/arraying_formula_cell_spec.rb +38 -0
- data/spec/dependency_builder_spec.rb +71 -0
- data/spec/excel_functions_spec.rb +381 -0
- data/spec/excel_matrix_spec.rb +92 -0
- data/spec/excel_range_spec.rb +161 -0
- data/spec/formula_builder_spec.rb +230 -0
- data/spec/formula_peg_spec.rb +165 -0
- data/spec/reference_spec.rb +72 -0
- data/spec/relationships_spec.rb +51 -0
- data/spec/runtime_formula_builder_spec.rb +55 -0
- data/spec/shared_formula_builder_spec.rb +29 -0
- data/spec/shared_formula_cell_spec.rb +23 -0
- data/spec/shared_formula_dependency_builder_spec.rb +48 -0
- data/spec/shared_strings_spec.rb +14 -0
- data/spec/sharing_formula_cell_spec.rb +79 -0
- data/spec/simple_formula_cell_spec.rb +78 -0
- data/spec/single_cell_array_formula_builder_spec.rb +19 -0
- data/spec/single_cell_array_formula_cell_spec.rb +25 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/table_spec.rb +100 -0
- data/spec/value_cell_spec.rb +49 -0
- data/spec/workbook_pruner_spec.rb +27 -0
- data/spec/workbook_spec.rb +283 -0
- data/spec/worksheet_failiures_spec.rb +41 -0
- data/spec/worksheet_spec.rb +486 -0
- metadata +291 -0
@@ -0,0 +1,105 @@
|
|
1
|
+
# Standard library
|
2
|
+
require 'fileutils'
|
3
|
+
require 'singleton'
|
4
|
+
|
5
|
+
# Gems
|
6
|
+
require 'nokogiri'
|
7
|
+
require 'rubyscriptwriter'
|
8
|
+
require 'rubyspecwriter'
|
9
|
+
require 'rubypeg'
|
10
|
+
|
11
|
+
# Components of RubyFromExcel
|
12
|
+
require_relative 'excelfile/excelfile'
|
13
|
+
require_relative 'formulae/formulae'
|
14
|
+
require_relative 'cells/cells'
|
15
|
+
require_relative 'optimiser/optimiser'
|
16
|
+
|
17
|
+
require_relative 'runtime/runtime_formula_builder'
|
18
|
+
|
19
|
+
module RubyFromExcel
|
20
|
+
class Process
|
21
|
+
attr_accessor :source_excel_directory
|
22
|
+
attr_accessor :target_ruby_directory
|
23
|
+
attr_accessor :workbook
|
24
|
+
attr_accessor :skip_tests
|
25
|
+
attr_accessor :prune_except_output_sheets
|
26
|
+
attr_accessor :convert_independent_of_input_sheets
|
27
|
+
|
28
|
+
def initialize(&block)
|
29
|
+
instance_eval(&block) if block
|
30
|
+
end
|
31
|
+
|
32
|
+
def workbook_filename
|
33
|
+
File.join(source_excel_directory,'xl','workbook.xml')
|
34
|
+
end
|
35
|
+
|
36
|
+
def start!
|
37
|
+
reset_global_classes
|
38
|
+
|
39
|
+
time "Preparing destination folder..." do
|
40
|
+
prepare_destination_folder
|
41
|
+
end
|
42
|
+
|
43
|
+
time "Loading..." do
|
44
|
+
self.workbook = Workbook.new(workbook_filename)
|
45
|
+
end
|
46
|
+
|
47
|
+
if prune_except_output_sheets
|
48
|
+
time "Pruning..." do
|
49
|
+
workbook.prune_cells_not_needed_for_output_sheets(*prune_except_output_sheets)
|
50
|
+
workbook.convert_cells_to_values_when_independent_of_input_sheets(*convert_independent_of_input_sheets)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
time "Workbook contains #{workbook.worksheets.size} sheets:\n" do
|
55
|
+
|
56
|
+
puts "0) Generating ruby for the workbook"
|
57
|
+
write workbook.to_ruby, :to, "spreadsheet.rb"
|
58
|
+
|
59
|
+
i = 0
|
60
|
+
workbook.worksheets.each do |variable_name, worksheet|
|
61
|
+
time "#{i+=1}) Generating ruby for #{variable_name}..." do
|
62
|
+
print 'ruby...'
|
63
|
+
write worksheet.to_ruby, :to, 'sheets', "#{variable_name}.rb"
|
64
|
+
unless skip_tests
|
65
|
+
print 'test...'
|
66
|
+
write worksheet.to_test, :to, 'specs',"#{variable_name}_rspec.rb"
|
67
|
+
end
|
68
|
+
# worksheet.nil_memory_consuming_variables!
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
unless skip_tests
|
74
|
+
puts "Running tests of generated files"
|
75
|
+
puts `spec -fo #{File.join(target_ruby_directory,'specs',"*")}`
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# FIXME: Urgh. Global variables. Need to eliminate these!
|
80
|
+
def reset_global_classes
|
81
|
+
SheetNames.instance.clear
|
82
|
+
SharedStrings.instance.clear
|
83
|
+
end
|
84
|
+
|
85
|
+
def prepare_destination_folder
|
86
|
+
FileUtils.mkpath(File.join(target_ruby_directory,'specs'))
|
87
|
+
FileUtils.mkpath(File.join(target_ruby_directory,'sheets'))
|
88
|
+
end
|
89
|
+
|
90
|
+
def write(thing,to,*filenames)
|
91
|
+
File.open(File.join(target_ruby_directory,*filenames),'w') do |f|
|
92
|
+
f.puts thing.to_s
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def time(message)
|
97
|
+
print message
|
98
|
+
STDOUT.flush
|
99
|
+
start_time = Time.now
|
100
|
+
yield
|
101
|
+
puts "took #{(Time.now-start_time).to_i} seconds."
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module RubyFromExcel
|
2
|
+
|
3
|
+
class RuntimeFormulaBuilder < FormulaBuilder
|
4
|
+
|
5
|
+
attr_accessor :worksheet, :refering_cell_reference
|
6
|
+
|
7
|
+
def initialize(worksheet, refering_cell_reference = nil)
|
8
|
+
self.worksheet = worksheet
|
9
|
+
self.refering_cell_reference = refering_cell_reference
|
10
|
+
end
|
11
|
+
|
12
|
+
def sheet_reference(sheet_name,reference)
|
13
|
+
"s('#{sheet_name}').#{reference.visit(self)}"
|
14
|
+
end
|
15
|
+
|
16
|
+
alias :quoted_sheet_reference :sheet_reference
|
17
|
+
|
18
|
+
def table_reference(table_name,structured_reference)
|
19
|
+
table = worksheet.t(table_name)
|
20
|
+
table.respond_to?(:reference_for) ? table.reference_for(structured_reference,refering_cell_reference).to_s : table
|
21
|
+
end
|
22
|
+
|
23
|
+
def named_reference(name)
|
24
|
+
name.to_method_name
|
25
|
+
end
|
26
|
+
|
27
|
+
def indirect_function(text_formula)
|
28
|
+
"indirect(#{text_formula.visit(self)},'#{formula_cell && formula_cell.reference}')"
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe ArrayFormulaBuilder, "Formulas with shared_formula_offsets" do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@builder = ArrayFormulaBuilder.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def ruby_for(formula)
|
10
|
+
ast = Formula.parse(formula)
|
11
|
+
ast.visit(@builder)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should leave individual references alone" do
|
15
|
+
ruby_for("A1").should == "a1"
|
16
|
+
ruby_for("A$1").should == "a1"
|
17
|
+
ruby_for("$A1").should == "a1"
|
18
|
+
ruby_for("$A$1").should == "a1"
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should replace range references with individual cell references" do
|
22
|
+
ruby_for("A:C").should == "c('a','c')"
|
23
|
+
ruby_for("1:10").should == "r(1,10)"
|
24
|
+
ruby_for("IF(A1:A5>0,A1:A5,1+2)").should == "m(m(a('a1','a5'),0.0) { |r1,r2| r1>r2 },a('a1','a5'),m(1.0,2.0) { |r1,r2| r1+r2 }) { |r1,r2,r3| excel_if(r1,r2,r3) }"
|
25
|
+
ruby_for("B10:B20+B5").should == "m(a('b10','b20'),b5) { |r1,r2| r1+r2 }"
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should not replace range references where they are expected by the formula" do
|
29
|
+
ruby_for("INDEX($F$16:$I$19, ,MATCH($E$8, $F$15:$I$15, 0))").should == "m(0.0,m(e8,0.0) { |r1,r2| match(r1,a('f15','i15'),r2) }) { |r1,r2| index(a('f16','i19'),r1,r2) }"
|
30
|
+
ruby_for("SUMIF($F$16:$I$19,C8)").should == "m(c8) { |r1| sumif(a('f16','i19'),r1) }"
|
31
|
+
ruby_for("SUMIF($F$16:$I$19,C8,$Q$16:$R$19)").should == "m(c8) { |r1| sumif(a('f16','i19'),r1,a('q16','r19')) }"
|
32
|
+
ruby_for("SUMIFS($F$16:$F$19,$G$16:$G$19,1.0,$H$16:$H$19,Q1:Q4)").should == "m(1.0,a('q1','q4')) { |r1,r2| sumifs(a('f16','f19'),a('g16','g19'),r1,a('h16','h19'),r2) }"
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe ArrayFormulaCell do
|
4
|
+
|
5
|
+
# <c r="B3"><f t="array" ref="B3:E6">B2:E2+A3:A6</f><v>2</v></c>
|
6
|
+
|
7
|
+
it "it is given a value cell and a pre-parsed formula and picks out values from its array references according to array_formula_offset" do
|
8
|
+
value_cell = ValueCell.new(mock('worksheet',:to_s => 'sheet1'),Nokogiri::XML('<c r="D6"><v>7</v></c>').root)
|
9
|
+
|
10
|
+
cell = ArrayFormulaCell.from_other_cell(value_cell)
|
11
|
+
cell.array_formula_reference = "b3_array"
|
12
|
+
cell.array_formula_offset = [1,1]
|
13
|
+
cell.to_ruby.should == "def d6; @d6 ||= b3_array.array_formula_offset(1,1); end\n"
|
14
|
+
cell.to_test.should == "it 'cell d6 should equal 7.0' do\n sheet1.d6.should be_close(7.0,0.7)\nend\n\n"
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe ArrayingFormulaCell do
|
4
|
+
|
5
|
+
# <c r="B3"><f t="array" ref="B3:E6">B2:E2+A3:A6</f><v>2</v></c>
|
6
|
+
|
7
|
+
before do
|
8
|
+
@worksheet = mock(:worksheet,:class_name => 'Sheet1', :to_s => 'sheet1')
|
9
|
+
|
10
|
+
@arraying_cell = ArrayingFormulaCell.new(
|
11
|
+
@worksheet,
|
12
|
+
Nokogiri::XML('<c r="B3"><f t="array" ref="B3:C3">D2:E2+A3:A6</f><v>2</v></c>').root
|
13
|
+
)
|
14
|
+
@value_cell = ValueCell.new(
|
15
|
+
@worksheet,
|
16
|
+
Nokogiri::XML('<c r="C3"><v>7</v></c>').root
|
17
|
+
)
|
18
|
+
@worksheet.should_receive(:cell).with('c3').and_return(@value_cell)
|
19
|
+
@worksheet.should_receive(:replace_cell) do |reference,new_cell|
|
20
|
+
reference.should == 'c3'
|
21
|
+
new_cell.to_ruby.should == "def c3; @c3 ||= b3_array.array_formula_offset(0,1); end\n"
|
22
|
+
end
|
23
|
+
@arraying_cell.alter_other_cells_if_required
|
24
|
+
end
|
25
|
+
|
26
|
+
it "it is given a pre-parsed formula and picks out values from its array references according to array_formula_offset" do
|
27
|
+
@arraying_cell.to_ruby.should == "def b3_array; @b3_array ||= m(a('d2','e2'),a('a3','a6')) { |r1,r2| r1+r2 }; end\ndef b3; @b3 ||= b3_array.array_formula_offset(0,0); end\n"
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should know its dependencies, and also apply them to the cells that it arrays with" do
|
31
|
+
array_cell = mock(:array_cell)
|
32
|
+
array_cell.should_receive(:dependencies=).with(["sheet1.a3", "sheet1.a4", "sheet1.a5", "sheet1.a6", "sheet1.d2", "sheet1.e2"])
|
33
|
+
@worksheet.should_receive(:cell).with('c3').and_return(array_cell)
|
34
|
+
@arraying_cell.work_out_dependencies
|
35
|
+
@arraying_cell.dependencies.should == ["sheet1.a3", "sheet1.a4", "sheet1.a5", "sheet1.a6", "sheet1.d2", "sheet1.e2"]
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe DependencyBuilder do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
SheetNames.instance.clear
|
7
|
+
SheetNames.instance['Other Sheet'] = 'sheet2'
|
8
|
+
@workbook = mock(:workbook, :named_references => {'named_cell' => 'sheet2.z10', 'named_cell2' => "sheet2.a('z10','ab10')"})
|
9
|
+
@worksheet1 = mock(:worksheet, :to_s => 'sheet1', :workbook => @workbook, :named_references => {'named_cell' => 'sheet1.a1'})
|
10
|
+
@worksheet2 = mock(:worksheet, :to_s => 'sheet2', :workbook => @workbook, :named_references => {})
|
11
|
+
@workbook.stub!(:worksheets => {'sheet1' => @worksheet1, 'sheet2' => @worksheet2 })
|
12
|
+
@cell = mock(:cell,:worksheet => @worksheet1, :reference => Reference.new('c30',@worksheet1))
|
13
|
+
@builder = DependencyBuilder.new(@cell)
|
14
|
+
end
|
15
|
+
|
16
|
+
def dependencies_for(formula)
|
17
|
+
ast = Formula.parse(formula)
|
18
|
+
ast.visit(@builder)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should know about single dependencies to referred cells" do
|
22
|
+
dependencies_for("A1").should == ['sheet1.a1']
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should know about multiple dependencies to referred cells " do
|
26
|
+
dependencies_for("A1+(B2*A1)").should == ['sheet1.a1','sheet1.b2']
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should know about dependences to other worksheets" do
|
30
|
+
dependencies_for("A1+'Other Sheet'!A1").should == ['sheet1.a1','sheet2.a1']
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should know about dependences in ranges" do
|
34
|
+
dependencies_for("A1:A3").should == ['sheet1.a1','sheet1.a2','sheet1.a3']
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should know about dependences in ranges on other sheets" do
|
38
|
+
dependencies_for("'Other Sheet'!A1:A3").should == ['sheet2.a1','sheet2.a2','sheet2.a3']
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should know about dependencies in named ranges" do
|
42
|
+
dependencies_for("named_cell").should == ['sheet1.a1']
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should know about dependencies in named ranges on other sheets" do
|
46
|
+
dependencies_for("'Other Sheet'!named_cell").should == ['sheet2.z10']
|
47
|
+
dependencies_for("'Other Sheet'!named_cell2").should == ['sheet2.aa10','sheet2.ab10','sheet2.z10']
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should know about dependencies created by table references" do
|
51
|
+
Table.new(@worksheet2,'Vectors','a1:b2',['ColA','Description'],1)
|
52
|
+
dependencies_for("Vectors[#all]").should == ["sheet2.a1","sheet2.a2",'sheet2.b1','sheet2.b2']
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should know about dependencies created by table references provided without table names" do
|
56
|
+
Table.new(@worksheet1,'Vectors','a1:c41',['ColA','Description','ColC'],1)
|
57
|
+
dependencies_for("[Description]").should == ["sheet1.b30"]
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should know about dependencies created by indirect formulae" do
|
61
|
+
Table.new(@worksheet2,'IndirectVectors','a1:b2',['ColA','Description'],1)
|
62
|
+
dependencies_for('INDIRECT("IndirectVectors[#all]")').should == ["sheet2.a1","sheet2.a2",'sheet2.b1','sheet2.b2']
|
63
|
+
end
|
64
|
+
|
65
|
+
it "and be able to deal with indirect formulae that call upon other vectors" do
|
66
|
+
Table.new(@worksheet2,'IndirectVectors2','a1:b10',['ColA','Description'],1)
|
67
|
+
@worksheet1.should_receive(:cell).with('c1').and_return(mock(:cell,:value_for_including => 'ColA',:can_be_replaced_with_value? => true))
|
68
|
+
dependencies_for('INDIRECT("IndirectVectors2["&C1&"]")').should == ["sheet1.c1","sheet2.a2", "sheet2.a3", "sheet2.a4", "sheet2.a5", "sheet2.a6", "sheet2.a7", "sheet2.a8", "sheet2.a9"]
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
@@ -0,0 +1,381 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
class FunctionTest
|
4
|
+
extend ExcelFunctions
|
5
|
+
def self.a1; 10.0; end
|
6
|
+
def self.a2; 100.0; end
|
7
|
+
def self.b1; 'Pear'; end
|
8
|
+
def self.b2; 'Bear'; end
|
9
|
+
def self.b3; 'Apple'; end
|
10
|
+
def self.zx10; 2.0; end
|
11
|
+
def self.zy10; 3.0; end
|
12
|
+
def self.zz10; 4.0; end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "set" do
|
16
|
+
it "should set the value of existing cells" do
|
17
|
+
class ValueSetTest
|
18
|
+
include ExcelFunctions
|
19
|
+
def a1; 10.0; end
|
20
|
+
end
|
21
|
+
v = ValueSetTest.new
|
22
|
+
v.a1.should == 10.0
|
23
|
+
v.set('a1',99.0)
|
24
|
+
v.a1.should == 99.0
|
25
|
+
v.set('a1',nil)
|
26
|
+
v.a1.should == 10.0
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "sum" do
|
31
|
+
it "should total areas correctly" do
|
32
|
+
FunctionTest.sum(1,2,3).should == 6
|
33
|
+
FunctionTest.sum(FunctionTest.a('a1','a2'),3).should == 113
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "choose" do
|
38
|
+
it "should return whichever argument is matched by the first argument" do
|
39
|
+
FunctionTest.choose(1,1,2,3,4).should == 1
|
40
|
+
FunctionTest.choose(2,1,2,3,4).should == 2
|
41
|
+
FunctionTest.choose(3,1,2,3,4).should == 3
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "abs" do
|
46
|
+
it "should return the absolute value of the input" do
|
47
|
+
FunctionTest.abs(1.0).should == 1
|
48
|
+
FunctionTest.abs(-1.0).should == 1.0
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "sumif" do
|
53
|
+
it "should only sum values in the area that meet the criteria" do
|
54
|
+
FunctionTest.sumif(FunctionTest.a('a1','a3'),10.0).should == 10.0
|
55
|
+
FunctionTest.sumif(FunctionTest.a('b1','b3'),'Bear',FunctionTest.a('a1','a2')).should == 100.0
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "sumifs" do
|
60
|
+
it "should only sum values that meet all of the criteria" do
|
61
|
+
FunctionTest.sumifs(FunctionTest.a('a1','a3'),FunctionTest.a('a1','a3'),10.0,FunctionTest.a('b1','b3'),'Bear').should == 0.0
|
62
|
+
FunctionTest.sumifs(FunctionTest.a('a1','a3'),FunctionTest.a('a1','a3'),10.0,FunctionTest.a('b1','b3'),'Pear').should == 10.0
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should work when single cells are given where ranges expected" do
|
66
|
+
FunctionTest.sumifs(0.143897265452564, "CAR", "CAR", "FCV", "FCV").should == 0.143897265452564
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "sumproduct" do
|
71
|
+
it "should multiply together and then sum the elements in row or column areas given as arguments" do
|
72
|
+
FunctionTest.sumproduct(FunctionTest.a('a1','a3'),FunctionTest.a('zx10','zz10')).should == 320.0
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "count" do
|
77
|
+
it "should count the number of numeric values in an area" do
|
78
|
+
FunctionTest.count(1,"two",FunctionTest.a('a1','a3')).should == 3
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "counta" do
|
83
|
+
it "should count the number of numeric or text values in an area" do
|
84
|
+
FunctionTest.counta(1,"two",FunctionTest.a('a1','a3')).should == 4
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe "average" do
|
89
|
+
it "should calculate the mean of its arguments" do
|
90
|
+
FunctionTest.average(1,2,3).should == 2
|
91
|
+
FunctionTest.average(1,"two",FunctionTest.a('a1','a3')).should == 111.0/3.0
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "subtotal" do
|
96
|
+
it "should calculate averages, counts, countas, sums depending on first argument" do
|
97
|
+
FunctionTest.subtotal(1.0,1,"two",FunctionTest.a('a1','a3')).should == 111.0/3.0 # Average
|
98
|
+
FunctionTest.subtotal(2.0,1,"two",FunctionTest.a('a1','a3')).should == 3 # count
|
99
|
+
FunctionTest.subtotal(3.0,1,"two",FunctionTest.a('a1','a3')).should == 4 # counta
|
100
|
+
FunctionTest.subtotal(9.0,1,"two",FunctionTest.a('a1','a3')).should == 111 # sum
|
101
|
+
|
102
|
+
FunctionTest.subtotal(101.0,1,"two",FunctionTest.a('a1','a3')).should == 111.0/3.0 # Average
|
103
|
+
FunctionTest.subtotal(102.0,1,"two",FunctionTest.a('a1','a3')).should == 3 # count
|
104
|
+
FunctionTest.subtotal(103.0,1,"two",FunctionTest.a('a1','a3')).should == 4 # counta
|
105
|
+
FunctionTest.subtotal(109.0,1,"two",FunctionTest.a('a1','a3')).should == 111 # sum
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe "match" do
|
110
|
+
it "should return the index of the first match of the first argument in the area" do
|
111
|
+
FunctionTest.match(10.0,FunctionTest.a('a1','a2'),0.0).should == 1
|
112
|
+
FunctionTest.match(100.0,FunctionTest.a('a1','a2'),0.0).should == 2
|
113
|
+
FunctionTest.match(1000.0,FunctionTest.a('a1','a2'),0.0).should == :na
|
114
|
+
FunctionTest.match('bEAr',FunctionTest.a('b1','b3'),0.0).should == 2
|
115
|
+
FunctionTest.match(1000.0,FunctionTest.a('a1','a2'),1.0).should == 2
|
116
|
+
FunctionTest.match(1.0,FunctionTest.a('a1','a2'),1.0).should == :na
|
117
|
+
FunctionTest.match('Care',FunctionTest.a('b1','b3'),-1.0).should == 1
|
118
|
+
FunctionTest.match('Zebra',FunctionTest.a('b1','b3'),-1.0).should == :na
|
119
|
+
FunctionTest.match('a',FunctionTest.a('b1','b3'),-1.0).should == 2
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
describe "index" do
|
124
|
+
it "should return the value at the row and column number given" do
|
125
|
+
FunctionTest.index(FunctionTest.a('a1','b1'),2.0).should == "Pear"
|
126
|
+
FunctionTest.index(FunctionTest.a('a1','a3'),2.0).should == 100.0
|
127
|
+
FunctionTest.index(FunctionTest.a('b1','b3'),2.0).should == "Bear"
|
128
|
+
FunctionTest.index(FunctionTest.a('a1','b3'),1.0,2.0).should == "Pear"
|
129
|
+
FunctionTest.index(FunctionTest.a('a1','b3'),2.0,1.0).should == 100.0
|
130
|
+
FunctionTest.index(FunctionTest.a('a1','b3'),3.0,1.0).should == 0.0
|
131
|
+
FunctionTest.index(FunctionTest.a('a1','b3'),3.0,3.0).should == :ref
|
132
|
+
FunctionTest.index(FunctionTest.a('a1','b3'),3.0).should == :ref
|
133
|
+
FunctionTest.index(FunctionTest.a('a1','b3'),1.0,0.0).to_a.should == [10.0,"Pear"]
|
134
|
+
FunctionTest.index(FunctionTest.a('a1','b3'),0.0,2.0).to_a.should == ["Pear","Bear","Apple"]
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe "max" do
|
139
|
+
it "should return the argument with the greatest value" do
|
140
|
+
FunctionTest.max(1,"two",FunctionTest.a('a1','a3')).should == 100
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
describe "min" do
|
145
|
+
it "should return the argument with the smallest value" do
|
146
|
+
FunctionTest.min(1000,"two",FunctionTest.a('a1','a3')).should == 10
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
describe "na" do
|
151
|
+
it "should return an na error" do
|
152
|
+
FunctionTest.na().should == :na
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
describe "iserr" do
|
157
|
+
it "should return true if passed a symbol" do
|
158
|
+
FunctionTest.iserr(:na).should == true
|
159
|
+
FunctionTest.iserr(:ref).should == true
|
160
|
+
end
|
161
|
+
|
162
|
+
it "should return false if passed anything else" do
|
163
|
+
FunctionTest.iserr(123).should == false
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
describe "excel_if" do
|
168
|
+
it "should return its second argument if its first argument is true" do
|
169
|
+
FunctionTest.excel_if(true,:second,:third).should == :second
|
170
|
+
end
|
171
|
+
|
172
|
+
it "should return its third argument if its first argument is false" do
|
173
|
+
FunctionTest.excel_if(false,:second,:third).should == :third
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
describe "iferror" do
|
178
|
+
it "should return its second value if there is an error in the first" do
|
179
|
+
FunctionTest.iferror(FunctionTest.index(FunctionTest.a('a1','b3'),3.0,1.0),"Not found").should == 0.0
|
180
|
+
FunctionTest.iferror(FunctionTest.index(FunctionTest.a('a1','b3'),3.0,3.0),"Not found").should == "Not found"
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
describe "excel_and" do
|
185
|
+
it "should return true if all its arguments are true" do
|
186
|
+
FunctionTest.excel_and(true,true,true) == true
|
187
|
+
end
|
188
|
+
|
189
|
+
it "should return false if any of its arguments are false" do
|
190
|
+
FunctionTest.excel_and(true,false,true) == false
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
describe "excel_or" do
|
195
|
+
it "should return false if all of its arguments are false" do
|
196
|
+
FunctionTest.excel_or(false,false,false) == false
|
197
|
+
end
|
198
|
+
|
199
|
+
it "should return true if any of its arguments are true" do
|
200
|
+
FunctionTest.excel_or(false,false,true) == true
|
201
|
+
FunctionTest.excel_or(true,true,true) == true
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
describe "left" do
|
206
|
+
it "should return the left n characters from a string" do
|
207
|
+
FunctionTest.left("ONE").should == "O"
|
208
|
+
FunctionTest.left("ONE",1).should == "O"
|
209
|
+
FunctionTest.left("ONE",3).should == "ONE"
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
describe "find" do
|
214
|
+
it "should find the first occurrence of one string in another" do
|
215
|
+
FunctionTest.find("one","onetwothree").should == 1
|
216
|
+
FunctionTest.find("one","twoonethree").should == 4
|
217
|
+
FunctionTest.find("one","twoonthree").should == :value
|
218
|
+
end
|
219
|
+
|
220
|
+
it "should find the first occurrence of one string in another after a given index" do
|
221
|
+
FunctionTest.find("one","onetwothree",1).should == 1
|
222
|
+
FunctionTest.find("one","twoonethree",5).should == :value
|
223
|
+
FunctionTest.find("one","oneone",2).should == 4
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
describe "ability to respond to empty cell references" do
|
228
|
+
it "should return 0 if a reference is made to an empty cell" do
|
229
|
+
FunctionTest.a23.should == 0.0
|
230
|
+
end
|
231
|
+
|
232
|
+
it "should return an object that is kind_of?(Empty) if a reference is made to an empty cell" do
|
233
|
+
FunctionTest.a23.should be_kind_of(Empty)
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
describe "ability to respond to the a, r and c methods for creating area references" do
|
238
|
+
it "should return an Area object for a(start_cell,end_cell)" do
|
239
|
+
FunctionTest.a('a1','b10').should be_kind_of(Area)
|
240
|
+
end
|
241
|
+
|
242
|
+
it "should return a Columns object for c(start_column_as_text,end_column_as_text)" do
|
243
|
+
FunctionTest.c('a','b').should be_kind_of(Columns)
|
244
|
+
end
|
245
|
+
|
246
|
+
it "should return a Rows object for r(start_row_number,end_row_number)" do
|
247
|
+
FunctionTest.r(1,10).should be_kind_of(Rows)
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
class FunctionTest2
|
252
|
+
include RubyFromExcel::ExcelFunctions
|
253
|
+
def initialize
|
254
|
+
@worksheet_names = {'first sheet'=>'sheet1'}
|
255
|
+
@workbook_tables = {"FirstTable"=>'Table.new(sheet1,"FirstTable","A1:C3",["ColA", "ColB", "ColC"],1)'}
|
256
|
+
end
|
257
|
+
def sheet1
|
258
|
+
self
|
259
|
+
end
|
260
|
+
def a1; "Cell A1"; end
|
261
|
+
def a2; "Middle A2"; end
|
262
|
+
def a3; "Total A3"; end
|
263
|
+
def to_s; 'sheet1'; end
|
264
|
+
end
|
265
|
+
|
266
|
+
describe "ability to return a sheet from the full excel name using s('excel name')" do
|
267
|
+
it "should return a string for known sheets" do
|
268
|
+
sheet = FunctionTest2.new
|
269
|
+
sheet.s('first sheet').should == sheet
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
describe "ability to return the table for a given name using t('table name')" do
|
274
|
+
it "should return a string for known sheets" do
|
275
|
+
FunctionTest2.new.t('FirstTable').reference_for('[#Totals],[ColA]').to_s.should == 'sheet1.a3'
|
276
|
+
end
|
277
|
+
|
278
|
+
it "should return a lowercase form of the class name as variable_name for compatibility with Table" do
|
279
|
+
FunctionTest.variable_name.should == "class"
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
describe "indirect method" do
|
284
|
+
it "should deal with the simple case where the indirect is pointing to a sheet or cell" do
|
285
|
+
FunctionTest2.new.indirect("A$1$").should == "Cell A1"
|
286
|
+
end
|
287
|
+
|
288
|
+
it "should also work with sheet name references" do
|
289
|
+
FunctionTest2.new.indirect("'first sheet'!A$1$").should == "Cell A1"
|
290
|
+
end
|
291
|
+
|
292
|
+
it "should also work with table references" do
|
293
|
+
FunctionTest2.new.indirect("FirstTable[[#Totals],[ColA]]").should == "Total A3"
|
294
|
+
FunctionTest2.new.indirect("FirstTable[[#This Row],[ColA]]",'B2').should == "Middle A2"
|
295
|
+
end
|
296
|
+
|
297
|
+
end
|
298
|
+
|
299
|
+
describe "boolean values" do
|
300
|
+
it "should be possible to treat true values as 1.0 when using them in arithmetic" do
|
301
|
+
(true*5.0).should == 5.0
|
302
|
+
(true+1.0).should == 2.0
|
303
|
+
(true/5.0).should == 0.2
|
304
|
+
(true-2.0).should == -1.0
|
305
|
+
(5.0*true).should == 5.0
|
306
|
+
(1.0+true).should == 2.0
|
307
|
+
(5.0/true).should == 5.0
|
308
|
+
(2.0-true).should == 1.0
|
309
|
+
end
|
310
|
+
|
311
|
+
it "should be possible to treat false values as 0.0 when using them in arithmetic" do
|
312
|
+
(false*5.0).should == 0.0
|
313
|
+
(false+1.0).should == 1.0
|
314
|
+
(false/5.0).should == 0.0
|
315
|
+
(false-2.0).should == -2.0
|
316
|
+
(5.0*false).should == 0.0
|
317
|
+
(1.0+false).should == 1.0
|
318
|
+
(5.0/false).should == (5.0/0.0)
|
319
|
+
(2.0-false).should == 2.0
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
describe "symbols" do
|
324
|
+
it "should be able to have infix operators applied to them" do
|
325
|
+
(-:one).should == :one
|
326
|
+
end
|
327
|
+
|
328
|
+
it "should be able to participate in arithmetic" do
|
329
|
+
(1 + :na).should == :na
|
330
|
+
(1 - :na).should == :na
|
331
|
+
(1 * :na).should == :na
|
332
|
+
(1 / :na).should == :na
|
333
|
+
(:na + 1).should == :na
|
334
|
+
(:na - 1).should == :na
|
335
|
+
(:na * 1).should == :na
|
336
|
+
(:na / 1).should == :na
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
describe "Strings", "should be able to operate as numbers if they appear to be numbers" do
|
341
|
+
it "should be able to have infix operators applied to them" do
|
342
|
+
(-"10").should == -10.0
|
343
|
+
end
|
344
|
+
|
345
|
+
it "should be able to participate in arithmetic" do
|
346
|
+
(1 + "10").should == 11.0
|
347
|
+
(1 - "10").should == -9.0
|
348
|
+
(1 * "10").should == 10.0
|
349
|
+
(1 / "10").should == 0.1
|
350
|
+
("10" + 1).should == 11.0
|
351
|
+
("10" + "20").should == 30.0
|
352
|
+
("10" + " apples").should == "10 apples"
|
353
|
+
("10" - 1).should == 9.0
|
354
|
+
("10" * 2).should == 20.0
|
355
|
+
("10" / 1).should == 10.0
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
class CacheFuncitonTest
|
360
|
+
attr_accessor :method_executed
|
361
|
+
include RubyFromExcel::ExcelFunctions
|
362
|
+
def a23
|
363
|
+
@method_executed = true
|
364
|
+
"one"
|
365
|
+
end
|
366
|
+
|
367
|
+
def other_function
|
368
|
+
@method_executed = true
|
369
|
+
"one"
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
describe "array formula operations" do
|
374
|
+
|
375
|
+
it "m(expression) should create an ExcelMatrixCollection, carry out an excel_map using the associated block and return an ExcelMatrix" do
|
376
|
+
m = FunctionTest.m("one",[[3]],[[:a,:b,:c],[1,2,3]],ExcelMatrix.new([:a,:b,:c])) { |i,j,k| "#{i}#{j}#{k}" }
|
377
|
+
m.should be_kind_of(ExcelMatrix)
|
378
|
+
m.values.should == [["one3a", "one3b", "one3c"], ["one31", "one32", "one33"]]
|
379
|
+
end
|
380
|
+
|
381
|
+
end
|