xls 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/bin/xls CHANGED
@@ -16,29 +16,38 @@ program :description, 'A command line utility for working with data in Excel.'
16
16
  #
17
17
  ################################################################################
18
18
 
19
- command :"enumerate" do |c|
20
- c.syntax = 'xls enumerate FILE'
21
- c.description = 'Executes Ruby code on each cell of a workbook.'
22
- c.option('--selection SELECTION', 'The Excel style selection to work within.')
23
- c.option('-e CODE', 'The code to execute for each cell.')
24
- c.when_called do|args, options|
25
- # Open input file.
26
- abort("Input file required") if args.length == 0
27
- workbook = Spreadsheet.open(args.first)
19
+ def build_enumerator_command(action, description)
20
+ command action do |c|
21
+ c.syntax = "xls #{action.to_s} FILE"
22
+ c.description = description
23
+ c.option('-s SELECTION', 'The Excel style selection to work within.')
24
+ c.option('-e CODE', 'The code to execute for each cell.')
25
+ c.option('--use-headers', 'Whether to use the first row as a header row.')
26
+ c.option('--output FILE', 'The path to the output file.') unless action == :each
27
+ c.when_called do|args, options|
28
+ abort("Input file required") if args.length == 0
29
+ abort("Output file required") if action != :each && options.e.nil?
30
+ abort("Execution code required") if options.e.nil?
28
31
 
29
- # Convert Ruby source to procs.
30
- abort("Enumerator code required") if options.e.nil?
31
- procs = options.e.is_a?(String) ? [options.e] : options.e
32
- procs.map! {|source| eval("lambda { |cell, col_index, row_index| #{source} }")}
33
-
34
- # Run enumerator.
35
- enumerator = Xls::Enumerator.new()
36
- enumerator.selection = Xls::Selection.parse(options.selection.upcase) unless options.selection.nil?
37
- enumerator.procs = procs
38
- enumerator.process(workbook)
32
+ # Run enumerator.
33
+ workbook = Spreadsheet.open(args.first)
34
+ enumerator = Xls::Enumerator.new()
35
+ enumerator.action = action
36
+ enumerator.use_headers = options.use_headers
37
+ enumerator.selection = Xls::Selection.parse(options.s.upcase) unless options.s.nil?
38
+ enumerator.proc = options.e
39
+ enumerator.process(workbook)
40
+
41
+ # Write output to file.
42
+ workbook.write(options.output) if action != :each
43
+ end
39
44
  end
40
45
  end
41
46
 
47
+ build_enumerator_command(:each, 'Executes Ruby code on each cell of a workbook.')
48
+ build_enumerator_command(:map, 'Maps output of Ruby code on each cell.')
49
+ build_enumerator_command(:select, 'Keeps each cell where the code evaluates true.')
50
+ build_enumerator_command(:reject, 'Keeps each cell where the code evaluates false.')
42
51
 
43
52
 
44
53
 
@@ -50,7 +59,7 @@ end
50
59
 
51
60
  command :columnize do |c|
52
61
  c.syntax = 'xls columnize FILE'
53
- c.description = 'Converts a worksheet formatted as table into 2-column rows using header/value.'
62
+ c.description = 'Converts table into 2-column rows table.'
54
63
  c.option('--output FILE', 'The path to the output file.')
55
64
  c.option('--fixed-columns COLUMNS', 'The columns that should stay fixed.')
56
65
  c.when_called do|args, options|
@@ -8,7 +8,7 @@ class Xls
8
8
 
9
9
  def initialize(options={})
10
10
  self.selection = options[:selection]
11
- self.procs = options[:procs] || []
11
+ self.proc = options[:proc]
12
12
  end
13
13
 
14
14
 
@@ -18,12 +18,18 @@ class Xls
18
18
  #
19
19
  ############################################################################
20
20
 
21
+ # The action to perform on each cell of data (:none, :map, :select, :reject).
22
+ attr_accessor :action
23
+
21
24
  # The selection to enumerate over.
22
25
  attr_accessor :selection
23
26
 
24
- # A list of procs to run on each cell.
25
- attr_accessor :procs
26
-
27
+ # The proc to run on each cell.
28
+ attr_accessor :proc
29
+
30
+ # A flag stating if headers should be used.
31
+ attr_accessor :use_headers
32
+
27
33
 
28
34
  ############################################################################
29
35
  #
@@ -31,25 +37,32 @@ class Xls
31
37
  #
32
38
  ############################################################################
33
39
 
34
- # Executes a set of procs on each cell in a selection.
40
+ # Executes a proc on each cell in a selection.
35
41
  #
36
42
  # @param [Workbook] input The input workbook.
37
43
  def process(input)
38
44
  # Loop over each worksheet.
39
45
  (0...input.sheet_count).each do |sheet_index|
40
46
  sheet = input.worksheet(sheet_index)
47
+ headers = sheet.row(0)
41
48
 
42
49
  # Loop over each row.
43
- sheet.each do |row|
50
+ sheet.each(use_headers ? 1 : 0) do |row|
44
51
  next unless selection.nil? || selection.rows.nil? || selection.rows.cover?(row.idx)
45
52
 
46
53
  # Loop over each cell.
47
54
  row.each_with_index do |cell, col_index|
48
55
  next unless selection.nil? || selection.columns.nil? || selection.columns.cover?(col_index)
49
56
 
50
- # Run each proc.
51
- procs.each do |proc|
52
- proc.call(cell.to_s, col_index, row.idx)
57
+ # Run proc and retrieve the results.
58
+ header = (use_headers ? headers[col_index].to_s : '')
59
+ result = cell_binding(cell.to_s, col_index, row.idx, header).eval(proc)
60
+
61
+ # Perform an action if one is specified.
62
+ case action
63
+ when :map then row[col_index] = result.to_s
64
+ when :select then row[col_index] = '' unless result
65
+ when :reject then row[col_index] = '' if result
53
66
  end
54
67
  end
55
68
  end
@@ -57,5 +70,15 @@ class Xls
57
70
 
58
71
  return nil
59
72
  end
73
+
74
+
75
+ ####################################
76
+ # Bindings
77
+ ####################################
78
+
79
+ # Returns the context in which cell procs are run.
80
+ def cell_binding(text, col, row, header)
81
+ return binding
82
+ end
60
83
  end
61
84
  end
@@ -1,3 +1,3 @@
1
1
  class Xls
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
@@ -9,23 +9,42 @@ class TestEnumerator < MiniTest::Unit::TestCase
9
9
  # Execute
10
10
  ######################################
11
11
 
12
- def test_enumerate
13
- my_arr = []
14
- input = Spreadsheet.open('fixtures/enumerator/basic.xls')
15
- @enumerator.procs = [
16
- lambda {|cell, col, row| my_arr << cell.to_s},
17
- lambda {|cell, col, row| my_arr << '0'},
18
- ]
19
- @enumerator.process(input)
20
- assert_equal ["a", "0", "b", "0", "c", "0", "d", "0", "e", "0", "f", "0", "g", "0", "h", "0", "i", "0"], my_arr
12
+ def test_map_enumerate
13
+ workbook = Spreadsheet.open('fixtures/enumerator/basic.xls')
14
+ @enumerator.action = :map
15
+ @enumerator.proc = "text.to_s + '!'"
16
+ @enumerator.process(workbook)
17
+ assert_worksheet [
18
+ ['a!', 'b!', 'c!'],
19
+ ['d!', 'e!', 'f!'],
20
+ ['g!', 'h!', 'i!'],
21
+ ],
22
+ workbook.worksheet(0)
21
23
  end
22
24
 
23
- def test_enumerate_with_selection
24
- my_arr = []
25
- input = Spreadsheet.open('fixtures/enumerator/basic.xls')
26
- @enumerator.procs = [lambda {|cell, col, row| my_arr << cell.to_s}]
27
- @enumerator.selection = Xls::Selection.parse("B2:C3")
28
- @enumerator.process(input)
29
- assert_equal ['e', 'f', 'h', 'i'], my_arr
25
+ def test_select_enumerate
26
+ workbook = Spreadsheet.open('fixtures/enumerator/basic.xls')
27
+ @enumerator.action = :select
28
+ @enumerator.proc = "text.to_s.ord % 2 == 0"
29
+ @enumerator.process(workbook)
30
+ assert_worksheet [
31
+ ['', 'b', ''],
32
+ ['d', '', 'f'],
33
+ ['', 'h', ''],
34
+ ],
35
+ workbook.worksheet(0)
36
+ end
37
+
38
+ def test_reject_enumerate
39
+ workbook = Spreadsheet.open('fixtures/enumerator/basic.xls')
40
+ @enumerator.action = :reject
41
+ @enumerator.proc = "text.to_s.ord % 2 == 0"
42
+ @enumerator.process(workbook)
43
+ assert_worksheet [
44
+ ['a', '', 'c'],
45
+ ['', 'e', ''],
46
+ ['g', '', 'i'],
47
+ ],
48
+ workbook.worksheet(0)
30
49
  end
31
50
  end
@@ -10,8 +10,8 @@ class MiniTest::Unit::TestCase
10
10
  worksheet.each do |row|
11
11
  act << row.map {|cell| cell.to_s.strip }
12
12
  end
13
- exp = exp.map {|row| row.map {|cell| '%-10s' % cell.to_s}.join('').strip}.join("\n")
14
- act = act.map {|row| row.map {|cell| '%-10s' % cell.to_s}.join('').strip}.join("\n")
13
+ exp = exp.map {|row| row.map {|cell| '%-10s' % cell.to_s}.join('').rstrip}.join("\n")
14
+ act = act.map {|row| row.map {|cell| '%-10s' % cell.to_s}.join('').rstrip}.join("\n")
15
15
  assert_equal(exp, act, msg)
16
16
  end
17
17
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xls
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: