robust_excel_ole 1.14 → 1.18.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.
- checksums.yaml +4 -4
- data/Changelog +34 -1
- data/README.rdoc +20 -6
- data/___dummy_workbook.xls +0 -0
- data/docs/README_excel.rdoc +7 -1
- data/docs/README_open.rdoc +45 -20
- data/docs/README_ranges.rdoc +11 -2
- data/examples/example_ruby_library.rb +27 -0
- data/extconf.rb +13 -0
- data/lib/robust_excel_ole.rb +4 -3
- data/lib/robust_excel_ole/{address.rb → address_tool.rb} +23 -22
- data/lib/robust_excel_ole/{reo_common.rb → base.rb} +2 -90
- data/lib/robust_excel_ole/bookstore.rb +14 -77
- data/lib/robust_excel_ole/cell.rb +30 -18
- data/lib/robust_excel_ole/excel.rb +105 -64
- data/lib/robust_excel_ole/general.rb +40 -15
- data/lib/robust_excel_ole/range.rb +42 -19
- data/lib/robust_excel_ole/range_owners.rb +40 -25
- data/lib/robust_excel_ole/vba_objects.rb +30 -0
- data/lib/robust_excel_ole/version.rb +1 -1
- data/lib/robust_excel_ole/workbook.rb +310 -336
- data/lib/robust_excel_ole/worksheet.rb +51 -25
- data/robust_excel_ole.gemspec +1 -0
- data/spec/address_tool_spec.rb +175 -0
- data/spec/{reo_common_spec.rb → base_spec.rb} +19 -34
- data/spec/bookstore_spec.rb +3 -3
- data/spec/cell_spec.rb +67 -25
- data/spec/data/more_data/workbook.xls +0 -0
- data/spec/excel_spec.rb +137 -369
- data/spec/general_spec.rb +21 -27
- data/spec/range_spec.rb +57 -3
- data/spec/workbook_spec.rb +11 -79
- data/spec/workbook_specs/workbook_misc_spec.rb +29 -40
- data/spec/workbook_specs/workbook_open_spec.rb +570 -30
- data/spec/workbook_specs/workbook_unobtr_spec.rb +440 -136
- data/spec/worksheet_spec.rb +36 -4
- metadata +11 -7
- data/spec/address_spec.rb +0 -174
@@ -50,94 +50,10 @@ module RobustExcelOle
|
|
50
50
|
class MiscREOError < REOError
|
51
51
|
end
|
52
52
|
|
53
|
-
# @private
|
54
|
-
class ExcelDamaged < ExcelREOError
|
55
|
-
end
|
56
|
-
|
57
|
-
# @private
|
58
|
-
class UnsavedWorkbooks < ExcelREOError
|
59
|
-
end
|
60
|
-
|
61
|
-
# @private
|
62
|
-
class WorkbookBlocked < WorkbookREOError
|
63
|
-
end
|
64
|
-
|
65
|
-
# @private
|
66
|
-
class WorkbookNotSaved < WorkbookREOError
|
67
|
-
end
|
68
|
-
|
69
|
-
# @private
|
70
|
-
class WorkbookReadOnly < WorkbookREOError
|
71
|
-
end
|
72
|
-
|
73
|
-
# @private
|
74
|
-
class WorkbookBeingUsed < WorkbookREOError
|
75
|
-
end
|
76
|
-
|
77
|
-
# @private
|
78
|
-
class WorkbookConnectingUnsavedError < WorkbookREOError
|
79
|
-
end
|
80
|
-
|
81
|
-
# @private
|
82
|
-
class WorkbookConnectingBlockingError < WorkbookREOError
|
83
|
-
end
|
84
|
-
|
85
|
-
# @private
|
86
|
-
class WorkbookConnectingUnknownError < WorkbookREOError
|
87
|
-
end
|
88
|
-
|
89
|
-
# @private
|
90
|
-
class FileNotFound < FileREOError
|
91
|
-
end
|
92
|
-
|
93
|
-
# @private
|
94
|
-
class FileNameNotGiven < FileREOError
|
95
|
-
end
|
96
|
-
|
97
|
-
# @private
|
98
|
-
class FileAlreadyExists < FileREOError
|
99
|
-
end
|
100
|
-
|
101
|
-
# @private
|
102
|
-
class NameNotFound < NamesREOError
|
103
|
-
end
|
104
|
-
|
105
|
-
# @private
|
106
|
-
class NameAlreadyExists < NamesREOError
|
107
|
-
end
|
108
|
-
|
109
|
-
# @private
|
110
|
-
class RangeNotEvaluatable < MiscREOError
|
111
|
-
end
|
112
|
-
|
113
|
-
# @private
|
114
|
-
class RangeNotCreated < MiscREOError
|
115
|
-
end
|
116
|
-
|
117
|
-
# @private
|
118
|
-
class RangeNotCopied < MiscREOError
|
119
|
-
end
|
120
|
-
|
121
|
-
# @private
|
122
|
-
class OptionInvalid < MiscREOError
|
123
|
-
end
|
124
|
-
|
125
|
-
# @private
|
126
|
-
class ObjectNotAlive < MiscREOError
|
127
|
-
end
|
128
|
-
|
129
53
|
# @private
|
130
54
|
class TypeREOError < REOError
|
131
55
|
end
|
132
56
|
|
133
|
-
# @private
|
134
|
-
class TimeOut < REOError
|
135
|
-
end
|
136
|
-
|
137
|
-
# @private
|
138
|
-
class AddressInvalid < REOError
|
139
|
-
end
|
140
|
-
|
141
57
|
# @private
|
142
58
|
class UnexpectedREOError < REOError
|
143
59
|
end
|
@@ -145,13 +61,9 @@ module RobustExcelOle
|
|
145
61
|
# @private
|
146
62
|
class NotImplementedREOError < REOError
|
147
63
|
end
|
64
|
+
|
148
65
|
|
149
|
-
class
|
150
|
-
|
151
|
-
# @private
|
152
|
-
def excel
|
153
|
-
raise TypeREOError, 'receiver instance is neither an Excel nor a Workbook'
|
154
|
-
end
|
66
|
+
class Base
|
155
67
|
|
156
68
|
# @private
|
157
69
|
def own_methods
|
@@ -2,7 +2,8 @@
|
|
2
2
|
|
3
3
|
module RobustExcelOle
|
4
4
|
|
5
|
-
class Bookstore <
|
5
|
+
class Bookstore < Base
|
6
|
+
|
6
7
|
def initialize
|
7
8
|
@filename2books ||= Hash.new { |hash, key| hash[key] = [] }
|
8
9
|
@hidden_excel_instance = nil
|
@@ -29,11 +30,9 @@ module RobustExcelOle
|
|
29
30
|
# otherwise proceeds according to prefer_writable
|
30
31
|
def fetch(filename, options = { :prefer_writable => true })
|
31
32
|
return nil unless filename
|
32
|
-
|
33
33
|
filename = General.absolute_path(filename)
|
34
34
|
filename_key = General.canonize(filename)
|
35
|
-
weakref_books = @filename2books[filename_key]
|
36
|
-
weakref_books = consider_networkpaths(filename_key) if weakref_books.empty? || weakref_books.nil?
|
35
|
+
weakref_books = @filename2books[filename_key]
|
37
36
|
return nil if weakref_books.nil? || weakref_books.empty?
|
38
37
|
|
39
38
|
result = open_book = closed_book = nil
|
@@ -67,68 +66,6 @@ module RobustExcelOle
|
|
67
66
|
result
|
68
67
|
end
|
69
68
|
|
70
|
-
# @private
|
71
|
-
def consider_networkpaths(filename)
|
72
|
-
network = WIN32OLE.new('WScript.Network')
|
73
|
-
drives = network.enumnetworkdrives
|
74
|
-
drive_letter, filename_after_drive_letter = filename.split(':')
|
75
|
-
found_filename = nil
|
76
|
-
# if filename starts with a drive letter not c and this drive exists,
|
77
|
-
# then if there is the corresponding host_share_path in the bookstore,
|
78
|
-
# then take the corresponding workbooks
|
79
|
-
if drive_letter != 'c' && drive_letter != filename
|
80
|
-
for i in 0 .. drives.Count-1
|
81
|
-
next if i % 2 == 1
|
82
|
-
if drives.Item(i).gsub(':','').downcase == drive_letter
|
83
|
-
hostname_share = drives.Item(i+1).gsub('\\','/').gsub('//','').downcase
|
84
|
-
break
|
85
|
-
end
|
86
|
-
end
|
87
|
-
@filename2books.each do |stored_filename,_|
|
88
|
-
if hostname_share && stored_filename
|
89
|
-
if stored_filename[0] == '/'
|
90
|
-
index_hostname = stored_filename[1,stored_filename.length].index('/')+2
|
91
|
-
index_hostname_share = stored_filename[index_hostname,stored_filename.length].index('/')
|
92
|
-
hostname_share_in_stored_filename = stored_filename[1,index_hostname+index_hostname_share-1]
|
93
|
-
if hostname_share_in_stored_filename == hostname_share
|
94
|
-
found_filename = stored_filename
|
95
|
-
break
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
elsif filename[0] == '/'
|
101
|
-
# if filename starts with a host name and share, and this is an existing host name share path,
|
102
|
-
# then if there are workbooks with the corresponding drive letter,
|
103
|
-
# then take these workbooks,
|
104
|
-
index_hostname = filename[1,filename.length].index('/')+2
|
105
|
-
index_hostname_share = filename[index_hostname,filename.length].index('/')
|
106
|
-
hostname_share_in_filename = filename[1,index_hostname+index_hostname_share-1]
|
107
|
-
filename_after_hostname_share = filename[index_hostname+index_hostname_share+1, filename.length]
|
108
|
-
require 'socket'
|
109
|
-
hostname = Socket.gethostname
|
110
|
-
if hostname_share_in_filename[0,hostname_share_in_filename.index('/')] == hostname.downcase
|
111
|
-
for i in 0 .. drives.Count-1
|
112
|
-
next if i % 2 == 1
|
113
|
-
hostname_share = drives.Item(i+1).gsub('\\','/').gsub('//','').downcase
|
114
|
-
if hostname_share == hostname_share_in_filename
|
115
|
-
drive_letter = drives.Item(i).gsub(':','').downcase
|
116
|
-
break
|
117
|
-
end
|
118
|
-
end
|
119
|
-
@filename2books.each do |stored_filename,_|
|
120
|
-
if stored_filename
|
121
|
-
if drive_letter && stored_filename.start_with?(drive_letter.downcase) && stored_filename.end_with?(filename_after_hostname_share)
|
122
|
-
found_filename = stored_filename
|
123
|
-
break
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
129
|
-
@filename2books[found_filename]
|
130
|
-
end
|
131
|
-
|
132
69
|
# stores a workbook
|
133
70
|
# @param [Workbook] book a given book
|
134
71
|
def store(book)
|
@@ -138,8 +75,7 @@ module RobustExcelOle
|
|
138
75
|
# deletes the weak reference to the book
|
139
76
|
@filename2books[old_filename_key].delete(book)
|
140
77
|
end
|
141
|
-
@filename2books[filename_key] |= [WeakRef.new(book)]
|
142
|
-
book.stored_filename = book.filename
|
78
|
+
@filename2books[filename_key] |= [WeakRef.new(book)]
|
143
79
|
end
|
144
80
|
|
145
81
|
# creates and returns a separate Excel instance with Visible and DisplayAlerts equal false
|
@@ -168,7 +104,6 @@ module RobustExcelOle
|
|
168
104
|
|
169
105
|
private
|
170
106
|
|
171
|
-
# @private
|
172
107
|
def try_hidden_excel
|
173
108
|
@hidden_excel_instance.__getobj__ if @hidden_excel_instance && @hidden_excel_instance.weakref_alive? && @hidden_excel_instance.__getobj__.alive?
|
174
109
|
end
|
@@ -177,24 +112,26 @@ module RobustExcelOle
|
|
177
112
|
|
178
113
|
# prints the book store
|
179
114
|
# @private
|
180
|
-
def
|
181
|
-
#
|
115
|
+
def print_filename2books
|
116
|
+
#puts "@filename2books:"
|
182
117
|
if @filename2books
|
183
|
-
@filename2books.each do |
|
184
|
-
#
|
185
|
-
#
|
118
|
+
@filename2books.each do |filename,books|
|
119
|
+
#puts " filename: #{filename}"
|
120
|
+
#puts " books:"
|
186
121
|
if books.empty?
|
187
|
-
#
|
122
|
+
#puts " []"
|
188
123
|
else
|
189
124
|
books.each do |book|
|
190
125
|
if book.weakref_alive?
|
191
|
-
#
|
126
|
+
#puts "book.filename: #{book.filename}"
|
192
127
|
else # this should never happen
|
193
|
-
#
|
128
|
+
#puts "weakref not alive"
|
194
129
|
end
|
195
130
|
end
|
196
131
|
end
|
197
132
|
end
|
133
|
+
else
|
134
|
+
#puts "nil"
|
198
135
|
end
|
199
136
|
end
|
200
137
|
end
|
@@ -1,11 +1,15 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
|
3
|
+
require File.join(File.dirname(__FILE__), './range')
|
4
|
+
|
3
5
|
module RobustExcelOle
|
4
|
-
class Cell < REOCommon
|
5
|
-
attr_reader :cell
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
class Cell < Range
|
8
|
+
#attr_reader :ole_cell
|
9
|
+
|
10
|
+
def initialize(win32_cell, worksheet)
|
11
|
+
super
|
12
|
+
ole_cell
|
9
13
|
end
|
10
14
|
|
11
15
|
def v
|
@@ -16,25 +20,33 @@ module RobustExcelOle
|
|
16
20
|
self.Value = value
|
17
21
|
end
|
18
22
|
|
23
|
+
def ole_cell
|
24
|
+
@ole_range = @ole_range.MergeArea.Item(1,1) if @ole_range.MergeCells
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
19
29
|
# @private
|
20
30
|
def method_missing(name, *args)
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
31
|
+
if name.to_s[0,1] =~ /[A-Z]/
|
32
|
+
if ::ERRORMESSAGE_JRUBY_BUG
|
33
|
+
begin
|
34
|
+
#@ole_cell.send(name, *args)
|
35
|
+
@ole_range.send(name, *args)
|
36
|
+
rescue Java::OrgRacobCom::ComFailException
|
37
|
+
raise VBAMethodMissingError, "unknown VBA property or method #{name.inspect}"
|
38
|
+
end
|
39
|
+
else
|
40
|
+
begin
|
41
|
+
#@ole_cell.send(name, *args)
|
42
|
+
@ole_range.send(name, *args)
|
43
|
+
rescue NoMethodError
|
44
|
+
raise VBAMethodMissingError, "unknown VBA property or method #{name.inspect}"
|
45
|
+
end
|
27
46
|
end
|
28
47
|
else
|
29
|
-
|
30
|
-
@cell.send(name, *args)
|
31
|
-
rescue NoMethodError
|
32
|
-
raise VBAMethodMissingError, "unknown VBA property or method #{name.inspect}"
|
33
|
-
end
|
48
|
+
super
|
34
49
|
end
|
35
|
-
# else
|
36
|
-
# super
|
37
|
-
# end
|
38
50
|
end
|
39
51
|
end
|
40
52
|
end
|
@@ -14,21 +14,17 @@ module RobustExcelOle
|
|
14
14
|
# that you would apply for an Application object.
|
15
15
|
# See https://docs.microsoft.com/en-us/office/vba/api/excel.application(object)#methods
|
16
16
|
|
17
|
-
class Excel <
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
# setter methods are implemented below
|
23
|
-
attr_reader :visible
|
24
|
-
attr_reader :displayalerts
|
25
|
-
attr_reader :calculation
|
26
|
-
attr_reader :screenupdating
|
17
|
+
class Excel < VbaObjects
|
18
|
+
attr_reader :ole_excel
|
19
|
+
attr_reader :properties
|
20
|
+
attr_reader :address_tool
|
27
21
|
|
28
22
|
alias ole_object ole_excel
|
29
23
|
|
30
24
|
@@hwnd2excel = {}
|
31
25
|
|
26
|
+
PROPERTIES = [:visible, :displayalerts, :calculation, :screenupdating]
|
27
|
+
|
32
28
|
# creates a new Excel instance
|
33
29
|
# @param [Hash] options the options
|
34
30
|
# @option options [Variant] :displayalerts
|
@@ -96,10 +92,7 @@ module RobustExcelOle
|
|
96
92
|
unless reused || connected
|
97
93
|
options = { :displayalerts => :if_visible, :visible => false, :screenupdating => true }.merge(options)
|
98
94
|
end
|
99
|
-
result.
|
100
|
-
result.displayalerts = options[:displayalerts] unless options[:displayalerts].nil?
|
101
|
-
result.calculation = options[:calculation] unless options[:calculation].nil?
|
102
|
-
result.screenupdating = options[:screenupdating] unless options[:screenupdating].nil?
|
95
|
+
result.set_options(options)
|
103
96
|
end
|
104
97
|
result
|
105
98
|
end
|
@@ -117,14 +110,10 @@ module RobustExcelOle
|
|
117
110
|
# @return [Excel] an Excel instance
|
118
111
|
def recreate(opts = {})
|
119
112
|
unless alive?
|
120
|
-
opts = {
|
121
|
-
|
122
|
-
:displayalerts => @displayalerts || :if_visible
|
123
|
-
}.merge(opts)
|
113
|
+
opts = {:visible => false, :displayalerts => :if_visible}.merge(
|
114
|
+
{:visible => @properties[:visible], :displayalerts => @properties[:displayalerts]}).merge(opts)
|
124
115
|
@ole_excel = WIN32OLE.new('Excel.Application')
|
125
|
-
|
126
|
-
self.displayalerts = opts[:displayalerts]
|
127
|
-
self.calculation = opts[:calculation]
|
116
|
+
set_options(opts)
|
128
117
|
if opts[:reopen_workbooks]
|
129
118
|
books = workbook_class.books
|
130
119
|
books.each do |book|
|
@@ -135,10 +124,18 @@ module RobustExcelOle
|
|
135
124
|
self
|
136
125
|
end
|
137
126
|
|
127
|
+
# @private
|
128
|
+
def address_tool
|
129
|
+
raise(ExcelREOError, "Excel contains no workbook") unless @ole_excel.Workbooks.Count > 0
|
130
|
+
@address_tool ||= begin
|
131
|
+
address_string = @ole_excel.Workbooks.Item(1).Worksheets.Item(1).Cells.Item(1,1).Address(true,true,XlR1C1)
|
132
|
+
address_tool_class.new(address_string)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
138
136
|
private
|
139
137
|
|
140
138
|
# retain the saved status of all workbooks
|
141
|
-
# @private
|
142
139
|
def retain_saved_workbooks
|
143
140
|
saved_stati = @ole_excel.Workbooks.map { |w| w.Saved }
|
144
141
|
begin
|
@@ -148,7 +145,6 @@ module RobustExcelOle
|
|
148
145
|
end
|
149
146
|
end
|
150
147
|
|
151
|
-
# @private
|
152
148
|
def ole_workbooks
|
153
149
|
ole_workbooks = begin
|
154
150
|
@ole_excel.Workbooks
|
@@ -163,11 +159,13 @@ module RobustExcelOle
|
|
163
159
|
|
164
160
|
public
|
165
161
|
|
162
|
+
# @private
|
166
163
|
def self.contains_unsaved_workbooks?
|
167
164
|
!Excel.current.unsaved_workbooks.empty?
|
168
165
|
end
|
169
166
|
|
170
167
|
# returns unsaved workbooks (win32ole objects)
|
168
|
+
# @private
|
171
169
|
def unsaved_workbooks
|
172
170
|
unsaved_workbooks = []
|
173
171
|
begin
|
@@ -185,6 +183,7 @@ module RobustExcelOle
|
|
185
183
|
# :forget -> closes the Excel instance without saving the workbooks
|
186
184
|
# :save -> saves the workbooks before closing
|
187
185
|
# :alert -> let Excel do it
|
186
|
+
# @private
|
188
187
|
def close_workbooks(options = { :if_unsaved => :raise })
|
189
188
|
return unless alive?
|
190
189
|
|
@@ -392,14 +391,13 @@ module RobustExcelOle
|
|
392
391
|
@@hwnd2excel.size
|
393
392
|
end
|
394
393
|
|
395
|
-
|
394
|
+
private
|
396
395
|
|
397
396
|
# returns a Win32OLE object that represents a Excel instance to which Excel connects
|
398
397
|
# connects to the first opened Excel instance
|
399
398
|
# if this Excel instance is being closed, then Excel creates a new Excel instance
|
400
|
-
# @private
|
401
399
|
def self.current_ole_excel
|
402
|
-
if
|
400
|
+
if ::CONNECT_EXCEL_JRUBY_BUG
|
403
401
|
result = known_excel_instance
|
404
402
|
if result.nil?
|
405
403
|
if excels_number > 0
|
@@ -440,6 +438,25 @@ module RobustExcelOle
|
|
440
438
|
nil
|
441
439
|
end
|
442
440
|
|
441
|
+
def self.hwnd2excel(hwnd)
|
442
|
+
excel_weakref = @@hwnd2excel[hwnd]
|
443
|
+
if excel_weakref
|
444
|
+
if excel_weakref.weakref_alive?
|
445
|
+
excel_weakref.__getobj__
|
446
|
+
else
|
447
|
+
trace 'dead reference to an Excel'
|
448
|
+
begin
|
449
|
+
@@hwnd2excel.delete(hwnd)
|
450
|
+
nil
|
451
|
+
rescue
|
452
|
+
trace "Warning: deleting dead reference failed! (hwnd: #{hwnd.inspect})"
|
453
|
+
end
|
454
|
+
end
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
458
|
+
public
|
459
|
+
|
443
460
|
# returns all Excel objects for all Excel instances opened with RobustExcelOle
|
444
461
|
def self.known_excel_instances
|
445
462
|
pid2excel = {}
|
@@ -474,24 +491,6 @@ module RobustExcelOle
|
|
474
491
|
self
|
475
492
|
end
|
476
493
|
|
477
|
-
# @private
|
478
|
-
def self.hwnd2excel(hwnd)
|
479
|
-
excel_weakref = @@hwnd2excel[hwnd]
|
480
|
-
if excel_weakref
|
481
|
-
if excel_weakref.weakref_alive?
|
482
|
-
excel_weakref.__getobj__
|
483
|
-
else
|
484
|
-
trace 'dead reference to an Excel'
|
485
|
-
begin
|
486
|
-
@@hwnd2excel.delete(hwnd)
|
487
|
-
nil
|
488
|
-
rescue
|
489
|
-
trace "Warning: deleting dead reference failed! (hwnd: #{hwnd.inspect})"
|
490
|
-
end
|
491
|
-
end
|
492
|
-
end
|
493
|
-
end
|
494
|
-
|
495
494
|
# @private
|
496
495
|
def hwnd
|
497
496
|
self.Hwnd
|
@@ -545,7 +544,7 @@ module RobustExcelOle
|
|
545
544
|
|
546
545
|
# sets DisplayAlerts in a block
|
547
546
|
def with_displayalerts displayalerts_value
|
548
|
-
old_displayalerts = displayalerts
|
547
|
+
old_displayalerts = @properties[:displayalerts]
|
549
548
|
self.displayalerts = displayalerts_value
|
550
549
|
begin
|
551
550
|
yield self
|
@@ -556,26 +555,29 @@ module RobustExcelOle
|
|
556
555
|
|
557
556
|
# makes the current Excel instance visible or invisible
|
558
557
|
def visible= visible_value
|
559
|
-
|
560
|
-
@ole_excel.
|
558
|
+
return if visible_value.nil?
|
559
|
+
@ole_excel.Visible = @properties[:visible] = visible_value
|
560
|
+
@ole_excel.DisplayAlerts = @properties[:visible] if @properties[:displayalerts] == :if_visible
|
561
561
|
end
|
562
562
|
|
563
563
|
# enables DisplayAlerts in the current Excel instance
|
564
564
|
def displayalerts= displayalerts_value
|
565
|
-
|
566
|
-
@
|
565
|
+
return if displayalerts_value.nil?
|
566
|
+
@properties[:displayalerts] = displayalerts_value
|
567
|
+
@ole_excel.DisplayAlerts = @properties[:displayalerts] == :if_visible ? @ole_excel.Visible : displayalerts_value
|
567
568
|
end
|
568
569
|
|
569
570
|
# sets ScreenUpdating
|
570
571
|
def screenupdating= screenupdating_value
|
571
|
-
|
572
|
+
return if screenupdating_value.nil?
|
573
|
+
@ole_excel.ScreenUpdating = @properties[:screenupdating] = screenupdating_value
|
572
574
|
end
|
573
575
|
|
574
576
|
# sets calculation mode
|
575
577
|
# retains the saved-status of the workbooks when set to manual
|
576
578
|
def calculation= calculation_mode
|
577
579
|
return if calculation_mode.nil?
|
578
|
-
@calculation = calculation_mode
|
580
|
+
@properties[:calculation] = calculation_mode
|
579
581
|
calc_mode_changable = @ole_excel.Workbooks.Count > 0 && @ole_excel.Calculation.is_a?(Integer)
|
580
582
|
if calc_mode_changable
|
581
583
|
retain_saved_workbooks do
|
@@ -615,9 +617,9 @@ module RobustExcelOle
|
|
615
617
|
def Calculation= calculation_vba_mode
|
616
618
|
case calculation_vba_mode
|
617
619
|
when XlCalculationManual
|
618
|
-
@calculation = :manual
|
620
|
+
@properties[:calculation] = :manual
|
619
621
|
when XlCalculationAutomatic
|
620
|
-
@calculation = :automatic
|
622
|
+
@properties[:calculation] = :automatic
|
621
623
|
end
|
622
624
|
@ole_excel.Calculation = calculation_vba_mode
|
623
625
|
end
|
@@ -637,13 +639,22 @@ module RobustExcelOle
|
|
637
639
|
|
638
640
|
# set options in this Excel instance
|
639
641
|
def for_this_instance(options)
|
640
|
-
|
642
|
+
set_options(options)
|
643
|
+
#self.class.new(@ole_excel, options)
|
641
644
|
end
|
642
645
|
|
643
|
-
def set_options(options)
|
644
|
-
|
645
|
-
end
|
646
|
+
#def set_options(options)
|
647
|
+
# for_this_instance(options)
|
648
|
+
#end
|
646
649
|
|
650
|
+
def set_options(options)
|
651
|
+
@properties ||= { }
|
652
|
+
PROPERTIES.each do |property|
|
653
|
+
method = (property.to_s + '=').to_sym
|
654
|
+
self.send(method, options[property])
|
655
|
+
end
|
656
|
+
end
|
657
|
+
|
647
658
|
# set options in all workbooks
|
648
659
|
def for_all_workbooks(options)
|
649
660
|
each_workbook(options)
|
@@ -690,12 +701,17 @@ module RobustExcelOle
|
|
690
701
|
# @param [String] name the name of the range
|
691
702
|
# @param [Variant] value the contents of the range
|
692
703
|
def []=(name, value)
|
693
|
-
|
694
|
-
workbook.color_if_modified = 42 unless workbook.nil? # aqua-marin
|
695
|
-
set_namevalue_glob(name,value)
|
696
|
-
workbook.color_if_modified = old_color_if_modified
|
704
|
+
set_namevalue_glob(name, value, :color => 42)
|
697
705
|
end
|
698
706
|
|
707
|
+
# @private
|
708
|
+
# returns active workbook
|
709
|
+
def workbook
|
710
|
+
@workbook ||= workbook_class.new(@ole_excel.ActiveWorkbook) if @ole_excel.Workbooks.Count > 0
|
711
|
+
end
|
712
|
+
|
713
|
+
alias_method :active_workbook, :workbook
|
714
|
+
|
699
715
|
# @private
|
700
716
|
def to_s
|
701
717
|
'#<Excel: ' + hwnd.to_s + ('not alive' unless alive?).to_s + '>'
|
@@ -721,15 +737,30 @@ module RobustExcelOle
|
|
721
737
|
self.class.workbook_class
|
722
738
|
end
|
723
739
|
|
740
|
+
# @private
|
741
|
+
def self.address_tool_class
|
742
|
+
@address_tool_class ||= begin
|
743
|
+
module_name = parent_name
|
744
|
+
"#{module_name}::AddressTool".constantize
|
745
|
+
rescue NameError => e
|
746
|
+
AddressTool
|
747
|
+
end
|
748
|
+
end
|
749
|
+
|
750
|
+
# @private
|
751
|
+
def address_tool_class
|
752
|
+
self.class.address_tool_class
|
753
|
+
end
|
754
|
+
|
755
|
+
|
724
756
|
include MethodHelpers
|
725
757
|
|
726
758
|
private
|
727
759
|
|
728
|
-
# @private
|
729
760
|
def method_missing(name, *args)
|
730
761
|
if name.to_s[0,1] =~ /[A-Z]/
|
731
762
|
raise ObjectNotAlive, 'method missing: Excel not alive' unless alive?
|
732
|
-
if
|
763
|
+
if ::ERRORMESSAGE_JRUBY_BUG
|
733
764
|
begin
|
734
765
|
@ole_excel.send(name, *args)
|
735
766
|
rescue Java::OrgRacobCom::ComFailException => msg
|
@@ -748,7 +779,16 @@ module RobustExcelOle
|
|
748
779
|
end
|
749
780
|
end
|
750
781
|
|
751
|
-
|
782
|
+
public
|
783
|
+
|
784
|
+
# @private
|
785
|
+
class ExcelDamaged < ExcelREOError
|
786
|
+
end
|
787
|
+
|
788
|
+
# @private
|
789
|
+
class UnsavedWorkbooks < ExcelREOError
|
790
|
+
end
|
791
|
+
|
752
792
|
|
753
793
|
Application = Excel
|
754
794
|
|
@@ -757,3 +797,4 @@ end
|
|
757
797
|
class WIN32OLE
|
758
798
|
include Enumerable
|
759
799
|
end
|
800
|
+
|