robust_excel_ole 1.35 → 1.36
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/.gitignore +1 -0
- data/Changelog +20 -2
- data/README.rdoc +31 -95
- data/docs/README_excel.rdoc +5 -6
- data/docs/README_listobjects.rdoc +8 -15
- data/docs/README_open.rdoc +48 -25
- data/docs/README_ranges.rdoc +7 -10
- data/docs/README_save_close.rdoc +4 -5
- data/docs/README_sheet.rdoc +4 -8
- data/examples/introductory_examples/example_introductory.rb +1 -1
- data/examples/introductory_examples/example_open.rb +1 -1
- data/lib/robust_excel_ole/excel.rb +98 -16
- data/lib/robust_excel_ole/general.rb +18 -6
- data/lib/robust_excel_ole/list_object.rb +11 -19
- data/lib/robust_excel_ole/list_row.rb +74 -19
- data/lib/robust_excel_ole/range.rb +6 -1
- data/lib/robust_excel_ole/range_owners.rb +24 -17
- data/lib/robust_excel_ole/version.rb +1 -1
- data/lib/robust_excel_ole/workbook.rb +107 -42
- data/lib/robust_excel_ole/worksheet.rb +1 -1
- data/robust_excel_ole.gemspec +0 -1
- data/spec/bookstore_spec.rb +1 -2
- data/spec/data/more_data/workbook.xls +0 -0
- data/spec/data/workbook_linked3.xlsm +0 -0
- data/spec/data/workbook_listobjects.xlsx +0 -0
- data/spec/data/workbook_unsaved.xlsm +0 -0
- data/spec/excel_spec.rb +4 -4
- data/spec/general_spec.rb +1 -2
- data/spec/list_object_spec.rb +26 -9
- data/spec/list_row_spec.rb +34 -20
- data/spec/range_spec.rb +9 -0
- data/spec/workbook_spec.rb +2 -2
- data/spec/workbook_specs/workbook_misc_spec.rb +249 -2
- data/spec/workbook_specs/workbook_open_spec.rb +307 -16
- data/spec/workbook_specs/workbook_unobtr_spec.rb +196 -42
- metadata +4 -16
@@ -1,12 +1,59 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
|
3
3
|
require 'weakref'
|
4
|
-
require '
|
4
|
+
require 'fiddle/import'
|
5
5
|
|
6
6
|
def ka
|
7
7
|
Excel.kill_all
|
8
8
|
end
|
9
9
|
|
10
|
+
module User32
|
11
|
+
# Extend this module to an importer
|
12
|
+
extend Fiddle::Importer
|
13
|
+
# Load 'user32' dynamic library into this importer
|
14
|
+
dlload 'user32'
|
15
|
+
# Set C aliases to this importer for further understanding of function signatures
|
16
|
+
typealias 'HWND', 'HANDLE'
|
17
|
+
typealias 'HANDLE', 'void*'
|
18
|
+
typealias 'LPCSTR', 'const char*'
|
19
|
+
typealias 'LPCWSTR', 'const wchar_t*'
|
20
|
+
typealias 'UINT', 'unsigned int'
|
21
|
+
typealias 'HANDLE', 'void*'
|
22
|
+
typealias 'ppvObject', 'void**'
|
23
|
+
typealias 'DWORD', 'unsigned long'
|
24
|
+
typealias 'LPDWORD', 'DWORD*'
|
25
|
+
# Import C functions from loaded libraries and set them as module functions
|
26
|
+
extern 'DWORD GetWindowThreadProcessId(HWND, LPDWORD)'
|
27
|
+
extern 'HWND FindWindowExA(HWND, HWND, LPCSTR, LPCSTR)'
|
28
|
+
extern 'DWORD SetForegroundWindow(HWND)'
|
29
|
+
end
|
30
|
+
|
31
|
+
module Oleacc
|
32
|
+
# Extend this module to an importer
|
33
|
+
extend Fiddle::Importer
|
34
|
+
# Load 'oleacc' dynamic library into this importer
|
35
|
+
dlload 'oleacc'
|
36
|
+
# Set C aliases to this importer for further understanding of function signatures
|
37
|
+
typealias 'HWND', 'HANDLE'
|
38
|
+
typealias 'HANDLE', 'void*'
|
39
|
+
typealias 'ppvObject', 'void**'
|
40
|
+
typealias 'DWORD', 'unsigned long'
|
41
|
+
typealias 'HRESULT', 'long'
|
42
|
+
Guid = struct [
|
43
|
+
'unsigned long data1',
|
44
|
+
'unsigned short data2',
|
45
|
+
'unsigned short data3',
|
46
|
+
'unsigned char data4[8]'
|
47
|
+
]
|
48
|
+
# Import C functions from loaded libraries and set them as module functions
|
49
|
+
extern 'HRESULT AccessibleObjectFromWindow(HWND, DWORD, struct guid*, ppvObject)'
|
50
|
+
#typealias 'REFIID', 'struct guid*'
|
51
|
+
#extern 'HRESULT AccessibleObjectFromWindow(HWND, DWORD, REFIID, ppvObject)'
|
52
|
+
#extern 'HRESULT AccessibleObjectFromWindow(HWND, DWORD, struct GUID*, ppvObject)'
|
53
|
+
#extern 'HRESULT AccessibleObjectFromWindow(HWND, DWORD, void*, ppvObject)'
|
54
|
+
#extern 'HRESULT AccessibleObjectFromWindow(HWND, DWORD, struct GUID*, ppvObject)'
|
55
|
+
end
|
56
|
+
|
10
57
|
module RobustExcelOle
|
11
58
|
|
12
59
|
# This class essentially wraps a Win32Ole Application object.
|
@@ -114,7 +161,7 @@ module RobustExcelOle
|
|
114
161
|
@ole_excel = WIN32OLE.new('Excel.Application')
|
115
162
|
set_options(opts)
|
116
163
|
if opts[:reopen_workbooks]
|
117
|
-
workbook_class.books.each{ |book| book.
|
164
|
+
workbook_class.books.each{ |book| book.open if !book.alive? && book.excel.alive? && book.excel == self }
|
118
165
|
end
|
119
166
|
end
|
120
167
|
self
|
@@ -294,9 +341,8 @@ module RobustExcelOle
|
|
294
341
|
sleep 0.1
|
295
342
|
if finishing_living_excel
|
296
343
|
if hwnd
|
297
|
-
process_id = Win32API.new('user32', 'GetWindowThreadProcessId', %w[I P], 'I')
|
298
344
|
pid_puffer = ' ' * 32
|
299
|
-
|
345
|
+
User32::GetWindowThreadProcessId(hwnd, pid_puffer)
|
300
346
|
pid = pid_puffer.unpack('L')[0]
|
301
347
|
Process.kill('KILL', pid) rescue nil
|
302
348
|
end
|
@@ -354,10 +400,50 @@ module RobustExcelOle
|
|
354
400
|
WIN32OLE.connect('winmgmts:\\\\.').InstancesOf('win32_process').select { |p| p.Name == 'EXCEL.EXE' }.size
|
355
401
|
end
|
356
402
|
|
357
|
-
def self.
|
403
|
+
def self.known_instances_count
|
358
404
|
@@hwnd2excel.size
|
359
405
|
end
|
360
406
|
|
407
|
+
# returns running Excel instances
|
408
|
+
# !!! This is work in progress
|
409
|
+
# the approach is currently restricted to visible Excel instances with at least one workbook
|
410
|
+
def self.running_excel_instances
|
411
|
+
win32ole_excel_instances = []
|
412
|
+
hwnd = 0
|
413
|
+
loop do
|
414
|
+
hwnd = User32::FindWindowExA(0, hwnd, "XLMAIN", nil).to_i
|
415
|
+
break if hwnd == 0
|
416
|
+
hwnd2 = User32::FindWindowExA(hwnd, 0, "XLDESK", nil).to_i
|
417
|
+
hwnd3 = User32::FindWindowExA(hwnd2, 0, "EXCEL7", nil).to_i
|
418
|
+
interface_address_buffer = ' ' * 8
|
419
|
+
guid = Oleacc::Guid.malloc
|
420
|
+
guid.data1 = 0x20400
|
421
|
+
guid.data2 = 0x0
|
422
|
+
guid.data3 = 0x0
|
423
|
+
guid.data4 = [0xc0,0x0,0x0,0x0,0x0,0x0,0x0,0x46]
|
424
|
+
status = Oleacc::AccessibleObjectFromWindow(hwnd3, 0xFFFFFFF0, guid, interface_address_buffer)
|
425
|
+
interface_address = nil
|
426
|
+
if status == 0
|
427
|
+
interface_address = interface_address_buffer.unpack('L')[0]
|
428
|
+
else
|
429
|
+
raise ExcelREOError, "could not determine the addresss of the specified interface of the Excel object"
|
430
|
+
end
|
431
|
+
accessed_object_buffer = ' ' * 8
|
432
|
+
# open issue: is there a dll containing QueryInterface?
|
433
|
+
status = Ole32::QueryInterface(interface_address, guid, accessed_object_buffer)
|
434
|
+
if status == 0
|
435
|
+
accessed_object = accessed_object_buffer.unpack('L')[0]
|
436
|
+
# open issue: a method, similar to create_win32ole in Win32ole creating a win32ole object
|
437
|
+
# we could use pr-win32ole (seems to be an old ruby gem, needing C to be installed)
|
438
|
+
ole_excel = create_win32ole(accessed_object)
|
439
|
+
win32ole_excel_instances << ole_excel.Application
|
440
|
+
else
|
441
|
+
raise ExcelREOError, "could not determine the Excel object from window"
|
442
|
+
end
|
443
|
+
end
|
444
|
+
win32ole_excel_instances.map{|w| w.to_reo}
|
445
|
+
end
|
446
|
+
|
361
447
|
# returns a running Excel instance opened with RobustExcelOle
|
362
448
|
def self.known_running_instance
|
363
449
|
self.known_running_instances.first
|
@@ -369,9 +455,8 @@ module RobustExcelOle
|
|
369
455
|
@@hwnd2excel.each do |hwnd,wr_excel|
|
370
456
|
next unless wr_excel.weakref_alive?
|
371
457
|
excel = wr_excel.__getobj__
|
372
|
-
process_id = Win32API.new('user32', 'GetWindowThreadProcessId', %w[I P], 'I')
|
373
458
|
pid_puffer = ' ' * 32
|
374
|
-
|
459
|
+
User32::GetWindowThreadProcessId(hwnd, pid_puffer)
|
375
460
|
pid = pid_puffer.unpack('L')[0]
|
376
461
|
pid2excel[pid] = excel
|
377
462
|
end
|
@@ -380,10 +465,10 @@ module RobustExcelOle
|
|
380
465
|
end
|
381
466
|
|
382
467
|
class << self
|
383
|
-
alias excels_number instance_count # :deprecated
|
384
|
-
alias known_excels_number
|
385
|
-
alias known_excel_instance known_running_instance # :deprecated
|
386
|
-
alias known_excel_instances known_running_instances # :deprecated
|
468
|
+
alias excels_number instance_count # :deprecated: #
|
469
|
+
alias known_excels_number known_instances_count # :deprecated: #
|
470
|
+
alias known_excel_instance known_running_instance # :deprecated: #
|
471
|
+
alias known_excel_instances known_running_instances # :deprecated: #
|
387
472
|
end
|
388
473
|
|
389
474
|
private
|
@@ -627,11 +712,8 @@ module RobustExcelOle
|
|
627
712
|
|
628
713
|
def focus
|
629
714
|
self.visible = true
|
630
|
-
|
631
|
-
|
632
|
-
# else
|
633
|
-
# Win32API.new("user32","SetForegroundWindow","","I").call
|
634
|
-
# end
|
715
|
+
status = User32::SetForegroundWindow(@ole_excel.Hwnd)
|
716
|
+
raise ExcelREOError, "could not set Excel window as foreground" if status == 0
|
635
717
|
end
|
636
718
|
|
637
719
|
# @private
|
@@ -224,18 +224,30 @@ module General
|
|
224
224
|
network = WIN32OLE.new('WScript.Network')
|
225
225
|
drives = network.enumnetworkdrives
|
226
226
|
count = drives.Count
|
227
|
-
(0..(count - 1)).step(2).map{ |i| NetworkDrive.new( drives.Item(i), drives.Item(i + 1).tr('\\','/')) }
|
227
|
+
# (0..(count - 1)).step(2).map{ |i| NetworkDrive.new( drives.Item(i), drives.Item(i + 1).tr('\\','/')) }
|
228
|
+
result = (0..(count - 1)).step(2).map { |i|
|
229
|
+
NetworkDrive.new( drives.Item(i), drives.Item(i + 1).tr('\\','/')) unless drives.Item(i).empty?
|
230
|
+
}.compact
|
231
|
+
result
|
228
232
|
end
|
229
233
|
end
|
230
234
|
|
231
235
|
# @private
|
232
236
|
def hostnameshare2networkpath(filename)
|
233
237
|
return filename unless filename[0,2] == "//"
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
238
|
+
hostname = filename[0,filename[3,filename.length].index('/')+3]
|
239
|
+
filename_wo_hostname = filename[hostname.length+1,filename.length]
|
240
|
+
abs_filename = absolute_path(filename_wo_hostname).tr('\\','/').tr('C:/','c$/')
|
241
|
+
adapted_filename = hostname + "/" + abs_filename
|
242
|
+
NetworkDrive.get_all_drives.each do |d|
|
243
|
+
new_filename = filename.sub(/#{(Regexp.escape(d.network_name))}/i,d.drive_letter)
|
244
|
+
return new_filename if new_filename != filename
|
245
|
+
new_filename = adapted_filename.sub(/#{(Regexp.escape(d.network_name))}/i,d.drive_letter)
|
246
|
+
return new_filename if new_filename != filename
|
247
|
+
end
|
248
|
+
filename
|
249
|
+
end
|
250
|
+
|
239
251
|
# @private
|
240
252
|
def absolute_path(file)
|
241
253
|
file = file.to_path if file.respond_to?(:to_path)
|
@@ -60,23 +60,6 @@ module RobustExcelOle
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
-
=begin
|
64
|
-
|
65
|
-
ole_table = @ole_table
|
66
|
-
|
67
|
-
@row_class = Class.new(ListRow) do
|
68
|
-
|
69
|
-
@@ole_table = ole_table
|
70
|
-
|
71
|
-
def ole_table
|
72
|
-
@@ole_table
|
73
|
-
end
|
74
|
-
|
75
|
-
end
|
76
|
-
|
77
|
-
end
|
78
|
-
|
79
|
-
=end
|
80
63
|
|
81
64
|
ole_table = @ole_table
|
82
65
|
|
@@ -141,13 +124,18 @@ module RobustExcelOle
|
|
141
124
|
|
142
125
|
private
|
143
126
|
|
144
|
-
|
127
|
+
def matching_via_traversing(key_hash, opts)
|
145
128
|
encode_utf8 = ->(val) {val.respond_to?(:gsub) ? val.encode('utf-8') : val}
|
146
129
|
cn2i = column_names_to_index
|
147
130
|
max_matching_num = opts[:limit] || 65536
|
148
131
|
matching_rows = @ole_table.ListRows.lazy.select { |listrow|
|
149
132
|
rowvalues = listrow.Range.Value.first
|
150
|
-
key_hash.all?{
|
133
|
+
key_hash.all?{|key,val|
|
134
|
+
rowvalue = encode_utf8.(rowvalues[cn2i[key]])
|
135
|
+
rowvalue == val ||
|
136
|
+
(val == "0" && rowvalue == 0) ||
|
137
|
+
(rowvalue.respond_to?(:abs) && val.to_i != 0 && rowvalue == val.to_i)
|
138
|
+
}
|
151
139
|
}.take(max_matching_num).to_a
|
152
140
|
rescue
|
153
141
|
raise(TableError, "cannot find row with key #{key_hash}")
|
@@ -386,6 +374,10 @@ module RobustExcelOle
|
|
386
374
|
self.Parent.to_reo == other_table.Parent.to_reo
|
387
375
|
end
|
388
376
|
|
377
|
+
# @private
|
378
|
+
def workbook
|
379
|
+
@workbook ||= ole_table.Parent.Parent.to_reo
|
380
|
+
end
|
389
381
|
|
390
382
|
# @private
|
391
383
|
# returns true, if the list object responds to VBA methods, false otherwise
|
@@ -27,6 +27,7 @@ module RobustExcelOle
|
|
27
27
|
# @param [Variant] column number or column name
|
28
28
|
# @return [Variant] value of the cell
|
29
29
|
def [] column_number_or_name
|
30
|
+
column_number_or_name = column_number_or_name.to_s if column_number_or_name.is_a?(Symbol)
|
30
31
|
ole_cell = ole_table.Application.Intersect(
|
31
32
|
@ole_tablerow.Range, ole_table.ListColumns.Item(column_number_or_name).Range)
|
32
33
|
value = ole_cell.Value
|
@@ -40,6 +41,7 @@ module RobustExcelOle
|
|
40
41
|
# @param [Variant] value of the cell
|
41
42
|
def []=(column_number_or_name, value)
|
42
43
|
begin
|
44
|
+
column_number_or_name = column_number_or_name.to_s if column_number_or_name.is_a?(Symbol)
|
43
45
|
ole_cell = ole_table.Application.Intersect(
|
44
46
|
@ole_tablerow.Range, ole_table.ListColumns.Item(column_number_or_name).Range)
|
45
47
|
ole_cell.Value = value
|
@@ -96,27 +98,68 @@ module RobustExcelOle
|
|
96
98
|
other_listrow.is_a?(ListRow) && other_listrow.values == self.values
|
97
99
|
end
|
98
100
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
c.replace_umlauts.underscore.gsub(/\W/,'_') == core_name
|
112
|
-
end
|
113
|
-
if column_name
|
114
|
-
define_and_call_method(column_name, name, *args)
|
115
|
-
else
|
116
|
-
super(name, *args)
|
101
|
+
# @private
|
102
|
+
def workbook
|
103
|
+
@workbook ||= workbook_class.new(ole_table.Parent.Parent)
|
104
|
+
end
|
105
|
+
|
106
|
+
# @private
|
107
|
+
def self.workbook_class
|
108
|
+
@workbook_class ||= begin
|
109
|
+
module_name = parent_name
|
110
|
+
"#{module_name}::Workbook".constantize
|
111
|
+
rescue NameError => e
|
112
|
+
Workbook
|
117
113
|
end
|
118
114
|
end
|
119
115
|
|
116
|
+
# @private
|
117
|
+
def workbook_class
|
118
|
+
self.class.workbook_class
|
119
|
+
end
|
120
|
+
|
121
|
+
# @private
|
122
|
+
def column_names
|
123
|
+
ole_table.HeaderRowRange.Value.first
|
124
|
+
end
|
125
|
+
|
126
|
+
# returns true, if the listrow reacts to methods, false otherwise
|
127
|
+
def alive?
|
128
|
+
@ole_tablerow.Parent
|
129
|
+
true
|
130
|
+
rescue
|
131
|
+
@ole_tablerow = nil # dead object won't be alive again
|
132
|
+
false
|
133
|
+
end
|
134
|
+
|
135
|
+
private
|
136
|
+
|
137
|
+
def valid_similar_names meth_name
|
138
|
+
[
|
139
|
+
meth_name,
|
140
|
+
meth_name.gsub(/\W/,'_'),
|
141
|
+
meth_name.underscore,
|
142
|
+
meth_name.underscore.gsub(/\W/,'_'),
|
143
|
+
meth_name.replace_umlauts.gsub(/\W/,'_'),
|
144
|
+
meth_name.replace_umlauts.underscore.gsub(/\W/,'_')
|
145
|
+
].uniq
|
146
|
+
end
|
147
|
+
|
148
|
+
public
|
149
|
+
|
150
|
+
# @private
|
151
|
+
def methods
|
152
|
+
@methods ||= begin
|
153
|
+
arr = column_names.map{ |c| valid_similar_names(c) }.flatten
|
154
|
+
(arr + arr.map{|m| m + '='}).map(&:to_sym) + super
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# @private
|
159
|
+
def respond_to?(meth_name)
|
160
|
+
methods.include?(meth_name.to_sym)
|
161
|
+
end
|
162
|
+
|
120
163
|
# @private
|
121
164
|
def to_s
|
122
165
|
inspect
|
@@ -129,7 +172,19 @@ module RobustExcelOle
|
|
129
172
|
|
130
173
|
private
|
131
174
|
|
132
|
-
def
|
175
|
+
def method_missing(meth_name, *args)
|
176
|
+
# this should not happen:
|
177
|
+
raise(TableRowError, "internal error: ole_table not defined") unless self.class.method_defined?(:ole_table)
|
178
|
+
if respond_to?(meth_name)
|
179
|
+
core_name = meth_name.to_s.chomp('=')
|
180
|
+
column_name = column_names.find{ |c| valid_similar_names(c).include?(core_name) }
|
181
|
+
define_and_call_method(column_name, meth_name, *args) if column_name
|
182
|
+
else
|
183
|
+
super(meth_name, *args)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def define_and_call_method(column_name, method_name, *args)
|
133
188
|
#column_name = column_name.force_encoding('cp850')
|
134
189
|
ole_cell = ole_table.Application.Intersect(
|
135
190
|
@ole_tablerow.Range, ole_table.ListColumns.Item(column_name).Range)
|
@@ -223,6 +223,11 @@ module RobustExcelOle
|
|
223
223
|
@worksheet.workbook.excel
|
224
224
|
end
|
225
225
|
|
226
|
+
# @private
|
227
|
+
def workbook
|
228
|
+
@workbook ||= @worksheet.workbook
|
229
|
+
end
|
230
|
+
|
226
231
|
# @private
|
227
232
|
# returns true, if the Range object responds to VBA methods, false otherwise
|
228
233
|
def alive?
|
@@ -231,7 +236,7 @@ module RobustExcelOle
|
|
231
236
|
rescue
|
232
237
|
# trace $!.message
|
233
238
|
false
|
234
|
-
end
|
239
|
+
end
|
235
240
|
|
236
241
|
# @private
|
237
242
|
def to_s
|
@@ -15,22 +15,25 @@ module RobustExcelOle
|
|
15
15
|
# @option opts [Symbol] :default the default value that is provided if no contents could be returned
|
16
16
|
# @return [Variant] the contents of a range with given name
|
17
17
|
def namevalue_global(name, opts = { default: :__not_provided })
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
ole_range = name_obj.RefersToRange
|
24
|
-
worksheet = self if self.is_a?(Worksheet)
|
25
|
-
value = begin
|
26
|
-
if !::RANGES_JRUBY_BUG
|
27
|
-
ole_range.Value
|
28
|
-
else
|
29
|
-
values = RobustExcelOle::Range.new(ole_range, worksheet).v
|
30
|
-
(values.size==1 && values.first.size==1) ? values.first.first : values
|
18
|
+
begin
|
19
|
+
name_obj = begin
|
20
|
+
get_name_object(name)
|
21
|
+
rescue NameNotFound
|
22
|
+
raise
|
31
23
|
end
|
32
|
-
|
24
|
+
ole_range = name_obj.RefersToRange
|
25
|
+
worksheet = self if self.is_a?(Worksheet)
|
26
|
+
value = begin
|
27
|
+
if !::RANGES_JRUBY_BUG
|
28
|
+
ole_range.Value
|
29
|
+
else
|
30
|
+
values = RobustExcelOle::Range.new(ole_range, worksheet).v
|
31
|
+
(values.size==1 && values.first.size==1) ? values.first.first : values
|
32
|
+
end
|
33
|
+
end
|
34
|
+
rescue # WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException
|
33
35
|
sheet = if self.is_a?(Worksheet) then self
|
36
|
+
# chooses simply the 1st worksheet?
|
34
37
|
elsif self.is_a?(Workbook) then self.sheet(1)
|
35
38
|
end
|
36
39
|
begin
|
@@ -42,16 +45,20 @@ module RobustExcelOle
|
|
42
45
|
values = RobustExcelOle::Range.new(ole_range, worksheet).v
|
43
46
|
(values.size==1 && values.first.size==1) ? values.first.first : values
|
44
47
|
end
|
45
|
-
rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException
|
48
|
+
rescue # WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException
|
46
49
|
return opts[:default] unless opts[:default] == :__not_provided
|
47
|
-
|
50
|
+
if name_obj.nil?
|
51
|
+
raise NameNotFound, "cannot find name #{name.inspect}"
|
52
|
+
else
|
53
|
+
raise RangeNotEvaluatable, "cannot evaluate range named #{name.inspect}"
|
54
|
+
end
|
48
55
|
end
|
49
56
|
end
|
50
57
|
if value == -2146828288 + RobustExcelOle::XlErrName
|
51
58
|
return opts[:default] unless opts[:default] == :__not_provided
|
52
59
|
raise RangeNotEvaluatable, "cannot evaluate range named #{name.inspect} in #{File.basename(workbook.stored_filename).inspect rescue nil}"
|
53
60
|
end
|
54
|
-
return opts[:default]
|
61
|
+
return opts[:default] if opts[:default] != :__not_provided && !value.nil?
|
55
62
|
value
|
56
63
|
end
|
57
64
|
|