rspreadsheet 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,47 @@
1
+ require 'andand'
2
+
3
+ module Rspreadsheet
4
+ class Cell
5
+ attr_reader :value,:col,:row, :source_node
6
+ def initialize(arow,acol,source_node=nil)
7
+ @col = acol
8
+ @row = arow
9
+ @source_node = source_node
10
+ unless @source_node.nil?
11
+ @type = @source_node.attributes['value-type'].to_s
12
+ if (@source_node.children.size == 0) and (not @source_node.attributes?)
13
+ @value = nil
14
+ else
15
+ # here you also ned to read style not only value
16
+ @value = case @type
17
+ when 'float'
18
+ @source_node.attributes['value'].to_f
19
+ when 'string'
20
+ @source_node.elements.first.andand.content.to_s
21
+ when 'date'
22
+ Date.strptime(@source_node.attributes['date-value'].to_s, '%Y-%m-%d')
23
+ when 'percentage'
24
+ @source_node.attributes['value'].to_f
25
+ else
26
+ if @source_node.children.size == 0
27
+ nil
28
+ else
29
+ nil
30
+ # raise "Unknown type from #{@source_node.to_s} / children size=#{@source_node.children.size.to_s} / type=#{@type}"
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ def to_s
37
+ value
38
+ end
39
+ def value=(avalue)
40
+ @value=avalue
41
+ self
42
+ end
43
+ def coordinates
44
+ [row,col]
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,30 @@
1
+ require('rspreadsheet/cell')
2
+
3
+ # Currently this is only syntax sugar for cells and contains no functionality
4
+
5
+ module Rspreadsheet
6
+
7
+ class Row
8
+ def initialize(workbook,rowi)
9
+ @rowi = rowi
10
+ @workbook = workbook
11
+ @rowcells = RowCells.new(workbook,rowi)
12
+ end
13
+ def cells
14
+ @rowcells
15
+ end
16
+ end
17
+
18
+ # this allows the row.cells[c] syntax
19
+ # this object is result of row.cells
20
+ class RowCells
21
+ def initialize(workbook,rowi)
22
+ @rowi = rowi
23
+ @workbook = workbook
24
+ end
25
+ def [] coli
26
+ @workbook.cells[@rowi,coli]
27
+ end
28
+ end
29
+
30
+ end
@@ -1,3 +1,3 @@
1
1
  module Rspreadsheet
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -0,0 +1,55 @@
1
+ require 'zip'
2
+ require 'libxml'
3
+
4
+ module Rspreadsheet
5
+ class Workbook
6
+ attr_reader :worksheets, :filename
7
+ def initialize(afilename=nil)
8
+ @worksheets={}
9
+ @filename = afilename
10
+ if filename.nil?
11
+ else
12
+ @content_xml = Zip::File.open(filename) do |zip|
13
+ LibXML::XML::Document.io zip.get_input_stream('content.xml')
14
+ end
15
+
16
+ ndx = 0
17
+ @content_xml.find_first('//office:spreadsheet').each_element { |node|
18
+ sheet = Worksheet.new(node)
19
+ @worksheets[ndx]=sheet
20
+ @worksheets[node.name]=sheet
21
+ ndx+=1
22
+ }
23
+ end
24
+ end
25
+ def save(new_filename=nil)
26
+ if @filename.nil? and new_filename.nil? then raise 'New file should be named on first save.' end
27
+ # if the filename has changed than first copy the original file to new location (or template if it is a new file)
28
+ if new_filename
29
+ FileUtils.cp(@filename || './lib/rspreadsheet/empty_file_template.ods', new_filename)
30
+ @filename = new_filename
31
+ end
32
+ Zip::File.open(@filename) do |zip|
33
+ # it is easy, because @content_xml in in sync with contents all the time
34
+ zip.get_output_stream('content.xml') do |f|
35
+ f.write @content_xml
36
+ end
37
+ end
38
+ end
39
+ def create_worksheet(node=nil)
40
+ sheet = Worksheet.new(node)
41
+ @worksheets[worksheets_count]=sheet
42
+ @worksheets[node.name]=sheet unless node.nil?
43
+ return sheet
44
+ end
45
+ def worksheets
46
+ @worksheets
47
+ end
48
+ def worksheets_count
49
+ @worksheets.keys.select{ |k| k.kind_of? Numeric }.size #TODO: ?? max
50
+ end
51
+ def worksheet_names
52
+ @worksheets.keys.reject{ |k| k.kind_of? Numeric }
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,112 @@
1
+ require 'rspreadsheet/row'
2
+ require 'forwardable'
3
+
4
+ module Rspreadsheet
5
+
6
+ module Tools
7
+ ## converts cell adress like 'F12' to pair od integers [row,col]
8
+ def self.convert_cell_address(*coords)
9
+ if coords.length == 1
10
+ coords.match(/^([A-Z]{1,3})(\d{1,8})$/)
11
+ colname = $~[1]
12
+ rowname = $~[2]
13
+ elsif coords.length == 2
14
+ colname = coords[0]
15
+ rowname = coords[1]
16
+ else
17
+ raise 'Wrong number of arguments'
18
+ end
19
+
20
+ colname=colname.rjust(3,'@')
21
+ col = (colname[-1].ord-65)+(colname[-2].ord-64)*26+(colname[-3].ord-64)*26*26
22
+ row = rowname.to_i-1
23
+ return [row,col]
24
+ end
25
+ end
26
+
27
+ class Worksheet
28
+ attr_accessor :name
29
+ extend Forwardable
30
+ def_delegators :@worksheetcells, :nonemptycells
31
+
32
+ def initialize(source_node=nil)
33
+ @source_node = source_node
34
+ @worksheetcells=WorksheetCells.new
35
+ rowi = 0
36
+ unless @source_node.nil?
37
+ @source_node.elements.select{ |node| node.name == 'table-row'}.each do |row_source_node|
38
+ coli = 0
39
+ row_source_node.elements.select{ |node| node.name == 'table-cell'}.each do |cell_source_node|
40
+ cells.initialize_cell(rowi,coli,cell_source_node)
41
+ coli += 1
42
+ end
43
+ rowi += 1
44
+ end
45
+ end
46
+ end
47
+ def cells
48
+ @worksheetcells
49
+ end
50
+ def [](r,c)
51
+ cells[r,c].value
52
+ end
53
+ def []=(r,c,avalue)
54
+ cells[r,c].value=avalue
55
+ end
56
+ def rows
57
+ WorksheetRows.new(self)
58
+ end
59
+ def method_missing method_name, *args, &block
60
+ if method_name.to_s.match(/^([A-Z]{1,3})(\d{1,8})(=?)$/)
61
+ row,col = Tools.convert_cell_address($~[1],$~[2])
62
+ assignchar = $~[3]
63
+ if assignchar == '='
64
+ self.cells[row,col].value = args.first
65
+ else
66
+ self.cells[row,col].value
67
+ end
68
+ else
69
+ super
70
+ end
71
+ end
72
+ end
73
+
74
+ # this allows the sheet.cells[r,c] syntax
75
+ # this object is result of sheet.cells
76
+ class WorksheetCells
77
+ def initialize
78
+ @cells = Hash.new do |hash, coords|
79
+ # we create empty cell and place it to hash, we do not have to check whether there is a cell in XML already, because it would be in hash as well
80
+ hash[coords]=Cell.new(coords[0],coords[1])
81
+ # TODO: create XML empty node here or upon save?
82
+ end
83
+ end
84
+ def [](r,c)
85
+ cells_object(r,c)
86
+ end
87
+ def nonemptycells
88
+ @cells.values
89
+ end
90
+
91
+ ### internal
92
+ def cells_object(r,c)
93
+ @cells[[r,c]]
94
+ end
95
+ def initialize_cell(r,c,source_node)
96
+ @cells[[r,c]]=Cell.new(r,c,source_node)
97
+ end
98
+ end
99
+
100
+ # this allows the sheet.rows[r] syntax
101
+ # this object is result of sheet.rows
102
+ class WorksheetRows
103
+ def initialize(aworkbook)
104
+ @workbook = aworkbook
105
+ @spredsheetrows=Array.new()
106
+ end
107
+ def [] rowi
108
+ @spredsheetrows[rowi] ||= Row.new(@workbook,rowi)
109
+ end
110
+ end
111
+
112
+ end
data/lib/rspreadsheet.rb CHANGED
@@ -1,5 +1,14 @@
1
1
  require "rspreadsheet/version"
2
+ require 'rspreadsheet/workbook'
3
+ require 'rspreadsheet/worksheet'
4
+ require 'class_extensions'
2
5
 
3
6
  module Rspreadsheet
4
- # Your code goes here...
7
+
8
+ def self.new(filename=nil)
9
+ Workbook.new(filename)
10
+ end
11
+ def self.open(filename)
12
+ Workbook.new(filename)
13
+ end
5
14
  end
data/rspreadsheet.gemspec CHANGED
@@ -9,15 +9,31 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ["Jakub A.Těšínský"]
10
10
  spec.email = ["jAkub.cz (A is at)"]
11
11
  spec.summary = %q{Manipulating spreadsheets with Ruby (read / create / modify OpenDocument Spreadsheet).}
12
- # spec.description = %q{TODO: Write a longer description. Optional.}
12
+ spec.description = %q{Manipulating spreadsheets with Ruby (read / create / modify OpenDocument Spreadsheet).}
13
13
  spec.homepage = "https://github.com/gorn/rspreadsheet"
14
- # spec.license = "MIT"
14
+ spec.license = "GPL"
15
15
 
16
16
  spec.files = `git ls-files -z`.split("\x0")
17
17
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
+ # runtime dependencies
22
+ spec.add_runtime_dependency 'libxml-ruby', '~>2.7' # parsing XML files
23
+ spec.add_runtime_dependency 'rubyzip', '~>1.1' # opening zip files
24
+ spec.add_runtime_dependency 'andand', '~>1.3'
25
+
26
+
27
+ # development dependencies
21
28
  spec.add_development_dependency "bundler", "~> 1.5"
22
- spec.add_development_dependency "rake"
29
+ spec.add_development_dependency "rake", '~>0.9'
30
+ # testig - see http://bit.ly/1n5yM51
31
+ spec.add_development_dependency "rspec", '~>2'
32
+
33
+ # optional and testing
34
+ spec.add_development_dependency "coveralls", '~>0.7'
35
+ spec.add_development_dependency "test_notifier", '~>2.0' # test notifier for kde and other platforms
36
+ spec.add_development_dependency "guard", '~>2.6'
37
+ spec.add_development_dependency "guard-rspec", '~>2.6'
38
+
23
39
  end
@@ -0,0 +1,154 @@
1
+ require 'spec_helper'
2
+
3
+ $test_filename = './spec/testfile1.ods'
4
+
5
+ describe Rspreadsheet do
6
+ it 'can open ods testfile and reads its content correctly' do
7
+ book = Rspreadsheet.new($test_filename)
8
+ book.worksheets[0].should_not == nil
9
+ book.worksheets[0].class.should == Rspreadsheet::Worksheet
10
+ s = book.worksheets[0]
11
+ (1..10).each do |i|
12
+ s[i-1,0].should === i
13
+ end
14
+ s[0,1].should === 'text'
15
+ s[1,1].should === Date.new(2014,1,1)
16
+ end
17
+ it 'can open and save file, and saved file has same cells as original' do
18
+ tmp_filename = '/tmp/testfile1.ods' # first delete temp file
19
+ File.delete(tmp_filename) if File.exists?(tmp_filename)
20
+ book = Rspreadsheet.new($test_filename) # than open test file
21
+ book.save(tmp_filename) # and save it as temp file
22
+
23
+ book1 = Rspreadsheet.new($test_filename) # now open both again
24
+ book2 = Rspreadsheet.new(tmp_filename)
25
+ @sheet1 = book1.worksheets[0]
26
+ @sheet2 = book2.worksheets[0]
27
+
28
+ @sheet1.nonemptycells.each do |cell| # and test identity
29
+ @sheet2[cell.row,cell.col].should == cell.value
30
+ end
31
+ end
32
+ it 'can open and save file, and saved file is exactly same as original' do
33
+ tmp_filename = '/tmp/testfile1.ods' # first delete temp file
34
+ File.delete(tmp_filename) if File.exists?(tmp_filename)
35
+ book = Rspreadsheet.new($test_filename) # than open test file
36
+ book.save(tmp_filename) # and save it as temp file
37
+
38
+ # now compare them
39
+ @content_xml1 = Zip::File.open($test_filename) do |zip|
40
+ LibXML::XML::Document.io zip.get_input_stream('content.xml')
41
+ end
42
+ @content_xml2 = Zip::File.open(tmp_filename) do |zip|
43
+ LibXML::XML::Document.io zip.get_input_stream('content.xml')
44
+ end
45
+ @content_xml1.root.equals?(@content_xml2.root).should == true
46
+ end
47
+ it 'when open and save file modified, than the file is different' do
48
+ tmp_filename = '/tmp/testfile1.ods' # first delete temp file
49
+ File.delete(tmp_filename) if File.exists?(tmp_filename)
50
+ book = Rspreadsheet.new($test_filename) # than open test file
51
+ book.worksheets[0][0,0].should_not == 'xyzxyz'
52
+ book.worksheets[0][0,0]='xyzxyz'
53
+ book.worksheets[0][0,0].should == 'xyzxyz'
54
+ book.save(tmp_filename) # and save it as temp file
55
+
56
+ # now compare them
57
+ @content_doc1 = Zip::File.open($test_filename) do |zip|
58
+ LibXML::XML::Document.io zip.get_input_stream('content.xml')
59
+ end
60
+ @content_doc2 = Zip::File.open(tmp_filename) do |zip|
61
+ LibXML::XML::Document.io zip.get_input_stream('content.xml')
62
+ end
63
+ @content_doc1.eql?(@content_doc2).should == false
64
+ end
65
+ it 'can create file' do
66
+ book = Rspreadsheet.new
67
+ end
68
+ it 'can create new worksheet' do
69
+ book = Rspreadsheet.new
70
+ book.create_worksheet
71
+ end
72
+ end
73
+
74
+ describe Rspreadsheet::Cell do
75
+ before do
76
+ book1 = Rspreadsheet.new
77
+ @sheet1 = book1.create_worksheet
78
+ @sheet1[0,0] = 'text'
79
+ book2 = Rspreadsheet.new($test_filename)
80
+ @sheet2 = book2.worksheets[0]
81
+ end
82
+ it 'contains good row and col coordinates' do
83
+ @cell = @sheet1.cells[1,3]
84
+ @cell.row.should == 1
85
+ @cell.col.should == 3
86
+ @cell.coordinates.should == [1,3]
87
+
88
+ @cell = @sheet2.cells[0,1]
89
+ @cell.row.should == 0
90
+ @cell.col.should == 1
91
+ @cell.coordinates.should == [0,1]
92
+ end
93
+ it 'can be referenced by more vars and both are synchromized' do
94
+ @cell = @sheet1.cells[0,0]
95
+ @sheet1[0,0] = 'novinka'
96
+ @cell.value.should == 'novinka'
97
+ end
98
+ it 'can be modyfied by more ways and all are identical' do
99
+ @cell = @sheet1.cells[2,2]
100
+ @sheet1[2,2] = 'zaprve'
101
+ @cell.value.should == 'zaprve'
102
+ @sheet1.cells[2,2].value = 'zadruhe'
103
+ @cell.value.should == 'zadruhe'
104
+ @sheet1.C3 = 'zatreti'
105
+ @cell.value.should == 'zatreti'
106
+ end
107
+ end
108
+
109
+
110
+ describe Rspreadsheet::Worksheet do
111
+ before do
112
+ book = Rspreadsheet.new
113
+ @sheet = book.create_worksheet
114
+ end
115
+ it 'remembers the value stored to A1 cell' do
116
+ @sheet[0,0].should == nil
117
+ @sheet[0,0] = 'test text'
118
+ @sheet[0,0].class.should == String
119
+ @sheet[0,0].should == 'test text'
120
+ end
121
+ it 'value stored to A1 is accesible using different syntax' do
122
+ @sheet[0,0] = 'test text'
123
+ @sheet[0,0].should == 'test text'
124
+ @sheet.cells[0,0].value.should == 'test text'
125
+ end
126
+ it 'makes Cell object accessible' do
127
+ @sheet.cells[0,0].value = 'test text'
128
+ @sheet.cells[0,0].class.should == Rspreadsheet::Cell
129
+ end
130
+ it 'has name, which can be changed and is remembered' do
131
+ @sheet.name.should be(nil)
132
+ @sheet.name = 'Icecream'
133
+ @sheet.name.should == 'Icecream'
134
+ @sheet.name = 'Cofee'
135
+ @sheet.name.should == 'Cofee'
136
+ end
137
+ end
138
+
139
+ describe Rspreadsheet::Row do
140
+ before do
141
+ book1 = Rspreadsheet.new
142
+ @sheet1 = book1.create_worksheet
143
+ end
144
+ it 'allows access to cells in a row' do
145
+ (2..5).each { |i| @sheet1[7,i] = i }
146
+ (2..5).each { |i|
147
+ a = @sheet1.rows
148
+ b = a[7]
149
+ c = b.cells
150
+ d = c[i]
151
+ d.value.should == i
152
+ }
153
+ end
154
+ end
@@ -0,0 +1,4 @@
1
+ require 'coveralls'
2
+ Coveralls.wear!
3
+
4
+ require 'rspreadsheet'
Binary file
metadata CHANGED
@@ -1,61 +1,190 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspreadsheet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
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: 2014-05-16 00:00:00.000000000 Z
11
+ date: 2014-07-24 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
+ - !ruby/object:Gem::Dependency
28
+ name: rubyzip
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.1'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: andand
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.3'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.3'
13
55
  - !ruby/object:Gem::Dependency
14
56
  name: bundler
15
57
  requirement: !ruby/object:Gem::Requirement
16
58
  requirements:
17
- - - ~>
59
+ - - "~>"
18
60
  - !ruby/object:Gem::Version
19
61
  version: '1.5'
20
62
  type: :development
21
63
  prerelease: false
22
64
  version_requirements: !ruby/object:Gem::Requirement
23
65
  requirements:
24
- - - ~>
66
+ - - "~>"
25
67
  - !ruby/object:Gem::Version
26
68
  version: '1.5'
27
69
  - !ruby/object:Gem::Dependency
28
70
  name: rake
29
71
  requirement: !ruby/object:Gem::Requirement
30
72
  requirements:
31
- - - '>='
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.9'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.9'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '2'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '2'
97
+ - !ruby/object:Gem::Dependency
98
+ name: coveralls
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0.7'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0.7'
111
+ - !ruby/object:Gem::Dependency
112
+ name: test_notifier
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
32
116
  - !ruby/object:Gem::Version
33
- version: '0'
117
+ version: '2.0'
34
118
  type: :development
35
119
  prerelease: false
36
120
  version_requirements: !ruby/object:Gem::Requirement
37
121
  requirements:
38
- - - '>='
122
+ - - "~>"
39
123
  - !ruby/object:Gem::Version
40
- version: '0'
41
- description:
124
+ version: '2.0'
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
+ description: Manipulating spreadsheets with Ruby (read / create / modify OpenDocument
154
+ Spreadsheet).
42
155
  email:
43
156
  - jAkub.cz (A is at)
44
157
  executables: []
45
158
  extensions: []
46
159
  extra_rdoc_files: []
47
160
  files:
48
- - .gitignore
161
+ - ".coveralls.yml"
162
+ - ".gitignore"
163
+ - ".travis.yml"
164
+ - COPYING.txt
165
+ - DEVEL_BLOG.md
49
166
  - GUIDE.md
50
167
  - Gemfile
51
- - LICENSE.txt
168
+ - Gemfile.lock
169
+ - Guardfile
170
+ - LICENSE.md
52
171
  - README.md
53
172
  - Rakefile
173
+ - lib/class_extensions.rb
54
174
  - lib/rspreadsheet.rb
175
+ - lib/rspreadsheet/cell.rb
176
+ - lib/rspreadsheet/empty_file_template.ods
177
+ - lib/rspreadsheet/row.rb
55
178
  - lib/rspreadsheet/version.rb
179
+ - lib/rspreadsheet/workbook.rb
180
+ - lib/rspreadsheet/worksheet.rb
56
181
  - rspreadsheet.gemspec
182
+ - spec/rspreadsheet_spec.rb
183
+ - spec/spec_helper.rb
184
+ - spec/testfile1.ods
57
185
  homepage: https://github.com/gorn/rspreadsheet
58
- licenses: []
186
+ licenses:
187
+ - GPL
59
188
  metadata: {}
60
189
  post_install_message:
61
190
  rdoc_options: []
@@ -63,19 +192,22 @@ require_paths:
63
192
  - lib
64
193
  required_ruby_version: !ruby/object:Gem::Requirement
65
194
  requirements:
66
- - - '>='
195
+ - - ">="
67
196
  - !ruby/object:Gem::Version
68
197
  version: '0'
69
198
  required_rubygems_version: !ruby/object:Gem::Requirement
70
199
  requirements:
71
- - - '>='
200
+ - - ">="
72
201
  - !ruby/object:Gem::Version
73
202
  version: '0'
74
203
  requirements: []
75
204
  rubyforge_project:
76
- rubygems_version: 2.0.14
205
+ rubygems_version: 2.2.2
77
206
  signing_key:
78
207
  specification_version: 4
79
208
  summary: Manipulating spreadsheets with Ruby (read / create / modify OpenDocument
80
209
  Spreadsheet).
81
- test_files: []
210
+ test_files:
211
+ - spec/rspreadsheet_spec.rb
212
+ - spec/spec_helper.rb
213
+ - spec/testfile1.ods