sycsvpro 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.rspec +1 -0
  4. data/Gemfile +2 -0
  5. data/Gemfile.lock +51 -0
  6. data/LICENSE +20 -0
  7. data/README.md +188 -0
  8. data/README.rdoc +44 -0
  9. data/Rakefile +44 -0
  10. data/bin/sycsvpro +208 -0
  11. data/features/step_definitions/sycsvpro_steps.rb +6 -0
  12. data/features/support/env.rb +15 -0
  13. data/features/sycsvpro.feature +8 -0
  14. data/html/Dsl.html +201 -0
  15. data/html/Object.html +116 -0
  16. data/html/README_rdoc.html +178 -0
  17. data/html/Sycsvpro/Analyzer.html +239 -0
  18. data/html/Sycsvpro/Calculator.html +354 -0
  19. data/html/Sycsvpro/Collector.html +281 -0
  20. data/html/Sycsvpro/ColumnFilter.html +165 -0
  21. data/html/Sycsvpro/Counter.html +397 -0
  22. data/html/Sycsvpro/Extractor.html +269 -0
  23. data/html/Sycsvpro/Filter.html +349 -0
  24. data/html/Sycsvpro/Header.html +228 -0
  25. data/html/Sycsvpro/Mapper.html +288 -0
  26. data/html/Sycsvpro/Profiler.html +234 -0
  27. data/html/Sycsvpro/RowFilter.html +162 -0
  28. data/html/Sycsvpro.html +141 -0
  29. data/html/created.rid +17 -0
  30. data/html/fonts/Lato-Light.ttf +0 -0
  31. data/html/fonts/Lato-LightItalic.ttf +0 -0
  32. data/html/fonts/Lato-Regular.ttf +0 -0
  33. data/html/fonts/Lato-RegularItalic.ttf +0 -0
  34. data/html/fonts/SourceCodePro-Bold.ttf +0 -0
  35. data/html/fonts/SourceCodePro-Regular.ttf +0 -0
  36. data/html/fonts.css +167 -0
  37. data/html/images/add.png +0 -0
  38. data/html/images/arrow_up.png +0 -0
  39. data/html/images/brick.png +0 -0
  40. data/html/images/brick_link.png +0 -0
  41. data/html/images/bug.png +0 -0
  42. data/html/images/bullet_black.png +0 -0
  43. data/html/images/bullet_toggle_minus.png +0 -0
  44. data/html/images/bullet_toggle_plus.png +0 -0
  45. data/html/images/date.png +0 -0
  46. data/html/images/delete.png +0 -0
  47. data/html/images/find.png +0 -0
  48. data/html/images/loadingAnimation.gif +0 -0
  49. data/html/images/macFFBgHack.png +0 -0
  50. data/html/images/package.png +0 -0
  51. data/html/images/page_green.png +0 -0
  52. data/html/images/page_white_text.png +0 -0
  53. data/html/images/page_white_width.png +0 -0
  54. data/html/images/plugin.png +0 -0
  55. data/html/images/ruby.png +0 -0
  56. data/html/images/tag_blue.png +0 -0
  57. data/html/images/tag_green.png +0 -0
  58. data/html/images/transparent.png +0 -0
  59. data/html/images/wrench.png +0 -0
  60. data/html/images/wrench_orange.png +0 -0
  61. data/html/images/zoom.png +0 -0
  62. data/html/index.html +202 -0
  63. data/html/js/darkfish.js +140 -0
  64. data/html/js/jquery.js +18 -0
  65. data/html/js/navigation.js +142 -0
  66. data/html/js/search.js +109 -0
  67. data/html/js/search_index.js +1 -0
  68. data/html/js/searcher.js +228 -0
  69. data/html/rdoc.css +580 -0
  70. data/html/table_of_contents.html +236 -0
  71. data/lib/sycsvpro/analyzer.rb +40 -0
  72. data/lib/sycsvpro/calculator.rb +94 -0
  73. data/lib/sycsvpro/collector.rb +60 -0
  74. data/lib/sycsvpro/column_filter.rb +23 -0
  75. data/lib/sycsvpro/counter.rb +74 -0
  76. data/lib/sycsvpro/dsl.rb +37 -0
  77. data/lib/sycsvpro/extractor.rb +39 -0
  78. data/lib/sycsvpro/filter.rb +98 -0
  79. data/lib/sycsvpro/header.rb +29 -0
  80. data/lib/sycsvpro/mapper.rb +53 -0
  81. data/lib/sycsvpro/profiler.rb +26 -0
  82. data/lib/sycsvpro/row_filter.rb +20 -0
  83. data/lib/sycsvpro/version.rb +5 -0
  84. data/lib/sycsvpro.rb +9 -0
  85. data/spec/sycsvpro/analyze_spec.rb +23 -0
  86. data/spec/sycsvpro/calculator_spec.rb +45 -0
  87. data/spec/sycsvpro/collector_spec.rb +27 -0
  88. data/spec/sycsvpro/counter_spec.rb +51 -0
  89. data/spec/sycsvpro/extractor_spec.rb +27 -0
  90. data/spec/sycsvpro/files/mappings +6 -0
  91. data/spec/sycsvpro/files/profile.rb +42 -0
  92. data/spec/sycsvpro/mapper_spec.rb +33 -0
  93. data/spec/sycsvpro/profiler_spec.rb +32 -0
  94. data/sycsvpro.gemspec +24 -0
  95. data/sycsvpro.rdoc +29 -0
  96. metadata +215 -0
@@ -0,0 +1,236 @@
1
+ <!DOCTYPE html>
2
+
3
+ <html>
4
+ <head>
5
+ <meta charset="UTF-8">
6
+
7
+ <title>Table of Contents - Your application title</title>
8
+
9
+ <link href="./fonts.css" rel="stylesheet">
10
+ <link href="./rdoc.css" rel="stylesheet">
11
+
12
+ <script type="text/javascript">
13
+ var rdoc_rel_prefix = "./";
14
+ </script>
15
+
16
+ <script src="./js/jquery.js"></script>
17
+ <script src="./js/navigation.js"></script>
18
+ <script src="./js/search_index.js"></script>
19
+ <script src="./js/search.js"></script>
20
+ <script src="./js/searcher.js"></script>
21
+ <script src="./js/darkfish.js"></script>
22
+
23
+
24
+ <body id="top" class="table-of-contents">
25
+ <main role="main">
26
+ <h1 class="class">Table of Contents - Your application title</h1>
27
+
28
+ <h2 id="pages">Pages</h2>
29
+ <ul>
30
+ <li class="file">
31
+ <a href="README_rdoc.html">README</a>
32
+
33
+ <ul>
34
+ <li><a href="README_rdoc.html#label-sycsvpro">sycsvpro</a>
35
+ <li><a href="README_rdoc.html#label-Install">Install</a>
36
+ <li><a href="README_rdoc.html#label-Use">Use</a>
37
+ <li><a href="README_rdoc.html#label-Developing+for+%60sycsvpro%60">Developing for `sycsvpro`</a>
38
+ <li><a href="README_rdoc.html#label-sycsvpro">sycsvpro</a>
39
+ </ul>
40
+ </li>
41
+
42
+ </ul>
43
+
44
+ <h2 id="classes">Classes and Modules</h2>
45
+ <ul>
46
+ <li class="module">
47
+ <a href="Dsl.html">Dsl</a>
48
+ </li>
49
+ <li class="class">
50
+ <a href="Object.html">Object</a>
51
+ </li>
52
+ <li class="module">
53
+ <a href="Sycsvpro.html">Sycsvpro</a>
54
+ </li>
55
+ <li class="class">
56
+ <a href="Sycsvpro/Analyzer.html">Sycsvpro::Analyzer</a>
57
+ </li>
58
+ <li class="class">
59
+ <a href="Sycsvpro/Calculator.html">Sycsvpro::Calculator</a>
60
+ </li>
61
+ <li class="class">
62
+ <a href="Sycsvpro/Collector.html">Sycsvpro::Collector</a>
63
+ </li>
64
+ <li class="class">
65
+ <a href="Sycsvpro/ColumnFilter.html">Sycsvpro::ColumnFilter</a>
66
+ </li>
67
+ <li class="class">
68
+ <a href="Sycsvpro/Counter.html">Sycsvpro::Counter</a>
69
+ </li>
70
+ <li class="class">
71
+ <a href="Sycsvpro/Extractor.html">Sycsvpro::Extractor</a>
72
+ </li>
73
+ <li class="class">
74
+ <a href="Sycsvpro/Filter.html">Sycsvpro::Filter</a>
75
+ </li>
76
+ <li class="class">
77
+ <a href="Sycsvpro/Header.html">Sycsvpro::Header</a>
78
+ </li>
79
+ <li class="class">
80
+ <a href="Sycsvpro/Mapper.html">Sycsvpro::Mapper</a>
81
+ </li>
82
+ <li class="class">
83
+ <a href="Sycsvpro/Profiler.html">Sycsvpro::Profiler</a>
84
+ </li>
85
+ <li class="class">
86
+ <a href="Sycsvpro/RowFilter.html">Sycsvpro::RowFilter</a>
87
+ </li>
88
+ </ul>
89
+
90
+ <h2 id="methods">Methods</h2>
91
+ <ul>
92
+
93
+ <li class="method">
94
+ <a href="Sycsvpro/Analyzer.html#method-c-new">::new</a>
95
+ &mdash;
96
+ <span class="container">Sycsvpro::Analyzer</span>
97
+
98
+ <li class="method">
99
+ <a href="Sycsvpro/Extractor.html#method-c-new">::new</a>
100
+ &mdash;
101
+ <span class="container">Sycsvpro::Extractor</span>
102
+
103
+ <li class="method">
104
+ <a href="Sycsvpro/Calculator.html#method-c-new">::new</a>
105
+ &mdash;
106
+ <span class="container">Sycsvpro::Calculator</span>
107
+
108
+ <li class="method">
109
+ <a href="Sycsvpro/Profiler.html#method-c-new">::new</a>
110
+ &mdash;
111
+ <span class="container">Sycsvpro::Profiler</span>
112
+
113
+ <li class="method">
114
+ <a href="Sycsvpro/Header.html#method-c-new">::new</a>
115
+ &mdash;
116
+ <span class="container">Sycsvpro::Header</span>
117
+
118
+ <li class="method">
119
+ <a href="Sycsvpro/Collector.html#method-c-new">::new</a>
120
+ &mdash;
121
+ <span class="container">Sycsvpro::Collector</span>
122
+
123
+ <li class="method">
124
+ <a href="Sycsvpro/Mapper.html#method-c-new">::new</a>
125
+ &mdash;
126
+ <span class="container">Sycsvpro::Mapper</span>
127
+
128
+ <li class="method">
129
+ <a href="Sycsvpro/Counter.html#method-c-new">::new</a>
130
+ &mdash;
131
+ <span class="container">Sycsvpro::Counter</span>
132
+
133
+ <li class="method">
134
+ <a href="Sycsvpro/Filter.html#method-c-new">::new</a>
135
+ &mdash;
136
+ <span class="container">Sycsvpro::Filter</span>
137
+
138
+ <li class="method">
139
+ <a href="Sycsvpro/Counter.html#method-i-execute">#execute</a>
140
+ &mdash;
141
+ <span class="container">Sycsvpro::Counter</span>
142
+
143
+ <li class="method">
144
+ <a href="Sycsvpro/Collector.html#method-i-execute">#execute</a>
145
+ &mdash;
146
+ <span class="container">Sycsvpro::Collector</span>
147
+
148
+ <li class="method">
149
+ <a href="Sycsvpro/Calculator.html#method-i-execute">#execute</a>
150
+ &mdash;
151
+ <span class="container">Sycsvpro::Calculator</span>
152
+
153
+ <li class="method">
154
+ <a href="Sycsvpro/Profiler.html#method-i-execute">#execute</a>
155
+ &mdash;
156
+ <span class="container">Sycsvpro::Profiler</span>
157
+
158
+ <li class="method">
159
+ <a href="Sycsvpro/Mapper.html#method-i-execute">#execute</a>
160
+ &mdash;
161
+ <span class="container">Sycsvpro::Mapper</span>
162
+
163
+ <li class="method">
164
+ <a href="Sycsvpro/Extractor.html#method-i-execute">#execute</a>
165
+ &mdash;
166
+ <span class="container">Sycsvpro::Extractor</span>
167
+
168
+ <li class="method">
169
+ <a href="Sycsvpro/Filter.html#method-i-method_missing">#method_missing</a>
170
+ &mdash;
171
+ <span class="container">Sycsvpro::Filter</span>
172
+
173
+ <li class="method">
174
+ <a href="Sycsvpro/Calculator.html#method-i-method_missing">#method_missing</a>
175
+ &mdash;
176
+ <span class="container">Sycsvpro::Calculator</span>
177
+
178
+ <li class="method">
179
+ <a href="Sycsvpro/Filter.html#method-i-pivot_each_column">#pivot_each_column</a>
180
+ &mdash;
181
+ <span class="container">Sycsvpro::Filter</span>
182
+
183
+ <li class="method">
184
+ <a href="Sycsvpro/Header.html#method-i-process">#process</a>
185
+ &mdash;
186
+ <span class="container">Sycsvpro::Header</span>
187
+
188
+ <li class="method">
189
+ <a href="Sycsvpro/Filter.html#method-i-process">#process</a>
190
+ &mdash;
191
+ <span class="container">Sycsvpro::Filter</span>
192
+
193
+ <li class="method">
194
+ <a href="Sycsvpro/RowFilter.html#method-i-process">#process</a>
195
+ &mdash;
196
+ <span class="container">Sycsvpro::RowFilter</span>
197
+
198
+ <li class="method">
199
+ <a href="Sycsvpro/ColumnFilter.html#method-i-process">#process</a>
200
+ &mdash;
201
+ <span class="container">Sycsvpro::ColumnFilter</span>
202
+
203
+ <li class="method">
204
+ <a href="Sycsvpro/Counter.html#method-i-process_file">#process_file</a>
205
+ &mdash;
206
+ <span class="container">Sycsvpro::Counter</span>
207
+
208
+ <li class="method">
209
+ <a href="Sycsvpro/Analyzer.html#method-i-result">#result</a>
210
+ &mdash;
211
+ <span class="container">Sycsvpro::Analyzer</span>
212
+
213
+ <li class="method">
214
+ <a href="Dsl.html#method-i-rows">#rows</a>
215
+ &mdash;
216
+ <span class="container">Dsl</span>
217
+
218
+ <li class="method">
219
+ <a href="Sycsvpro/Counter.html#method-i-write_result">#write_result</a>
220
+ &mdash;
221
+ <span class="container">Sycsvpro::Counter</span>
222
+
223
+ <li class="method">
224
+ <a href="Dsl.html#method-i-write_to">#write_to</a>
225
+ &mdash;
226
+ <span class="container">Dsl</span>
227
+ </ul>
228
+ </main>
229
+
230
+
231
+ <footer id="validator-badges" role="contentinfo">
232
+ <p><a href="http://validator.w3.org/check/referer">Validate</a>
233
+ <p>Generated by <a href="http://rdoc.rubyforge.org">RDoc</a> 4.1.1.
234
+ <p>Based on <a href="http://deveiate.org/projects/Darkfish-Rdoc/">Darkfish</a> by <a href="http://deveiate.org">Michael Granger</a>.
235
+ </footer>
236
+
@@ -0,0 +1,40 @@
1
+ # Operating csv files
2
+ module Sycsvpro
3
+
4
+ # Holds the analytics of the file
5
+ Result = Struct.new(:cols, :col_count, :row_count, :sample_row)
6
+
7
+ # Analyzes the file structure
8
+ class Analyzer
9
+
10
+ # File that is analyzed
11
+ attr_reader :file
12
+
13
+ # Creates a new analyzer
14
+ def initialize(file)
15
+ @file = file
16
+ end
17
+
18
+ # Analyzes the file and returns the result
19
+ def result
20
+ rows = File.readlines(file)
21
+
22
+ result = Result.new
23
+ unless rows.empty?
24
+ row_number = 0
25
+ row_number += 1 while rows[row_number].chomp.empty?
26
+
27
+ result.cols = rows[row_number].chomp.split(';')
28
+ result.col_count = result.cols.size
29
+
30
+ row_number += 1
31
+ row_number += 1 while rows[row_number].chomp.empty?
32
+
33
+ result.row_count = rows.size - 1
34
+ result.sample_row = rows[row_number].chomp
35
+ end
36
+
37
+ result
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,94 @@
1
+ require_relative 'row_filter'
2
+ require_relative 'header'
3
+
4
+ # Operating csv files
5
+ module Sycsvpro
6
+
7
+ # Processes arithmetic operations on columns of a csv file. A column value has to be a number.
8
+ # Possible operations are +, -, * and /. It is also possible to use values of columns as an
9
+ # operator like c1*2 will multiply the value of column 1 with 2.
10
+ class Calculator
11
+
12
+ # infile contains the data that is operated on
13
+ attr_reader :infile
14
+ # outfile is the file where the result is written to
15
+ attr_reader :outfile
16
+ # filter that is used for rows
17
+ attr_reader :row_filter
18
+ # the operations on columns
19
+ attr_reader :formulae
20
+ # header of the outfile
21
+ attr_reader :header
22
+ # filter that is used for columns
23
+ attr_reader :columns
24
+
25
+ # Creates a new Calculator. Options expects :infile, :outfile, :rows and :columns. Optionally
26
+ # a header can be provided. The header can be supplemented with additional column names that
27
+ # are generated due to a arithmetic operation that creates new columns
28
+ def initialize(options={})
29
+ @infile = options[:infile]
30
+ @outfile = options[:outfile]
31
+ @row_filter = RowFilter.new(options[:rows])
32
+ @header = Header.new(options[:header])
33
+ @formulae = {}
34
+ create_calculator(options[:cols])
35
+ end
36
+
37
+ # Retrieves the values from a row as the result of a arithmetic operation
38
+ def method_missing(id, *args, &block)
39
+ to_number(columns[$1.to_i]) if id =~ /c(\d+)/
40
+ end
41
+
42
+ # Executes the calculator
43
+ def execute
44
+ processed_header = false
45
+
46
+ File.open(outfile, 'w') do |out|
47
+ File.open(infile).each_with_index do |line, index|
48
+ next if line.chomp.empty?
49
+
50
+ unless processed_header
51
+ header_row = header.process(line.chomp)
52
+ out.puts header_row unless header_row.empty?
53
+ processed_header = true
54
+ next
55
+ end
56
+
57
+ next if row_filter.process(line, row: index).nil?
58
+
59
+ @columns = line.chomp.split(';')
60
+ formulae.each do |col, formula|
61
+ @columns[col.to_i] = eval(formula)
62
+ end
63
+ out.puts @columns.join(';')
64
+ end
65
+ end
66
+ end
67
+
68
+ private
69
+
70
+ # given a csv file with a;b;c
71
+ # code is in the form of
72
+ # 1:*2,2:*c3-1,4:c1+1
73
+ # 1:*2 means multiply value from column 1 by 2 and assign it to column 1 c[1] = c[1]*2
74
+ # 2:*c3-1 means multiply value from column 2 with value from column 3, subtract 1 and assign
75
+ # the result to column 2 c[2] = c[2] * c[3] - 1
76
+ # 4:c1+1 means create a new column and assign to it the result of the sum of the value of
77
+ # column 1 + 1 c[4] = c[1] + 1
78
+ def create_calculator(code)
79
+ code.split(',').each do |operation|
80
+ col, term = operation.split(':')
81
+ term = "c#{col}#{term}" unless term =~ /^c\d+/
82
+ formulae[col] = term
83
+ end
84
+ end
85
+
86
+ # Casts a string to an integer or float depending whether the value has a decimal point
87
+ def to_number(value)
88
+ return value.to_i unless value =~ /\./
89
+ return value.to_f if value =~ /\./
90
+ end
91
+
92
+ end
93
+
94
+ end
@@ -0,0 +1,60 @@
1
+ require_relative 'row_filter'
2
+ require_relative 'column_filter'
3
+
4
+ # Operating csv files
5
+ module Sycsvpro
6
+
7
+ # Collects values from rows and groups them in categories
8
+ class Collector
9
+
10
+ # infile contains the data that is operated on
11
+ attr_reader :infile
12
+ # outfile is the file where the result is written to
13
+ attr_reader :outfile
14
+ # filter that is used for rows
15
+ attr_reader :row_filter
16
+ # collected values assigned to categories
17
+ attr_reader :collection
18
+
19
+ # Creates a new Collector
20
+ def initialize(options={})
21
+ @infile = options[:infile]
22
+ @outfile = options[:outfile]
23
+ @row_filter = RowFilter.new(options[:rows])
24
+ @collection = {}
25
+ init_collection(options[:cols])
26
+ end
27
+
28
+ # Execute the collector
29
+ def execute
30
+ File.new(infile).each_with_index do |line, index|
31
+ row = row_filter.process(line, row: index)
32
+ next if row.nil? or row.chomp.empty?
33
+ collection.each do |category, elements|
34
+ values = elements[:filter].process(row)
35
+ values.chomp.split(';').each do |value|
36
+ elements[:entries] << value.chomp if elements[:entries].index(value.chomp).nil?
37
+ end
38
+ end
39
+ end
40
+
41
+ File.open(outfile, 'w') do |out|
42
+ collection.each do |category, elements|
43
+ out.puts "[#{category}]"
44
+ elements[:entries].sort.each { |c| out.puts c }
45
+ end
46
+ end
47
+ end
48
+
49
+ private
50
+
51
+ # Initializes the collection
52
+ def init_collection(column_filter)
53
+ column_filter.split('+').each do |f|
54
+ category, filter = f.split(':')
55
+ collection[category] = { entries: [], filter: ColumnFilter.new(filter) }
56
+ end
57
+ end
58
+ end
59
+
60
+ end
@@ -0,0 +1,23 @@
1
+ require_relative 'filter'
2
+
3
+ # Operating csv files
4
+ module Sycsvpro
5
+
6
+ # Creates a new column filter
7
+ class ColumnFilter < Filter
8
+
9
+ # Processes the filter and returns the values that respect the filter
10
+ def process(object, options={})
11
+ return nil if object.nil? or object.empty?
12
+ object = object.encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '')
13
+ return object if filter.empty? and pivot.empty?
14
+ filtered = object.split(';').values_at(*filter.flatten.uniq)
15
+ pivot_each_column(object.split(';')) do |column, match|
16
+ filtered << column if match
17
+ end
18
+ filtered.compact.join(';')
19
+ end
20
+
21
+ end
22
+
23
+ end
@@ -0,0 +1,74 @@
1
+ require_relative 'row_filter'
2
+ require_relative 'column_filter'
3
+
4
+ # Operating csv files
5
+ module Sycsvpro
6
+
7
+ # Creates a new counter that counts values and uses the values as column names and uses the count
8
+ # as the column value
9
+ class Counter
10
+
11
+ # infile contains the data that is operated on
12
+ attr_reader :infile
13
+ # outfile is the file where the result is written to
14
+ attr_reader :outfile
15
+ # values are assigned to the key column
16
+ attr_reader :key_column
17
+ # filter that is used for rows
18
+ attr_reader :row_filter
19
+ # filter that is used for columns
20
+ attr_reader :col_filter
21
+ # values that are assigned to the key column
22
+ attr_reader :customers
23
+ # header of the out file
24
+ attr_reader :heading
25
+
26
+ # Creates a new counter
27
+ def initialize(options={})
28
+ @infile = options[:infile]
29
+ @outfile = options[:outfile]
30
+ @key_column = options[:key].to_i
31
+ @row_filter = RowFilter.new(options[:rows])
32
+ @col_filter = ColumnFilter.new(options[:cols], df: options[:df])
33
+ @customers = {}
34
+ @heading = []
35
+ end
36
+
37
+ # Executes the counter
38
+ def execute
39
+ process_file
40
+ write_result
41
+ end
42
+
43
+ # Processes the counting on the in file
44
+ def process_file
45
+ File.new(infile).each_with_index do |line, index|
46
+ result = col_filter.process(row_filter.process(line.chomp, row: index))
47
+ unless result.nil? or result.empty?
48
+ key = line.split(';')[key_column]
49
+ customer = customers[key] || customers[key] = { name: key, products: Hash.new(0) }
50
+ result.chomp.split(';').each do |column|
51
+ heading << column if heading.index(column).nil?
52
+ customer[:products][column] += 1
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ # Writes the results
59
+ def write_result
60
+ File.open(outfile, 'w') do |out|
61
+ out.puts (["customer"] + heading.sort).join(';')
62
+ customers.each do |k,v|
63
+ line = [k]
64
+ heading.sort.each do |h|
65
+ line << v[:products][h]
66
+ end
67
+ out.puts line.join(';')
68
+ end
69
+ end
70
+ end
71
+
72
+ end
73
+
74
+ end
@@ -0,0 +1,37 @@
1
+ require_relative 'row_filter'
2
+
3
+ # Methods to be used in customer specific script files
4
+ module Dsl
5
+
6
+ # Retrieves rows and columns from the file and returns them to the block provided by the caller
7
+ def rows(options={})
8
+ infile = File.expand_path(options[:infile])
9
+ row_filter = Sycsvpro::RowFilter.new(options[:row_filter]) if options[:row_filter]
10
+
11
+ File.new(infile).each_with_index do |line, index|
12
+ next if line.chomp.empty?
13
+ next if !row_filter.nil? and row_filter.process(line.chomp, row: index).nil?
14
+
15
+ values = line.chomp.split(';')
16
+ params = []
17
+ options.each { |k,v| params << extract_values(values, k, v) if k =~ /column$|columns$/ }
18
+
19
+ yield *params
20
+ end
21
+ end
22
+
23
+ # writes values provided by a block to the given file
24
+ def write_to(file)
25
+ File.open(file, 'w') do |out|
26
+ yield out
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ # Assigns values to keys that are used in rows and yielded to the block
33
+ def extract_values(values, key, position)
34
+ return values[position] if key =~ /column$/
35
+ return values.values_at(*position) if key =~ /columns$/
36
+ end
37
+ end
@@ -0,0 +1,39 @@
1
+ require_relative 'row_filter'
2
+ require_relative 'column_filter'
3
+
4
+ # Operating csv files
5
+ module Sycsvpro
6
+
7
+ # Extracts rows and columns from a csv file
8
+ class Extractor
9
+
10
+ # infile contains the data that is operated on
11
+ attr_reader :in_file
12
+ # outfile is the file where the result is written to
13
+ attr_reader :out_file
14
+ # filter that is used for rows
15
+ attr_reader :row_filter
16
+ # filter that is used for columns
17
+ attr_reader :col_filter
18
+
19
+ # Creates a new extractor
20
+ def initialize(options={})
21
+ @in_file = options[:infile]
22
+ @out_file = options[:outfile]
23
+ @row_filter = RowFilter.new(options[:rows])
24
+ @col_filter = ColumnFilter.new(options[:cols])
25
+ end
26
+
27
+ # Executes the extractor
28
+ def execute
29
+ File.open(out_file, 'w') do |o|
30
+ File.new(in_file, 'r').each_with_index do |line, index|
31
+ extraction = col_filter.process(row_filter.process(line.chomp, row: index))
32
+ o.puts extraction unless extraction.nil?
33
+ end
34
+ end
35
+ end
36
+
37
+ end
38
+
39
+ end