ld 0.1.0

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.
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