ld 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/ld/excel.rb ADDED
@@ -0,0 +1,623 @@
1
+ require 'spreadsheet'
2
+ Spreadsheet.client_encoding = 'UTF-8'
3
+
4
+ class Ld::Excel
5
+ attr_accessor :excel,:path,:basename,:sheets,:sheet,:scope_arrs,:mappings,:bean,:beans
6
+ attr_accessor :format
7
+
8
+ @@hz ||= ".xls"
9
+ ZIMU ||= {}
10
+
11
+ if ZIMU.empty?
12
+ flag = 'A'
13
+ 0.upto(9999) do |i|
14
+ ZIMU.store(flag,i)
15
+ flag = flag.succ
16
+ end
17
+ end
18
+
19
+ # 构造函数,如果未传path则是创建一个新的excel, 如果传了path,则打开这个excel,不过打开前会验证后缀与是否存在
20
+ def initialize(path = nil)
21
+ if path!=nil
22
+ if path.match(/.xls$/)!=nil
23
+ if File::exist? path
24
+ @excel = Spreadsheet.open path
25
+ @path = path
26
+ puts "打开文件: #{path}"
27
+ else
28
+ raise "文件不存在: #{path}"
29
+ end
30
+ else
31
+ raise "只能打开.xls结尾的文件"
32
+ end
33
+ else
34
+ @excel = Spreadsheet::Workbook.new
35
+ puts "创建新的Excel实例"
36
+ end
37
+ @sheets = {}
38
+ @sheet = nil
39
+ end
40
+
41
+ def self.open(path)
42
+ self.new(path)
43
+ end
44
+
45
+ # 获取一页
46
+ def open_sheet sheet_name
47
+ @sheet = @excel.worksheet sheet_name
48
+ if @sheet == nil
49
+ raise "未找到 sheet #{sheet_name}"
50
+ else
51
+ # puts "sheet #{sheet_name}"
52
+ end
53
+ self
54
+ end
55
+
56
+ # 获取所有页
57
+ def get_sheets
58
+ @sheets = @excel.worksheets
59
+ puts "返回 #{@sheets.size} 页"
60
+ self
61
+ end
62
+
63
+ # 创建新页(先查有没有该页)
64
+ def new_sheet(sheet_name)
65
+ @sheet = @excel.create_worksheet(:name => sheet_name)
66
+ # puts "创建了一页 #{sheet_name}"
67
+ self
68
+ end
69
+
70
+ # 读一个单元格
71
+ def read_location(location,parse = true)
72
+ l = parse_location(location)
73
+ unit = read_unit_by_xy(l[:r],l[:c],parse)
74
+ # puts ""
75
+ end
76
+
77
+ # 读一个单元格2
78
+ def read_sheet_location(location,parse = true)
79
+ open_sheet location.split('?')[0]
80
+ read_location location.split('?')[1]
81
+ end
82
+
83
+
84
+ # 刷新excel中的sheet
85
+ def open_new
86
+ excel_new = Excel.open @path
87
+ end
88
+
89
+ # 读很多个location链,返回二维数组
90
+ def read_location_list_arr(location_list_arr_str)
91
+ units_arr = []
92
+ location_list_arr_str.split(',').each do |location_list|
93
+ units = read_location_list(location_list)
94
+ units_arr << units
95
+ end
96
+ units_arr
97
+ end
98
+
99
+ # 读取一个location链 ,返回一维数组
100
+ def read_sheet_locations(locations_config,parse = true)
101
+ unit_list = []
102
+ open_sheet locations_config.split('?')[0]
103
+ locations_config.split('?')[1].split('.').each do |location|
104
+ l = parse_location(location)
105
+ unit = read_unit_by_xy(l[:r],l[:c],parse)
106
+ unit_list << unit
107
+ end
108
+ unit_list
109
+ end
110
+
111
+ # 通过xy坐标往unit写内容
112
+ def write_unit_by_xy x, y, unit
113
+ unit = unit.to_s if unit.class == Array
114
+ @sheet.row(x)[y] = unit
115
+ end
116
+
117
+ # 通过x,y坐标获取unit内容
118
+ def read_unit_by_xy x, y, parse
119
+ # puts "x: #{x}\ty: #{y}"
120
+ unit = @sheet.row(y)[x]
121
+ if unit.instance_of? Spreadsheet::Formula
122
+ if parse
123
+ return unit.value
124
+ end
125
+ end
126
+ return unit
127
+ end
128
+
129
+ def flush
130
+ Excel.new self.path
131
+ end
132
+
133
+ def parse_del_to_hash address, scope
134
+ arr = address.split '-'
135
+ arr = arr[1..arr.size-1]
136
+ start_row_num = scope.scan(/\d/).join[0..1]# 首行行号
137
+ location = parse_location(scope.split(':')[0])
138
+ hash = {}
139
+ del_rows = []
140
+ address.each do |del_row_num|# 去除行行号
141
+ rows << del_row_num.to_i - start_row_num.to_i# 去除行行号 - 首行行号 = 数组角标位置
142
+ end
143
+ hash.store(:rows,jiang(rows))
144
+ hash
145
+ end
146
+
147
+ # 解析一个excel location
148
+ def parse_location location
149
+ if location and location.class == String
150
+ location.upcase!
151
+ {
152
+ :x => ZIMU[location.scan(/[A-Z]+/).join].to_i,
153
+ :y => (location.scan(/[0-9]+/).join.to_i - 1)
154
+ }
155
+ else
156
+ ms.puts_fail "location为空或不是String类型,无法解析"
157
+ end
158
+ end
159
+
160
+ def ab_to a, b
161
+ type = nil
162
+ if is_number?(a) == true and is_number?(b) == true
163
+ type = 'y'
164
+ case a.to_i <=> b.to_i
165
+ when 1
166
+ return [type, (b..a).to_a]
167
+ when -1
168
+ return [type, (a..b).to_a]
169
+ when 0
170
+ return [type, [a]]
171
+ end
172
+ elsif is_number?(a) == false and is_number?(b) == false
173
+ type = 'x'
174
+ case a <=> b
175
+ when 1
176
+ return [type, (b..a).to_a]
177
+ when -1
178
+ return [type, (a..b).to_a]
179
+ when 0
180
+ return [type, [a]]
181
+ end
182
+ else
183
+ raise "解析excel配置范围时,':'两边必须要么都是字母,要么都是数字!"
184
+ end
185
+ end
186
+
187
+ def map_adds map, adds
188
+ case adds[0]
189
+ when 'x'
190
+ adds[1].each do |add|
191
+ map[:x] << add
192
+ end
193
+ when 'y'
194
+ adds[1].each do |add|
195
+ map[:y] << add
196
+ end
197
+ end
198
+ end
199
+
200
+ def map_add map, add
201
+ if is_number? add
202
+ map[:y] << add
203
+ else
204
+ map[:x] << add
205
+ end
206
+ end
207
+
208
+ def map_mins map, mins
209
+ case mins[0]
210
+ when 'x'
211
+ mins[1].each do |min|
212
+ map[:x].delete min
213
+ end
214
+ when 'y'
215
+ mins[1].each do |min|
216
+ map[:y].delete min
217
+ end
218
+ end
219
+ end
220
+
221
+ def map_min map, min
222
+ if is_number? min
223
+ map[:y].delete min
224
+ else
225
+ map[:x].delete min
226
+ end
227
+ end
228
+
229
+ def is_number? str
230
+ if str.to_i.to_s == str.to_s
231
+ return true
232
+ end
233
+ false
234
+ end
235
+
236
+ # 用坐标解析一个excel scope
237
+ def generate_map address_str
238
+ map = {:x => [], :y => []}
239
+ config = parse_address address_str
240
+ if config[:scope]
241
+ if config[:scope].include? ':'
242
+ # map初始化
243
+ arr = config[:scope].split(':')
244
+ if config[:scope].scan(/[0-9]+/).join == ''
245
+ map_adds(map, ab_to(arr[0].scan(/[A-Z]+/).join, arr[1].scan(/[A-Z]+/).join))
246
+ elsif config[:scope].scan(/[A-Z]+/).join == ''
247
+ map_adds(map, ab_to(arr[0].scan(/[0-9]+/).join, arr[1].scan(/[0-9]+/).join))
248
+ else
249
+ map_adds(map, ab_to(arr[0].scan(/[0-9]+/).join, arr[1].scan(/[0-9]+/).join))
250
+ map_adds(map, ab_to(arr[0].scan(/[A-Z]+/).join, arr[1].scan(/[A-Z]+/).join))
251
+ end
252
+ # map 添加
253
+ if config[:add_str]
254
+ config[:add_str].split(',').each do |add|
255
+ if add.include? ":"
256
+ map_adds(map, ab_to(add.split(':')[0], add.split(':')[1]))
257
+ else
258
+ map_add map, add
259
+ end
260
+ end
261
+ end
262
+ # map 减小
263
+ if config[:min_str]
264
+ config[:min_str].split(',').each do |min|
265
+ if min.include? ":"
266
+ map_mins(map, ab_to(min.split(':')[0], min.split(':')[1]))
267
+ else
268
+ map_min map, min
269
+ end
270
+ end
271
+ end
272
+ else
273
+ raise "scope 没有 ':' 无法解析"
274
+ end
275
+ else
276
+ raise "scope == nil"
277
+ end
278
+ map[:x].uniq!
279
+ map[:y].uniq!
280
+ arrs = []
281
+ map[:y].each do |y|
282
+ rows = []
283
+ map[:x].each do |x|
284
+ rows << ["#{x}_#{y}", ZIMU[x], y.to_i - 1]
285
+ end
286
+ arrs << rows
287
+ end
288
+ return arrs
289
+ rescue
290
+ puts "生成map时发生错误: #{$!}"
291
+ puts $@
292
+ end
293
+
294
+
295
+ # 解析范围配置
296
+ def parse_address address
297
+ hash = {}
298
+ if address
299
+ address.upcase!
300
+ else
301
+ raise "address 为 nil"
302
+ end
303
+ if address.split('+').size > 2
304
+ raise "'+'号只能有1个"
305
+ end
306
+ if address.split('-').size > 2
307
+ raise "'-'号只能有1个"
308
+ end
309
+ if address.include?('+')
310
+ a = address.split('+')[0]
311
+ b = address.split('+')[1]
312
+ if a.include?('-')
313
+ hash.store :scope, a.split('-')[0]
314
+ hash.store :min_str, a.split('-')[1]
315
+ hash.store :add_str, b
316
+ else
317
+ hash.store :scope, a
318
+ if b.include?('-')
319
+ hash.store :min_str, b.split('-')[1]
320
+ hash.store :add_str, b.split('-')[0]
321
+ else
322
+ hash.store :add_str, b
323
+ end
324
+ end
325
+ else
326
+ if address.include?('-')
327
+ hash.store :scope, address.split('-')[0]
328
+ hash.store :min_str, address.split('-')[1]
329
+ else
330
+ hash.store :scope, address
331
+ end
332
+ end
333
+ hash
334
+ end
335
+
336
+ # 先打开一个sheet页,再读scope范围数据
337
+ # params?b13:m27-g.j.k.(14:18)
338
+ def read_sheet_scope full_scope, simple = true, filter_nil = false
339
+ if full_scope.include?('?')
340
+ sheet_name = full_scope.split('?')[0]
341
+ if sheet_name
342
+ open_sheet sheet_name
343
+ else
344
+ raise "sheetname为nil"
345
+ end
346
+ address_str = full_scope.split('?')[1]
347
+ map = generate_map address_str
348
+ data_arrs = read_map map, simple
349
+ if data_arrs.size == 0
350
+ puts "没有任何内容的区域! #{full_scope}"
351
+ else
352
+ puts "#{full_scope}"
353
+ end
354
+ # 除去不完整数据
355
+ if filter_nil == true
356
+ (data_arrs.size - 1).downto(0) do |i|
357
+ arr = data_arrs[i]
358
+ if arr[0] == nil or arr[1] == nil
359
+ data_arrs.delete_at i
360
+ end
361
+ end
362
+ end
363
+ return data_arrs
364
+ else
365
+ raise "缺少?,需要在'?'左边指定sheet的名称"
366
+ end
367
+ end
368
+
369
+ def read_map arrs, simple = true
370
+ @scope_arrs = []
371
+ arrs.each do |arr|
372
+ rows = []
373
+ arr.each do |a|
374
+ if simple
375
+ rows << read_unit_by_xy(a[1], a[2], true)
376
+ else
377
+ rows << {:index => a[0], :value => read_unit_by_xy(a[1], a[2], true)}
378
+ end
379
+ end
380
+ @scope_arrs << rows
381
+ end
382
+ @scope_arrs
383
+ end
384
+
385
+ # 排序
386
+ def jiang arr
387
+ 0.upto(arr.size - 2) do |i|
388
+ (i+1).upto(arr.size - 1) do |j|
389
+ if arr[i] < arr[j]
390
+ arr[i] = arr[i] + arr[j]
391
+ arr[j] = arr[i] - arr[j]
392
+ arr[i] = arr[i] - arr[j]
393
+ end
394
+ end
395
+ end
396
+ arr
397
+ end
398
+
399
+ def sheng arr
400
+ 0.upto(arr.size - 2) do |i|
401
+ (i+1).upto(arr.size - 1) do |j|
402
+ if arr[i] > arr[j]
403
+ arr[i] = arr[i] + arr[j]
404
+ arr[j] = arr[i] - arr[j]
405
+ arr[i] = arr[i] - arr[j]
406
+ end
407
+ end
408
+ end
409
+ arr
410
+ end
411
+
412
+ # 将二维数组写到表中
413
+ def write_arrs_to_point(arrs,point = "a1")
414
+ l = parse_location(point)
415
+ arrs.each_with_index do |arr,r|
416
+ arr.each_with_index do |data,c|
417
+ write_unit_by_xy(r+l[:x],c+l[:y],data)
418
+ end
419
+ end
420
+ self
421
+ end
422
+
423
+ # 将一维数组写到表中,可写成列,也可以写成行
424
+ def write_arr_to_point(arr, rank = '|', point = "a1")
425
+ l = parse_location(point)
426
+ if rank == '|' or rank == 'col'
427
+ arr.each_with_index do |data,r|
428
+ # 坚写,行动列不动
429
+ write_unit_by_xy(l[:r]+r,l[:c],data)
430
+ end
431
+ elsif rank == '-' or rank == 'row'
432
+ arr.each_with_index do |data,c|
433
+ # 横写,列动行不动
434
+ write_unit_by_xy(l[:r],l[:c]+c,data)
435
+ end
436
+ else
437
+ raise "横写rank | 竖写rank - 无法识别#{rank}"
438
+ end
439
+ self
440
+ end
441
+
442
+ # 保存文件
443
+ def save(path = nil)
444
+ flag = 1
445
+ if path==nil
446
+ if File.exist? @path
447
+ @excel.write @path
448
+ puts "保存覆盖了一个同名文件 #{@path}"
449
+ else
450
+ @excel.write @path
451
+ puts "保存到: #{@path}"
452
+ end
453
+ else
454
+ @excel.write path
455
+ if File.exist? path
456
+ puts "保存到: #{path}"
457
+ else
458
+ raise "保存失败!"
459
+ end
460
+ end
461
+ self
462
+ end
463
+
464
+ def save_to_source(basename)
465
+ if basename.match(/.xls$/)!=nil
466
+ save(@@base_path + "source/" + basename)
467
+ else
468
+ raise "要以.xls结尾"
469
+ end
470
+ self
471
+ end
472
+
473
+ def save_to_complete(basename)
474
+ if basename.match(/.xls$/)!=nil
475
+ save(@@base_path + "complete/" + basename)
476
+ else
477
+ raise "要以.xls结尾"
478
+ end
479
+ self
480
+ end
481
+
482
+ def save_to(path_name)
483
+ if path_name.match(/.xls$/)!=nil
484
+ save(path_name)
485
+ else
486
+ raise "要以.xls结尾"
487
+ end
488
+ self
489
+ end
490
+
491
+ # 打印信息
492
+ def info
493
+ if File.exist?(@path)
494
+ @sheets ||= @excel.worksheets
495
+ @sheets.each_with_index do |sheet,i|
496
+ puts "第#{i}个sheet,name:#{sheet.name}"
497
+ end
498
+ puts "Excel文件size:#{File.size @path},sheet数:#{@sheets.size},文件path:#{@path}"
499
+ else
500
+ puts "不存在的文件,#{@path}"
501
+ end
502
+ self
503
+ end
504
+
505
+ # 获取第一列的所有单元格格式颜色arr
506
+ def get_examples
507
+ @sheet.row(4).formats[0].pattern_fg_color == :red
508
+ cols = excel.sheet.column(0)
509
+ cols.each do |col|
510
+ puts col
511
+ end
512
+ end
513
+
514
+ # 重新加载文件数据
515
+ def reload
516
+ if @path!=nil
517
+ if File.exist? @path
518
+ @excel = Spreadsheet.open @path
519
+ @sheets = @excel.worksheets
520
+ @sheet = nil
521
+ @basename = nil
522
+ puts "reload成功 #{@path}"
523
+ else
524
+ raise "#{path},这个文件不存在,无法reload"
525
+ end
526
+
527
+ else
528
+ raise "@path==nil,无法reload"
529
+ end
530
+ self
531
+ end
532
+
533
+ def set_default_format(font_color = :black)
534
+ if @sheet!=nil
535
+ @format = Spreadsheet::Format.new(
536
+ :color => :blue,
537
+ :weight => :bold,
538
+ :size => 11
539
+ )
540
+ @format.font.color = font_color
541
+ @format.font.name = "微软雅黑"
542
+ @format.font.size = 11
543
+ @sheet.default_format = @format
544
+ # puts "设置默认格式成功 #{@sheet.name}"
545
+ else
546
+ raise "@sheet==nil,无法获取默认格式,无法设置默认格式"
547
+ end
548
+ @format
549
+ end
550
+
551
+ def write_sheet(sheet)
552
+ new_sheet sheet[:name]
553
+ set_default_format(sheet[:color].nil? ? 'black' : sheet[:color])
554
+ write_arrs_to_point(sheet[:arrs], sheet[:point].nil? ? "a1" : sheet[:point])
555
+ sheet
556
+ end
557
+
558
+ def self.write_excel(arrs_list,excel_name)
559
+ new_excel = Excel.new
560
+ arrs_list.each_with_index do |arrs,i|
561
+ new_excel.write_sheet arrs,'sheet'+(i+1).to_s,:red
562
+ end
563
+ new_excel.save_to_complete excel_name
564
+ end
565
+
566
+ def self.create(path, sheets)
567
+ e = Excel.new
568
+ sheets.each do |sheet|
569
+ e.write_sheet sheet
570
+ end
571
+ e.save path
572
+ end
573
+
574
+ def self.write_excel2(arrs,excel_name)
575
+ new_excel = Excel.new
576
+ new_excel.write_sheet arrs,'sheet1',:red
577
+ new_excel.save_to excel_name
578
+ rescue
579
+ puts $!
580
+ puts $@
581
+ end
582
+
583
+ end
584
+
585
+ =begin
586
+
587
+ # <Spreadsheet::Format:0x007fe8297dba40
588
+ @bottom=:none,
589
+ @bottom_color=:builtin_black,
590
+ @cross_down=false,
591
+ @cross_up=false,
592
+ @diagonal_color=:builtin_black,
593
+ @font=
594
+ # <Spreadsheet::Font:0x007fe8285948a0
595
+ @color=:black,
596
+ @encoding=:iso_latin1,
597
+ @escapement=:normal,
598
+ @family=:none,
599
+ @italic=false,
600
+ @name="仿宋",
601
+ @outline=false,
602
+ @previous_fast_key=nil,
603
+ @shadow=false,
604
+ @size=11,
605
+ @strikeout=false,
606
+ @underline=:none,
607
+ @weight=400>,
608
+ @horizontal_align=:center,
609
+ @indent_level=0,
610
+ @left=:none,
611
+ @left_color=:builtin_black,
612
+ @number_format="GENERAL",
613
+ @pattern=1,
614
+ @pattern_bg_color=:border,
615
+ @pattern_fg_color=:red,
616
+ @regexes=
617
+ {:date=>/[YMD]/,
618
+ :date_or_time=>/[hmsYMD]/,
619
+ :datetime=>/([YMD].*[HS])|([HS].*[YMD])/,
620
+ :time=>/[hms]/,
621
+ :number=>/([# ]|0+)/,
622
+ :locale=>/(?-mix:\A\[\$\-\d+\])/},
623
+ =end
data/lib/ld/file.rb ADDED
@@ -0,0 +1,82 @@
1
+ class Ld::File
2
+
3
+ attr_accessor :path, :name, :type
4
+
5
+ def initialize path
6
+ @path = path
7
+ @name = File.basename @path
8
+ @type = File.directory?(@path) ? 1 : 0
9
+ end
10
+
11
+ def brothers
12
+ father.children
13
+ end
14
+
15
+ def children
16
+ arr = []
17
+ Dir.foreach(@path)do |p|
18
+ if !['.','..','.DS_Store'].include?(p)
19
+ arr << Ld::File.new("#{@path}/#{p}")
20
+ end
21
+ end
22
+ arr.sort!{|a,b| b.type-a.type}
23
+ arr
24
+ end
25
+
26
+ def father
27
+ arr = @path.split('/')
28
+ arr.pop
29
+ Ld::File.new(arr.join('/'))
30
+ end
31
+
32
+ def find name
33
+ name = name.to_s
34
+ children.each do |f|
35
+ if f.name == name
36
+ return f
37
+ end
38
+ end
39
+ return nil
40
+ end
41
+
42
+ def read
43
+ File.open(@path).read
44
+ end
45
+
46
+ def readlines
47
+ File.open(@path).readlines
48
+ end
49
+
50
+ def where regexp
51
+ arr = []
52
+ iter_search regexp, arr
53
+ arr
54
+ end
55
+
56
+ def iter_search regexp, arr
57
+ children.each do |f|
58
+ if f.type == 1
59
+ f.iter_search regexp, arr
60
+ end
61
+ if f.name.match(regexp)
62
+ arr << f
63
+ end
64
+ end
65
+ self
66
+ end
67
+
68
+ def iter arr
69
+ children.each do |f|
70
+ if f.type == 1
71
+ f.iter arr
72
+ end
73
+ arr << f
74
+ end
75
+ self
76
+ end
77
+
78
+ def method_missing name
79
+ find name
80
+ end
81
+
82
+ end
data/lib/ld/node.rb ADDED
@@ -0,0 +1,13 @@
1
+ class Ld::Node
2
+ attr_accessor :id, :depth, :name, :path ,:type, :suffix
3
+
4
+ def initialize id, depth, path
5
+ @id = id
6
+ @depth = depth
7
+ @path = path
8
+ @type = File.directory?(path) ? 1 : 0
9
+ @name = File.basename path
10
+ @suffix = @type == 1 ? nil : @name.split('.').last
11
+ end
12
+
13
+ end