rspreadsheet 0.2.0 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.directory +4 -0
- data/.gitignore +2 -0
- data/.kateproject +4 -0
- data/.kateproject.d/notes.txt +0 -0
- data/DEVEL_BLOG.md +11 -5
- data/GUIDE.md +2 -2
- data/Guardfile +2 -2
- data/README.md +31 -14
- data/lib/class_extensions.rb +0 -11
- data/lib/rspreadsheet/cell.rb +118 -116
- data/lib/rspreadsheet/row.rb +339 -373
- data/lib/rspreadsheet/tools.rb +14 -5
- data/lib/rspreadsheet/version.rb +1 -1
- data/lib/rspreadsheet/worksheet.rb +24 -113
- data/lib/rspreadsheet/xml_tied.rb +234 -0
- data/lib/rspreadsheet.rb +1 -1
- data/reinstall2.sh +7 -0
- data/rspreadsheet.gemspec +6 -7
- data/spec/cell_spec.rb +187 -10
- data/spec/row_spec.rb +63 -7
- data/spec/rspreadsheet_spec.rb +32 -0
- data/spec/testfile1.ods +0 -0
- data/spec/worksheet_spec.rb +6 -4
- metadata +7 -5
- data/lib/rspreadsheet/.row.rb.kate-swp.bak +0 -0
- data/spec/xml_tied_array_spec.rb +0 -9
data/lib/rspreadsheet/row.rb
CHANGED
@@ -1,54 +1,64 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require 'rspreadsheet/cell'
|
2
|
+
require 'rspreadsheet/xml_tied'
|
3
3
|
|
4
4
|
# Currently this is only syntax sugar for cells and contains no functionality
|
5
5
|
|
6
6
|
module Rspreadsheet
|
7
7
|
|
8
|
-
class Row <
|
8
|
+
class Row < XMLTiedItem
|
9
|
+
include XMLTiedArray
|
9
10
|
attr_reader :worksheet, :rowi
|
11
|
+
def xml_repeated_attribute; 'number-rows-repeated' end
|
12
|
+
def xml_items_node_name; 'table-row' end
|
13
|
+
def xml_options; {:xml_items_node_name => xml_items_node_name, :xml_repeated_attribute => xml_repeated_attribute} end
|
14
|
+
def subitem_xml_options; {:xml_items_node_name => 'table-cell', :xml_repeated_attribute => 'number-columns-repeated'} end
|
15
|
+
|
10
16
|
def initialize(aworksheet,arowi)
|
11
17
|
@worksheet = aworksheet
|
12
18
|
@rowi = arowi
|
19
|
+
@itemcache = Hash.new #TODO: move to module XMLTiedArray
|
13
20
|
end
|
14
|
-
def xmlnode;
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
+
def xmlnode; parent.find_my_subnode_respect_repeated(index, xml_options) end
|
22
|
+
|
23
|
+
# XMLTiedItem things and extensions
|
24
|
+
def parent; @worksheet end
|
25
|
+
def index; @rowi end
|
26
|
+
def set_index(value); @rowi=value end
|
27
|
+
|
28
|
+
# XMLTiedArray rozšíření
|
29
|
+
def prepare_subitem(coli); Cell.new(@worksheet,@rowi,coli) end
|
30
|
+
def cells(*params)
|
31
|
+
raise 'Invalid row reference' if invalid_reference?
|
32
|
+
case params.length
|
33
|
+
when 0 then subitems_array
|
34
|
+
when 1 then subitem(params[0])
|
35
|
+
else raise Exception.new('Wrong number of arguments.')
|
21
36
|
end
|
22
37
|
end
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
def detach_if_needed;
|
29
|
-
detach if repeated?
|
30
|
-
end
|
31
|
-
def detach
|
32
|
-
@worksheet.detach_row_in_xml(@rowi)
|
33
|
-
self
|
34
|
-
end
|
35
|
-
def repeated
|
36
|
-
(Tools.get_ns_attribute_value(self.xmlnode, 'table', 'number-rows-repeated') || 1).to_i
|
37
|
-
end
|
38
|
-
def repeated?; mode==:repeated || mode==:outbound end
|
39
|
-
alias :is_repeated? :repeated?
|
38
|
+
# syntactis sugar to cells and its values
|
39
|
+
def [](coli); cells(coli).value end
|
40
|
+
def []=(coli,avalue); cells(coli).value=avalue end
|
41
|
+
|
42
|
+
# další
|
40
43
|
def style_name=(value);
|
41
44
|
detach_if_needed
|
42
45
|
Tools.set_ns_attribute(xmlnode,'table','style-name',value)
|
43
46
|
end
|
44
|
-
def used_range
|
45
|
-
@worksheet.rowrange(@rowi)
|
46
|
-
end
|
47
47
|
def nonemptycells
|
48
|
-
nonemptycellsindexes.collect{ |index|
|
48
|
+
nonemptycellsindexes.collect{ |index| subitem(index) }
|
49
49
|
end
|
50
50
|
def nonemptycellsindexes
|
51
|
-
|
51
|
+
myxmlnode = xmlnode
|
52
|
+
if myxmlnode.nil?
|
53
|
+
[]
|
54
|
+
else
|
55
|
+
@worksheet.find_nonempty_subnode_indexes(myxmlnode, {:xml_items_node_name => 'table-cell', :xml_repeated_attribute => 'number-columns-repeated'})
|
56
|
+
end
|
57
|
+
end
|
58
|
+
alias :used_range :range
|
59
|
+
def shift_by(diff)
|
60
|
+
super
|
61
|
+
@itemcache.each_value{ |cell| cell.set_rowi(@rowi) }
|
52
62
|
end
|
53
63
|
end
|
54
64
|
|
@@ -68,189 +78,175 @@ end
|
|
68
78
|
# --------------------------
|
69
79
|
|
70
80
|
|
71
|
-
# XmlTiedArrayItemGroup is internal representation of repeated items in XmlTiedArray.
|
72
|
-
class XmlTiedArrayItemGroup
|
73
|
-
# extend Forwardable
|
74
|
-
# delegate [:normalize ] => :@row_group
|
75
|
-
|
76
|
-
|
77
|
-
def range; @rowgroup.range end
|
78
|
-
def repeated?; self.range.size>1 end
|
79
|
-
def xmlnode; @rowgroup.xmlnode end
|
81
|
+
# # XmlTiedArrayItemGroup is internal representation of repeated items in XmlTiedArray.
|
82
|
+
# class XmlTiedArrayItemGroup
|
83
|
+
# # extend Forwardable
|
84
|
+
# # delegate [:normalize ] => :@row_group
|
85
|
+
#
|
86
|
+
# def normalize; @rowgroup.normalize end
|
80
87
|
|
81
|
-
|
82
|
-
@rowgroup = RowGroup.new(aparent_array,arange,axmlnode)
|
83
|
-
end
|
84
|
-
def self.new_from_xml
|
85
|
-
end
|
86
|
-
def to_rowgroup
|
87
|
-
@rowgroup
|
88
|
-
end
|
89
|
-
def range=(arange)
|
90
|
-
|
91
|
-
end
|
92
|
-
end
|
88
|
+
# end
|
93
89
|
|
94
90
|
# array which synchronizes with xml structure and reflects. number-xxx-repeated attributes
|
95
91
|
# also caches returned objects for indexes.
|
96
92
|
# options must contain
|
97
93
|
# :xml_items, :xml_repeated_attribute, :object_type
|
98
94
|
|
99
|
-
class XmlTiedArray < Array
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
end
|
95
|
+
# class XmlTiedArray < Array
|
96
|
+
# def initialize(axmlnode, options={}) # TODO get rid of XmlTiedArray
|
97
|
+
# @xmlnode = axmlnode
|
98
|
+
# @options = options
|
99
|
+
#
|
100
|
+
# missing_options = [:xml_repeated_attribute,:xml_items_node_name,:object_type]-@options.keys
|
101
|
+
# raise "Some options missing (#{missing_options.inspect})" unless missing_options.empty?
|
102
|
+
#
|
103
|
+
# unless @xmlnode.nil?
|
104
|
+
# @xmlnode.elements.select{|node| node.name == options[:xml_items_node_name]}.each do |group_source_node|
|
105
|
+
# self << parse_xml_to_group(group_source_node) # it is in @xmlnode so suffices to add object to @rowgroups
|
106
|
+
# end
|
107
|
+
# end
|
108
|
+
# @itemcache=Hash.new()
|
109
|
+
# end
|
110
|
+
# def parse_xml_to_group(size_or_xmlnode) # parses xml to new RowGroup which can be added at the end
|
111
|
+
# # reading params
|
112
|
+
# if size_or_xmlnode.kind_of? LibXML::XML::Node
|
113
|
+
# size = (size_or_xmlnode[@options[:xml_repeated_attribute]] || 1).to_i
|
114
|
+
# node = size_or_xmlnode
|
115
|
+
# elsif size_or_xmlnode.to_i>0
|
116
|
+
# size = size_or_xmlnode.to_i
|
117
|
+
# node = nil
|
118
|
+
# else
|
119
|
+
# return nil
|
120
|
+
# end
|
121
|
+
# index = first_unused_index
|
122
|
+
# # construct result
|
123
|
+
# Rspreadsheet::XmlTiedArrayItemGroup.new(self,index..index+size-1,node)
|
124
|
+
# end
|
125
|
+
# def add_item_group(size_or_xmlnode)
|
126
|
+
# result = parse_xml_to_group(size_or_xmlnode)
|
127
|
+
# self << result
|
128
|
+
# @xmlnode << result.xmlnode
|
129
|
+
# result
|
130
|
+
# end
|
131
|
+
# def first_unused_index
|
132
|
+
# empty? ? 1 : last.range.end+1
|
133
|
+
# end
|
134
|
+
# # prolonges the RowArray to cantain rowi and returns it
|
135
|
+
# def detach_of_bound_item(index)
|
136
|
+
# fill_row_group_size = index-first_unused_index
|
137
|
+
# if fill_row_group_size>0
|
138
|
+
# add_item_group(fill_row_group_size)
|
139
|
+
# end
|
140
|
+
# add_item_group(1)
|
141
|
+
# get_item(index) # aby se odpoved nacacheovala
|
142
|
+
# end
|
143
|
+
# def get_item_group(index)
|
144
|
+
# find{ |item_group| item_group.range.cover?(index) }
|
145
|
+
# end
|
146
|
+
# def detach_item(index); get_item(index) end # TODO předělat do lazy podoby, kdy tohle nebude stejny
|
147
|
+
# def get_item(index)
|
148
|
+
# if index>= first_unused_index
|
149
|
+
# nil
|
150
|
+
# else
|
151
|
+
# @itemcache[index] ||= Rspreadsheet::XmlTiedArrayItem.new(self,index)
|
152
|
+
# end
|
153
|
+
# end
|
154
|
+
# # This detaches item index from the group and perhaps splits the RowGroup
|
155
|
+
# # into two pieces. This makes the row individually editable.
|
156
|
+
# def detach(index)
|
157
|
+
# group_index = get_group_index(index)
|
158
|
+
# item_group = self[group_index]
|
159
|
+
# range = item_group.range
|
160
|
+
# return self if range==(index..index)
|
161
|
+
#
|
162
|
+
# # prepare new components
|
163
|
+
# replaceby = []
|
164
|
+
# replaceby << RowGroup.new(self,range.begin..index-1)
|
165
|
+
# replaceby << (result = SingleRow.new(self,index))
|
166
|
+
# replaceby << RowGroup.new(self,index+1..range.end)
|
167
|
+
#
|
168
|
+
# # put original range somewhere in replaceby and shorten it
|
169
|
+
#
|
170
|
+
# if index>range.begin
|
171
|
+
# replaceby[0] = item_group
|
172
|
+
# item_group.range = range.begin..index-1
|
173
|
+
# else
|
174
|
+
# replaceby[2] = item_group
|
175
|
+
# item_group.range = index+1..range.end
|
176
|
+
# end
|
177
|
+
#
|
178
|
+
# # normalize and delete empty parts
|
179
|
+
# replaceby = replaceby.map(&:normalize).compact
|
180
|
+
#
|
181
|
+
# # do the replacement in xml
|
182
|
+
# marker = LibXML::XML::Node.new('temporarymarker')
|
183
|
+
# item_group.xmlnode.next = marker
|
184
|
+
# item_group.xmlnode.remove!
|
185
|
+
# replaceby.each{ |rg|
|
186
|
+
# marker.prev = rg.xmlnode
|
187
|
+
# }
|
188
|
+
# marker.remove!
|
189
|
+
#
|
190
|
+
# # do the replacement in array
|
191
|
+
# self[group_index..group_index]=replaceby
|
192
|
+
# result
|
193
|
+
# end
|
194
|
+
# private
|
195
|
+
# def get_group_index(index)
|
196
|
+
# self.find_index{ |rowgroup| rowgroup.range.cover?(index) }
|
197
|
+
# end
|
198
|
+
# end
|
203
199
|
|
204
|
-
class XmlTiedArrayItem
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
end
|
200
|
+
# class XmlTiedArrayItem
|
201
|
+
# attr_reader :index
|
202
|
+
# def initialize(aarray,aindex)
|
203
|
+
# @array = aarray
|
204
|
+
# @index = aindex
|
205
|
+
# if self.virtual?
|
206
|
+
# @object = nil
|
207
|
+
# else
|
208
|
+
# @object = @array.options[:object_type].new(group.xmlnode)
|
209
|
+
# end
|
210
|
+
# end
|
211
|
+
# def group; @array.get_item_group(index) end
|
212
|
+
# def repeated?; group.repeated? end
|
213
|
+
# def virtual?; ! self.repeated? end
|
214
|
+
# def array
|
215
|
+
# raise 'Group empty' if @group.nil?
|
216
|
+
# @array
|
217
|
+
# end
|
218
|
+
# end
|
223
219
|
|
224
|
-
class RowArray < XmlTiedArray
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
end
|
220
|
+
# class RowArray < XmlTiedArray
|
221
|
+
# attr_reader :row_array_cache
|
222
|
+
# def initialize(aworksheet,aworksheet_node)
|
223
|
+
# @worksheet = aworksheet
|
224
|
+
# @row_array_cache = Hash.new()
|
225
|
+
# super(aworksheet_node, :xml_items_node_name => 'table-row', :xml_repeated_attribute => xml_repeated_attribute, :object_type=>Row)
|
226
|
+
# end
|
227
|
+
# def get_row(rowi)
|
228
|
+
# if @row_array_cache.has_key?(rowi)
|
229
|
+
# return @row_array_cache[rowi]
|
230
|
+
# end
|
231
|
+
# item = self.get_item(rowi)
|
232
|
+
# @row_array_cache[rowi] = if item.nil?
|
233
|
+
# if rowi>0 then Rspreadsheet::UninitializedEmptyRow.new(self,rowi) else nil end
|
234
|
+
# else
|
235
|
+
# if item.repeated?
|
236
|
+
# Rspreadsheet::MemberOfRowGroup.new(item.index, item.group.to_rowgroup)
|
237
|
+
# else
|
238
|
+
# Rspreadsheet::SingleRow.new_from_rowgroup(item.group.to_rowgroup)
|
239
|
+
# end
|
240
|
+
# end
|
241
|
+
# end
|
242
|
+
# # aliases
|
243
|
+
# def first_unused_row_index; first_unused_index end
|
244
|
+
# def worksheet; @worksheet end
|
245
|
+
# def detach_of_bound_row_group(index)
|
246
|
+
# super(index)
|
247
|
+
# return get_row(index)
|
248
|
+
# end
|
249
|
+
# end
|
254
250
|
|
255
251
|
# class Row
|
256
252
|
# def initialize
|
@@ -272,177 +268,147 @@ end
|
|
272
268
|
# end
|
273
269
|
# end
|
274
270
|
|
275
|
-
class RowWithXMLNode < Row
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
end
|
318
|
-
|
319
|
-
class RowGroup < RowWithXMLNode
|
320
|
-
@readonly = :yes_always
|
321
|
-
attr_reader :range
|
322
|
-
attr_accessor :parent_array, :xmlnode
|
323
|
-
def initialize(aparent_array,arange,axmlnode=nil)
|
324
|
-
super()
|
325
|
-
@parent_array = aparent_array
|
326
|
-
@range = arange
|
327
|
-
if axmlnode.nil?
|
328
|
-
axmlnode = Row.empty_row_node
|
329
|
-
Tools.set_ns_attribute(axmlnode,'table','number-rows-repeated',range.size) if range.size>1
|
330
|
-
end
|
331
|
-
@xmlnode = axmlnode
|
332
|
-
end
|
333
|
-
# returns SingleRow if size of range is 1 and nil if it is 0 or less
|
334
|
-
def normalize
|
335
|
-
case range.size
|
336
|
-
when 2..Float::INFINITY then self
|
337
|
-
when 1 then SingleRow.new_from_rowgroup(self)
|
338
|
-
else nil
|
339
|
-
end
|
340
|
-
end
|
341
|
-
def repeated; range.size end
|
342
|
-
def repeated?; range.size>1 end
|
343
|
-
def range=(arange)
|
344
|
-
@range=arange
|
345
|
-
Tools.set_ns_attribute(@xmlnode,'table','number-rows-repeated',range.size, 1)
|
346
|
-
end
|
347
|
-
end
|
271
|
+
# class RowWithXMLNode < Row
|
272
|
+
# attr_accessor :xmlnode
|
273
|
+
# def style_name=(value); Tools.set_ns_attribute(@xmlnode,'table','style-name',value) end
|
274
|
+
# def get_cell(coli)
|
275
|
+
# Cell.new(self,coli,cellnodes(coli))
|
276
|
+
# end
|
277
|
+
# def nonemptycells
|
278
|
+
# nonemptycellsindexes.collect{ |index| cells(index) }
|
279
|
+
# end
|
280
|
+
# def nonemptycellsindexes
|
281
|
+
# used_col_range.to_a.select do |coli|
|
282
|
+
# cellnode = cellnodes(coli)
|
283
|
+
# !(cellnode.content.nil? or cellnode.content.empty? or cellnode.content =='') or
|
284
|
+
# !cellnode.attributes.to_a.reject{ |attr| attr.name == 'number-columns-repeated'}.empty?
|
285
|
+
# end
|
286
|
+
# end
|
287
|
+
# def cellnodes(coli)
|
288
|
+
# cellnode = nil
|
289
|
+
# while true
|
290
|
+
# curr_coli=1
|
291
|
+
# cellnode = @xmlnode.elements.select{|n| n.name=='table-cell'}.find do |el|
|
292
|
+
# curr_coli += (Tools.get_ns_attribute_value(el, 'table', 'number-columns-repeated') || 1).to_i
|
293
|
+
# curr_coli > coli
|
294
|
+
# end
|
295
|
+
# unless cellnode.nil?
|
296
|
+
# return cellnode
|
297
|
+
# else
|
298
|
+
# add_cell
|
299
|
+
# end
|
300
|
+
# end
|
301
|
+
# end
|
302
|
+
# def add_cell(repeated=1)
|
303
|
+
# cell = Cell.new(self,first_unused_column_index)
|
304
|
+
# Tools.set_ns_attribute(cell.xmlnode,'table','number-columns-repeated',repeated) if repeated>1
|
305
|
+
# @xmlnode << cell.xmlnode
|
306
|
+
# cell
|
307
|
+
# end
|
308
|
+
# def first_unused_column_index
|
309
|
+
# 1 + @xmlnode.elements.select{|n| n.name=='table-cell'}.reduce(0) do |sum, el|
|
310
|
+
# sum + (Tools.get_ns_attribute_value(el, 'table', 'number-columns-repeated') || 1).to_i
|
311
|
+
# end
|
312
|
+
# end
|
313
|
+
# end
|
348
314
|
|
349
|
-
class
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
315
|
+
# class RowGroup < RowWithXMLNode
|
316
|
+
# @readonly = :yes_always
|
317
|
+
# attr_reader :range
|
318
|
+
# attr_accessor :parent_array, :xmlnode
|
319
|
+
# def initialize(aparent_array,arange,axmlnode=nil)
|
320
|
+
# super()
|
321
|
+
# @parent_array = aparent_array
|
322
|
+
# @range = arange
|
323
|
+
# if axmlnode.nil?
|
324
|
+
# axmlnode = Row.empty_row_node
|
325
|
+
# Tools.set_ns_attribute(axmlnode,'table','number-rows-repeated',range.size) if range.size>1
|
326
|
+
# end
|
327
|
+
# @xmlnode = axmlnode
|
328
|
+
# end
|
329
|
+
# # returns SingleRow if size of range is 1 and nil if it is 0 or less
|
330
|
+
# def normalize
|
331
|
+
# case range.size
|
332
|
+
# when 2..Float::INFINITY then self
|
333
|
+
# when 1 then SingleRow.new_from_rowgroup(self)
|
334
|
+
# else nil
|
335
|
+
# end
|
336
|
+
# end
|
337
|
+
# def repeated; range.size end
|
338
|
+
# def repeated?; range.size>1 end
|
339
|
+
# def range=(arange)
|
340
|
+
# @range=arange
|
341
|
+
# Tools.set_ns_attribute(@xmlnode,'table','number-rows-repeated',range.size, 1)
|
342
|
+
# end
|
343
|
+
# end
|
375
344
|
|
376
|
-
class
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
345
|
+
# class SingleRow < RowWithXMLNode
|
346
|
+
# @readonly = :no
|
347
|
+
# attr_accessor :xmlnode
|
348
|
+
# # index Integer
|
349
|
+
# def initialize(aparent_array,aindex,axmlnode=nil)
|
350
|
+
# super()
|
351
|
+
# @parent_array = aparent_array
|
352
|
+
# @index = aindex
|
353
|
+
# if axmlnode.nil?
|
354
|
+
# axmlnode = Row.empty_row_node
|
355
|
+
# end
|
356
|
+
# @xmlnode = axmlnode
|
357
|
+
# end
|
358
|
+
# def self.new_from_rowgroup(rg)
|
359
|
+
# anode = rg.xmlnode
|
360
|
+
# Tools.remove_ns_attribute(anode,'table','number-rows-repeated')
|
361
|
+
# SingleRow.new(rg.parent_array,rg.range.begin,anode)
|
362
|
+
# end
|
363
|
+
# def normalize; self end
|
364
|
+
# def repeated?; false end
|
365
|
+
# def repeated; 1 end
|
366
|
+
# def range; (@index..@index) end
|
367
|
+
# def detach; self end
|
368
|
+
# def row; @index end
|
369
|
+
# def still_out_of_used_range?; false end
|
370
|
+
# end
|
386
371
|
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
372
|
+
# class LazyDetachableRow < Row
|
373
|
+
# @readonly = :yes_but_detachable
|
374
|
+
# def initialize(rowi)
|
375
|
+
# super()
|
376
|
+
# @index = rowi.to_i
|
377
|
+
# end
|
378
|
+
# def add_cell; detach.add_cell end
|
379
|
+
# def style_name=(value); detach.style_name=value end
|
380
|
+
# def row; @index end
|
381
|
+
# end
|
393
382
|
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
end
|
383
|
+
# ## there are not data in this object, they are taken from RowGroup, but this is only readonly
|
384
|
+
# class MemberOfRowGroup < LazyDetachableRow
|
385
|
+
# @readonly = :yes_but_detachable
|
386
|
+
# extend Forwardable
|
387
|
+
# delegate [:repeated?, :repeated, :xmlnode, :parent_array] => :@row_group
|
388
|
+
# attr_accessor :row_group # for dubugging
|
389
|
+
#
|
390
|
+
# # @index Integer
|
391
|
+
# # @row_group RepeatedRow
|
392
|
+
# def initialize(arowi,arow_group)
|
393
|
+
# super(arowi)
|
394
|
+
# @row_group = arow_group
|
395
|
+
# raise 'Wrong parameter given - class is '+@row_group.class.to_a unless @row_group.is_a? RowGroup
|
396
|
+
# end
|
397
|
+
# def detach # detaches MemberOfRowGroup from its RowGroup perhaps splitting RowGroup
|
398
|
+
# @row_group.parent_array.detach(@index)
|
399
|
+
# end
|
400
|
+
# def get_cell(coli)
|
401
|
+
# c = Cell.new(self,coli,@row_group.cellnodes(coli))
|
402
|
+
# c.mode = :repeated
|
403
|
+
# c
|
404
|
+
# end
|
405
|
+
# def first_unused_column_index
|
406
|
+
# @row_group.first_unused_column_index
|
407
|
+
# end
|
408
|
+
# def nonemptycells
|
409
|
+
# @row_group.nonemptycellsindexes.collect{ |coli| cells(coli) }
|
410
|
+
# end
|
411
|
+
# end
|
416
412
|
|
417
|
-
## 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
|
418
|
-
class UninitializedEmptyRow < LazyDetachableRow
|
419
|
-
@readonly = :yes_but_detachable
|
420
|
-
attr_reader :parent_array # debug only
|
421
|
-
def initialize(aparent_array,arowi)
|
422
|
-
super(arowi)
|
423
|
-
@parent_array = aparent_array
|
424
|
-
end
|
425
|
-
def get_cell(coli)
|
426
|
-
if still_out_of_used_range?
|
427
|
-
Cell.new(self,coli,nil)
|
428
|
-
else
|
429
|
-
@parent_array.get_row(@index).cells(coli)
|
430
|
-
end
|
431
|
-
end
|
432
|
-
def normalize
|
433
|
-
if still_out_of_used_range?
|
434
|
-
self
|
435
|
-
else
|
436
|
-
@parent_array.get_row(@index)
|
437
|
-
end
|
438
|
-
end
|
439
|
-
def detach; @parent_array.detach_item(@index) end
|
440
|
-
def detach_cell(col)
|
441
|
-
self.detach.detach_cell(col)
|
442
|
-
end
|
443
|
-
def still_out_of_used_range?; @index >= @parent_array.first_unused_row_index end
|
444
|
-
def xmlnode; Row.empty_row_node end
|
445
|
-
def first_unused_column_index; 1 end
|
446
|
-
end
|
447
413
|
|
448
414
|
end
|