rspreadsheet 0.2.12 → 0.2.14

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e934c460d044d82af82b8cb6aa7fb8d9336ef961
4
- data.tar.gz: fc75adfff414efcfbf0649b9262c4faf23bfb292
3
+ metadata.gz: d2f168c71e8ec1b014d48658b230c03780c6fb40
4
+ data.tar.gz: 11aaf6ed2a306be9eb3a2f3dcfa89dffed291f88
5
5
  SHA512:
6
- metadata.gz: 35d61b752404f07748c738225895d61d5bfe11aeb2512042e272075a48b6b44112cb849671231d05bcbffe70fa74b188fd92c18f52545aa95dbe488ce0c1e374
7
- data.tar.gz: ae2c7fe343d5a75c469a36b594ead4551faf341bcb2c2ade99c3cf4c046c54aa66074d08cb689bcd4cd3fa042ce430543133cf7dc5af066513370255a81cd501
6
+ metadata.gz: fa517af98e5a410bd50f9bb62a878b8752bed69bc77eb1cff3d50dcb05839c4a81956417a64a8b3f32b55376c1906d3c983c3260e426ccdc69145768063e6639
7
+ data.tar.gz: 95e37cd4a06b66f107b612c8467ca91f2524bf61477208129e159dc0a479a476bc9be5e965eefd1b573c70919b2fd8cb28ce33d0eb5c299064cbef044bbe5a56
@@ -1,7 +1,9 @@
1
1
  language: ruby
2
2
  cache: bundler
3
3
  rvm:
4
- - 2.1.2
4
+ - 2.2.3
5
+ - 2.2.0
6
+ - 2.1.7
5
7
  - 2.0.0
6
8
  - 1.9.3
7
9
  script: 'bundle exec rake'
@@ -49,6 +49,10 @@ RSpreadsheet.generate('pricelist.ods') do
49
49
  * Range#merge() - Merges the cells in the range together into a single block.
50
50
  * @book.sheet_names - Array of names of sheets.
51
51
 
52
+
53
+ * array returned by rows of cells can have predefined dummy object as defaults for out of range indexes
54
+
55
+
52
56
  ##Guiding ideas
53
57
  * xml document is always synchronized with the data. So the save is trivial.
54
58
  * no duplication of data. Objects like RowArray should containg minimum information. This one exists solely to speed up cell search. Taken to extream it is questionable, whether we need such objects at all, it might be possible to always work with xml directly.
data/GUIDE.md CHANGED
@@ -7,14 +7,14 @@ You can open ODS file like this
7
7
  ````
8
8
  and access its first sheet like this
9
9
  ````ruby
10
- @sheet = @workbook.worksheets(1)
10
+ @sheet = @workbook.worksheet(1)
11
11
  ````
12
12
  ### Accessing cells
13
13
 
14
14
  you can get and set contents of cells using "verbatim" syntax like
15
15
  ````ruby
16
- @sheet.rows(5).cells(4).value
17
- @sheet.rows(5).cells(4).value = 10
16
+ @sheet.row(5).cell(4).value
17
+ @sheet.row(5).cell(4).value = 10
18
18
  ````
19
19
  or using "brief" syntax like
20
20
  ````ruby
@@ -24,7 +24,7 @@ or using "brief" syntax like
24
24
 
25
25
  You can mix these two at will, for example like this
26
26
  ````ruby
27
- @row = @sheet.rows(5)
27
+ @row = @sheet.row(5)
28
28
  @row[4] = 10
29
29
  ````
30
30
 
@@ -37,5 +37,6 @@ You can mix these two at will, for example like this
37
37
  * **all indexes are 1-based**. This applies to rows, cells cordinates, and all array like structures like list od worksheets etc. Spreadsheet world is 1-based, ruby is 0-based do I had to make a decision. I intend to make an global option for this, but in early stage I need to keep things simple.
38
38
  * with numeric coordinates row always comes before col as in (row,col)
39
39
  * with alphanumerical col always comes before row as in F12
40
- * Shorter syntax worksheet[x,y] returns value, longer syntax worksheet.cells(x,y) return cell objects. This allows to work conviniently with values using short syntax and access the cell object if needed (to access formatting for example).
40
+ * Shorter syntax worksheet[x,y] returns value, longer syntax worksheet.cell(x,y) return cell objects. This allows to work conviniently with values using short syntax and access the cell object if needed (to access formatting for example).
41
+ * Note: currently plural and singular like sheet/sheets, row/rows, cell/cells can be used intergangebly, but there is a (discussion)[https://github.com/gorn/rspreadsheet/issues/10] about this and in future versions we might use singular style for methods and plural for array style.
41
42
 
data/README.md CHANGED
@@ -16,20 +16,20 @@ sheet = book.worksheets(1)
16
16
  # get value of a cell B5 (there are more ways to do this)
17
17
  sheet.B5 # => 'cell value'
18
18
  sheet[5,2] # => 'cell value'
19
- sheet.rows(5).cells(2).value # => 'cell value'
19
+ sheet.row(5).cell(2).value # => 'cell value'
20
20
 
21
21
  # set value of a cell B5
22
22
  sheet.F5 = 'text'
23
23
  sheet[5,2] = 7
24
- sheet.cells(5,2).value = 1.78
24
+ sheet.cell(5,2).value = 1.78
25
25
 
26
26
  # working with cell format
27
- sheet.cells(5,2).format.bold = true
28
- sheet.cells(5,2).format.background_color = '#FF0000'
27
+ sheet.cell(5,2).format.bold = true
28
+ sheet.cell(5,2).format.background_color = '#FF0000'
29
29
 
30
30
  # calculate sum of cells in row
31
- sheet.rows(5).cellvalues.sum
32
- sheet.rows(5).cells.sum{ |cell| cell.value.to_f }
31
+ sheet.row(5).cellvalues.sum
32
+ sheet.row(5).cells.sum{ |cell| cell.value.to_f }
33
33
 
34
34
  # or set formula to a cell
35
35
  sheet.A1.formula='=SUM(A2:A9)'
@@ -1,49 +1,105 @@
1
- # @private
1
+ if RUBY_VERSION > '2.1'
2
+
3
+ module ClassExtensions
4
+
5
+ refine Array do
6
+ def sum(identity = 0, &block)
7
+ if block_given?
8
+ map(&block).sum(identity)
9
+ else
10
+ inject(0){ |sum, element| sum.to_f + element.to_f } || identity
11
+ end
12
+ end
13
+ end
14
+
15
+ refine LibXML::XML::Node do
16
+ def ==(node2)
17
+ self.simplification_of?(node2) and node2.simplification_of?(self)
18
+ end
19
+ # if node2 contains at least all that I do
20
+ def simplification_of?(node2)
21
+ first_diff(node2).nil?
22
+ end
23
+ # return first difference where self has something more than node2 does
24
+ def first_diff(node2)
25
+ where = self.path.split('/').last
26
+
27
+ return "#{where}> Equivalent node does not exist: #{self.name} != NOTHING" if node2.nil?
28
+ return "#{where}> Names are different: #{self.name} != #{node2.name}" if (self.name != node2.name)
29
+ self.attributes.each do |attr|
30
+ return "#{where}> Attribute #{attr} have diffent values: #{attr.value} != #{node2.attributes[attr.name]}" unless node2.attributes[attr.name] == attr.value
31
+ end
32
+
33
+ elems1 = self.elements
34
+ elems2 = node2.elements
35
+ # return "#{where}> elements have different number of subelements #{elems1.length} != #{elems2.length}" if (elems1.length != elems2.length)
36
+ elems1.length.times do |i|
37
+ if (elems1[i].node_type_name == 'text') && ((elems1[i].to_s != elems2[i].to_s) )
38
+ return "#{where}> #{i+1}th text subelements are different: #{elems1[i].to_s} != #{elems2[i].to_s}"
39
+ elsif (elems1[i].node_type_name == 'element') && (!elems1[i].simplification_of?(elems2[i]))
40
+ return "#{where}/[#{i+1}]#{elems1[i].first_diff(elems2[i])}"
41
+ end
42
+ end
43
+
44
+ return nil
45
+ end
46
+ def elements
47
+ result = []
48
+ each_element { |e| result << e }
49
+ return result
50
+ end
2
51
 
3
- class LibXML::XML::Node
4
- def elements
5
- result = []
6
- each_element { |e| result << e }
7
- return result
8
- end
9
- # if node2 contains at least all that I do
10
- def simplification_of?(node2)
11
- first_diff(node2).nil?
12
- end
13
- # return first difference where self has something more than node2 does
14
- def first_diff(node2)
15
- where = self.path.split('/').last
16
-
17
- return "#{where}> Equivalent node does not exist: #{self.name} != NOTHING" if node2.nil?
18
- return "#{where}> Names are different: #{self.name} != #{node2.name}" if (self.name != node2.name)
19
- self.attributes.each do |attr|
20
- return "#{where}> Attribute #{attr} have diffent values: #{attr.value} != #{node2.attributes[attr.name]}" unless node2.attributes[attr.name] == attr.value
21
52
  end
22
53
 
23
- elems1 = self.elements
24
- elems2 = node2.elements
25
- # return "#{where}> elements have different number of subelements #{elems1.length} != #{elems2.length}" if (elems1.length != elems2.length)
26
- elems1.length.times do |i|
27
- if (elems1[i].node_type_name == 'text') && ((elems1[i].to_s != elems2[i].to_s) )
28
- return "#{where}> #{i+1}th text subelements are different: #{elems1[i].to_s} != #{elems2[i].to_s}"
29
- elsif (elems1[i].node_type_name == 'element') && (!elems1[i].simplification_of?(elems2[i]))
30
- return "#{where}/[#{i+1}]#{elems1[i].first_diff(elems2[i])}"
54
+ end # module ClassExtensions
55
+
56
+ else # Monkeypatching
57
+ class Array
58
+ def sum(identity = 0, &block)
59
+ if block_given?
60
+ map(&block).sum(identity)
61
+ else
62
+ inject(0){ |sum, element| sum.to_f + element.to_f } || identity
31
63
  end
32
64
  end
33
-
34
- return nil
35
65
  end
36
- def equals?(node2) #TODO redefine == with this
37
- self.simplification_of?(node2) and node2.simplification_of?(self)
38
- end
39
- end
40
66
 
41
- class Array
42
- def sum(identity = 0, &block)
43
- if block_given?
44
- map(&block).sum(identity)
45
- else
46
- inject(0){ |sum, element| sum.to_f + element.to_f } || identity
67
+ class LibXML::XML::Node
68
+ def ==(node2)
69
+ self.simplification_of?(node2) and node2.simplification_of?(self)
70
+ end
71
+ # if node2 contains at least all that I do
72
+ def simplification_of?(node2)
73
+ first_diff(node2).nil?
47
74
  end
75
+ # return first difference where self has something more than node2 does
76
+ def first_diff(node2)
77
+ where = self.path.split('/').last
78
+
79
+ return "#{where}> Equivalent node does not exist: #{self.name} != NOTHING" if node2.nil?
80
+ return "#{where}> Names are different: #{self.name} != #{node2.name}" if (self.name != node2.name)
81
+ self.attributes.each do |attr|
82
+ return "#{where}> Attribute #{attr} have diffent values: #{attr.value} != #{node2.attributes[attr.name]}" unless node2.attributes[attr.name] == attr.value
83
+ end
84
+
85
+ elems1 = self.elements
86
+ elems2 = node2.elements
87
+ # return "#{where}> elements have different number of subelements #{elems1.length} != #{elems2.length}" if (elems1.length != elems2.length)
88
+ elems1.length.times do |i|
89
+ if (elems1[i].node_type_name == 'text') && ((elems1[i].to_s != elems2[i].to_s) )
90
+ return "#{where}> #{i+1}th text subelements are different: #{elems1[i].to_s} != #{elems2[i].to_s}"
91
+ elsif (elems1[i].node_type_name == 'element') && (!elems1[i].simplification_of?(elems2[i]))
92
+ return "#{where}/[#{i+1}]#{elems1[i].first_diff(elems2[i])}"
93
+ end
94
+ end
95
+
96
+ return nil
97
+ end
98
+ def elements
99
+ result = []
100
+ each_element { |e| result << e }
101
+ return result
102
+ end
103
+
48
104
  end
49
105
  end
@@ -7,8 +7,10 @@ require 'rspreadsheet/xml_tied'
7
7
  require 'date'
8
8
  require 'bigdecimal'
9
9
  require 'bigdecimal/util' # for to_d method
10
+ require 'helpers/class_extensions'
10
11
 
11
12
  module Rspreadsheet
13
+ using ClassExtensions if RUBY_VERSION > '2.1'
12
14
 
13
15
  ###
14
16
  # Represents a cell in spreadsheet which has coordinates, contains value, formula and can be formated.
@@ -40,7 +42,7 @@ class Cell < XMLTiedItem
40
42
  def coordinates; [rowi,coli] end
41
43
  def to_s; value.to_s end
42
44
  def valuexml; self.valuexmlnode.andand.inner_xml end
43
- def valuexmlnode; self.xmlnode.children.first end
45
+ def valuexmlnode; self.xmlnode.elements.first end
44
46
  # use this to find node in cell xml. ex. xmlfind('.//text:a') finds all link nodes
45
47
  def valuexmlfindall(path)
46
48
  valuexmlnode.nil? ? [] : valuexmlnode.find(path)
@@ -150,10 +152,10 @@ class Cell < XMLTiedItem
150
152
  when 'N/A' then :unassigned
151
153
  when 'currency' then :currency
152
154
  else
153
- if xmlnode.children.size == 0
155
+ if xmlnode.elements.size == 0
154
156
  nil
155
157
  else
156
- raise "Unknown type at #{coordinates.to_s} from #{xmlnode.to_s} / children size=#{xmlnode.children.size.to_s} / type=#{xmlnode.attributes['value-type'].to_s}"
158
+ raise "Unknown type at #{coordinates.to_s} from #{xmlnode.to_s} / elements size=#{xmlnode.elements.size.to_s} / type=#{xmlnode.attributes['value-type'].to_s}"
157
159
  end
158
160
  end
159
161
 
@@ -0,0 +1,17 @@
1
+ module Rspreadsheet
2
+
3
+ # Represents a columns in a spreadsheet. Similar to Row object, but
4
+ # currently only partly implemented
5
+
6
+ class Column
7
+ def initialize(aworksheet,acoli)
8
+ @worksheet = aworksheet
9
+ @coli = acoli
10
+ end
11
+ def cell(rowi)
12
+ @worksheet.row(rowi).cell(@coli)
13
+
14
+ end
15
+ end
16
+
17
+ end
@@ -7,7 +7,7 @@ module Rspreadsheet
7
7
  # Represents a row in a spreadsheet which has coordinates, contains value, formula and can be formated.
8
8
  # You can get this object like this (suppose that @worksheet contains {Rspreadsheet::Worksheet} object)
9
9
  #
10
- # @row = @worksheet.rows(5)
10
+ # @row = @worksheet.row(5)
11
11
  #
12
12
  # Mostly you will this object to access row cells values
13
13
  #
@@ -15,7 +15,7 @@ module Rspreadsheet
15
15
  #
16
16
  # or directly row `Cell` objects
17
17
  #
18
- # @row.cells(2) # => identical to @worksheet.rows(5).cells(2)
18
+ # @row.cell(2) # => identical to @worksheet.rows(5).cells(2)
19
19
  #
20
20
  # You can use it to manipulate rows
21
21
  #
@@ -43,6 +43,7 @@ class Row < XMLTiedItem
43
43
 
44
44
  # @!group Syntactic sugar
45
45
  def cells(*params); subitems(*params) end
46
+ alias :cell :cells
46
47
 
47
48
  ## @return [String or Float or Date] value of the cell
48
49
  # @param coli [Integer] colum index of the cell
@@ -119,353 +120,4 @@ class Row < XMLTiedItem
119
120
  def set_index(value); @rowi=value end
120
121
  end
121
122
 
122
- # class Row
123
- # def initialize
124
- # @readonly = :unknown
125
- # @cells = {}
126
- # end
127
- # def worksheet; @parent_array.worksheet end
128
- # def parent_array; @parent_array end # for debug only
129
- # def used_col_range; 1..first_unused_column_index-1 end
130
- # def used_range; used_col_range end
131
- # def first_unused_column_index; raise 'this should be redefined in subclasses' end
132
- # end
133
-
134
-
135
- # --------------------------
136
-
137
-
138
- # # XmlTiedArrayItemGroup is internal representation of repeated items in XmlTiedArray.
139
- # class XmlTiedArrayItemGroup
140
- # # extend Forwardable
141
- # # delegate [:normalize ] => :@row_group
142
- #
143
- # def normalize; @rowgroup.normalize end
144
-
145
- # end
146
-
147
- # array which synchronizes with xml structure and reflects. number-xxx-repeated attributes
148
- # also caches returned objects for indexes.
149
- # options must contain
150
- # :xml_items, :xml_repeated_attribute, :object_type
151
-
152
- # class XmlTiedArray < Array
153
- # def initialize(axmlnode, options={}) # TODO get rid of XmlTiedArray
154
- # @xmlnode = axmlnode
155
- # @options = options
156
- #
157
- # missing_options = [:xml_repeated_attribute,:xml_items_node_name,:object_type]-@options.keys
158
- # raise "Some options missing (#{missing_options.inspect})" unless missing_options.empty?
159
- #
160
- # unless @xmlnode.nil?
161
- # @xmlnode.elements.select{|node| node.name == options[:xml_items_node_name]}.each do |group_source_node|
162
- # self << parse_xml_to_group(group_source_node) # it is in @xmlnode so suffices to add object to @rowgroups
163
- # end
164
- # end
165
- # @itemcache=Hash.new()
166
- # end
167
- # def parse_xml_to_group(size_or_xmlnode) # parses xml to new RowGroup which can be added at the end
168
- # # reading params
169
- # if size_or_xmlnode.kind_of? LibXML::XML::Node
170
- # size = (size_or_xmlnode[@options[:xml_repeated_attribute]] || 1).to_i
171
- # node = size_or_xmlnode
172
- # elsif size_or_xmlnode.to_i>0
173
- # size = size_or_xmlnode.to_i
174
- # node = nil
175
- # else
176
- # return nil
177
- # end
178
- # index = first_unused_index
179
- # # construct result
180
- # Rspreadsheet::XmlTiedArrayItemGroup.new(self,index..index+size-1,node)
181
- # end
182
- # def add_item_group(size_or_xmlnode)
183
- # result = parse_xml_to_group(size_or_xmlnode)
184
- # self << result
185
- # @xmlnode << result.xmlnode
186
- # result
187
- # end
188
- # def first_unused_index
189
- # empty? ? 1 : last.range.end+1
190
- # end
191
- # # prolonges the RowArray to cantain rowi and returns it
192
- # def detach_of_bound_item(index)
193
- # fill_row_group_size = index-first_unused_index
194
- # if fill_row_group_size>0
195
- # add_item_group(fill_row_group_size)
196
- # end
197
- # add_item_group(1)
198
- # get_item(index) # aby se odpoved nacacheovala
199
- # end
200
- # def get_item_group(index)
201
- # find{ |item_group| item_group.range.cover?(index) }
202
- # end
203
- # def detach_item(index); get_item(index) end # TODO předělat do lazy podoby, kdy tohle nebude stejny
204
- # def get_item(index)
205
- # if index>= first_unused_index
206
- # nil
207
- # else
208
- # @itemcache[index] ||= Rspreadsheet::XmlTiedArrayItem.new(self,index)
209
- # end
210
- # end
211
- # # This detaches item index from the group and perhaps splits the RowGroup
212
- # # into two pieces. This makes the row individually editable.
213
- # def detach(index)
214
- # group_index = get_group_index(index)
215
- # item_group = self[group_index]
216
- # range = item_group.range
217
- # return self if range==(index..index)
218
- #
219
- # # prepare new components
220
- # replaceby = []
221
- # replaceby << RowGroup.new(self,range.begin..index-1)
222
- # replaceby << (result = SingleRow.new(self,index))
223
- # replaceby << RowGroup.new(self,index+1..range.end)
224
- #
225
- # # put original range somewhere in replaceby and shorten it
226
- #
227
- # if index>range.begin
228
- # replaceby[0] = item_group
229
- # item_group.range = range.begin..index-1
230
- # else
231
- # replaceby[2] = item_group
232
- # item_group.range = index+1..range.end
233
- # end
234
- #
235
- # # normalize and delete empty parts
236
- # replaceby = replaceby.map(&:normalize).compact
237
- #
238
- # # do the replacement in xml
239
- # marker = LibXML::XML::Node.new('temporarymarker')
240
- # item_group.xmlnode.next = marker
241
- # item_group.xmlnode.remove!
242
- # replaceby.each{ |rg|
243
- # marker.prev = rg.xmlnode
244
- # }
245
- # marker.remove!
246
- #
247
- # # do the replacement in array
248
- # self[group_index..group_index]=replaceby
249
- # result
250
- # end
251
- # private
252
- # def get_group_index(index)
253
- # self.find_index{ |rowgroup| rowgroup.range.cover?(index) }
254
- # end
255
- # end
256
-
257
- # class XmlTiedArrayItem
258
- # attr_reader :index
259
- # def initialize(aarray,aindex)
260
- # @array = aarray
261
- # @index = aindex
262
- # if self.virtual?
263
- # @object = nil
264
- # else
265
- # @object = @array.options[:object_type].new(group.xmlnode)
266
- # end
267
- # end
268
- # def group; @array.get_item_group(index) end
269
- # def repeated?; group.repeated? end
270
- # def virtual?; ! self.repeated? end
271
- # def array
272
- # raise 'Group empty' if @group.nil?
273
- # @array
274
- # end
275
- # end
276
-
277
- # class RowArray < XmlTiedArray
278
- # attr_reader :row_array_cache
279
- # def initialize(aworksheet,aworksheet_node)
280
- # @worksheet = aworksheet
281
- # @row_array_cache = Hash.new()
282
- # super(aworksheet_node, :xml_items_node_name => 'table-row', :xml_repeated_attribute => xml_repeated_attribute, :object_type=>Row)
283
- # end
284
- # def get_row(rowi)
285
- # if @row_array_cache.has_key?(rowi)
286
- # return @row_array_cache[rowi]
287
- # end
288
- # item = self.get_item(rowi)
289
- # @row_array_cache[rowi] = if item.nil?
290
- # if rowi>0 then Rspreadsheet::UninitializedEmptyRow.new(self,rowi) else nil end
291
- # else
292
- # if item.repeated?
293
- # Rspreadsheet::MemberOfRowGroup.new(item.index, item.group.to_rowgroup)
294
- # else
295
- # Rspreadsheet::SingleRow.new_from_rowgroup(item.group.to_rowgroup)
296
- # end
297
- # end
298
- # end
299
- # # aliases
300
- # def first_unused_row_index; first_unused_index end
301
- # def worksheet; @worksheet end
302
- # def detach_of_bound_row_group(index)
303
- # super(index)
304
- # return get_row(index)
305
- # end
306
- # end
307
-
308
- # class Row
309
- # def initialize
310
- # @readonly = :unknown
311
- # @cells = {}
312
- # end
313
- # def self.empty_row_node
314
- # LibXML::XML::Node.new('table-row',nil, Tools.get_namespace('table'))
315
- # end
316
- # def worksheet; @parent_array.worksheet end
317
- # def parent_array; @parent_array end # for debug only
318
- # def used_col_range; 1..first_unused_column_index-1 end
319
- # def used_range; used_col_range end
320
- # def first_unused_column_index; raise 'this should be redefined in subclasses' end
321
- # def cells(coli)
322
- # coli = coli.to_i
323
- # return nil if coli.to_i<=0
324
- # @cells[coli] ||= get_cell(coli)
325
- # end
326
- # end
327
-
328
- # class RowWithXMLNode < Row
329
- # attr_accessor :xmlnode
330
- # def style_name=(value); Tools.set_ns_attribute(@xmlnode,'table','style-name',value) end
331
- # def get_cell(coli)
332
- # Cell.new(self,coli,cellnodes(coli))
333
- # end
334
- # def nonemptycells
335
- # nonemptycellsindexes.collect{ |index| cells(index) }
336
- # end
337
- # def nonemptycellsindexes
338
- # used_col_range.to_a.select do |coli|
339
- # cellnode = cellnodes(coli)
340
- # !(cellnode.content.nil? or cellnode.content.empty? or cellnode.content =='') or
341
- # !cellnode.attributes.to_a.reject{ |attr| attr.name == 'number-columns-repeated'}.empty?
342
- # end
343
- # end
344
- # def cellnodes(coli)
345
- # cellnode = nil
346
- # while true
347
- # curr_coli=1
348
- # cellnode = @xmlnode.elements.select{|n| n.name=='table-cell'}.find do |el|
349
- # curr_coli += (Tools.get_ns_attribute_value(el, 'table', 'number-columns-repeated') || 1).to_i
350
- # curr_coli > coli
351
- # end
352
- # unless cellnode.nil?
353
- # return cellnode
354
- # else
355
- # add_cell
356
- # end
357
- # end
358
- # end
359
- # def add_cell(repeated=1)
360
- # cell = Cell.new(self,first_unused_column_index)
361
- # Tools.set_ns_attribute(cell.xmlnode,'table','number-columns-repeated',repeated) if repeated>1
362
- # @xmlnode << cell.xmlnode
363
- # cell
364
- # end
365
- # def first_unused_column_index
366
- # 1 + @xmlnode.elements.select{|n| n.name=='table-cell'}.reduce(0) do |sum, el|
367
- # sum + (Tools.get_ns_attribute_value(el, 'table', 'number-columns-repeated') || 1).to_i
368
- # end
369
- # end
370
- # end
371
-
372
- # class RowGroup < RowWithXMLNode
373
- # @readonly = :yes_always
374
- # attr_reader :range
375
- # attr_accessor :parent_array, :xmlnode
376
- # def initialize(aparent_array,arange,axmlnode=nil)
377
- # super()
378
- # @parent_array = aparent_array
379
- # @range = arange
380
- # if axmlnode.nil?
381
- # axmlnode = Row.empty_row_node
382
- # Tools.set_ns_attribute(axmlnode,'table','number-rows-repeated',range.size) if range.size>1
383
- # end
384
- # @xmlnode = axmlnode
385
- # end
386
- # # returns SingleRow if size of range is 1 and nil if it is 0 or less
387
- # def normalize
388
- # case range.size
389
- # when 2..Float::INFINITY then self
390
- # when 1 then SingleRow.new_from_rowgroup(self)
391
- # else nil
392
- # end
393
- # end
394
- # def repeated; range.size end
395
- # def repeated?; range.size>1 end
396
- # def range=(arange)
397
- # @range=arange
398
- # Tools.set_ns_attribute(@xmlnode,'table','number-rows-repeated',range.size, 1)
399
- # end
400
- # end
401
-
402
- # class SingleRow < RowWithXMLNode
403
- # @readonly = :no
404
- # attr_accessor :xmlnode
405
- # # index Integer
406
- # def initialize(aparent_array,aindex,axmlnode=nil)
407
- # super()
408
- # @parent_array = aparent_array
409
- # @index = aindex
410
- # if axmlnode.nil?
411
- # axmlnode = Row.empty_row_node
412
- # end
413
- # @xmlnode = axmlnode
414
- # end
415
- # def self.new_from_rowgroup(rg)
416
- # anode = rg.xmlnode
417
- # Tools.remove_ns_attribute(anode,'table','number-rows-repeated')
418
- # SingleRow.new(rg.parent_array,rg.range.begin,anode)
419
- # end
420
- # def normalize; self end
421
- # def repeated?; false end
422
- # def repeated; 1 end
423
- # def range; (@index..@index) end
424
- # def detach; self end
425
- # def row; @index end
426
- # def still_out_of_used_range?; false end
427
- # end
428
-
429
- # class LazyDetachableRow < Row
430
- # @readonly = :yes_but_detachable
431
- # def initialize(rowi)
432
- # super()
433
- # @index = rowi.to_i
434
- # end
435
- # def add_cell; detach.add_cell end
436
- # def style_name=(value); detach.style_name=value end
437
- # def row; @index end
438
- # end
439
-
440
- # ## there are not data in this object, they are taken from RowGroup, but this is only readonly
441
- # class MemberOfRowGroup < LazyDetachableRow
442
- # @readonly = :yes_but_detachable
443
- # extend Forwardable
444
- # delegate [:repeated?, :repeated, :xmlnode, :parent_array] => :@row_group
445
- # attr_accessor :row_group # for dubugging
446
- #
447
- # # @index Integer
448
- # # @row_group RepeatedRow
449
- # def initialize(arowi,arow_group)
450
- # super(arowi)
451
- # @row_group = arow_group
452
- # raise 'Wrong parameter given - class is '+@row_group.class.to_a unless @row_group.is_a? RowGroup
453
- # end
454
- # def detach # detaches MemberOfRowGroup from its RowGroup perhaps splitting RowGroup
455
- # @row_group.parent_array.detach(@index)
456
- # end
457
- # def get_cell(coli)
458
- # c = Cell.new(self,coli,@row_group.cellnodes(coli))
459
- # c.mode = :repeated
460
- # c
461
- # end
462
- # def first_unused_column_index
463
- # @row_group.first_unused_column_index
464
- # end
465
- # def nonemptycells
466
- # @row_group.nonemptycellsindexes.collect{ |coli| cells(coli) }
467
- # end
468
- # end
469
-
470
-
471
123
  end
@@ -1,3 +1,3 @@
1
1
  module Rspreadsheet
2
- VERSION = "0.2.12"
2
+ VERSION = "0.2.14"
3
3
  end
@@ -1,5 +1,7 @@
1
1
  require 'rspreadsheet/row'
2
+ require 'rspreadsheet/column'
2
3
  require 'rspreadsheet/tools'
4
+ require 'helpers/class_extensions'
3
5
  # require 'forwardable'
4
6
 
5
7
  module Rspreadsheet
@@ -54,6 +56,7 @@ class Worksheet
54
56
 
55
57
  #@!group XMLTiedArray connected methods
56
58
  def rows(*params); subitems(*params) end
59
+ alias :row :rows
57
60
  def prepare_subitem(rowi); Row.new(self,rowi) end
58
61
  def rowcache; @itemcache end
59
62
 
@@ -82,10 +85,15 @@ class Worksheet
82
85
  when 0 then raise 'Not implemented yet' #TODO: return list of all cells
83
86
  when 1..2
84
87
  r,c = Rspreadsheet::Tools.a2c(*params)
85
- rows(r).andand.cells(c)
88
+ row(r).andand.cell(c)
86
89
  else raise Exception.new('Wrong number of arguments.')
87
90
  end
88
91
  end
92
+ alias :cell :cells
93
+ def column(param)
94
+ r,coli = Rspreadsheet::Tools.a2c(1,param)
95
+ Column.new(self,coli)
96
+ end
89
97
  # Allows syntax like sheet.F15. TO catch errors easier, allows only up to three uppercase letters in colum part, althought it won't be necessarry to restrict.
90
98
  def method_missing method_name, *args, &block
91
99
  if method_name.to_s.match(/^([A-Z]{1,3})(\d{1,8})(=?)$/)
@@ -1,5 +1,9 @@
1
+ require 'helpers/class_extensions'
2
+
1
3
  module Rspreadsheet
2
4
 
5
+ using ClassExtensions if RUBY_VERSION > '2.1'
6
+
3
7
  # @private
4
8
  class XMLTied
5
9
  def xml
@@ -66,8 +70,8 @@ end
66
70
 
67
71
  # abstract class. All importers MUST implement: prepare_subitem (and delete)
68
72
  # terminology
69
- # item, subitem is object from @itemcache (quite often subclass of XMLTiedItem)
70
- # node, subnode is LibXML::XML::Node object
73
+ # item, subitem is object from @itemcache (quite often subclass of XMLTiedItem)
74
+ # node, subnode is LibXML::XML::Node object
71
75
  #
72
76
  # this class is made to be included, not subclassed - the reason is in delete method which calls super
73
77
  # @private
@@ -8,115 +8,119 @@ describe Rspreadsheet::Cell do
8
8
  @sheet2 = book2.worksheets(1)
9
9
  end
10
10
  it 'contains good row and col coordinates' do
11
- @cell = @sheet1.cells(1,3)
11
+ @cell = @sheet1.cell(1,3)
12
12
  @cell.rowi.should == 1
13
13
  @cell.coli.should == 3
14
14
  @cell.coordinates.should == [1,3]
15
- @cell = @sheet2.cells(7,2)
15
+ @cell = @sheet2.cell(7,2)
16
16
  @cell.rowi.should == 7
17
17
  @cell.coli.should == 2
18
18
  @cell.coordinates.should == [7,2]
19
19
  end
20
20
  it 'can be referenced by more vars and both are synchronized' do
21
- @cell = @sheet1.cells(1,1)
21
+ @cell = @sheet1.cell(1,1)
22
22
  @sheet1[1,1] = 'novinka'
23
23
  @cell.value.should == 'novinka'
24
24
  end
25
25
  it 'can be modified by more ways and all are identical' do
26
- @cell = @sheet1.cells(2,2)
26
+ @cell = @sheet1.cell(2,2)
27
27
  @sheet1[2,2] = 'zaprve'
28
28
  @cell.value.should == 'zaprve'
29
- @sheet1.cells(2,2).value = 'zadruhe'
29
+ @sheet1.cell(2,2).value = 'zadruhe'
30
30
  @cell.value.should == 'zadruhe'
31
31
  @sheet1.B2 = 'zatreti'
32
32
  @cell.value.should == 'zatreti'
33
- @sheet1.rows(2).cells(2).value = 'zactvrte'
33
+ @sheet1.row(2).cell(2).value = 'zactvrte'
34
34
  @cell.value.should == 'zactvrte'
35
- @sheet1.rows(2)[2] = 'zapate'
35
+ @sheet1.rows[1].cell(2).value = 'zactvrte s arrayem'
36
+ @cell.value.should == 'zactvrte s arrayem'
37
+ @sheet1.row(2)[2] = 'zapate'
36
38
  @cell.value.should == 'zapate'
39
+ @sheet1.rows[1][2] = 'zaseste' ## tohle je divoka moznost
40
+ @cell.value.should == 'zaseste'
37
41
  end
38
42
  it 'can include links' do
39
43
  @sheet2.A12.should == '[http://example.org/]'
40
- @sheet2.cells(12,2).valuexmlfindall('.//text:a').size.should eq 0
41
- @sheet2.cells(12,1).valuexmlfindall('.//text:a').size.should eq 1
42
- @sheet2.cells(12,1).valuexmlfindfirst('.//text:a').attributes['href'].should eq 'http://example.org/'
44
+ @sheet2.cell(12,2).valuexmlfindall('.//text:a').size.should eq 0
45
+ @sheet2.cell(12,1).valuexmlfindall('.//text:a').size.should eq 1
46
+ @sheet2.cell(12,1).valuexmlfindfirst('.//text:a').attributes['href'].should eq 'http://example.org/'
43
47
  end
44
48
  it 'contains good row and col coordinates even after table:number-columns-repeated cells' do
45
- @cell = @sheet2.cells(13,5)
49
+ @cell = @sheet2.cell(13,5)
46
50
  @cell.value.should == 'afterrepeated'
47
51
  @cell.rowi.should == 13
48
52
  @cell.coli.should == 5
49
53
  end
50
54
  it 'reports good range of coordinates for repeated cells' do
51
- @cell = @sheet2.cells(13,2)
55
+ @cell = @sheet2.cell(13,2)
52
56
  @cell.range.should == (1..4)
53
57
  @cell.mode.should == :repeated
54
58
  end
55
59
  it 'returns nil on negative and zero cell indexes or raises exception depending on configuration' do
56
60
  pom = Rspreadsheet.raise_on_negative_coordinates
57
61
  # default is to raise error
58
- expect {@sheet2.cells(0,5) }.to raise_error
62
+ expect {@sheet2.cell(0,5) }.to raise_error
59
63
 
60
64
  # return nil if configured to do so
61
65
  Rspreadsheet.raise_on_negative_coordinates = false
62
- @sheet2.cells(0,5).should be_nil
63
- @sheet2.cells(2,-5).should be(nil)
64
- @sheet2.cells(-2,-5).should be(nil)
66
+ @sheet2.cell(0,5).should be_nil
67
+ @sheet2.cell(2,-5).should be(nil)
68
+ @sheet2.cell(-2,-5).should be(nil)
65
69
 
66
70
  Rspreadsheet.raise_on_negative_coordinates = pom # reset the setting back
67
71
  end
68
72
  it 'has nonempty parents' do
69
- @cell = @sheet2.cells(13,5)
73
+ @cell = @sheet2.cell(13,5)
70
74
  @cell.row.should_not be_nil
71
75
  @cell.worksheet.should_not be_nil
72
76
 
73
- @cell = @sheet1.cells(2,2)
77
+ @cell = @sheet1.cell(2,2)
74
78
  @cell.row.should_not be_nil
75
79
  @cell.worksheet.should_not be_nil
76
80
  end
77
81
  it 'handles relative correctly' do
78
- @sheet2.cells(3,3).relative(-1,+2).coordinates.should == [2,5]
79
- @sheet2.cells(3,3).relative(0,0).coordinates.should == [3,3]
82
+ @sheet2.cell(3,3).relative(-1,+2).coordinates.should == [2,5]
83
+ @sheet2.cell(3,3).relative(0,0).coordinates.should == [3,3]
80
84
  end
81
85
  it 'is automatically "unrepeated" on value assignement' do
82
- @cell = @sheet2.cells(13,2)
86
+ @cell = @sheet2.cell(13,2)
83
87
  @cell.is_repeated?.should == true
84
88
  @cell.value = 'cokoli'
85
89
  @cell.is_repeated?.should == false
86
90
  @cell.value.should == 'cokoli'
87
- @sheet2.cells(13,1).should_not == 'cokoli'
88
- @sheet2.cells(13,3).should_not == 'cokoli'
89
- @sheet2.cells(13,4).should_not == 'cokoli'
91
+ @sheet2.cell(13,1).should_not == 'cokoli'
92
+ @sheet2.cell(13,3).should_not == 'cokoli'
93
+ @sheet2.cell(13,4).should_not == 'cokoli'
90
94
  end
91
95
  it 'returns correct type for the cell' do
92
- @sheet2.cells(1,2).type.should eq :string
93
- @sheet2.cells(2,2).type.should eq :date
94
- @sheet2.cells(3,1).type.should eq :float
95
- @sheet2.cells(3,2).type.should eq :percentage
96
- @sheet2.cells(4,2).type.should eq :string
97
- @sheet2.cells('B22').type.should eq :currency
98
- @sheet2.cells('B23').type.should eq :currency
99
- @sheet2.cells(200,200).type.should eq :unassigned
96
+ @sheet2.cell(1,2).type.should eq :string
97
+ @sheet2.cell(2,2).type.should eq :date
98
+ @sheet2.cell(3,1).type.should eq :float
99
+ @sheet2.cell(3,2).type.should eq :percentage
100
+ @sheet2.cell(4,2).type.should eq :string
101
+ @sheet2.cell('B22').type.should eq :currency
102
+ @sheet2.cell('B23').type.should eq :currency
103
+ @sheet2.cell(200,200).type.should eq :unassigned
100
104
  end
101
105
  it 'returns value of correct type' do
102
106
  @sheet2[1,2].should be_kind_of(String)
103
107
  @sheet2[2,2].should be_kind_of(Date)
104
108
  @sheet2[3,1].should be_kind_of(Float)
105
109
  @sheet2[3,2].should be_kind_of(Float)
106
- @sheet2.cells(3,2).type.should eq :percentage
107
- @sheet2.cells(3,2).guess_cell_type.should eq :percentage
108
- @sheet2.cells(3,2).guess_cell_type(1).should eq :percentage
110
+ @sheet2.cell(3,2).type.should eq :percentage
111
+ @sheet2.cell(3,2).guess_cell_type.should eq :percentage
112
+ @sheet2.cell(3,2).guess_cell_type(1).should eq :percentage
109
113
  @sheet2[3,2]=0.1
110
- @sheet2.cells(3,2).type.should eq :percentage
114
+ @sheet2.cell(3,2).type.should eq :percentage
111
115
  @sheet2[4,2].should be_kind_of(String)
112
116
  end
113
117
  it 'is the same object no matter how you access it' do
114
- @cell1 = @sheet2.cells(5,5)
115
- @cell2 = @sheet2.rows(5).cells(5)
118
+ @cell1 = @sheet2.cell(5,5)
119
+ @cell2 = @sheet2.rows(5).cell(5)
116
120
  @cell1.should equal(@cell2)
117
121
  end
118
122
  it 'splits correctly cells if written in the middle of repeated group' do
119
- @cell = @sheet2.cells(4,6)
123
+ @cell = @sheet2.cell(4,6)
120
124
  @cell.range.should == (4..7)
121
125
  @cell.value.should == 7
122
126
 
@@ -124,16 +128,16 @@ describe Rspreadsheet::Cell do
124
128
  @cell.range.should == (6..6)
125
129
  @cell.value.should == 'nebesa'
126
130
 
127
- @cellA = @sheet2.cells(4,5)
131
+ @cellA = @sheet2.cell(4,5)
128
132
  @cellA.range.should == (4..5)
129
133
  @cellA.value.should == 7
130
134
 
131
- @cellB = @sheet2.cells(4,7)
135
+ @cellB = @sheet2.cell(4,7)
132
136
  @cellB.range.should == (7..7)
133
137
  @cellB.value.should == 7
134
138
  end
135
139
  it 'inserts correctly cell in the middle of repeated group' do
136
- @cell = @sheet2.cells(4,6)
140
+ @cell = @sheet2.cell(4,6)
137
141
  @cell.range.should == (4..7)
138
142
  @cell.value.should == 7
139
143
  @cell.coli.should == 6
@@ -141,15 +145,15 @@ describe Rspreadsheet::Cell do
141
145
  @sheet2.insert_cell_before(4,6)
142
146
  @cell.coli.should == 7
143
147
 
144
- @cellA = @sheet2.cells(4,5)
148
+ @cellA = @sheet2.cell(4,5)
145
149
  @cellA.range.should == (4..5)
146
150
  @cellA.value.should == 7
147
151
 
148
- @cellB = @sheet2.cells(4,7)
152
+ @cellB = @sheet2.cell(4,7)
149
153
  @cellB.range.should == (7..8)
150
154
  @cellB.value.should == 7
151
155
 
152
- @cell = @sheet2.cells(16,4)
156
+ @cell = @sheet2.cell(16,4)
153
157
  @cell.range.should == (1..7)
154
158
  @cell.value.should == nil
155
159
 
@@ -157,45 +161,45 @@ describe Rspreadsheet::Cell do
157
161
  @sheet2.rows(16).range.should == (14..18)
158
162
  @sheet2.rows(17).range.should == (14..18)
159
163
  @sheet2.insert_cell_before(16,3)
160
- @sheet2.cells(16,3).value = 'baf'
161
- @sheet2.cells(17,3).value.should_not == 'baf'
164
+ @sheet2.cell(16,3).value = 'baf'
165
+ @sheet2.cell(17,3).value.should_not == 'baf'
162
166
  @sheet2.rows(15).range.should == (14..15)
163
167
  @sheet2.rows(16).range.should == (16..16)
164
168
  @sheet2.rows(17).range.should == (17..18)
165
169
 
166
- @cellA = @sheet2.cells(16,1)
170
+ @cellA = @sheet2.cell(16,1)
167
171
  @cellA.range.should == (1..2)
168
172
  @cellA.value.should be_nil
169
173
 
170
- @cellB = @sheet2.cells(16,5)
174
+ @cellB = @sheet2.cell(16,5)
171
175
  @cellB.range.should == (4..8)
172
176
  @cellB.value.should be_nil
173
177
 
174
178
  end
175
179
  it 'inserted has correct class' do # based on real error
176
180
  @sheet2.insert_cell_before(1,1)
177
- @sheet2.rows(1).cells(1).should be_kind_of(Rspreadsheet::Cell)
181
+ @sheet2.rows(1).cell(1).should be_kind_of(Rspreadsheet::Cell)
178
182
  end
179
183
  it 'can have different formats' do
180
- @cell = @sheet2.cells(6,3)
184
+ @cell = @sheet2.cell(6,3)
181
185
  @cell.format.bold.should == true
182
- @cell = @sheet2.cells(6,4)
186
+ @cell = @sheet2.cell(6,4)
183
187
  @cell.format.bold.should == false
184
188
  @cell.format.italic.should == true
185
- @cell = @sheet2.cells(6,5)
189
+ @cell = @sheet2.cell(6,5)
186
190
  @cell.format.italic.should == false
187
191
  @cell.format.color.should == '#ff3333'
188
- @cell = @sheet2.cells(6,6)
192
+ @cell = @sheet2.cell(6,6)
189
193
  @cell.format.color.should_not == '#ff3333'
190
194
  @cell.format.background_color.should == '#6666ff'
191
- @cell = @sheet2.cells(6,7)
195
+ @cell = @sheet2.cell(6,7)
192
196
  @cell.format.font_size.should == '7pt'
193
197
 
194
198
  # after fresh create
195
199
  @cell.xmlnode.attributes['style-name'].should_not be_nil
196
200
  end
197
- it 'can set formats of the cells in new file' do
198
- @cell = @sheet1.cells(1,1)
201
+ it 'can set formats of the cell in new file' do
202
+ @cell = @sheet1.cell(1,1)
199
203
  @cell.value = '1'
200
204
  # bold
201
205
  @cell.format.bold.should be_falsey
@@ -226,15 +230,15 @@ describe Rspreadsheet::Cell do
226
230
 
227
231
  end
228
232
  it 'changes coordinates when row inserted above' do
229
- @sheet1.cells(2,2).detach
230
- @cell = @sheet1.cells(2,2)
233
+ @sheet1.cell(2,2).detach
234
+ @cell = @sheet1.cell(2,2)
231
235
  @cell.rowi.should == 2
232
236
  @sheet1.add_row_above(1)
233
237
  @cell.rowi.should == 3
234
238
  end
235
239
  it 'switches to invalid_reference cell when deleted' do
236
240
  @sheet1[2,5] = 'nejaka data'
237
- @cell = @sheet1.cells(2,2)
241
+ @cell = @sheet1.cell(2,2)
238
242
  @cell.value = 'data'
239
243
  @cell.invalid_reference?.should be false
240
244
  @cell.delete
@@ -242,11 +246,11 @@ describe Rspreadsheet::Cell do
242
246
  expect { @cell.rowi }.to raise_error
243
247
  expect { @cell.address }.to raise_error
244
248
 
245
- @sheet1.cells(2,2).type.should == :empty
246
- @sheet1.cells(3,2).type.should == :unassigned
249
+ @sheet1.cell(2,2).type.should == :empty
250
+ @sheet1.cell(3,2).type.should == :unassigned
247
251
  end
248
252
  it 'switches to invalid_reference cell when its row is deleted' do
249
- @cell = @sheet1.cells(6,2)
253
+ @cell = @sheet1.cell(6,2)
250
254
  @cell.value = 'data'
251
255
  @cell.rowi.should == 6
252
256
  @sheet1.rows(6).delete
@@ -254,35 +258,35 @@ describe Rspreadsheet::Cell do
254
258
  @cell.invalid_reference?.should be true
255
259
  end
256
260
  it 'has inspect method returning something good' do
257
- @cell = @sheet1.cells(6,2)
261
+ @cell = @sheet1.cell(6,2)
258
262
  @cell.value = 'abcde'
259
263
  expect(@cell.inspect).to include('abcde','::Cell','6','2','row')
260
264
  end
261
265
  it 'stores date correctly' do
262
- @cell = @sheet1.cells(1,1)
266
+ @cell = @sheet1.cell(1,1)
263
267
  @cell.value= Date.parse('2014-01-02')
264
268
  @cell.value.year.should eq 2014
265
269
  @cell.value.month.should eq 1
266
270
  @cell.value.day.should eq 2
267
271
  end
268
272
  it 'can be addressed by even more ways and all are identical' do
269
- @cell = @sheet1.cells(2,2)
270
- @sheet1.cells('B2').value = 'zaseste'
271
- @sheet1.cells('B2').value.should == 'zaseste'
273
+ @cell = @sheet1.cell(2,2)
274
+ @sheet1.cell('B2').value = 'zaseste'
275
+ @sheet1.cell('B2').value.should == 'zaseste'
272
276
  @cell.value.should == 'zaseste'
273
- @sheet1.cells(2,'B').value.should == 'zaseste'
274
- @sheet1.cells(2,'B').value = 'zasedme'
277
+ @sheet1.cell(2,'B').value.should == 'zaseste'
278
+ @sheet1.cell(2,'B').value = 'zasedme'
275
279
  @cell.value.should == 'zasedme'
276
280
  @sheet1['B2'].should == 'zasedme'
277
281
  @sheet1['B2'] = 'zaosme'
278
282
  @cell.value.should == 'zaosme'
279
283
 
280
- @sheet2.cells('F2').should be @sheet2.cells(2,6)
281
- @sheet2.cells('BA177').should be @sheet2.cells(177,53)
282
- @sheet2.cells('ADA2').should be @sheet2.cells(2,781)
284
+ @sheet2.cell('F2').should be @sheet2.cell(2,6)
285
+ @sheet2.cell('BA177').should be @sheet2.cell(177,53)
286
+ @sheet2.cell('ADA2').should be @sheet2.cell(2,781)
283
287
  end
284
288
  it 'setting format in new file detaches the cell' do
285
- @cell = @sheet1.cells(1,1)
289
+ @cell = @sheet1.cell(1,1)
286
290
  # bold
287
291
  @cell.format.bold.should be_falsey
288
292
  @cell.format.bold = true
@@ -290,14 +294,14 @@ describe Rspreadsheet::Cell do
290
294
  @cell.mode.should eq :regular
291
295
  end
292
296
  it 'remembers formula when set' do
293
- @cell = @sheet1.cells(1,1)
297
+ @cell = @sheet1.cell(1,1)
294
298
  # bold
295
299
  @cell.formula.should be_nil
296
300
  @cell.formula='=1+5'
297
301
  @cell.formula.should eq '=1+5'
298
302
  end
299
303
  it 'unsets cell type when formula set - we can not guess it correctly', :focus do
300
- @cell = @sheet1.cells(1,1)
304
+ @cell = @sheet1.cell(1,1)
301
305
  @cell.value = 'ahoj'
302
306
  @cell.type.should eq :string
303
307
  @cell.formula='=1+5'
@@ -306,7 +310,7 @@ describe Rspreadsheet::Cell do
306
310
  @cell.type.should eq :empty
307
311
  end
308
312
  it 'wipes out formula after assiging value' do
309
- @cell = @sheet1.cells(1,1)
313
+ @cell = @sheet1.cell(1,1)
310
314
  @cell.formula='=1+5'
311
315
  @cell.formula.should_not be_nil
312
316
  @cell.value = 'baf'
@@ -314,19 +318,13 @@ describe Rspreadsheet::Cell do
314
318
  @cell.formula.should be_nil
315
319
  end
316
320
  it 'works well with currency types' do
317
- @usdcell = @sheet2.cells('B22')
321
+ @usdcell = @sheet2.cell('B22')
318
322
  @usdcell.type.should eq :currency
319
323
  @usdcell.value.should == -147984.84
320
324
  @usdcell.format.currency.should == 'USD'
321
325
 
322
- @czkcell = @sheet2.cells('B23')
326
+ @czkcell = @sheet2.cell('B23')
323
327
  @czkcell.value.should == 344.to_d
324
328
  @czkcell.format.currency.should == 'CZK'
325
329
  end
326
330
  end
327
-
328
-
329
-
330
-
331
-
332
-
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+
3
+ if RUBY_VERSION > '2.1'
4
+ using ClassExtensions
5
+
6
+ describe Array do
7
+ it 'can sum simple array' do
8
+ a = [1,2,3,4]
9
+ a.sum.should == 10
10
+ end
11
+ it 'ignores text and nils while summing' do
12
+ a = [1,nil, nil,2,3,'foo',5.0]
13
+ a.sum.should == 11
14
+ [nil, 'nic'].sum.should == 0
15
+ [].sum.should == 0
16
+ end
17
+ end
18
+
19
+ describe LibXML::XML::Node do
20
+ before do
21
+ @n = LibXML::XML::Node.new('a')
22
+ @n << LibXML::XML::Node.new('i','italic')
23
+ b = LibXML::XML::Node.new('p','paragraph')
24
+ b << LibXML::XML::Node.new('b','boldtext')
25
+ @n << b
26
+ @n << LibXML::XML::Node.new_text('textnode')
27
+
28
+ @m = LibXML::XML::Node.new('a')
29
+ @m << LibXML::XML::Node.new('i','italic')
30
+ c = LibXML::XML::Node.new('p','paragraph')
31
+ c << LibXML::XML::Node.new('b','boldtext')
32
+ @m << c
33
+ @m << LibXML::XML::Node.new_text('textnode')
34
+
35
+ @m2 = LibXML::XML::Node.new('a')
36
+ end
37
+ it 'can compare nodes' do
38
+ @n.should == @m
39
+ @n.should_not == @m2
40
+ end
41
+ it 'has correct elements' do
42
+ # raise @n.first_diff(@m).inspect
43
+ end
44
+ end
45
+
46
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rspreadsheet::Cell do
4
+ before do
5
+ book1 = Rspreadsheet.new
6
+ @sheet = book1.create_worksheet
7
+ end
8
+ it 'contains the right cells' do
9
+ @sheet[1,1] = '11'
10
+ @sheet[1,2] = '12'
11
+ @sheet[2,1] = '21'
12
+ @sheet[2,2] = '22'
13
+ @sheet.column(1).cell(2).value.should eq('21')
14
+ @sheet.column(2).cell(2).value.should eq('22')
15
+ @sheet.column(2).cell(1).should eq(@sheet.cell(1,2))
16
+ end
17
+
18
+ end
@@ -1,4 +1,5 @@
1
1
  require 'spec_helper'
2
+ using ClassExtensions if RUBY_VERSION > '2.1'
2
3
 
3
4
  describe Rspreadsheet do
4
5
  it 'can open ods testfile and reads its content correctly' do
@@ -42,7 +43,7 @@ describe Rspreadsheet do
42
43
  @content_xml2.root.first_diff(@content_xml1.root).should be_nil
43
44
  @content_xml1.root.first_diff(@content_xml2.root).should be_nil
44
45
 
45
- @content_xml1.root.equals?(@content_xml2.root).should == true
46
+ @content_xml1.root.should == @content_xml2.root
46
47
  end
47
48
  it 'when open and save file modified, than the file is different' do
48
49
  tmp_filename = '/tmp/testfile1.ods' # first delete temp file
@@ -87,7 +88,7 @@ describe Rspreadsheet do
87
88
  sheet.cells(5,2).format.bold = true
88
89
  sheet.cells(5,2).format.background_color = '#FF0000'
89
90
  }.not_to raise_error
90
-
91
+
91
92
  sheet.rows(4).cellvalues.sum{|val| val.to_f}.should eq 4+7*4
92
93
  sheet.rows(4).cells.sum{ |cell| cell.value.to_f }.should eq 4+7*4
93
94
 
@@ -1,4 +1,5 @@
1
1
  require 'spec_helper'
2
+ using ClassExtensions if RUBY_VERSION > '2.1'
2
3
 
3
4
  describe Rspreadsheet::Worksheet do
4
5
  describe "from test workbook file" do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspreadsheet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.12
4
+ version: 0.2.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jakub A.Těšínský
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-16 00:00:00.000000000 Z
11
+ date: 2015-11-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: libxml-ruby
@@ -180,6 +180,7 @@ files:
180
180
  - lib/helpers/configuration.rb
181
181
  - lib/rspreadsheet.rb
182
182
  - lib/rspreadsheet/cell.rb
183
+ - lib/rspreadsheet/column.rb
183
184
  - lib/rspreadsheet/empty_file_template.ods
184
185
  - lib/rspreadsheet/row.rb
185
186
  - lib/rspreadsheet/tools.rb
@@ -190,6 +191,8 @@ files:
190
191
  - reinstall_local_gem.sh
191
192
  - rspreadsheet.gemspec
192
193
  - spec/cell_spec.rb
194
+ - spec/class_extensions_spec.rb
195
+ - spec/column_spec.rb
193
196
  - spec/row_spec.rb
194
197
  - spec/rspreadsheet_spec.rb
195
198
  - spec/spec_helper.rb
@@ -224,6 +227,8 @@ summary: Manipulating spreadsheets with Ruby (read / create / modify OpenDocumen
224
227
  Spreadsheet).
225
228
  test_files:
226
229
  - spec/cell_spec.rb
230
+ - spec/class_extensions_spec.rb
231
+ - spec/column_spec.rb
227
232
  - spec/row_spec.rb
228
233
  - spec/rspreadsheet_spec.rb
229
234
  - spec/spec_helper.rb