exceler 0.9.2 → 0.9.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +29 -16
- data/exceler.gemspec +1 -1
- data/lib/exceler/version.rb +2 -1
- data/lib/exceler.rb +152 -21
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f8e672118ac522c08f9a0177be4373a6457afa52
|
4
|
+
data.tar.gz: c9f60b1fafbc9919a1ad09b066bca352e29d9ea3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 12f45bd0585b7481ce263abbef78a174739e27df96b536dcf389f9a4f079e37dcc24e03b09fd20da7c03db5a2afb0c28aabc7b0c4de930390d03e7ba96179e54
|
7
|
+
data.tar.gz: 1dec0eb72d03e33f5ce7c122501975b0a168da1990fcba29f2ab55fc505a9e8883cfb1dfac679e14a25fb311abc0c335ac489eede56e0ccc9f93692115f247f1
|
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# Exceler
|
2
2
|
|
3
3
|
Excel document parser for project metrics.
|
4
|
+
プロジェクト計測に使用できる、エクセル文書パーサー
|
4
5
|
|
5
6
|
## Installation
|
6
7
|
|
@@ -11,25 +12,37 @@ Excel document parser for project metrics.
|
|
11
12
|
```
|
12
13
|
require 'exceler'
|
13
14
|
|
14
|
-
#
|
15
|
+
#find Excel files エクセルファイルを探します。
|
16
|
+
files = list = Exceler.list_files( "." )
|
15
17
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
# Example2 F列が済となっていれば済とみなす例
|
18
|
+
#create item scan option エクセルファイルをスキャンするオプションを設定します。
|
19
|
+
# sheet,header,id,contnet,assign,start,limit,state,state_condition
|
20
|
+
so = Exceler::ScanOption.new( nil, 1 , "B" , "C", "D" , nil , nil , "E" , nil )
|
21
21
|
|
22
|
-
|
23
|
-
so = ScanOption.new( 2 , "A" , "B" , "D" , "E" , "F" , "済" )
|
22
|
+
#find items in excel files エクセルファイルからアイテムを探します。
|
24
23
|
items = Exceler.scan_items( list ,so )
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
24
|
+
|
25
|
+
#find persons who are assigned to some issues. アイテムの担当をリストアップします。
|
26
|
+
plist = Exceler.list_assigned_person( items )
|
27
|
+
|
28
|
+
#create issue list for each person 担当ごとに作業します。
|
29
|
+
s = "" # HTML
|
30
|
+
m = {};
|
31
|
+
|
32
|
+
for p in plist
|
33
|
+
pi = Exceler.pickup_assigned( items , p ) #担当に割り当てられたアイテムを取得します。
|
34
|
+
pi = Exceler.pickup_incomplete( pi ) # そのうち、未完了のものを取得します。
|
35
|
+
if( pi.length != 0 ) # 未完了なものがあればHTMLにエクスポートしておきます。
|
36
|
+
s+=Exceler.export_item_html( items , p ,nil )
|
37
|
+
m[p]=pi.length.to_s # 担当ごとの残アイテム数をMAPにしておきます。
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
#export as html
|
42
|
+
Exceler.write_html_file( "test.html" , s , nil )
|
43
|
+
|
44
|
+
#export as csv
|
45
|
+
Exceler.write_csv_file( "test.csv" , m )
|
33
46
|
|
34
47
|
```
|
35
48
|
|
data/exceler.gemspec
CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_development_dependency "bundler"
|
21
|
+
spec.add_development_dependency "bundler"
|
22
22
|
spec.add_development_dependency "rake"
|
23
23
|
spec.add_dependency "roo"
|
24
24
|
end
|
data/lib/exceler/version.rb
CHANGED
data/lib/exceler.rb
CHANGED
@@ -1,20 +1,7 @@
|
|
1
1
|
require "exceler/version"
|
2
|
+
require "roo"
|
2
3
|
|
3
4
|
module Exceler
|
4
|
-
def hello
|
5
|
-
puts "hello"
|
6
|
-
end
|
7
|
-
|
8
|
-
def self.hello2
|
9
|
-
puts "helo2"
|
10
|
-
end
|
11
|
-
|
12
|
-
class Foo
|
13
|
-
def self.bar
|
14
|
-
puts "bar"
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
5
|
#
|
19
6
|
# ScanOption
|
20
7
|
# アイテムを取得する際のオプション
|
@@ -25,17 +12,21 @@ class ScanOption
|
|
25
12
|
# new
|
26
13
|
#
|
27
14
|
# ==== Args
|
15
|
+
# sheet :: シート名(nilの場合は全てのシートに適用)
|
28
16
|
# header :: ヘッダー行(スキップする行数)
|
29
17
|
# id_row :: アイテムの存在を確認する列
|
18
|
+
# content_row :: コンテンツの内容を表す列
|
30
19
|
# assign_row :: 担当者の列
|
31
20
|
# start_row :: 開始日の列
|
32
21
|
# limit_row :: 期限の列
|
33
22
|
# state_row :: ステータスの列
|
34
23
|
# state_condition :: 合致で済とする場合は合致の文字列、埋まっていることで済とする場合はnil
|
35
24
|
#
|
36
|
-
def initialize( header , id_row , assign_row , start_row , limit_row , state_row, state_condition )
|
25
|
+
def initialize( sheet, header , id_row , content_row , assign_row , start_row , limit_row , state_row, state_condition )
|
26
|
+
@sheet = sheet
|
37
27
|
@header = header # ヘッダー行(スキップする行数)
|
38
28
|
@id_row = id_row # アイテムの存在を確認する列
|
29
|
+
@content_row = content_row
|
39
30
|
@assign_row = assign_row # 担当者の列
|
40
31
|
@start_row = start_row # 開始日の列
|
41
32
|
@limit_row = limit_row # 期限の列
|
@@ -43,8 +34,10 @@ class ScanOption
|
|
43
34
|
@state_condition = state_condition
|
44
35
|
end
|
45
36
|
|
37
|
+
attr_reader :sheet
|
46
38
|
attr_reader :header
|
47
39
|
attr_reader :id_row
|
40
|
+
attr_reader :content_row
|
48
41
|
attr_reader :assign_row
|
49
42
|
attr_reader :start_row
|
50
43
|
attr_reader :limit_row
|
@@ -60,6 +53,8 @@ class Item
|
|
60
53
|
INCOMPLETE = 2
|
61
54
|
|
62
55
|
def initialize
|
56
|
+
@file = nil
|
57
|
+
@id = nil
|
63
58
|
@content = nil
|
64
59
|
@state = INCOMPLETE
|
65
60
|
@assign = nil
|
@@ -67,6 +62,8 @@ class Item
|
|
67
62
|
@limit = nil
|
68
63
|
end
|
69
64
|
|
65
|
+
attr_accessor :file
|
66
|
+
attr_accessor :id
|
70
67
|
attr_accessor :content
|
71
68
|
attr_accessor :state
|
72
69
|
attr_accessor :assign
|
@@ -89,7 +86,7 @@ end
|
|
89
86
|
for ext in EXT_PATTERNS
|
90
87
|
filepattern = dir+File::SEPARATOR+"*."+ext;
|
91
88
|
Dir[filepattern].each do |file|
|
92
|
-
puts "founds " + file
|
89
|
+
# puts "founds " + file
|
93
90
|
ret.push( file )
|
94
91
|
end
|
95
92
|
end
|
@@ -129,7 +126,7 @@ end
|
|
129
126
|
# opt :: 検索時のオプション、ScanOptionオブジェクト
|
130
127
|
# ==== Return
|
131
128
|
# アイテムの配列
|
132
|
-
def self.scan_items( files , opt)
|
129
|
+
def self.scan_items( files , opt )
|
133
130
|
ret = []
|
134
131
|
if( opt == nil )
|
135
132
|
return nil
|
@@ -138,14 +135,22 @@ end
|
|
138
135
|
puts file
|
139
136
|
re = Regexp.new( XLS+"$" )
|
140
137
|
if( file =~ re ) # XLS file
|
141
|
-
puts "XLS file scan " + file
|
138
|
+
# puts "XLS file scan " + file
|
142
139
|
s = Roo::Excel.new(file)
|
143
140
|
else #XLSX file
|
144
|
-
puts "XLSX file scan"+file
|
141
|
+
# puts "XLSX file scan"+file
|
145
142
|
s = Roo::Excelx.new(file)
|
146
143
|
end
|
147
144
|
|
148
145
|
for sheet in s.sheets
|
146
|
+
# if sheet option is nil then scan all sheets
|
147
|
+
# else scan only one sheet that has the specified sheet name.
|
148
|
+
if( opt.sheet != nil )
|
149
|
+
if( opt.sheet != sheet )
|
150
|
+
next
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
149
154
|
s.default_sheet = sheet
|
150
155
|
if( s.first_row == nil )
|
151
156
|
next
|
@@ -159,8 +164,14 @@ end
|
|
159
164
|
c = s.cell( opt.id_row , num )
|
160
165
|
if( c != nil )
|
161
166
|
i = Item.new
|
167
|
+
i.file = file
|
168
|
+
i.id = s.cell( opt.id_row, num )
|
169
|
+
if( opt.content_row != nil )
|
170
|
+
i.content = s.cell( opt.content_row ,num )
|
171
|
+
end
|
162
172
|
if( opt.assign_row != nil )
|
163
173
|
i.assign = s.cell( opt.assign_row , num )
|
174
|
+
i.assign.strip!
|
164
175
|
end
|
165
176
|
if( opt.start_row != nil )
|
166
177
|
i.start = s.cell( opt.start_row , num )
|
@@ -195,6 +206,25 @@ end
|
|
195
206
|
return ret
|
196
207
|
end
|
197
208
|
|
209
|
+
|
210
|
+
#
|
211
|
+
# 渡されたアイテムのうち、割り当てられた人を一覧します。
|
212
|
+
# list item assigned person.
|
213
|
+
#
|
214
|
+
# ==== Args
|
215
|
+
# items :: アイテムの配列
|
216
|
+
# ==== Return
|
217
|
+
# 担当に割あたっている人の配列
|
218
|
+
#
|
219
|
+
def self.list_assigned_person( items )
|
220
|
+
pl = {}
|
221
|
+
for item in items
|
222
|
+
if( item.assign != nil )
|
223
|
+
pl[item.assign] = item
|
224
|
+
end
|
225
|
+
end
|
226
|
+
return pl.keys
|
227
|
+
end
|
198
228
|
|
199
229
|
#
|
200
230
|
# 渡されたアイテムのうち、特定の人に割り当てられたアイテムをピックアップします。
|
@@ -242,13 +272,13 @@ end
|
|
242
272
|
# items :: アイテムの配列
|
243
273
|
# ==== Return
|
244
274
|
# 期限切れになっているアイテムの配列
|
245
|
-
def self.
|
275
|
+
def self.pickup_expired( items )
|
246
276
|
ret = []
|
247
277
|
current = Date.today
|
248
278
|
incomplete = pickup_incomplete( items )
|
249
279
|
for item in incomplete
|
250
280
|
if( item.limit != nil )
|
251
|
-
puts item.limit.strftime("%Y/%m/%d")+"-"+current.strftime("%Y/%m%d")
|
281
|
+
# puts item.limit.strftime("%Y/%m/%d")+"-"+current.strftime("%Y/%m%d")
|
252
282
|
if( item.limit < current )
|
253
283
|
ret.push(item)
|
254
284
|
end
|
@@ -256,4 +286,105 @@ end
|
|
256
286
|
end
|
257
287
|
return ret
|
258
288
|
end
|
289
|
+
|
290
|
+
#
|
291
|
+
# タスクの状況をHTMLにする。
|
292
|
+
# transform task status to html string.
|
293
|
+
#
|
294
|
+
# ==== Args
|
295
|
+
# items :: アイテムの配列
|
296
|
+
# ==== Return
|
297
|
+
# HTML Content
|
298
|
+
#
|
299
|
+
def self.export_item_html( items , title , subtitle )
|
300
|
+
s=""
|
301
|
+
if( title != nil )
|
302
|
+
puts "!!"
|
303
|
+
s+="<p class='exceler-title'><h3>"+title+ "-"
|
304
|
+
if( subtitle != nil )
|
305
|
+
s+=subtitle+ ":" + items.length.to_s
|
306
|
+
end
|
307
|
+
s+="</h3><br>"
|
308
|
+
end
|
309
|
+
s += "<table class='exceler-table'>"
|
310
|
+
for item in items
|
311
|
+
s+="<tr>"
|
312
|
+
if( item.file != nil )
|
313
|
+
s+=( "<td>"+ item.file + "</td>" )
|
314
|
+
end
|
315
|
+
if( item.content != nil )
|
316
|
+
s+=( "<td>"+ item.content.to_s + "</td>" )
|
317
|
+
end
|
318
|
+
if( item.limit != nil )
|
319
|
+
s+=( "<td>"+ item.limit.to_s + "</td>" )
|
320
|
+
end
|
321
|
+
s+="</td>"
|
322
|
+
end
|
323
|
+
s+= "</table>"
|
324
|
+
s+= "</p>"
|
325
|
+
# puts "------"
|
326
|
+
# puts s
|
327
|
+
return s
|
328
|
+
end
|
329
|
+
|
330
|
+
DEFAULT_CSS = "<style type='text/css'>
|
331
|
+
.exceler-title h3 {
|
332
|
+
color : blue;
|
333
|
+
}
|
334
|
+
.exceler-table {
|
335
|
+
border-collapse: collapse;
|
336
|
+
background-color: #ccf;
|
337
|
+
width : 100%;
|
338
|
+
border : 1px solid #888;
|
339
|
+
}
|
340
|
+
.exceler-table tr {
|
341
|
+
border : 1px solid #888;
|
342
|
+
}
|
343
|
+
.exceler-table td {
|
344
|
+
border : 1px solid #888;
|
345
|
+
}
|
346
|
+
</style>"
|
347
|
+
|
348
|
+
#
|
349
|
+
# 作成したHTMLファイルコンテンツにCSSを埋め込んで保存します。
|
350
|
+
# ==== Args
|
351
|
+
# file :: output file
|
352
|
+
# content :: Content of the file
|
353
|
+
# ==== Return
|
354
|
+
# HTML Content
|
355
|
+
#
|
356
|
+
def self.write_html_file( file , content , css )
|
357
|
+
f = open( file , "w" )
|
358
|
+
if( css == nil )
|
359
|
+
css = DEFAULT_CSS
|
360
|
+
end
|
361
|
+
f.puts( DEFAULT_CSS )
|
362
|
+
f.puts( content )
|
363
|
+
f.flush()
|
364
|
+
f.close()
|
365
|
+
end
|
366
|
+
|
367
|
+
#
|
368
|
+
# マップオブジェクトをCSVをにして保存します。
|
369
|
+
# ==== Args
|
370
|
+
# file :: output file
|
371
|
+
# content :: Content of the file
|
372
|
+
# ==== Return
|
373
|
+
# HTML Content
|
374
|
+
#
|
375
|
+
def self.write_csv_file( file , map )
|
376
|
+
keys = map.keys
|
377
|
+
ks = ""
|
378
|
+
vs = ""
|
379
|
+
for key in keys
|
380
|
+
ks += (key + ",")
|
381
|
+
vs += (map[key].to_s + "," )
|
382
|
+
end
|
383
|
+
f = open( file , "w" )
|
384
|
+
f.puts( ks )
|
385
|
+
f.puts( vs )
|
386
|
+
f.flush()
|
387
|
+
f.close()
|
388
|
+
end
|
389
|
+
|
259
390
|
end
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: exceler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- kitfactory
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-07-
|
11
|
+
date: 2014-07-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - '>='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - '>='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|