robust_excel_ole 1.16 → 1.17
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/docs/README_open.rdoc +4 -0
- data/lib/robust_excel_ole.rb +5 -4
- 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 +2 -2
- data/lib/robust_excel_ole/cell.rb +21 -17
- data/lib/robust_excel_ole/excel.rb +64 -26
- data/lib/robust_excel_ole/general.rb +7 -5
- data/lib/robust_excel_ole/range.rb +15 -7
- data/lib/robust_excel_ole/range_owners.rb +18 -6
- data/lib/robust_excel_ole/version.rb +1 -1
- data/lib/robust_excel_ole/workbook.rb +140 -147
- data/lib/robust_excel_ole/worksheet.rb +7 -7
- data/spec/address_tool_spec.rb +175 -0
- data/spec/{reo_common_spec.rb → base_spec.rb} +10 -29
- data/spec/cell_spec.rb +67 -25
- data/spec/data/more_data/workbook.xls +0 -0
- data/spec/data/workbook.xls +0 -0
- data/spec/excel_spec.rb +25 -273
- data/spec/general_spec.rb +16 -19
- data/spec/range_spec.rb +1 -1
- data/spec/workbook_spec.rb +7 -75
- data/spec/workbook_specs/workbook_misc_spec.rb +10 -10
- data/spec/workbook_specs/workbook_open_spec.rb +228 -14
- data/spec/workbook_specs/workbook_unobtr_spec.rb +31 -31
- metadata +6 -6
- data/spec/address_spec.rb +0 -174
@@ -95,26 +95,28 @@ end
|
|
95
95
|
|
96
96
|
# @private
|
97
97
|
class WIN32OLE
|
98
|
-
|
99
|
-
include RobustExcelOle
|
100
98
|
|
101
99
|
# type-lifting WIN32OLE objects to RobustExcelOle objects
|
102
100
|
def to_reo
|
103
|
-
class2method = [{Excel => :Hwnd}, {Workbook => :FullName}, {Worksheet => :Copy}, {Range => :
|
101
|
+
class2method = [{Excel => :Hwnd}, {Workbook => :FullName}, {Worksheet => :Copy}, {RobustExcelOle::Range => :Row}]
|
104
102
|
class2method.each do |element|
|
105
103
|
classname = element.first.first
|
106
104
|
method = element.first.last
|
107
105
|
begin
|
108
106
|
self.send(method)
|
109
|
-
|
107
|
+
if classname == RobustExcelOle::Range && self.Rows.Count == 1 && self.Columns.Count == 1
|
108
|
+
return Cell.new(self)
|
109
|
+
else
|
110
|
+
return classname.new(self)
|
111
|
+
end
|
110
112
|
rescue
|
111
113
|
next
|
112
114
|
end
|
113
115
|
end
|
116
|
+
raise TypeREOError, "given object cannot be type-lifted to a RobustExcelOle object"
|
114
117
|
end
|
115
118
|
end
|
116
119
|
|
117
|
-
|
118
120
|
# @private
|
119
121
|
class ::String
|
120
122
|
def / path_part
|
@@ -6,7 +6,7 @@ module RobustExcelOle
|
|
6
6
|
# that you would apply for a Range object.
|
7
7
|
# See https://docs.microsoft.com/en-us/office/vba/api/excel.worksheet#methods
|
8
8
|
|
9
|
-
class Range <
|
9
|
+
class Range < VbaObjects
|
10
10
|
include Enumerable
|
11
11
|
attr_reader :ole_range
|
12
12
|
attr_reader :worksheet
|
@@ -48,7 +48,7 @@ module RobustExcelOle
|
|
48
48
|
self.Value
|
49
49
|
else
|
50
50
|
address_r1c1 = self.AddressLocal(true,true,XlR1C1)
|
51
|
-
row, col =
|
51
|
+
row, col = address_tool.as_integer_ranges(address_r1c1)
|
52
52
|
values = []
|
53
53
|
row.each do |r|
|
54
54
|
values_col = []
|
@@ -69,7 +69,7 @@ module RobustExcelOle
|
|
69
69
|
ole_range.Value = value
|
70
70
|
else
|
71
71
|
address_r1c1 = ole_range.AddressLocal(true,true,XlR1C1)
|
72
|
-
row, col =
|
72
|
+
row, col = address_tool.as_integer_ranges(address_r1c1)
|
73
73
|
row.each_with_index do |r,i|
|
74
74
|
col.each_with_index do |c,j|
|
75
75
|
ole_range.Cells(i+1,j+1).Value = (value.respond_to?(:first) ? value[i][j] : value)
|
@@ -115,8 +115,7 @@ module RobustExcelOle
|
|
115
115
|
{ }
|
116
116
|
end
|
117
117
|
end
|
118
|
-
rows, columns =
|
119
|
-
#dest_sheet = @worksheet if dest_sheet == :__not_provided
|
118
|
+
rows, columns = address_tool.as_integer_ranges(dest_address)
|
120
119
|
dest_address_is_position = (rows.min == rows.max && columns.min == columns.max)
|
121
120
|
dest_range_address = if (not dest_address_is_position)
|
122
121
|
[rows.min..rows.max,columns.min..columns.max]
|
@@ -168,7 +167,7 @@ module RobustExcelOle
|
|
168
167
|
# @options [Worksheet] the destination worksheet
|
169
168
|
# @options [Hash] options: :transpose, :values_only
|
170
169
|
def copy_special(dest_address, dest_sheet = :__not_provided, options = { })
|
171
|
-
rows, columns =
|
170
|
+
rows, columns = address_tool.as_integer_ranges(dest_address)
|
172
171
|
dest_sheet = @worksheet if dest_sheet == :__not_provided
|
173
172
|
dest_address_is_position = (rows.min == rows.max && columns.min == columns.max)
|
174
173
|
dest_range_address = if (not dest_address_is_position)
|
@@ -220,6 +219,11 @@ module RobustExcelOle
|
|
220
219
|
self.Address == other_range.Address
|
221
220
|
end
|
222
221
|
|
222
|
+
# @private
|
223
|
+
def excel
|
224
|
+
@worksheet.workbook.excel
|
225
|
+
end
|
226
|
+
|
223
227
|
# @private
|
224
228
|
def self.worksheet_class
|
225
229
|
@worksheet_class ||= begin
|
@@ -237,7 +241,6 @@ module RobustExcelOle
|
|
237
241
|
|
238
242
|
private
|
239
243
|
|
240
|
-
# @private
|
241
244
|
def method_missing(name, *args)
|
242
245
|
if name.to_s[0,1] =~ /[A-Z]/
|
243
246
|
if ::ERRORMESSAGE_JRUBY_BUG
|
@@ -258,4 +261,9 @@ module RobustExcelOle
|
|
258
261
|
end
|
259
262
|
end
|
260
263
|
end
|
264
|
+
|
265
|
+
# @private
|
266
|
+
class RangeNotCopied < MiscREOError
|
267
|
+
end
|
268
|
+
|
261
269
|
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module RobustExcelOle
|
4
4
|
|
5
|
-
class RangeOwners <
|
5
|
+
class RangeOwners < VbaObjects
|
6
6
|
|
7
7
|
# returns the contents of a range with given name
|
8
8
|
# if the name could not be found or the value could not be determined,
|
@@ -75,7 +75,7 @@ module RobustExcelOle
|
|
75
75
|
ole_range.Value = value
|
76
76
|
else
|
77
77
|
address_r1c1 = ole_range.AddressLocal(true,true,XlR1C1)
|
78
|
-
row, col =
|
78
|
+
row, col = address_tool.as_integer_ranges(address_r1c1)
|
79
79
|
row.each_with_index do |r,i|
|
80
80
|
col.each_with_index do |c,j|
|
81
81
|
ole_range.Cells(i+1,j+1).Value = (value.respond_to?(:first) ? value[i][j] : value )
|
@@ -141,7 +141,7 @@ module RobustExcelOle
|
|
141
141
|
ole_range.Value = value
|
142
142
|
else
|
143
143
|
address_r1c1 = ole_range.AddressLocal(true,true,XlR1C1)
|
144
|
-
row, col =
|
144
|
+
row, col = address_tool.as_integer_ranges(address_r1c1)
|
145
145
|
row.each_with_index do |r,i|
|
146
146
|
col.each_with_index do |c,j|
|
147
147
|
ole_range.Cells(i+1,j+1).Value = (value.respond_to?(:first) ? value[i][j] : value)
|
@@ -192,7 +192,7 @@ module RobustExcelOle
|
|
192
192
|
if self.is_a?(Worksheet) && (range.nil? || (address2 != :__not_provided))
|
193
193
|
address = name_or_address
|
194
194
|
address = [name_or_address,address2] unless address2 == :__not_provided
|
195
|
-
self.Names.Add('__dummy001',nil,true,nil,nil,nil,nil,nil,nil,'=' +
|
195
|
+
self.Names.Add('__dummy001',nil,true,nil,nil,nil,nil,nil,nil,'=' + address_tool.as_r1c1(address))
|
196
196
|
range = RobustExcelOle::Range.new(name_object('__dummy001').RefersToRange)
|
197
197
|
self.Names.Item('__dummy001').Delete
|
198
198
|
workbook = self.is_a?(Workbook) ? self : self.workbook
|
@@ -216,7 +216,7 @@ module RobustExcelOle
|
|
216
216
|
def add_name(name, addr, addr_deprecated = :__not_provided)
|
217
217
|
addr = [addr,addr_deprecated] unless addr_deprecated == :__not_provided
|
218
218
|
begin
|
219
|
-
self.Names.Add(name, nil, true, nil, nil, nil, nil, nil, nil, '=' +
|
219
|
+
self.Names.Add(name, nil, true, nil, nil, nil, nil, nil, nil, '=' + address_tool.as_r1c1(addr))
|
220
220
|
rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException
|
221
221
|
raise RangeNotEvaluatable, "cannot add name #{name.inspect} to range #{addr.inspect}"
|
222
222
|
end
|
@@ -257,7 +257,7 @@ module RobustExcelOle
|
|
257
257
|
rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException
|
258
258
|
raise UnexpectedREOError, "name error in #{File.basename(self.stored_filename).inspect}"
|
259
259
|
end
|
260
|
-
end
|
260
|
+
end
|
261
261
|
|
262
262
|
private
|
263
263
|
|
@@ -273,4 +273,16 @@ module RobustExcelOle
|
|
273
273
|
|
274
274
|
end
|
275
275
|
|
276
|
+
# @private
|
277
|
+
class NameNotFound < NamesREOError
|
278
|
+
end
|
279
|
+
|
280
|
+
# @private
|
281
|
+
class NameAlreadyExists < NamesREOError
|
282
|
+
end
|
283
|
+
|
284
|
+
# @private
|
285
|
+
class RangeNotCreated < MiscREOError
|
286
|
+
end
|
287
|
+
|
276
288
|
end
|
@@ -22,7 +22,7 @@ module RobustExcelOle
|
|
22
22
|
CORE_DEFAULT_OPEN_OPTS = {
|
23
23
|
:default => {:excel => :current},
|
24
24
|
:force => {},
|
25
|
-
:update_links => :never
|
25
|
+
:update_links => :never
|
26
26
|
}.freeze
|
27
27
|
|
28
28
|
DEFAULT_OPEN_OPTS = {
|
@@ -85,7 +85,7 @@ module RobustExcelOle
|
|
85
85
|
# :check_compatibility true -> check compatibility when saving
|
86
86
|
# :update_links true -> user is being asked how to update links, false -> links are never updated
|
87
87
|
# @return [Workbook] a representation of a workbook
|
88
|
-
def self.new(file_or_workbook, opts = { }
|
88
|
+
def self.new(file_or_workbook, opts = { })
|
89
89
|
process_options(opts)
|
90
90
|
case file_or_workbook
|
91
91
|
when NilClass
|
@@ -93,7 +93,7 @@ module RobustExcelOle
|
|
93
93
|
when WIN32OLE
|
94
94
|
file = file_or_workbook.Fullname.tr('\\','/')
|
95
95
|
when Workbook
|
96
|
-
|
96
|
+
file = file_or_workbook.Fullname.tr('\\','/')
|
97
97
|
when String
|
98
98
|
file = file_or_workbook
|
99
99
|
raise FileNotFound, "file #{General.absolute_path(file).inspect} is a directory" if File.directory?(file)
|
@@ -105,9 +105,12 @@ module RobustExcelOle
|
|
105
105
|
book = nil
|
106
106
|
if opts[:force][:excel] != :new
|
107
107
|
# if readonly is true, then prefer a book that is given in force_excel if this option is set
|
108
|
-
forced_excel =
|
108
|
+
forced_excel = begin
|
109
109
|
(opts[:force][:excel].nil? || opts[:force][:excel] == :current) ?
|
110
|
-
(excel_class.new(:reuse => true) if !::CONNECT_JRUBY_BUG) :
|
110
|
+
(excel_class.new(:reuse => true) if !::CONNECT_JRUBY_BUG) : opts[:force][:excel].to_reo.excel
|
111
|
+
rescue NoMethodError
|
112
|
+
raise TypeREOError, "provided Excel option value is neither an Excel object nor a valid option"
|
113
|
+
end
|
111
114
|
begin
|
112
115
|
book = if File.exists?(file)
|
113
116
|
bookstore.fetch(file, :prefer_writable => !(opts[:read_only]),
|
@@ -115,7 +118,7 @@ module RobustExcelOle
|
|
115
118
|
end
|
116
119
|
rescue
|
117
120
|
raise
|
118
|
-
trace "#{$!.message}"
|
121
|
+
#trace "#{$!.message}"
|
119
122
|
end
|
120
123
|
if book
|
121
124
|
set_was_open opts, book.alive?
|
@@ -125,12 +128,12 @@ module RobustExcelOle
|
|
125
128
|
!(book.alive? && !book.saved && (opts[:if_unsaved] != :accept))
|
126
129
|
opts[:force][:excel] = book.excel if book.excel && book.excel.alive?
|
127
130
|
book.ensure_workbook(file,opts)
|
128
|
-
book.
|
131
|
+
book.send :apply_options, file, opts
|
129
132
|
return book
|
130
133
|
end
|
131
134
|
end
|
132
135
|
end
|
133
|
-
super(file_or_workbook, opts
|
136
|
+
super(file_or_workbook, opts)
|
134
137
|
end
|
135
138
|
|
136
139
|
singleton_class.send :alias_method, :open, :new
|
@@ -141,25 +144,23 @@ module RobustExcelOle
|
|
141
144
|
# @param [Hash] opts
|
142
145
|
# @option opts [Symbol] see above
|
143
146
|
# @return [Workbook] a workbook
|
144
|
-
def initialize(file_or_workbook,
|
147
|
+
def initialize(file_or_workbook, opts)
|
145
148
|
if file_or_workbook.is_a? WIN32OLE
|
146
149
|
@ole_workbook = file_or_workbook
|
147
|
-
ole_excel = begin
|
148
|
-
|
149
|
-
rescue
|
150
|
+
ole_excel = begin
|
151
|
+
@ole_workbook.Application
|
152
|
+
rescue WIN32OLERuntimeError
|
150
153
|
raise ExcelREOError, 'could not determine the Excel instance'
|
151
154
|
end
|
152
155
|
@excel = excel_class.new(ole_excel)
|
153
|
-
filename =
|
156
|
+
filename = @ole_workbook.Fullname.tr('\\','/')
|
154
157
|
else
|
155
158
|
filename = file_or_workbook
|
156
|
-
ensure_workbook(filename,
|
159
|
+
ensure_workbook(filename, opts)
|
157
160
|
end
|
158
|
-
|
161
|
+
apply_options(filename, opts)
|
159
162
|
store_myself
|
160
|
-
|
161
|
-
address_class.new(r1c1_letters)
|
162
|
-
if block
|
163
|
+
if block_given?
|
163
164
|
begin
|
164
165
|
yield self
|
165
166
|
ensure
|
@@ -170,28 +171,21 @@ module RobustExcelOle
|
|
170
171
|
|
171
172
|
private
|
172
173
|
|
173
|
-
# @private
|
174
174
|
def self.set_was_open(hash, value)
|
175
175
|
hash[:was_open] = value if hash.has_key?(:was_open)
|
176
176
|
end
|
177
177
|
|
178
|
-
# @private
|
179
178
|
def set_was_open(hash, value)
|
180
179
|
self.class.set_was_open(hash, value)
|
181
180
|
end
|
182
181
|
|
183
|
-
# @private
|
184
|
-
# translates abbreviations and synonyms and merges with default options
|
185
182
|
def self.process_options(opts, proc_opts = {:use_defaults => true})
|
186
183
|
translate(opts)
|
187
184
|
default_opts = (proc_opts[:use_defaults] ? DEFAULT_OPEN_OPTS : CORE_DEFAULT_OPEN_OPTS).dup
|
188
185
|
translate(default_opts)
|
189
|
-
opts.merge!(default_opts) {|key, v1, v2| v1 }
|
190
|
-
opts[:default] = default_opts[:default].merge(opts[:default]) unless opts[:default].nil?
|
191
|
-
opts[:force] = default_opts[:force].merge(opts[:force]) unless opts[:force].nil?
|
186
|
+
opts.merge!(default_opts) { |key, v1, v2| !v2.is_a?(Hash) ? v1 : v2.merge(v1 || {}) }
|
192
187
|
end
|
193
188
|
|
194
|
-
# @private
|
195
189
|
def self.translate(opts)
|
196
190
|
erg = {}
|
197
191
|
opts.each do |key,value|
|
@@ -219,34 +213,26 @@ module RobustExcelOle
|
|
219
213
|
opts[:force][:excel] = :current if opts[:force][:excel] == :reuse || opts[:force][:excel] == :active
|
220
214
|
end
|
221
215
|
|
222
|
-
# returns an Excel object when given Excel, Workbook or Win32ole object representing a Workbook or an Excel
|
223
|
-
# @private
|
224
|
-
def self.excel_of(object)
|
225
|
-
begin
|
226
|
-
object = object.to_reo if object.is_a? WIN32OLE
|
227
|
-
object.excel
|
228
|
-
rescue
|
229
|
-
raise TypeREOError, 'given object is neither an Excel, a Workbook, nor a Win32ole'
|
230
|
-
end
|
231
|
-
end
|
232
|
-
|
233
216
|
public
|
234
217
|
|
235
218
|
# @private
|
236
219
|
# ensures an excel but not for jruby if current Excel shall be used
|
237
220
|
def ensure_excel(options)
|
238
221
|
return if @excel && @excel.alive?
|
239
|
-
excel_option = options[:force][:excel]
|
222
|
+
excel_option = options[:force][:excel] || options[:default][:excel] || :current
|
240
223
|
@excel = if excel_option == :new
|
241
224
|
excel_class.new(:reuse => false)
|
242
|
-
elsif excel_option
|
225
|
+
elsif excel_option == :current
|
243
226
|
excel_class.new(:reuse => true)
|
227
|
+
elsif excel_option.respond_to?(:to_reo)
|
228
|
+
excel_option.to_reo.excel
|
244
229
|
else
|
245
|
-
|
230
|
+
raise TypeREOError, "provided Excel option value is neither an Excel object nor a valid option"
|
246
231
|
end
|
247
|
-
raise ExcelREOError, "
|
232
|
+
raise ExcelREOError, "Excel is not alive" unless @excel && @excel.alive?
|
248
233
|
end
|
249
234
|
|
235
|
+
|
250
236
|
# @private
|
251
237
|
def ensure_workbook(filename, options)
|
252
238
|
set_was_open options, true
|
@@ -263,12 +249,12 @@ module RobustExcelOle
|
|
263
249
|
workbooks = @excel.Workbooks
|
264
250
|
@ole_workbook = workbooks.Item(File.basename(filename)) rescue nil if @ole_workbook.nil?
|
265
251
|
if @ole_workbook && alive?
|
266
|
-
set_was_open options, true
|
252
|
+
set_was_open options, true
|
267
253
|
manage_blocking_or_unsaved_workbook(filename,options)
|
268
254
|
open_or_create_workbook(filename,options) if @ole_workbook.ReadOnly != options[:read_only]
|
269
255
|
else
|
270
|
-
if excel_option.nil? || excel_option == :current &&
|
271
|
-
(
|
256
|
+
if (excel_option.nil? || excel_option == :current) &&
|
257
|
+
!(::CONNECT_JRUBY_BUG && filename[0] == '/')
|
272
258
|
connect(filename,options)
|
273
259
|
else
|
274
260
|
open_or_create_workbook(filename,options)
|
@@ -276,11 +262,14 @@ module RobustExcelOle
|
|
276
262
|
end
|
277
263
|
end
|
278
264
|
|
279
|
-
|
280
|
-
|
281
|
-
|
265
|
+
private
|
266
|
+
|
267
|
+
# applies options to workbook named with filename
|
268
|
+
def apply_options(filename, options)
|
269
|
+
# changing read-only mode
|
270
|
+
#ensure_workbook(filename, options) if options[:read_only] && options[:read_only] != @ole_workbook.ReadOnly
|
282
271
|
if (!options[:read_only].nil?) && options[:read_only] != @ole_workbook.ReadOnly
|
283
|
-
ensure_workbook(filename, options)
|
272
|
+
ensure_workbook(filename, options)
|
284
273
|
end
|
285
274
|
retain_saved do
|
286
275
|
self.visible = options[:force][:visible].nil? ? @excel.Visible : options[:force][:visible]
|
@@ -289,36 +278,32 @@ module RobustExcelOle
|
|
289
278
|
end
|
290
279
|
end
|
291
280
|
|
292
|
-
private
|
293
|
-
|
294
|
-
# @private
|
295
281
|
# connects to an unknown workbook
|
296
|
-
def connect(filename,options)
|
282
|
+
def connect(filename, options)
|
297
283
|
workbooks_number = excel_class.excels_number==0 ? 0 : excel_class.current.Workbooks.Count
|
298
284
|
@ole_workbook = begin
|
299
285
|
WIN32OLE.connect(General.absolute_path(filename))
|
300
286
|
rescue
|
301
287
|
if $!.message =~ /moniker/
|
302
|
-
raise WorkbookConnectingBlockingError
|
303
|
-
else
|
304
|
-
raise WorkbookConnectingUnknownError
|
288
|
+
raise WorkbookConnectingBlockingError, "some workbook is blocking when connecting"
|
289
|
+
else
|
290
|
+
raise WorkbookConnectingUnknownError, "unknown error when connecting to a workbook"
|
305
291
|
end
|
306
292
|
end
|
307
293
|
ole_excel = begin
|
308
294
|
@ole_workbook.Application
|
309
295
|
rescue
|
310
296
|
if $!.message =~ /dispid/
|
311
|
-
raise WorkbookConnectingUnsavedError
|
312
|
-
else
|
313
|
-
raise WorkbookConnectingUnknownError
|
297
|
+
raise WorkbookConnectingUnsavedError, "workbook is unsaved when connecting"
|
298
|
+
else
|
299
|
+
raise WorkbookConnectingUnknownError, "unknown error when connecting to a workbook"
|
314
300
|
end
|
315
301
|
end
|
316
302
|
set_was_open options, (ole_excel.Workbooks.Count == workbooks_number)
|
317
303
|
@excel = excel_class.new(ole_excel)
|
318
304
|
end
|
319
305
|
|
320
|
-
|
321
|
-
def manage_nonexisting_file(filename,options)
|
306
|
+
def manage_nonexisting_file(filename, options)
|
322
307
|
return if File.exist?(filename)
|
323
308
|
abs_filename = General.absolute_path(filename)
|
324
309
|
if options[:if_absent] == :create
|
@@ -336,8 +321,7 @@ module RobustExcelOle
|
|
336
321
|
end
|
337
322
|
end
|
338
323
|
|
339
|
-
|
340
|
-
def manage_blocking_or_unsaved_workbook(filename,options)
|
324
|
+
def manage_blocking_or_unsaved_workbook(filename, options)
|
341
325
|
filename = General.absolute_path(filename)
|
342
326
|
filename = General.canonize(filename)
|
343
327
|
previous_file = General.canonize(@ole_workbook.Fullname)
|
@@ -354,8 +338,7 @@ module RobustExcelOle
|
|
354
338
|
end
|
355
339
|
end
|
356
340
|
|
357
|
-
|
358
|
-
def manage_blocking_workbook(filename,options)
|
341
|
+
def manage_blocking_workbook(filename, options)
|
359
342
|
case options[:if_obstructed]
|
360
343
|
when :raise
|
361
344
|
raise WorkbookBlocked, "can't open workbook #{filename},
|
@@ -369,7 +352,8 @@ module RobustExcelOle
|
|
369
352
|
manage_saving_workbook(filename, options)
|
370
353
|
when :close_if_saved
|
371
354
|
if !@ole_workbook.Saved
|
372
|
-
raise WorkbookBlocked, "workbook with the same name in a different path is unsaved: #{@ole_workbook.Fullname.tr('\\','/')}"
|
355
|
+
raise WorkbookBlocked, "workbook with the same name in a different path is unsaved: #{@ole_workbook.Fullname.tr('\\','/')}" +
|
356
|
+
"\nHint: Use the option :if_blocked => :save to save the workbook"
|
373
357
|
else
|
374
358
|
manage_forgetting_workbook(filename, options)
|
375
359
|
end
|
@@ -381,15 +365,14 @@ module RobustExcelOle
|
|
381
365
|
end
|
382
366
|
end
|
383
367
|
|
384
|
-
|
385
|
-
def manage_unsaved_workbook(filename,options)
|
368
|
+
def manage_unsaved_workbook(filename, options)
|
386
369
|
case options[:if_unsaved]
|
387
370
|
when :raise
|
388
371
|
raise WorkbookNotSaved, "workbook is already open but not saved: #{File.basename(filename).inspect}" +
|
389
372
|
"\nHint: Save the workbook or open the workbook using option :if_unsaved with values :forget and :accept to
|
390
373
|
close the unsaved workbook and reopen it, or to let the unsaved workbook open, respectively"
|
391
374
|
when :forget
|
392
|
-
manage_forgetting_workbook(filename,options)
|
375
|
+
manage_forgetting_workbook(filename, options)
|
393
376
|
when :accept
|
394
377
|
# do nothing
|
395
378
|
when :save
|
@@ -404,27 +387,23 @@ module RobustExcelOle
|
|
404
387
|
end
|
405
388
|
end
|
406
389
|
|
407
|
-
# @private
|
408
390
|
def manage_forgetting_workbook(filename, options)
|
409
391
|
@excel.with_displayalerts(false) { @ole_workbook.Close }
|
410
392
|
@ole_workbook = nil
|
411
393
|
open_or_create_workbook(filename, options)
|
412
394
|
end
|
413
395
|
|
414
|
-
# @private
|
415
396
|
def manage_saving_workbook(filename, options)
|
416
397
|
save unless @ole_workbook.Saved
|
417
398
|
manage_forgetting_workbook(filename, options)
|
418
399
|
end
|
419
400
|
|
420
|
-
# @private
|
421
401
|
def manage_new_excel(filename, options)
|
422
402
|
@excel = excel_class.new(:reuse => false)
|
423
403
|
@ole_workbook = nil
|
424
404
|
open_or_create_workbook(filename, options)
|
425
405
|
end
|
426
406
|
|
427
|
-
# @private
|
428
407
|
def open_or_create_workbook(filename, options)
|
429
408
|
return if @ole_workbook && options[:if_unsaved] != :alert && options[:if_unsaved] != :excel &&
|
430
409
|
(options[:read_only].nil? || options[:read_only]==@ole_workbook.ReadOnly )
|
@@ -460,7 +439,6 @@ module RobustExcelOle
|
|
460
439
|
end
|
461
440
|
end
|
462
441
|
|
463
|
-
# @private
|
464
442
|
# translating the option UpdateLinks from REO to VBA
|
465
443
|
# setting UpdateLinks works only if calculation mode is automatic,
|
466
444
|
# parameter 'UpdateLinks' has no effect
|
@@ -473,7 +451,6 @@ module RobustExcelOle
|
|
473
451
|
end
|
474
452
|
end
|
475
453
|
|
476
|
-
# @private
|
477
454
|
# workaround for linked workbooks for Excel 2007:
|
478
455
|
# opening and closing a dummy workbook if Excel has no workbooks.
|
479
456
|
# delay: with visible: 0.2 sec, without visible almost none
|
@@ -537,13 +514,10 @@ module RobustExcelOle
|
|
537
514
|
else
|
538
515
|
close_workbook
|
539
516
|
end
|
540
|
-
# trace "close: canceled by user" if alive? &&
|
541
|
-
# (opts[:if_unsaved] == :alert || opts[:if_unsaved] == :excel) && (not @ole_workbook.Saved)
|
542
517
|
end
|
543
518
|
|
544
519
|
private
|
545
520
|
|
546
|
-
# @private
|
547
521
|
def close_workbook
|
548
522
|
@ole_workbook.Close if alive?
|
549
523
|
@ole_workbook = nil unless alive?
|
@@ -596,7 +570,8 @@ module RobustExcelOle
|
|
596
570
|
self.class.unobtrusively_opening(file, opts, alive?, &block)
|
597
571
|
end
|
598
572
|
|
599
|
-
|
573
|
+
private
|
574
|
+
|
600
575
|
def self.unobtrusively_opening(file, opts, book_is_alive, &block)
|
601
576
|
process_options(opts)
|
602
577
|
opts = {:if_closed => :current, :keep_open => false}.merge(opts)
|
@@ -620,15 +595,15 @@ module RobustExcelOle
|
|
620
595
|
was_saved = book.saved
|
621
596
|
was_check_compatibility = book.check_compatibility
|
622
597
|
was_calculation = book.excel.properties[:calculation]
|
623
|
-
book.
|
598
|
+
book.send :apply_options, file, opts
|
624
599
|
yield book
|
625
600
|
ensure
|
626
601
|
if book && book.alive?
|
627
602
|
do_not_write = opts[:read_only] || opts[:writable]==false
|
628
603
|
book.save unless book.saved || do_not_write || !book.writable
|
629
604
|
if (opts[:read_only] && was_writable) || (!opts[:read_only] && !was_writable)
|
630
|
-
book.
|
631
|
-
|
605
|
+
book.send :apply_options, file, opts.merge({:read_only => !was_writable,
|
606
|
+
:if_unsaved => (opts[:writable]==false ? :forget : :save)})
|
632
607
|
end
|
633
608
|
was_open = open_opts[:was_open]
|
634
609
|
if was_open
|
@@ -642,6 +617,8 @@ module RobustExcelOle
|
|
642
617
|
end
|
643
618
|
end
|
644
619
|
|
620
|
+
public
|
621
|
+
|
645
622
|
# reopens a closed workbook
|
646
623
|
# @options options
|
647
624
|
def reopen(options = { })
|
@@ -655,10 +632,6 @@ module RobustExcelOle
|
|
655
632
|
def save(opts = { }) # option opts is deprecated #
|
656
633
|
raise ObjectNotAlive, 'workbook is not alive' unless alive?
|
657
634
|
raise WorkbookReadOnly, 'Not opened for writing (opened with :read_only option)' if @ole_workbook.ReadOnly
|
658
|
-
# if you have open the workbook with :read_only => true,
|
659
|
-
# then you could close the workbook and open it again with option :read_only => false
|
660
|
-
# otherwise the workbook may already be open writable in an another Excel instance
|
661
|
-
# then you could use this workbook or close the workbook there
|
662
635
|
begin
|
663
636
|
@ole_workbook.Save
|
664
637
|
rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException => msg
|
@@ -748,12 +721,6 @@ module RobustExcelOle
|
|
748
721
|
|
749
722
|
private
|
750
723
|
|
751
|
-
def store_myself
|
752
|
-
bookstore.store(self)
|
753
|
-
@stored_filename = filename
|
754
|
-
end
|
755
|
-
|
756
|
-
# @private
|
757
724
|
def save_as_workbook(file, options)
|
758
725
|
dirname, basename = File.split(file)
|
759
726
|
file_format =
|
@@ -773,6 +740,11 @@ module RobustExcelOle
|
|
773
740
|
end
|
774
741
|
end
|
775
742
|
|
743
|
+
def store_myself
|
744
|
+
bookstore.store(self)
|
745
|
+
@stored_filename = filename
|
746
|
+
end
|
747
|
+
|
776
748
|
public
|
777
749
|
|
778
750
|
# closes a given file if it is open
|
@@ -842,35 +814,23 @@ module RobustExcelOle
|
|
842
814
|
last_sheet_local = last_sheet
|
843
815
|
after_or_before, base_sheet = opts.to_a.first || [:after, last_sheet_local]
|
844
816
|
begin
|
845
|
-
if !::COPYSHEETS_JRUBY_BUG
|
846
|
-
if sheet
|
847
|
-
|
848
|
-
else
|
849
|
-
|
850
|
-
|
851
|
-
|
817
|
+
if !::COPYSHEETS_JRUBY_BUG
|
818
|
+
#if sheet
|
819
|
+
# sheet.Copy({ after_or_before.to_s => base_sheet.ole_worksheet })
|
820
|
+
#else
|
821
|
+
# ole_workbook.Worksheets.Add({ after_or_before.to_s => base_sheet.ole_worksheet })
|
822
|
+
#end
|
823
|
+
add_or_copy_sheet_simple(sheet, { after_or_before.to_s => base_sheet.ole_worksheet })
|
852
824
|
else
|
853
825
|
if after_or_before == :before
|
854
|
-
|
855
|
-
|
856
|
-
else
|
857
|
-
ole_workbook.Worksheets.Add(base_sheet.ole_worksheet)
|
858
|
-
end
|
826
|
+
#add_or_copy_sheet_simple(sheet,base_sheet)
|
827
|
+
add_or_copy_sheet_simple(sheet, base_sheet.ole_worksheet)
|
859
828
|
else
|
860
|
-
#not_given = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_NULL)
|
861
|
-
#ole_workbook.Worksheets.Add(not_given,base_sheet.ole_worksheet)
|
862
829
|
if base_sheet.name != last_sheet_local.name
|
863
|
-
|
864
|
-
sheet.Copy(base_sheet.Next)
|
865
|
-
else
|
866
|
-
ole_workbook.Worksheets.Add(base_sheet.Next)
|
867
|
-
end
|
830
|
+
add_or_copy_sheet_simple(sheet, base_sheet.Next)
|
868
831
|
else
|
869
|
-
|
870
|
-
|
871
|
-
else
|
872
|
-
ole_workbook.Worksheets.Add(base_sheet.ole_worksheet)
|
873
|
-
end
|
832
|
+
#add_or_copy_sheet_simple(sheet,base_sheet)
|
833
|
+
add_or_copy_sheet_simple(sheet, base_sheet.ole_worksheet)
|
874
834
|
base_sheet.Move(ole_workbook.Worksheets.Item(ole_workbook.Worksheets.Count-1))
|
875
835
|
ole_workbook.Worksheets.Item(ole_workbook.Worksheets.Count).Activate
|
876
836
|
end
|
@@ -879,12 +839,31 @@ module RobustExcelOle
|
|
879
839
|
rescue WIN32OLERuntimeError, NameNotFound, Java::OrgRacobCom::ComFailException
|
880
840
|
raise WorksheetREOError, "could not add given worksheet #{sheet.inspect}"
|
881
841
|
end
|
882
|
-
|
883
|
-
new_sheet = worksheet_class.new(ole_sheet)
|
842
|
+
new_sheet = worksheet_class.new(ole_workbook.Activesheet)
|
884
843
|
new_sheet.name = new_sheet_name if new_sheet_name
|
885
844
|
new_sheet
|
886
845
|
end
|
887
846
|
|
847
|
+
private
|
848
|
+
|
849
|
+
#def add_or_copy_sheet_simple(sheet, base_sheet)
|
850
|
+
# if sheet
|
851
|
+
# sheet.Copy(base_sheet.ole_worksheet)
|
852
|
+
# else
|
853
|
+
# ole_workbook.Worksheets.Add(base_sheet.ole_worksheet)
|
854
|
+
# end
|
855
|
+
#end
|
856
|
+
|
857
|
+
def add_or_copy_sheet_simple(sheet, base_ole_worksheet)
|
858
|
+
if sheet
|
859
|
+
sheet.Copy(base_ole_worksheet)
|
860
|
+
else
|
861
|
+
ole_workbook.Worksheets.Add(base_ole_worksheet)
|
862
|
+
end
|
863
|
+
end
|
864
|
+
|
865
|
+
public
|
866
|
+
|
888
867
|
# for compatibility to older versions
|
889
868
|
def add_sheet(sheet = nil, opts = { })
|
890
869
|
add_or_copy_sheet(sheet, opts)
|
@@ -914,7 +893,7 @@ module RobustExcelOle
|
|
914
893
|
# @param [String] name the name of the range
|
915
894
|
# @param [Variant] value the contents of the range
|
916
895
|
def []= (name, value)
|
917
|
-
set_namevalue_glob(name,value
|
896
|
+
set_namevalue_glob(name, value, :color => 42)
|
918
897
|
end
|
919
898
|
|
920
899
|
# sets options
|
@@ -922,19 +901,7 @@ module RobustExcelOle
|
|
922
901
|
def for_this_workbook(opts)
|
923
902
|
return unless alive?
|
924
903
|
self.class.process_options(opts, :use_defaults => false)
|
925
|
-
|
926
|
-
check_compatibility_before = check_compatibility
|
927
|
-
unless opts[:read_only].nil?
|
928
|
-
# if the ReadOnly status shall be changed, then close and reopen it
|
929
|
-
if (!writable && !(opts[:read_only])) || (writable && opts[:read_only])
|
930
|
-
opts[:check_compatibility] = check_compatibility if opts[:check_compatibility].nil?
|
931
|
-
close(:if_unsaved => true)
|
932
|
-
open_or_create_workbook(@stored_filename, opts)
|
933
|
-
end
|
934
|
-
end
|
935
|
-
self.visible = opts[:force][:visible].nil? ? visible_before : opts[:force][:visible]
|
936
|
-
self.CheckCompatibility = opts[:check_compatibility].nil? ? check_compatibility_before : opts[:check_compatibility]
|
937
|
-
@excel.calculation = opts[:calculation] unless opts[:calculation].nil?
|
904
|
+
self.send :apply_options, @stored_filename, opts
|
938
905
|
end
|
939
906
|
|
940
907
|
# brings workbook to foreground, makes it available for heyboard inputs, makes the Excel instance visible
|
@@ -950,7 +917,6 @@ module RobustExcelOle
|
|
950
917
|
true
|
951
918
|
rescue
|
952
919
|
@ole_workbook = nil # dead object won't be alive again
|
953
|
-
# t $!.message
|
954
920
|
false
|
955
921
|
end
|
956
922
|
|
@@ -1012,6 +978,7 @@ module RobustExcelOle
|
|
1012
978
|
self.filename == other_book.filename
|
1013
979
|
end
|
1014
980
|
|
981
|
+
# @private
|
1015
982
|
def self.books
|
1016
983
|
bookstore.books
|
1017
984
|
end
|
@@ -1062,16 +1029,6 @@ module RobustExcelOle
|
|
1062
1029
|
end
|
1063
1030
|
end
|
1064
1031
|
|
1065
|
-
# @private
|
1066
|
-
def self.address_class
|
1067
|
-
@address_class ||= begin
|
1068
|
-
module_name = self.parent_name
|
1069
|
-
"#{module_name}::Address".constantize
|
1070
|
-
rescue NameError => e
|
1071
|
-
Address
|
1072
|
-
end
|
1073
|
-
end
|
1074
|
-
|
1075
1032
|
# @private
|
1076
1033
|
def excel_class
|
1077
1034
|
self.class.excel_class
|
@@ -1082,11 +1039,6 @@ module RobustExcelOle
|
|
1082
1039
|
self.class.worksheet_class
|
1083
1040
|
end
|
1084
1041
|
|
1085
|
-
# @private
|
1086
|
-
def address_class
|
1087
|
-
self.class.address_class
|
1088
|
-
end
|
1089
|
-
|
1090
1042
|
include MethodHelpers
|
1091
1043
|
|
1092
1044
|
private
|
@@ -1116,6 +1068,47 @@ module RobustExcelOle
|
|
1116
1068
|
|
1117
1069
|
public
|
1118
1070
|
|
1071
|
+
# @private
|
1072
|
+
class WorkbookBlocked < WorkbookREOError
|
1073
|
+
end
|
1074
|
+
|
1075
|
+
# @private
|
1076
|
+
class WorkbookNotSaved < WorkbookREOError
|
1077
|
+
end
|
1078
|
+
|
1079
|
+
# @private
|
1080
|
+
class WorkbookReadOnly < WorkbookREOError
|
1081
|
+
end
|
1082
|
+
|
1083
|
+
# @private
|
1084
|
+
class WorkbookBeingUsed < WorkbookREOError
|
1085
|
+
end
|
1086
|
+
|
1087
|
+
# @private
|
1088
|
+
class WorkbookConnectingUnsavedError < WorkbookREOError
|
1089
|
+
end
|
1090
|
+
|
1091
|
+
# @private
|
1092
|
+
class WorkbookConnectingBlockingError < WorkbookREOError
|
1093
|
+
end
|
1094
|
+
|
1095
|
+
# @private
|
1096
|
+
class WorkbookConnectingUnknownError < WorkbookREOError
|
1097
|
+
end
|
1098
|
+
|
1099
|
+
# @private
|
1100
|
+
class FileAlreadyExists < FileREOError
|
1101
|
+
end
|
1102
|
+
|
1103
|
+
# @private
|
1104
|
+
class FileNameNotGiven < FileREOError
|
1105
|
+
end
|
1106
|
+
|
1107
|
+
# @private
|
1108
|
+
class FileNotFound < FileREOError
|
1109
|
+
end
|
1110
|
+
|
1111
|
+
|
1119
1112
|
Book = Workbook
|
1120
1113
|
|
1121
1114
|
end
|