excel_walker 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NDgzODY3NzdiOTA0NzdhMzgwMzY5YmM4NDcyNjUwODY3Zjg1ODNjMg==
4
+ M2Y0NTYwMjQyYTEwMzhjYjU5NGMxNTQzNTY1ZWY0ZjgzMmRhMDZlZg==
5
5
  data.tar.gz: !binary |-
6
- Njg3MWMyNTVkNDM0OWRjMmUwM2I0MDZkNTRkNjJiN2U4Y2NiOTg5ZQ==
6
+ ODdiOWFhNmY0OGM4MjY0Y2IyZmE4YzRjYTQ0MjQ5OTcyMTMzYzBhOA==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- MjIzM2IyZDRhYWIzYjUwMmFlNTUxMjU3YjNhMjgxMGQyMjFmOWNkZjFkNTNh
10
- OGU1ODEyMWM3MjIyNzM3NjkxZGNjZDMzNWY1Njg4NGQzM2FmN2NjNmRmNjBl
11
- YzNhNmY4MmE2ZDJhNWE2ZjY2ZTgxZGZiNzA1M2IwNzBiMmM3YTA=
9
+ YjFiYjM3ZmQwYmE0MzA3YmM4YWMzZDIwOTNmYjFlYzRmZDUzNDRlYTQ3YTMx
10
+ YzU2M2U1ZjgyYmNjMjhjOWM1NzUwMjBiZGJlMTFkNDgyOWIxMGRjMTZhZTEy
11
+ YTgwOWRlNjkzY2FkNjM3MTc5ZmQ4NTQ2MWZiNWYzY2Y0OTZjNGQ=
12
12
  data.tar.gz: !binary |-
13
- YmY4MzAzZTJiN2EzOTQ2YzQ5MWIzNGVjNTZlNjM5ZTg0YThlZjExYWE3NDEx
14
- YjVjNTE2ZTE0ZmJjYjdmZTc0OTc1NWM0OTIwZWU5ZjZhNGIyYjk3Mzk5OTNl
15
- YzhkYjg0NTVjZTFmMmYxOWJkOWUxMzVlOGY3ZDZhZDMxNjY3Y2E=
13
+ ZWY3YzU0Y2E3ZTg1NGZlNjVjZTQyZThhYjJlMWI5ZGJjY2NlMjZmZDVkNmRl
14
+ NjdhNDQwN2JiYzBkNzRkNDYyZWI4NDVlNDhlMzk4NTEzNzI3ZjNmM2EwMmVh
15
+ NGJlNWMzZTQyZTcyODc1YjA3OGQ4YWYwYmQwZGM1OWY2ZDRmNjU=
@@ -2,11 +2,6 @@ language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
4
  - 2.0.0
5
-
6
- env:
7
- - "RAILS_VERSION=4.0"
8
- - "RAILS_VERSION=3.2"
9
- - "RAILS_VERSION=3.1"
10
- - "RAILS_VERSION=3.0"
5
+ - 2.1.0
11
6
 
12
7
  script: bundle exec rspec
data/README.md CHANGED
@@ -1,14 +1,14 @@
1
- # ExcelWalker
1
+ # ExcelWalker [![Gem Version](https://badge.fury.io/rb/excel_walker.png)](http://badge.fury.io/rb/excel_walker) [![Build Status](https://secure.travis-ci.org/shadabahmed/excel_walker.png)](https://secure.travis-ci.org/shadabahmed/excel_walker)
2
2
 
3
3
  Excel Walker is a declarative Microsoft Excel file parser and generator. It uses [Axlsx](https://github.com/randym/axlsx) to write and [Creek](https://github.com/pythonicrubyist/creek) to read.
4
4
 
5
5
  # Why I created this ?
6
6
 
7
- While dealing with Excel files recently, I noticed that excel files are never a set of homogenous data, which you can iterate over directly. Rather there are regions of interest whether in the same worksheet or across worksheets, which have different types of data you are interested in. For e.g. look at the spreadsheet below:
7
+ While dealing with Excel files recently, I noticed that excel files are never a set of homogenous data, which you can iterate over directly. Rather there are regions of interest whether in the same worksheet or across worksheets, which you want to work upon differently. For e.g. look at the spreadsheet below:
8
8
 
9
9
  ![currency_excel](https://cloud.githubusercontent.com/assets/830679/2937625/d333658e-d8bf-11e3-9619-658e20c425a0.png)
10
10
 
11
- We are not interested in the top header, we just want the country, currency and USD exchange rate so that we can store that in our database in currencies table. The regions are marked in RED. If you were to go interatively over each row, then lot of custom logic would have to fit in.
11
+ We are not interested in the top header, we just want the country, currency and USD exchange rate so that we can store that in our database in currencies table. The regions are marked in RED. If you were to go iteratively over each row, then lot of custom logic would have to fit in.
12
12
 
13
13
  What if you could just declare this - Start from row 3 and just give me 1st, 2nd and 4th column. Let's see this in code:
14
14
 
@@ -4,28 +4,32 @@ module ExcelWalker
4
4
  class Hook
5
5
  def initialize(condition)
6
6
  @matcher = case true
7
- when condition.respond_to?(:call)
7
+ when condition.is_a?(Proc)
8
8
  condition
9
9
  when condition.is_a?(Array), condition.is_a?(Range)
10
10
  proc { |row_num| condition.include?(row_num) }
11
11
  when condition.is_a?(Fixnum)
12
12
  proc { |row_num| condition === row_num }
13
+ else
14
+ raise ArgumentError.new('Can only take Array, Number, Range or a Block')
13
15
  end
14
16
  end
15
17
 
16
- def columns(cols_condition = nil, &block)
17
- cols_condition = block if block_given?
18
+ def columns(cols_matcher = nil, &block)
19
+ cols_matcher = block if block_given?
18
20
  @cols_extractor =
19
- case cols_condition.class.name
20
- when 'Array'
21
- cols_set = Set.new(cols_condition)
22
- proc { |row| row.values.select.with_index { |_, idx| cols_set.include?(idx + 1) } }
23
- when 'Fixnum'
24
- proc { |row| row.values[cols_condition - 1] }
25
- when 'Range'
26
- proc { |row| row.values[(cols_condition.min - 1)..(cols_condition.max - 1)] }
27
- when 'Proc'
28
- proc { |row| cols_condition[row.values] }
21
+ case true
22
+ when cols_matcher.is_a?(Array)
23
+ cols_set = Set.new(cols_matcher)
24
+ proc { |row| row.select.with_index { |_, idx| cols_set.include?(idx + 1) } }
25
+ when cols_matcher.is_a?(Fixnum)
26
+ proc { |row| row[cols_matcher - 1] }
27
+ when cols_matcher.is_a?(Range)
28
+ proc { |row| row[(cols_matcher.min - 1)..(cols_matcher.max - 1)] }
29
+ when cols_matcher.is_a?(Proc)
30
+ proc { |row| cols_matcher[row] }
31
+ else
32
+ raise ArgumentError.new('Can only take Array, Number, Range or a Block')
29
33
  end
30
34
  self
31
35
  end
@@ -36,7 +40,7 @@ module ExcelWalker
36
40
  @run_block = block
37
41
  end
38
42
 
39
- def match?(row_num, sheet_num)
43
+ def match?(row_num, sheet_num = nil)
40
44
  @matcher[row_num, sheet_num]
41
45
  end
42
46
 
@@ -67,7 +67,7 @@ module ExcelWalker
67
67
  row_num += 1
68
68
  break if @max_rows[sheet_num] && row_num > @max_rows[sheet_num]
69
69
  @hooks[sheet_num].each do |hook|
70
- hook.call(row, row_num, sheet, sheet_num) if hook.match?(row_num, sheet_num)
70
+ hook.call(row.values, row_num, sheet, sheet_num) if hook.match?(row_num, sheet_num)
71
71
  end
72
72
  end
73
73
  end
@@ -1,3 +1,3 @@
1
1
  module ExcelWalker
2
- VERSION = '0.1.1'
2
+ VERSION = '0.1.2'
3
3
  end
@@ -14,7 +14,7 @@ module ExcelWalker
14
14
  @max = condition
15
15
  proc { |row_num| condition === row_num }
16
16
  else
17
- raise ArgumentException.new('Can only take Range, Integers or Arrays here')
17
+ raise ArgumentError.new('Can only take Range, Integers or Arrays')
18
18
  end
19
19
  @row_index = 0
20
20
  end
@@ -0,0 +1,91 @@
1
+ require 'spec_helper'
2
+
3
+ module ExcelWalker::Reader
4
+ describe Hook do
5
+ subject(:hook) { Hook.new(proc { true }) }
6
+ it 'raises error on wrong initializaion' do
7
+ expect { Hook.new('string') }.to raise_error(ArgumentError, 'Can only take Array, Number, Range or a Block')
8
+ end
9
+
10
+ describe '#match?' do
11
+ context 'array condition for rows' do
12
+ subject(:hook) { Hook.new([1, 2, 3]) }
13
+ it 'gives correct output on match' do
14
+ expect(hook.match?(2)).to be_true
15
+ expect(hook.match?(0)).to be_false
16
+ end
17
+ end
18
+
19
+ context 'range condition for rows' do
20
+ subject(:hook) { Hook.new(1..3) }
21
+ it 'gives correct output on match' do
22
+ expect(hook.match?(2)).to be_true
23
+ expect(hook.match?(0)).to be_false
24
+ end
25
+ end
26
+
27
+ context 'number condition for rows' do
28
+ subject(:hook) { Hook.new(2) }
29
+ it 'gives correct output on match' do
30
+ expect(hook.match?(2)).to be_true
31
+ expect(hook.match?(3)).to be_false
32
+ end
33
+ end
34
+
35
+ context 'proc condition for rows' do
36
+ subject(:hook) { Hook.new(proc { |x, y| x == y && y == 2 }) }
37
+ it 'gives correct output on match' do
38
+ expect(hook.match?(2, 2)).to be_true
39
+ expect(hook.match?(2, 3)).to be_false
40
+ end
41
+ end
42
+ end
43
+
44
+ describe '#run' do
45
+ let(:hook_lambda) { proc {} }
46
+ it 'assigns the block to run when hook is executed' do
47
+ hook.run(&hook_lambda)
48
+ expect(hook.instance_variable_get('@run_block')).to eq hook_lambda
49
+ end
50
+ end
51
+
52
+ describe '#call' do
53
+ let(:collection) { (1..100).to_a }
54
+ let(:hook_block) { double }
55
+ before { subject.run { |a, b, c, d| hook_block.call(a, b, c, d) } }
56
+
57
+ context 'array column numbers matcher' do
58
+ subject { hook.columns([1, 2, 4]) }
59
+ it 'sends correct data to the hooked block' do
60
+ hook_block.should_receive(:call).with([1, 2, 4], 'b', 'c', 'd')
61
+ subject.call(collection, 'b', 'c', 'd')
62
+ end
63
+ end
64
+
65
+ context 'range column numbers matcher' do
66
+ subject { hook.columns(6..9) }
67
+ it 'sends correct data to the hooked block' do
68
+ hook_block.should_receive(:call).with([6, 7, 8, 9], 'b', 'c', 'd')
69
+ subject.call(collection, 'b', 'c', 'd')
70
+ end
71
+ end
72
+
73
+ context 'number column matcher' do
74
+ subject { hook.columns(11) }
75
+ it 'sends correct data to the hooked block' do
76
+ hook_block.should_receive(:call).with(11, 'b', 'c', 'd')
77
+ subject.call(collection, 'b', 'c', 'd')
78
+ end
79
+ end
80
+
81
+ context 'proc column matcher' do
82
+ subject { hook.columns {|row| row[96] } }
83
+ it 'sends correct data to the hooked block' do
84
+ hook_block.should_receive(:call).with(97, 'b', 'c', 'd')
85
+ subject.call(collection, 'b', 'c', 'd')
86
+ end
87
+ end
88
+ end
89
+
90
+ end
91
+ end
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+
3
+ module ExcelWalker::Writer
4
+ describe Cells do
5
+ subject(:cells) { Cells.new(:style) }
6
+
7
+ describe '#set_data_at' do
8
+ it 'sets data at specified position' do
9
+ cells.set_data_at(2, :data)
10
+ expect(cells.data).to eq [nil, nil, :data]
11
+ end
12
+
13
+ it 'sets data at specified range' do
14
+ cells.set_data_at(4..6, :data)
15
+ expect(cells.data).to eq [nil, nil, nil, nil, :data, :data, :data]
16
+ end
17
+ end
18
+
19
+ describe '#set_style_at' do
20
+ it 'sets style at specified position' do
21
+ cells.set_style_at(2, :style)
22
+ expect(cells.styles).to eq [nil, nil, :style]
23
+ end
24
+
25
+ it 'sets data at specified range' do
26
+ cells.set_style_at(4..6, :style)
27
+ expect(cells.styles).to eq [nil, nil, nil, nil, :style, :style, :style]
28
+ end
29
+ end
30
+
31
+ describe '#build' do
32
+
33
+ context 'when no data is set but width is set' do
34
+ it 'maps style for each data cell' do
35
+ cells.width = 4
36
+ cells.build
37
+ expect(cells.styles).to eq [:style, :style, :style, :style]
38
+ end
39
+ end
40
+
41
+ context 'when data is set' do
42
+ it 'maps style for each data cell' do
43
+ cells.set_data_at(3..5, :data)
44
+ cells.build
45
+ expect(cells.data).to eq [nil, nil, nil, :data, :data, :data]
46
+ expect(cells.styles).to eq [:style, :style, :style, :style, :style, :style]
47
+ end
48
+ end
49
+
50
+ context 'when both data and styles are set' do
51
+ it 'maps style for each data cell' do
52
+ cells.set_data_at(3..5, :data)
53
+ cells.set_style_at([2, 3, 5], :new_style)
54
+ cells.build
55
+ expect(cells.styles).to eq [:style, :style, :new_style, :new_style, :style, :new_style]
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,77 @@
1
+ require 'spec_helper'
2
+
3
+ module ExcelWalker::Writer
4
+ describe Hook do
5
+ subject(:hook) { Hook.new(0..100) }
6
+ it 'raises error on wrong initializaion' do
7
+ expect { Hook.new('string') }.to raise_error(ArgumentError, 'Can only take Range, Integers or Arrays')
8
+ end
9
+
10
+ describe '#match?' do
11
+ context 'array condition for rows' do
12
+ subject(:hook) { Hook.new([1, 2, 3]) }
13
+ it 'gives correct output on match' do
14
+ expect(hook.match?(2)).to be_true
15
+ expect(hook.match?(0)).to be_false
16
+ end
17
+ end
18
+
19
+ context 'range condition for rows' do
20
+ subject(:hook) { Hook.new(1..3) }
21
+ it 'gives correct output on match' do
22
+ expect(hook.match?(2)).to be_true
23
+ expect(hook.match?(0)).to be_false
24
+ end
25
+ end
26
+
27
+ context 'number condition for rows' do
28
+ subject(:hook) { Hook.new(2) }
29
+ it 'gives correct output on match' do
30
+ expect(hook.match?(2)).to be_true
31
+ expect(hook.match?(3)).to be_false
32
+ end
33
+ end
34
+ end
35
+
36
+ describe '#max' do
37
+ it 'gives the correct value of max row number for the hook' do
38
+ expect(Hook.new(0..100).max).to eq 100
39
+ expect(Hook.new([0, 1, 110]).max).to eq 110
40
+ expect(Hook.new(200).max).to eq 200
41
+ end
42
+ end
43
+
44
+ describe '#after_column' do
45
+ it 'assigns the block to run when hook is executed' do
46
+ hook.after_column(10)
47
+ expect(hook.instance_variable_get('@offset')).to eq 10
48
+ end
49
+ end
50
+
51
+
52
+ describe '#fill' do
53
+ let(:hook_lambda) { proc {} }
54
+ it 'assigns the block to run when hook is executed' do
55
+ hook.fill(&hook_lambda)
56
+ expect(hook.instance_variable_get('@filler')).to eq hook_lambda
57
+ end
58
+ end
59
+
60
+ describe '#run' do
61
+ let(:hook_block) { double }
62
+ let(:cells) { double(build: nil) }
63
+ before { subject.fill { |a, b, c| hook_block.call(a, b, c) } }
64
+ subject { hook.after_column(10) }
65
+ it 'sends correct data to the hooked block' do
66
+ Cells.should_receive(:new).times.exactly(2).and_return(cells)
67
+ #first run
68
+ hook_block.should_receive(:call).with(cells, 0, 5)
69
+ expect(subject.run(5)).to eq cells
70
+ #second run
71
+ hook_block.should_receive(:call).with(cells, 1, 6)
72
+ expect(subject.run(6)).to eq cells
73
+ end
74
+ end
75
+
76
+ end
77
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: excel_walker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shadab Ahmed
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-05-11 00:00:00.000000000 Z
11
+ date: 2014-05-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: creek