rubyexcel 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/lib/README.md CHANGED
@@ -93,11 +93,10 @@ wb = s.parent
93
93
  ```
94
94
 
95
95
  Using the Mechanize gem to get data
96
+ --------
96
97
 
97
98
  This example is for context, there are many potential data sources
98
99
 
99
- --------
100
-
101
100
  ```ruby
102
101
  s = RubyExcel::Workbook.new.load( CSV.parse( Mechanize.new.get('http://example.com/myfile.csv').content ) )
103
102
  ```
@@ -134,8 +133,6 @@ s.column( 1 ) #=> Column
134
133
  Some Examples
135
134
  ========
136
135
 
137
- This list may be removed in favour of the gem's documentation on rubydoc.
138
-
139
136
  Common Operations
140
137
  --------
141
138
 
@@ -143,10 +140,16 @@ Common Operations
143
140
  #Append a Column by adding a header
144
141
  s << 'Numbers'
145
142
  x = 1
143
+
146
144
  #Iterate through the rest of the rows while appending data
147
145
  s.rows(2) { |row| row << x; x+=1 }
148
146
 
147
+ #
148
+
149
+ #Split the data into multiple sheets by part number
150
+ wb = s.split( 'Part' )
149
151
 
152
+ #Will add more examples here later.
150
153
 
151
154
  ```
152
155
 
@@ -273,7 +276,7 @@ s.maxcol #=> 5
273
276
  s.columns.count #=> 5
274
277
 
275
278
  #Partition the sheet into two, given a header and a block (like Filter)
276
- #Note: this keeps the headers intact in both outputs sheets
279
+ #Note: this keeps the headers intact in both output sheets
277
280
  type_1_and_3, other = s.partition( 'Part' ) { |value| value =~ /Type[13]/ }
278
281
  type_1_and_3, other = s.partition( 'Part', &/Type[13]/ )
279
282
 
@@ -285,6 +288,10 @@ s.reverse_columns!
285
288
  s.sort! { |r1,r2| r1['A'] <=> r2['A'] }
286
289
  s.sort_by! { |r| r['A'] }
287
290
 
291
+ #Split a Sheet into a Workbook of Sheets by a column (selected by header)
292
+ wb = s.split( 'Part' )
293
+ #=> <Workbook: [Sheet:Type1, Sheet:Type2, Sheet:Type3, Sheet:Type4]>
294
+
288
295
  #Sum all elements in a column by criteria in another column (selected by header)
289
296
  #Parameters: Header to pass to the block, Header to sum, Block.
290
297
  #Note: Now also accepts Column objects in place of headers.
@@ -35,6 +35,26 @@ require_relative 'address.rb'
35
35
  @data = input_data.dup
36
36
  calc_dimensions
37
37
  end
38
+
39
+ #
40
+ # Append an object to Data
41
+ #
42
+ # @param [Object] other the data to append
43
+ # @return [self]
44
+ #
45
+
46
+ def <<( other )
47
+ case other
48
+ when Array ; multi_array?( other ) ? @data += other : @data << other
49
+ when Hash ; @data += _convert_hash( other )
50
+ when Sheet ; empty? ? @data = other.data.all.dup : @data += other.data.dup.no_headers
51
+ when Row ; @data << other.to_a.dup
52
+ when Column ; @data.map!.with_index { |row, i| row << other[ i+1 ] }
53
+ else ; @data[0] << other
54
+ end
55
+ calc_dimensions
56
+ self
57
+ end
38
58
 
39
59
  # @overload advanced_filter!( header, comparison_operator, search_criteria, ... )
40
60
  # Filter on multiple criteria
@@ -239,7 +259,8 @@ require_relative 'address.rb'
239
259
  #
240
260
 
241
261
  def headers
242
- sheet.header_rows > 0 ? @data[ 0..sheet.header_rows-1 ] : nil
262
+ return nil if sheet.header_rows.nil? || sheet.header_rows.zero?
263
+ @data[ 0..sheet.header_rows-1 ]
243
264
  end
244
265
 
245
266
  #
@@ -285,6 +306,7 @@ require_relative 'address.rb'
285
306
  #
286
307
 
287
308
  def no_headers
309
+ return @data unless sheet.header_rows
288
310
  @data[ sheet.header_rows..-1 ]
289
311
  end
290
312
 
@@ -399,6 +421,14 @@ require_relative 'address.rb'
399
421
  @data = @data.map { |ar| ar.length == cols ? ar : ar + Array.new( cols - ar.length, nil) }
400
422
  end
401
423
 
424
+ def _convert_hash(h)
425
+ _hash_to_a(h).each_slice(2).map { |a1,a2| a1 << a2.last }
426
+ end
427
+
428
+ def _hash_to_a(h)
429
+ h.map { |k,v| v.is_a?(Hash) ? _hash_to_a(v).map { |val| ([ k ] + [ val ]).flatten(1) } : [ k, v ] }.flatten(1)
430
+ end
431
+
402
432
  end
403
433
 
404
434
  end
@@ -142,6 +142,15 @@ module RubyExcel
142
142
  return to_enum( :map! ) unless block_given?
143
143
  each_address { |addr| data[addr] = ( yield data[addr] ) }
144
144
  end
145
+
146
+ #
147
+ # Replaces each value with the result of the block, skipping headers
148
+ #
149
+
150
+ def map_without_headers!
151
+ return to_enum( :map_without_headers! ) unless block_given?
152
+ each_address_without_headers { |addr| data[addr] = ( yield data[addr] ) }
153
+ end
145
154
 
146
155
  #
147
156
  # Read a value by address
data/lib/rubyexcel.rb CHANGED
@@ -285,21 +285,16 @@ module RubyExcel
285
285
  end
286
286
 
287
287
  #
288
- # Append data to the Sheet
288
+ # Append an object to the Sheet
289
289
  #
290
- # @param [Array<Array>, Hash<Hash>, RubyExcel::Sheet] other the data to append
290
+ # @param [Object] other the object to append
291
291
  # @return [self]
292
292
  # @note When adding another Sheet it won't import the headers unless this Sheet is empty.
293
- # @note Anything other than an an Array, Hash, or Sheet will be appended to the first row
293
+ # @note Anything other than an an Array, Hash, Row, Column or Sheet will be appended to the first row
294
294
  #
295
295
 
296
296
  def <<( other )
297
- case other
298
- when Array ; load( data.all + other, header_rows )
299
- when Hash ; load( data.all + _convert_hash( other ), header_rows )
300
- when Sheet ; empty? ? load( other.to_a, other.header_rows ) : load( data.all + other.data.no_headers, header_rows )
301
- else ; row(1) << other
302
- end
297
+ data << other
303
298
  self
304
299
  end
305
300
 
@@ -675,16 +670,37 @@ module RubyExcel
675
670
 
676
671
  # {Sheet#sort_by!}
677
672
 
678
- def sort_by( &block )
679
- dup.sort_by!( &block )
673
+ def sort_by( header )
674
+ dup.sort_by!( header )
680
675
  end
681
676
 
682
677
  #
683
- # Sort the data by the block value (avoiding headers)
678
+ # Sort the data by a column, selected by header
679
+ #
680
+ # @param [String] header the header to sort the Sheet by
684
681
  #
685
682
 
686
- def sort_by!( &block )
687
- data.sort_by!( &block ); self
683
+ def sort_by!( header )
684
+ idx = data.index_by_header( header ) - 1
685
+ sort_method = lambda { |array| array[idx] }
686
+ data.sort_by!( &sort_method )
687
+ self
688
+ end
689
+
690
+ #
691
+ # Break the Sheet into a Workbook with multiple Sheets, split by the values under a header.
692
+ #
693
+ # @param [String] header the header to split by
694
+ # @return [RubyExcel::Workbook] a new workbook containing the split Sheets (each with headers)
695
+ #
696
+
697
+ def split( header )
698
+ wb = Workbook.new
699
+ ch( header ).each_wh.to_a.uniq.each { |name| wb.add( name ).load( data.headers ) }
700
+ rows( header_rows+1 ) do |row|
701
+ wb.sheets( row.val( header ) ) << row
702
+ end
703
+ wb
688
704
  end
689
705
 
690
706
  #
@@ -775,16 +791,6 @@ module RubyExcel
775
791
  return_col[ row_id( find_col.find( &block ) ) ] rescue nil
776
792
  end
777
793
 
778
- private
779
-
780
- def _hash_to_a(h)
781
- h.map { |k,v| v.is_a?(Hash) ? _hash_to_a(v).map { |val| ([ k ] + [ val ]).flatten(1) } : [ k, v ] }.flatten(1)
782
- end
783
-
784
- def _convert_hash(h)
785
- _hash_to_a(h).each_slice(2).map { |a1,a2| a1 << a2.last }
786
- end
787
-
788
794
  end # Sheet
789
795
 
790
796
  end # RubyExcel
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubyexcel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,9 +9,10 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-05-02 00:00:00.000000000 Z
12
+ date: 2013-05-03 00:00:00.000000000 Z
13
13
  dependencies: []
14
- description: A tabular data structure, mixing Ruby with some of Excel's API style.
14
+ description: A tabular data structure in Ruby, with header-based helper methods and
15
+ some of Excel's API style.
15
16
  email: VirtuosoJoel@gmail.com
16
17
  executables: []
17
18
  extensions: []