rubyexcel 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,54 @@
1
+
2
+ module Excel_Tools
3
+
4
+ require 'win32ole'
5
+
6
+ def get_excel
7
+ excel = WIN32OLE::connect( 'excel.application' ) rescue WIN32OLE::new( 'excel.application' )
8
+ excel.visible = true
9
+ excel
10
+ end
11
+
12
+ def get_workbook( excel=nil )
13
+ excel ||= get_excel
14
+ wb = excel.workbooks.add
15
+ ( ( wb.sheets.count.to_i ) - 1 ).times { |time| wb.sheets(2).delete }
16
+ wb
17
+ end
18
+
19
+ def dump_to_sheet( data, sheet=nil )
20
+ fail ArgumentError, "Invalid data type: #{ data.class }" unless data.is_a?( Array ) || data.is_a?( RubyExcel )
21
+ data = data.to_a if data.is_a? RubyExcel
22
+ sheet ||= get_workbook.sheets(1)
23
+ sheet.range( sheet.cells( 1, 1 ), sheet.cells( data.length, data[0].length ) ).value = data
24
+ sheet
25
+ end
26
+
27
+ def make_sheet_pretty( sheet )
28
+ c = sheet.cells
29
+ c.EntireColumn.AutoFit
30
+ c.HorizontalAlignment = -4108
31
+ c.VerticalAlignment = -4108
32
+ sheet
33
+ end
34
+
35
+ def to_excel
36
+ fail NoMethodError, 'Duplicate sheet name' if self.sheets.count != self.sheets.map(&:name).uniq.length
37
+ wb = get_workbook
38
+ wb.parent.DisplayAlerts = false
39
+ first_time = true
40
+ self.each do |s|
41
+ sht = ( first_time ? wb.sheets(1) : wb.sheets.add( { 'after' => wb.sheets( wb.sheets.count ) } ) ); first_time = false
42
+ sht.name = s.name
43
+ make_sheet_pretty( dump_to_sheet( s.data.all, sht ) )
44
+ end
45
+ wb.sheets(1).select
46
+ wb
47
+ end
48
+
49
+ def save_excel( filename = 'Output.xlsx' )
50
+ filename = Dir.pwd.gsub('/','\\') + '\\' + filename unless filename.include?('\\')
51
+ to_excel.saveas filename
52
+ end
53
+
54
+ end
@@ -0,0 +1,164 @@
1
+ module RubyExcel
2
+
3
+ def self.sample_data
4
+ a=[];8.times{|t|b=[];c='A';5.times{b<<"#{c}#{t+1}";c.next!};a<<b};a
5
+ end
6
+
7
+ def self.sample_sheet
8
+ Workbook.new.load RubyExcel.sample_data
9
+ end
10
+
11
+ class Sheet
12
+
13
+ def +( other )
14
+ dup << other
15
+ end
16
+
17
+ def -( other )
18
+ case other
19
+ when Array
20
+ Workbook.new.load( data.all - other )
21
+ when Sheet
22
+ Workbook.new.load( data.all - other.data.no_headers )
23
+ else
24
+ fail ArgumentError, "Unsupported class: #{ other.class }"
25
+ end
26
+ end
27
+
28
+ def <<( other )
29
+ case other
30
+ when Array
31
+ load( data.all + other, header_rows, header_cols )
32
+ when Sheet
33
+ load( data.all + other.data.no_headers, header_rows, header_cols )
34
+ else
35
+ fail ArgumentError, "Unsupported class: #{ other.class }"
36
+ end
37
+ end
38
+
39
+ def compact!
40
+ data.compact!
41
+ self
42
+ end
43
+
44
+ def empty?
45
+ data.empty?
46
+ end
47
+
48
+ def column_by_header( header )
49
+ Column.new( self, data.colref_by_header( header ) )
50
+ end
51
+ alias ch column_by_header
52
+
53
+ def filter!( ref, &block )
54
+ data.filter!( ref, &block )
55
+ self
56
+ end
57
+
58
+ def sumif( find_header, sum_header )
59
+ col1 = column_by_header( find_header )
60
+ col2 = column_by_header( sum_header )
61
+ total = 0
62
+ col1.each.with_index do |val,idx|
63
+ total += ( ( n = col2[ idx + 1 ] ).is_a?( String ) ? n.to_i : n ) if yield( val ) && idx >= header_rows
64
+ end
65
+ total
66
+ end
67
+
68
+ def uniq!( header )
69
+ data.uniq!( header )
70
+ self
71
+ end
72
+ alias unique! uniq!
73
+
74
+ end
75
+
76
+ class Data
77
+
78
+ def delete( object )
79
+ case object
80
+ when Row
81
+ @data.slice!( object.idx - 1 )
82
+ when Column
83
+ idx = col_index( object.idx ) - 1
84
+ @data.each { |r| r.slice! idx }
85
+ when Element
86
+ addresses = expand( object.address )
87
+ indices = [ address_to_indices( addresses.first.first ), address_to_indices( addresses.last.last ) ].flatten.map { |n| n-1 }
88
+ @data[ indices[0]..indices[2] ].each { |r| r.slice!( indices[1], indices[3] - indices[1] + 1 ) }
89
+ @data.delete_if.with_index { |r,i| r.empty? && i.between?( indices[0], indices[2] ) }
90
+ else
91
+ fail NoMethodError, "#{ object.class } is not supported"
92
+ end
93
+ self
94
+ end
95
+
96
+ def delete_column( ref )
97
+ delete( Column.new( sheet, ref ) )
98
+ end
99
+
100
+ def delete_row( ref )
101
+ delete( Row.new( sheet, ref ) )
102
+ end
103
+
104
+ def delete_range( ref )
105
+ delete( Element.new( sheet, ref ) )
106
+ end
107
+
108
+ def filter!( header )
109
+ hrows = sheet.header_rows
110
+ idx = col_index( hrows > 0 ? colref_by_header( header ) : header )
111
+ @data = @data.select.with_index { |row, i| hrows > i || yield( row[ idx -1 ] ) }
112
+ calc_dimensions
113
+ self
114
+ end
115
+
116
+ def get_columns!( *headers )
117
+ hrow = sheet.header_rows - 1
118
+ ensure_shape
119
+ @data = @data.transpose.select{ |col| headers.include?( col[hrow] ) }
120
+ ensure_shape
121
+ @data = @data.sort_by{ |col| headers.index( col[hrow] ) || col[hrow] }.transpose
122
+ calc_dimensions
123
+ self
124
+ end
125
+
126
+ def uniq!( header )
127
+ column = col_index( colref_by_header( header ) )
128
+ @data = @data.uniq { |row| row[ column - 1 ] }
129
+ self
130
+ end
131
+ alias unique! uniq!
132
+
133
+ end
134
+
135
+ class Section
136
+
137
+ def <<( value )
138
+ if self.is_a? Row
139
+ lastone = ( col_index( idx ) == 1 ? data.cols + 1 : data.cols )
140
+ else
141
+ lastone = ( col_index( idx ) == 1 ? data.rows + 1 : data.rows )
142
+ end
143
+ data[ translate_address( lastone ) ] = value
144
+ end
145
+
146
+ end
147
+
148
+ class Row < Section
149
+
150
+ def getref( header )
151
+ column_id( sheet.row(1).find &/#{header}/ )
152
+ end
153
+
154
+ end
155
+
156
+ class Column < Section
157
+
158
+ end
159
+
160
+ class Element
161
+
162
+ end
163
+
164
+ end
@@ -0,0 +1,348 @@
1
+ module RubyExcel
2
+
3
+ module Address
4
+
5
+ def address_to_col_index( address )
6
+ col_index( column_id( address ) )
7
+ end
8
+
9
+ def address_to_indices( address )
10
+ [ row_id( address ), address_to_col_index( address ) ]
11
+ end
12
+
13
+ def col_index( letter )
14
+ return letter if letter.is_a? Fixnum
15
+ letter !~ /[^A-Z]/ && [1,2,3].include?( letter.length ) or fail ArgumentError, "Invalid column reference: #{ letter }"
16
+ idx, a = 1, 'A'
17
+ loop { return idx if a == letter; idx+=1; a.next! }
18
+ end
19
+
20
+ def col_letter( index )
21
+ return index if index.is_a? String
22
+ index > 0 or fail ArgumentError, 'Indexing is 1-based'
23
+ a = 'A' ; return a if index == 1
24
+ (index - 1).times{ a.next! }; a
25
+ end
26
+
27
+ def column_id( address )
28
+ address[/[A-Z]+/] or fail ArgumentError, "Invalid address: #{ address }"
29
+ end
30
+
31
+ def expand( address )
32
+ return [[address]] unless address.include? ':'
33
+ start_col, end_col, start_row, end_row = [ address[/^[A-Z]+/], address[/(?<=:)[A-Z]+/] ].sort + [ address.match(/(\d+):/).captures.first, address[/\d+$/] ].sort
34
+ (start_row..end_row).map { |r| (start_col..end_col).map { |c| "#{ c }#{ r }" } }
35
+ end
36
+
37
+ def indices_to_address( row_idx, column_idx )
38
+ [ row_idx, column_idx ].all? { |a| a.is_a?( Fixnum ) } or fail ArgumentError, 'Input must be Fixnum'
39
+ col_letter( column_idx ) + row_idx.to_s
40
+ end
41
+
42
+ def multi_array?( obj )
43
+ obj.all? { |el| el.is_a?( Array ) } && obj.is_a?( Array ) rescue false
44
+ end
45
+
46
+ def offset(address, row, col)
47
+ ( col_letter( address_to_col_index( address ) + col ) ) + ( row_id( address ) + row ).to_s
48
+ end
49
+
50
+ def to_range_address( obj1, obj2 )
51
+ if obj2
52
+ obj2.is_a?( String ) ? ( obj1 + ':' + obj2 ) : "#{ obj1.address }:#{ obj2.address }"
53
+ else
54
+ obj1.is_a?( String ) ? obj1 : obj1.address
55
+ end
56
+ end
57
+
58
+ def row_id( address )
59
+ return nil unless address
60
+ address[/\d+/].to_i
61
+ end
62
+
63
+ end
64
+
65
+ class Data
66
+ attr_reader :rows, :cols
67
+ attr_accessor :sheet
68
+ alias parent sheet
69
+
70
+ include Address
71
+
72
+ def initialize( sheet, input_data )
73
+ @sheet = sheet
74
+ ( input_data.kind_of?( Array ) && input_data.all? { |el| el.kind_of?( Array ) } ) or fail ArgumentError, 'Input must be Array of Arrays'
75
+ @data = input_data.dup
76
+ calc_dimensions
77
+ end
78
+
79
+ def all
80
+ @data.dup
81
+ end
82
+
83
+ def append( multi_array )
84
+ @data
85
+ @data += multi_array
86
+ calc_dimensions
87
+ end
88
+
89
+ def colref_by_header( header )
90
+ sheet.header_rows > 0 or fail NoMethodError, 'No header rows present'
91
+ @data[ 0..sheet.header_rows-1 ].each do |r|
92
+ if ( idx = r.index( header ) )
93
+ return col_letter( idx+1 )
94
+ end
95
+ end
96
+ fail IndexError, "#{ header } is not a valid header"
97
+ end
98
+
99
+ def compact!
100
+ compact_columns!
101
+ compact_rows!
102
+ end
103
+
104
+ def compact_columns!
105
+ ensure_shape
106
+ @data = @data.transpose.delete_if { |ar| ar.all? { |el| el.to_s.empty? } || ar.empty? }.transpose
107
+ calc_dimensions
108
+ @data
109
+ end
110
+
111
+ def compact_rows!
112
+ @data.delete_if { |ar| ar.all? { |el| el.to_s.empty? } || ar.empty? }
113
+ calc_dimensions
114
+ @data
115
+ end
116
+
117
+ def dup
118
+ Data.new( sheet, @data.dup )
119
+ end
120
+
121
+ def empty?
122
+ no_headers.empty?
123
+ end
124
+
125
+ def insert_columns( before, number=1 )
126
+ a = Array.new( number, nil )
127
+ before = col_index( before ) - 1
128
+ @data.map! { |row| row.insert( before, *a ) }
129
+ end
130
+
131
+ def insert_rows( before, number=1 )
132
+ @data = @data.insert( ( col_index( before ) - 1 ), *Array.new( number, [nil] ) )
133
+ end
134
+
135
+ def no_headers
136
+ if sheet.header_cols.zero?
137
+ @data[ sheet.header_rows..-1 ].dup
138
+ else
139
+ @data[ sheet.header_rows..-1 ].map { |row| row[ sheet.header_cols..-1 ] }
140
+ end
141
+ end
142
+
143
+ def read( addr )
144
+ row_idx, col_idx = address_to_indices( addr )
145
+ @data[ row_idx-1 ][ col_idx-1 ]
146
+ end
147
+ alias [] read
148
+
149
+ def write( addr, val )
150
+ row_idx, col_idx = address_to_indices( addr )
151
+ ( row_idx - rows ).times { @data << [] }
152
+ @data[ row_idx-1 ][ col_idx-1 ] = val
153
+ calc_dimensions
154
+ end
155
+ alias []= write
156
+
157
+ include Enumerable
158
+
159
+ def each
160
+ @data.each { |ar| yield ar }
161
+ end
162
+
163
+ private
164
+
165
+ def calc_dimensions
166
+ @rows, @cols = @data.length, @data.max_by(&:length).length
167
+ end
168
+
169
+ def ensure_shape
170
+ calc_dimensions
171
+ @data.map! { |ar| ar.length == cols ? ar : ar + Array.new( cols - ar.length, nil) }
172
+ @data
173
+ end
174
+
175
+ end
176
+
177
+ class Section
178
+
179
+ include Address
180
+
181
+ attr_reader :sheet, :idx, :data
182
+ alias parent sheet
183
+
184
+ def initialize( sheet )
185
+ @sheet = sheet
186
+ @data = sheet.data
187
+ end
188
+
189
+ def delete
190
+ data.delete( self )
191
+ end
192
+
193
+ def empty?
194
+ all? { |val| val.to_s.empty? }
195
+ end
196
+
197
+ def find
198
+ each.with_index { |val,i| return translate_address( i + 1 ) if yield val }; nil
199
+ end
200
+
201
+ def inspect
202
+ "#{ self.class }:0x#{ '%x' % (object_id << 1) }: #{ idx }"
203
+ end
204
+
205
+ def read( id )
206
+ data[ translate_address( id ) ]
207
+ end
208
+ alias [] read
209
+
210
+ def to_s
211
+ to_a.join ( self.is_a?( Row ) ? "\t" : "\n" )
212
+ end
213
+
214
+ def write( id, val )
215
+ data[ translate_address( id ) ] = val
216
+ end
217
+ alias []= write
218
+
219
+ include Enumerable
220
+
221
+ def each
222
+ return to_enum(:each) unless block_given?
223
+ each_address { |addr| yield data[ addr ] }
224
+ end
225
+
226
+ def each_cell
227
+ return to_enum(:each_cell) unless block_given?
228
+ each_address { |addr| yield Element.new( sheet, addr ) }
229
+ end
230
+
231
+ def map!
232
+ return to_enum(:map!) unless block_given?
233
+ each_address { |addr| data[addr] = ( yield data[addr] ) }
234
+ end
235
+
236
+ private
237
+
238
+ def translate_address( addr )
239
+ case self
240
+ when Row
241
+ col_letter( addr ) + idx.to_s
242
+ when Column
243
+ addr = addr.to_s unless addr.is_a?( String )
244
+ fail ArgumentError, "Invalid address : #{ addr }" if addr =~ /[^\d]/
245
+ idx + addr
246
+ end
247
+ end
248
+
249
+ end
250
+
251
+ class Row < Section
252
+
253
+ attr_reader :idx
254
+
255
+ def initialize( sheet, idx )
256
+ @idx = idx.to_i
257
+ super( sheet )
258
+ end
259
+
260
+ private
261
+
262
+ def each_address
263
+ ( 'A'..col_letter( data.cols ) ).each { |col_id| yield "#{col_id}#{idx}" }
264
+ end
265
+
266
+ end
267
+
268
+ class Column < Section
269
+
270
+ attr_reader :idx
271
+
272
+ def initialize( sheet, idx )
273
+ @idx = idx
274
+ super( sheet )
275
+ end
276
+
277
+ private
278
+
279
+ def each_address
280
+ 1.upto( data.rows ) { |row_id| yield idx + row_id.to_s }
281
+ end
282
+
283
+ end
284
+
285
+ class Element
286
+
287
+ attr_reader :sheet, :address, :data
288
+ alias parent sheet
289
+
290
+ def initialize( sheet, addr )
291
+ fail ArgumentError, "Invalid range: #{ addr }" unless addr =~ /\A[A-Z]+\d+:[A-Z]+\d+\z|\A[A-Z]+\d+\z/
292
+ @sheet = sheet
293
+ @data = sheet.data
294
+ @address = addr
295
+ end
296
+
297
+ def delete
298
+ data.delete( self )
299
+ end
300
+
301
+ include Address
302
+
303
+ def value
304
+ if address.include? ':'
305
+ expand( address ).map { |ar| ar.map { |addr| data[ addr ] } }
306
+ else
307
+ data[ address ]
308
+ end
309
+ end
310
+
311
+ def value=( val )
312
+ if address.include? ':'
313
+ if multi_array?( val )
314
+ expand( address ).each_with_index { |row,idx| row.each_with_index { |el,i| data[ el ] = val[idx][i] } }
315
+ else
316
+ expand( address ).each { |ar| ar.each { |addr| data[ addr ] = val } }
317
+ end
318
+ else
319
+ data[ address ] = val
320
+ end
321
+ self
322
+ end
323
+
324
+ def to_s
325
+ value.is_a?( Array ) ? value.map { |ar| ar.join "\t" }.join($/) : value.to_s
326
+ end
327
+
328
+ def inspect
329
+ "#{ self.class }:0x#{ '%x' % (object_id << 1) }: #{ address }"
330
+ end
331
+
332
+ include Enumerable
333
+
334
+ def each
335
+ expand( address ).flatten.each { |addr| yield data[ addr ] }
336
+ end
337
+
338
+ def each_cell
339
+ expand( address ).flatten.each { |addr| yield Element.new( sheet, addr ) }
340
+ end
341
+
342
+ def map!
343
+ expand( address ).flatten.each { |addr| data[ addr ] = yield data[ addr ] }
344
+ end
345
+
346
+ end
347
+
348
+ end
data/lib/rubyexcel.rb ADDED
@@ -0,0 +1,230 @@
1
+ require_relative 'rubyexcel/rubyexcel_components.rb'
2
+ require_relative 'rubyexcel/rubyexcel_advanced.rb'
3
+ require_relative 'rubyexcel/excel_tools.rb'
4
+
5
+ class Regexp
6
+ def to_proc
7
+ proc { |s| self =~ s.to_s }
8
+ end
9
+ end
10
+
11
+ module RubyExcel
12
+
13
+ class Workbook
14
+
15
+ def initialize
16
+ @sheets = []
17
+ end
18
+
19
+ def <<( other )
20
+ case other
21
+ when RubyExcel
22
+ other.each { |s| @sheets << s }
23
+ when Sheet
24
+ @sheets << other
25
+ end
26
+ end
27
+
28
+ def add( ref=nil )
29
+ case ref
30
+ when nil
31
+ s = Sheet.new( 'Sheet' + ( @sheets.count + 1 ).to_s, self )
32
+ when Sheet
33
+ s = ref
34
+ s.workbook = self
35
+ when String
36
+ s = Sheet.new( ref, self )
37
+ else
38
+ fail TypeError, "Unsupported Type: #{ ref.class }"
39
+ end
40
+ @sheets << s
41
+ s
42
+ end
43
+ alias add_sheet add
44
+
45
+ def clear_all
46
+ @sheets = []
47
+ self
48
+ end
49
+
50
+ def delete( ref )
51
+ case ref
52
+ when Fixnum
53
+ @sheets.delete_at( ref - 1 )
54
+ when String
55
+ @sheets.reject! { |s| s.name == ref }
56
+ when Regexp
57
+ @sheets.reject! { |s| s.name =~ ref }
58
+ when Sheet
59
+ @sheets.reject! { |s| s == ref }
60
+ else
61
+ fail ArgumentError, "Unrecognised Argument Type: #{ ref.class }"
62
+ end
63
+ end
64
+
65
+ def dup
66
+ wb = Workbook.new
67
+ self.each {|s| wb.add s.dup }
68
+ wb
69
+ end
70
+
71
+ def empty?
72
+ @sheets.empty?
73
+ end
74
+
75
+ def load( *args )
76
+ add.load( *args )
77
+ end
78
+
79
+ def sheets( ref=nil )
80
+ return to_enum (:each) if ref.nil?
81
+ ref.is_a?( Fixnum ) ? @sheets[ ref - 1 ] : @sheets.find { |s| s.name =~ /^#{ ref }$/i }
82
+ end
83
+
84
+ def sort_by!( &block )
85
+ if block_given?
86
+ @sheets = @sheets.sort_by(&block)
87
+ else
88
+ @sheets = @sheets.sort_by(&:name)
89
+ end
90
+ end
91
+ alias sort! sort_by!
92
+
93
+ include Enumerable
94
+
95
+ def each
96
+ return to_enum(:each) unless block_given?
97
+ @sheets.each { |s| yield s }
98
+ end
99
+
100
+ include Excel_Tools
101
+
102
+ end
103
+
104
+ class Sheet
105
+
106
+ attr_reader :data
107
+ attr_accessor :name, :header_rows, :header_cols, :workbook
108
+ alias parent workbook
109
+
110
+ include Address
111
+
112
+ def initialize( name, workbook )
113
+ @workbook = workbook
114
+ @name = name
115
+ @header_rows, @header_cols = nil, nil
116
+ @data = Data.new( self, [[]] )
117
+ end
118
+
119
+ def[]( addr )
120
+ range( addr ).value
121
+ end
122
+
123
+ def []=( addr, val )
124
+ range( addr ).value = val
125
+ end
126
+
127
+ def cell( row, col )
128
+ Element.new( self, indices_to_address( row, col ) )
129
+ end
130
+ alias cells cell
131
+
132
+ def column( index )
133
+ Column.new( self, col_letter( index ) )
134
+ end
135
+
136
+ def columns( start_column = 'A', end_column = data.cols )
137
+ start_column, end_column = col_letter( start_column ), col_letter( end_column )
138
+ return to_enum(:columns, start_column, end_column) unless block_given?
139
+ ( start_column..end_column ).each { |idx| yield column( idx ) }
140
+ end
141
+
142
+ def get_columns( *headers )
143
+ s = dup
144
+ s.data.get_columns!( *headers )
145
+ s
146
+ end
147
+ alias gc get_columns
148
+
149
+ def get_columns!( *headers )
150
+ data.get_columns!( *headers )
151
+ self
152
+ end
153
+ alias gc! get_columns!
154
+
155
+ def delete
156
+ workbook.delete self
157
+ end
158
+
159
+ def dup
160
+ s = Sheet.new( name, workbook )
161
+ d = data
162
+ unless d.nil?
163
+ d = d.dup
164
+ s.load( d.all, header_rows, header_cols )
165
+ d.sheet = s
166
+ end
167
+ s
168
+ end
169
+
170
+ def insert_columns( *args )
171
+ data.insert_columns( *args )
172
+ self
173
+ end
174
+
175
+ def insert_rows( *args )
176
+ data.insert_rows( *args )
177
+ self
178
+ end
179
+
180
+ def inspect
181
+ "#{ self.class }:0x#{ '%x' % (object_id << 1) }: #{ name }"
182
+ end
183
+
184
+ def load( input_data, header_rows=1, header_cols=0 )
185
+ @header_rows, @header_cols = header_rows, header_cols
186
+ @data = Data.new( self, input_data )
187
+ self
188
+ end
189
+
190
+ def match( header, &block )
191
+ row_id( column_by_header( header ).find( &block ) )
192
+ end
193
+
194
+ def maxrow
195
+ data.rows
196
+ end
197
+
198
+ def maxcol
199
+ data.cols
200
+ end
201
+ alias maxcolumn maxcol
202
+
203
+ def range( first_cell, last_cell=nil )
204
+ Element.new( self, to_range_address( first_cell, last_cell ) )
205
+ end
206
+
207
+ def row( index )
208
+ Row.new( self, index )
209
+ end
210
+
211
+ def rows( start_row = 1, end_row = data.rows )
212
+ return to_enum(:rows, start_row, end_row) unless block_given?
213
+ ( start_row..end_row ).each { |idx| yield row( idx ) }
214
+ end
215
+
216
+ def to_a
217
+ data.all
218
+ end
219
+
220
+ def to_excel
221
+ workbook.dup.clear_all.add( self.dup ).workbook.to_excel
222
+ end
223
+
224
+ def to_s
225
+ data.nil? ? '' : data.map { |ar| ar.join "\t" }.join( $/ )
226
+ end
227
+
228
+ end
229
+
230
+ end
metadata ADDED
@@ -0,0 +1,49 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rubyexcel
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Joel Pearson
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-03-23 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: A tabular data structure, mixing Ruby with some of Excel's API.
15
+ email:
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/rubyexcel.rb
21
+ - lib/rubyexcel/excel_tools.rb
22
+ - lib/rubyexcel/rubyexcel_components.rb
23
+ - lib/rubyexcel/rubyexcel_advanced.rb
24
+ homepage:
25
+ licenses: []
26
+ post_install_message:
27
+ rdoc_options: []
28
+ require_paths:
29
+ - lib
30
+ required_ruby_version: !ruby/object:Gem::Requirement
31
+ none: false
32
+ requirements:
33
+ - - ! '>='
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ required_rubygems_version: !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ! '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ requirements: []
43
+ rubyforge_project:
44
+ rubygems_version: 1.8.24
45
+ signing_key:
46
+ specification_version: 3
47
+ summary: Spreadsheets in Ruby
48
+ test_files: []
49
+ has_rdoc: