gen_sheet 0.0.4 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cc08c206bc562c7453bd04dd705376f6f1c5e268
4
- data.tar.gz: 99b212578eabb2dfa471f525ac61bc299c1a2ce2
3
+ metadata.gz: e186436a668732ade059542eed9ffdf4ebc1f861
4
+ data.tar.gz: 07920ab7916e4425a0fecf7f1f974e4f739c5a19
5
5
  SHA512:
6
- metadata.gz: 1b91d5ca089d7b6796469acebd21e9a1c5e3d9c14d1efb11663cd41ff0c66defc214e54b81bcb7db69db867a65931d52b5b7913166eed7bbe3bcedeed2a7f8a2
7
- data.tar.gz: bf60356f62cc002ffe7f4d1ea44e8b1fad814a6fd6807ba43e34859e5c9a624e1ea5ccba2a57d705b3fe205c5af2fa21f193d44bc3c3e8101b741e1d8ab2e576
6
+ metadata.gz: ef77eb88902d6ac5b34a5ed464d79cb6194b334ed891759f0f6cc794a40ad6159e7a04dece6fa18079d1adcc1ce2f4c893d89cd68359513a248dea91e4f70673
7
+ data.tar.gz: aec344e192676987d5c38aa658a4d1b83dde8928be56604737d72f3b83fb36f6e8a7c441e232942a191c6297042cd18a6611f635ed3b28918251363361e7c662
data/.gitignore CHANGED
@@ -1,9 +1,8 @@
1
- *.swo
2
1
  *.swp
2
+ *.swo
3
3
  .DS_Store
4
4
  .project
5
5
  Gemfile.lock
6
- Guardfile
7
6
  *.gem
8
7
  /tmp
9
8
  /spec/files/xls_out.xls
@@ -0,0 +1,2 @@
1
+ AsciiComments:
2
+ Enabled: false
data/Gemfile CHANGED
@@ -8,4 +8,6 @@ group :development do
8
8
  gem 'libnotify'
9
9
  gem 'guard'
10
10
  gem 'guard-rspec'
11
+ gem 'rubocop'
12
+ gem 'guard-rubocop'
11
13
  end
@@ -0,0 +1,51 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard :rspec do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+
9
+ # Rails example
10
+ watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
11
+ watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
12
+ watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
13
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
14
+ watch('config/routes.rb') { "spec/routing" }
15
+ watch('app/controllers/application_controller.rb') { "spec/controllers" }
16
+
17
+ # Capybara features specs
18
+ watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
19
+
20
+ # Turnip features and steps
21
+ watch(%r{^spec/acceptance/(.+)\.feature$})
22
+ watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
23
+ end
24
+
25
+
26
+ guard :rspec do
27
+ watch(%r{^spec/.+_spec\.rb$})
28
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
29
+ watch('spec/spec_helper.rb') { "spec" }
30
+
31
+ # Rails example
32
+ watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
33
+ watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
34
+ watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
35
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
36
+ watch('config/routes.rb') { "spec/routing" }
37
+ watch('app/controllers/application_controller.rb') { "spec/controllers" }
38
+
39
+ # Capybara features specs
40
+ watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
41
+
42
+ # Turnip features and steps
43
+ watch(%r{^spec/acceptance/(.+)\.feature$})
44
+ watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
45
+ end
46
+
47
+
48
+ guard :rubocop do
49
+ watch(%r{.+\.rb$})
50
+ watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) }
51
+ end
@@ -1,9 +1,10 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'gen_sheet'
3
- s.version = '0.0.4'
4
- s.summary = "A spreadsheet generator (ODS, XLS) for Roo."
5
- s.description = "Takes a Roo spreadsheet object and renders it in XLS or ODS. Also allows you to use a template sheet and fill it with data from Roo, then output a rendered sheet."
6
- s.authors = ["Rei Kagetsuki"]
3
+ s.version = '0.1.0'
4
+ s.summary = "A spreadsheet generator (ODS, XLS) and parsing tool. Uses Roo as a backend and attempts to implement newer features on top of it."
5
+ s.description = "A spreadsheet generator (ODS, XLS) and parsing tool. Uses Roo as a backend and attempts to implement newer features on top of it."
6
+ s.authors = ["Rei Kagetsuki", "Rika Yoshida"]
7
+ s.license = "GNU GPL version 3"
7
8
  s.email = 'zero@genshin.org'
8
9
  s.files = `git ls-files`.split("\n")
9
10
  s.homepage = 'https://github.com/Genshin/GenSheet'
@@ -1,167 +1,11 @@
1
1
  require 'roo'
2
- require 'writeexcel'
3
- require 'odf/spreadsheet'
2
+ require 'GenSheetExporters'
4
3
 
5
4
  class GenSheet
6
-
7
- @roo
8
-
9
- def to_xls(filename)
10
- @outbook_xls = WriteExcel.new(filename)
11
-
12
- workbook = @roo.instance_variable_get('@workbook')
13
- formats = workbook.instance_variable_get('@formats')
14
- worksheets = workbook.instance_variable_get('@worksheets')
15
-
16
- # 出力シート準備、元シート分解
17
- outsheets = Array.new
18
- originalsheets = Array.new
19
- names = Array.new
20
- pre_sheet_xls(outsheets, originalsheets, names)
21
-
22
- # mergeしてあるセルのセット
23
- merges = Array.new
24
- set_mergedcell_sheet(worksheets, outsheets, merges)
25
-
26
- # シートのセット
27
- set_sheet_xls(outsheets, originalsheets, names, merges)
28
-
29
- # # 出力
30
- # for i in 0..originalsheets.size - 1
31
- # originalsheets[i].parse do |row|
32
- # puts row
33
- # end
34
- # end
35
-
36
- @outbook_xls.close
37
- end
38
-
39
- def pre_sheet_xls(outsheets, originalsheets, names)
40
- @roo.each_with_pagename do |name, sheet|
41
- outsheets << @outbook_xls.add_worksheet(name)
42
- originalsheets << sheet.clone
43
- names << name
44
- end
45
- end
46
-
47
- def set_mergedcell_sheet(worksheets, outsheets, merges)
48
- for i in 0..worksheets.size - 1
49
- merges << worksheets[i].instance_variable_get('@merged_cells')
50
- if merges[i] != nil && merges[i] != []
51
- set_mergedcell(outsheets[i], merges[i])
52
- end
53
- end
54
- end
55
-
56
- def set_mergedcell(outsheet, merge)
57
- format = @outbook_xls.add_format(:align => 'merge')
58
- for j in 0..merge.size - 1
59
- outsheet.merge_range(merge[j][0], merge[j][2], merge[j][1], merge[j][3], '', format)
60
- end
61
- end
62
-
63
- def set_sheet_xls(outsheets, originalsheets, names, merges)
64
- #@getformat = @formats[(x + 1) * (y + 1) - 1] # fontもborderも入ってるけどもインデックスがわからない
65
- fonts = @roo.instance_variable_get('@fonts')
66
- for i in 0..originalsheets.size - 1
67
- originalsheets[i].each_with_index do |row, y|
68
- row.each_with_index do |cell, x|
69
- font = fonts[names[i]][[y + 1, x + 1]]
70
- set_cell_xls(outsheets[i], cell, x, y, font, merges[i])
71
- end
72
- end
5
+ class << self
6
+ def open(file)
7
+ sheet =Roo::Spreadsheet.open(file)
8
+ sheet.extend GenSheetExporters
73
9
  end
74
10
  end
75
-
76
- def set_cell_xls(outsheet, cell, x, y, font, merge)
77
- # cellが空の場合は何もしない
78
- return if cell == nil
79
-
80
- # 各フォントフォーマットのセット
81
- format = set_format(font)
82
-
83
- # mergeしてあるセルの場合フォーマット追加
84
- for i in 0..merge.size - 1
85
- if y == merge[i][0] && x == merge[i][2]
86
- set_mergedcell_format(format)
87
- end
88
- end
89
-
90
- outsheet.write(y, x, cell, format)
91
- end
92
-
93
- def set_format(font)
94
- format = @outbook_xls.add_format(
95
- #:bottom => 1, #
96
- #:top => 1, # border
97
- #:left => 1, #
98
- #:right => 1, #
99
- :color => font.instance_variable_get('@color'),
100
- :italic => font.instance_variable_get('@italic') ? 1 : 0,
101
- :font => font.instance_variable_get('@name'),
102
- :outline => font.instance_variable_get('@outline'),
103
- :shadow => font.instance_variable_get('@shadow'),
104
- :size => font.instance_variable_get('@size'),
105
- :strikeout => font.instance_variable_get('@strikeout'),
106
- :underline => font..instance_variable_get('@underline') == :none ? 0 : 1, # アンダーラインの種類は4つだけどとりあえず
107
- :bold => font.instance_variable_get('@weight') > 400 ? 1 : 0 # weightが普通だと400、boldだと700になるようなのでとりあえず
108
- #:encoding => font.encoding, #
109
- #:escapement => font.escapement, # fontにまとめて入っていたけど
110
- #:family => font.family, # どれに対応するのか..
111
- #:previous_fast_key => font.previous_fast_key, #
112
- )
113
-
114
- return format
115
- end
116
-
117
- def set_mergedcell_format(format)
118
- format.set_align('center')
119
- format.set_valign('vcenter')
120
- end
121
-
122
- def to_ods(filename)
123
- @outbook_ods = ODF::SpreadSheet.new
124
-
125
- tables = Array.new
126
- sheets = Array.new
127
- pre_sheet_ods(tables, sheets)
128
-
129
- @outbook_ods.write_to filename
130
- end
131
-
132
- def pre_sheet_ods(tables, sheets)
133
- @roo.each_with_pagename do |name, sheet|
134
- # シート作成
135
- tables << (@outbook_ods.table name)
136
- sheets << sheet.clone
137
- end
138
-
139
- set_sheet_ods(tables, sheets)
140
- end
141
-
142
- def set_sheet_ods(tables, sheets)
143
- for i in 0..sheets.size - 1
144
- sheets[i].each_with_index do |row, y|
145
- # 行作成
146
- ob_row = tables[i].row
147
- set_cell_ods(row, ob_row)
148
- end
149
- end
150
- end
151
-
152
- def set_cell_ods(row, ob_row)
153
- row.each_with_index do |cell, x|
154
- # スタイル作成
155
- @outbook_ods.style 'font-style', :family => :cell do
156
- #property :text, 'font-weight' => 'bold', 'color' => '#ff0000'
157
- end
158
- # セル作成、スタイル適用
159
- ob_cell = ob_row.cell(cell, :style => 'font-style')
160
- end
161
- end
162
-
163
- def initialize(roo)
164
- @roo = roo
165
- end
166
-
167
11
  end
@@ -0,0 +1,148 @@
1
+ require 'writeexcel'
2
+ require 'odf/spreadsheet'
3
+
4
+ module GenSheetExporters
5
+ def to_ods(filename = nil)
6
+ ods = ODF::SpreadSheet.new
7
+ _workbook_to_ods(ods)
8
+ ods.write_to(filename) unless filename.nil?
9
+ return ods
10
+ end
11
+
12
+ def to_xls(filename = nil)
13
+ xls = WriteExcel.new(filename)
14
+
15
+ # 出力シート準備、元シート分解
16
+ outsheets, originalsheets, names = [], [], []
17
+ _workbook_to_xls(xls, outsheets, originalsheets, names)
18
+
19
+ # mergeしてあるセルのセット
20
+ merges = []
21
+ _set_sheet_mergedcells(xls, outsheets, merges)
22
+
23
+ # シートのセット
24
+ _set_cell_formating(xls, outsheets, originalsheets, names, merges)
25
+
26
+ xls.close
27
+ return xls
28
+ end
29
+
30
+ private
31
+
32
+ def _workbook_to_ods(ods)
33
+ tables, sheets = [], []
34
+ self.each_with_pagename do |name, sheet|
35
+ # シート作成
36
+ tables << (ods.table name)
37
+ sheets << sheet.clone
38
+ end
39
+
40
+ _set_ods_sheets(ods, tables, sheets)
41
+ return ods
42
+ end
43
+
44
+ def _set_ods_sheets(ods, tables, sheets)
45
+ for i in 0..sheets.size - 1
46
+ sheets[i].each_with_index do |row, y|
47
+ # 行作成
48
+ ob_row = tables[i].row
49
+ _set_cell_ods(ods, row, ob_row)
50
+ end
51
+ end
52
+ end
53
+
54
+ def _set_cell_ods(ods, row, ob_row)
55
+ row.each_with_index do |cell, x|
56
+ # スタイル作成
57
+ ods.style 'font-style', family: :cell do
58
+ # property :text, 'font-weight' => 'bold', 'color' => '#ff0000'
59
+ end
60
+ # セル作成、スタイル適用
61
+ ob_row.cell(cell, style: 'font-style')
62
+ end
63
+ end
64
+
65
+ def _workbook_to_xls(xls, outsheets, originalsheets, names)
66
+ self.each_with_pagename do |name, sheet|
67
+ outsheets << xls.add_worksheet(name)
68
+ originalsheets << sheet.clone
69
+ names << name
70
+ end
71
+ end
72
+
73
+ def _set_sheet_mergedcells(xls, outsheets, merges)
74
+ worksheets = @workbook.instance_variable_get('@worksheets')
75
+ for i in 0..worksheets.size - 1
76
+ merges << worksheets[i].instance_variable_get('@merged_cells')
77
+ if merges[i] != nil && merges[i] != []
78
+ _set_mergedcell(xls, outsheets[i], merges[i])
79
+ end
80
+ end
81
+ end
82
+
83
+ def _set_mergedcell(xls, outsheet, merge)
84
+ format = xls.add_format(align: 'merge')
85
+ for j in 0..merge.size - 1
86
+ outsheet.merge_range(merge[j][0], merge[j][2],
87
+ merge[j][1], merge[j][3], '', format)
88
+ end
89
+ end
90
+
91
+ def _set_cell_formating(xls, outsheets, originalsheets, names, merges)
92
+ # fontもborderも入ってるけどもインデックスがわからない
93
+ for i in 0..originalsheets.size - 1
94
+ originalsheets[i].each_with_index do |row, y|
95
+ row.each_with_index do |cell, x|
96
+ font = @fonts[names[i]][[y + 1, x + 1]]
97
+ _set_cell_xls(xls, outsheets[i], cell, x, y, font, merges[i])
98
+ end
99
+ end
100
+ end
101
+ end
102
+
103
+ def _set_cell_xls(xls, outsheet, cell, x, y, font, merge)
104
+ # cellが空の場合は何もしない
105
+ return if cell == nil
106
+
107
+ # 各フォントフォーマットのセット
108
+ format = _set_format(xls, font)
109
+
110
+ # mergeしてあるセルの場合フォーマット追加
111
+ for i in 0..merge.size - 1
112
+ set_mergedcell_format(format) if y == merge[i][0] && x == merge[i][2]
113
+ end
114
+
115
+ outsheet.write(y, x, cell, format)
116
+ end
117
+
118
+ def _set_format(xls, font)
119
+ format = xls.add_format(
120
+ # :bottom => 1, #
121
+ # :top => 1, # border
122
+ # :left => 1, #
123
+ # :right => 1, #
124
+ color: font.instance_variable_get('@color'),
125
+ italic: font.instance_variable_get('@italic') ? 1 : 0,
126
+ font: font.instance_variable_get('@name'),
127
+ outline: font.instance_variable_get('@outline'),
128
+ shadow: font.instance_variable_get('@shadow'),
129
+ size: font.instance_variable_get('@size'),
130
+ strikeout: font.instance_variable_get('@strikeout'),
131
+ # アンダーラインの種類は4つだけどとりあえず
132
+ underline: font..instance_variable_get('@underline') == :none ? 0 : 1,
133
+ # weightが普通だと400、boldだと700になるようなのでとりあえず
134
+ bold: font.instance_variable_get('@weight') > 400 ? 1 : 0
135
+ # :encoding => font.encoding, #
136
+ # :escapement => font.escapement, # fontにまとめて入っていたけど
137
+ # :family => font.family, # どれに対応するのか..
138
+ # :previous_fast_key => font.previous_fast_key, #
139
+ )
140
+
141
+ return format
142
+ end
143
+
144
+ def set_mergedcell_format(format)
145
+ format.set_align('center')
146
+ format.set_valign('vcenter')
147
+ end
148
+ end
@@ -1,20 +1,13 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe 'open ods with roo' do
4
- it 'opens and inspects an xls file' do
3
+ describe 'opens an ods file' do
4
+ it 'opens and inspects an ods file' do
5
5
  open_ods()
6
6
  end
7
7
  end
8
8
 
9
- describe '#new' do
10
- it 'creates a new GenSheet object from Roo ODS' do
11
- create_gens_from_ods()
12
- end
13
- end
14
-
15
- describe '#to_ods' do
9
+ describe 'ods #to_ods' do
16
10
  it 'creates an ods file' do
17
- create_gens_from_ods()
18
- @gens.to_ods('./spec/files/ods_out.ods')
11
+ open_ods().to_ods('./spec/files/ods_out.ods')
19
12
  end
20
13
  end
@@ -1,8 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe '#to_xls' do
3
+ describe 'ods #to_xls' do
4
4
  it 'creates an xls file from an ods base' do
5
- create_gens_from_ods()
6
- @gens.to_xls('./spec/files/ods_out.xls')
5
+ open_ods().to_xls('./spec/files/ods_out.xls')
7
6
  end
8
7
  end
@@ -1,26 +1,13 @@
1
- require 'roo'
2
1
  require_relative '../lib/GenSheet.rb'
3
2
 
4
- @xls
5
- @ods
6
- @gens
7
-
8
- def open_xls()
9
- @xls = Roo::Spreadsheet.open('./spec/files/template.xls')
10
- @xls.inspect
11
- end
12
-
13
- def open_ods()
14
- @ods = Roo::Spreadsheet.open('./spec/files/template.ods')
15
- @ods.inspect
16
- end
17
-
18
- def create_gens_from_xls()
19
- open_xls()
20
- @gens = GenSheet.new(@xls)
3
+ def open_xls
4
+ xls = GenSheet.open('./spec/files/template.xls')
5
+ xls.inspect
6
+ return xls
21
7
  end
22
8
 
23
- def create_gens_from_ods()
24
- open_ods()
25
- @gens = GenSheet.new(@ods)
9
+ def open_ods
10
+ ods = GenSheet.open('./spec/files/template.ods')
11
+ ods.inspect
12
+ return ods
26
13
  end
@@ -1,8 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe '#to_ods' do
3
+ describe 'xls #to_ods' do
4
4
  it 'creates an ods file from an xls base' do
5
- create_gens_from_xls()
6
- @gens.to_ods('./spec/files/xls_out.ods')
5
+ open_xls().to_ods('./spec/files/xls_out.ods')
7
6
  end
8
7
  end
@@ -1,20 +1,13 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe 'open xls with roo' do
3
+ describe 'opens an xls file' do
4
4
  it 'opens and inspects an xls file' do
5
5
  open_xls()
6
6
  end
7
7
  end
8
8
 
9
- describe '#new' do
10
- it 'creates a new GenSheet object from Roo XLS' do
11
- create_gens_from_xls()
12
- end
13
- end
14
-
15
- describe '#to_xls' do
9
+ describe 'xls #to_xls' do
16
10
  it 'creates an xls file' do
17
- create_gens_from_xls()
18
- @gens.to_xls('./spec/files/xls_out.xls')
11
+ open_xls().to_xls('./spec/files/xls_out.xls')
19
12
  end
20
13
  end
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gen_sheet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rei Kagetsuki
8
+ - Rika Yoshida
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2013-05-24 00:00:00.000000000 Z
12
+ date: 2013-07-03 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: roo
@@ -52,20 +53,22 @@ dependencies:
52
53
  - - '>='
53
54
  - !ruby/object:Gem::Version
54
55
  version: '0'
55
- description: Takes a Roo spreadsheet object and renders it in XLS or ODS. Also allows
56
- you to use a template sheet and fill it with data from Roo, then output a rendered
57
- sheet.
56
+ description: A spreadsheet generator (ODS, XLS) and parsing tool. Uses Roo as a backend
57
+ and attempts to implement newer features on top of it.
58
58
  email: zero@genshin.org
59
59
  executables: []
60
60
  extensions: []
61
61
  extra_rdoc_files: []
62
62
  files:
63
63
  - .gitignore
64
+ - .rubocop.yml
64
65
  - Gemfile
66
+ - Guardfile
65
67
  - README.md
66
68
  - Rakefile
67
69
  - gen_sheet.gemspec
68
70
  - lib/GenSheet.rb
71
+ - lib/GenSheetExporters.rb
69
72
  - spec/files/template.ods
70
73
  - spec/files/template.xls
71
74
  - spec/ods_ods_spec.rb
@@ -74,7 +77,8 @@ files:
74
77
  - spec/xls_ods_spec.rb
75
78
  - spec/xls_xls_spec.rb
76
79
  homepage: https://github.com/Genshin/GenSheet
77
- licenses: []
80
+ licenses:
81
+ - GNU GPL version 3
78
82
  metadata: {}
79
83
  post_install_message:
80
84
  rdoc_options: []
@@ -92,8 +96,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
92
96
  version: '0'
93
97
  requirements: []
94
98
  rubyforge_project:
95
- rubygems_version: 2.0.0.rc.2
99
+ rubygems_version: 2.0.3
96
100
  signing_key:
97
101
  specification_version: 4
98
- summary: A spreadsheet generator (ODS, XLS) for Roo.
102
+ summary: A spreadsheet generator (ODS, XLS) and parsing tool. Uses Roo as a backend
103
+ and attempts to implement newer features on top of it.
99
104
  test_files: []