rspreadsheet 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,17 +1,296 @@
1
1
  require('rspreadsheet/cell')
2
+ include Forwardable
2
3
 
3
4
  # Currently this is only syntax sugar for cells and contains no functionality
4
5
 
5
6
  module Rspreadsheet
6
7
 
8
+ class RowArray
9
+ def initialize(aworksheet_node)
10
+ @worksheet_node = aworksheet_node
11
+
12
+ # initialize @rowgroups from @worksheet_node
13
+ @rowgroups = []
14
+ unless @worksheet_node.nil?
15
+ @worksheet_node.elements.select{|node| node.name == 'table-row'}.each do |row_source_node|
16
+ @rowgroups << prepare_row_group(row_source_node) # it is in @worksheet_node so suffices to add object to @rowgroups
17
+ end
18
+ end
19
+ end
20
+ def prepare_row_group(size_or_xmlnode) # appends new RowGroup at the end
21
+ # reading params
22
+ if size_or_xmlnode.kind_of? LibXML::XML::Node
23
+ size = (size_or_xmlnode['number-rows-repeated'] || 1).to_i
24
+ node = size_or_xmlnode
25
+ elsif size_or_xmlnode.to_i>0
26
+ size = size_or_xmlnode.to_i
27
+ node = nil
28
+ else
29
+ return nil
30
+ end
31
+ index = first_unused_row_index
32
+
33
+ # construct result
34
+ RowGroup.new(self,index..index+size-1,node).normalize
35
+ end
36
+ def add_row_group(size_or_xmlnode)
37
+ result = prepare_row_group(size_or_xmlnode)
38
+ @rowgroups << result
39
+ @worksheet_node << result.xmlnode
40
+ result
41
+ end
42
+ def get_row_group(rowi)
43
+ @rowgroups.find{ |rowgroup| rowgroup.range.cover?(rowi) }
44
+ end
45
+ def get_row(rowi)
46
+ rg = get_row_group(rowi).andand.normalize
47
+ case rg
48
+ when SingleRow then rg
49
+ when RowGroup then MemberOfRowGroup.new(rowi, rg)
50
+ when nil
51
+ if rowi>0 then UninitializedEmptyRow.new(self,rowi) else nil end
52
+ else raise
53
+ end
54
+ end
55
+ # prolonges the RowArray to cantain rowi and returns it
56
+ def detach_of_bound_row_group(rowi)
57
+ fill_row_group_size = rowi-first_unused_row_index
58
+ if fill_row_group_size>0
59
+ add_row_group(fill_row_group_size)
60
+ end
61
+ add_row_group(1)
62
+ return get_row(rowi)
63
+ end
64
+ def first_unused_row_index
65
+ if @rowgroups.empty?
66
+ 1
67
+ else
68
+ @rowgroups.last.range.end+1
69
+ end
70
+ end
71
+ # This detaches row rowi from the group and perhaps splits the RowGroup
72
+ # into two pieces. This makes the row individually editable.
73
+ def detach(rowi)
74
+ index = get_row_group_index(rowi)
75
+ row_group = @rowgroups[index]
76
+ range = row_group.range
77
+
78
+ # prepare new components
79
+ replaceby = []
80
+ replaceby << RowGroup.new(self,range.begin..rowi-1)
81
+ replaceby << (result = SingleRow.new(self,rowi))
82
+ replaceby << RowGroup.new(self,rowi+1..range.end)
83
+
84
+ # put original range somewhere in replaceby and shorten it
85
+ if rowi>range.begin
86
+ replaceby[0] = row_group
87
+ row_group.range = range.begin..rowi-1
88
+ else
89
+ replaceby[2] = row_group
90
+ row_group.range = rowi+1..range.end
91
+ end
92
+
93
+ # normalize and delete empty parts
94
+ replaceby = replaceby.map(&:normalize).compact
95
+
96
+ # do the replacement in xml
97
+ marker = LibXML::XML::Node.new('temporarymarker')
98
+ row_group.xmlnode.next = marker
99
+ row_group.xmlnode.remove!
100
+ replaceby.each{ |rg|
101
+ marker.prev = rg.xmlnode
102
+ }
103
+ marker.remove!
104
+
105
+ # do the replacement in array
106
+ @rowgroups[index..index]=replaceby
107
+ result
108
+ end
109
+
110
+ private
111
+ def get_row_group_index(rowi)
112
+ @rowgroups.find_index{ |rowgroup| rowgroup.range.cover?(rowi) }
113
+ end
114
+ end
115
+
7
116
  class Row
8
- def initialize(workbook,rowi)
9
- @rowi = rowi
10
- @workbook = workbook
117
+ @readonly = :unknown
118
+ # ? @rowindex
119
+ def self.empty_row_node
120
+ LibXML::XML::Node.new('table-row',nil, Tools.get_namespace('table'))
11
121
  end
122
+ end
123
+
124
+ class RowWithXMLNode < Row
125
+ attr_accessor :xmlnode
126
+ def style_name=(value); Tools.set_ns_attribute(@xmlnode,'table','style-name',value) end
12
127
  def cells(coli)
13
- @workbook.cells(@rowi,coli)
128
+ coli = coli.to_i
129
+ return nil if coli.to_i<=0
130
+ Cell.new(self,coli,cellnodes(coli))
131
+ end
132
+ def nonemptycells
133
+ nonemptycellsindexes.collect{ |index| cells(index) }
134
+ end
135
+ def nonemptycellsindexes
136
+ used_col_range.to_a.select do |coli|
137
+ cellnode = cellnodes(coli)
138
+ !(cellnode.content.nil? or cellnode.content.empty? or cellnode.content =='') or
139
+ !cellnode.attributes.to_a.reject{ |attr| attr.name == 'number-columns-repeated'}.empty?
140
+ end
141
+ end
142
+ def used_col_range
143
+ 1..first_unused_column_index-1
144
+ end
145
+ def cellnodes(coli)
146
+ cellnode = nil
147
+ while true
148
+ curr_coli=1
149
+ cellnode = @xmlnode.elements.select{|n| n.name=='table-cell'}.find do |el|
150
+ curr_coli += (Tools.get_ns_attribute_value(el, 'table', 'number-columns-repeated') || 1).to_i
151
+ curr_coli > coli
152
+ end
153
+ unless cellnode.nil?
154
+ return cellnode
155
+ else
156
+ add_cell
157
+ end
158
+ end
159
+ end
160
+ def add_cell(repeated=1)
161
+ cell = Cell.new(self,first_unused_column_index)
162
+ Tools.set_ns_attribute(cell.xmlnode,'table','number-columns-repeated',repeated) if repeated>1
163
+ @xmlnode << cell.xmlnode
164
+ cell
165
+ end
166
+ def used_range
167
+ fu = first_unused_column_index
168
+ (fu>1) ? 1..fu : nil
169
+ end
170
+ def first_unused_column_index
171
+ 1 + @xmlnode.elements.select{|n| n.name=='table-cell'}.reduce(0) do |sum, el|
172
+ sum + (Tools.get_ns_attribute_value(el, 'table', 'number-columns-repeated') || 1).to_i
173
+ end
14
174
  end
15
175
  end
16
176
 
177
+ class RowGroup < RowWithXMLNode
178
+ @readonly = :yes_always
179
+ attr_reader :range
180
+ attr_accessor :parent_array, :xmlnode
181
+ def initialize(aparent_array,arange,axmlnode=nil)
182
+ @parent_array = aparent_array
183
+ @range = arange
184
+ if axmlnode.nil?
185
+ axmlnode = Row.empty_row_node
186
+ Tools.set_ns_attribute(axmlnode,'table','number-rows-repeated',range.size) if range.size>1
187
+ end
188
+ @xmlnode = axmlnode
189
+ end
190
+ # returns SingleRow if size of range is 1 and nil if it is 0 or less
191
+ def normalize
192
+ case range.size
193
+ when 2..Float::INFINITY then self
194
+ when 1 then SingleRow.new_from_rowgroup(self)
195
+ else nil
196
+ end
197
+ end
198
+ def repeated; range.size end
199
+ def repeated?; range.size>1 end
200
+ def range=(arange)
201
+ @range=arange
202
+ Tools.set_ns_attribute(@xmlnode,'table','number-rows-repeated',range.size, 1)
203
+ end
204
+ end
205
+
206
+ class SingleRow < RowWithXMLNode
207
+ @readonly = :no
208
+ attr_accessor :xmlnode
209
+ # index Integer
210
+ def initialize(aparent_array,aindex,axmlnode=nil)
211
+ @parent_array = aparent_array
212
+ @index = aindex
213
+ if axmlnode.nil?
214
+ axmlnode = Row.empty_row_node
215
+ end
216
+ @xmlnode = axmlnode
217
+ end
218
+ def self.new_from_rowgroup(rg)
219
+ anode = rg.xmlnode
220
+ Tools.remove_ns_attribute(anode,'table','number-rows-repeated')
221
+
222
+ SingleRow.new(rg.parent_array,rg.range.begin,anode)
223
+ end
224
+ def normalize; self end
225
+ def repeated?; false end
226
+ def repeated; 1 end
227
+ def range; (@index..@index) end
228
+ def detach; true end
229
+ def row; @index end
230
+
231
+ end
232
+
233
+ class LazyDetachableRow < Row
234
+ @readonly = :yes_but_detachable
235
+ def initialize(rowi)
236
+ @index = rowi.to_i
237
+ end
238
+ def add_cell; detach.add_cell end
239
+ def style_name=(value); detach.style_name=value end
240
+ def row; @index end
17
241
  end
242
+
243
+ ## there are not data in this object, they are taken from RowGroup, but this is only readonly
244
+ class MemberOfRowGroup < LazyDetachableRow
245
+ @readonly = :yes_but_detachable
246
+ extend Forwardable
247
+ delegate [:repeated?, :repeated, :xmlnode, :parent_array] => :@row_group
248
+ attr_accessor :row_group # for dubugging
249
+
250
+ # @index Integer
251
+ # @row_group RepeatedRow
252
+ def initialize(arowi,arow_group)
253
+ super(arowi)
254
+ @row_group = arow_group
255
+ raise 'Wrong parameter given' unless @row_group.is_a? RowGroup
256
+ end
257
+ def detach # detaches MemberOfRowGroup from its RowGroup perhaps splitting RowGroup
258
+ @row_group.parent_array.detach(@index)
259
+ end
260
+ def cells(coli)
261
+ Cell.new(self,coli,@row_group.cellnodes(coli)).tap{|n| n.mode = :repeated}
262
+ end
263
+ def nonemptycells
264
+ @row_group.nonemptycellsindexes.collect{ |coli| cells(coli) }
265
+ end
266
+ end
267
+
268
+ ## this is a row outside the used bounds. the main purpose of this object is to magically synchronize to existing data, once they are created
269
+ class UninitializedEmptyRow < LazyDetachableRow
270
+ @readonly = :yes_but_detachable
271
+ attr_reader :parent_array # debug only
272
+ def initialize(aparent_array,arowi)
273
+ super(arowi)
274
+ @parent_array = aparent_array
275
+ end
276
+ def cells(coli)
277
+ if still_out_of_used_range?
278
+ Cell.new(self,coli,Cell.empty_cell_node).tap{|n| n.mode = :outbound}
279
+ else
280
+ @parent_array.get_row(@index).cells(coli)
281
+ end
282
+ end
283
+ def normalize
284
+ if still_out_of_used_range?
285
+ self
286
+ else
287
+ @parent_array.get_row(@index)
288
+ end
289
+ end
290
+ def detach; @parent_array.detach_of_bound_row_group(@index) end
291
+ def still_out_of_used_range?; @index >= @parent_array.first_unused_row_index end
292
+ def xmlnode; Row.empty_row_node end
293
+ def nonemptycells; [] end
294
+ end
295
+
296
+ end
@@ -20,13 +20,87 @@ module Tools
20
20
  row = rowname.to_i
21
21
  return [row,col]
22
22
  end
23
-
24
- # this object represents array which can contain repeated values
25
- # inspired valuely by http://www-users.cs.umn.edu/~saad/software/SPARSKIT/paper.ps
26
- class SparseRepeatedArray < Array
23
+ def self.get_namespace(prefix)
24
+ ns_array = {
25
+ 'office'=>"urn:oasis:names:tc:opendocument:xmlns:office:1.0",
26
+ 'style'=>"urn:oasis:names:tc:opendocument:xmlns:style:1.0",
27
+ 'text'=>"urn:oasis:names:tc:opendocument:xmlns:text:1.0",
28
+ 'table'=>"urn:oasis:names:tc:opendocument:xmlns:table:1.0",
29
+ 'draw'=>"urn:oasis:names:tc:opendocument:xmlns:drawing:1.0",
30
+ 'fo'=>"urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0",
31
+ 'xlink'=>"http://www.w3.org/1999/xlink",
32
+ 'dc'=>"http://purl.org/dc/elements/1.1/",
33
+ 'meta'=>"urn:oasis:names:tc:opendocument:xmlns:meta:1.0",
34
+ 'number'=>"urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0",
35
+ 'presentation'=>"urn:oasis:names:tc:opendocument:xmlns:presentation:1.0",
36
+ 'svg'=>"urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0",
37
+ 'chart'=>"urn:oasis:names:tc:opendocument:xmlns:chart:1.0",
38
+ 'dr3d'=>"urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0",
39
+ 'math'=>"http://www.w3.org/1998/Math/MathML",
40
+ 'form'=>"urn:oasis:names:tc:opendocument:xmlns:form:1.0",
41
+ 'script'=>"urn:oasis:names:tc:opendocument:xmlns:script:1.0",
42
+ 'ooo'=>"http://openoffice.org/2004/office",
43
+ 'ooow'=>"http://openoffice.org/2004/writer",
44
+ 'oooc'=>"http://openoffice.org/2004/calc",
45
+ 'dom'=>"http://www.w3.org/2001/xml-events",
46
+ 'xforms'=>"http://www.w3.org/2002/xforms",
47
+ 'xsd'=>"http://www.w3.org/2001/XMLSchema",
48
+ 'xsi'=>"http://www.w3.org/2001/XMLSchema-instance",
49
+ 'rpt'=>"http://openoffice.org/2005/report",
50
+ 'of'=>"urn:oasis:names:tc:opendocument:xmlns:of:1.2",
51
+ 'xhtml'=>"http://www.w3.org/1999/xhtml",
52
+ 'grddl'=>"http://www.w3.org/2003/g/data-view#",
53
+ 'tableooo'=>"http://openoffice.org/2009/table",
54
+ 'drawooo'=>"http://openoffice.org/2010/draw",
55
+ 'calcext'=>"urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0",
56
+ 'loext'=>"urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0",
57
+ 'field'=>"urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0",
58
+ 'formx'=>"urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0",
59
+ 'css3t'=>"http://www.w3.org/TR/css3-text/"
60
+ }
61
+ if @pomnode.nil?
62
+ @pomnode = LibXML::XML::Node.new('xxx')
63
+ end
64
+ if @ns.nil? then @ns={} end
65
+ if @ns[prefix].nil?
66
+ @ns[prefix] = LibXML::XML::Namespace.new(@pomnode, prefix, ns_array[prefix])
67
+ end
68
+ return @ns[prefix]
69
+ end
70
+ # sets namespaced attribute "ns_prefix:key" in node to value. if value == delete_value then remove the attribute
71
+ def self.set_ns_attribute(node,ns_prefix,key,value,delete_value=nil)
72
+ ns = Tools.get_namespace(ns_prefix)
73
+ attr = node.attributes.get_attribute_ns(ns.href, key)
27
74
 
28
-
75
+ unless value==delete_value # set attribute
76
+ if attr.nil? # create attribute if needed
77
+ attr = LibXML::XML::Attr.new(node, key,'temporarilyempty')
78
+ attr.namespaces.namespace = ns
79
+ end
80
+ attr.value = value.to_s
81
+ attr
82
+ else # remove attribute
83
+ attr.remove! unless attr.nil?
84
+ nil
85
+ end
86
+ end
87
+ def self.get_ns_attribute(node,ns_prefix,key)
88
+ node.attributes.get_attribute_ns(Tools.get_namespace(ns_prefix).href,key)
89
+ end
90
+ def self.get_ns_attribute_value(node,ns_prefix,key)
91
+ Tools.get_ns_attribute(node,ns_prefix,key).andand.value
92
+ end
93
+ def self.remove_ns_attribute(node,ns_prefix,key)
94
+ node.attributes.get_attribute_ns(Tools.get_namespace(ns_prefix).href,key)
95
+ attr.remove! unless attr.nil?
29
96
  end
30
97
  end
31
98
 
99
+ end
100
+
101
+ class Range
102
+ def size
103
+ res = self.end-self.begin+1
104
+ res>0 ? res : 0
105
+ end
32
106
  end
@@ -1,3 +1,3 @@
1
1
  module Rspreadsheet
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.6"
3
3
  end
@@ -4,22 +4,16 @@ require 'libxml'
4
4
  module Rspreadsheet
5
5
  class Workbook
6
6
  attr_reader :worksheets, :filename
7
+ attr_reader :xmlnode # debug
7
8
  def initialize(afilename=nil)
8
9
  @worksheets={}
9
10
  @filename = afilename
10
- if filename.nil?
11
- else
12
- @content_xml = Zip::File.open(filename) do |zip|
13
- LibXML::XML::Document.io zip.get_input_stream('content.xml')
14
- end
15
-
16
- ndx = 0
17
- @content_xml.find_first('//office:spreadsheet').each_element { |node|
18
- sheet = Worksheet.new(node)
19
- @worksheets[ndx]=sheet
20
- @worksheets[node.name]=sheet
21
- ndx+=1
22
- }
11
+ @content_xml = Zip::File.open(@filename || './lib/rspreadsheet/empty_file_template.ods') do |zip|
12
+ LibXML::XML::Document.io zip.get_input_stream('content.xml')
13
+ end
14
+ @xmlnode = @content_xml.find_first('//office:spreadsheet')
15
+ @xmlnode.find('./table:table').each do |node|
16
+ create_worksheet_from_node(node)
23
17
  end
24
18
  end
25
19
  def save(new_filename=nil)
@@ -30,20 +24,31 @@ class Workbook
30
24
  @filename = new_filename
31
25
  end
32
26
  Zip::File.open(@filename) do |zip|
33
- # it is easy, because @content_xml in in sync with contents all the time
27
+ # it is easy, because @xmlnode in in sync with contents all the time
34
28
  zip.get_output_stream('content.xml') do |f|
35
29
  f.write @content_xml
36
30
  end
37
31
  end
38
32
  end
39
- def create_worksheet(node=nil)
40
- sheet = Worksheet.new(node)
41
- @worksheets[worksheets_count]=sheet
42
- @worksheets[node.name]=sheet unless node.nil?
33
+ def create_worksheet_from_node(source_node)
34
+ sheet = Worksheet.new(source_node)
35
+ register_worksheet(sheet)
43
36
  return sheet
44
37
  end
45
- def worksheets
46
- @worksheets
38
+ def create_worksheet_with_name(name)
39
+ sheet = Worksheet.new(name)
40
+ register_worksheet(sheet)
41
+ return sheet
42
+ end
43
+ def create_worksheet
44
+ index = worksheets_count
45
+ create_worksheet_with_name("Strana #{index}")
46
+ end
47
+ def register_worksheet(worksheet)
48
+ index = worksheets_count+1
49
+ @worksheets[index]=worksheet
50
+ @worksheets[worksheet.name]=worksheet unless worksheet.name.nil?
51
+ @xmlnode << worksheet.xmlnode if worksheet.xmlnode.doc != @xmlnode.doc
47
52
  end
48
53
  def worksheets_count
49
54
  @worksheets.keys.select{ |k| k.kind_of? Numeric }.size #TODO: ?? max
@@ -51,5 +56,8 @@ class Workbook
51
56
  def worksheet_names
52
57
  @worksheets.keys.reject{ |k| k.kind_of? Numeric }
53
58
  end
59
+ def xmldoc
60
+ @xmlnode.doc
61
+ end
54
62
  end
55
63
  end
@@ -1,47 +1,38 @@
1
1
  require 'rspreadsheet/row'
2
2
  require 'rspreadsheet/tools'
3
- require 'forwardable'
3
+ # require 'forwardable'
4
4
 
5
5
  module Rspreadsheet
6
6
 
7
7
  class Worksheet
8
- attr_accessor :name
9
- extend Forwardable
10
- def_delegators :nonemptycells
8
+ attr_accessor :name, :xmlnode
9
+ # extend Forwardable
10
+ # def_delegators :nonemptycells
11
11
 
12
- def initialize(source_node=nil)
13
- @source_node = source_node
14
- ## initialize cells
15
- @cells = Hash.new do |hash, coords|
16
- # we create empty cell and place it to hash, we do not have to check whether there is a cell in XML already, because it would be in hash as well
17
- hash[coords]=Cell.new(coords[0],coords[1])
18
- # TODO: create XML empty node here or upon save?
19
- end
20
- rowi = 1
21
- unless @source_node.nil?
22
- @source_node.elements.select{ |node| node.name == 'table-row'}.each do |row_source_node|
23
- coli = 1
24
- row_source_node.elements.select{ |node| node.name == 'table-cell'}.each do |cell_source_node|
25
- initialize_cell(rowi,coli,cell_source_node)
26
- coli += 1
27
- end
28
- rowi += 1
29
- end
12
+ def initialize(xmlnode_or_sheet_name)
13
+ # set up the @xmlnode according to parameter
14
+ case xmlnode_or_sheet_name
15
+ when LibXML::XML::Node
16
+ @xmlnode = xmlnode_or_sheet_name
17
+ when String
18
+ @xmlnode = LibXML::XML::Node.new('table')
19
+ ns = LibXML::XML::Namespace.new(@xmlnode, 'table', 'urn:oasis:names:tc:opendocument:xmlns:table:1.0')
20
+ @xmlnode .namespaces.namespace = ns
21
+ @xmlnode['table:name'] = xmlnode_or_sheet_name
22
+ else raise 'Provide name or xml node to create a Worksheet object'
30
23
  end
24
+
31
25
  ## initialize rows
32
- @spredsheetrows=Array.new()
33
- end
34
- def initialize_cell(r,c,source_node)
35
- @cells[[r,c]]=Cell.new(r,c,source_node)
26
+ @spredsheetrows=RowArray.new(@xmlnode)
36
27
  end
37
28
  def cells(r,c)
38
- @cells[[r,c]]
29
+ rows(r).andand.cells(c)
39
30
  end
40
31
  def nonemptycells
41
- @cells.values
32
+ used_rows_range.collect{ |rowi| rows(rowi) }.collect { |row| row.nonemptycells }.flatten
42
33
  end
43
34
  def rows(rowi)
44
- @spredsheetrows[rowi] ||= Row.new(self,rowi)
35
+ @spredsheetrows.get_row(rowi)
45
36
  end
46
37
  ## syntactic sugar follows
47
38
  def [](r,c)
@@ -64,6 +55,9 @@ class Worksheet
64
55
  super
65
56
  end
66
57
  end
58
+ def used_rows_range
59
+ 1..@spredsheetrows.first_unused_row_index-1
60
+ end
67
61
  end
68
62
 
69
63
  end
data/rspreadsheet.gemspec CHANGED
@@ -28,12 +28,13 @@ Gem::Specification.new do |spec|
28
28
  spec.add_development_dependency "bundler", "~> 1.5"
29
29
  spec.add_development_dependency "rake", '~>0.9'
30
30
  # testig - see http://bit.ly/1n5yM51
31
- spec.add_development_dependency "rspec", '~>2'
31
+ spec.add_development_dependency "rspec", '~>2' # testing
32
+ spec.add_development_dependency 'pry-nav' # enables pry 'next', 'step' commands
32
33
 
33
34
  # optional and testing
34
35
  spec.add_development_dependency "coveralls", '~>0.7'
35
- spec.add_development_dependency "test_notifier", '~>2.0' # test notifier for kde and other platforms
36
36
  spec.add_development_dependency "guard", '~>2.6'
37
37
  spec.add_development_dependency "guard-rspec", '~>2.6'
38
+ # spec.add_development_dependency 'equivalent-xml' # implementing xml diff
38
39
 
39
40
  end
data/spec/cell_spec.rb ADDED
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rspreadsheet::Cell do
4
+ before do
5
+ book1 = Rspreadsheet.new
6
+ @sheet1 = book1.create_worksheet
7
+ book2 = Rspreadsheet.new($test_filename)
8
+ @sheet2 = book2.worksheets[1]
9
+ end
10
+ it 'contains good row and col coordinates' do
11
+ @cell = @sheet1.cells(1,3)
12
+ @cell.row.should == 1
13
+ @cell.col.should == 3
14
+ @cell.coordinates.should == [1,3]
15
+
16
+ @cell = @sheet2.cells(7,2)
17
+ @cell.row.should == 7
18
+ @cell.col.should == 2
19
+ @cell.coordinates.should == [7,2]
20
+ end
21
+ it 'can be referenced by more vars and both are synchronized' do
22
+ @cell = @sheet1.cells(1,1)
23
+ @sheet1[1,1] = 'novinka'
24
+ @cell.value.should == 'novinka'
25
+ end
26
+ it 'can be modified by more ways and all are identical' do
27
+ @cell = @sheet1.cells(2,2)
28
+ @sheet1[2,2] = 'zaprve'
29
+ @cell.value.should == 'zaprve'
30
+ @sheet1.cells(2,2).value = 'zadruhe'
31
+ @cell.value.should == 'zadruhe'
32
+ @sheet1.B2 = 'zatreti'
33
+ @cell.value.should == 'zatreti'
34
+ end
35
+ it 'can include links' do
36
+ @sheet2.A12.should == '[http://example.org/]'
37
+ end
38
+ it 'contains good row and col coordinates even after table:number-columns-repeated cells' do
39
+ @cell = @sheet2.cells(13,5)
40
+ @cell.value.should == 'afterrepeated'
41
+ @cell.row.should == 13
42
+ @cell.col.should == 5
43
+ end
44
+ it 'does not accept negative and zero coordinates' do
45
+ @sheet2.cells(0,5).should be(nil)
46
+ @sheet2.cells(2,-5).should be(nil)
47
+ @sheet2.cells(-2,-5).should be(nil)
48
+ end
49
+ end