robust_excel_ole 1.20 → 1.23
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 +10 -1
- data/README.rdoc +1 -121
- data/bin/jreo +11 -11
- data/bin/reo +11 -11
- data/docs/README_ranges.rdoc +26 -6
- data/docs/README_sheet.rdoc +1 -1
- data/jreo.bat +1 -1
- data/lib/reo_console.rb +10 -10
- data/lib/robust_excel_ole.rb +1 -1
- data/lib/robust_excel_ole/base.rbs +63 -0
- data/lib/robust_excel_ole/bookstore.rb +4 -3
- data/lib/robust_excel_ole/cell.rb +9 -5
- data/lib/robust_excel_ole/cell.rbs +25 -0
- data/lib/robust_excel_ole/excel.rb +1 -6
- data/lib/robust_excel_ole/general.rb +41 -58
- data/lib/robust_excel_ole/list_object.rb +54 -21
- data/lib/robust_excel_ole/range.rb +88 -104
- data/lib/robust_excel_ole/range_owners.rb +4 -30
- data/lib/robust_excel_ole/vba_objects.rbs +23 -0
- data/lib/robust_excel_ole/version.rb +1 -1
- data/lib/robust_excel_ole/workbook.rb +27 -8
- data/lib/robust_excel_ole/worksheet.rb +42 -16
- data/reo.bat +3 -0
- data/robust_excel_ole.gemspec +1 -0
- data/spec/general_spec.rb +10 -11
- data/spec/list_object_spec.rb +18 -5
- data/spec/range_spec.rb +8 -2
- data/spec/workbook_specs/workbook_misc_spec.rb +12 -2
- data/spec/worksheet_spec.rb +3 -0
- metadata +20 -2
@@ -12,26 +12,30 @@ module RobustExcelOle
|
|
12
12
|
ole_cell
|
13
13
|
end
|
14
14
|
|
15
|
-
def
|
15
|
+
def value
|
16
16
|
self.Value
|
17
17
|
end
|
18
18
|
|
19
|
-
def
|
19
|
+
def value=(value)
|
20
20
|
self.Value = value
|
21
21
|
end
|
22
22
|
|
23
|
+
alias_method :v, :value
|
24
|
+
alias_method :v=, :value=
|
25
|
+
|
26
|
+
# @private
|
23
27
|
def ole_cell
|
24
28
|
@ole_range = @ole_range.MergeArea.Item(1,1) if @ole_range.MergeCells
|
25
29
|
end
|
26
30
|
|
27
31
|
# @private
|
28
32
|
def to_s
|
29
|
-
@
|
33
|
+
"#<Cell:" + " (#{@ole_range.Row},#{@ole_range.Column})" + ">"
|
30
34
|
end
|
31
35
|
|
32
36
|
# @private
|
33
|
-
def inspect
|
34
|
-
|
37
|
+
def inspect
|
38
|
+
self.to_s[0..-2] + " #{@ole_range.Parent.Name}" + ">"
|
35
39
|
end
|
36
40
|
|
37
41
|
private
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module RobustExcelOle
|
4
|
+
|
5
|
+
class Cell < Range
|
6
|
+
|
7
|
+
def initialize: (win32_cell: WIN32OLE, worksheet: Worksheet) -> void
|
8
|
+
|
9
|
+
def value -> String
|
10
|
+
|
11
|
+
def value= (value: Variant) -> Variant
|
12
|
+
|
13
|
+
def v -> String
|
14
|
+
|
15
|
+
def v= (value: Variant) -> Variant
|
16
|
+
|
17
|
+
def ole_cell -> WIN32OLE | void
|
18
|
+
|
19
|
+
def to_s -> String
|
20
|
+
|
21
|
+
def inspect -> String
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -640,13 +640,8 @@ module RobustExcelOle
|
|
640
640
|
# set options in this Excel instance
|
641
641
|
def for_this_instance(options)
|
642
642
|
set_options(options)
|
643
|
-
#self.class.new(@ole_excel, options)
|
644
643
|
end
|
645
644
|
|
646
|
-
#def set_options(options)
|
647
|
-
# for_this_instance(options)
|
648
|
-
#end
|
649
|
-
|
650
645
|
def set_options(options)
|
651
646
|
@properties ||= { }
|
652
647
|
PROPERTIES.each do |property|
|
@@ -701,7 +696,7 @@ module RobustExcelOle
|
|
701
696
|
# @param [String] name the name of the range
|
702
697
|
# @param [Variant] value the contents of the range
|
703
698
|
def []=(name, value)
|
704
|
-
set_namevalue_glob(name, value
|
699
|
+
set_namevalue_glob(name, value)
|
705
700
|
end
|
706
701
|
|
707
702
|
# @private
|
@@ -10,13 +10,14 @@ module General
|
|
10
10
|
::CONNECT_EXCEL_JRUBY_BUG = IS_JRUBY_PLATFORM && true
|
11
11
|
::RANGES_JRUBY_BUG = IS_JRUBY_PLATFORM && true
|
12
12
|
|
13
|
+
@private
|
13
14
|
NetworkDrive = Struct.new(:drive_letter, :network_name) do
|
14
15
|
|
15
16
|
def self.get_all(drives)
|
16
17
|
ndrives = []
|
17
18
|
count = drives.Count
|
18
19
|
(0..(count - 1)).step(2) do |i|
|
19
|
-
ndrives << NetworkDrive.new( drives.Item(i), drives.Item(i + 1))
|
20
|
+
ndrives << NetworkDrive.new( drives.Item(i), drives.Item(i + 1).tr('\\','/'))
|
20
21
|
end
|
21
22
|
ndrives
|
22
23
|
end
|
@@ -24,65 +25,22 @@ module General
|
|
24
25
|
end
|
25
26
|
|
26
27
|
@private
|
27
|
-
def
|
28
|
+
def hostnameshare2networkpath(filename)
|
29
|
+
return filename unless filename[0,2] == "//"
|
28
30
|
network = WIN32OLE.new('WScript.Network')
|
29
31
|
drives = network.enumnetworkdrives
|
30
|
-
drive_letter, filename_after_drive_letter = filename.split(':')
|
31
|
-
drive_letter = normalize_drive_letter(drive_letter)
|
32
32
|
network_drives = NetworkDrive.get_all(drives)
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
end
|
41
|
-
|
42
|
-
|
43
|
-
=begin
|
44
|
-
NetworkDrive = Struct.new(:drive_letter, :network_name)
|
45
|
-
|
46
|
-
@private
|
47
|
-
def network2hostnamesharepath(filename)
|
48
|
-
puts "network2hostnamesharepath:"
|
49
|
-
puts "filename: #{filename}"
|
50
|
-
network = WIN32OLE.new('WScript.Network')
|
51
|
-
drives = network.enumnetworkdrives
|
52
|
-
puts "drives: #{drives.inspect}"
|
53
|
-
drive_letter, filename_after_drive_letter = filename.split(':')
|
54
|
-
puts "drive_letter: #{drive_letter.inspect}"
|
55
|
-
puts "filename_after_drive_letter: #{filename_after_drive_letter.inspect}"
|
56
|
-
drive_letter = normalize_drive_letter(drive_letter)
|
57
|
-
puts "drive_letter: #{drive_letter.inspect}"
|
58
|
-
network_drives = get_network_drives
|
59
|
-
puts "network_drives: #{network_drives.inspect}"
|
60
|
-
network_drive = network_drives.find{ |d| d.drive_letter == drive_letter }
|
61
|
-
puts "network_drive: #{network_drive.inspect}"
|
62
|
-
return filename unless network_drive
|
63
|
-
#return (File.exists?(filename) ? filename : nil) unless network_drive
|
64
|
-
return network_drive.network_name + filename_after_drive_letter
|
65
|
-
end
|
66
|
-
|
67
|
-
def get_network_drives
|
68
|
-
network = WIN32OLE.new('WScript.Network')
|
69
|
-
drives = network.enumnetworkdrives
|
70
|
-
ndrives = []
|
71
|
-
count = drives.Count
|
72
|
-
(0..(count - 1)).step(2) do |i|
|
73
|
-
ndrives << NetworkDrive.new( drives.Item(i), drives.Item(i + 1))
|
74
|
-
end
|
75
|
-
ndrives
|
76
|
-
end
|
77
|
-
|
78
|
-
def normalize_drive_letter(drive)
|
79
|
-
drive.upcase.end_with?(':') ? drive : "#{drive}:"
|
80
|
-
end
|
81
|
-
|
82
|
-
=end
|
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
|
83
40
|
|
84
41
|
# @private
|
85
|
-
def absolute_path(file)
|
42
|
+
def absolute_path(file)
|
43
|
+
return file if file[0,2] == "//"
|
86
44
|
file[0,2] = './' if ::EXPANDPATH_JRUBY_BUG && file =~ /[A-Z]:[^\/]/
|
87
45
|
file = File.expand_path(file)
|
88
46
|
file = RobustExcelOle::Cygwin.cygpath('-w', file) if RUBY_PLATFORM =~ /cygwin/
|
@@ -92,8 +50,8 @@ module General
|
|
92
50
|
# @private
|
93
51
|
def canonize(filename)
|
94
52
|
raise TypeREOError, "No string given to canonize, but #{filename.inspect}" unless filename.is_a?(String)
|
95
|
-
filename =
|
96
|
-
normalize(filename)
|
53
|
+
filename = hostnameshare2networkpath(filename)
|
54
|
+
normalize(filename) if filename
|
97
55
|
end
|
98
56
|
|
99
57
|
# @private
|
@@ -163,7 +121,7 @@ class WIN32OLE
|
|
163
121
|
class2method = [
|
164
122
|
{Excel => :Hwnd},
|
165
123
|
{Workbook => :FullName},
|
166
|
-
{Worksheet => :
|
124
|
+
{Worksheet => :UsedRange},
|
167
125
|
{RobustExcelOle::Range => :Row},
|
168
126
|
{ListObject => :ListRows}
|
169
127
|
]
|
@@ -224,6 +182,31 @@ class ::String
|
|
224
182
|
word
|
225
183
|
end
|
226
184
|
|
185
|
+
def delete_multiple_underscores
|
186
|
+
word = self
|
187
|
+
while word.index('__') do
|
188
|
+
word.gsub!('__','_')
|
189
|
+
end
|
190
|
+
word
|
191
|
+
end
|
192
|
+
|
193
|
+
def replace_umlauts
|
194
|
+
word = self
|
195
|
+
word.gsub!('ä','ae')
|
196
|
+
word.gsub!('Ä','Ae')
|
197
|
+
word.gsub!('ö','oe')
|
198
|
+
word.gsub!('Ö','Oe')
|
199
|
+
word.gsub!('ü','ue')
|
200
|
+
word.gsub!('Ü','Ue')
|
201
|
+
#word.gsub!(/\x84/,'ae')
|
202
|
+
#word.gsub!(/\x8E/,'Ae')
|
203
|
+
#word.gsub!(/\x94/,'oe')
|
204
|
+
#word.gsub!(/\x99/,'Oe')
|
205
|
+
#word.gsub!(/\x81/,'ue')
|
206
|
+
#word.gsub!(/\x9A/,'Ue')
|
207
|
+
word
|
208
|
+
end
|
209
|
+
|
227
210
|
# taken from http://apidock.com/rails/ActiveSupport/Inflector/constantize
|
228
211
|
# File activesupport/lib/active_support/inflector/methods.rb, line 226
|
229
212
|
def constantize # (camel_cased_word)
|
@@ -14,24 +14,33 @@ module RobustExcelOle
|
|
14
14
|
|
15
15
|
attr_reader :ole_table
|
16
16
|
|
17
|
+
alias ole_object ole_table
|
18
|
+
|
17
19
|
# constructs a list object (or table).
|
18
|
-
# @param [Variable]
|
20
|
+
# @param [Variable] worksheet_or_listobject a worksheet or a list object
|
19
21
|
# @param [Variable] table_name_or_number a table name or table number
|
20
22
|
# @param [Array] position a position of the upper left corner
|
21
23
|
# @param [Integer] rows_count number of rows
|
22
24
|
# @param [Variable] columns_count_or_names number of columns or array of column names
|
23
25
|
# @return [ListObject] a ListObject object
|
24
|
-
def initialize(
|
25
|
-
table_name_or_number = "",
|
26
|
+
def initialize(worksheet_or_listobject,
|
27
|
+
table_name_or_number = "_table_name",
|
26
28
|
position = [1,1],
|
27
29
|
rows_count = 1,
|
28
30
|
columns_count_or_names = 1)
|
29
|
-
|
30
|
-
if
|
31
|
-
|
31
|
+
|
32
|
+
# ole_table is being assigned to the first parameter, if this parameter is a ListObject
|
33
|
+
# otherwise the first parameter could be a worksheet, and get the ole_table via the ListObject name or number
|
34
|
+
@ole_table = if worksheet_or_listobject.respond_to?(:ListRows)
|
35
|
+
worksheet_or_listobject.ole_table
|
32
36
|
else
|
33
|
-
|
34
|
-
|
37
|
+
begin
|
38
|
+
worksheet_or_listobject.send(:ListRows)
|
39
|
+
worksheet_or_listobject
|
40
|
+
rescue
|
41
|
+
@worksheet = worksheet_or_listobject.to_reo
|
42
|
+
@worksheet.ListObjects.Item(table_name_or_number) rescue nil
|
43
|
+
end
|
35
44
|
end
|
36
45
|
unless @ole_table
|
37
46
|
columns_count =
|
@@ -50,6 +59,7 @@ module RobustExcelOle
|
|
50
59
|
end
|
51
60
|
end
|
52
61
|
|
62
|
+
|
53
63
|
ole_table = @ole_table
|
54
64
|
@row_class = Class.new(ListRow) do
|
55
65
|
|
@@ -115,31 +125,42 @@ module RobustExcelOle
|
|
115
125
|
raise TableError, "could not delete values"
|
116
126
|
end
|
117
127
|
end
|
118
|
-
|
128
|
+
|
119
129
|
def method_missing(name, *args)
|
120
|
-
|
130
|
+
name_str = name.to_s
|
131
|
+
core_name = name_str[-1]!='=' ? name_str : name_str[0..-2]
|
121
132
|
column_names = @@ole_table.HeaderRowRange.Value.first
|
122
|
-
|
123
|
-
|
133
|
+
column_name = column_names.find do |c|
|
134
|
+
c == core_name ||
|
135
|
+
c.gsub(/\W/,'') == core_name ||
|
136
|
+
c.replace_umlauts == core_name ||
|
137
|
+
c.gsub(/\W/,'').replace_umlauts == core_name ||
|
138
|
+
c.gsub(/\W/,'').replace_umlauts.underscore.gsub(/[^[\w\d]]/, '_').delete_multiple_underscores == core_name
|
139
|
+
end
|
124
140
|
if column_name
|
125
|
-
|
126
|
-
|
127
|
-
define_getting_setting_method(ole_cell,name.to_s)
|
128
|
-
self.send(name, *args)
|
141
|
+
method_name = core_name.gsub(/\W/,'') + (name_str[-1]!='=' ? "" : "=")
|
142
|
+
define_and_call_method(column_name,method_name,*args)
|
129
143
|
else
|
130
|
-
super
|
144
|
+
super(name, *args)
|
131
145
|
end
|
132
146
|
end
|
133
147
|
|
134
148
|
private
|
135
149
|
|
136
|
-
def
|
137
|
-
|
138
|
-
|
150
|
+
def define_and_call_method(column_name,method_name,*args)
|
151
|
+
ole_cell = @@ole_table.Application.Intersect(
|
152
|
+
@ole_listrow.Range, @@ole_table.ListColumns.Item(column_name).Range)
|
153
|
+
define_getting_setting_method(ole_cell,method_name)
|
154
|
+
self.send(method_name, *args)
|
155
|
+
end
|
156
|
+
|
157
|
+
def define_getting_setting_method(ole_cell,name)
|
158
|
+
if name[-1] != '='
|
159
|
+
self.class.define_method(name) do
|
139
160
|
ole_cell.Value
|
140
161
|
end
|
141
162
|
else
|
142
|
-
self.class.define_method(
|
163
|
+
self.class.define_method(name) do |value|
|
143
164
|
ole_cell.Value = value
|
144
165
|
end
|
145
166
|
end
|
@@ -349,6 +370,16 @@ module RobustExcelOle
|
|
349
370
|
@ole_table.Sort.Apply
|
350
371
|
end
|
351
372
|
|
373
|
+
# @private
|
374
|
+
# returns true, if the list object responds to VBA methods, false otherwise
|
375
|
+
def alive?
|
376
|
+
@ole_table.ListRows
|
377
|
+
true
|
378
|
+
rescue
|
379
|
+
# trace $!.message
|
380
|
+
false
|
381
|
+
end
|
382
|
+
|
352
383
|
# @private
|
353
384
|
def to_s
|
354
385
|
@ole_table.Name.to_s
|
@@ -361,6 +392,8 @@ module RobustExcelOle
|
|
361
392
|
" #{@ole_table.Parent.Name}" + " #{@ole_table.Parent.Parent.Name}" + ">"
|
362
393
|
end
|
363
394
|
|
395
|
+
include MethodHelpers
|
396
|
+
|
364
397
|
private
|
365
398
|
|
366
399
|
def method_missing(name, *args)
|
@@ -5,17 +5,29 @@ module RobustExcelOle
|
|
5
5
|
# This class essentially wraps a Win32Ole Range object.
|
6
6
|
# You can apply all VBA methods (starting with a capital letter)
|
7
7
|
# that you would apply for a Range object.
|
8
|
-
# See https://docs.microsoft.com/en-us/office/vba/api/excel.
|
8
|
+
# See https://docs.microsoft.com/en-us/office/vba/api/excel.range#methods
|
9
9
|
|
10
10
|
class Range < VbaObjects
|
11
|
+
|
11
12
|
include Enumerable
|
13
|
+
|
12
14
|
attr_reader :ole_range
|
13
15
|
attr_reader :worksheet
|
14
16
|
|
17
|
+
alias ole_object ole_range
|
18
|
+
|
19
|
+
|
15
20
|
def initialize(win32_range, worksheet = nil)
|
16
21
|
@ole_range = win32_range
|
17
|
-
@worksheet = worksheet ? worksheet : worksheet_class.new(self.Parent)
|
18
|
-
|
22
|
+
@worksheet = worksheet ? worksheet.to_reo : worksheet_class.new(self.Parent)
|
23
|
+
end
|
24
|
+
|
25
|
+
def rows
|
26
|
+
@rows ||= (1..@ole_range.Rows.Count)
|
27
|
+
end
|
28
|
+
|
29
|
+
def columns
|
30
|
+
@columns ||= (1..@ole_range.Columns.Count)
|
19
31
|
end
|
20
32
|
|
21
33
|
def each
|
@@ -43,7 +55,6 @@ module RobustExcelOle
|
|
43
55
|
# @params [Range] a range
|
44
56
|
# @returns [Array] the values
|
45
57
|
def values(range = nil)
|
46
|
-
#result = map { |x| x.Value }.flatten
|
47
58
|
result_unflatten = if !::RANGES_JRUBY_BUG
|
48
59
|
map { |x| x.v }
|
49
60
|
else
|
@@ -59,17 +70,17 @@ module RobustExcelOle
|
|
59
70
|
end
|
60
71
|
end
|
61
72
|
|
62
|
-
|
73
|
+
# returns flat array of the values of a given range
|
74
|
+
# @returns [Array] values of the range (as a nested array)
|
75
|
+
def value
|
63
76
|
begin
|
64
77
|
if !::RANGES_JRUBY_BUG
|
65
78
|
self.Value
|
66
79
|
else
|
67
|
-
address_r1c1 = self.AddressLocal(true,true,XlR1C1)
|
68
|
-
row, col = address_tool.as_integer_ranges(address_r1c1)
|
69
80
|
values = []
|
70
|
-
|
81
|
+
rows.each do |r|
|
71
82
|
values_col = []
|
72
|
-
|
83
|
+
columns.each{ |c| values_col << worksheet.Cells(r,c).Value}
|
73
84
|
values << values_col
|
74
85
|
end
|
75
86
|
values
|
@@ -80,150 +91,101 @@ module RobustExcelOle
|
|
80
91
|
|
81
92
|
end
|
82
93
|
|
83
|
-
|
94
|
+
# sets the values if the range
|
95
|
+
# @param [Variant] value
|
96
|
+
def value=(value)
|
84
97
|
begin
|
85
98
|
if !::RANGES_JRUBY_BUG
|
86
99
|
ole_range.Value = value
|
87
100
|
else
|
88
|
-
|
89
|
-
|
90
|
-
row.each_with_index do |r,i|
|
91
|
-
col.each_with_index do |c,j|
|
101
|
+
rows.each_with_index do |r,i|
|
102
|
+
columns.each_with_index do |c,j|
|
92
103
|
ole_range.Cells(i+1,j+1).Value = (value.respond_to?(:first) ? value[i][j] : value)
|
93
104
|
end
|
94
105
|
end
|
95
106
|
end
|
96
107
|
value
|
97
108
|
rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException => msg
|
98
|
-
raise RangeNotEvaluatable, "cannot assign value to range #{
|
109
|
+
raise RangeNotEvaluatable, "cannot assign value to range #{self.inspect}"
|
99
110
|
end
|
100
111
|
end
|
101
112
|
|
102
|
-
alias_method :
|
103
|
-
alias_method :
|
113
|
+
alias_method :v, :value
|
114
|
+
alias_method :v=, :value=
|
104
115
|
|
105
|
-
#
|
106
|
-
# @
|
107
|
-
# @
|
108
|
-
|
109
|
-
def copy(dest_address1, sheet_or_dest_address2 = :__not_provided, options_or_sheet = :__not_provided, not_provided_or_options = :__not_provided)
|
110
|
-
dest_address = if sheet_or_dest_address2.is_a?(Object::Range) or sheet_or_dest_address2.is_a?(Integer)
|
111
|
-
[dest_address1,sheet_or_dest_address2]
|
112
|
-
else
|
113
|
-
dest_address1
|
114
|
-
end
|
115
|
-
dest_sheet = if sheet_or_dest_address2.is_a?(Worksheet)
|
116
|
-
sheet_or_dest_address2
|
117
|
-
else
|
118
|
-
if options_or_sheet.is_a?(Worksheet)
|
119
|
-
options_or_sheet
|
120
|
-
else
|
121
|
-
@worksheet
|
122
|
-
end
|
123
|
-
end
|
124
|
-
options = if options_or_sheet.is_a?(Hash)
|
125
|
-
options_or_sheet
|
126
|
-
else
|
127
|
-
if not_provided_or_options.is_a?(Hash)
|
128
|
-
not_provided_or_options
|
129
|
-
else
|
130
|
-
{ }
|
131
|
-
end
|
132
|
-
end
|
133
|
-
rows, columns = address_tool.as_integer_ranges(dest_address)
|
134
|
-
dest_address_is_position = (rows.min == rows.max && columns.min == columns.max)
|
135
|
-
dest_range_address = if (not dest_address_is_position)
|
136
|
-
[rows.min..rows.max,columns.min..columns.max]
|
137
|
-
else
|
138
|
-
if (not options[:transpose])
|
139
|
-
[rows.min..rows.min+self.Rows.Count-1,
|
140
|
-
columns.min..columns.min+self.Columns.Count-1]
|
141
|
-
else
|
142
|
-
[rows.min..rows.min+self.Columns.Count-1,
|
143
|
-
columns.min..columns.min+self.Rows.Count-1]
|
144
|
-
end
|
145
|
-
end
|
146
|
-
dest_range = dest_sheet.range(dest_range_address)
|
116
|
+
# sets the values if the range with a given color
|
117
|
+
# @param [Variant] value
|
118
|
+
# @option opts [Symbol] :color the color of the cell when set
|
119
|
+
def set_value(value, opts = { })
|
147
120
|
begin
|
148
|
-
if
|
149
|
-
|
150
|
-
dest_range.v = options[:transpose] ? self.v.transpose : self.v
|
121
|
+
if !::RANGES_JRUBY_BUG
|
122
|
+
ole_range.Value = value
|
151
123
|
else
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
#dest_range.PasteSpecial('transpose' => true)
|
156
|
-
dest_range.PasteSpecial(XlPasteAll,XlPasteSpecialOperationNone,false,true)
|
157
|
-
else
|
158
|
-
#self.Copy('destination' => dest_range.ole_range)
|
159
|
-
self.Copy(dest_range.ole_range)
|
160
|
-
end
|
161
|
-
else
|
162
|
-
if options[:transpose]
|
163
|
-
added_sheet = @worksheet.workbook.add_sheet
|
164
|
-
self.copy_special(dest_address, added_sheet, :transpose => true)
|
165
|
-
added_sheet.range(dest_range_address).copy_special(dest_address,dest_sheet)
|
166
|
-
@worksheet.workbook.excel.with_displayalerts(false) {added_sheet.Delete}
|
167
|
-
else
|
168
|
-
self.Copy
|
169
|
-
#dest_sheet.Paste('destination' => dest_range.ole_range)
|
170
|
-
dest_sheet.Paste(dest_range.ole_range)
|
124
|
+
rows.each_with_index do |r,i|
|
125
|
+
columns.each_with_index do |c,j|
|
126
|
+
ole_range.Cells(i+1,j+1).Value = (value.respond_to?(:first) ? value[i][j] : value)
|
171
127
|
end
|
172
128
|
end
|
173
129
|
end
|
174
|
-
|
175
|
-
|
130
|
+
ole_range.Interior.ColorIndex = opts[:color] unless opts[:color].nil?
|
131
|
+
value
|
132
|
+
rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException => msg
|
133
|
+
raise RangeNotEvaluatable, "cannot assign value to range #{self.inspect}"
|
176
134
|
end
|
177
135
|
end
|
178
136
|
|
179
|
-
# becomes copy
|
180
137
|
# copies a range
|
181
138
|
# @params [Address or Address-Array] address or upper left position of the destination range
|
182
139
|
# @options [Worksheet] the destination worksheet
|
183
140
|
# @options [Hash] options: :transpose, :values_only
|
184
|
-
def
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
141
|
+
def copy(dest_address, *remaining_args)
|
142
|
+
dest_sheet = @worksheet
|
143
|
+
options = { }
|
144
|
+
remaining_args.each do |arg|
|
145
|
+
case arg
|
146
|
+
when Object::Range, Integer then dest_address = [dest_address,arg]
|
147
|
+
when Worksheet, WIN32OLE then dest_sheet = arg.to_reo
|
148
|
+
when Hash then options = arg
|
149
|
+
else raise RangeNotCopied, "cannot copy range: argument error: #{remaining_args.inspect}"
|
150
|
+
end
|
151
|
+
end
|
152
|
+
begin
|
153
|
+
rows, columns = address_tool.as_integer_ranges(dest_address)
|
154
|
+
dest_address_is_position = (rows.min == rows.max && columns.min == columns.max)
|
155
|
+
dest_range_address = if (not dest_address_is_position)
|
189
156
|
[rows.min..rows.max,columns.min..columns.max]
|
190
157
|
else
|
191
158
|
if (not options[:transpose])
|
192
|
-
[rows.min..rows.min+self.Rows.Count-1,
|
193
|
-
columns.min..columns.min+self.Columns.Count-1]
|
159
|
+
[rows.min..rows.min+self.Rows.Count-1, columns.min..columns.min+self.Columns.Count-1]
|
194
160
|
else
|
195
|
-
[rows.min..rows.min+self.Columns.Count-1,
|
196
|
-
columns.min..columns.min+self.Rows.Count-1]
|
161
|
+
[rows.min..rows.min+self.Columns.Count-1, columns.min..columns.min+self.Rows.Count-1]
|
197
162
|
end
|
198
163
|
end
|
199
|
-
|
200
|
-
begin
|
164
|
+
dest_range = dest_sheet.range(dest_range_address)
|
201
165
|
if options[:values_only]
|
202
|
-
dest_range.
|
166
|
+
dest_range.v = options[:transpose] ? self.v.transpose : self.v
|
203
167
|
else
|
204
|
-
if dest_range.worksheet.workbook.excel == @worksheet.workbook.excel
|
168
|
+
if dest_range.worksheet.workbook.excel == @worksheet.workbook.excel
|
205
169
|
if options[:transpose]
|
206
|
-
self.Copy
|
207
|
-
#dest_range.PasteSpecial('transpose' => true)
|
170
|
+
self.Copy
|
208
171
|
dest_range.PasteSpecial(XlPasteAll,XlPasteSpecialOperationNone,false,true)
|
209
172
|
else
|
210
|
-
#self.Copy('destination' => dest_range.ole_range)
|
211
173
|
self.Copy(dest_range.ole_range)
|
212
174
|
end
|
213
175
|
else
|
214
176
|
if options[:transpose]
|
215
177
|
added_sheet = @worksheet.workbook.add_sheet
|
216
|
-
self.
|
217
|
-
added_sheet.range(dest_range_address).
|
178
|
+
self.copy(dest_address, added_sheet, :transpose => true)
|
179
|
+
added_sheet.range(dest_range_address).copy(dest_address,dest_sheet)
|
218
180
|
@worksheet.workbook.excel.with_displayalerts(false) {added_sheet.Delete}
|
219
181
|
else
|
220
182
|
self.Copy
|
221
|
-
#dest_sheet.Paste('destination' => dest_range.ole_range)
|
222
183
|
dest_sheet.Paste(dest_range.ole_range)
|
223
184
|
end
|
224
185
|
end
|
225
186
|
end
|
226
|
-
|
187
|
+
dest_range
|
188
|
+
rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException => msg
|
227
189
|
raise RangeNotCopied, 'cannot copy range'
|
228
190
|
end
|
229
191
|
end
|
@@ -239,6 +201,26 @@ module RobustExcelOle
|
|
239
201
|
@worksheet.workbook.excel
|
240
202
|
end
|
241
203
|
|
204
|
+
# @private
|
205
|
+
# returns true, if the Range object responds to VBA methods, false otherwise
|
206
|
+
def alive?
|
207
|
+
@ole_range.Row
|
208
|
+
true
|
209
|
+
rescue
|
210
|
+
# trace $!.message
|
211
|
+
false
|
212
|
+
end
|
213
|
+
|
214
|
+
# @private
|
215
|
+
def to_s
|
216
|
+
"#<REO::Range: " + "#{@ole_range.Address('External' => true).gsub(/\$/,'')} " + ">"
|
217
|
+
end
|
218
|
+
|
219
|
+
# @private
|
220
|
+
def inspect
|
221
|
+
to_s
|
222
|
+
end
|
223
|
+
|
242
224
|
# @private
|
243
225
|
def self.worksheet_class
|
244
226
|
@worksheet_class ||= begin
|
@@ -254,6 +236,8 @@ module RobustExcelOle
|
|
254
236
|
self.class.worksheet_class
|
255
237
|
end
|
256
238
|
|
239
|
+
include MethodHelpers
|
240
|
+
|
257
241
|
private
|
258
242
|
|
259
243
|
def method_missing(name, *args)
|