rspreadsheet 0.2.15 → 0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -9,8 +10,10 @@ describe Rspreadsheet::Worksheet do
9
10
  @sheet.rows(1).xmlnode.elements.size.should be >1
10
11
  end
11
12
  it 'uses detach_my_subnode_respect_repeated well' do
12
- @sheet.detach_my_subnode_respect_repeated(50, {:xml_items_node_name => 'table-row', :xml_repeated_attribute => 'number-rows-repeated'})
13
- @sheet.rows(50).detach_my_subnode_respect_repeated(12, {:xml_items_node_name => 'table-cell', :xml_repeated_attribute => 'number-columns-repeated'})
13
+ @sheet.cell(50,12).mode.should_not == :regular
14
+ @sheet.detach_my_subnode_respect_repeated(50)
15
+ @sheet.rows(50).detach_my_subnode_respect_repeated(12)
16
+ @sheet.cell(50,12).mode.should == :regular
14
17
  end
15
18
  end
16
19
  end
@@ -21,6 +24,10 @@ describe Rspreadsheet::Worksheet do
21
24
  @book = Rspreadsheet.new
22
25
  @sheet = @book.create_worksheet
23
26
  end
27
+ it 'array of rows is empty Array' do
28
+ @sheet.subitems_array.should == []
29
+ @sheet.images.count.should == 0
30
+ end
24
31
  it 'has correctly namespaced xmlnode' do
25
32
  @xmlnode = @sheet.xmlnode
26
33
  @xmlnode.namespaces.to_a.size.should >5
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspreadsheet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.15
4
+ version: '0.3'
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: 2016-01-22 00:00:00.000000000 Z
11
+ date: 2017-01-18 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: libxml-ruby
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '2.7'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '2.7'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: rubyzip
29
15
  requirement: !ruby/object:Gem::Requirement
@@ -122,34 +108,6 @@ dependencies:
122
108
  - - "~>"
123
109
  - !ruby/object:Gem::Version
124
110
  version: '0.7'
125
- - !ruby/object:Gem::Dependency
126
- name: guard
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - "~>"
130
- - !ruby/object:Gem::Version
131
- version: '2.6'
132
- type: :development
133
- prerelease: false
134
- version_requirements: !ruby/object:Gem::Requirement
135
- requirements:
136
- - - "~>"
137
- - !ruby/object:Gem::Version
138
- version: '2.6'
139
- - !ruby/object:Gem::Dependency
140
- name: guard-rspec
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - "~>"
144
- - !ruby/object:Gem::Version
145
- version: '2.6'
146
- type: :development
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - "~>"
151
- - !ruby/object:Gem::Version
152
- version: '2.6'
153
111
  description: Manipulating OpenDocument spreadsheets with Ruby. This gem can create
154
112
  new, read existing files abd modify them. When modyfying files, it tries to change
155
113
  as little as possible, making it as much forward compatifle as possible.
@@ -160,7 +118,6 @@ extensions: []
160
118
  extra_rdoc_files: []
161
119
  files:
162
120
  - ".coveralls.yml"
163
- - ".directory"
164
121
  - ".gitignore"
165
122
  - ".kateproject"
166
123
  - ".travis.yml"
@@ -175,31 +132,41 @@ files:
175
132
  - LICENSE.md
176
133
  - README.md
177
134
  - Rakefile
178
- - investigate.rb
179
135
  - lib/helpers/class_extensions.rb
180
136
  - lib/helpers/configuration.rb
181
137
  - lib/rspreadsheet.rb
182
138
  - lib/rspreadsheet/cell.rb
183
139
  - lib/rspreadsheet/column.rb
184
140
  - lib/rspreadsheet/empty_file_template.ods
141
+ - lib/rspreadsheet/image.rb
185
142
  - lib/rspreadsheet/row.rb
186
143
  - lib/rspreadsheet/tools.rb
187
144
  - lib/rspreadsheet/version.rb
188
145
  - lib/rspreadsheet/workbook.rb
189
146
  - lib/rspreadsheet/worksheet.rb
190
- - lib/rspreadsheet/xml_tied.rb
147
+ - lib/rspreadsheet/xml_tied_array.rb
148
+ - lib/rspreadsheet/xml_tied_item.rb
149
+ - lib/rspreadsheet/xml_tied_repeatable.rb
191
150
  - reinstall_local_gem.sh
192
151
  - rspreadsheet.gemspec
193
152
  - spec/cell_spec.rb
153
+ - spec/class_extensions_spec.rb
194
154
  - spec/column_spec.rb
155
+ - spec/image_spec.rb
156
+ - spec/included_image_spec.rb
195
157
  - spec/io_spec.rb
196
158
  - spec/row_spec.rb
197
159
  - spec/rspreadsheet_spec.rb
198
160
  - spec/spec_helper.rb
161
+ - spec/test-image-blue.png
162
+ - spec/test-image.png
199
163
  - spec/testfile1.ods
164
+ - spec/testfile2-images.ods
200
165
  - spec/tools_spec.rb
201
166
  - spec/workbook_spec.rb
202
167
  - spec/worksheet_spec.rb
168
+ - w/test.rb
169
+ - w/time.ods
203
170
  homepage: https://github.com/gorn/rspreadsheet
204
171
  licenses:
205
172
  - GPL
@@ -227,12 +194,18 @@ summary: Manipulating spreadsheets with Ruby (read / create / modify OpenDocumen
227
194
  Spreadsheet).
228
195
  test_files:
229
196
  - spec/cell_spec.rb
197
+ - spec/class_extensions_spec.rb
230
198
  - spec/column_spec.rb
199
+ - spec/image_spec.rb
200
+ - spec/included_image_spec.rb
231
201
  - spec/io_spec.rb
232
202
  - spec/row_spec.rb
233
203
  - spec/rspreadsheet_spec.rb
234
204
  - spec/spec_helper.rb
205
+ - spec/test-image-blue.png
206
+ - spec/test-image.png
235
207
  - spec/testfile1.ods
208
+ - spec/testfile2-images.ods
236
209
  - spec/tools_spec.rb
237
210
  - spec/workbook_spec.rb
238
211
  - spec/worksheet_spec.rb
data/investigate.rb DELETED
@@ -1,19 +0,0 @@
1
- require 'xml'
2
-
3
- ns = XML::Namespace.new(XML::Node.new('xxx'), 'soap', 'http://schemas.xmlsoap.org/soap/envelope/')
4
-
5
-
6
- d = XML::Document.new
7
- nr = XML::Node.new('root', 'text')
8
- d.root = nr
9
- n2 = XML::Node.new('element', 'content')
10
- nr << n2
11
- puts d.to_s
12
-
13
- n2.namespaces.namespace = ns
14
- nr.namespaces.namespace = ns
15
- puts d.to_s
16
-
17
- n2.namespaces.namespace = ns
18
- puts d.to_s
19
-
@@ -1,253 +0,0 @@
1
- module Rspreadsheet
2
-
3
- # @private
4
- class XMLTied
5
- def xml
6
- xmlnode.to_s
7
- end
8
- end
9
-
10
- # @private
11
- # abstrac class. All successort MUST implement: set_index,xml_options,parent,index
12
- class XMLTiedItem < XMLTied
13
- def mode
14
- case
15
- when xmlnode.nil? then :outbound
16
- when repeated>1 then :repeated
17
- else :regular
18
- end
19
- end
20
- def repeated; (Tools.get_ns_attribute_value(xmlnode, 'table', xml_options[:xml_repeated_attribute]) || 1 ).to_i end
21
- def repeated?; mode==:repeated || mode==:outbound end
22
- alias :is_repeated? :repeated?
23
- def xmlnode
24
- parentnode = parent.xmlnode
25
- if parentnode.nil?
26
- nil
27
- else
28
- parent.find_my_subnode_respect_repeated(index, xml_options)
29
- end
30
- end
31
- def detach_if_needed
32
- detach if repeated? # item did not exist individually yet, detach it within its parent and therefore make it individally editable
33
- end
34
- def detach
35
- parent.detach_if_needed if parent.respond_to?(:detach_if_needed)
36
- parent.detach_my_subnode_respect_repeated(index, xml_options)
37
- self
38
- end
39
- def _shift_by(diff)
40
- set_index(index + diff)
41
- end
42
- def range
43
- parent.find_my_subnode_range_respect_repeated(index,xml_options)
44
- end
45
- def invalid_reference?; false end
46
- # destroys the object so it can not be used, this is necessarry to prevent
47
- # accessing cells and rows which has been long time ago deleted and do not represent
48
- # any physical object anymore
49
- def invalidate_myself
50
- raise_destroyed_cell_error = Proc.new {|*params| raise "Calling method of already destroyed Cell."}
51
- (self.methods - Object.methods + [:nil?]).each do |method| # "undefine" all methods
52
- self.singleton_class.send(:define_method, method, raise_destroyed_cell_error)
53
- end
54
- self.singleton_class.send(:define_method, :inspect, -> { "#<%s:0x%x destroyed cell>" % [self.class,object_id] }) # define descriptive inspect
55
- self.singleton_class.send(:define_method, :invalid_reference?, -> { true }) # define invalid_reference? method
56
- # self.instance_variables.each do |variable|
57
- # instance_variable_set(variable,nil)
58
- # end
59
- end
60
- def delete
61
- parent.delete_subitem(index)
62
- invalidate_myself
63
- end
64
-
65
- end
66
-
67
- # abstract class. All importers MUST implement: prepare_subitem (and delete)
68
- # terminology
69
- # item, subitem is object from @itemcache (quite often subclass of XMLTiedItem)
70
- # node, subnode is LibXML::XML::Node object
71
- #
72
- # this class is made to be included, not subclassed - the reason is in delete method which calls super
73
- # @private
74
-
75
- module XMLTiedArray
76
- attr_reader :itemcache
77
-
78
- def find_my_subnode_range_respect_repeated(aindex, options)
79
- index = 0
80
- xmlnode.elements.select{|node| node.name == options[:xml_items_node_name]}.each do |node|
81
- repeated = (node.attributes[options[:xml_repeated_attribute]] || 1).to_i
82
- if index+repeated >= aindex
83
- return (index+1..index+repeated)
84
- else
85
- index = index+repeated
86
- end
87
- end
88
- return (index+1..Float::INFINITY)
89
- end
90
-
91
- # vrátí xmlnode na souřadnici aindex
92
- def find_my_subnode_respect_repeated(aindex, options)
93
- find_subnode_respect_repeated(xmlnode,aindex, options)
94
- end
95
- # vrátí item na souřadnici aindex
96
- def subitem(aindex)
97
- aindex = aindex.to_i
98
- if aindex.to_i<=0
99
- raise 'Item index should be greater then 0' if Rspreadsheet.raise_on_negative_coordinates
100
- nil
101
- else
102
- @itemcache[aindex] ||= prepare_subitem(aindex)
103
- end
104
- end
105
-
106
- def subitems(*params)
107
- case params.length
108
- when 0 then subitems_array
109
- when 1 then subitem(params[0])
110
- else raise Exception.new('Wrong number of arguments.')
111
- end
112
- end
113
-
114
- def subitems_array
115
- (1..self.size).collect do |i|
116
- subitem(i)
117
- end
118
- end
119
-
120
- def size; find_first_unused_index_respect_repeated(subitem_xml_options)-1 end
121
-
122
- def find_subnode_respect_repeated(axmlnode, aindex, options)
123
- result1, result2 = find_subnode_with_range_respect_repeated(axmlnode, aindex, options)
124
- return result1
125
- end
126
-
127
- def find_subnode_with_range_respect_repeated(axmlnode, aindex, options)
128
- index = 0
129
- axmlnode.elements.select{|node| node.name == options[:xml_items_node_name]}.each do |node|
130
- repeated = (node.attributes[options[:xml_repeated_attribute]] || 1).to_i
131
- oldindex = index
132
- index = index+repeated
133
- if index>= aindex
134
- return node, oldindex..index
135
- end
136
- end
137
- return nil, index..Float::INFINITY
138
- end
139
-
140
- def prepare_repeated_subnode(times_repeated,options)
141
- result = LibXML::XML::Node.new(options[:xml_items_node_name],nil, Tools.get_namespace('table'))
142
- Tools.set_ns_attribute(result,'table',options[:xml_repeated_attribute],times_repeated, 1)
143
- result
144
- end
145
-
146
- def clone_before_and_set_repeated_attribute(node,times_repeated,options)
147
- newnode = node.copy(true)
148
- Tools.set_ns_attribute(newnode,'table',options[:xml_repeated_attribute],times_repeated,1)
149
- node.prev = newnode
150
- end
151
-
152
- # detaches subnode with aindex
153
- def detach_my_subnode_respect_repeated(aindex, options)
154
- axmlnode = xmlnode
155
- node,index_range = find_subnode_with_range_respect_repeated(axmlnode, aindex, options)
156
- if index_range.size > 1 # pokud potřebuje vůbec detachovat
157
- if !node.nil? # detach subnode
158
- [index_range.begin+1..aindex-1,aindex..aindex,aindex+1..index_range.end].reject {|range| range.size<1}.each do |range| # create new structure by cloning
159
- clone_before_and_set_repeated_attribute(node,range.size,options)
160
- end
161
- node.remove! # remove the original node
162
- else # add outbound xmlnode
163
- [index_range.begin+1..aindex-1,aindex..aindex].reject {|range| range.size<1}.each do |range|
164
- axmlnode << prepare_repeated_subnode(range.size, options)
165
- end
166
- end
167
- end
168
- return find_subnode_respect_repeated(axmlnode, aindex, options)
169
- end
170
-
171
- def insert_my_subnode_before_respect_repeated(aindex, options)
172
- axmlnode = xmlnode
173
-
174
- node,index_range = find_subnode_with_range_respect_repeated(axmlnode, aindex, options)
175
-
176
- if !node.nil? # found the node, now do the insert
177
- [index_range.begin+1..aindex-1,aindex..index_range.end].reject {|range| range.size<1}.each do |range| # split original node by cloning
178
- clone_before_and_set_repeated_attribute(node,range.size,options)
179
- end
180
- clone_before_and_set_repeated_attribute(node.prev,1,options) # insert new node
181
- node.remove! # remove the original node
182
- else # insert outbound xmlnode
183
- [index+1..aindex-1,aindex..aindex].reject {|range| range.size<1}.each do |range|
184
- axmlnode << XMLTiedArray.prepare_repeated_subnode(range.size, options)
185
- end
186
- end
187
- return find_subnode_respect_repeated(axmlnode, aindex, options)
188
- end
189
-
190
- def delete_my_subnode_respect_repeated(aindex,options)
191
- detach_my_subnode_respect_repeated(aindex,options) #TODO: tohle neni uplne spravne, protoze to zanecha skupinu rozdelenou na dve casti
192
- subitem(aindex).xmlnode.remove!
193
- end
194
-
195
- def find_first_unused_index_respect_repeated(options)
196
- index = 0
197
- return 1 if xmlnode.nil?
198
- xmlnode.elements.select{|node| node.name == options[:xml_items_node_name]}.each do |node|
199
- repeated = (node.attributes[options[:xml_repeated_attribute]] || 1).to_i
200
- index = index+repeated
201
- end
202
- return index+1
203
- end
204
-
205
- def add_empty_subitem_before(aindex)
206
- @itemcache.keys.sort.reverse.select{|i| i>=aindex }.each do |i|
207
- @itemcache[i+1]=@itemcache.delete(i)
208
- @itemcache[i+1]._shift_by(1)
209
- end
210
- insert_my_subnode_before_respect_repeated(aindex,subitem_xml_options) # nyní vlož node do xml
211
- @itemcache[aindex] = subitem(aindex)
212
- end
213
-
214
- # clean up item from xml (handle possible detachments) and itemcache. leave the object invalidation on the object
215
- # this should not be called from nowhere but XMLTiedItem.delete
216
- def delete_subitem(aindex)
217
- options = subitem_xml_options
218
- delete_my_subnode_respect_repeated(aindex,options) # vymaž node z xml
219
- @itemcache.delete(aindex)
220
- @itemcache.keys.sort.select{|i| i>=aindex+1 }.each do |i|
221
- @itemcache[i-1]=@itemcache.delete(i)
222
- @itemcache[i-1]._shift_by(-1)
223
- end
224
- end
225
-
226
- def delete
227
- @itemcache.each do |key,item|
228
- item.delete # delete item - this destroys its subitems, xmlnode and invalidates it
229
- @itemcache.delete(key) # delete the entry from the hash, normally this would mean this ceases to exist, if user does not have reference stored somewhere. Of he does, the object is invalidated anyways
230
- end
231
- super # this for example for Row objects calls XMLTiedItem.delete because Row is subclass of XMLTiedItem
232
- end
233
-
234
- def find_nonempty_subnode_indexes(axmlnode, options)
235
- index = 0
236
- result = []
237
- axmlnode.elements.select{|node| node.name == options[:xml_items_node_name]}.each do |node|
238
- repeated = (node.attributes[options[:xml_repeated_attribute]] || 1).to_i
239
- index = index + repeated
240
- if !(node.content.nil? or node.content.empty? or node.content =='') and (repeated==1)
241
- result << index
242
- end
243
- end
244
- return result
245
- end
246
-
247
- # truncate the item completely, deleting all its subitems
248
- def truncate
249
- subitems.reverse.each{ |subitem| subitem.delete } # reverse je tu jen kvuli performanci, aby to mazal zezadu
250
- end
251
- end
252
-
253
- end