robust_excel_ole 0.6 → 0.6.1
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/Changelog +12 -0
- data/README.rdoc +5 -3
- data/README_detail.rdoc +1 -1
- data/examples/edit_sheets/example_adding_sheets.rb +1 -1
- data/examples/edit_sheets/example_expanding.rb +1 -1
- data/examples/open_save_close/example_control_to_excel.rb +2 -2
- data/examples/open_save_close/example_if_obstructed_closeifsaved.rb +1 -1
- data/examples/open_save_close/example_if_obstructed_forget.rb +1 -1
- data/examples/open_save_close/example_if_unsaved_accept.rb +2 -2
- data/examples/open_save_close/example_read_only.rb +1 -1
- data/examples/open_save_close/example_simple.rb +1 -1
- data/lib/robust_excel_ole/book.rb +89 -111
- data/lib/robust_excel_ole/excel.rb +49 -50
- data/lib/robust_excel_ole/general.rb +3 -3
- data/lib/robust_excel_ole/reo_common.rb +78 -1
- data/lib/robust_excel_ole/sheet.rb +16 -23
- data/lib/robust_excel_ole/version.rb +1 -1
- data/spec/book_spec.rb +7 -7
- data/spec/book_specs/book_close_spec.rb +24 -5
- data/spec/book_specs/book_misc_spec.rb +16 -7
- data/spec/book_specs/book_open_spec.rb +15 -20
- data/spec/book_specs/book_save_spec.rb +21 -21
- data/spec/book_specs/book_sheet_spec.rb +3 -3
- data/spec/book_specs/book_unobtr_spec.rb +1 -1
- data/spec/data/book_with_blank.xls +0 -0
- data/spec/data/different_workbook.xls +0 -0
- data/spec/data/refed_wb.xls +0 -0
- data/spec/data/reference_workbook.xls +0 -0
- data/spec/data/referencing_wb.xls +0 -0
- data/spec/data/workbook.xls +0 -0
- data/spec/excel_spec.rb +87 -125
- data/spec/general_spec.rb +2 -2
- data/spec/reo_common_spec.rb +1 -1
- data/spec/sheet_spec.rb +13 -17
- metadata +7 -3
@@ -58,26 +58,24 @@ module RobustExcelOle
|
|
58
58
|
ole_xl = current_excel
|
59
59
|
end
|
60
60
|
end
|
61
|
-
|
62
|
-
|
63
|
-
ole_xl = WIN32OLE.new('Excel.Application')
|
64
|
-
options = {
|
65
|
-
:displayalerts => :if_visible,
|
66
|
-
:visible => false,
|
67
|
-
}.merge(options)
|
68
|
-
end
|
61
|
+
ole_xl = WIN32OLE.new('Excel.Application') unless ole_xl
|
62
|
+
|
69
63
|
hwnd = ole_xl.HWnd
|
70
64
|
stored = hwnd2excel(hwnd)
|
71
65
|
if stored
|
72
66
|
result = stored
|
73
|
-
else
|
67
|
+
else
|
74
68
|
result = super(options)
|
75
69
|
result.instance_variable_set(:@ole_excel, ole_xl)
|
76
70
|
WIN32OLE.const_load(ole_xl, RobustExcelOle) unless RobustExcelOle.const_defined?(:CONSTANTS)
|
77
71
|
@@hwnd2excel[hwnd] = WeakRef.new(result)
|
78
72
|
end
|
73
|
+
|
79
74
|
unless options.is_a? WIN32OLE
|
80
75
|
reused = options[:reuse] && (not stored.nil?)
|
76
|
+
options = { :displayalerts => :if_visible, :visible => false}.merge(options) unless reused
|
77
|
+
result.visible = result.Visible
|
78
|
+
result.DisplayAlerts = result.DisplayAlerts
|
81
79
|
visible_value = (reused && options[:visible].nil?) ? result.visible : options[:visible]
|
82
80
|
displayalerts_value = (reused && options[:displayalerts].nil?) ? result.displayalerts : options[:displayalerts]
|
83
81
|
ole_xl.Visible = visible_value
|
@@ -157,7 +155,7 @@ module RobustExcelOle
|
|
157
155
|
close_excel(options) if managed_unsaved_workbooks(options)
|
158
156
|
end
|
159
157
|
|
160
|
-
# closes
|
158
|
+
# closes Excel instances opened via RobustExcelOle
|
161
159
|
# @param [Hash] options the options
|
162
160
|
# @option options [Symbol] :if_unsaved :raise, :save, :forget, or :alert
|
163
161
|
# @option options [Boolean] :hard
|
@@ -170,8 +168,6 @@ module RobustExcelOle
|
|
170
168
|
# :alert -> give control to Excel
|
171
169
|
# :hard closes Excel instances soft (default: false), or, additionally kills the Excel processes hard (true)
|
172
170
|
# :kill_if_timeout: kills Excel instances hard if the closing process exceeds a certain time limit (default: false)
|
173
|
-
# @raise ExcelError if time limit has exceeded, some Excel instance cannot be closed, or
|
174
|
-
# unsaved workbooks exist and option :if_unsaved is :raise
|
175
171
|
def self.close_all(options={})
|
176
172
|
options = {
|
177
173
|
:if_unsaved => :raise,
|
@@ -181,18 +177,25 @@ module RobustExcelOle
|
|
181
177
|
timeout = false
|
182
178
|
number = excels_number
|
183
179
|
begin
|
184
|
-
status = Timeout::timeout(
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
(Excel.new(ole_xl).close(options); Excel.new(ole_xl).close(options)) if ole_xl # two times necessary ?!
|
189
|
-
rescue RuntimeError => msg
|
190
|
-
raise msg unless msg.message =~ /failed to get Dispatch Interface/
|
191
|
-
end
|
180
|
+
status = Timeout::timeout(60) {
|
181
|
+
@@hwnd2excel.each do |hwnd, wr_excel|
|
182
|
+
excel = wr_excel.__getobj__
|
183
|
+
excel.close(options)
|
192
184
|
end
|
185
|
+
sleep 0.2
|
186
|
+
free_all_ole_objects if excels_number > 0
|
187
|
+
# close also interactively opened Excels, but for unsaved workbooks: hangs as soon sending a VBA method
|
188
|
+
#while (n = excels_number) > 0 do
|
189
|
+
# ole_xl = current_excel
|
190
|
+
# begin
|
191
|
+
# Excel.new(ole_xl).close(options) if ole_xl
|
192
|
+
# rescue RuntimeError => msg
|
193
|
+
# raise msg unless msg.message =~ /failed to get Dispatch Interface/
|
194
|
+
# end
|
195
|
+
#end
|
193
196
|
}
|
194
197
|
rescue Timeout::Error
|
195
|
-
raise
|
198
|
+
raise TimeOut, "close_all: timeout" unless options[:kill_if_timeout]
|
196
199
|
timeout = true
|
197
200
|
end
|
198
201
|
kill_all if options[:hard] || (timeout && options[:kill_if_timeout])
|
@@ -203,13 +206,9 @@ module RobustExcelOle
|
|
203
206
|
def close_excel(options) # :nodoc:
|
204
207
|
ole_xl = @ole_excel
|
205
208
|
begin
|
206
|
-
|
207
|
-
with_displayalerts(true) {ole_xl.Workbooks.Close}
|
208
|
-
else
|
209
|
-
ole_xl.Workbooks.Close
|
210
|
-
end
|
209
|
+
with_displayalerts(options[:if_unsaved] == :alert) { ole_xl.Workbooks.Close }
|
211
210
|
rescue WIN32OLERuntimeError => msg
|
212
|
-
|
211
|
+
trace "close: canceled by user" if msg.message =~ /80020009/ &&
|
213
212
|
options[:if_unsaved] == :alert && (not unsaved_workbooks.empty?)
|
214
213
|
end
|
215
214
|
excel_hwnd = ole_xl.HWnd
|
@@ -245,12 +244,12 @@ module RobustExcelOle
|
|
245
244
|
@ole_excel.Workbooks.each {|w| unsaved_workbooks << w unless (w.Saved || w.ReadOnly)}
|
246
245
|
rescue RuntimeError => msg
|
247
246
|
trace "RuntimeError: #{msg.message}"
|
248
|
-
raise
|
247
|
+
raise ExcelDamaged, "Excel instance not alive or damaged" if msg.message =~ /failed to get Dispatch Interface/
|
249
248
|
end
|
250
249
|
unless unsaved_workbooks.empty?
|
251
250
|
case options[:if_unsaved]
|
252
251
|
when :raise
|
253
|
-
raise
|
252
|
+
raise UnsavedWorkbooks, "Excel contains unsaved workbooks"
|
254
253
|
when :save
|
255
254
|
unsaved_workbooks.each do |workbook|
|
256
255
|
workbook.Save
|
@@ -263,7 +262,7 @@ module RobustExcelOle
|
|
263
262
|
when :keep_open
|
264
263
|
return false
|
265
264
|
else
|
266
|
-
raise
|
265
|
+
raise OptionInvalid, ":if_unsaved: invalid option: #{options[:if_unsaved].inspect}"
|
267
266
|
end
|
268
267
|
end
|
269
268
|
return true
|
@@ -318,7 +317,6 @@ module RobustExcelOle
|
|
318
317
|
WIN32OLE.connect("winmgmts:\\\\.").InstancesOf("win32_process").select{|p| (p.name == "EXCEL.EXE")}.size
|
319
318
|
end
|
320
319
|
|
321
|
-
=begin
|
322
320
|
# provide Excel objects
|
323
321
|
# (so far restricted to all Excel instances opened with RobustExcelOle,
|
324
322
|
# not for Excel instances opened by the user)
|
@@ -347,7 +345,6 @@ module RobustExcelOle
|
|
347
345
|
end
|
348
346
|
result
|
349
347
|
end
|
350
|
-
=end
|
351
348
|
|
352
349
|
def excel # :nodoc: #
|
353
350
|
self
|
@@ -413,7 +410,7 @@ module RobustExcelOle
|
|
413
410
|
self.Workbooks.each {|w| result << w unless (w.Saved || w.ReadOnly)}
|
414
411
|
rescue RuntimeError => msg
|
415
412
|
trace "RuntimeError: #{msg.message}"
|
416
|
-
raise
|
413
|
+
raise ExcelDamaged, "Excel instance not alive or damaged" if msg.message =~ /failed to get Dispatch Interface/
|
417
414
|
end
|
418
415
|
result
|
419
416
|
end
|
@@ -432,10 +429,10 @@ module RobustExcelOle
|
|
432
429
|
empty_workbook.SaveAs(filename)
|
433
430
|
rescue WIN32OLERuntimeError => msg
|
434
431
|
if msg.message =~ /SaveAs/ and msg.message =~ /Workbook/ then
|
435
|
-
raise
|
432
|
+
raise WIN32OLERuntimeError, "could not save workbook with filename #{file_name.inspect}"
|
436
433
|
else
|
437
434
|
# todo some time: find out when this occurs :
|
438
|
-
raise
|
435
|
+
raise UnexpectedError, "unknown WIN32OELERuntimeError with filename #{file_name.inspect}: \n#{msg.message}"
|
439
436
|
end
|
440
437
|
end
|
441
438
|
end
|
@@ -474,10 +471,16 @@ module RobustExcelOle
|
|
474
471
|
end
|
475
472
|
rescue RuntimeError => msg
|
476
473
|
trace "RuntimeError: #{msg.message}"
|
477
|
-
raise
|
474
|
+
raise ExcelDamaged, "Excel instance not alive or damaged" if msg.message =~ /failed to get Dispatch Interface/
|
478
475
|
end
|
479
476
|
end
|
480
477
|
|
478
|
+
|
479
|
+
def foremost_window
|
480
|
+
self.visible = true
|
481
|
+
#Win32API.new("user32","SetForegroundWindow","I","I").call(@ole_excel.Hwnd)
|
482
|
+
end
|
483
|
+
|
481
484
|
# sets calculation mode in a block
|
482
485
|
def with_calculation(calculation_mode = :automatic)
|
483
486
|
if @ole_excel.Workbooks.Count > 0
|
@@ -522,13 +525,12 @@ module RobustExcelOle
|
|
522
525
|
# @param [String] name the range name
|
523
526
|
# @param [Hash] opts the options
|
524
527
|
# @option opts [Variant] :default default value (default: nil)
|
525
|
-
# @raise ExcelError if name is not defined or if value of the range cannot be evaluated
|
526
528
|
def nameval(name, opts = {:default => nil})
|
527
529
|
begin
|
528
530
|
name_obj = self.Names.Item(name)
|
529
531
|
rescue WIN32OLERuntimeError
|
530
532
|
return opts[:default] if opts[:default]
|
531
|
-
raise
|
533
|
+
raise NameNotFound, "cannot find name #{name.inspect}"
|
532
534
|
end
|
533
535
|
begin
|
534
536
|
value = name_obj.RefersToRange.Value
|
@@ -537,12 +539,12 @@ module RobustExcelOle
|
|
537
539
|
value = self.Evaluate(name_obj.Name)
|
538
540
|
rescue WIN32OLERuntimeError
|
539
541
|
return opts[:default] if opts[:default]
|
540
|
-
raise
|
542
|
+
raise RangeNotEvaluatable, "cannot evaluate range named #{name.inspect}"
|
541
543
|
end
|
542
544
|
end
|
543
545
|
if value == -2146826259
|
544
546
|
return opts[:default] if opts[:default]
|
545
|
-
raise
|
547
|
+
raise RangeNotEvaluatable, "cannot evaluate range named #{name.inspect}"
|
546
548
|
end
|
547
549
|
return opts[:default] if (value.nil? && opts[:default])
|
548
550
|
value
|
@@ -551,17 +553,16 @@ module RobustExcelOle
|
|
551
553
|
# assigns a value to a range with given name
|
552
554
|
# @param [String] name the range name
|
553
555
|
# @param [Variant] value the assigned value
|
554
|
-
# @raise ExcelError if name is not in the sheet or the value cannot be assigned
|
555
556
|
def set_nameval(name,value)
|
556
557
|
begin
|
557
558
|
name_obj = self.Names.Item(name)
|
558
559
|
rescue WIN32OLERuntimeError
|
559
|
-
raise
|
560
|
+
raise NameNotFound, "cannot find name #{name.inspect}"
|
560
561
|
end
|
561
562
|
begin
|
562
563
|
name_obj.RefersToRange.Value = value
|
563
564
|
rescue WIN32OLERuntimeError
|
564
|
-
raise
|
565
|
+
raise RangeNotEvaluatable, "cannot assign value to range named #{name.inspect}"
|
565
566
|
end
|
566
567
|
end
|
567
568
|
|
@@ -571,20 +572,19 @@ module RobustExcelOle
|
|
571
572
|
# @param [String] name the range name
|
572
573
|
# @param [Hash] opts the options
|
573
574
|
# @option opts [Symbol] :default the default value that is provided if no contents could be returned
|
574
|
-
# @raise ExcelError if range name is not definied in the worksheet or if range value could not be evaluated
|
575
575
|
# @return [Variant] the contents of a range with given name
|
576
576
|
def rangeval(name, opts = {:default => nil})
|
577
577
|
begin
|
578
578
|
range = self.Range(name)
|
579
579
|
rescue WIN32OLERuntimeError
|
580
580
|
return opts[:default] if opts[:default]
|
581
|
-
raise
|
581
|
+
raise NameNotFound, "cannot find name #{name.inspect}"
|
582
582
|
end
|
583
583
|
begin
|
584
584
|
value = range.Value
|
585
585
|
rescue WIN32OLERuntimeError
|
586
586
|
return opts[:default] if opts[:default]
|
587
|
-
raise
|
587
|
+
raise RangeNotEvaluatable, "cannot determine value of range named #{name.inspect}"
|
588
588
|
end
|
589
589
|
return opts[:default] if (value.nil? && opts[:default])
|
590
590
|
value
|
@@ -593,17 +593,16 @@ module RobustExcelOle
|
|
593
593
|
# assigns a value to a range given a defined loval name
|
594
594
|
# @param [String] name the range name
|
595
595
|
# @param [Variant] value the assigned value
|
596
|
-
# @raise ExcelError if name is not in the sheet or the value cannot be assigned
|
597
596
|
def set_rangeval(name,value)
|
598
597
|
begin
|
599
598
|
range = self.Range(name)
|
600
599
|
rescue WIN32OLERuntimeError
|
601
|
-
raise
|
600
|
+
raise NameNotFound, "cannot find name #{name.inspect}"
|
602
601
|
end
|
603
602
|
begin
|
604
603
|
range.Value = value
|
605
604
|
rescue WIN32OLERuntimeError
|
606
|
-
raise
|
605
|
+
raise RangeNotEvaluatable, "cannot assign value to range named #{name.inspect} in #{self.name}"
|
607
606
|
end
|
608
607
|
end
|
609
608
|
|
@@ -635,7 +634,7 @@ module RobustExcelOle
|
|
635
634
|
def method_missing(name, *args) # :nodoc: #
|
636
635
|
if name.to_s[0,1] =~ /[A-Z]/
|
637
636
|
begin
|
638
|
-
raise
|
637
|
+
raise ObjectNotAlive, "method missing: Excel not alive" unless alive?
|
639
638
|
@ole_excel.send(name, *args)
|
640
639
|
rescue WIN32OLERuntimeError => msg
|
641
640
|
if msg.message =~ /unknown property or method/
|
@@ -9,7 +9,7 @@ module General
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def canonize(filename) # :nodoc: #
|
12
|
-
raise
|
12
|
+
raise TypeErrorREO, "No string given to canonize, but #{filename.inspect}" unless filename.is_a?(String)
|
13
13
|
normalize(filename).downcase
|
14
14
|
end
|
15
15
|
|
@@ -42,7 +42,7 @@ class ::String # :nodoc: #
|
|
42
42
|
begin
|
43
43
|
File.join self, path_part
|
44
44
|
rescue TypeError
|
45
|
-
raise "Only strings can be parts of paths (given: #{path_part.inspect} of class #{path_part.class})"
|
45
|
+
raise TypeError, "Only strings can be parts of paths (given: #{path_part.inspect} of class #{path_part.class})"
|
46
46
|
end
|
47
47
|
end
|
48
48
|
end
|
@@ -108,7 +108,7 @@ end
|
|
108
108
|
module MethodHelpers
|
109
109
|
|
110
110
|
def respond_to?(meth_name, include_private = false) # :nodoc: #
|
111
|
-
raise
|
111
|
+
raise ObjectNotAlive, "respond_to?: #{self.class.name} not alive" unless alive?
|
112
112
|
super
|
113
113
|
end
|
114
114
|
|
@@ -7,7 +7,7 @@ File.delete REO_LOG_FILE rescue nil
|
|
7
7
|
class REOCommon
|
8
8
|
|
9
9
|
def excel
|
10
|
-
raise
|
10
|
+
raise TypeErrorREO, "receiver instance is neither an Excel nor a Book"
|
11
11
|
end
|
12
12
|
|
13
13
|
def own_methods
|
@@ -39,3 +39,80 @@ class REOCommon
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
end
|
42
|
+
|
43
|
+
module RobustExcelOle
|
44
|
+
|
45
|
+
class REOError < RuntimeError # :nodoc: #
|
46
|
+
end
|
47
|
+
|
48
|
+
class ExcelError < REOError # :nodoc: #
|
49
|
+
end
|
50
|
+
|
51
|
+
class WorkbookError < REOError # :nodoc: #
|
52
|
+
end
|
53
|
+
|
54
|
+
class FileError < REOError # :nodoc: #
|
55
|
+
end
|
56
|
+
|
57
|
+
class NamesError < REOError # :nodoc: #
|
58
|
+
end
|
59
|
+
|
60
|
+
class MiscError < REOError # :nodoc: #
|
61
|
+
end
|
62
|
+
|
63
|
+
class ExcelDamaged < ExcelError # :nodoc: #
|
64
|
+
end
|
65
|
+
|
66
|
+
class ExcelWeakRef < ExcelError # :nodoc: #
|
67
|
+
end
|
68
|
+
|
69
|
+
class UnsavedWorkbooks < ExcelError # :nodoc: #
|
70
|
+
end
|
71
|
+
|
72
|
+
class WorkbookBlocked < WorkbookError # :nodoc: #
|
73
|
+
end
|
74
|
+
|
75
|
+
class WorkbookNotSaved < WorkbookError # :nodoc: #
|
76
|
+
end
|
77
|
+
|
78
|
+
class WorkbookReadOnly < WorkbookError # :nodoc: #
|
79
|
+
end
|
80
|
+
|
81
|
+
class WorkbookBeingUsed < WorkbookError # :nodoc: #
|
82
|
+
end
|
83
|
+
|
84
|
+
class FileNotFound < FileError # :nodoc: #
|
85
|
+
end
|
86
|
+
|
87
|
+
class FileNameNotGiven < FileError # :nodoc: #
|
88
|
+
end
|
89
|
+
|
90
|
+
class FileAlreadyExists < FileError # :nodoc: #
|
91
|
+
end
|
92
|
+
|
93
|
+
class NameNotFound < NamesError # :nodoc: #
|
94
|
+
end
|
95
|
+
|
96
|
+
class NameAlreadyExists < NamesError # :nodoc: #
|
97
|
+
end
|
98
|
+
|
99
|
+
class RangeNotEvaluatable < MiscError # :nodoc: #
|
100
|
+
end
|
101
|
+
|
102
|
+
class OptionInvalid < MiscError # :nodoc: #
|
103
|
+
end
|
104
|
+
|
105
|
+
class ObjectNotAlive < MiscError # :nodoc: #
|
106
|
+
end
|
107
|
+
|
108
|
+
class TypeErrorREO < REOError # :nodoc: #
|
109
|
+
end
|
110
|
+
|
111
|
+
class TimeOut < REOError # :nodoc: #
|
112
|
+
end
|
113
|
+
|
114
|
+
class UnexpectedError < REOError # :nodoc: #
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
@@ -34,10 +34,10 @@ module RobustExcelOle
|
|
34
34
|
@worksheet.Name = new_name
|
35
35
|
rescue WIN32OLERuntimeError => msg
|
36
36
|
if msg.message =~ /800A03EC/
|
37
|
-
raise
|
37
|
+
raise NameAlreadyExists, "sheet name #{new_name.inspect} already exists"
|
38
38
|
else
|
39
39
|
trace "#{msg.message}"
|
40
|
-
raise
|
40
|
+
raise UnexpectedError
|
41
41
|
end
|
42
42
|
end
|
43
43
|
end
|
@@ -54,10 +54,10 @@ module RobustExcelOle
|
|
54
54
|
name = p1
|
55
55
|
begin
|
56
56
|
nameval(name)
|
57
|
-
rescue
|
57
|
+
rescue REOError
|
58
58
|
begin
|
59
59
|
book_class.new(self.Parent).nameval(name)
|
60
|
-
rescue
|
60
|
+
rescue REOError
|
61
61
|
rangeval(name)
|
62
62
|
end
|
63
63
|
end
|
@@ -74,10 +74,10 @@ module RobustExcelOle
|
|
74
74
|
name, value = p1, p2
|
75
75
|
begin
|
76
76
|
set_nameval(name, value)
|
77
|
-
rescue
|
77
|
+
rescue REOError
|
78
78
|
begin
|
79
79
|
workbook.set_nameval(name, value)
|
80
|
-
rescue
|
80
|
+
rescue REOError
|
81
81
|
set_rangeval(name, value)
|
82
82
|
end
|
83
83
|
end
|
@@ -136,13 +136,12 @@ module RobustExcelOle
|
|
136
136
|
# @param [String] name the name of a range
|
137
137
|
# @param [Hash] opts the options
|
138
138
|
# @option opts [Variant] :default default value (default: nil)
|
139
|
-
# @raise SheetError if name is not defined or if value of the range cannot be evaluated
|
140
139
|
def nameval(name, opts = {:default => nil})
|
141
140
|
begin
|
142
141
|
name_obj = self.Names.Item(name)
|
143
142
|
rescue WIN32OLERuntimeError
|
144
143
|
return opts[:default] if opts[:default]
|
145
|
-
raise
|
144
|
+
raise NameNotFound, "name #{name.inspect} not in #{self.Name}"
|
146
145
|
end
|
147
146
|
begin
|
148
147
|
value = name_obj.RefersToRange.Value
|
@@ -151,12 +150,12 @@ module RobustExcelOle
|
|
151
150
|
value = self.Evaluate(name_obj.Name)
|
152
151
|
rescue WIN32OLERuntimeError
|
153
152
|
return opts[:default] if opts[:default]
|
154
|
-
raise
|
153
|
+
raise RangeNotEvaluatable, "cannot evaluate range named #{name.inspect} in #{self.Name}"
|
155
154
|
end
|
156
155
|
end
|
157
156
|
if value == RobustExcelOle::XlErrName # -2146826259
|
158
157
|
return opts[:default] if opts[:default]
|
159
|
-
raise
|
158
|
+
raise RangeNotEvaluatable, "cannot evaluate range named #{name.inspect} in #{self.Name}"
|
160
159
|
end
|
161
160
|
return opts[:default] if (value.nil? && opts[:default])
|
162
161
|
value
|
@@ -165,17 +164,16 @@ module RobustExcelOle
|
|
165
164
|
# assigns a value to a range
|
166
165
|
# @param [String] name the name of a range
|
167
166
|
# @param [Variant] value the assigned value
|
168
|
-
# @raise SheetError if name is not in the sheet or the value cannot be assigned
|
169
167
|
def set_nameval(name,value)
|
170
168
|
begin
|
171
169
|
name_obj = self.Names.Item(name)
|
172
170
|
rescue WIN32OLERuntimeError
|
173
|
-
raise
|
171
|
+
raise NameNotFound, "name #{name.inspect} not in #{self.name}"
|
174
172
|
end
|
175
173
|
begin
|
176
174
|
name_obj.RefersToRange.Value = value
|
177
175
|
rescue WIN32OLERuntimeError
|
178
|
-
raise
|
176
|
+
raise RangeNotEvaluatable, "cannot assign value to range named #{name.inspect} in #{self.name}"
|
179
177
|
end
|
180
178
|
end
|
181
179
|
|
@@ -185,20 +183,19 @@ module RobustExcelOle
|
|
185
183
|
# @param [String] name the name of a range
|
186
184
|
# @param [Hash] opts the options
|
187
185
|
# @option opts [Symbol] :default the default value that is provided if no contents could be returned
|
188
|
-
# @raise SheetError if range name is not definied in the worksheet or if range value could not be evaluated
|
189
186
|
# @return [Variant] the contents of a range with given name
|
190
187
|
def rangeval(name, opts = {:default => nil})
|
191
188
|
begin
|
192
189
|
range = self.Range(name)
|
193
190
|
rescue WIN32OLERuntimeError
|
194
191
|
return opts[:default] if opts[:default]
|
195
|
-
raise
|
192
|
+
raise NameNotFound, "name #{name.inspect} not in #{self.name}"
|
196
193
|
end
|
197
194
|
begin
|
198
195
|
value = range.Value
|
199
196
|
rescue WIN32OLERuntimeError
|
200
197
|
return opts[:default] if opts[:default]
|
201
|
-
raise
|
198
|
+
raise RangeNotEvaluatable, "cannot determine value of range named #{name.inspect} in #{self.name}"
|
202
199
|
end
|
203
200
|
return opts[:default] if (value.nil? && opts[:default])
|
204
201
|
value
|
@@ -207,17 +204,16 @@ module RobustExcelOle
|
|
207
204
|
# assigns a value to a range given a defined local name
|
208
205
|
# @param [String] name the name of a range
|
209
206
|
# @param [Variant] value the assigned value
|
210
|
-
# @raise SheetError if name is not in the sheet or the value cannot be assigned
|
211
207
|
def set_rangeval(name,value)
|
212
208
|
begin
|
213
209
|
range = self.Range(name)
|
214
210
|
rescue WIN32OLERuntimeError
|
215
|
-
raise
|
211
|
+
raise NameNotFound, "name #{name.inspect} not in #{self.name}"
|
216
212
|
end
|
217
213
|
begin
|
218
214
|
range.Value = value
|
219
215
|
rescue WIN32OLERuntimeError
|
220
|
-
raise
|
216
|
+
raise RangeNotEvaluatable, "cannot assign value to range named #{name.inspect} in #{self.name}"
|
221
217
|
end
|
222
218
|
end
|
223
219
|
|
@@ -236,7 +232,7 @@ module RobustExcelOle
|
|
236
232
|
end
|
237
233
|
rescue WIN32OLERuntimeError => msg
|
238
234
|
trace "WIN32OLERuntimeError: #{msg.message}"
|
239
|
-
raise
|
235
|
+
raise RangeNotEvaluatable, "cannot add name #{name.inspect} to cell with row #{row.inspect} and column #{column.inspect}"
|
240
236
|
end
|
241
237
|
end
|
242
238
|
|
@@ -297,7 +293,4 @@ module RobustExcelOle
|
|
297
293
|
|
298
294
|
public
|
299
295
|
|
300
|
-
class SheetError < RuntimeError # :nodoc: #
|
301
|
-
end
|
302
|
-
|
303
296
|
end
|
data/spec/book_spec.rb
CHANGED
@@ -277,7 +277,7 @@ describe Book do
|
|
277
277
|
it "should raise an error, if :if_unsaved is :raise" do
|
278
278
|
expect {
|
279
279
|
@new_book = Book.open(@simple_file, :if_unsaved => :raise)
|
280
|
-
}.to raise_error(
|
280
|
+
}.to raise_error(WorkbookNotSaved, /workbook is already open but not saved: "workbook.xls"/)
|
281
281
|
end
|
282
282
|
|
283
283
|
it "should let the book open, if :if_unsaved is :accept" do
|
@@ -316,7 +316,7 @@ describe Book do
|
|
316
316
|
@key_sender.puts "{right}{enter}"
|
317
317
|
expect{
|
318
318
|
Book.open(@simple_file, :if_unsaved => :alert)
|
319
|
-
}.to raise_error(
|
319
|
+
}.to raise_error(WorkbookError, "open: user canceled or open error")
|
320
320
|
@book.should be_alive
|
321
321
|
end
|
322
322
|
|
@@ -338,7 +338,7 @@ describe Book do
|
|
338
338
|
@key_sender.puts "{right}{enter}"
|
339
339
|
expect{
|
340
340
|
Book.open(@simple_file, :if_unsaved => :excel)
|
341
|
-
}.to raise_error(
|
341
|
+
}.to raise_error(WorkbookError, "open: user canceled or open error")
|
342
342
|
@book.should be_alive
|
343
343
|
end
|
344
344
|
|
@@ -381,7 +381,7 @@ describe Book do
|
|
381
381
|
if :if_obstructed is :close_if_saved" do
|
382
382
|
expect{
|
383
383
|
@new_book = Book.open(@simple_file1, :if_obstructed => :close_if_saved)
|
384
|
-
}.to raise_error(
|
384
|
+
}.to raise_error(WorkbookNotSaved, /workbook with the same name in a different path is unsaved/)
|
385
385
|
@book.save
|
386
386
|
@new_book = Book.open(@simple_file1, :if_obstructed => :close_if_saved)
|
387
387
|
@book.should_not be_alive
|
@@ -409,7 +409,7 @@ describe Book do
|
|
409
409
|
File.delete @simple_save_file rescue nil
|
410
410
|
expect {
|
411
411
|
Book.open(@simple_save_file)
|
412
|
-
}.to raise_error(
|
412
|
+
}.to raise_error(NameNotFound, /file "#{@simple_save_file}" not found/)
|
413
413
|
end
|
414
414
|
end
|
415
415
|
|
@@ -569,7 +569,7 @@ describe Book do
|
|
569
569
|
begin
|
570
570
|
@excel1.close
|
571
571
|
@excel2.close
|
572
|
-
rescue
|
572
|
+
rescue ExcelError => msg
|
573
573
|
puts "ExcelError: #{msg.message}" if msg.message =~ /Excel instance not alive or damaged/
|
574
574
|
end
|
575
575
|
end
|
@@ -1025,7 +1025,7 @@ describe Book do
|
|
1025
1025
|
it "should raise error by default" do
|
1026
1026
|
expect{
|
1027
1027
|
@book.close(:if_unsaved => :raise)
|
1028
|
-
}.to raise_error(
|
1028
|
+
}.to raise_error(WorkbookNotSaved, /workbook is unsaved: "workbook.xls"/)
|
1029
1029
|
end
|
1030
1030
|
|
1031
1031
|
it "should save the book before close with option :save" do
|
@@ -82,13 +82,13 @@ describe Book do
|
|
82
82
|
it "should raise error with option :raise" do
|
83
83
|
expect{
|
84
84
|
@book.close(:if_unsaved => :raise)
|
85
|
-
}.to raise_error(
|
85
|
+
}.to raise_error(WorkbookNotSaved, /workbook is unsaved: "workbook.xls"/)
|
86
86
|
end
|
87
87
|
|
88
88
|
it "should raise error by default" do
|
89
89
|
expect{
|
90
90
|
@book.close(:if_unsaved => :raise)
|
91
|
-
}.to raise_error(
|
91
|
+
}.to raise_error(WorkbookNotSaved, /workbook is unsaved: "workbook.xls"/)
|
92
92
|
end
|
93
93
|
|
94
94
|
it "should keep the book open" do
|
@@ -118,10 +118,29 @@ describe Book do
|
|
118
118
|
end
|
119
119
|
end
|
120
120
|
|
121
|
+
it "should close the book and leave its file untouched with option :forget even with displayalerts true" do
|
122
|
+
ole_workbook = @book.ole_workbook
|
123
|
+
excel = @book.excel
|
124
|
+
excel.displayalerts = true
|
125
|
+
excel.Workbooks.Count.should == 1
|
126
|
+
@book.close(:if_unsaved => :forget)
|
127
|
+
excel.Workbooks.Count.should == 0
|
128
|
+
@book.ole_workbook.should == nil
|
129
|
+
@book.should_not be_alive
|
130
|
+
expect{
|
131
|
+
ole_workbook.Name}.to raise_error(WIN32OLERuntimeError)
|
132
|
+
new_book = Book.open(@simple_file1)
|
133
|
+
begin
|
134
|
+
new_book.ole_workbook.Worksheets.Count.should == @sheet_count
|
135
|
+
ensure
|
136
|
+
new_book.close
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
121
140
|
it "should raise an error for invalid option" do
|
122
141
|
expect {
|
123
142
|
@book.close(:if_unsaved => :invalid_option)
|
124
|
-
}.to raise_error(
|
143
|
+
}.to raise_error(OptionInvalid, ":if_unsaved: invalid option: :invalid_option")
|
125
144
|
end
|
126
145
|
|
127
146
|
|
@@ -163,7 +182,7 @@ describe Book do
|
|
163
182
|
if answer == :cancel then
|
164
183
|
expect {
|
165
184
|
@book.close(:if_unsaved => :alert)
|
166
|
-
}.
|
185
|
+
}.to_not raise_error
|
167
186
|
@book.ole_workbook.Saved.should be_false
|
168
187
|
@book.ole_workbook.should_not == nil
|
169
188
|
@book.should be_alive
|
@@ -206,7 +225,7 @@ describe Book do
|
|
206
225
|
if answer == :cancel then
|
207
226
|
expect {
|
208
227
|
@book.close(:if_unsaved => :excel)
|
209
|
-
}.
|
228
|
+
}.to_not raise_error
|
210
229
|
@book.ole_workbook.Saved.should be_false
|
211
230
|
@book.ole_workbook.should_not == nil
|
212
231
|
@book.should be_alive
|