rspreadsheet 0.2.7 → 0.2.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +3 -3
- data/lib/rspreadsheet/cell.rb +49 -16
- data/lib/rspreadsheet/tools.rb +7 -2
- data/lib/rspreadsheet/version.rb +1 -1
- data/spec/cell_spec.rb +36 -4
- data/spec/testfile1.ods +0 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6cefcb8b1947902d4008ba3f9a77cbf1789addd1
|
4
|
+
data.tar.gz: 841b189fbbe35436ff05e92dcd7fe0cfc368cd0f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 69b9f5968540c86671c39cd93efc04f243cf5c441789e60bedd69a6fdc12a68ccf51016021a9a4bd75fffe65c716cadaeaf79289b6d00fedcdfda46973f62898
|
7
|
+
data.tar.gz: 52eea9086874e653eddab4374c396a82f09741daf55596a5cb393662d4130b25f5273e8664b43134981e5214d2bcfb3ffe9b3b88136c9d6e50a4eaab77f0df15
|
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
[![Build Status](https://api.travis-ci.org/gorn/rspreadsheet.svg?branch=master)](https://travis-ci.org/gorn/rspreadsheet) [![Coverage Status](https://coveralls.io/repos/gorn/rspreadsheet/badge.png)](https://coveralls.io/r/gorn/rspreadsheet)
|
4
4
|
|
5
|
-
Manipulating spreadsheets with Ruby. Read, modify, write or create new OpenDocument Spreadsheet files from ruby code.
|
5
|
+
Manipulating spreadsheets with Ruby. Read, modify, write or create new OpenDocument Spreadsheet files from ruby code.
|
6
6
|
|
7
7
|
## Contibutions, ideas and wishes welcomed
|
8
8
|
|
@@ -82,8 +82,8 @@ then you might not have installed libxml for ruby. I.e. in debian something like
|
|
82
82
|
|
83
83
|
This project arised from the necessity. Alhought it is not true that there are no ruby gems allowing to acess OpenDOcument spreadsheet, I did not find another decent one which would suit my needs. Most of them also look abandoned and inactive. I have investigated these options:
|
84
84
|
|
85
|
-
* [ruby-ods](https://github.com/yalab/ruby-ods) - this one seems as if it never really started
|
86
|
-
* [rodf](https://github.com/thiagoarrais/rodf)- this only
|
85
|
+
* [ruby-ods](https://github.com/yalab/ruby-ods) - this one seems abandoned, or even as if it never really started
|
86
|
+
* [rodf](https://github.com/thiagoarrais/rodf)- this only serves as builder, it can not read existing files or modify them
|
87
87
|
* [rods](http://www.drbreinlinger.de/ruby/rods/) - this is pretty ok, but it has terrible syntax. I first thought of writing wrapper around it, but it turned to be not so easy. Also last commit is 2 years old.
|
88
88
|
* [rubiod](https://github.com/netoctone/rubiod) - this one is quite ok, the syntax is definitely better that in rods, but it seems also very abandoned. It does not support formats. This is a closest match.
|
89
89
|
* [spreadsheet](https://github.com/zdavatz/spreadsheet) - this does not work with OpenDocument and even with Excel has issues in modyfying document. However since it is supposedly used, and has quite good syntax it might be inspirative. I also find the way this gem handles lazy writing of new rows to Spreadsheet object flawed, as well as strange accesibility of rows array object, which if assigned breaks consistency of sheet.
|
data/lib/rspreadsheet/cell.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
# @markup markdown
|
2
2
|
# @author Jakub Tesinsky
|
3
|
-
# @
|
3
|
+
# @title rspreadsheet Cell
|
4
4
|
|
5
5
|
require 'andand'
|
6
6
|
require 'rspreadsheet/xml_tied'
|
7
|
+
require 'date'
|
7
8
|
|
8
9
|
|
9
10
|
|
@@ -72,23 +73,23 @@ class Cell < XMLTiedItem
|
|
72
73
|
gt = guess_cell_type(avalue)
|
73
74
|
case
|
74
75
|
when gt == nil then raise 'This value type is not storable to cell'
|
75
|
-
when gt == Float
|
76
|
-
set_type_attribute('float')
|
76
|
+
when gt == Float then
|
77
77
|
remove_all_value_attributes_and_content(xmlnode)
|
78
|
+
set_type_attribute('float')
|
78
79
|
Tools.set_ns_attribute(xmlnode,'office','value', avalue.to_s)
|
79
80
|
xmlnode << Tools.prepare_ns_node('text','p', avalue.to_f.to_s)
|
80
81
|
when gt == String then
|
81
|
-
set_type_attribute('string')
|
82
82
|
remove_all_value_attributes_and_content(xmlnode)
|
83
|
+
set_type_attribute('string')
|
83
84
|
xmlnode << Tools.prepare_ns_node('text','p', avalue.to_s)
|
84
85
|
when gt == Date then
|
85
|
-
set_type_attribute('date')
|
86
86
|
remove_all_value_attributes_and_content(xmlnode)
|
87
|
+
set_type_attribute('date')
|
87
88
|
Tools.set_ns_attribute(xmlnode,'office','date-value', avalue.strftime('%Y-%m-%d'))
|
88
89
|
xmlnode << Tools.prepare_ns_node('text','p', avalue.strftime('%Y-%m-%d'))
|
89
|
-
when gt == :percentage
|
90
|
-
set_type_attribute('percentage')
|
90
|
+
when gt == :percentage then
|
91
91
|
remove_all_value_attributes_and_content(xmlnode)
|
92
|
+
set_type_attribute('percentage')
|
92
93
|
Tools.set_ns_attribute(xmlnode,'office','value', '%0.2d%' % avalue.to_f)
|
93
94
|
xmlnode << Tools.prepare_ns_node('text','p', (avalue.to_f*100).round.to_s+'%')
|
94
95
|
end
|
@@ -98,12 +99,17 @@ class Cell < XMLTiedItem
|
|
98
99
|
end
|
99
100
|
def set_type_attribute(typestring)
|
100
101
|
Tools.set_ns_attribute(xmlnode,'office','value-type',typestring)
|
102
|
+
Tools.set_ns_attribute(xmlnode,'calcext','value-type',typestring)
|
101
103
|
end
|
102
|
-
def remove_all_value_attributes_and_content(node)
|
104
|
+
def remove_all_value_attributes_and_content(node=xmlnode)
|
103
105
|
if att = Tools.get_ns_attribute(node, 'office','value') then att.remove! end
|
104
106
|
if att = Tools.get_ns_attribute(node, 'office','date-value') then att.remove! end
|
107
|
+
if att = Tools.get_ns_attribute(node, 'table','formula') then att.remove! end
|
105
108
|
node.content=''
|
106
109
|
end
|
110
|
+
def remove_all_type_attributes
|
111
|
+
set_type_attribute(nil)
|
112
|
+
end
|
107
113
|
def relative(rowdiff,coldiff)
|
108
114
|
@worksheet.cells(self.rowi+rowdiff, self.coli+coldiff)
|
109
115
|
end
|
@@ -115,6 +121,7 @@ class Cell < XMLTiedItem
|
|
115
121
|
when gct == Date then :date
|
116
122
|
when gct == :percentage then :percentage
|
117
123
|
when gct == :unassigned then :unassigned
|
124
|
+
when gct == NilClass then :empty
|
118
125
|
when gct == nil then :unknown
|
119
126
|
else :unknown
|
120
127
|
end
|
@@ -161,9 +168,11 @@ class Cell < XMLTiedItem
|
|
161
168
|
typeguess
|
162
169
|
end
|
163
170
|
else # it not have a typeguess
|
164
|
-
if (
|
171
|
+
if (avalue.nil?) # if nil then nil
|
172
|
+
NilClass
|
173
|
+
elsif (String(avalue) rescue false) # convertible to String
|
165
174
|
String
|
166
|
-
else
|
175
|
+
else # giving up
|
167
176
|
nil
|
168
177
|
end
|
169
178
|
end
|
@@ -178,6 +187,24 @@ class Cell < XMLTiedItem
|
|
178
187
|
def address
|
179
188
|
Tools.convert_cell_coordinates_to_address(coordinates)
|
180
189
|
end
|
190
|
+
|
191
|
+
def formula
|
192
|
+
rawformula = Tools.get_ns_attribute(xmlnode,'table','formula',nil).andand.value
|
193
|
+
if rawformula.nil?
|
194
|
+
nil
|
195
|
+
elsif rawformula.match(/^of:(.*)$/)
|
196
|
+
$1
|
197
|
+
else
|
198
|
+
raise "Mischmatched value in table:formula attribute - does not start with of: (#{rawformula.to_s})"
|
199
|
+
end
|
200
|
+
end
|
201
|
+
def formula=(formulastring)
|
202
|
+
detach_if_needed
|
203
|
+
raise 'Formula string must begin with "=" character' unless formulastring[0,1] == '='
|
204
|
+
remove_all_value_attributes_and_content(xmlnode)
|
205
|
+
remove_all_type_attributes
|
206
|
+
Tools.set_ns_attribute(xmlnode,'table','formula','of:'+formulastring.to_s)
|
207
|
+
end
|
181
208
|
|
182
209
|
end
|
183
210
|
|
@@ -209,6 +236,7 @@ class CellFormat
|
|
209
236
|
def color=(value); set_text_style_node_attribute('color', value) end
|
210
237
|
def font_size=(value);set_text_style_node_attribute('font-size', value) end
|
211
238
|
def set_text_style_node_attribute(attribute_name,value)
|
239
|
+
@cell.detach if @cell.mode != :regular
|
212
240
|
if text_style_node.nil?
|
213
241
|
self.create_text_style_node
|
214
242
|
raise 'Style node was not correctly initialized' if text_style_node.nil?
|
@@ -250,17 +278,22 @@ class CellFormat
|
|
250
278
|
end
|
251
279
|
|
252
280
|
def unused_cell_style_name
|
253
|
-
last = cellnode.doc.root.find('./office:automatic-styles/style:style').
|
281
|
+
last = (cellnode.nil? ? [] : cellnode.doc.root.find('./office:automatic-styles/style:style')).
|
254
282
|
collect {|node| node['name']}.
|
255
283
|
collect{ |name| /^ce(\d*)$/.match(name); $1.andand.to_i}.
|
256
284
|
compact.max || 0
|
257
285
|
"ce#{last+1}"
|
258
286
|
end
|
259
|
-
def automatic_styles_node;
|
260
|
-
def style_name; Tools.get_ns_attribute_value(cellnode,'table','style-name') end
|
261
|
-
def style_node;
|
262
|
-
def text_style_node;
|
263
|
-
def cell_style_node;
|
287
|
+
def automatic_styles_node; style_node_with_partial_xpath('') end
|
288
|
+
def style_name; Tools.get_ns_attribute_value(cellnode,'table','style-name',nil) end
|
289
|
+
def style_node; style_node_with_partial_xpath("/style:style[@style:name=\"#{style_name}\"]") end
|
290
|
+
def text_style_node; style_node_with_partial_xpath("/style:style[@style:name=\"#{style_name}\"]/style:text-properties") end
|
291
|
+
def cell_style_node; style_node_with_partial_xpath("/style:style[@style:name=\"#{style_name}\"]/style:table-cell-properties") end
|
292
|
+
def style_node_with_partial_xpath(xpath)
|
293
|
+
return nil if cellnode.nil?
|
294
|
+
cellnode.doc.root.find("./office:automatic-styles#{xpath}").first
|
295
|
+
end
|
296
|
+
|
264
297
|
end
|
265
298
|
|
266
299
|
end
|
data/lib/rspreadsheet/tools.rb
CHANGED
@@ -130,6 +130,7 @@ module Tools
|
|
130
130
|
end
|
131
131
|
# sets namespaced attribute "ns_prefix:key" in node to value. if value == delete_value then remove the attribute
|
132
132
|
def self.set_ns_attribute(node,ns_prefix,key,value,delete_value=nil)
|
133
|
+
raise 'Tools.set_ns_attribute can not set attribute on nil node' if node.nil?
|
133
134
|
ns = Tools.get_namespace(ns_prefix)
|
134
135
|
attr = node.attributes.get_attribute_ns(ns.href, key)
|
135
136
|
|
@@ -152,8 +153,12 @@ module Tools
|
|
152
153
|
node.nil? ? default : node.attributes.get_attribute_ns(Tools.get_namespace(ns_prefix).href,key) || default
|
153
154
|
end
|
154
155
|
end
|
155
|
-
def self.get_ns_attribute_value(node,ns_prefix,key)
|
156
|
-
|
156
|
+
def self.get_ns_attribute_value(node,ns_prefix,key,default=:undefined_default)
|
157
|
+
if default==:undefined_default
|
158
|
+
Tools.get_ns_attribute(node,ns_prefix,key).andand.value
|
159
|
+
else
|
160
|
+
node.nil? ? default : Tools.get_ns_attribute(node,ns_prefix,key,nil).andand.value || default
|
161
|
+
end
|
157
162
|
end
|
158
163
|
def self.remove_ns_attribute(node,ns_prefix,key)
|
159
164
|
node.attributes.get_attribute_ns(Tools.get_namespace(ns_prefix).href,key)
|
data/lib/rspreadsheet/version.rb
CHANGED
data/spec/cell_spec.rb
CHANGED
@@ -141,7 +141,7 @@ describe Rspreadsheet::Cell do
|
|
141
141
|
|
142
142
|
@cell = @sheet2.cells(16,4)
|
143
143
|
@cell.range.should == (1..7)
|
144
|
-
@cell.value.should ==
|
144
|
+
@cell.value.should == nil
|
145
145
|
|
146
146
|
@sheet2.rows(15).range.should == (14..18)
|
147
147
|
@sheet2.rows(16).range.should == (14..18)
|
@@ -155,11 +155,11 @@ describe Rspreadsheet::Cell do
|
|
155
155
|
|
156
156
|
@cellA = @sheet2.cells(16,1)
|
157
157
|
@cellA.range.should == (1..2)
|
158
|
-
@cellA.value.should
|
158
|
+
@cellA.value.should be_nil
|
159
159
|
|
160
160
|
@cellB = @sheet2.cells(16,5)
|
161
161
|
@cellB.range.should == (4..8)
|
162
|
-
@cellB.value.should
|
162
|
+
@cellB.value.should be_nil
|
163
163
|
|
164
164
|
end
|
165
165
|
it 'inserted has correct class' do # based on real error
|
@@ -232,7 +232,7 @@ describe Rspreadsheet::Cell do
|
|
232
232
|
expect { @cell.rowi }.to raise_error
|
233
233
|
expect { @cell.address }.to raise_error
|
234
234
|
|
235
|
-
@sheet1.cells(2,2).type.should == :
|
235
|
+
@sheet1.cells(2,2).type.should == :empty
|
236
236
|
@sheet1.cells(3,2).type.should == :unassigned
|
237
237
|
end
|
238
238
|
it 'switches to invalid_reference cell when its row is deleted' do
|
@@ -271,6 +271,38 @@ describe Rspreadsheet::Cell do
|
|
271
271
|
@sheet2.cells('BA177').should be @sheet2.cells(177,53)
|
272
272
|
@sheet2.cells('ADA2').should be @sheet2.cells(2,781)
|
273
273
|
end
|
274
|
+
it 'setting format in new file detaches the cell' do
|
275
|
+
@cell = @sheet1.cells(1,1)
|
276
|
+
# bold
|
277
|
+
@cell.format.bold.should be_falsey
|
278
|
+
@cell.format.bold = true
|
279
|
+
@cell.format.bold.should be_truthy
|
280
|
+
@cell.mode.should eq :regular
|
281
|
+
end
|
282
|
+
it 'remembers formula when set' do
|
283
|
+
@cell = @sheet1.cells(1,1)
|
284
|
+
# bold
|
285
|
+
@cell.formula.should be_nil
|
286
|
+
@cell.formula='=1+5'
|
287
|
+
@cell.formula.should eq '=1+5'
|
288
|
+
end
|
289
|
+
it 'unsets cell type when formula set - we can not guess it correctly', :focus do
|
290
|
+
@cell = @sheet1.cells(1,1)
|
291
|
+
@cell.value = 'ahoj'
|
292
|
+
@cell.type.should eq :string
|
293
|
+
@cell.formula='=1+5'
|
294
|
+
typ = @cell.xmlnode.nil? ? 'N/A' : @cell.xmlnode.attributes['value-type']
|
295
|
+
@cell.type.should_not eq :string
|
296
|
+
@cell.type.should eq :empty
|
297
|
+
end
|
298
|
+
it 'wipes out formula after assiging value' do
|
299
|
+
@cell = @sheet1.cells(1,1)
|
300
|
+
@cell.formula='=1+5'
|
301
|
+
@cell.formula.should_not be_nil
|
302
|
+
@cell.value = 'baf'
|
303
|
+
@cell.type.should eq :string
|
304
|
+
@cell.formula.should be_nil
|
305
|
+
end
|
274
306
|
end
|
275
307
|
|
276
308
|
|
data/spec/testfile1.ods
CHANGED
Binary file
|
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.
|
4
|
+
version: 0.2.9
|
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:
|
11
|
+
date: 2015-09-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: libxml-ruby
|
@@ -216,7 +216,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
216
216
|
version: '0'
|
217
217
|
requirements: []
|
218
218
|
rubyforge_project:
|
219
|
-
rubygems_version: 2.
|
219
|
+
rubygems_version: 2.4.1
|
220
220
|
signing_key:
|
221
221
|
specification_version: 4
|
222
222
|
summary: Manipulating spreadsheets with Ruby (read / create / modify OpenDocument
|