ruby-ods 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 19cfa5706fdcfab427e629b4801bb1f8e14bb9c6e7379b73c706b3b87483da73
4
+ data.tar.gz: d768b41cbf282fe3f40fca9e23518550b8253deca15fd7486aec36efdfcae0d5
5
+ SHA512:
6
+ metadata.gz: 6104b0c45fa68f977f94783c02559fb7c6a377e933db25b480337b42a10ae97c1caa73e20e79e2e58c1e7aef511c51d3bfc0ce34d0df1be38630495b286ae20e
7
+ data.tar.gz: 742eda97b8a6e5983b780a30ebe50ad5ca5fdadac26a826193558834a95cb5ba438715736ba39598349db62a97c0c04050182d66a98e0d16ad6c60e36dd9569d
data/README.md ADDED
@@ -0,0 +1,64 @@
1
+ # Ruby::Ods
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/ruby-ods.svg)](https://badge.fury.io/rb/ruby-ods)
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'ruby-ods'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install ruby-ods
20
+
21
+ ## Usage
22
+
23
+ For initializing the ODS object
24
+
25
+ ```ruby
26
+ require 'ruby/ods'
27
+ ods = Ruby::Ods::Manager.new('sample1.ods')
28
+ ```
29
+
30
+ For getting sheets
31
+ ```ruby
32
+ sheet = ods.sheets[0]
33
+ ```
34
+
35
+ For getting value of columns
36
+
37
+ ```ruby
38
+ sheet[3, :A].value
39
+ ```
40
+
41
+ For saving a value in the row column
42
+
43
+ ```ruby
44
+ sheet[3, :A].value = "2092"
45
+ ods.save
46
+ ```
47
+
48
+ ## Development
49
+
50
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
51
+
52
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
53
+
54
+ ## Contributing
55
+
56
+ Bug reports and pull requests are welcome on GitHub at https://github.com/ratnamyadav/ruby-ods. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
57
+
58
+ ## License
59
+
60
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
61
+
62
+ ## Code of Conduct
63
+
64
+ Everyone interacting in the Ruby::Ods project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/ruby-ods/blob/master/CODE_OF_CONDUCT.md).
@@ -0,0 +1,28 @@
1
+ # -*- coding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+
4
+ Nokogiri::XML::Element.module_eval do
5
+ def add_element(name, attributes={})
6
+ (prefix, name) = name.split(':') if name.include?(':')
7
+ node = Nokogiri::XML::Node.new(name, self)
8
+ attributes.each do |attr, val|
9
+ node.set_attribute(attr, val)
10
+ end
11
+ ns = node.add_namespace_definition(prefix, Ruby::Ods::Manager::NAMESPACES[prefix])
12
+ node.namespace = ns
13
+ self.add_child(node)
14
+ node
15
+ end
16
+
17
+ def fetch(xpath)
18
+ if node = self.xpath(xpath).first
19
+ return node
20
+ end
21
+
22
+ return self.add_element(xpath) unless xpath.include?('/')
23
+
24
+ xpath = xpath.split('/')
25
+ last_path = xpath.pop
26
+ fetch(xpath.join('/')).fetch(last_path)
27
+ end
28
+ end
@@ -0,0 +1,5 @@
1
+ module Ruby
2
+ module Ods
3
+ VERSION = "0.1.3"
4
+ end
5
+ end
data/lib/ruby/ods.rb ADDED
@@ -0,0 +1,214 @@
1
+ require "ruby/ods/version"
2
+ require "forwardable"
3
+ require "rubygems"
4
+ require "nokogiri"
5
+ require "ruby/nokogiri_ext"
6
+ require "zip"
7
+ require "fileutils"
8
+
9
+ module Ruby
10
+ module Ods
11
+ class Error < StandardError; end
12
+
13
+ class Manager
14
+ attr_reader :content, :sheets
15
+ XPATH_SHEETS = '//office:body/office:spreadsheet/table:table'
16
+
17
+ NAMESPACES = {
18
+ 'office' => 'urn:oasis:names:tc:opendocument:xmlns:office:1.0',
19
+ 'style' => 'urn:oasis:names:tc:opendocument:xmlns:style:1.0',
20
+ 'text' => 'urn:oasis:names:tc:opendocument:xmlns:text:1.0',
21
+ 'table' => 'urn:oasis:names:tc:opendocument:xmlns:table:1.0',
22
+ 'draw' => 'urn:oasis:names:tc:opendocument:xmlns:drawing:1.0',
23
+ 'fo' => 'urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0',
24
+ 'xlink' => 'http://www.w3.org/1999/xlink',
25
+ 'dc' => 'http://purl.org/dc/elements/1.1/',
26
+ 'meta' => 'urn:oasis:names:tc:opendocument:xmlns:meta:1.0',
27
+ 'number' => 'urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0',
28
+ 'presentation' => 'urn:oasis:names:tc:opendocument:xmlns:presentation:1.0',
29
+ 'svg' => 'urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0',
30
+ 'chart' => 'urn:oasis:names:tc:opendocument:xmlns:chart:1.0',
31
+ 'dr3d' => 'urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0',
32
+ 'math' => 'http://www.w3.org/1998/Math/MathML',
33
+ 'form' => 'urn:oasis:names:tc:opendocument:xmlns:form:1.0',
34
+ 'script' => 'urn:oasis:names:tc:opendocument:xmlns:script:1.0',
35
+ 'ooo' => 'http://openoffice.org/2004/office',
36
+ 'ooow' => 'http://openoffice.org/2004/writer',
37
+ 'oooc' => 'http://openoffice.org/2004/calc',
38
+ 'dom' => 'http://www.w3.org/2001/xml-events',
39
+ 'xforms' => 'http://www.w3.org/2002/xforms',
40
+ 'xsd' => 'http://www.w3.org/2001/XMLSchema',
41
+ 'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
42
+ 'rpt' => 'http://openoffice.org/2005/report',
43
+ 'of' => 'urn:oasis:names:tc:opendocument:xmlns:of:1.2',
44
+ 'rdfa' => 'http://docs.oasis-open.org/opendocument/meta/rdfa#',
45
+ 'field' => 'urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0',
46
+ 'formx' => 'urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0'
47
+ }
48
+
49
+ def initialize(path)
50
+ @path = path
51
+ Zip::File.open(@path) do |zip|
52
+ @content = Nokogiri::XML::Document.parse(zip.read('content.xml'))
53
+ end
54
+ @sheets = []
55
+ @content.root.xpath(XPATH_SHEETS).each do |sheet|
56
+ @sheets.push(Sheet.new(sheet))
57
+ end
58
+ @content
59
+ end
60
+
61
+ def save(dest=nil)
62
+ if dest
63
+ FileUtils.cp(@path, dest)
64
+ else
65
+ dest = @path
66
+ end
67
+
68
+ @sheets.each do |sheet|
69
+ column = sheet.column
70
+ max_length = 0
71
+ column.content.parent.xpath('table:table-row').each do |row|
72
+ length = row.xpath('table:table-cell').length
73
+ max_length = length if max_length < length
74
+ end
75
+ column.set_attr('repeated', max_length)
76
+ end
77
+
78
+ Zip::File.open(dest) do |zip|
79
+ zip.get_output_stream('content.xml') do |io|
80
+ io << @content.to_s
81
+ end
82
+ end
83
+ end
84
+
85
+ def create_sheet
86
+ parent = @content.root.xpath(XPATH_SHEETS.split('/')[0..-2].join('/'))[0]
87
+ table = parent.add_element('table:table',
88
+ 'name' => "Sheet#{@sheets.length + 1}",
89
+ 'style-name' => 'ta1',
90
+ 'print' => 'false')
91
+ table.add_element('table:table-column',
92
+ 'style-name' => 'co1',
93
+ 'default-cell-style-name' => 'Default')
94
+ new_sheet = Sheet.new(table)
95
+ @sheets.push(new_sheet)
96
+ new_sheet
97
+ end
98
+
99
+ class Sheet
100
+ attr_reader :content
101
+ def initialize(content)
102
+ @content = content
103
+ end
104
+
105
+ def name
106
+ @content.attribute('name').to_s
107
+ end
108
+
109
+ def name=(name)
110
+ @content.set_attribute('table:name', name)
111
+ end
112
+
113
+ def [](row, col)
114
+ (row - rows.length).times do
115
+ rows.push(Row.new(@content.add_element('table:table-row',
116
+ 'table:style-name' => 'ro1'), rows.length+1))
117
+ end
118
+ row = rows[row-1]
119
+ col = ('A'..col.to_s).to_a.index(col.to_s)
120
+ cols = row.cols
121
+ (col - cols.length + 1).times do
122
+ no = (cols.last) ? cols.last.no.to_s.succ : 'A'
123
+ cols.push(Cell.new(row.add_element('table:table-cell', 'office:value-type' => 'string'), no))
124
+ end
125
+ cols[col]
126
+ end
127
+
128
+ def rows
129
+ return @rows if @rows
130
+ @rows = []
131
+ @content.xpath('./table:table-row').each_with_index{|row, index|
132
+ @rows << Row.new(row, index+1)
133
+ }
134
+ @rows
135
+ end
136
+
137
+ def column
138
+ Column.new(@content.xpath('table:table-column').first)
139
+ end
140
+ end
141
+
142
+ class Row
143
+ extend Forwardable
144
+
145
+ def_delegator :@content, :xpath, :xpath
146
+ def_delegator :@content, :add_element, :add_element
147
+ attr_reader :no
148
+
149
+ def initialize(content, no)
150
+ @content = content
151
+ @no = no
152
+ end
153
+
154
+ def cols
155
+ return @cols if @cols
156
+ @cols = []
157
+ no = 'A'
158
+ xpath('table:table-cell').each{|cell|
159
+ @cols << Cell.new(cell, no)
160
+ no.succ!
161
+ }
162
+ @cols
163
+ end
164
+
165
+ def create_cell
166
+
167
+ end
168
+ end
169
+
170
+ class Cell
171
+ extend Forwardable
172
+
173
+ def_delegator :@content, :fetch, :fetch
174
+ attr_reader :no
175
+
176
+ def initialize(content, no)
177
+ @content = content
178
+ @no = no.to_sym
179
+ end
180
+
181
+ def value
182
+ fetch('text:p').content
183
+ end
184
+
185
+ def value=(value)
186
+ fetch('text:p').content = value
187
+ end
188
+
189
+ def annotation
190
+ fetch('office:annotation/text:p').content
191
+ end
192
+
193
+ def annotation=(value)
194
+ fetch('office:annotation/text:p').content = value
195
+ end
196
+ end
197
+
198
+ class Column
199
+ attr_reader :content
200
+ def initialize(content)
201
+ @content = content
202
+ end
203
+
204
+ def attr(name)
205
+ @content['number-columns-' + name]
206
+ end
207
+
208
+ def set_attr(name, value)
209
+ @content['table:number-columns-' + name] = value.to_s
210
+ end
211
+ end
212
+ end
213
+ end
214
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby-ods
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.3
5
+ platform: ruby
6
+ authors:
7
+ - Ratnam Yadav
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-01-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: nokogiri
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.4'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.4.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '1.4'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 1.4.0
33
+ - !ruby/object:Gem::Dependency
34
+ name: rubyzip
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 1.3.0
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 1.3.0
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: 1.3.0
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 1.3.0
53
+ description: Gem for interacting with Ods files
54
+ email: heartcombo@googlegroups.com
55
+ executables: []
56
+ extensions: []
57
+ extra_rdoc_files: []
58
+ files:
59
+ - README.md
60
+ - lib/ruby/nokogiri_ext.rb
61
+ - lib/ruby/ods.rb
62
+ - lib/ruby/ods/version.rb
63
+ homepage: https://github.com/ratnamyadav/ruby-ods
64
+ licenses:
65
+ - MIT
66
+ metadata: {}
67
+ post_install_message:
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: 2.1.0
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ requirements: []
82
+ rubygems_version: 3.2.32
83
+ signing_key:
84
+ specification_version: 4
85
+ summary: Gem for interacting with Ods files
86
+ test_files: []