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/tools.rb
CHANGED
@@ -14,9 +14,18 @@ module Tools
|
|
14
14
|
else
|
15
15
|
raise 'Wrong number of arguments'
|
16
16
|
end
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
|
18
|
+
## first possibility how to implement it
|
19
|
+
# colname=colname.rjust(3,'@')
|
20
|
+
# col = (colname[-1].ord-64)+(colname[-2].ord-64)*26+(colname[-3].ord-64)*26*26
|
21
|
+
|
22
|
+
## second possibility how to implement it
|
23
|
+
# col=(colname.to_i(36)-('A'*colname.size).to_i(36)).to_s(36).to_i(26)+('1'*colname.size).to_i(26)
|
24
|
+
|
25
|
+
## third possibility how to implement it (second one little shortened)
|
26
|
+
s=colname.size
|
27
|
+
col=(colname.to_i(36)-(36**s-1).div(3.5)).to_s(36).to_i(26)+(26**s-1)/25
|
28
|
+
|
20
29
|
row = rowname.to_i
|
21
30
|
return [row,col]
|
22
31
|
end
|
@@ -115,8 +124,8 @@ module Tools
|
|
115
124
|
node.attributes.get_attribute_ns(Tools.get_namespace(ns_prefix).href,key)
|
116
125
|
attr.remove! unless attr.nil?
|
117
126
|
end
|
118
|
-
def self.create_ns_node(nodename,
|
119
|
-
LibXML::XML::Node.new(nodename,
|
127
|
+
def self.create_ns_node(ns_prefix,nodename,value=nil)
|
128
|
+
LibXML::XML::Node.new(nodename,value, Tools.get_namespace(ns_prefix))
|
120
129
|
end
|
121
130
|
end
|
122
131
|
|
data/lib/rspreadsheet/version.rb
CHANGED
@@ -5,145 +5,53 @@ require 'rspreadsheet/tools'
|
|
5
5
|
module Rspreadsheet
|
6
6
|
|
7
7
|
class Worksheet
|
8
|
+
include XMLTiedArray
|
8
9
|
attr_accessor :name, :xmlnode
|
9
|
-
|
10
|
-
# def_delegators :nonemptycells
|
10
|
+
def subitem_xml_options; {:xml_items_node_name => 'table-row', :xml_repeated_attribute => 'number-rows-repeated'} end
|
11
11
|
|
12
12
|
def initialize(xmlnode_or_sheet_name)
|
13
|
-
@
|
13
|
+
@itemcache = Hash.new #TODO: move to module XMLTiedArray
|
14
14
|
# set up the @xmlnode according to parameter
|
15
15
|
case xmlnode_or_sheet_name
|
16
16
|
when LibXML::XML::Node
|
17
17
|
@xmlnode = xmlnode_or_sheet_name
|
18
18
|
when String
|
19
|
-
@xmlnode =
|
20
|
-
|
21
|
-
@xmlnode .namespaces.namespace = ns
|
22
|
-
@xmlnode['table:name'] = xmlnode_or_sheet_name
|
19
|
+
@xmlnode = Tools.create_ns_node('table','table')
|
20
|
+
Tools.set_ns_attribute(@xmlnode,'table','name', xmlnode_or_sheet_name)
|
23
21
|
else raise 'Provide name or xml node to create a Worksheet object'
|
24
22
|
end
|
25
23
|
end
|
26
24
|
|
27
25
|
def rowxmlnode(rowi)
|
28
|
-
|
26
|
+
find_my_subnode_respect_repeated(rowi, {:xml_items_node_name => 'table-row', :xml_repeated_attribute => 'number-rows-repeated'})
|
29
27
|
end
|
30
|
-
|
31
|
-
def
|
32
|
-
|
33
|
-
end
|
34
|
-
|
35
|
-
def row_nonempty_cells_col_indexes(rowi)
|
36
|
-
arowxmlnode = rowxmlnode(rowi)
|
37
|
-
if arowxmlnode.nil?
|
38
|
-
[]
|
39
|
-
else
|
40
|
-
find_nonempty_subnode_indexes(arowxmlnode, {:xml_items_node_name => 'table-cell', :xml_repeated_attribute => 'number-columns-repeated'})
|
41
|
-
end
|
28
|
+
|
29
|
+
def first_unused_row_index
|
30
|
+
find_first_unused_index_respect_repeated({:xml_items_node_name => 'table-row', :xml_repeated_attribute => 'number-rows-repeated'})
|
42
31
|
end
|
43
32
|
|
44
|
-
def
|
45
|
-
|
46
|
-
if arowxmlnode.nil?
|
47
|
-
nil
|
48
|
-
else
|
49
|
-
find_subnode_respect_repeated(arowxmlnode, coli, {:xml_items_node_name => 'table-cell', :xml_repeated_attribute => 'number-columns-repeated'})
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
def cellrange(coli)
|
54
|
-
find_subnode_range_respect_repeated(@xmlnode, rowi, {:xml_items_node_name => 'table-row', :xml_repeated_attribute => 'number-rows-repeated'})
|
33
|
+
def insert_row_above(arowi)
|
34
|
+
insert_subitem_before(arowi)
|
55
35
|
end
|
56
36
|
|
57
|
-
def
|
58
|
-
|
37
|
+
def insert_cell_before(arowi,acoli)
|
38
|
+
detach_row_in_xml(arowi)
|
39
|
+
rows(arowi).insert_subitem_before(acoli)
|
59
40
|
end
|
60
41
|
|
61
42
|
def detach_row_in_xml(rowi)
|
62
|
-
return
|
63
|
-
end
|
64
|
-
def detach_cell_in_xml(rowi,coli)
|
65
|
-
rownode = detach_row_in_xml(rowi)
|
66
|
-
return detach_subnode_respect_repeated(rownode, coli, {:xml_items_node_name => 'table-cell', :xml_repeated_attribute => 'number-columns-repeated'})
|
43
|
+
return detach_my_subnode_respect_repeated(rowi, {:xml_items_node_name => 'table-row', :xml_repeated_attribute => 'number-rows-repeated'})
|
67
44
|
end
|
68
45
|
|
69
|
-
def
|
70
|
-
|
71
|
-
axmlnode.elements.select{|node| node.name == options[:xml_items_node_name]}.each do |node|
|
72
|
-
repeated = (node.attributes[options[:xml_repeated_attribute]] || 1).to_i
|
73
|
-
oldindex = index
|
74
|
-
index = index+repeated
|
75
|
-
if index>= aindex # found the node, now do the detachement
|
76
|
-
ranges = [oldindex+1..aindex-1,aindex..aindex,aindex+1..index].reject {|range| range.size<1}
|
77
|
-
ranges.each do |range|
|
78
|
-
newnode = node.copy(true)
|
79
|
-
Tools.set_ns_attribute(newnode,'table',options[:xml_repeated_attribute],range.size,1)
|
80
|
-
node.prev = newnode
|
81
|
-
end
|
82
|
-
node.remove!
|
83
|
-
return find_subnode_respect_repeated(axmlnode, aindex, options)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
# add outbound xmlnode
|
87
|
-
[index+1..aindex-1,aindex..aindex].reject {|range| range.size<1}.each do |range|
|
88
|
-
node = LibXML::XML::Node.new(options[:xml_items_node_name],nil, Tools.get_namespace('table'))
|
89
|
-
Tools.set_ns_attribute(node,'table',options[:xml_repeated_attribute],range.size, 1)
|
90
|
-
axmlnode << node
|
91
|
-
end
|
92
|
-
find_subnode_respect_repeated(axmlnode, aindex, options)
|
93
|
-
end
|
94
|
-
|
95
|
-
def find_subnode_respect_repeated(axmlnode, aindex, options)
|
96
|
-
index = 0
|
97
|
-
axmlnode.elements.select{|node| node.name == options[:xml_items_node_name]}.each do |node|
|
98
|
-
repeated = (node.attributes[options[:xml_repeated_attribute]] || 1).to_i
|
99
|
-
index = index+repeated
|
100
|
-
return node if index>= aindex
|
101
|
-
end
|
102
|
-
return nil
|
103
|
-
end
|
104
|
-
def find_subnode_range_respect_repeated(axmlnode, aindex, options)
|
105
|
-
index = 0
|
106
|
-
axmlnode.elements.select{|node| node.name == options[:xml_items_node_name]}.each do |node|
|
107
|
-
repeated = (node.attributes[options[:xml_repeated_attribute]] || 1).to_i
|
108
|
-
if index+repeated >= aindex
|
109
|
-
return (index+1..index+repeated)
|
110
|
-
else
|
111
|
-
index = index+repeated
|
112
|
-
end
|
113
|
-
end
|
114
|
-
return (index+1..Float::INFINITY)
|
46
|
+
def nonemptycells
|
47
|
+
used_rows_range.collect{ |rowi| rows(rowi).nonemptycells }.flatten
|
115
48
|
end
|
116
49
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
repeated = (node.attributes[options[:xml_repeated_attribute]] || 1).to_i
|
122
|
-
index = index + repeated
|
123
|
-
if !(node.content.nil? or node.content.empty? or node.content =='') and (repeated==1)
|
124
|
-
result << index
|
125
|
-
end
|
126
|
-
end
|
127
|
-
return result
|
128
|
-
end
|
129
|
-
def find_first_unused_index_respect_repeated(axmlnode, options)
|
130
|
-
index = 0
|
131
|
-
axmlnode.elements.select{|node| node.name == options[:xml_items_node_name]}.each do |node|
|
132
|
-
repeated = (node.attributes[options[:xml_repeated_attribute]] || 1).to_i
|
133
|
-
index = index+repeated
|
134
|
-
end
|
135
|
-
return index+1
|
136
|
-
end
|
50
|
+
# rozšíření XMLTiedArray
|
51
|
+
def rows(rowi); subitem(rowi) end
|
52
|
+
def prepare_subitem(rowi); Row.new(self,rowi) end
|
53
|
+
def rowcache; @itemcache end
|
137
54
|
|
138
|
-
def cells(r,c)
|
139
|
-
rows(r).andand.cells(c)
|
140
|
-
end
|
141
|
-
def nonemptycells
|
142
|
-
used_rows_range.collect{ |rowi| rows(rowi) }.collect { |row| row.nonemptycells }.flatten
|
143
|
-
end
|
144
|
-
def rows(rowi)
|
145
|
-
@rowcache[rowi] ||= Row.new(self,rowi) unless rowi<=0
|
146
|
-
end
|
147
55
|
## syntactic sugar follows
|
148
56
|
def [](r,c)
|
149
57
|
cells(r,c).andand.value
|
@@ -151,6 +59,9 @@ class Worksheet
|
|
151
59
|
def []=(r,c,avalue)
|
152
60
|
cells(r,c).andand.value=avalue
|
153
61
|
end
|
62
|
+
def cells(r,c)
|
63
|
+
rows(r).andand.cells(c)
|
64
|
+
end
|
154
65
|
# allows syntax like sheet.F15
|
155
66
|
def method_missing method_name, *args, &block
|
156
67
|
if method_name.to_s.match(/^([A-Z]{1,3})(\d{1,8})(=?)$/)
|
@@ -0,0 +1,234 @@
|
|
1
|
+
module Rspreadsheet
|
2
|
+
|
3
|
+
class XMLTied
|
4
|
+
def xml
|
5
|
+
xmlnode.to_s
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
# abstrac class. All successort MUST implement: set_index,xml_options,parent,index
|
10
|
+
class XMLTiedItem < XMLTied
|
11
|
+
def mode
|
12
|
+
case
|
13
|
+
when xmlnode.nil? then :outbound
|
14
|
+
when repeated>1 then :repeated
|
15
|
+
else :regular
|
16
|
+
end
|
17
|
+
end
|
18
|
+
def repeated; (Tools.get_ns_attribute_value(xmlnode, 'table', xml_repeated_attribute) || 1 ).to_i end
|
19
|
+
def repeated?; mode==:repeated || mode==:outbound end
|
20
|
+
alias :is_repeated? :repeated?
|
21
|
+
def xmlnode
|
22
|
+
parentnode = parent.xmlnode
|
23
|
+
if parentnode.nil?
|
24
|
+
nil
|
25
|
+
else
|
26
|
+
parent.find_my_subnode_respect_repeated(index, xml_options)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
def detach_if_needed
|
30
|
+
detach if repeated? # item did not exist individually yet, detach it within its parent and therefore make it individally editable
|
31
|
+
end
|
32
|
+
def detach
|
33
|
+
parent.detach_if_needed if parent.respond_to?(:detach_if_needed)
|
34
|
+
parent.detach_my_subnode_respect_repeated(index, xml_options)
|
35
|
+
self
|
36
|
+
end
|
37
|
+
def shift_by(diff)
|
38
|
+
set_index(index + diff)
|
39
|
+
end
|
40
|
+
def range
|
41
|
+
parent.find_my_subnode_range_respect_repeated(index,xml_options)
|
42
|
+
end
|
43
|
+
def invalid_reference?; false end
|
44
|
+
# destroys the object so it can not be used, this is necessarry to prevent
|
45
|
+
# accessing cells and rows which has been long time ago deleted and do not represent
|
46
|
+
# any physical object anymore
|
47
|
+
def invalidate_myself
|
48
|
+
raise_destroyed_cell_error = Proc.new {|*params| raise "Calling method of already destroyed Cell."}
|
49
|
+
(self.methods - Object.methods + [:nil?]).each do |method| # "undefine" all methods
|
50
|
+
self.singleton_class.send(:define_method, method, raise_destroyed_cell_error)
|
51
|
+
end
|
52
|
+
self.singleton_class.send(:define_method, :inspect, -> { "#<%s:0x%x destroyed cell>" % [self.class,object_id] }) # define descriptive inspect
|
53
|
+
self.singleton_class.send(:define_method, :invalid_reference?, -> { true }) # define invalid_reference? method
|
54
|
+
# self.instance_variables.each do |variable|
|
55
|
+
# instance_variable_set(variable,nil)
|
56
|
+
# end
|
57
|
+
end
|
58
|
+
def delete
|
59
|
+
parent.delete_subitem(index)
|
60
|
+
invalidate_myself
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# abstrac class. All successort MUST implement: prepare_subitem
|
65
|
+
# terminology
|
66
|
+
# item, subitem is object from @itemcache (quite often subclass of XMLTiedItem)
|
67
|
+
# node, subnode is LibXML::XML::Node object
|
68
|
+
|
69
|
+
module XMLTiedArray
|
70
|
+
attr_reader :itemcache
|
71
|
+
|
72
|
+
def find_my_subnode_range_respect_repeated(aindex, options)
|
73
|
+
index = 0
|
74
|
+
xmlnode.elements.select{|node| node.name == options[:xml_items_node_name]}.each do |node|
|
75
|
+
repeated = (node.attributes[options[:xml_repeated_attribute]] || 1).to_i
|
76
|
+
if index+repeated >= aindex
|
77
|
+
return (index+1..index+repeated)
|
78
|
+
else
|
79
|
+
index = index+repeated
|
80
|
+
end
|
81
|
+
end
|
82
|
+
return (index+1..Float::INFINITY)
|
83
|
+
end
|
84
|
+
|
85
|
+
# vrátí xmlnode na souřadnici aindex
|
86
|
+
def find_my_subnode_respect_repeated(aindex, options)
|
87
|
+
find_subnode_respect_repeated(xmlnode,aindex, options)
|
88
|
+
end
|
89
|
+
# vrátí item na souřadnici aindex
|
90
|
+
def subitem(aindex)
|
91
|
+
aindex = aindex.to_i
|
92
|
+
if aindex.to_i<=0
|
93
|
+
nil
|
94
|
+
else
|
95
|
+
@itemcache[aindex] ||= prepare_subitem(aindex)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def subitems_array
|
100
|
+
(1..(find_first_unused_index_respect_repeated(subitem_xml_options)-1)).collect do |i|
|
101
|
+
subitem(i)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def find_subnode_respect_repeated(axmlnode, aindex, options)
|
106
|
+
result1, result2 = find_subnode_with_range_respect_repeated(axmlnode, aindex, options)
|
107
|
+
return result1
|
108
|
+
end
|
109
|
+
|
110
|
+
def find_subnode_with_range_respect_repeated(axmlnode, aindex, options)
|
111
|
+
index = 0
|
112
|
+
axmlnode.elements.select{|node| node.name == options[:xml_items_node_name]}.each do |node|
|
113
|
+
repeated = (node.attributes[options[:xml_repeated_attribute]] || 1).to_i
|
114
|
+
oldindex = index
|
115
|
+
index = index+repeated
|
116
|
+
if index>= aindex
|
117
|
+
return node, oldindex..index
|
118
|
+
end
|
119
|
+
end
|
120
|
+
return nil, index..Float::INFINITY
|
121
|
+
end
|
122
|
+
|
123
|
+
def prepare_repeated_subnode(times_repeated,options)
|
124
|
+
result = LibXML::XML::Node.new(options[:xml_items_node_name],nil, Tools.get_namespace('table'))
|
125
|
+
Tools.set_ns_attribute(result,'table',options[:xml_repeated_attribute],times_repeated, 1)
|
126
|
+
result
|
127
|
+
end
|
128
|
+
|
129
|
+
def clone_before_and_set_repeated_attribute(node,times_repeated,options)
|
130
|
+
newnode = node.copy(true)
|
131
|
+
Tools.set_ns_attribute(newnode,'table',options[:xml_repeated_attribute],times_repeated,1)
|
132
|
+
node.prev = newnode
|
133
|
+
end
|
134
|
+
|
135
|
+
# detaches subnode with aindex
|
136
|
+
def detach_my_subnode_respect_repeated(aindex, options)
|
137
|
+
axmlnode = xmlnode
|
138
|
+
node,index_range = find_subnode_with_range_respect_repeated(axmlnode, aindex, options)
|
139
|
+
if index_range.size > 1 # pokud potřebuje vůbec detachovat
|
140
|
+
if !node.nil? # detach subnode
|
141
|
+
[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
|
142
|
+
clone_before_and_set_repeated_attribute(node,range.size,options)
|
143
|
+
end
|
144
|
+
node.remove! # remove the original node
|
145
|
+
else # add outbound xmlnode
|
146
|
+
[index_range.begin+1..aindex-1,aindex..aindex].reject {|range| range.size<1}.each do |range|
|
147
|
+
axmlnode << prepare_repeated_subnode(range.size, options)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
return find_subnode_respect_repeated(axmlnode, aindex, options)
|
152
|
+
end
|
153
|
+
|
154
|
+
def insert_my_subnode_before_respect_repeated(aindex, options)
|
155
|
+
axmlnode = xmlnode
|
156
|
+
|
157
|
+
node,index_range = find_subnode_with_range_respect_repeated(axmlnode, aindex, options)
|
158
|
+
|
159
|
+
if !node.nil? # found the node, now do the insert
|
160
|
+
[index_range.begin+1..aindex-1,aindex..index_range.end].reject {|range| range.size<1}.each do |range| # split original node by cloning
|
161
|
+
clone_before_and_set_repeated_attribute(node,range.size,options)
|
162
|
+
end
|
163
|
+
clone_before_and_set_repeated_attribute(node.prev,1,options) # insert new node
|
164
|
+
node.remove! # remove the original node
|
165
|
+
else # insert outbound xmlnode
|
166
|
+
[index+1..aindex-1,aindex..aindex].reject {|range| range.size<1}.each do |range|
|
167
|
+
axmlnode << XMLTiedArray.prepare_repeated_subnode(range.size, options)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
return find_subnode_respect_repeated(axmlnode, aindex, options)
|
171
|
+
end
|
172
|
+
|
173
|
+
def delete_my_subnode_respect_repeated(aindex,options)
|
174
|
+
detach_my_subnode_respect_repeated(aindex,options) #TODO: tohle neni uplne spravne, protoze to zanecha skupinu rozdelenou na dve casti
|
175
|
+
subitem(aindex).xmlnode.remove!
|
176
|
+
end
|
177
|
+
|
178
|
+
def find_first_unused_index_respect_repeated(options)
|
179
|
+
index = 0
|
180
|
+
xmlnode.elements.select{|node| node.name == options[:xml_items_node_name]}.each do |node|
|
181
|
+
repeated = (node.attributes[options[:xml_repeated_attribute]] || 1).to_i
|
182
|
+
index = index+repeated
|
183
|
+
end
|
184
|
+
return index+1
|
185
|
+
end
|
186
|
+
|
187
|
+
def insert_subitem_before(aindex)
|
188
|
+
insert_subitem_before_with_options(aindex,subitem_xml_options)
|
189
|
+
end
|
190
|
+
def insert_subitem_before_with_options(aindex,options)
|
191
|
+
@itemcache.keys.sort.reverse.select{|i| i>=aindex }.each do |i|
|
192
|
+
@itemcache[i+1]=@itemcache.delete(i)
|
193
|
+
@itemcache[i+1].shift_by(1)
|
194
|
+
end
|
195
|
+
insert_my_subnode_before_respect_repeated(aindex,options) # nyní vlož node do xml
|
196
|
+
@itemcache[aindex] = subitem(aindex)
|
197
|
+
end
|
198
|
+
|
199
|
+
# clean up item from xml (handle possible detachments) and itemcache. leave the object invalidation on the object
|
200
|
+
# this should not be called from nowhere but XMLTiedItem.delete
|
201
|
+
def delete_subitem(aindex)
|
202
|
+
options = subitem_xml_options
|
203
|
+
delete_my_subnode_respect_repeated(aindex,options) # vymaž node z xml
|
204
|
+
@itemcache.delete(aindex)
|
205
|
+
@itemcache.keys.sort.select{|i| i>=aindex+1 }.each do |i|
|
206
|
+
@itemcache[i-1]=@itemcache.delete(i)
|
207
|
+
@itemcache[i-1].shift_by(-1)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
def delete
|
212
|
+
@itemcache.each do |key,item|
|
213
|
+
item.delete # delete item - this destroys its subitems, xmlnode and invalidates it
|
214
|
+
@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
|
215
|
+
end
|
216
|
+
super # this for example for Row objects calls XMLTiedItem.delete
|
217
|
+
end
|
218
|
+
|
219
|
+
def find_nonempty_subnode_indexes(axmlnode, options)
|
220
|
+
index = 0
|
221
|
+
result = []
|
222
|
+
axmlnode.elements.select{|node| node.name == options[:xml_items_node_name]}.each do |node|
|
223
|
+
repeated = (node.attributes[options[:xml_repeated_attribute]] || 1).to_i
|
224
|
+
index = index + repeated
|
225
|
+
if !(node.content.nil? or node.content.empty? or node.content =='') and (repeated==1)
|
226
|
+
result << index
|
227
|
+
end
|
228
|
+
end
|
229
|
+
return result
|
230
|
+
end
|
231
|
+
|
232
|
+
end
|
233
|
+
|
234
|
+
end
|
data/lib/rspreadsheet.rb
CHANGED
data/reinstall2.sh
ADDED
data/rspreadsheet.gemspec
CHANGED
@@ -22,19 +22,18 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.add_runtime_dependency 'libxml-ruby', '~>2.7' # parsing XML files
|
23
23
|
spec.add_runtime_dependency 'rubyzip', '~>1.1' # opening zip files
|
24
24
|
spec.add_runtime_dependency 'andand', '~>1.3'
|
25
|
-
|
26
|
-
|
25
|
+
|
27
26
|
# development dependencies
|
28
27
|
spec.add_development_dependency "bundler", "~> 1.5"
|
29
28
|
spec.add_development_dependency "rake", '~>0.9'
|
30
29
|
# testig - see http://bit.ly/1n5yM51
|
31
|
-
spec.add_development_dependency "rspec", '~>2'
|
32
|
-
spec.add_development_dependency 'pry-nav', '~>0'
|
33
|
-
|
30
|
+
spec.add_development_dependency "rspec", '~>2' # testing
|
31
|
+
spec.add_development_dependency 'pry-nav', '~>0' # enables pry 'next', 'step' commands
|
32
|
+
|
34
33
|
# optional and testing
|
35
34
|
spec.add_development_dependency "coveralls", '~>0.7'
|
36
35
|
spec.add_development_dependency "guard", '~>2.6'
|
37
36
|
spec.add_development_dependency "guard-rspec", '~>2.6'
|
38
|
-
# spec.add_development_dependency 'equivalent-xml'
|
39
|
-
|
37
|
+
# spec.add_development_dependency 'equivalent-xml' # implementing xml diff
|
38
|
+
|
40
39
|
end
|