rubyfromexcel 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- 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,72 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe Reference do
|
4
|
+
it "converts excel A1 style references to ruby method calls" do
|
5
|
+
Reference.new("A1").to_ruby.should == "a1"
|
6
|
+
Reference.new("$AA$103").to_ruby.should == "aa103"
|
7
|
+
Reference.new("ZZ1").to_ruby.should == "zz1"
|
8
|
+
end
|
9
|
+
|
10
|
+
it "offsets references if required, dealing with any absolute constraints" do
|
11
|
+
Reference.new("A1").shift!([1,1]).to_ruby.should == "b2"
|
12
|
+
Reference.new("A$1").shift!([1,1]).to_ruby.should == "b1"
|
13
|
+
Reference.new("$A1").shift!([1,1]).to_ruby.should == "a2"
|
14
|
+
Reference.new("$A$1").shift!([1,1]).to_ruby.should == "a1"
|
15
|
+
end
|
16
|
+
|
17
|
+
it "manages wrap on column numbering when offsetting" do
|
18
|
+
Reference.new("Z1").shift!([1,1]).to_ruby.should == "aa2"
|
19
|
+
Reference.new("ZZ1").shift!([1,1]).to_ruby.should == "aaa2"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "deals with a nil value as an offset, treating it as offset [0,0]" do
|
23
|
+
Reference.new("A1").shift!(nil).to_ruby.should == "a1"
|
24
|
+
end
|
25
|
+
|
26
|
+
it "converts columns to integers" do
|
27
|
+
Reference.column_to_integer("A").should == 1
|
28
|
+
Reference.column_to_integer("B").should == 2
|
29
|
+
Reference.column_to_integer("Z").should == 26
|
30
|
+
Reference.column_to_integer("AA").should == 27
|
31
|
+
Reference.column_to_integer("AB").should == 28
|
32
|
+
end
|
33
|
+
|
34
|
+
it "converts integers to columns" do
|
35
|
+
Reference.integer_to_column(1).should == "a"
|
36
|
+
Reference.integer_to_column(2).should == "b"
|
37
|
+
Reference.integer_to_column(26).should == "z"
|
38
|
+
Reference.integer_to_column(27).should == "aa"
|
39
|
+
Reference.integer_to_column(28).should == "ab"
|
40
|
+
end
|
41
|
+
|
42
|
+
it "raises an exception if asked for a column number < 1 (Excel column numbering starts at 1)" do
|
43
|
+
lambda { Reference.integer_to_column(0) }.should raise_error(Exception)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "can return the column_number and row_number for a reference" do
|
47
|
+
Reference.new("AB1").column_number.should == 28
|
48
|
+
Reference.new("AB1").row_number.should == 1
|
49
|
+
end
|
50
|
+
|
51
|
+
it "converts column and row numbers into ruby versions of cell references" do
|
52
|
+
Reference.ruby_for(28,1).should == "ab1"
|
53
|
+
Reference.ruby_for(16384,16384).should == "xfd16384"
|
54
|
+
Reference.ruby_for(26,10).should == "z10"
|
55
|
+
Reference.ruby_for(701,10).should == "zy10"
|
56
|
+
Reference.ruby_for(702,10).should == "zz10"
|
57
|
+
Reference.ruby_for(703,10).should == "aaa10"
|
58
|
+
Reference.ruby_for(704,10).should == "aab10"
|
59
|
+
Reference.ruby_for(1378,10).should == "azz10"
|
60
|
+
Reference.ruby_for(2054,10).should == "bzz10"
|
61
|
+
end
|
62
|
+
|
63
|
+
it "returns its value as a ruby_method style reference when to_s is called" do
|
64
|
+
Reference.new("$AB$1").to_s.should == "ab1"
|
65
|
+
end
|
66
|
+
|
67
|
+
it "returns an array with [row_offset,column_offset] when subtracted from another reference" do
|
68
|
+
(Reference.new("A1") - Reference.new("A1")).should == [0,0]
|
69
|
+
(Reference.new("B2") - Reference.new("A1")).should == [1,1]
|
70
|
+
(Reference.new("AA10") - Reference.new("Z9")).should == [1,1]
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe Relationships do
|
4
|
+
|
5
|
+
relationship_xml =<<END
|
6
|
+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
7
|
+
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
|
8
|
+
<Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet3.xml"/>
|
9
|
+
<Relationship Id="rId7" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/calcChain" Target="calcChain.xml"/>
|
10
|
+
<Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet2.xml"/>
|
11
|
+
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml"/>
|
12
|
+
<Relationship Id="rId6" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings" Target="sharedStrings.xml"/>
|
13
|
+
<Relationship Id="rId5" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>
|
14
|
+
<Relationship Id="rId4" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" Target="theme/theme1.xml"/>
|
15
|
+
</Relationships>
|
16
|
+
END
|
17
|
+
|
18
|
+
it "it should be created from xml be equivalent to a Hash where the keys are the relationship ids and the values are the target files" do
|
19
|
+
wr = Relationships.new(Nokogiri::XML(relationship_xml).root)
|
20
|
+
wr['rId3'].should == 'worksheets/sheet3.xml'
|
21
|
+
end
|
22
|
+
|
23
|
+
it "when given a root_directory will prepend that to the target files" do
|
24
|
+
wr = Relationships.new(Nokogiri::XML(relationship_xml).root, root_directory = '/usr/local')
|
25
|
+
wr['rId3'].should == '/usr/local/worksheets/sheet3.xml'
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should have a Relationships.for_file(path_to_workkbook) that loads the xml automatically" do
|
29
|
+
File.should_receive(:open).with('/usr/local/excel_dir/xl/_rels/workbook.xml.rels').and_yield(StringIO.new(relationship_xml))
|
30
|
+
File.should_receive(:exist?).with('/usr/local/excel_dir/xl/_rels/workbook.xml.rels').and_return(true)
|
31
|
+
|
32
|
+
wr = Relationships.for_file('/usr/local/excel_dir/xl/workbook.xml')
|
33
|
+
wr['rId3'].should == '/usr/local/excel_dir/xl/worksheets/sheet3.xml'
|
34
|
+
|
35
|
+
File.should_receive(:open).with('/usr/local/excel_dir/xl/worksheets/_rels/sheet1.xml.rels').and_yield(StringIO.new(relationship_xml))
|
36
|
+
File.should_receive(:exist?).with('/usr/local/excel_dir/xl/worksheets/_rels/sheet1.xml.rels').and_return(true)
|
37
|
+
wr = Relationships.for_file('/usr/local/excel_dir/xl/worksheets/sheet1.xml')
|
38
|
+
wr['rId3'].should == '/usr/local/excel_dir/xl/worksheets/worksheets/sheet3.xml'
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should return an empty Relationships if relationships xml file doesn't exist" do
|
43
|
+
wr = Relationships.for_file('missing_file')
|
44
|
+
wr.size.should == 0
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should pick out the sharedStrings relationship and put in an accessor" do
|
48
|
+
wr = Relationships.new(Nokogiri::XML(relationship_xml).root)
|
49
|
+
wr.shared_strings.should == 'sharedStrings.xml'
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe RuntimeFormulaBuilder, "For parsing indirect references" do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@worksheet = mock(:worksheet)
|
7
|
+
@builder = RuntimeFormulaBuilder.new(@worksheet)
|
8
|
+
end
|
9
|
+
|
10
|
+
def ruby_for(formula)
|
11
|
+
ast = Formula.parse(formula)
|
12
|
+
ast.visit(@builder)
|
13
|
+
end
|
14
|
+
# These are the new conversions
|
15
|
+
it "should convert sheet names to ruby methods" do
|
16
|
+
ruby_for("asheetname!A3:B20").should == "s('asheetname').a('a3','b20')"
|
17
|
+
ruby_for("'a long sheet name with spaces'!A3:B20").should == "s('a long sheet name with spaces').a('a3','b20')"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should convert table names to references" do
|
21
|
+
table = mock(:table)
|
22
|
+
table.should_receive('reference_for').with('[#totals],[Description]',nil).and_return("cell reference")
|
23
|
+
@worksheet.should_receive('t').with('Vectors').and_return(table)
|
24
|
+
ruby_for("Vectors[[#totals],[Description]]").should == "cell reference"
|
25
|
+
end
|
26
|
+
|
27
|
+
# All these are the standard conversions
|
28
|
+
it "Should convert simple references to ruby method calls" do
|
29
|
+
ruby_for("AA1").should == "aa1"
|
30
|
+
ruby_for("$AA$100").should == "aa100"
|
31
|
+
ruby_for("A$1").should == "a1"
|
32
|
+
ruby_for("$A1").should == "a1"
|
33
|
+
ruby_for("I9+J9+K9+P9+Q9").should == "i9+j9+k9+p9+q9"
|
34
|
+
end
|
35
|
+
|
36
|
+
it "Should convert area references to a(start,end) functions" do
|
37
|
+
ruby_for('$A$1:BZ$2000').should == "a('a1','bz2000')"
|
38
|
+
end
|
39
|
+
|
40
|
+
it "Should convert column references to c(start,end) functions" do
|
41
|
+
ruby_for('A:ZZ').should == "c('a','zz')"
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should convert row references to r(start,end) functions" do
|
45
|
+
ruby_for('1:1000').should == 'r(1,1000)'
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should convert named references to ruby methods" do
|
49
|
+
ruby_for("SUM(OneAnd2)").should == "sum(one_and2)"
|
50
|
+
ruby_for("ReferenceOne").should == "reference_one"
|
51
|
+
ruby_for("Reference.2").should == "reference_2"
|
52
|
+
ruby_for("-($AG70+$X70)*EF.NaturalGas.N2O").should == "-(ag70+x70)*ef_natural_gas_n2o"
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe SharedFormulaBuilder, "Formulas with shared_formula_offsets" do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@builder = SharedFormulaBuilder.new
|
7
|
+
@builder.shared_formula_offset = [1,1]
|
8
|
+
end
|
9
|
+
|
10
|
+
def ruby_for(formula)
|
11
|
+
ast = Formula.parse(formula)
|
12
|
+
ast.visit(@builder)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should move individual references appropriately" do
|
16
|
+
ruby_for("A1").should == "b2"
|
17
|
+
ruby_for("A$1").should == "b1"
|
18
|
+
ruby_for("$A1").should == "a2"
|
19
|
+
ruby_for("$A$1").should == "a1"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should move several references in the same formula" do
|
23
|
+
ruby_for("A1+B2").should == "b2+c3"
|
24
|
+
ruby_for("A$1+B$1").should == "b1+c1"
|
25
|
+
ruby_for("$A1+$B1").should == "a2+b2"
|
26
|
+
ruby_for("$A$1+$B$1").should == "a1+b1"
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe SharedFormulaCell do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@cell = SharedFormulaCell.new(
|
7
|
+
mock(:worksheet,:class_name => 'Sheet1', :to_s => 'sheet1'),
|
8
|
+
Nokogiri::XML('<c r="W8" s="49"><f t="shared" si="2"/><v>1</v></c>').root
|
9
|
+
)
|
10
|
+
@cell.shared_formula = Formula.parse("$A$1+B2")
|
11
|
+
@cell.shared_formula_offset = [1,1]
|
12
|
+
end
|
13
|
+
|
14
|
+
it "it is given a pre-parsed formula and offsets its references by the amount of its shared_formula_offset" do
|
15
|
+
@cell.to_ruby.should == "def w8; @w8 ||= a1+c3; end\n"
|
16
|
+
@cell.to_test.should == "it 'cell w8 should equal 1.0' do\n sheet1.w8.should be_close(1.0,0.1)\nend\n\n"
|
17
|
+
end
|
18
|
+
|
19
|
+
it "knows what it depends on" do
|
20
|
+
@cell.work_out_dependencies
|
21
|
+
@cell.dependencies.should == ['sheet1.a1','sheet1.c3']
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe SharedFormulaDependencyBuilder 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 = SharedFormulaDependencyBuilder.new(@cell)
|
14
|
+
@builder.shared_formula_offset = [1,1]
|
15
|
+
end
|
16
|
+
|
17
|
+
def ruby_for(formula)
|
18
|
+
ast = Formula.parse(formula)
|
19
|
+
ast.visit(@builder)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should offset single cell dependencies appropriately" do
|
23
|
+
ruby_for("A1").should == ['sheet1.b2']
|
24
|
+
ruby_for("$A1").should == ['sheet1.a2']
|
25
|
+
ruby_for("A$1").should == ['sheet1.b1']
|
26
|
+
ruby_for("$A$1").should == ['sheet1.a1']
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should offset dependences on other worksheets" do
|
30
|
+
ruby_for("A1+'Other Sheet'!A1").should == ['sheet1.b2','sheet2.b2']
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should offset dependences in ranges" do
|
34
|
+
ruby_for("A1:A3").should == ['sheet1.b2','sheet1.b3','sheet1.b4']
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should not offset dependencies in named_cells" do
|
38
|
+
ruby_for("named_cell").should == ['sheet1.a1']
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should not offset dependencies created by table references" do
|
42
|
+
Table.new(@worksheet2,'Vectors','a1:b2',['ColA','Description'],1)
|
43
|
+
ruby_for("Vectors[#all]").should == ["sheet2.a1","sheet2.a2",'sheet2.b1','sheet2.b2']
|
44
|
+
Table.new(@worksheet1,'Vectors','a1:d41',['ColA','Description','ColC'],1)
|
45
|
+
ruby_for("[Description]").should == ["sheet1.b30"]
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe SharedStrings do
|
4
|
+
|
5
|
+
it "should return a shared string when provided with an index" do
|
6
|
+
xml = Nokogiri::XML('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
7
|
+
<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="2" uniqueCount="2"><si><t>This a second shared string</t><phoneticPr fontId="3" type="noConversion"/></si><si><r><t>This is, h</t></r><r><rPr><b/><sz val="10"/><rFont val="Verdana"/></rPr><t>opefully, the first</t></r><r><rPr><sz val="10"/><rFont val="Verdana"/></rPr><t xml:space="preserve"> shared string</t></r><phoneticPr fontId="3" type="noConversion"/></si></sst>')
|
8
|
+
shared_strings = SharedStrings.instance
|
9
|
+
shared_strings.clear
|
10
|
+
shared_strings.load_strings_from_xml xml
|
11
|
+
SharedStrings.shared_string_for(0).should == "This a second shared string"
|
12
|
+
SharedStrings.shared_string_for(1).should == "This is, hopefully, the first shared string"
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe SharingFormulaCell do
|
4
|
+
it "it is given a pre-parsed formula and offsets its references by the amount of its shared_formula_offset" do
|
5
|
+
worksheet = mock(:worksheet,:class_name => 'Sheet1',:to_s => 'sheet1')
|
6
|
+
sharing_cell = SharingFormulaCell.new(
|
7
|
+
worksheet,
|
8
|
+
Nokogiri::XML('<c r="W7" s="49"><f t="shared" ref="W7:W8" si="2">A1+B2</f><v>1</v></c>').root
|
9
|
+
)
|
10
|
+
shared_cell = SharedFormulaCell.new(
|
11
|
+
worksheet,
|
12
|
+
Nokogiri::XML('<c r="W8" s="49"><f t="shared" si="2"></f><v>2</v></c>').root
|
13
|
+
)
|
14
|
+
worksheet.should_receive(:cell).with('w8').and_return(shared_cell)
|
15
|
+
|
16
|
+
sharing_cell.alter_other_cells_if_required
|
17
|
+
sharing_cell.to_ruby.should == "def w7; @w7 ||= a1+b2; end\n"
|
18
|
+
shared_cell.to_ruby.should == "def w8; @w8 ||= a2+b3; end\n"
|
19
|
+
end
|
20
|
+
|
21
|
+
it "knows what it depends upon" do
|
22
|
+
worksheet = mock(:worksheet,:class_name => 'Sheet1',:to_s => 'sheet1')
|
23
|
+
sharing_cell = SharingFormulaCell.new(
|
24
|
+
worksheet,
|
25
|
+
Nokogiri::XML('<c r="W7" s="49"><f t="shared" ref="W7:W8" si="2">A1+B2</f><v>1</v></c>').root
|
26
|
+
)
|
27
|
+
shared_cell = SharedFormulaCell.new(
|
28
|
+
worksheet,
|
29
|
+
Nokogiri::XML('<c r="W8" s="49"><f t="shared" si="2"></f><v>2</v></c>').root
|
30
|
+
)
|
31
|
+
worksheet.should_receive(:cell).with('w8').and_return(shared_cell)
|
32
|
+
|
33
|
+
sharing_cell.alter_other_cells_if_required
|
34
|
+
sharing_cell.work_out_dependencies
|
35
|
+
shared_cell.work_out_dependencies
|
36
|
+
sharing_cell.dependencies.should == ['sheet1.a1','sheet1.b2']
|
37
|
+
shared_cell.dependencies.should == ['sheet1.a2','sheet1.b3']
|
38
|
+
end
|
39
|
+
|
40
|
+
it "it should cope if it is sharing only with itself" do
|
41
|
+
worksheet = mock(:worksheet,:class_name => 'Sheet1')
|
42
|
+
sharing_cell = SharingFormulaCell.new(
|
43
|
+
worksheet,
|
44
|
+
Nokogiri::XML('<c r="W7" s="49"><f t="shared" ref="W7" si="2">A1+B2</f><v>1</v></c>').root
|
45
|
+
)
|
46
|
+
|
47
|
+
sharing_cell.alter_other_cells_if_required
|
48
|
+
sharing_cell.to_ruby.should == "def w7; @w7 ||= a1+b2; end\n"
|
49
|
+
end
|
50
|
+
|
51
|
+
it "it should cope if it is sharing to a formula that doesn't exist" do
|
52
|
+
worksheet = mock(:worksheet,:class_name => 'Sheet1')
|
53
|
+
sharing_cell = SharingFormulaCell.new(
|
54
|
+
worksheet,
|
55
|
+
Nokogiri::XML('<c r="W7" s="49"><f t="shared" ref="W7:W8" si="2">A1+B2</f><v>1</v></c>').root
|
56
|
+
)
|
57
|
+
worksheet.should_receive(:cell).with('w8').and_return(nil)
|
58
|
+
|
59
|
+
sharing_cell.alter_other_cells_if_required
|
60
|
+
sharing_cell.to_ruby.should == "def w7; @w7 ||= a1+b2; end\n"
|
61
|
+
end
|
62
|
+
|
63
|
+
it "it should cope if it is sharing with a cell that has its own formula" do
|
64
|
+
worksheet = mock(:worksheet,:class_name => 'Sheet1')
|
65
|
+
sharing_cell = SharingFormulaCell.new(
|
66
|
+
worksheet,
|
67
|
+
Nokogiri::XML('<c r="W7" s="49"><f t="shared" ref="W7:W8" si="2">A1+B2</f><v>1</v></c>').root
|
68
|
+
)
|
69
|
+
shared_cell = SimpleFormulaCell.new(
|
70
|
+
worksheet,
|
71
|
+
Nokogiri::XML('<c r="W8" s="49"><f>AND(1,2)</f><v>1</v></c>').root
|
72
|
+
)
|
73
|
+
worksheet.should_receive(:cell).with('w8').and_return(shared_cell)
|
74
|
+
|
75
|
+
sharing_cell.alter_other_cells_if_required
|
76
|
+
sharing_cell.to_ruby.should == "def w7; @w7 ||= a1+b2; end\n"
|
77
|
+
shared_cell.to_ruby.should == "def w8; @w8 ||= excel_and(1.0,2.0); end\n"
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe SimpleFormulaCell, "when result is a number" do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@cell = SimpleFormulaCell.new(
|
7
|
+
mock(:worksheet,:class_name => 'Sheet1', :to_s => 'sheet1'),
|
8
|
+
Nokogiri::XML("<c r=\"C3\"><f>1+2</f><v>3</v></c>").root
|
9
|
+
)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should use the FormulaPeg to create ruby code for a formula and turn that into a method" do
|
13
|
+
@cell.to_ruby.should == "def c3; @c3 ||= 1.0+2.0; end\n"
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should create a test for the ruby code" do
|
17
|
+
@cell.to_test.should == %Q{it 'cell c3 should equal 3.0' do\n sheet1.c3.should be_close(3.0,0.3)\nend\n\n}
|
18
|
+
end
|
19
|
+
|
20
|
+
it "has a method that says it cannot be replaced with its value" do
|
21
|
+
@cell.can_be_replaced_with_value?.should be_false
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
describe SimpleFormulaCell, "when result is a boolean" do
|
27
|
+
|
28
|
+
before do
|
29
|
+
@cell = SimpleFormulaCell.new(
|
30
|
+
mock(:worksheet,:class_name => 'Sheet1', :to_s => 'sheet1'),
|
31
|
+
Nokogiri::XML('<c r="C3" t="b"><f>AND(1,2)</f><v>TRUE</v></c>').root
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should use the FormulaPeg to create ruby code for a formula and turn that into a method" do
|
36
|
+
@cell.to_ruby.should == "def c3; @c3 ||= excel_and(1.0,2.0); end\n"
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should create a test for the ruby code" do
|
40
|
+
@cell.to_test.should == %Q{it 'cell c3 should equal true' do\n sheet1.c3.should == true\nend\n\n}
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
describe SimpleFormulaCell, "when result is a string" do
|
46
|
+
|
47
|
+
before do
|
48
|
+
@cell = SimpleFormulaCell.new(
|
49
|
+
mock(:worksheet,:class_name => 'Sheet1', :to_s => 'sheet1'),
|
50
|
+
Nokogiri::XML('<c r="C3" t="str"><f>"Hello "&A1</f><v>Hello Bob</v></c>').root
|
51
|
+
)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should use the FormulaPeg to create ruby code for a formula and turn that into a method" do
|
55
|
+
@cell.to_ruby.should == %Q{def c3; @c3 ||= "Hello "+a1.to_s; end\n}
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should create a test for the ruby code" do
|
59
|
+
@cell.to_test.should == %Q{it 'cell c3 should equal "Hello Bob"' do\n sheet1.c3.should == "Hello Bob"\nend\n\n}
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
describe SimpleFormulaCell, "can list the cells upon which it depends" do
|
65
|
+
|
66
|
+
before do
|
67
|
+
@cell = SimpleFormulaCell.new(
|
68
|
+
mock(:worksheet,:class_name => 'Sheet1', :to_s => 'sheet1'),
|
69
|
+
Nokogiri::XML("<c r=\"C3\" t=\"str\"><f>A1</f><v>Hello Bob</v></c>").root
|
70
|
+
)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "in simple cases knows what it depends upon" do
|
74
|
+
@cell.work_out_dependencies
|
75
|
+
@cell.dependencies.should == ['sheet1.a1']
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe SingleCellArrayFormulaBuilder, "Single cell array formulas" do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@builder = SingleCellArrayFormulaBuilder.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def ruby_for(formula)
|
10
|
+
ast = Formula.parse(formula)
|
11
|
+
ast.visit(@builder)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should wrap operations in an array_operation(left,operation,right) methods" do
|
15
|
+
ruby_for("SUM(F$437:F$449/$M$150:$M$162*($B454=$F$149:$N$149)*($F$150:$N$162))").should == "sum(m(a('f437','f449'),a('m150','m162'),(m(b454,a('f149','n149')) { |r1,r2| r1==r2 }),(a('f150','n162'))) { |r1,r2,r3,r4| r1/r2*r3*r4 })"
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe SingleCellArrayFormulaCell do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@cell = SingleCellArrayFormulaCell.new(
|
7
|
+
mock(:worksheet,:class_name => 'Sheet1', :to_s => 'sheet1'),
|
8
|
+
Nokogiri::XML("<c r=\"C3\"><f t=\"array\" ref=\"C3\">SUM(F$437:F$449/$M$150:$M$162*($B454=$F$149:$N$149)*($F$150:$N$162))</f><v>3</v></c>").root
|
9
|
+
)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should use the FormulaPeg to create ruby code for a formula and turn that into a method" do
|
13
|
+
@cell.to_ruby.should == "def c3; @c3 ||= sum(m(a('f437','f449'),a('m150','m162'),(m(b454,a('f149','n149')) { |r1,r2| r1==r2 }),(a('f150','n162'))) { |r1,r2,r3,r4| r1/r2*r3*r4 }); end\n"
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should create a test for the ruby code" do
|
17
|
+
@cell.to_test.should == %Q{it 'cell c3 should equal 3.0' do\n sheet1.c3.should be_close(3.0,0.3)\nend\n\n}
|
18
|
+
end
|
19
|
+
|
20
|
+
it "in can list the cells upon which it depends" do
|
21
|
+
@cell.work_out_dependencies
|
22
|
+
dependencies = @cell.dependencies
|
23
|
+
dependencies.include?('sheet1.g151').should be_true
|
24
|
+
end
|
25
|
+
end
|
data/spec/spec_helper.rb
ADDED
data/spec/table_spec.rb
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe Table do
|
4
|
+
|
5
|
+
def table
|
6
|
+
table_xml =<<-END
|
7
|
+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
8
|
+
<table xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" id="1" name="FirstTable" displayName="FirstTable" ref="B3:D7" totalsRowCount="1">
|
9
|
+
<autoFilter ref="B3:D6"/>
|
10
|
+
<tableColumns count="3">
|
11
|
+
<tableColumn id="1" name="ColA" totalsRowLabel="Total"/>
|
12
|
+
<tableColumn id="2" name="ColB" totalsRowFunction="custom" dataDxfId="1">
|
13
|
+
<calculatedColumnFormula>FirstTable[[#This Row],[ColA]]+FirstTable[[#This Row],[ColC]]</calculatedColumnFormula>
|
14
|
+
<totalsRowFormula>AVERAGE(FirstTable[ColB])</totalsRowFormula>
|
15
|
+
</tableColumn>
|
16
|
+
<tableColumn id="3" name="ColC" totalsRowFunction="count" dataDxfId="0">
|
17
|
+
<calculatedColumnFormula>3*FirstTable[[#This Row],[ColA]]</calculatedColumnFormula>
|
18
|
+
</tableColumn>
|
19
|
+
</tableColumns>
|
20
|
+
<tableStyleInfo name="TableStyleLight16" showFirstColumn="1" showLastColumn="1" showRowStripes="1" showColumnStripes="1"/>
|
21
|
+
</table>
|
22
|
+
END
|
23
|
+
@worksheet ||= mock(:worksheet,:to_s => 'sheet1')
|
24
|
+
@table ||= Table.from_xml(@worksheet, Nokogiri::XML(table_xml).root)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should know its name" do
|
28
|
+
table.name.should == 'FirstTable'
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should know the area (returned in #all) that it covers" do
|
32
|
+
table.all.start_cell.to_s.should == 'b3'
|
33
|
+
table.all.end_cell.to_s.should == 'd7'
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should know the area (returned in #data) covered by its data" do
|
37
|
+
table.data.start_cell.to_s.should == 'b4'
|
38
|
+
table.data.end_cell.to_s.should == 'd6'
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should know the area covered by its headers" do
|
42
|
+
table.headers.start_cell.to_s.should == 'b3'
|
43
|
+
table.headers.end_cell.to_s.should == 'd3'
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should know the area covered by its totals" do
|
47
|
+
table.totals.start_cell.to_s.should == 'b7'
|
48
|
+
table.totals.end_cell.to_s.should == 'd7'
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should know the area covered by each of its columns (excluding the headers and the totals)" do
|
52
|
+
table.column('ColA').start_cell.to_s.should == 'b4'
|
53
|
+
table.column('ColA').end_cell.to_s.should == 'b6'
|
54
|
+
table.column('ColC').start_cell.to_s.should == 'd4'
|
55
|
+
table.column('ColC').end_cell.to_s.should == 'd6'
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should be able to translate structured references into normal references" do
|
59
|
+
table.reference_for('ColA').start_cell.to_s.should == 'b4'
|
60
|
+
table.reference_for('ColA').end_cell.to_s.should == 'b6'
|
61
|
+
table.reference_for('#All').start_cell.to_s.should == 'b3'
|
62
|
+
table.reference_for('#All').end_cell.to_s.should == 'd7'
|
63
|
+
table.reference_for('#Data').start_cell.to_s.should == 'b4'
|
64
|
+
table.reference_for('#Data').end_cell.to_s.should == 'd6'
|
65
|
+
table.reference_for('#Headers').start_cell.to_s.should == 'b3'
|
66
|
+
table.reference_for('#Headers').end_cell.to_s.should == 'd3'
|
67
|
+
table.reference_for('#Totals').start_cell.to_s.should == 'b7'
|
68
|
+
table.reference_for('#Totals').end_cell.to_s.should == 'd7'
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should be able to translate structured references that are intersections into normal references" do
|
72
|
+
table.reference_for('[#Totals],[ColA]').to_s.should == 'sheet1.b7'
|
73
|
+
table.reference_for('[#Headers],[ColC]').to_s.should == 'sheet1.d3'
|
74
|
+
table.reference_for('[#All],[ColB]').start_cell.to_s.should == 'c3'
|
75
|
+
table.reference_for('[#All],[ColB]').end_cell.to_s.should == 'c7'
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should be able to translate structured references that include the special variable #This Row" do
|
79
|
+
table.reference_for('[#This Row],[ColA]', Reference.new('e5')).to_s.should == 'sheet1.b5'
|
80
|
+
table.reference_for('#This Row',Reference.new('e5')).start_cell.to_s.should == 'b5'
|
81
|
+
table.reference_for('#This Row',Reference.new('e5')).end_cell.to_s.should == 'd5'
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should be able to translate structured references from cells that are in the table, treating them as if they had indicated [#This row] as part of the reference" do
|
85
|
+
table.reference_for('ColA', Reference.new('e5',@worksheet)).to_s.should == "sheet1.a('b4','b6')"
|
86
|
+
table.reference_for('ColA', Reference.new('c5',@worksheet)).to_s.should == 'sheet1.b5'
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should be able to access structured references by providing the table name to Table.reference_for(table_name,structured_reference,referring_cell)" do
|
90
|
+
table
|
91
|
+
Table.reference_for('FirstTable','#Data').start_cell.to_s.should == 'b4'
|
92
|
+
Table.reference_for('Not a known table','#Data').should == ":ref"
|
93
|
+
Table.reference_for('FirstTable','[#This Row],[ColA]', Reference.new('e5')).to_s.should == 'sheet1.b5'
|
94
|
+
end
|
95
|
+
|
96
|
+
it "#inspect should create a string that can be used to recreate the table" do
|
97
|
+
table.inspect.should == %Q{'Table.new(sheet1,"FirstTable","B3:D7",["ColA", "ColB", "ColC"],1)'}
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe ValueCell do
|
4
|
+
|
5
|
+
it "creates a ruby method that returns the cell's value as a float if it is a number" do
|
6
|
+
cell = ValueCell.new(mock('worksheet',:ruby_name => 'sheet1'),Nokogiri::XML('<c r="C22"><v>24</v></c>').root)
|
7
|
+
cell.to_ruby.should == "def c22; 24.0; end\n"
|
8
|
+
end
|
9
|
+
|
10
|
+
it "creates a ruby method that returns the cell's value as a ruby boolean if it is a boolean" do
|
11
|
+
cell = ValueCell.new(mock('worksheet',:ruby_name => 'sheet1'),Nokogiri::XML('<c r="C22" t="b"><v>TRUE</v></c>').root)
|
12
|
+
cell.to_ruby.should == "def c22; true; end\n"
|
13
|
+
cell = ValueCell.new(mock('worksheet',:ruby_name => 'sheet1'),Nokogiri::XML('<c r="C22" t="b"><v>1</v></c>').root)
|
14
|
+
cell.to_ruby.should == "def c22; true; end\n"
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
it "creates a ruby method that returns the cell's value as a ruby string if it is a string" do
|
19
|
+
cell = ValueCell.new(mock('worksheet',:ruby_name => 'sheet1'),Nokogiri::XML('<c r="B6" t="str"><v>hello</v></c>').root)
|
20
|
+
cell.to_ruby.should == %Q{def b6; "hello"; end\n}
|
21
|
+
end
|
22
|
+
|
23
|
+
it "creates a ruby method that returns the cell's value as a ruby string if it is a shared string" do
|
24
|
+
cell = ValueCell.new(mock('worksheet',:ruby_name => 'sheet1'),Nokogiri::XML('<c r="B6" t="s"><v>7</v></c>').root)
|
25
|
+
SharedStrings.should_receive(:shared_string_for).with(7).and_return('hello')
|
26
|
+
cell.to_ruby.should == %Q{def b6; "hello"; end\n}
|
27
|
+
end
|
28
|
+
|
29
|
+
it "creates a ruby method that returns an appropriate symbol if it is an error" do
|
30
|
+
cell = ValueCell.new(mock('worksheet',:ruby_name => 'sheet1'),Nokogiri::XML('<c r="B6" t="e"><v>#N/A</v></c>').root)
|
31
|
+
cell.to_ruby.should == "def b6; :na; end\n"
|
32
|
+
end
|
33
|
+
|
34
|
+
it "has a method that confirms it can be replaced with its value" do
|
35
|
+
cell = ValueCell.new(mock('worksheet',:ruby_name => 'sheet1'),Nokogiri::XML('<c r="B6" t="str"><v>hello</v></c>').root)
|
36
|
+
cell.can_be_replaced_with_value?.should be_true
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
describe ValueCell, "can list the cells upon which it depends" do
|
42
|
+
|
43
|
+
it "in simple cases knows what it depends upon" do
|
44
|
+
cell = ValueCell.new(mock('worksheet',:ruby_name => 'sheet1'),Nokogiri::XML('<c r="B6" t="s"><v>7</v></c>').root)
|
45
|
+
cell.work_out_dependencies
|
46
|
+
cell.dependencies.should == []
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|