axlsx_report 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 45c3786fefc932fcf9f891788cfb0c3fcf4d885d
4
+ data.tar.gz: 681f81d9bb9042f0da7200688d80229e368574d1
5
+ SHA512:
6
+ metadata.gz: 9b7f8e17f841fce40e7d0fdf4f687e9b3ffbd8583a3846eb0ce456ef1e8929ddf2ae536a45ba768cf87bce7f0df5174dd20e1a06677c5b36b28cfdf55e9fe837
7
+ data.tar.gz: 7f973dd5e6d1a139e46274c2570c8ac89990f6255c45067d146689e3fda510a9d34a6d4584c3e8ed64254687ae39384abf55e9e87834bef64e3fb67d47fa05de
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ /*.xlsx
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in axlsx_report.gemspec
4
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Alexey Volochnev
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,55 @@
1
+ # AxlsxReport
2
+
3
+ Declarative excel reports based on [axlsx](https://github.com/randym/axlsx).
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'axlsx_report'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install axlsx_report
20
+
21
+ ## Usage
22
+
23
+ ```ruby
24
+ require 'axlsx_report'
25
+
26
+ class BaseReport < AxlsxReport::Base
27
+ column 'Number' do |i|
28
+ i
29
+ end
30
+
31
+ column 'Square' do |i|
32
+ i * i
33
+ end
34
+ end
35
+
36
+ report = BaseReport.new
37
+
38
+ (1..10).each do |i|
39
+ report << i
40
+ end
41
+
42
+ report.save('base_report.xlsx')
43
+ ```
44
+
45
+ Find more examples in examples folder.
46
+
47
+ ## Contributing
48
+
49
+ Bug reports and pull requests are welcome on GitHub at https://github.com/avolochnev/axlsx_report.
50
+
51
+
52
+ ## License
53
+
54
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
55
+
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
Binary file
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'axlsx_report/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "axlsx_report"
8
+ spec.version = AxlsxReport::VERSION
9
+ spec.authors = ["Alexey Volochnev"]
10
+ spec.email = ["alexey.volochnev@gmail.com"]
11
+
12
+ spec.summary = %q{Declarative excel reports based on axlsx.}
13
+ spec.homepage = "https://github.com/avolochnev/axlsx_report"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.require_paths = ["lib"]
18
+
19
+ spec.add_runtime_dependency 'axlsx', '~> 2.0', '>= 2.0.1'
20
+ spec.add_development_dependency "bundler", "~> 1.11"
21
+ spec.add_development_dependency "rake", "~> 10.0"
22
+ spec.add_development_dependency "rspec", "~> 3.0"
23
+ spec.add_development_dependency 'roo', '~> 1.13', '>= 1.13.2'
24
+ end
@@ -0,0 +1,21 @@
1
+ $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
2
+
3
+ require 'axlsx_report'
4
+
5
+ class BaseReport < AxlsxReport::Base
6
+ column 'Integer' do |i|
7
+ i
8
+ end
9
+
10
+ column 'Square' do |i|
11
+ i * i
12
+ end
13
+ end
14
+
15
+ if __FILE__ == $0
16
+ report = BaseReport.new
17
+ (1..10).each { |i| report << i }
18
+ report.save('base_report.xlsx')
19
+ end
20
+
21
+
@@ -0,0 +1,28 @@
1
+ $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
2
+
3
+ require 'axlsx_report'
4
+
5
+ class GroupReport < AxlsxReport::Base
6
+ column 'Integer' do |i|
7
+ i
8
+ end
9
+
10
+ # Define group of columns with merged group header
11
+ group 'Calculations' do
12
+ column 'Square' do |i|
13
+ i * i
14
+ end
15
+
16
+ column 'Sqrt' do |i|
17
+ Math.sqrt(i)
18
+ end
19
+ end
20
+ end
21
+
22
+ if __FILE__ == $0
23
+ report = GroupReport.new
24
+ (1..10).each { |i| report << i }
25
+ report.save('group_report.xlsx')
26
+ end
27
+
28
+
@@ -0,0 +1,18 @@
1
+ $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
2
+
3
+ require 'axlsx_report'
4
+
5
+ class LambdaReport < AxlsxReport::Base
6
+ # proc without params called in context of given object
7
+ column 'Integer', -> { self }
8
+ column 'Odd?', -> { odd? }, width: 7
9
+ column 'Even?', -> { even? }, width: 7
10
+ end
11
+
12
+ if __FILE__ == $0
13
+ report = LambdaReport.new
14
+ (1..10).each { |i| report << i }
15
+ report.save('lambda_report.xlsx')
16
+ end
17
+
18
+
@@ -0,0 +1,21 @@
1
+ $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
2
+
3
+ require 'axlsx_report'
4
+
5
+ class WidthReport < AxlsxReport::Base
6
+ column 'Integer', width: 20 do |i|
7
+ i
8
+ end
9
+
10
+ column 'Square', width: 20 do |i|
11
+ i * i
12
+ end
13
+ end
14
+
15
+ if __FILE__ == $0
16
+ report = WidthReport.new
17
+ (1..10).each { |i| report << i }
18
+ report.save('width_report.xlsx')
19
+ end
20
+
21
+
@@ -0,0 +1,5 @@
1
+ require 'axlsx_report/version'
2
+ require 'axlsx_report/base'
3
+
4
+ module AxlsxReport
5
+ end
@@ -0,0 +1,355 @@
1
+ require 'axlsx'
2
+ require_relative 'column_name_conv'
3
+ require_relative 'group'
4
+ require_relative 'column'
5
+
6
+ module AxlsxReport
7
+ class Base
8
+ include ColumnNameConv
9
+
10
+ # Creates new report.
11
+ # By default creates own Axlsx::Package.
12
+ # @param [Axlsx::Package] package - provide existing package to add report sheet to combined document.
13
+ def initialize(package = nil)
14
+ @package = package || Axlsx::Package.new
15
+ end
16
+
17
+ # Define report column.
18
+ #
19
+ # Usage:
20
+ # Human = Struct.new(:first_name, :last_name, :birthday)
21
+ # class Report < AxlsxReport::Base
22
+ # # calculate column value with block:
23
+ # column 'First Name', width: 10 do |human|
24
+ # human.first_name
25
+ # end
26
+ # # or lambda in context of given object
27
+ # column 'Last Name', -> { last_name }, width: 15
28
+ # # or chagne context using with:
29
+ # column 'Age', -> { Date.today.year - year }, with: :birthday
30
+ # end
31
+ #
32
+ # @see Column#initialize for options description
33
+ #
34
+ # @param [String] name - column header
35
+ # @param [Proc] callable - use proc or lambda instead of block to get cell value. Optional.
36
+ # @param [Hash] options - last param,
37
+ # @param block
38
+ # args: callable = nil, options = {}
39
+ def self.column(col_name, *args, &block)
40
+ @columns ||= []
41
+ options =
42
+ if args.last.is_a? Hash
43
+ args.pop
44
+ else
45
+ {}
46
+ end
47
+ options[:group] = @current_group if @current_group
48
+ callable = args.first || block
49
+ @columns << Column.new(col_name, callable, options)
50
+ end
51
+
52
+ # Define group of columns
53
+ #
54
+ # Usage:
55
+ # Human = Struct.new(:first_name, :last_name, :birthday)
56
+ # class Report < AxlsxReport::Base
57
+ # group 'Name' do
58
+ # column 'First', &:first_name
59
+ # column 'Last', &:last_name
60
+ # end
61
+ # column 'Birthday', &:birthday
62
+ # end
63
+ #
64
+ # @param [String] name group name
65
+ def self.group(name, &block)
66
+ @columns ||= []
67
+ unless @groups
68
+ @groups = []
69
+ define_method :groups do
70
+ self.class.instance_eval { @groups }
71
+ end
72
+ end
73
+ raise 'Nested groups are not implemented yet' if @current_group
74
+ @current_group = Group.new(name, @columns.length)
75
+ @groups << @current_group
76
+ instance_exec(&block)
77
+ @current_group.end_index = @columns.length - 1
78
+ @current_group = nil
79
+ end
80
+
81
+ # Define group row height.
82
+ # Used if any groups are defiend. Autoheight is used by default
83
+ # @param [Integer] num group row height
84
+ def self.group_height(num)
85
+ define_method(:group_height) { num }
86
+ end
87
+
88
+ # Define head row height.
89
+ # Autoheight is used by default
90
+ # @param [Integer] num head row height
91
+ def self.head_height(num)
92
+ define_method(:head_height) { num }
93
+ end
94
+
95
+ # Add 1,2,3...N row below head row
96
+ def self.numerate_columns
97
+ define_method(:numerate_columns) { true }
98
+ end
99
+
100
+ # Define sheet name.
101
+ #
102
+ # @param [String] name (nil) static sheet name.
103
+ # @param block dinamic sheet name (if given)
104
+ def self.sheet_name(name = nil, &block)
105
+ if block_given?
106
+ define_method(:sheet_name, &block)
107
+ else
108
+ define_method(:sheet_name) { name }
109
+ end
110
+ end
111
+
112
+ # Add row to the report.
113
+ # @param [Any] obj object providing the data for columns
114
+ def <<(obj)
115
+ row = columns.map { |column| column.value(self, obj) }
116
+ add_totals row
117
+ sheet.add_row row, row_options
118
+ end
119
+
120
+ # Returns sheet name.
121
+ #
122
+ # May be overriden to provide custom sheet name
123
+ # @see Base.sheet_name
124
+ def sheet_name
125
+ 'Sheet1'
126
+ end
127
+
128
+ # def run(file = nil, enum = nil)
129
+ # file = file_name unless file
130
+ # enum = enumerator if enum.nil? && !block_given?
131
+ # if enum
132
+ # enum.each do |obj|
133
+ # self << obj
134
+ # end
135
+ # elsif block_given?
136
+ # yield self
137
+ # else
138
+ # raise 'No block or enum given. Use #new -> << -> #save for generating report later'
139
+ # end
140
+ # save(file)
141
+ # end
142
+
143
+ # def self.[](*args)
144
+ # new.run(*args)
145
+ # end
146
+
147
+ # Save xlsx file with provided data
148
+ # @param [String] file File name the data to be serialized
149
+ def save(file)
150
+ done
151
+ begin
152
+ @package.serialize(file)
153
+ rescue Errno::EACCES => e
154
+ puts "#{file} is protected!"
155
+ file = file + ".tmp"
156
+ @package.serialize(file)
157
+ end
158
+ end
159
+
160
+ # Finalize document formatting after data collecting and before saving.
161
+ # @note Called during #save.
162
+ # @note Don't call twice. Don't call before all data provided.
163
+ def done
164
+ apply_width(sheet)
165
+ merge_same(sheet)
166
+ sheet.add_row(@totals) if @totals
167
+ end
168
+
169
+ # Axlsx sheet.
170
+ # @return [Axlsx::Worksheet]
171
+ def sheet
172
+ @sheet ||= init_sheet(sheet_name)
173
+ end
174
+
175
+ private
176
+
177
+ def columns
178
+ self.class.instance_eval { @columns }
179
+ end
180
+
181
+ def init_sheet(name = 'Sheet1')
182
+ sheet = @package.workbook.add_worksheet(:name => sheetify_name(name))
183
+ if self.respond_to? :title
184
+ if title.is_a? Array
185
+ title.each do |t|
186
+ sheet.add_row [t]
187
+ end
188
+ else
189
+ sheet.add_row [title]
190
+ end
191
+ end
192
+ if defined? groups
193
+ add_group_head sheet
194
+ else
195
+ add_head sheet, *columns.map{ |col| eval_name(col.name) }
196
+ sheet.rows.last.height = head_height if defined? head_height
197
+ end
198
+ if defined? numerate_columns
199
+ add_frozen_head sheet, *(1..(columns.length)).to_a
200
+ else
201
+ froze(sheet, sheet.rows.count)
202
+ auto_filter(sheet)
203
+ end
204
+ @header_rows = sheet.rows.count
205
+ sheet
206
+ end
207
+
208
+ def auto_filter(sheet)
209
+ sheet.auto_filter = Axlsx::cell_range(sheet.rows.last.cells, false)
210
+ end
211
+
212
+ def apply_width(sheet)
213
+ sheet.column_widths *columns.map(&:width).map { |width| width || default_column_width }
214
+ end
215
+
216
+ def merge_same(sheet)
217
+ columns.map(&:options).each_with_index do |ops, col_num|
218
+ next unless ops[:merge_same]
219
+ merged_style ||= sheet.styles.add_style(:alignment => { :vertical => :center })
220
+ col_char = column_num_to_name(col_num + 1)
221
+ last, start_row = nil, 0
222
+ sheet.rows.dup.each_with_index do |row, row_num|
223
+ next if row_num < @header_rows
224
+ col_value = row.cells[col_num].value
225
+ if last && last != col_value && (row_num - start_row) > 1
226
+ range = "#{col_char}#{start_row + 1}:#{col_char}#{row_num}"
227
+ sheet.merge_cells(range)
228
+ sheet[range].each { |c| c.style = merged_style }
229
+ end
230
+ if last != col_value
231
+ last = col_value
232
+ start_row = row_num
233
+ end
234
+ end
235
+ if last && (sheet.rows.length - start_row) > 1
236
+ range = "#{col_char}#{start_row + 1}:#{col_char}#{sheet.rows.length}"
237
+ sheet.merge_cells(range)
238
+ sheet[range].each { |c| c.style = merged_style }
239
+ end
240
+ end
241
+ end
242
+
243
+ def default_column_width
244
+ 16
245
+ end
246
+
247
+ def add_group_head(sheet)
248
+ head_row = *columns.map{ |col| eval_name(col.name) }
249
+ groups.each { |g| head_row[g.start_index] = g.name }
250
+ add_head sheet, *head_row
251
+ group_row = sheet.rows.length
252
+ groups.map { |g| "#{column_num_to_name(g.start_index + 1)}#{group_row}:#{column_num_to_name(g.end_index + 1)}#{group_row}" }
253
+ .each { |rng| sheet.merge_cells(rng) }
254
+ sheet.rows.last.height = group_height if defined? group_height
255
+ add_head sheet, *columns.map{ |col| eval_name(col.name) }
256
+ sheet.rows.last.height = head_height if defined? head_height
257
+ names_row = sheet.rows.length
258
+ units = *columns.map(&:units)
259
+ has_units = !units.all?(&:nil?)
260
+ if has_units
261
+ add_head sheet, *units
262
+ end
263
+ units_row = sheet.rows.length
264
+ columns.map(&:options).each_with_index do |ops, index|
265
+ row_name = column_num_to_name(index + 1)
266
+ case
267
+ when ops[:units] && ops[:group]
268
+ nil
269
+ when ops[:group]
270
+ sheet.merge_cells("#{row_name}#{names_row}:#{row_name}#{units_row}") if has_units
271
+ when ops[:units]
272
+ sheet.merge_cells("#{row_name}#{group_row}:#{row_name}#{names_row}")
273
+ else
274
+ sheet.merge_cells("#{row_name}#{group_row}:#{row_name}#{units_row}")
275
+ end
276
+ end
277
+ end
278
+
279
+ def add_totals(row)
280
+ return unless total_actions
281
+ @totals ||= [nil] * columns.length
282
+ total_actions.each_with_index do |action, index|
283
+ case action
284
+ when String
285
+ @totals[index] = action
286
+ when :sum
287
+ if row[index]
288
+ @totals[index] ||= 0.0
289
+ @totals[index] += row[index]
290
+ end
291
+ when :count
292
+ if row[index]
293
+ @totals[index] ||= 0
294
+ @totals[index] += 1
295
+ end
296
+ when Proc
297
+ @totals[index] = action[row]
298
+ end
299
+ end
300
+ end
301
+
302
+ def total_actions
303
+ @total_actions ||=
304
+ columns.map(&:options).each do |ops|
305
+ ops[:total]
306
+ end
307
+ end
308
+
309
+ def eval_name(name)
310
+ name.is_a?(Proc) ? instance_exec(&name) : name
311
+ end
312
+
313
+ def sheetify_name(name)
314
+ name.gsub('/', '_')[0..30]
315
+ end
316
+
317
+ def add_head(sheet, *header)
318
+ row = nil
319
+ sheet.workbook.styles do |s|
320
+ head_style = s.add_style :border => { :style => :thin, :color => "00" },
321
+ :alignment => { :horizontal => :center,
322
+ :vertical => :center ,
323
+ :wrap_text => true}
324
+ row = sheet.add_row header, style: head_style
325
+ end
326
+ row
327
+ end
328
+
329
+ def add_frozen_head(sheet, *header)
330
+ row = add_head(sheet, *header)
331
+ froze(sheet, sheet.rows.count)
332
+ sheet.auto_filter = Axlsx::cell_range(row.cells, false)
333
+ end
334
+
335
+ def separate_sheet(sheet, sheet_name = 'Sheet2', &block)
336
+ sheet.workbook.add_worksheet(name: sheet_name) { |sheet| yield sheet }
337
+ end
338
+
339
+ def froze(sheet, num_rows = 2)
340
+ sheet.sheet_view do |vs|
341
+ vs.pane do |pane|
342
+ pane.state = :frozen
343
+ pane.y_split = num_rows
344
+ end
345
+ end
346
+ end
347
+
348
+ def row_options
349
+ options = {}
350
+ types = columns.map { |c| c.options[:type] }
351
+ options[:types] = types unless types.all?(&:nil?)
352
+ options
353
+ end
354
+ end
355
+ end
@@ -0,0 +1,55 @@
1
+ module AxlsxReport
2
+ # Report's column representation
3
+ class Column
4
+ attr_reader :name, :callable, :options
5
+
6
+ # Creates new column
7
+ #
8
+ # @param [String] name Column name
9
+ # @param [Proc] callable Proc to calculate column value form given object
10
+ # @param [Hash] options ({}) Column parameters
11
+ # @option options [Integer] width: (16) column width
12
+ # @option options [Symbol] transform: report object method to be called after value calculation
13
+ # @option options [Symbol] with: method name of given object to be used to base for cell value calculation
14
+ # @option options [String] units: Units text to be added to the header in the column
15
+ # @option options [Symbol] type: axlsx type to be used in this column. One of Axlsx::Cell::CELL_TYPES
16
+ def initialize(name, callable, options = {})
17
+ @name, @callable, @options = name, callable, options
18
+ end
19
+
20
+ # Quick access to options
21
+ %i{width units}.each do |option|
22
+ define_method(option) do
23
+ @options[option]
24
+ end
25
+ end
26
+
27
+ # Calculates column value for given object
28
+ #
29
+ # @param [AxlsxReport::Base] report Report the value is calculated for
30
+ # @param [Any] obj Source object for column value
31
+ # @return Column value for given object.
32
+ def value(report, obj)
33
+ source = extract_source(obj)
34
+ return nil if source.nil?
35
+ value =
36
+ if callable.arity.zero?
37
+ source.instance_exec &callable
38
+ else
39
+ report.instance_exec source, &callable
40
+ end
41
+ transform = options[:transform]
42
+ value = report.send transform, value if transform
43
+ value
44
+ end
45
+
46
+ private
47
+
48
+ def extract_source(obj)
49
+ with = options[:with]
50
+ return obj unless with
51
+ return nil unless obj.respond_to?(with)
52
+ obj.send(with)
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,32 @@
1
+ module AxlsxReport
2
+ module ColumnNameConv
3
+ extend self
4
+
5
+ # 'Z' => 25
6
+ # 'AA' => 26
7
+ def column_name_to_num(name)
8
+ num = 0
9
+ name.upcase.each_char do |c|
10
+ num *= 26 if num > 0
11
+ add = c.ord - "A".ord + 1
12
+ raise "Invalid symbol in Excel column name: '#{c}'" if add < 1 || add > 26
13
+ num += add
14
+ end
15
+ num - 1
16
+ end
17
+
18
+ # 1 => 'А'
19
+ # 26 => 'Z'
20
+ # 27 => 'AA'
21
+ # 28 => 'АB'
22
+ def column_num_to_name(num)
23
+ name = ""
24
+ while num > 0
25
+ nm = (num - 1) % 26
26
+ num = (num - 1) / 26
27
+ name << ("A".ord + nm).chr
28
+ end
29
+ name.reverse
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,11 @@
1
+ module AxlsxReport
2
+ class Group
3
+ attr_reader :name, :start_index
4
+ attr_accessor :end_index
5
+
6
+ def initialize(name, start_index)
7
+ @name = name
8
+ @start_index = start_index
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module AxlsxReport
2
+ VERSION = "0.1.1"
3
+ end
metadata ADDED
@@ -0,0 +1,144 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: axlsx_report
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Alexey Volochnev
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-10-31 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: axlsx
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 2.0.1
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '2.0'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 2.0.1
33
+ - !ruby/object:Gem::Dependency
34
+ name: bundler
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.11'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '1.11'
47
+ - !ruby/object:Gem::Dependency
48
+ name: rake
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '10.0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '10.0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: rspec
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '3.0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '3.0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: roo
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '1.13'
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: 1.13.2
85
+ type: :development
86
+ prerelease: false
87
+ version_requirements: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - "~>"
90
+ - !ruby/object:Gem::Version
91
+ version: '1.13'
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: 1.13.2
95
+ description:
96
+ email:
97
+ - alexey.volochnev@gmail.com
98
+ executables: []
99
+ extensions: []
100
+ extra_rdoc_files: []
101
+ files:
102
+ - ".gitignore"
103
+ - ".rspec"
104
+ - Gemfile
105
+ - LICENSE.txt
106
+ - README.md
107
+ - Rakefile
108
+ - axlsx_report-0.1.0.gem
109
+ - axlsx_report.gemspec
110
+ - examples/base_report.rb
111
+ - examples/group_report.rb
112
+ - examples/lambda_report.rb
113
+ - examples/width_report.rb
114
+ - lib/axlsx_report.rb
115
+ - lib/axlsx_report/base.rb
116
+ - lib/axlsx_report/column.rb
117
+ - lib/axlsx_report/column_name_conv.rb
118
+ - lib/axlsx_report/group.rb
119
+ - lib/axlsx_report/version.rb
120
+ homepage: https://github.com/avolochnev/axlsx_report
121
+ licenses:
122
+ - MIT
123
+ metadata: {}
124
+ post_install_message:
125
+ rdoc_options: []
126
+ require_paths:
127
+ - lib
128
+ required_ruby_version: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ required_rubygems_version: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ requirements: []
139
+ rubyforge_project:
140
+ rubygems_version: 2.2.5
141
+ signing_key:
142
+ specification_version: 4
143
+ summary: Declarative excel reports based on axlsx.
144
+ test_files: []