sycsvpro 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +21 -0
- data/.rspec +1 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +51 -0
- data/LICENSE +20 -0
- data/README.md +188 -0
- data/README.rdoc +44 -0
- data/Rakefile +44 -0
- data/bin/sycsvpro +208 -0
- data/features/step_definitions/sycsvpro_steps.rb +6 -0
- data/features/support/env.rb +15 -0
- data/features/sycsvpro.feature +8 -0
- data/html/Dsl.html +201 -0
- data/html/Object.html +116 -0
- data/html/README_rdoc.html +178 -0
- data/html/Sycsvpro/Analyzer.html +239 -0
- data/html/Sycsvpro/Calculator.html +354 -0
- data/html/Sycsvpro/Collector.html +281 -0
- data/html/Sycsvpro/ColumnFilter.html +165 -0
- data/html/Sycsvpro/Counter.html +397 -0
- data/html/Sycsvpro/Extractor.html +269 -0
- data/html/Sycsvpro/Filter.html +349 -0
- data/html/Sycsvpro/Header.html +228 -0
- data/html/Sycsvpro/Mapper.html +288 -0
- data/html/Sycsvpro/Profiler.html +234 -0
- data/html/Sycsvpro/RowFilter.html +162 -0
- data/html/Sycsvpro.html +141 -0
- data/html/created.rid +17 -0
- data/html/fonts/Lato-Light.ttf +0 -0
- data/html/fonts/Lato-LightItalic.ttf +0 -0
- data/html/fonts/Lato-Regular.ttf +0 -0
- data/html/fonts/Lato-RegularItalic.ttf +0 -0
- data/html/fonts/SourceCodePro-Bold.ttf +0 -0
- data/html/fonts/SourceCodePro-Regular.ttf +0 -0
- data/html/fonts.css +167 -0
- data/html/images/add.png +0 -0
- data/html/images/arrow_up.png +0 -0
- data/html/images/brick.png +0 -0
- data/html/images/brick_link.png +0 -0
- data/html/images/bug.png +0 -0
- data/html/images/bullet_black.png +0 -0
- data/html/images/bullet_toggle_minus.png +0 -0
- data/html/images/bullet_toggle_plus.png +0 -0
- data/html/images/date.png +0 -0
- data/html/images/delete.png +0 -0
- data/html/images/find.png +0 -0
- data/html/images/loadingAnimation.gif +0 -0
- data/html/images/macFFBgHack.png +0 -0
- data/html/images/package.png +0 -0
- data/html/images/page_green.png +0 -0
- data/html/images/page_white_text.png +0 -0
- data/html/images/page_white_width.png +0 -0
- data/html/images/plugin.png +0 -0
- data/html/images/ruby.png +0 -0
- data/html/images/tag_blue.png +0 -0
- data/html/images/tag_green.png +0 -0
- data/html/images/transparent.png +0 -0
- data/html/images/wrench.png +0 -0
- data/html/images/wrench_orange.png +0 -0
- data/html/images/zoom.png +0 -0
- data/html/index.html +202 -0
- data/html/js/darkfish.js +140 -0
- data/html/js/jquery.js +18 -0
- data/html/js/navigation.js +142 -0
- data/html/js/search.js +109 -0
- data/html/js/search_index.js +1 -0
- data/html/js/searcher.js +228 -0
- data/html/rdoc.css +580 -0
- data/html/table_of_contents.html +236 -0
- data/lib/sycsvpro/analyzer.rb +40 -0
- data/lib/sycsvpro/calculator.rb +94 -0
- data/lib/sycsvpro/collector.rb +60 -0
- data/lib/sycsvpro/column_filter.rb +23 -0
- data/lib/sycsvpro/counter.rb +74 -0
- data/lib/sycsvpro/dsl.rb +37 -0
- data/lib/sycsvpro/extractor.rb +39 -0
- data/lib/sycsvpro/filter.rb +98 -0
- data/lib/sycsvpro/header.rb +29 -0
- data/lib/sycsvpro/mapper.rb +53 -0
- data/lib/sycsvpro/profiler.rb +26 -0
- data/lib/sycsvpro/row_filter.rb +20 -0
- data/lib/sycsvpro/version.rb +5 -0
- data/lib/sycsvpro.rb +9 -0
- data/spec/sycsvpro/analyze_spec.rb +23 -0
- data/spec/sycsvpro/calculator_spec.rb +45 -0
- data/spec/sycsvpro/collector_spec.rb +27 -0
- data/spec/sycsvpro/counter_spec.rb +51 -0
- data/spec/sycsvpro/extractor_spec.rb +27 -0
- data/spec/sycsvpro/files/mappings +6 -0
- data/spec/sycsvpro/files/profile.rb +42 -0
- data/spec/sycsvpro/mapper_spec.rb +33 -0
- data/spec/sycsvpro/profiler_spec.rb +32 -0
- data/sycsvpro.gemspec +24 -0
- data/sycsvpro.rdoc +29 -0
- metadata +215 -0
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
# Operating csv files
|
4
|
+
module Sycsvpro
|
5
|
+
|
6
|
+
# Creates a new filter that can be extended by sub-classes. A sub-class needs to override the
|
7
|
+
# process method
|
8
|
+
class Filter
|
9
|
+
|
10
|
+
# When date are used as filters the date format has to be provided
|
11
|
+
attr_reader :date_format
|
12
|
+
# Filter for rows and columns
|
13
|
+
attr_reader :filter
|
14
|
+
# Pattern that is used as a filter
|
15
|
+
attr_reader :pattern
|
16
|
+
# Comparison that is used as a filter
|
17
|
+
attr_reader :pivot
|
18
|
+
|
19
|
+
# Creates a new filter
|
20
|
+
def initialize(values, options={})
|
21
|
+
@date_format = options[:df] || "%Y-%m-%d"
|
22
|
+
@filter = []
|
23
|
+
@pattern = []
|
24
|
+
@pivot = {}
|
25
|
+
create_filter(values)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Creates the filters based on the given patterns
|
29
|
+
def method_missing(id, *args, &block)
|
30
|
+
return equal($1, args, block) if id =~ /^(\d+)$/
|
31
|
+
return range($1, $2, args, block) if id =~ /^(\d+)-(\d+)$/
|
32
|
+
return regex($1, args, block) if id =~ /^\/(.*)\/$/
|
33
|
+
return col_regex($1, $2, args, block) if id =~ /^(\d+):\/(.*)\/$/
|
34
|
+
return date($1, $2, $3, args, block) if id =~ /^(\d+):(<|=|>)(\d+.\d+.\d+)/
|
35
|
+
return date_range($1, $2, $3, args, block) if id =~ /^(\d+):(\d+.\d+.\d+.)-(\d+.\d+.\d+)$/
|
36
|
+
super
|
37
|
+
end
|
38
|
+
|
39
|
+
# Processes the filter. Needs to be overridden by the sub-class
|
40
|
+
def process(object, options={})
|
41
|
+
raise 'Needs to be overridden by sub class'
|
42
|
+
end
|
43
|
+
|
44
|
+
# Yields the column value and whether the filter matches the column
|
45
|
+
def pivot_each_column(values=[])
|
46
|
+
pivot.each do |column, parameters|
|
47
|
+
yield column, eval(parameters[:operation].gsub('[value]', values[parameters[:col].to_i]))
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
# Creates a filter based on the provided rows and columns
|
54
|
+
def create_filter(values)
|
55
|
+
values.split(',').each { |f| send(f) } unless values.nil?
|
56
|
+
end
|
57
|
+
|
58
|
+
# Adds a single value to the filter
|
59
|
+
def equal(value, args, block)
|
60
|
+
filter << value.to_i unless filter.index(value.to_i)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Adds a range to the filter
|
64
|
+
def range(start_value, end_value, args, block)
|
65
|
+
filter << (start_value.to_i..end_value.to_i).to_a
|
66
|
+
end
|
67
|
+
|
68
|
+
# Adds a regex to the pattern filter
|
69
|
+
def regex(value, args, block)
|
70
|
+
pattern << value unless pattern.index(value)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Adds a comparisson filter
|
74
|
+
def col_regex(col, r, args, block)
|
75
|
+
operation = "'[value]' =~ Regexp.new('#{r}')"
|
76
|
+
pivot[r] = { col: col, operation: operation }
|
77
|
+
end
|
78
|
+
|
79
|
+
# Adds a date filter
|
80
|
+
def date(col, comparator, date, args, block)
|
81
|
+
comparator = '==' if comparator == '='
|
82
|
+
operation = "Date.strptime(\"[value]\", \"#{date_format}\") #{comparator} " +
|
83
|
+
"Date.strptime(\"#{date}\", \"#{date_format}\")"
|
84
|
+
pivot["#{comparator}#{date}"] = { col: col, operation: operation }
|
85
|
+
end
|
86
|
+
|
87
|
+
# Adds a date range filter
|
88
|
+
def date_range(col, start_date, end_date, args, block)
|
89
|
+
operation = " Date.strptime(\"#{start_date}\", \"#{date_format}\") " +
|
90
|
+
"<= Date.strptime(\"[value]\", \"#{date_format}\") && " +
|
91
|
+
" Date.strptime(\"[value]\", \"#{date_format}\") " +
|
92
|
+
"<= Date.strptime(\"#{end_date}\", \"#{date_format}\")"
|
93
|
+
pivot["#{start_date}-#{end_date}"] = { col: col, operation: operation }
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative 'filter'
|
2
|
+
|
3
|
+
# Operating csv files
|
4
|
+
module Sycsvpro
|
5
|
+
|
6
|
+
# Creates a header
|
7
|
+
class Header < Filter
|
8
|
+
|
9
|
+
# Header columns
|
10
|
+
attr_reader :header_cols
|
11
|
+
|
12
|
+
# Create a new header
|
13
|
+
def initialize(header)
|
14
|
+
unless header.nil? or header.empty?
|
15
|
+
@header_cols = header.split(',')
|
16
|
+
else
|
17
|
+
@header_cols = []
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns the header
|
22
|
+
def process(line)
|
23
|
+
return "" if @header_cols.empty?
|
24
|
+
@header_cols[0] = line.split(';')
|
25
|
+
@header_cols.flatten.join(';')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# Operating csv files
|
2
|
+
module Sycsvpro
|
3
|
+
|
4
|
+
# Map values to new values described in a mapping file
|
5
|
+
class Mapper
|
6
|
+
|
7
|
+
# infile contains the data that is operated on
|
8
|
+
attr_reader :infile
|
9
|
+
# outfile is the file where the result is written to
|
10
|
+
attr_reader :outfile
|
11
|
+
# file that contains the mappings from existing column values to new values
|
12
|
+
attr_reader :mapper
|
13
|
+
# filter that is used for rows
|
14
|
+
attr_reader :row_filter
|
15
|
+
# filter that is used for columns
|
16
|
+
attr_reader :col_filter
|
17
|
+
|
18
|
+
# Creates new mapper
|
19
|
+
def initialize(options={})
|
20
|
+
@infile = options[:infile]
|
21
|
+
@outfile = options[:outfile]
|
22
|
+
@row_filter = RowFilter.new(options[:row_filter])
|
23
|
+
@col_filter = ColumnFilter.new(options[:col_filter])
|
24
|
+
@mapper = {}
|
25
|
+
init_mapper(options[:mapping])
|
26
|
+
end
|
27
|
+
|
28
|
+
# Executes the mapper
|
29
|
+
def execute
|
30
|
+
File.open(outfile, 'w') do |out|
|
31
|
+
File.new(infile, 'r').each_with_index do |line, index|
|
32
|
+
result = col_filter.process(row_filter.process(line, row: index))
|
33
|
+
next if result.chomp.empty? or result.nil?
|
34
|
+
mapper.each do |from, to|
|
35
|
+
result = result.chomp.gsub(/(?<=^|;)#{from}(?=;|$)/, to)
|
36
|
+
end
|
37
|
+
out.puts result
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
# Initializes the mappings
|
45
|
+
def init_mapper(file)
|
46
|
+
File.new(file, 'r').each_line do |line|
|
47
|
+
from, to = line.chomp.split(':')
|
48
|
+
mapper[from] = to
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require_relative 'dsl'
|
2
|
+
|
3
|
+
# Operating csv files
|
4
|
+
module Sycsvpro
|
5
|
+
|
6
|
+
# A profiler takes a Ruby script and executes the provided method in the script
|
7
|
+
class Profiler
|
8
|
+
|
9
|
+
include Dsl
|
10
|
+
|
11
|
+
# Ruby script file
|
12
|
+
attr_reader :pro_file
|
13
|
+
|
14
|
+
# Creates a new profiler
|
15
|
+
def initialize(pro_file)
|
16
|
+
require pro_file
|
17
|
+
end
|
18
|
+
|
19
|
+
# Executes the provided method in the Ruby script
|
20
|
+
def execute(method)
|
21
|
+
send(method)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require_relative 'filter'
|
2
|
+
|
3
|
+
# Operating csv files
|
4
|
+
module Sycsvpro
|
5
|
+
|
6
|
+
# Filters rows based on provided patterns
|
7
|
+
class RowFilter < Filter
|
8
|
+
|
9
|
+
# Processes the filter on the given row
|
10
|
+
def process(object, options={})
|
11
|
+
filtered = (!filter.flatten.uniq.index(options[:row]).nil? or filter.empty?)
|
12
|
+
pattern.each do |p|
|
13
|
+
filtered = (filtered or !(object =~ Regexp.new(p)).nil?)
|
14
|
+
end
|
15
|
+
filtered ? object : nil
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
data/lib/sycsvpro.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'sycsvpro/version.rb'
|
2
|
+
require 'sycsvpro/analyzer.rb'
|
3
|
+
require 'sycsvpro/extractor.rb'
|
4
|
+
require 'sycsvpro/profiler.rb'
|
5
|
+
require 'sycsvpro/counter.rb'
|
6
|
+
require 'sycsvpro/collector.rb'
|
7
|
+
require 'sycsvpro/mapper.rb'
|
8
|
+
require 'sycsvpro/header.rb'
|
9
|
+
require 'sycsvpro/calculator.rb'
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'sycsvpro/analyzer.rb'
|
2
|
+
|
3
|
+
module Sycsvpro
|
4
|
+
|
5
|
+
describe Analyzer do
|
6
|
+
|
7
|
+
before do
|
8
|
+
@in_file = File.join(File.dirname(__FILE__), "files/in.csv")
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should analyze infile" do
|
12
|
+
analyzer = Analyzer.new(@in_file)
|
13
|
+
result = analyzer.result
|
14
|
+
result.cols.should =~ ['customer', 'contract-number', 'expires-on', 'machine',
|
15
|
+
'product1', 'product2']
|
16
|
+
result.col_count.should eq 6
|
17
|
+
result.row_count.should eq 5
|
18
|
+
result.sample_row.should eq "Fink;1234;20.12.2015;f1;con123;dri222"
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'sycsvpro/calculator.rb'
|
2
|
+
|
3
|
+
module Sycsvpro
|
4
|
+
|
5
|
+
describe Calculator do
|
6
|
+
|
7
|
+
before do
|
8
|
+
@in_file = File.join(File.dirname(__FILE__), "files/machines.csv")
|
9
|
+
@out_file = File.join(File.dirname(__FILE__), "files/machines_out.csv")
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should operate on existing row" do
|
13
|
+
rows = "2-8"
|
14
|
+
cols = "3:*3,4:*4+1"
|
15
|
+
calculator = Calculator.new(infile: @in_file, outfile: @out_file, rows: rows, cols: cols)
|
16
|
+
calculator.execute
|
17
|
+
|
18
|
+
result = ["Fink;2;2;3;5", "Haas;3;3;3;5.0", "Gent;4;4;3;5", "Rank;5;5;3;5"]
|
19
|
+
|
20
|
+
File.new(@out_file, 'r').each_with_index do |line, index|
|
21
|
+
expect(line.chomp).to eq result[index]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should add additional rows" do
|
26
|
+
header = "*,drives,motors"
|
27
|
+
rows = "1-8"
|
28
|
+
cols = "5:c3+c4,6:c3*2"
|
29
|
+
calculator = Calculator.new(infile: @in_file, outfile: @out_file,
|
30
|
+
header: header, rows: rows, cols: cols)
|
31
|
+
calculator.execute
|
32
|
+
|
33
|
+
result = ["customer;machines;controls;contracts;visits;drives;motors",
|
34
|
+
"Fink;2;2;1;1;2;2",
|
35
|
+
"Haas;3;3;1;1.0;2.0;2",
|
36
|
+
"Gent;4;4;1;1;2;2",
|
37
|
+
"Rank;5;5;1;1;2;2"]
|
38
|
+
|
39
|
+
File.new(@out_file, 'r').each_with_index do |line, index|
|
40
|
+
expect(line.chomp).to eq result[index]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'sycsvpro/collector.rb'
|
2
|
+
|
3
|
+
module Sycsvpro
|
4
|
+
|
5
|
+
describe Collector do
|
6
|
+
|
7
|
+
before do
|
8
|
+
@in_file = File.join(File.dirname(__FILE__), "files/in.csv")
|
9
|
+
@out_file = File.join(File.dirname(__FILE__), "files/out.csv")
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should collect and categorize values" do
|
13
|
+
collector = Collector.new(infile: @in_file, outfile: @out_file,
|
14
|
+
cols: "customer:0+products:4,5", rows: "1-20")
|
15
|
+
collector.execute
|
16
|
+
|
17
|
+
result = ['[customer]', 'Fink', 'Gent', 'Haas', 'Rank',
|
18
|
+
'[products]', 'con123', 'con332', 'con333',
|
19
|
+
'dri111', 'dri222', 'dri321']
|
20
|
+
File.open(@out_file).each_with_index do |line, index|
|
21
|
+
line.chomp.should eq result[index]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'sycsvpro/counter.rb'
|
2
|
+
|
3
|
+
module Sycsvpro
|
4
|
+
|
5
|
+
describe Counter do
|
6
|
+
|
7
|
+
before do
|
8
|
+
@in_file = File.join(File.dirname(__FILE__), "files/in.csv")
|
9
|
+
@out_file = File.join(File.dirname(__FILE__), "files/out.csv")
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should count columns" do
|
13
|
+
counter = Counter.new(infile: @in_file, outfile: @out_file, rows: "1-10", cols: "4,5",
|
14
|
+
key: "0")
|
15
|
+
|
16
|
+
counter.execute
|
17
|
+
|
18
|
+
result = [ "customer;con123;con332;con333;dri111;dri222;dri321",
|
19
|
+
"Fink;1;0;1;0;1;1",
|
20
|
+
"Haas;0;1;0;1;0;0",
|
21
|
+
"Gent;1;0;0;1;0;0",
|
22
|
+
"Rank;0;1;0;0;0;1" ]
|
23
|
+
|
24
|
+
File.open(@out_file).each_with_index do |line, index|
|
25
|
+
line.chomp.should eq result[index]
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should count date coloms" do
|
31
|
+
counter = Counter.new(infile: @in_file, outfile: @out_file, rows: "1-10",
|
32
|
+
cols: "2:<1.1.2013,2:1.1.2013-31.12.2014,2:>31.12.2014", key: "0",
|
33
|
+
df: "%d.%m.%Y")
|
34
|
+
|
35
|
+
counter.execute
|
36
|
+
|
37
|
+
result = [ "customer;1.1.2013-31.12.2014;<1.1.2013;>31.12.2014",
|
38
|
+
"Fink;0;0;2",
|
39
|
+
"Haas;0;1;0",
|
40
|
+
"Gent;1;0;0",
|
41
|
+
"Rank;1;0;0" ]
|
42
|
+
|
43
|
+
File.open(@out_file).each_with_index do |line, index|
|
44
|
+
line.chomp.should eq result[index]
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'sycsvpro/extractor.rb'
|
2
|
+
|
3
|
+
module Sycsvpro
|
4
|
+
|
5
|
+
describe Extractor do
|
6
|
+
|
7
|
+
before do
|
8
|
+
@in_file = File.join(File.dirname(__FILE__), "files/in.csv")
|
9
|
+
@out_file = File.join(File.dirname(__FILE__), "files/out.csv")
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should extract rows and columns" do
|
13
|
+
extractor = Extractor.new(infile: @in_file, outfile: @out_file, rows: "2-4", cols: "1,3")
|
14
|
+
|
15
|
+
extractor.execute
|
16
|
+
|
17
|
+
result = ["3322;h1", "4323;g1", "3342;f2"]
|
18
|
+
|
19
|
+
File.open(@out_file).each_with_index do |line, index|
|
20
|
+
line.chomp.should eq result[index]
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# This is an example of a sycsvpro DSL to process a CSV file
|
2
|
+
|
3
|
+
def calc
|
4
|
+
|
5
|
+
customers = {}
|
6
|
+
heading = []
|
7
|
+
|
8
|
+
rows infile: "./spec/sycsvpro/files/in.csv",
|
9
|
+
row_filter: "1-20",
|
10
|
+
key_column: 0,
|
11
|
+
machine_column: 3,
|
12
|
+
data_columns: [4,5] do |key, machine, columns|
|
13
|
+
customer = customers[key] || customers[key] = { name: key, products: Hash.new(0) }
|
14
|
+
columns.each do |column|
|
15
|
+
heading << column if heading.index(column).nil?
|
16
|
+
customer[:products][column] += 1
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# puts heading.sort.join('-')
|
21
|
+
|
22
|
+
=begin
|
23
|
+
customers.each do |k,v|
|
24
|
+
print k
|
25
|
+
heading.sort.each do |h|
|
26
|
+
print " #{v[:products][h]} "
|
27
|
+
end
|
28
|
+
puts
|
29
|
+
end
|
30
|
+
=end
|
31
|
+
|
32
|
+
write_to "./spec/sycsvpro/files/out.csv" do |out|
|
33
|
+
out.puts (["customer"] + heading.sort).join(';')
|
34
|
+
customers.each do |k,v|
|
35
|
+
line = [k]
|
36
|
+
heading.sort.each do |h|
|
37
|
+
line << v[:products][h]
|
38
|
+
end
|
39
|
+
out.puts line.join(';')
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'sycsvpro/mapper.rb'
|
2
|
+
|
3
|
+
module Sycsvpro
|
4
|
+
|
5
|
+
describe Mapper do
|
6
|
+
|
7
|
+
before do
|
8
|
+
@in_file = File.join(File.dirname(__FILE__), "files/in.csv")
|
9
|
+
@out_file = File.join(File.dirname(__FILE__), "files/out.csv")
|
10
|
+
@mappings = File.join(File.dirname(__FILE__), "files/mappings")
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should map values to new values" do
|
14
|
+
mapper = Mapper.new(infile: @in_file, outfile: @out_file, mapping: @mappings)
|
15
|
+
|
16
|
+
mapper.execute
|
17
|
+
|
18
|
+
result = [ "customer;contract-number;expires-on;machine;product1;product2",
|
19
|
+
"Fink;1234;20.12.2015;f1;control123;drive222",
|
20
|
+
"Haas;3322;1.10.2011;h1;control332;drive111",
|
21
|
+
"Gent;4323;1.3.2014;g1;control123;drive111",
|
22
|
+
"Fink;3342;30.12.2016;f2;control333;drive321",
|
23
|
+
"Rank;3232;1.5.2013;r1;control332;drive321" ]
|
24
|
+
|
25
|
+
File.open(@out_file).each_with_index do |line, index|
|
26
|
+
line.chomp.should eq result[index]
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'sycsvpro/profiler.rb'
|
2
|
+
|
3
|
+
module Sycsvpro
|
4
|
+
|
5
|
+
describe Profiler do
|
6
|
+
|
7
|
+
before do
|
8
|
+
@profile = File.join(File.dirname(__FILE__), "files/profile.rb")
|
9
|
+
@method = "calc"
|
10
|
+
@out_file = File.join(File.dirname(__FILE__), "files/out.csv")
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should execute the profile file" do
|
14
|
+
profiler = Profiler.new(@profile)
|
15
|
+
|
16
|
+
profiler.execute(@method)
|
17
|
+
|
18
|
+
result = [ "customer;con123;con332;con333;dri111;dri222;dri321",
|
19
|
+
"Fink;1;0;1;0;1;1",
|
20
|
+
"Haas;0;1;0;1;0;0",
|
21
|
+
"Gent;1;0;0;1;0;0",
|
22
|
+
"Rank;0;1;0;0;0;1" ]
|
23
|
+
|
24
|
+
File.open(@out_file).each_with_index do |line, index|
|
25
|
+
line.chomp.should eq result[index]
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
data/sycsvpro.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# Ensure we require the local version and not one we might have installed already
|
2
|
+
require File.join([File.dirname(__FILE__),'lib','sycsvpro','version.rb'])
|
3
|
+
spec = Gem::Specification.new do |s|
|
4
|
+
s.name = 'sycsvpro'
|
5
|
+
s.version = Sycsvpro::VERSION
|
6
|
+
s.author = 'Pierre Sugar'
|
7
|
+
s.email = 'pierre@sugaryourcoffee.de'
|
8
|
+
s.homepage = 'https://github.com/sugaryourcoffee/syc-svpro'
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
s.summary = 'Processing of csv files'
|
11
|
+
s.files = `git ls-files`.split("
|
12
|
+
")
|
13
|
+
s.require_paths << 'lib'
|
14
|
+
s.has_rdoc = true
|
15
|
+
s.extra_rdoc_files = ['README.rdoc','sycsvpro.rdoc']
|
16
|
+
s.rdoc_options << '--title' << 'sycsvpro' << '--main' << 'README.rdoc' << '-ri'
|
17
|
+
s.bindir = 'bin'
|
18
|
+
s.executables << 'sycsvpro'
|
19
|
+
s.add_development_dependency('rake')
|
20
|
+
s.add_development_dependency('rdoc')
|
21
|
+
s.add_development_dependency('aruba')
|
22
|
+
s.add_development_dependency('rspec')
|
23
|
+
s.add_runtime_dependency('gli','2.9.0')
|
24
|
+
end
|
data/sycsvpro.rdoc
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
= sycsvpro
|
2
|
+
|
3
|
+
NAME
|
4
|
+
sycsvpro - Processing CSV files
|
5
|
+
|
6
|
+
SYNOPSIS
|
7
|
+
sycsvpro [global options] command [command options] [arguments...]
|
8
|
+
|
9
|
+
VERSION
|
10
|
+
0.0.1
|
11
|
+
|
12
|
+
GLOBAL OPTIONS
|
13
|
+
-f, --file=FILE - CSV file to operate on (default: none)
|
14
|
+
--help - Show this message
|
15
|
+
-o, --out=OUT_FILE - CSV file to write the result to (default: none)
|
16
|
+
--version - Display the program version
|
17
|
+
|
18
|
+
COMMANDS
|
19
|
+
analyze - Analyze the CSV file regarding columns, rows and content
|
20
|
+
calc - Process math operations on columns
|
21
|
+
collect - Collect values of specified rows and columns from the file and group them in
|
22
|
+
categories
|
23
|
+
count - Counts the occurences of column values. Uses column values as headings with count as
|
24
|
+
values. Columns with a condition will be added as new columns and the condition will
|
25
|
+
be set as column name
|
26
|
+
execute - Executes the code provided in a file
|
27
|
+
extract - Extract specified rows and columns from the file
|
28
|
+
help - Shows a list of commands or help for one command
|
29
|
+
map - Map values in columns to new values
|