robust_excel_ole 1.25 → 1.30
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/Changelog +23 -0
- data/README.rdoc +22 -11
- data/bin/jreo +20 -1
- data/bin/reo +20 -1
- data/docs/README_open.rdoc +8 -4
- data/lib/robust_excel_ole.rb +2 -3
- data/lib/robust_excel_ole/base.rb +5 -0
- data/lib/robust_excel_ole/bookstore.rb +1 -1
- data/lib/robust_excel_ole/excel.rb +14 -24
- data/lib/robust_excel_ole/general.rb +314 -193
- data/lib/robust_excel_ole/list_object.rb +6 -2
- data/lib/robust_excel_ole/range.rb +5 -1
- data/lib/robust_excel_ole/range_owners.rb +4 -71
- data/lib/robust_excel_ole/version.rb +1 -1
- data/lib/robust_excel_ole/workbook.rb +26 -17
- data/lib/robust_excel_ole/worksheet.rb +72 -4
- data/spec/base_spec.rb +17 -15
- data/spec/data/more_data/workbook.xls +0 -0
- data/spec/general_spec.rb +30 -0
- data/spec/workbook_spec.rb +11 -11
- data/spec/workbook_specs/workbook_misc_spec.rb +30 -30
- data/spec/workbook_specs/workbook_open_spec.rb +11 -0
- data/spec/workbook_specs/workbook_unobtr_spec.rb +292 -112
- data/spec/worksheet_spec.rb +18 -18
- metadata +2 -5
- data/jreo.bat +0 -3
- data/lib/reo_console.rb +0 -72
- data/reo.bat +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 468109a0884d48ed77c70d9681d0067453aadfbd7294c6b152fb6457141bb98d
|
4
|
+
data.tar.gz: 2527cdd343eefb7325c077204203e1893d8e32f00830a8a6591669aba7ad43ec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5637d87926eef9515335fb075add5cf4810cf97229c762f2b182fbdad42cae99f128c6a2ee253acbf29362c49005d579944e283e875aff4785df5220a6f0bff6
|
7
|
+
data.tar.gz: 59f015190d12c0a0b3c7e8016e6dd81da74ae5b760e166d0044a5b04dab5d0fb0b8fa295d13f66a30861a71867c921c2352119957b0543caeb467ecd881b3223
|
data/Changelog
CHANGED
@@ -1,6 +1,29 @@
|
|
1
1
|
# Change Log
|
2
2
|
All notable changes to this project will be documented in this file.
|
3
3
|
|
4
|
+
## [1.30] 2020-18-11
|
5
|
+
|
6
|
+
## [1.29] 2020-05-11
|
7
|
+
|
8
|
+
### Added
|
9
|
+
- Workbook.open can also take a Pathname object
|
10
|
+
- General#init_reo_for_win32ole
|
11
|
+
|
12
|
+
## [1.28] 2020-23-10
|
13
|
+
|
14
|
+
## [1.27] 2020-16-10
|
15
|
+
|
16
|
+
## [1.26] 2020-09-10
|
17
|
+
|
18
|
+
### Added
|
19
|
+
- General#change_current_binding
|
20
|
+
|
21
|
+
## [1.25] 2020-10-09]
|
22
|
+
|
23
|
+
## [1.24] 2020-25-09
|
24
|
+
|
25
|
+
## [1.23] 2020-02-09
|
26
|
+
|
4
27
|
## [1.22] 2020-10-08
|
5
28
|
|
6
29
|
### Added
|
data/README.rdoc
CHANGED
@@ -64,15 +64,7 @@ If you want to start the console under jruby, and if you don't want to use a ver
|
|
64
64
|
|
65
65
|
jreo
|
66
66
|
|
67
|
-
The call of the console will include RobustExcelOle for you. The consoles require the ruby gem 'pry' and 'pry-bond' to enable the ruby shell 'pry' with filename and string completion.
|
68
|
-
|
69
|
-
object.pry
|
70
|
-
|
71
|
-
or
|
72
|
-
|
73
|
-
cd object
|
74
|
-
|
75
|
-
to assign self to this object. The original pry console is adapted to preserve local variables.
|
67
|
+
The call of the console will include RobustExcelOle for you. The consoles require the ruby gem 'pry' and 'pry-bond' to enable the ruby shell 'pry' with filename and string completion.
|
76
68
|
|
77
69
|
The following examples can be used for both scripts and console. If you have started the console in the gem path, you can just put these examples.
|
78
70
|
|
@@ -326,9 +318,28 @@ and set another value to that range.
|
|
326
318
|
For more details about reading and writing contents of cells and ranges see {README_ranges}[https://github.com/Thomas008/robust_excel_ole/blob/master/docs/README_ranges.rdoc]
|
327
319
|
|
328
320
|
|
329
|
-
=== More
|
321
|
+
=== More features
|
322
|
+
|
323
|
+
1. The method +General.change_current_binding+ allows to change the value of self within the current binding, while preserving the local variables, without starting another repl. Assume, +object+ shall be the self, then you would put
|
324
|
+
|
325
|
+
General.change_current_binding(object)
|
326
|
+
|
327
|
+
Without this method, the ruby shell 'pry' allows to change the value of 'self' in the console as well, e.g.
|
328
|
+
|
329
|
+
object.pry
|
330
|
+
|
331
|
+
or
|
332
|
+
|
333
|
+
cd object
|
334
|
+
|
335
|
+
However, this command also starts another pry repl (with another binding). Moreover, local variables in the previous binding are forgotten.
|
336
|
+
|
337
|
+
|
338
|
+
2. The class Win32Ole is being extended such that RobustExcelOle methods can be applied to Win32Ole objects. As mentioned above, the RobustExcelOle objects are wrapper of corresponding WIN32OLE objects. With help of +update_to_reo+ the RobustExcelOle objects and their wrapped Win32Ole objects are interchangeable. One example would be
|
339
|
+
|
340
|
+
range.ole_range.copy([4,3])
|
330
341
|
|
331
|
-
|
342
|
+
Likewise it is possible to convert ("type-lift") Win32Ole objects into the corresponding RobustExcelOle object, using General.to_reo.
|
332
343
|
|
333
344
|
range = sheet.Names.Item("firstcell").to_reo
|
334
345
|
|
data/bin/jreo
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
# -*- jruby -*-
|
3
3
|
|
4
4
|
require 'pry'
|
5
|
-
|
5
|
+
require_relative '../lib/robust_excel_ole'
|
6
6
|
|
7
7
|
include REO
|
8
8
|
include General
|
@@ -15,10 +15,29 @@ Pry.config.prompt_name = "REO "
|
|
15
15
|
#Pry.config.history_save = true
|
16
16
|
#Pry.editor = 'notepad' # 'subl', 'vi'
|
17
17
|
|
18
|
+
prompt_proc1 = proc { |target_self, nest_level, pry|
|
19
|
+
"[#{pry.input_ring.count}] #{pry.config.prompt_name}(#{Pry.view_clip(target_self)})#{":#{nest_level}" unless nest_level.zero?}> "
|
20
|
+
}
|
21
|
+
|
22
|
+
prompt_proc2 = proc { |target_self, nest_level, pry|
|
23
|
+
"[#{pry.input_ring.count}] #{pry.config.prompt_name}(#{Pry.view_clip(target_self.inspect.gsub(/\"/, ''))})})#{":#{nest_level}" unless nest_level.zero?}* "
|
24
|
+
}
|
25
|
+
|
26
|
+
Pry.config.prompt = if RUBY_PLATFORM =~ /java/
|
27
|
+
[prompt_proc1, prompt_proc2]
|
28
|
+
else
|
29
|
+
Pry::Prompt.new(
|
30
|
+
"REO",
|
31
|
+
"The RobustExcelOle Prompt. Besides the standard information it puts the current object",
|
32
|
+
[prompt_proc1, prompt_proc2]
|
33
|
+
)
|
34
|
+
end
|
35
|
+
|
18
36
|
hooks = Pry::Hooks.new
|
19
37
|
|
20
38
|
hooks.add_hook :when_started, :hook12 do
|
21
39
|
puts 'REO console started'
|
22
40
|
puts
|
23
41
|
end
|
42
|
+
|
24
43
|
Pry.start(nil, hooks: hooks)
|
data/bin/reo
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
# -*- ruby -*-
|
3
3
|
|
4
4
|
require 'pry'
|
5
|
-
|
5
|
+
require_relative '../lib/robust_excel_ole'
|
6
6
|
|
7
7
|
include REO
|
8
8
|
include General
|
@@ -15,10 +15,29 @@ Pry.config.prompt_name = "REO "
|
|
15
15
|
#Pry.config.history_save = true
|
16
16
|
#Pry.editor = 'notepad' # 'subl', 'vi'
|
17
17
|
|
18
|
+
prompt_proc1 = proc { |target_self, nest_level, pry|
|
19
|
+
"[#{pry.input_ring.count}] #{pry.config.prompt_name}(#{Pry.view_clip(target_self)})#{":#{nest_level}" unless nest_level.zero?}> "
|
20
|
+
}
|
21
|
+
|
22
|
+
prompt_proc2 = proc { |target_self, nest_level, pry|
|
23
|
+
"[#{pry.input_ring.count}] #{pry.config.prompt_name}(#{Pry.view_clip(target_self)})#{":#{nest_level}" unless nest_level.zero?}* "
|
24
|
+
}
|
25
|
+
|
26
|
+
Pry.config.prompt = if RUBY_PLATFORM =~ /java/
|
27
|
+
[prompt_proc1, prompt_proc2]
|
28
|
+
else
|
29
|
+
Pry::Prompt.new(
|
30
|
+
"REO",
|
31
|
+
"The RobustExcelOle Prompt. Besides the standard information it puts the current object",
|
32
|
+
[prompt_proc1, prompt_proc2]
|
33
|
+
)
|
34
|
+
end
|
35
|
+
|
18
36
|
hooks = Pry::Hooks.new
|
19
37
|
|
20
38
|
hooks.add_hook :when_started, :hook12 do
|
21
39
|
puts 'REO console started'
|
22
40
|
puts
|
23
41
|
end
|
42
|
+
|
24
43
|
Pry.start(nil, hooks: hooks)
|
data/docs/README_open.rdoc
CHANGED
@@ -17,6 +17,11 @@ The semantics is similar to, e.g., +File.open+.
|
|
17
17
|
# do something
|
18
18
|
end
|
19
19
|
|
20
|
+
You can provide the filename as a string (as above) or as Pathname object.
|
21
|
+
|
22
|
+
pathname = Pathname('spec/data/workbook.xls')
|
23
|
+
workbook = Workbook.open(pathname)
|
24
|
+
|
20
25
|
The options are the following:
|
21
26
|
|
22
27
|
+:default+:: if the workbook was already open, then use the properties of this workbook.otherwise use the properties stated in +:default+
|
@@ -195,12 +200,11 @@ The method +unobtrusively+ enables the user to read or modify a workbook, no mat
|
|
195
200
|
|
196
201
|
Options are the following:
|
197
202
|
|
198
|
-
+:if_closed+:: the Excel instance in which to open the workbook, if it was closed (default: +:current+). (Note: this option works workbooks opened via RobustExcelOle only.)
|
199
|
-
|
200
203
|
+:read_only+:: Whether the workbook shall be forced to be open in ReadOnly mode
|
201
|
-
+:writable+:: Whether changes in the workbook shall be saved
|
202
|
-
|
204
|
+
+:writable+:: Whether changes in the workbook shall be saved and the workbook shall be opened in ReadOnly mode by default (i.e., when the workbook was not open before) (default: true)
|
203
205
|
+:keep_open+:: Whether the workbook shall be open after unobtrusively opening (default: false)
|
206
|
+
+:if_closed+:: the Excel instance in which to open the workbook, if it was closed (default: +:current+).
|
207
|
+
(Note: this option works workbooks opened via RobustExcelOle only.)
|
204
208
|
|
205
209
|
There are the class method and the instance method of +unobtrusively+. Here is an example of the class method:
|
206
210
|
|
data/lib/robust_excel_ole.rb
CHANGED
@@ -3,8 +3,8 @@ if RUBY_PLATFORM =~ /java/
|
|
3
3
|
else
|
4
4
|
require 'win32ole'
|
5
5
|
end
|
6
|
-
require File.join(File.dirname(__FILE__), 'robust_excel_ole/base')
|
7
6
|
require File.join(File.dirname(__FILE__), 'robust_excel_ole/general')
|
7
|
+
require File.join(File.dirname(__FILE__), 'robust_excel_ole/base')
|
8
8
|
require File.join(File.dirname(__FILE__), 'robust_excel_ole/vba_objects')
|
9
9
|
require File.join(File.dirname(__FILE__), 'robust_excel_ole/range_owners')
|
10
10
|
require File.join(File.dirname(__FILE__), 'robust_excel_ole/address_tool')
|
@@ -18,5 +18,4 @@ require File.join(File.dirname(__FILE__), 'robust_excel_ole/list_object')
|
|
18
18
|
require File.join(File.dirname(__FILE__), 'robust_excel_ole/cygwin') if RUBY_PLATFORM =~ /cygwin/
|
19
19
|
require File.join(File.dirname(__FILE__), 'robust_excel_ole/version')
|
20
20
|
|
21
|
-
|
22
|
-
include General
|
21
|
+
General.init_reo_for_win32ole
|
@@ -15,6 +15,7 @@ module RobustExcelOle
|
|
15
15
|
# See https://docs.microsoft.com/en-us/office/vba/api/excel.application(object)#methods
|
16
16
|
|
17
17
|
class Excel < VbaObjects
|
18
|
+
|
18
19
|
attr_reader :ole_excel
|
19
20
|
attr_reader :properties
|
20
21
|
attr_reader :address_tool
|
@@ -76,7 +77,7 @@ module RobustExcelOle
|
|
76
77
|
end
|
77
78
|
connected = (not ole_xl.nil?) && win32ole_excel.nil?
|
78
79
|
ole_xl ||= WIN32OLE.new('Excel.Application')
|
79
|
-
hwnd = ole_xl.
|
80
|
+
hwnd = ole_xl.Hwnd
|
80
81
|
stored = hwnd2excel(hwnd)
|
81
82
|
if stored && stored.alive?
|
82
83
|
result = stored
|
@@ -297,7 +298,7 @@ module RobustExcelOle
|
|
297
298
|
finishing_living_excel = alive?
|
298
299
|
if finishing_living_excel
|
299
300
|
hwnd = (begin
|
300
|
-
@ole_excel.
|
301
|
+
@ole_excel.Hwnd
|
301
302
|
rescue
|
302
303
|
nil
|
303
304
|
end)
|
@@ -370,7 +371,7 @@ module RobustExcelOle
|
|
370
371
|
number = 0
|
371
372
|
WIN32OLE.connect('winmgmts:\\\\.').InstancesOf('win32_process').each do |p|
|
372
373
|
begin
|
373
|
-
if p.
|
374
|
+
if p.Name == 'EXCEL.EXE'
|
374
375
|
Process.kill('KILL', p.processid)
|
375
376
|
number += 1
|
376
377
|
end
|
@@ -384,7 +385,7 @@ module RobustExcelOle
|
|
384
385
|
|
385
386
|
def self.excels_number
|
386
387
|
processes = WIN32OLE.connect('winmgmts:\\\\.').InstancesOf('win32_process')
|
387
|
-
processes.select { |p| p.
|
388
|
+
processes.select { |p| p.Name == 'EXCEL.EXE' }.size
|
388
389
|
end
|
389
390
|
|
390
391
|
def self.known_excels_number
|
@@ -417,7 +418,7 @@ module RobustExcelOle
|
|
417
418
|
result.Visible # send any method, just to see if it responds
|
418
419
|
rescue
|
419
420
|
trace 'dead excel ' + (begin
|
420
|
-
"Window-handle = #{result.
|
421
|
+
"Window-handle = #{result.Hwnd}"
|
421
422
|
rescue
|
422
423
|
'without window handle'
|
423
424
|
end)
|
@@ -471,13 +472,13 @@ module RobustExcelOle
|
|
471
472
|
pid2excel[pid] = excel
|
472
473
|
end
|
473
474
|
processes = WIN32OLE.connect('winmgmts:\\\\.').InstancesOf('win32_process')
|
474
|
-
processes.select { |p| Excel.new(pid2excel[p.
|
475
|
+
processes.select { |p| Excel.new(pid2excel[p.ProcessId]) if p.Name == 'EXCEL.EXE' && pid2excel.include?(p.ProcessId) }
|
475
476
|
result = []
|
476
477
|
processes.each do |p|
|
477
|
-
next unless p.
|
478
|
+
next unless p.Name == 'EXCEL.EXE'
|
478
479
|
|
479
|
-
if pid2excel.include?(p.
|
480
|
-
excel = pid2excel[p.
|
480
|
+
if pid2excel.include?(p.ProcessId)
|
481
|
+
excel = pid2excel[p.ProcessId]
|
481
482
|
result << excel
|
482
483
|
end
|
483
484
|
# how to connect to an (interactively opened) Excel instance and get a WIN32OLE object?
|
@@ -684,21 +685,7 @@ module RobustExcelOle
|
|
684
685
|
# Win32API.new("user32","SetForegroundWindow","","I").call
|
685
686
|
# end
|
686
687
|
end
|
687
|
-
|
688
|
-
# returns the value of a range
|
689
|
-
# @param [String] name the name of a range
|
690
|
-
# @returns [Variant] the value of the range
|
691
|
-
def [] name
|
692
|
-
namevalue_glob(name)
|
693
|
-
end
|
694
|
-
|
695
|
-
# sets the value of a range
|
696
|
-
# @param [String] name the name of the range
|
697
|
-
# @param [Variant] value the contents of the range
|
698
|
-
def []=(name, value)
|
699
|
-
set_namevalue_glob(name, value)
|
700
|
-
end
|
701
|
-
|
688
|
+
|
702
689
|
# @private
|
703
690
|
# returns active workbook
|
704
691
|
def workbook
|
@@ -717,6 +704,9 @@ module RobustExcelOle
|
|
717
704
|
to_s
|
718
705
|
end
|
719
706
|
|
707
|
+
using ParentRefinement
|
708
|
+
using StringRefinement
|
709
|
+
|
720
710
|
# @private
|
721
711
|
def self.workbook_class
|
722
712
|
@workbook_class ||= begin
|
@@ -1,74 +1,175 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
|
+
require 'pathname'
|
2
3
|
|
3
|
-
|
4
|
+
# @private
|
5
|
+
module ToReoRefinement
|
4
6
|
|
5
|
-
|
6
|
-
::EXPANDPATH_JRUBY_BUG = IS_JRUBY_PLATFORM && true
|
7
|
-
::CONNECT_JRUBY_BUG = IS_JRUBY_PLATFORM && true
|
8
|
-
::COPYSHEETS_JRUBY_BUG = IS_JRUBY_PLATFORM && true
|
9
|
-
::ERRORMESSAGE_JRUBY_BUG = IS_JRUBY_PLATFORM && true
|
10
|
-
::CONNECT_EXCEL_JRUBY_BUG = IS_JRUBY_PLATFORM && true
|
11
|
-
::RANGES_JRUBY_BUG = IS_JRUBY_PLATFORM && true
|
12
|
-
|
13
|
-
@private
|
14
|
-
NetworkDrive = Struct.new(:drive_letter, :network_name) do
|
7
|
+
refine WIN32OLE do
|
15
8
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
9
|
+
# type-lifting WIN32OLE objects to RobustExcelOle objects
|
10
|
+
def to_reo
|
11
|
+
General.class2method.each do |element|
|
12
|
+
classname = element.first.first
|
13
|
+
method = element.first.last
|
14
|
+
begin
|
15
|
+
self.send(method)
|
16
|
+
if classname == RobustExcelOle::Range && self.Rows.Count == 1 && self.Columns.Count == 1
|
17
|
+
return Cell.new(self, self.Parent)
|
18
|
+
else
|
19
|
+
return classname.new(self)
|
20
|
+
end
|
21
|
+
rescue
|
22
|
+
next
|
23
|
+
end
|
21
24
|
end
|
22
|
-
|
25
|
+
raise TypeREOError, "given object cannot be type-lifted to a RobustExcelOle object"
|
23
26
|
end
|
24
27
|
|
25
28
|
end
|
26
29
|
|
27
|
-
|
28
|
-
def hostnameshare2networkpath(filename)
|
29
|
-
return filename unless filename[0,2] == "//"
|
30
|
-
network = WIN32OLE.new('WScript.Network')
|
31
|
-
drives = network.enumnetworkdrives
|
32
|
-
network_drives = NetworkDrive.get_all(drives)
|
33
|
-
f_c = filename.dup
|
34
|
-
network_drive = network_drives.find do |d|
|
35
|
-
e = f_c.sub!(d.network_name,d.drive_letter)
|
36
|
-
return e if e
|
37
|
-
end
|
38
|
-
filename
|
39
|
-
end
|
30
|
+
end
|
40
31
|
|
41
|
-
|
42
|
-
|
43
|
-
return file if file[0,2] == "//"
|
44
|
-
file[0,2] = './' if ::EXPANDPATH_JRUBY_BUG && file =~ /[A-Z]:[^\/]/
|
45
|
-
file = File.expand_path(file)
|
46
|
-
file = RobustExcelOle::Cygwin.cygpath('-w', file) if RUBY_PLATFORM =~ /cygwin/
|
47
|
-
WIN32OLE.new('Scripting.FileSystemObject').GetAbsolutePathName(file).tr('/','\\')
|
48
|
-
end
|
32
|
+
# @private
|
33
|
+
class WIN32OLE
|
49
34
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
35
|
+
include Enumerable
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
# @private
|
40
|
+
module FindAllIndicesRefinement
|
41
|
+
|
42
|
+
refine Array do
|
43
|
+
|
44
|
+
def find_all_indices elem
|
45
|
+
found, index, result = -1, -1, []
|
46
|
+
while found
|
47
|
+
found = self[index+1..-1].index(elem)
|
48
|
+
if found
|
49
|
+
index = index + found + 1
|
50
|
+
result << index
|
51
|
+
end
|
52
|
+
end
|
53
|
+
result
|
54
|
+
end
|
56
55
|
|
57
|
-
# @private
|
58
|
-
def normalize(path)
|
59
|
-
return unless path
|
60
|
-
path = path.gsub('/./', '/') + '/'
|
61
|
-
path = path.gsub(/[\/\\]+/, '/')
|
62
|
-
nil while path.gsub!(/(\/|^)(?!\.\.?)([^\/]+)\/\.\.\//, '\1')
|
63
|
-
path = path.chomp('/')
|
64
|
-
path
|
65
56
|
end
|
66
57
|
|
67
|
-
|
58
|
+
end
|
59
|
+
|
60
|
+
# @private
|
61
|
+
module StringRefinement
|
62
|
+
|
63
|
+
refine String do
|
64
|
+
|
65
|
+
def / path_part
|
66
|
+
if empty?
|
67
|
+
path_part
|
68
|
+
else
|
69
|
+
if path_part.nil? || path_part.empty?
|
70
|
+
self
|
71
|
+
else
|
72
|
+
begin
|
73
|
+
File.join self, path_part
|
74
|
+
rescue TypeError
|
75
|
+
raise TypeError, "Only strings can be parts of paths (given: #{path_part.inspect} of class #{path_part.class})"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# taken from http://apidock.com/rails/ActiveSupport/Inflector/underscore
|
82
|
+
def underscore
|
83
|
+
word = gsub('::', '/')
|
84
|
+
word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
|
85
|
+
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
86
|
+
word.tr!('-', '_')
|
87
|
+
word.downcase!
|
88
|
+
word
|
89
|
+
end
|
90
|
+
|
91
|
+
def delete_multiple_underscores
|
92
|
+
word = self
|
93
|
+
while word.index('__') do
|
94
|
+
word.gsub!('__','_')
|
95
|
+
end
|
96
|
+
word
|
97
|
+
end
|
98
|
+
|
99
|
+
def replace_umlauts
|
100
|
+
word = self
|
101
|
+
word.gsub!('ä','ae')
|
102
|
+
word.gsub!('Ä','Ae')
|
103
|
+
word.gsub!('ö','oe')
|
104
|
+
word.gsub!('Ö','Oe')
|
105
|
+
word.gsub!('ü','ue')
|
106
|
+
word.gsub!('Ü','Ue')
|
107
|
+
#word.gsub!(/\x84/,'ae')
|
108
|
+
#word.gsub!(/\x8E/,'Ae')
|
109
|
+
#word.gsub!(/\x94/,'oe')
|
110
|
+
#word.gsub!(/\x99/,'Oe')
|
111
|
+
#word.gsub!(/\x81/,'ue')
|
112
|
+
#word.gsub!(/\x9A/,'Ue')
|
113
|
+
word
|
114
|
+
end
|
115
|
+
|
116
|
+
# taken from http://apidock.com/rails/ActiveSupport/Inflector/constantize
|
117
|
+
# File activesupport/lib/active_support/inflector/methods.rb, line 226
|
118
|
+
def constantize # (camel_cased_word)
|
119
|
+
names = split('::')
|
120
|
+
|
121
|
+
# Trigger a builtin NameError exception including the ill-formed constant in the message.
|
122
|
+
Object.const_get(self) if names.empty?
|
123
|
+
|
124
|
+
# Remove the first blank element in case of '::ClassName' notation.
|
125
|
+
names.shift if names.size > 1 && names.first.empty?
|
68
126
|
|
127
|
+
names.inject(Object) do |constant, name|
|
128
|
+
if constant == Object
|
129
|
+
constant.const_get(name)
|
130
|
+
else
|
131
|
+
candidate = constant.const_get(name)
|
132
|
+
next candidate if constant.const_defined?(name)
|
133
|
+
next candidate unless Object.const_defined?(name)
|
134
|
+
|
135
|
+
# Go down the ancestors to check it it's owned
|
136
|
+
# directly before we reach Object or the end of ancestors.
|
137
|
+
constant = constant.ancestors.inject do |const, ancestor|
|
138
|
+
break const if ancestor == Object
|
139
|
+
break ancestor if ancestor.const_defined?(name)
|
140
|
+
|
141
|
+
const
|
142
|
+
end
|
143
|
+
|
144
|
+
# owner is in Object, so raise
|
145
|
+
constant.const_get(name)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
69
150
|
end
|
70
151
|
|
71
152
|
# @private
|
153
|
+
module ParentRefinement
|
154
|
+
|
155
|
+
using StringRefinement
|
156
|
+
|
157
|
+
# taken from http://api.rubyonrails.org/v2.3.8/classes/ActiveSupport/CoreExtensions/Module.html#M000806
|
158
|
+
refine Module do
|
159
|
+
|
160
|
+
def parent_name
|
161
|
+
unless defined? @parent_name
|
162
|
+
@parent_name = name =~ /::[^:]+\Z/ ? $`.freeze : nil
|
163
|
+
end
|
164
|
+
@parent_name
|
165
|
+
end
|
166
|
+
|
167
|
+
def parent
|
168
|
+
parent_name ? parent_name.constantize : Object
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
72
173
|
class Integer
|
73
174
|
|
74
175
|
alias old_spaceship <=>
|
@@ -98,179 +199,202 @@ class Array
|
|
98
199
|
end
|
99
200
|
end
|
100
201
|
|
101
|
-
def find_each_index find
|
102
|
-
found, index, q = -1, -1, []
|
103
|
-
while found
|
104
|
-
found = self[index+1..-1].index(find)
|
105
|
-
if found
|
106
|
-
index = index + found + 1
|
107
|
-
q << index
|
108
|
-
end
|
109
|
-
end
|
110
|
-
q
|
111
|
-
end
|
112
202
|
end
|
113
203
|
|
204
|
+
|
205
|
+
=begin
|
114
206
|
# @private
|
115
|
-
|
207
|
+
module SpaceshipRefinement
|
116
208
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
]
|
128
|
-
class2method.each do |element|
|
129
|
-
classname = element.first.first
|
130
|
-
method = element.first.last
|
131
|
-
begin
|
132
|
-
self.send(method)
|
133
|
-
if classname == RobustExcelOle::Range && self.Rows.Count == 1 && self.Columns.Count == 1
|
134
|
-
return Cell.new(self, self.Parent)
|
135
|
-
else
|
136
|
-
return classname.new(self)
|
137
|
-
end
|
138
|
-
rescue
|
139
|
-
next
|
209
|
+
refine Integer do
|
210
|
+
|
211
|
+
alias old_spaceship <=>
|
212
|
+
|
213
|
+
def <=> other
|
214
|
+
# p other
|
215
|
+
if other.is_a? Array
|
216
|
+
self <=> other.first
|
217
|
+
else
|
218
|
+
old_spaceship other
|
140
219
|
end
|
141
220
|
end
|
142
|
-
raise TypeREOError, "given object cannot be type-lifted to a RobustExcelOle object"
|
143
221
|
end
|
144
222
|
|
223
|
+
refine Array do
|
145
224
|
|
146
|
-
|
147
|
-
# puts "method_missing:"
|
148
|
-
# puts "name: #{name.inspect}"
|
149
|
-
# puts "self: #{self}"
|
150
|
-
# puts "self.ole_type: #{self.ole_type}"
|
151
|
-
# puts "self.to_reo: #{self.to_reo}"
|
152
|
-
# begin
|
153
|
-
# reo_obj = self.to_reo
|
154
|
-
# rescue
|
155
|
-
# puts "error: #{$!.message}"
|
156
|
-
# raise # NoMethodError, "undefined method #{name.inspect} for #{self.inspect}"
|
157
|
-
# end
|
158
|
-
# reo_obj.send(name, *args, &blk)
|
159
|
-
# end
|
160
|
-
|
161
|
-
#alias method_missing_before_implicit_typelift method_missing
|
162
|
-
#def method_missing(name, *args, &blk)
|
163
|
-
# begin
|
164
|
-
# reo_obj = self.to_reo
|
165
|
-
# rescue
|
166
|
-
# puts "$!.message: #{$!.message}"
|
167
|
-
# method_missing_before_implicit_typelift(name, *args, &blk)
|
168
|
-
# end
|
169
|
-
# reo_obj.send(name, *args, &blk)
|
170
|
-
#end
|
171
|
-
|
172
|
-
end
|
225
|
+
alias old_spaceship <=>
|
173
226
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
path_part
|
179
|
-
else
|
180
|
-
if path_part.nil? || path_part.empty?
|
181
|
-
self
|
227
|
+
def <=> other
|
228
|
+
# p other
|
229
|
+
if other.is_a? Integer
|
230
|
+
self <=> [other]
|
182
231
|
else
|
183
|
-
|
184
|
-
File.join self, path_part
|
185
|
-
rescue TypeError
|
186
|
-
raise TypeError, "Only strings can be parts of paths (given: #{path_part.inspect} of class #{path_part.class})"
|
187
|
-
end
|
232
|
+
old_spaceship other
|
188
233
|
end
|
189
234
|
end
|
190
235
|
end
|
236
|
+
end
|
237
|
+
=end
|
238
|
+
|
239
|
+
module General
|
240
|
+
|
241
|
+
IS_JRUBY_PLATFORM = (RUBY_PLATFORM =~ /java/)
|
242
|
+
::EXPANDPATH_JRUBY_BUG = IS_JRUBY_PLATFORM && true
|
243
|
+
::CONNECT_JRUBY_BUG = IS_JRUBY_PLATFORM && true
|
244
|
+
::COPYSHEETS_JRUBY_BUG = IS_JRUBY_PLATFORM && true
|
245
|
+
::ERRORMESSAGE_JRUBY_BUG = IS_JRUBY_PLATFORM && true
|
246
|
+
::CONNECT_EXCEL_JRUBY_BUG = IS_JRUBY_PLATFORM && true
|
247
|
+
::RANGES_JRUBY_BUG = IS_JRUBY_PLATFORM && true
|
248
|
+
|
249
|
+
# @private
|
250
|
+
NetworkDrive = Struct.new(:drive_letter, :network_name) do
|
251
|
+
|
252
|
+
def self.get_all(drives)
|
253
|
+
ndrives = []
|
254
|
+
count = drives.Count
|
255
|
+
(0..(count - 1)).step(2) do |i|
|
256
|
+
ndrives << NetworkDrive.new( drives.Item(i), drives.Item(i + 1).tr('\\','/'))
|
257
|
+
end
|
258
|
+
ndrives
|
259
|
+
end
|
191
260
|
|
192
|
-
# taken from http://apidock.com/rails/ActiveSupport/Inflector/underscore
|
193
|
-
def underscore
|
194
|
-
word = gsub('::', '/')
|
195
|
-
word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
|
196
|
-
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
197
|
-
word.tr!('-', '_')
|
198
|
-
word.downcase!
|
199
|
-
word
|
200
261
|
end
|
201
262
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
263
|
+
# @private
|
264
|
+
def hostnameshare2networkpath(filename)
|
265
|
+
return filename unless filename[0,2] == "//"
|
266
|
+
network = WIN32OLE.new('WScript.Network')
|
267
|
+
drives = network.enumnetworkdrives
|
268
|
+
network_drives = NetworkDrive.get_all(drives)
|
269
|
+
f_c = filename.dup
|
270
|
+
network_drive = network_drives.find do |d|
|
271
|
+
e = f_c.sub!(d.network_name,d.drive_letter)
|
272
|
+
return e if e
|
206
273
|
end
|
207
|
-
|
208
|
-
end
|
274
|
+
filename
|
275
|
+
end
|
209
276
|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
#word.gsub!(/\x84/,'ae')
|
219
|
-
#word.gsub!(/\x8E/,'Ae')
|
220
|
-
#word.gsub!(/\x94/,'oe')
|
221
|
-
#word.gsub!(/\x99/,'Oe')
|
222
|
-
#word.gsub!(/\x81/,'ue')
|
223
|
-
#word.gsub!(/\x9A/,'Ue')
|
224
|
-
word
|
277
|
+
# @private
|
278
|
+
def absolute_path(file)
|
279
|
+
file = file.to_path if file.respond_to?(:to_path)
|
280
|
+
return file if file[0,2] == "//"
|
281
|
+
file[0,2] = './' if ::EXPANDPATH_JRUBY_BUG && file =~ /[A-Z]:[^\/]/
|
282
|
+
file = File.expand_path(file)
|
283
|
+
file = RobustExcelOle::Cygwin.cygpath('-w', file) if RUBY_PLATFORM =~ /cygwin/
|
284
|
+
WIN32OLE.new('Scripting.FileSystemObject').GetAbsolutePathName(file) #.tr('/','\\')
|
225
285
|
end
|
226
286
|
|
227
|
-
#
|
228
|
-
|
229
|
-
|
230
|
-
|
287
|
+
# @private
|
288
|
+
def canonize(filename)
|
289
|
+
raise TypeREOError, "No string given to canonize, but #{filename.inspect}" unless filename.is_a?(String)
|
290
|
+
filename = hostnameshare2networkpath(filename)
|
291
|
+
normalize(filename) if filename
|
292
|
+
end
|
231
293
|
|
232
|
-
|
233
|
-
|
294
|
+
# @private
|
295
|
+
def normalize(path)
|
296
|
+
return unless path
|
297
|
+
path = path.gsub('/./', '/') + '/'
|
298
|
+
path = path.gsub(/[\/\\]+/, '/')
|
299
|
+
nil while path.gsub!(/(\/|^)(?!\.\.?)([^\/]+)\/\.\.\//, '\1')
|
300
|
+
path = path.chomp('/')
|
301
|
+
path
|
302
|
+
end
|
234
303
|
|
235
|
-
|
236
|
-
|
304
|
+
def change_current_binding(current_object)
|
305
|
+
Pry.change_current_binding(current_object)
|
306
|
+
end
|
237
307
|
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
308
|
+
def class2method
|
309
|
+
[{RobustExcelOle::Excel => :Hwnd},
|
310
|
+
{RobustExcelOle::Workbook => :FullName},
|
311
|
+
{RobustExcelOle::Worksheet => :UsedRange},
|
312
|
+
{RobustExcelOle::Range => :Row},
|
313
|
+
{RobustExcelOle::ListObject => :ListRows}]
|
314
|
+
end
|
245
315
|
|
246
|
-
|
247
|
-
# directly before we reach Object or the end of ancestors.
|
248
|
-
constant = constant.ancestors.inject do |const, ancestor|
|
249
|
-
break const if ancestor == Object
|
250
|
-
break ancestor if ancestor.const_defined?(name)
|
316
|
+
using ToReoRefinement
|
251
317
|
|
252
|
-
|
318
|
+
# enable RobustExcelOle methods to Win32Ole objects
|
319
|
+
def init_reo_for_win32ole
|
320
|
+
exclude_list = [:each, :each_with_index, :inspect, :Calculation=]
|
321
|
+
class2method.each do |element|
|
322
|
+
classname = element.first.first
|
323
|
+
classname.instance_methods(false).each do |inst_method|
|
324
|
+
if !exclude_list.include?(inst_method)
|
325
|
+
WIN32OLE.send(:define_method, inst_method) do |*args, &blk|
|
326
|
+
self.to_reo.send(inst_method, *args, &blk)
|
327
|
+
end
|
253
328
|
end
|
254
|
-
|
255
|
-
# owner is in Object, so raise
|
256
|
-
constant.const_get(name)
|
257
329
|
end
|
258
330
|
end
|
331
|
+
nil
|
259
332
|
end
|
333
|
+
|
334
|
+
module_function :absolute_path, :canonize, :normalize, :change_current_binding, :class2method,
|
335
|
+
:init_reo_for_win32ole, :hostnameshare2networkpath
|
336
|
+
|
260
337
|
end
|
261
338
|
|
262
|
-
|
339
|
+
|
263
340
|
# @private
|
264
|
-
class
|
265
|
-
|
266
|
-
|
267
|
-
|
341
|
+
class Pry
|
342
|
+
|
343
|
+
# change the current binding such that self is the current object in the pry-instance,
|
344
|
+
# preserve the local variables
|
345
|
+
|
346
|
+
class << self
|
347
|
+
attr_accessor :pry_instance
|
348
|
+
end
|
349
|
+
|
350
|
+
def self.change_current_binding(current_object)
|
351
|
+
pry_instance = self.pry_instance
|
352
|
+
old_binding = pry_instance.binding_stack.pop
|
353
|
+
pry_instance.push_binding(current_object.__binding__)
|
354
|
+
exclude_vars = [:__, :_, :_dir, :_dir_, :_file, :_file_, :_in_, :_out_, :_ex, :_ex_, :pry_instance]
|
355
|
+
old_binding.local_variables.each do |var|
|
356
|
+
pry_instance.add_sticky_local(var) {old_binding.local_variable_get(var)} unless exclude_vars.include?(var)
|
268
357
|
end
|
269
|
-
|
358
|
+
self.pry_instance = pry_instance
|
359
|
+
nil
|
270
360
|
end
|
271
361
|
|
272
|
-
def
|
273
|
-
|
362
|
+
def push_initial_binding(target = nil)
|
363
|
+
# memorize the current pry instance
|
364
|
+
self.class.pry_instance = self
|
365
|
+
push_binding(target || Pry.toplevel_binding)
|
366
|
+
end
|
367
|
+
|
368
|
+
class REPL
|
369
|
+
|
370
|
+
def read
|
371
|
+
@indent.reset if pry.eval_string.empty?
|
372
|
+
current_prompt = pry.select_prompt
|
373
|
+
indentation = pry.config.auto_indent ? @indent.current_prefix : ''
|
374
|
+
val = read_line("#{current_prompt}#{indentation}")
|
375
|
+
# Return nil for EOF, :no_more_input for error, or :control_c for <Ctrl-C>
|
376
|
+
return val unless val.is_a?(String)
|
377
|
+
if pry.config.auto_indent
|
378
|
+
original_val = "#{indentation}#{val}"
|
379
|
+
indented_val = @indent.indent(val)
|
380
|
+
|
381
|
+
if output.tty? &&
|
382
|
+
pry.config.correct_indent &&
|
383
|
+
Pry::Helpers::BaseHelpers.use_ansi_codes?
|
384
|
+
# avoid repeating read line
|
385
|
+
|
386
|
+
#output.print @indent.correct_indentation(
|
387
|
+
# current_prompt,
|
388
|
+
# indented_val,
|
389
|
+
# calculate_overhang(current_prompt, original_val, indented_val)
|
390
|
+
#)
|
391
|
+
output.flush
|
392
|
+
end
|
393
|
+
else
|
394
|
+
indented_val = val
|
395
|
+
end
|
396
|
+
indented_val
|
397
|
+
end
|
274
398
|
end
|
275
399
|
end
|
276
400
|
|
@@ -293,7 +417,4 @@ module MethodHelpers
|
|
293
417
|
super
|
294
418
|
end
|
295
419
|
end
|
296
|
-
|
297
420
|
end
|
298
|
-
|
299
|
-
REO = RobustExcelOle
|