rubyexcel 0.3.9 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,71 +1,71 @@
1
- require_relative 'address.rb'
2
- require_relative 'data.rb'
3
- require_relative 'element.rb'
4
- #require_relative 'excel_tools.rb'
5
- require_relative 'section.rb'
6
- require_relative 'sheet.rb'
7
-
8
- module RubyExcel
9
-
10
- #
11
- # Example data to use in tests / demos
12
- #
13
-
14
- def self.sample_data
15
- [
16
- [ 'Part', 'Ref1', 'Ref2', 'Qty', 'Cost' ],
17
- [ 'Type1', 'QT1', '231', 1, 35.15 ],
18
- [ 'Type2', 'QT3', '123', 1, 40 ],
19
- [ 'Type3', 'XT1', '321', 3, 0.1 ],
20
- [ 'Type1', 'XY2', '132', 1, 30.00 ],
21
- [ 'Type4', 'XT3', '312', 2, 3 ],
22
- [ 'Type2', 'QY2', '213', 1, 99.99 ],
23
- [ 'Type1', 'QT4', '123', 2, 104 ]
24
- ]
25
-
26
- end
27
-
28
- #
29
- # Example hash to demonstrate imports
30
- #
31
-
32
- def self.sample_hash
33
-
34
- {
35
- Part1: {
36
- Type1: {
37
- SubType1: 1, SubType2: 2, SubType3: 3
38
- },
39
- Type2: {
40
- SubType1: 4, SubType2: 5, SubType3: 6
41
- }
42
- },
43
- Part2: {
44
- Type1: {
45
- SubType1: 1, SubType2: 2, SubType3: 3
46
- },
47
- Type2: {
48
- SubType1: 4, SubType2: 5, SubType3: 6
49
- }
50
- }
51
- }
52
-
53
- end
54
-
55
- #
56
- # Shortcut to create a Sheet with example data
57
- #
58
-
59
- def self.sample_sheet
60
- Workbook.new.load RubyExcel.sample_data
61
- end
62
-
63
- #
64
- # Shortcut to import a WIN32OLE Workbook or Sheet
65
- #
66
-
67
- def self.import( *args )
68
- Workbook.new.import( *args )
69
- end
70
-
1
+ require_relative 'address.rb'
2
+ require_relative 'data.rb'
3
+ require_relative 'element.rb'
4
+ #require_relative 'excel_tools.rb'
5
+ require_relative 'section.rb'
6
+ require_relative 'sheet.rb'
7
+
8
+ module RubyExcel
9
+
10
+ #
11
+ # Example data to use in tests / demos
12
+ #
13
+
14
+ def self.sample_data
15
+ [
16
+ [ 'Part', 'Ref1', 'Ref2', 'Qty', 'Cost' ],
17
+ [ 'Type1', 'QT1', '231', 1, 35.15 ],
18
+ [ 'Type2', 'QT3', '123', 1, 40 ],
19
+ [ 'Type3', 'XT1', '321', 3, 0.1 ],
20
+ [ 'Type1', 'XY2', '132', 1, 30.00 ],
21
+ [ 'Type4', 'XT3', '312', 2, 3 ],
22
+ [ 'Type2', 'QY2', '213', 1, 99.99 ],
23
+ [ 'Type1', 'QT4', '123', 2, 104 ]
24
+ ]
25
+
26
+ end
27
+
28
+ #
29
+ # Example hash to demonstrate imports
30
+ #
31
+
32
+ def self.sample_hash
33
+
34
+ {
35
+ Part1: {
36
+ Type1: {
37
+ SubType1: 1, SubType2: 2, SubType3: 3
38
+ },
39
+ Type2: {
40
+ SubType1: 4, SubType2: 5, SubType3: 6
41
+ }
42
+ },
43
+ Part2: {
44
+ Type1: {
45
+ SubType1: 1, SubType2: 2, SubType3: 3
46
+ },
47
+ Type2: {
48
+ SubType1: 4, SubType2: 5, SubType3: 6
49
+ }
50
+ }
51
+ }
52
+
53
+ end
54
+
55
+ #
56
+ # Shortcut to create a Sheet with example data
57
+ #
58
+
59
+ def self.sample_sheet
60
+ Workbook.new.load RubyExcel.sample_data
61
+ end
62
+
63
+ #
64
+ # Shortcut to import a WIN32OLE Workbook or Sheet
65
+ #
66
+
67
+ def self.import( *args )
68
+ Workbook.new.import( *args )
69
+ end
70
+
71
71
  end
@@ -1,377 +1,377 @@
1
- module RubyExcel
2
-
3
- #
4
- # Superclass for Row and Column
5
- #
6
-
7
- class Section
8
- include Address
9
- include Enumerable
10
-
11
- # The Sheet parent of the Section
12
- attr_reader :sheet
13
- alias parent sheet
14
-
15
- # The Data underlying the Sheet
16
- attr_reader :data
17
-
18
- #
19
- # Creates a RubyExcel::Section instance
20
- #
21
- # @param [RubyExcel::Sheet] sheet the parent Sheet
22
- #
23
-
24
- def initialize( sheet )
25
- @sheet = sheet
26
- @data = sheet.data
27
- end
28
-
29
- #
30
- # Access a cell by its index within the Section
31
- #
32
-
33
- def cell( ref )
34
- Cell.new( sheet, translate_address( ref ) )
35
- end
36
-
37
- #
38
- # Delete the data referenced by self
39
- #
40
-
41
- def delete
42
- data.delete( self ); self
43
- end
44
-
45
- #
46
- # Yields each value
47
- #
48
-
49
- def each
50
- return to_enum(:each) unless block_given?
51
- each_address { |addr| yield data[ addr ] }
52
- end
53
-
54
- #
55
- # Yields each value, skipping headers
56
- #
57
-
58
- def each_without_headers
59
- return to_enum( :each_without_headers ) unless block_given?
60
- each_address( false ) { |addr| yield data[ addr ] }
61
- end
62
- alias each_wh each_without_headers
63
-
64
- #
65
- # Yields each cell
66
- #
67
-
68
- def each_cell
69
- return to_enum( :each_cell ) unless block_given?
70
- each_address { |addr| yield Cell.new( sheet, addr ) }
71
- end
72
-
73
- #
74
- # Yields each cell, skipping headers
75
- #
76
-
77
- def each_cell_without_headers
78
- return to_enum( :each_cell_without_headers ) unless block_given?
79
- each_address( false ) { |addr| yield Cell.new( sheet, addr ) }
80
- end
81
- alias each_cell_wh each_cell_without_headers
82
-
83
- #
84
- # Check whether the data in self is empty
85
- #
86
-
87
- def empty?
88
- each_wh.all? { |val| val.to_s.empty? }
89
- end
90
-
91
- #
92
- # Return the address of a given value
93
- #
94
- # @yield [Object] yields each cell value to the block
95
- # @return [String, nil] the address of the value or nil
96
- #
97
-
98
- def find
99
- return to_enum( :find ) unless block_given?
100
- each_cell { |ce| return ce.address if yield ce.value }; nil
101
- end
102
-
103
- #
104
- # View the object for debugging
105
- #
106
-
107
- def inspect
108
- "#{ self.class }:0x#{ '%x' % (object_id << 1) }: #{ idx }"
109
- end
110
-
111
- #
112
- # Return the value of the last cell
113
- #
114
-
115
- def last
116
- last_cell.value
117
- end
118
-
119
- #
120
- # Return the last cell
121
- #
122
- # @return [RubyExcel::Cell]
123
- #
124
-
125
- def last_cell
126
- Cell.new( sheet, each_address.to_a.last )
127
- end
128
-
129
- #
130
- # Replaces each value with the result of the block
131
- #
132
-
133
- def map!
134
- return to_enum( :map! ) unless block_given?
135
- each_address { |addr| data[addr] = ( yield data[addr] ) }
136
- end
137
-
138
- #
139
- # Replaces each value with the result of the block, skipping headers
140
- #
141
-
142
- def map_without_headers!
143
- return to_enum( :map_without_headers! ) unless block_given?
144
- each_address( false ) { |addr| data[addr] = ( yield data[addr] ) }
145
- end
146
- alias map_wh! map_without_headers!
147
-
148
- #
149
- # Read a value by address
150
- #
151
- # @param [String, Fixnum, ::Range] start an index or Range of indices.
152
- # @param [Fixnum] slice if the first argument is an index, how many cells to read.
153
- #
154
-
155
- def read( start, slice=nil )
156
- if slice
157
- ( start..( step_index( start, slice ) ) ).map { |n| data[ translate_address( n ) ] }
158
- else
159
- if start.is_a?( ::Range ) # Standard Ruby Range
160
- start.map { |n| data[ translate_address( n ) ] }
161
- else # Single value
162
- data[ translate_address( start ) ]
163
- end
164
- end
165
- end
166
- alias [] read
167
-
168
- #
169
- # Summarise the values of a Section into a Hash
170
- #
171
- # @return [Hash]
172
- #
173
-
174
- def summarise
175
- each_wh.inject( Hash.new(0) ) { |h, v| h[v]+=1; h }
176
- end
177
- alias summarize summarise
178
-
179
- #
180
- # The Section as a seperated value String
181
- #
182
-
183
- def to_s
184
- to_a.map { |v| v.to_s.gsub(/\t|\n|\r/,' ') }.join ( self.is_a?( Row ) ? "\t" : "\n" )
185
- end
186
-
187
- #
188
- # Write a value by address
189
- #
190
- # @param [Array<String, Fixnum, ::Range, Object>] args the address to write the data to, and the data to write.
191
- #
192
-
193
- def write( *args )
194
- val = args.pop
195
- if args.length == 1
196
- if args[0].is_a?( ::Range ) # Standard Ruby Range
197
- sheet.range( to_range_address( translate_address( args[0].first ), translate_address( args[0].last ) ) ).value = val
198
- else # Single value
199
- data[ translate_address( args[0] ) ] = val
200
- end
201
- else # Slice
202
- sheet.range( to_range_address( translate_address( args[0] ), translate_address( step_index( args[0], args[1] ) ) ) ).value = val
203
- end
204
- end
205
- alias []= write
206
-
207
- end # Section
208
-
209
- #
210
- # A Row in the Sheet
211
- # @attr_reader [Fixnum] idx the Row index
212
- # @attr_reader [Fixnum] length the Row length
213
- #
214
-
215
- class Row < Section
216
-
217
- # The Row number
218
- attr_reader :idx
219
- alias index idx
220
-
221
- #
222
- # Creates a RubyExcel::Row instance
223
- #
224
- # @param [RubyExcel::Sheet] sheet the Sheet which holds this Row
225
- # @param [Fixnum] idx the index of this Row
226
- #
227
-
228
- def initialize( sheet, idx )
229
- @idx = Integer( idx )
230
- super( sheet )
231
- end
232
-
233
- #
234
- # Append a value to the Row.
235
- #
236
- # @param [Object] value the object to append
237
- # @note This only adds an extra cell if it is the first Row
238
- # This prevents a loop through Rows from extending diagonally away from the main data.
239
- #
240
-
241
- def <<( value )
242
- data[ translate_address( idx == 1 ? data.cols + 1 : data.cols ) ] = value
243
- end
244
-
245
- #
246
- # Access a Cell by its header
247
- #
248
- # @param [String] header the header to search for
249
- # @return [RubyExcel::Cell] the cell
250
- #
251
-
252
- def cell_by_header( header )
253
- cell( getref( header ) )
254
- end
255
- alias cell_h cell_by_header
256
-
257
- #
258
- # Find the Address of a header
259
- #
260
- # @param [String] header the header to search for
261
- # @return [String] the address of the header
262
- #
263
-
264
- def getref( header )
265
- sheet.header_rows.times do |t|
266
- res = sheet.row( t + 1 ).find { |v| v == header }
267
- return column_id( res ) if res
268
- end
269
- fail ArgumentError, 'Invalid header: ' + header.to_s
270
- end
271
-
272
- #
273
- # The number of Columns in the Row
274
- #
275
-
276
- def length
277
- data.cols
278
- end
279
-
280
- #
281
- # Find a value in this Row by its header
282
- #
283
- # @param [String] header the header to search for
284
- # @return [Object] the value at the address
285
- #
286
-
287
- def value_by_header( header )
288
- self[ getref( header ) ]
289
- end
290
- alias val value_by_header
291
-
292
- #
293
- # Set a value in this Row by its header
294
- #
295
- # @param [String] header the header to search for
296
- # @param [Object] val the value to write
297
- #
298
-
299
- def set_value_by_header( header, val )
300
- self[ getref( header ) ] = val
301
- end
302
- alias set_val set_value_by_header
303
-
304
- private
305
-
306
- def each_address( unused=nil )
307
- return to_enum( :each_address ) unless block_given?
308
- ( 'A'..col_letter( data.cols ) ).each { |col_id| yield translate_address( col_id ) }
309
- end
310
-
311
- def translate_address( addr )
312
- col_letter( addr ) + idx.to_s
313
- end
314
-
315
- end # Row
316
-
317
- #
318
- # A Column in the Sheet
319
- #
320
- # @attr_reader [String] idx the Column index
321
- # @attr_reader [Fixnum] length the Column length
322
- #
323
-
324
- class Column < Section
325
-
326
- # The Column letter
327
- attr_reader :idx
328
- alias index idx
329
-
330
- #
331
- # Creates a RubyExcel::Column instance
332
- #
333
- # @param [RubyExcel::Sheet] sheet the Sheet which holds this Column
334
- # @param [String, Fixnum] idx the index of this Column
335
- #
336
-
337
- def initialize( sheet, idx )
338
- @idx = idx
339
- super( sheet )
340
- end
341
-
342
- #
343
- # Append a value to the Column.
344
- #
345
- # @param [Object] value the object to append
346
- # @note This only adds an extra cell if it is the first Column.
347
- # This prevents a loop through Columns from extending diagonally away from the main data.
348
- #
349
-
350
- def <<( value )
351
- data[ translate_address( idx == 'A' ? data.rows + 1 : data.rows ) ] = value
352
- end
353
-
354
- #
355
- # The number of Rows in the Column
356
- #
357
-
358
- def length
359
- data.rows
360
- end
361
-
362
- private
363
-
364
- def each_address( headers=true )
365
- return to_enum( :each_address ) unless block_given?
366
- ( headers ? 1 : sheet.header_rows + 1 ).upto( data.rows ) { |row_id| yield translate_address( row_id ) }
367
- end
368
-
369
- def translate_address( addr )
370
- addr = addr.to_s unless addr.is_a?( String )
371
- fail ArgumentError, "Invalid address : #{ addr }" if addr =~ /[^\d]/
372
- idx + addr
373
- end
374
-
375
- end # Column
376
-
1
+ module RubyExcel
2
+
3
+ #
4
+ # Superclass for Row and Column
5
+ #
6
+
7
+ class Section
8
+ include Address
9
+ include Enumerable
10
+
11
+ # The Sheet parent of the Section
12
+ attr_reader :sheet
13
+ alias parent sheet
14
+
15
+ # The Data underlying the Sheet
16
+ attr_reader :data
17
+
18
+ #
19
+ # Creates a RubyExcel::Section instance
20
+ #
21
+ # @param [RubyExcel::Sheet] sheet the parent Sheet
22
+ #
23
+
24
+ def initialize( sheet )
25
+ @sheet = sheet
26
+ @data = sheet.data
27
+ end
28
+
29
+ #
30
+ # Access a cell by its index within the Section
31
+ #
32
+
33
+ def cell( ref )
34
+ Cell.new( sheet, translate_address( ref ) )
35
+ end
36
+
37
+ #
38
+ # Delete the data referenced by self
39
+ #
40
+
41
+ def delete
42
+ data.delete( self ); self
43
+ end
44
+
45
+ #
46
+ # Yields each value
47
+ #
48
+
49
+ def each
50
+ return to_enum(:each) unless block_given?
51
+ each_address { |addr| yield data[ addr ] }
52
+ end
53
+
54
+ #
55
+ # Yields each value, skipping headers
56
+ #
57
+
58
+ def each_without_headers
59
+ return to_enum( :each_without_headers ) unless block_given?
60
+ each_address( false ) { |addr| yield data[ addr ] }
61
+ end
62
+ alias each_wh each_without_headers
63
+
64
+ #
65
+ # Yields each cell
66
+ #
67
+
68
+ def each_cell
69
+ return to_enum( :each_cell ) unless block_given?
70
+ each_address { |addr| yield Cell.new( sheet, addr ) }
71
+ end
72
+
73
+ #
74
+ # Yields each cell, skipping headers
75
+ #
76
+
77
+ def each_cell_without_headers
78
+ return to_enum( :each_cell_without_headers ) unless block_given?
79
+ each_address( false ) { |addr| yield Cell.new( sheet, addr ) }
80
+ end
81
+ alias each_cell_wh each_cell_without_headers
82
+
83
+ #
84
+ # Check whether the data in self is empty
85
+ #
86
+
87
+ def empty?
88
+ each_wh.all? { |val| val.to_s.empty? }
89
+ end
90
+
91
+ #
92
+ # Return the address of a given value
93
+ #
94
+ # @yield [Object] yields each cell value to the block
95
+ # @return [String, nil] the address of the value or nil
96
+ #
97
+
98
+ def find
99
+ return to_enum( :find ) unless block_given?
100
+ each_cell { |ce| return ce.address if yield ce.value }; nil
101
+ end
102
+
103
+ #
104
+ # View the object for debugging
105
+ #
106
+
107
+ def inspect
108
+ "#{ self.class }:0x#{ '%x' % (object_id << 1) }: #{ idx }"
109
+ end
110
+
111
+ #
112
+ # Return the value of the last cell
113
+ #
114
+
115
+ def last
116
+ last_cell.value
117
+ end
118
+
119
+ #
120
+ # Return the last cell
121
+ #
122
+ # @return [RubyExcel::Cell]
123
+ #
124
+
125
+ def last_cell
126
+ Cell.new( sheet, each_address.to_a.last )
127
+ end
128
+
129
+ #
130
+ # Replaces each value with the result of the block
131
+ #
132
+
133
+ def map!
134
+ return to_enum( :map! ) unless block_given?
135
+ each_address { |addr| data[addr] = ( yield data[addr] ) }
136
+ end
137
+
138
+ #
139
+ # Replaces each value with the result of the block, skipping headers
140
+ #
141
+
142
+ def map_without_headers!
143
+ return to_enum( :map_without_headers! ) unless block_given?
144
+ each_address( false ) { |addr| data[addr] = ( yield data[addr] ) }
145
+ end
146
+ alias map_wh! map_without_headers!
147
+
148
+ #
149
+ # Read a value by address
150
+ #
151
+ # @param [String, Fixnum, ::Range] start an index or Range of indices.
152
+ # @param [Fixnum] slice if the first argument is an index, how many cells to read.
153
+ #
154
+
155
+ def read( start, slice=nil )
156
+ if slice
157
+ ( start..( step_index( start, slice ) ) ).map { |n| data[ translate_address( n ) ] }
158
+ else
159
+ if start.is_a?( ::Range ) # Standard Ruby Range
160
+ start.map { |n| data[ translate_address( n ) ] }
161
+ else # Single value
162
+ data[ translate_address( start ) ]
163
+ end
164
+ end
165
+ end
166
+ alias [] read
167
+
168
+ #
169
+ # Summarise the values of a Section into a Hash
170
+ #
171
+ # @return [Hash]
172
+ #
173
+
174
+ def summarise
175
+ each_wh.inject( Hash.new(0) ) { |h, v| h[v]+=1; h }
176
+ end
177
+ alias summarize summarise
178
+
179
+ #
180
+ # The Section as a seperated value String
181
+ #
182
+
183
+ def to_s
184
+ to_a.map { |v| v.to_s.gsub(/\t|\n|\r/,' ') }.join ( self.is_a?( Row ) ? "\t" : "\n" )
185
+ end
186
+
187
+ #
188
+ # Write a value by address
189
+ #
190
+ # @param [Array<String, Fixnum, ::Range, Object>] args the address to write the data to, and the data to write.
191
+ #
192
+
193
+ def write( *args )
194
+ val = args.pop
195
+ if args.length == 1
196
+ if args[0].is_a?( ::Range ) # Standard Ruby Range
197
+ sheet.range( to_range_address( translate_address( args[0].first ), translate_address( args[0].last ) ) ).value = val
198
+ else # Single value
199
+ data[ translate_address( args[0] ) ] = val
200
+ end
201
+ else # Slice
202
+ sheet.range( to_range_address( translate_address( args[0] ), translate_address( step_index( args[0], args[1] ) ) ) ).value = val
203
+ end
204
+ end
205
+ alias []= write
206
+
207
+ end # Section
208
+
209
+ #
210
+ # A Row in the Sheet
211
+ # @attr_reader [Fixnum] idx the Row index
212
+ # @attr_reader [Fixnum] length the Row length
213
+ #
214
+
215
+ class Row < Section
216
+
217
+ # The Row number
218
+ attr_reader :idx
219
+ alias index idx
220
+
221
+ #
222
+ # Creates a RubyExcel::Row instance
223
+ #
224
+ # @param [RubyExcel::Sheet] sheet the Sheet which holds this Row
225
+ # @param [Fixnum] idx the index of this Row
226
+ #
227
+
228
+ def initialize( sheet, idx )
229
+ @idx = Integer( idx )
230
+ super( sheet )
231
+ end
232
+
233
+ #
234
+ # Append a value to the Row.
235
+ #
236
+ # @param [Object] value the object to append
237
+ # @note This only adds an extra cell if it is the first Row
238
+ # This prevents a loop through Rows from extending diagonally away from the main data.
239
+ #
240
+
241
+ def <<( value )
242
+ data[ translate_address( idx == 1 ? data.cols + 1 : data.cols ) ] = value
243
+ end
244
+
245
+ #
246
+ # Access a Cell by its header
247
+ #
248
+ # @param [String] header the header to search for
249
+ # @return [RubyExcel::Cell] the cell
250
+ #
251
+
252
+ def cell_by_header( header )
253
+ cell( getref( header ) )
254
+ end
255
+ alias cell_h cell_by_header
256
+
257
+ #
258
+ # Find the Address of a header
259
+ #
260
+ # @param [String] header the header to search for
261
+ # @return [String] the address of the header
262
+ #
263
+
264
+ def getref( header )
265
+ sheet.header_rows.times do |t|
266
+ res = sheet.row( t + 1 ).find { |v| v == header }
267
+ return column_id( res ) if res
268
+ end
269
+ fail ArgumentError, 'Invalid header: ' + header.to_s
270
+ end
271
+
272
+ #
273
+ # The number of Columns in the Row
274
+ #
275
+
276
+ def length
277
+ data.cols
278
+ end
279
+
280
+ #
281
+ # Find a value in this Row by its header
282
+ #
283
+ # @param [String] header the header to search for
284
+ # @return [Object] the value at the address
285
+ #
286
+
287
+ def value_by_header( header )
288
+ self[ getref( header ) ]
289
+ end
290
+ alias val value_by_header
291
+
292
+ #
293
+ # Set a value in this Row by its header
294
+ #
295
+ # @param [String] header the header to search for
296
+ # @param [Object] val the value to write
297
+ #
298
+
299
+ def set_value_by_header( header, val )
300
+ self[ getref( header ) ] = val
301
+ end
302
+ alias set_val set_value_by_header
303
+
304
+ private
305
+
306
+ def each_address( unused=nil )
307
+ return to_enum( :each_address ) unless block_given?
308
+ ( 'A'..col_letter( data.cols ) ).each { |col_id| yield translate_address( col_id ) }
309
+ end
310
+
311
+ def translate_address( addr )
312
+ col_letter( addr ) + idx.to_s
313
+ end
314
+
315
+ end # Row
316
+
317
+ #
318
+ # A Column in the Sheet
319
+ #
320
+ # @attr_reader [String] idx the Column index
321
+ # @attr_reader [Fixnum] length the Column length
322
+ #
323
+
324
+ class Column < Section
325
+
326
+ # The Column letter
327
+ attr_reader :idx
328
+ alias index idx
329
+
330
+ #
331
+ # Creates a RubyExcel::Column instance
332
+ #
333
+ # @param [RubyExcel::Sheet] sheet the Sheet which holds this Column
334
+ # @param [String, Fixnum] idx the index of this Column
335
+ #
336
+
337
+ def initialize( sheet, idx )
338
+ @idx = idx
339
+ super( sheet )
340
+ end
341
+
342
+ #
343
+ # Append a value to the Column.
344
+ #
345
+ # @param [Object] value the object to append
346
+ # @note This only adds an extra cell if it is the first Column.
347
+ # This prevents a loop through Columns from extending diagonally away from the main data.
348
+ #
349
+
350
+ def <<( value )
351
+ data[ translate_address( idx == 'A' ? data.rows + 1 : data.rows ) ] = value
352
+ end
353
+
354
+ #
355
+ # The number of Rows in the Column
356
+ #
357
+
358
+ def length
359
+ data.rows
360
+ end
361
+
362
+ private
363
+
364
+ def each_address( headers=true )
365
+ return to_enum( :each_address ) unless block_given?
366
+ ( headers ? 1 : sheet.header_rows + 1 ).upto( data.rows ) { |row_id| yield translate_address( row_id ) }
367
+ end
368
+
369
+ def translate_address( addr )
370
+ addr = addr.to_s unless addr.is_a?( String )
371
+ fail ArgumentError, "Invalid address : #{ addr }" if addr =~ /[^\d]/
372
+ idx + addr
373
+ end
374
+
375
+ end # Column
376
+
377
377
  end # RubyExcel