robust_excel_ole 1.12 → 1.13
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.rdoc +3 -17
- data/lib/robust_excel_ole/cell.rb +10 -6
- data/lib/robust_excel_ole/excel.rb +13 -10
- data/lib/robust_excel_ole/general.rb +8 -0
- data/lib/robust_excel_ole/range.rb +18 -13
- data/lib/robust_excel_ole/range_owners.rb +20 -20
- data/lib/robust_excel_ole/version.rb +1 -1
- data/lib/robust_excel_ole/workbook.rb +82 -75
- data/lib/robust_excel_ole/worksheet.rb +13 -9
- data/robust_excel_ole.gemspec +6 -4
- data/spec/bookstore_spec.rb +1 -0
- data/spec/cell_spec.rb +1 -0
- data/spec/data/workbook.xls +0 -0
- data/spec/excel_spec.rb +31 -30
- data/spec/range_spec.rb +1 -0
- data/spec/workbook_spec.rb +38 -0
- data/spec/workbook_specs/workbook_open_spec.rb +42 -7
- data/spec/workbook_specs/workbook_save_spec.rb +1 -0
- data/spec/worksheet_spec.rb +6 -6
- metadata +9 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f76aadd233f6dd4c2f5d568d54ef10c6c030762544906a3357c7f04464e24846
|
4
|
+
data.tar.gz: 68101beb84d01cd1b2da24c4568a833d5b6d641c5829b3b7e1da793c651a1aa3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8b79a216b5460efd0b51ff81c335e53c37d8c7530185838f88e7befc0eacbd686338d7578ffee7db399795427c0983abc091a2c673230e126d01ff335e1cb80f
|
7
|
+
data.tar.gz: 55c8c0bb5a58d2574bf2938333e551e91402e7eb75eb40bc380fc3eee998766aa693f7e4eb5f615ad21f2c9882376259c900b813541547f47b0f3d071121cc10
|
data/README.rdoc
CHANGED
@@ -65,7 +65,7 @@ Let's open a workbook.
|
|
65
65
|
Now we have a Workbook object that wraps a win32ole object. That is, you can send any win32ole (VBA) method to it. See
|
66
66
|
https://docs.microsoft.com/en-us/office/vba/api/excel.workbook#methods.
|
67
67
|
|
68
|
-
For example, you can determine the name and the
|
68
|
+
For example, you can determine the name and the visible status of the workbook.
|
69
69
|
|
70
70
|
workbook.Name
|
71
71
|
# => "workbook.xls"
|
@@ -198,12 +198,6 @@ For hard terminating all Excel processes we can use
|
|
198
198
|
|
199
199
|
For more details about creating Excel instances see README_excel[https://github.com/Thomas008/robust_excel_ole/blob/master/README/README_excel_rdoc]
|
200
200
|
|
201
|
-
=== Generating a new workbook
|
202
|
-
|
203
|
-
You can creata a new, empty workbook by
|
204
|
-
|
205
|
-
Excel.generate_workbook('spec/data/new_workbook.xls')
|
206
|
-
|
207
201
|
=== Opening workbooks in several Excel instances
|
208
202
|
|
209
203
|
RobustExcelOle enables opening and processing workbooks in several Excel instances. Using more than one Excel process allows, e.g., running a script that operates in one Excel instance, while a user (or another script) modifies workbooks in another Excel instance.
|
@@ -317,19 +311,10 @@ and set another value to that range.
|
|
317
311
|
|
318
312
|
For more details about reading and writing contents of cells and ranges see {README_ranges}[https://github.com/Thomas008/robust_excel_ole/blob/master/docs/README_ranges.rdoc]
|
319
313
|
|
320
|
-
=== Running in jruby
|
321
|
-
|
322
|
-
RobustExcelOle runs in jruby as well. You can call the console via the command +jreo+. We implemented workarounds to cope with some restrictions of the library jruby-win32ole. Some issues still remain when running under jruby. So you might consider the following points when running RobustExcelOle under jruby:
|
323
|
-
|
324
|
-
1. +Excel.current+ or +Excel.new(:reuse => true)+ does not connect to an already running Excel instance, unless some workbook has been opened via RobustExcelOle.
|
325
|
-
|
326
|
-
2. Use +Excel.kill_all+ instead of +Excel.close_all+. +Excel.close_all does not work yet. It relies on stepping through all heap objects in ObjectSpace. In jruby ObjectSpace is disabled. Each_object will only work with Class.
|
327
|
-
|
328
|
-
3. When providing an absolute path, you have to state the "/" ("C:/abc.xls" works, "C:abc" does not work).
|
329
314
|
|
330
315
|
=== More things
|
331
316
|
|
332
|
-
You can convert
|
317
|
+
You can convert some win32ole objects into a RobustExcelOle object.
|
333
318
|
|
334
319
|
range = sheet.Names.Item("firstcell").to_reo
|
335
320
|
|
@@ -339,6 +324,7 @@ You can run the examples included in the directory +examples+, e.g.
|
|
339
324
|
|
340
325
|
ruby examples\open_save_close\example_unobtrusively.rb
|
341
326
|
|
327
|
+
|
342
328
|
== Development
|
343
329
|
|
344
330
|
This project RobustExcelOle is work in progress. We are happy to implement further features. So we invite you to send your pull requests. We then strive to realize them as soon as possible. If you have any feedback, or you find use cases that RobustExcelOle does not satisfy, please let us know.
|
@@ -19,15 +19,19 @@ module RobustExcelOle
|
|
19
19
|
# @private
|
20
20
|
def method_missing(name, *args)
|
21
21
|
#if name.to_s[0,1] =~ /[A-Z]/
|
22
|
+
if JRUBY_BUG_ERRORMESSAGE
|
22
23
|
begin
|
23
24
|
@cell.send(name, *args)
|
24
|
-
rescue
|
25
|
-
|
26
|
-
raise VBAMethodMissingError, "unknown VBA property or method #{name.inspect}"
|
27
|
-
else
|
28
|
-
raise msg
|
29
|
-
end
|
25
|
+
rescue Java::OrgRacobCom::ComFailException
|
26
|
+
raise VBAMethodMissingError, "unknown VBA property or method #{name.inspect}"
|
30
27
|
end
|
28
|
+
else
|
29
|
+
begin
|
30
|
+
@cell.send(name, *args)
|
31
|
+
rescue NoMethodError
|
32
|
+
raise VBAMethodMissingError, "unknown VBA property or method #{name.inspect}"
|
33
|
+
end
|
34
|
+
end
|
31
35
|
# else
|
32
36
|
# super
|
33
37
|
# end
|
@@ -75,9 +75,8 @@ module RobustExcelOle
|
|
75
75
|
end
|
76
76
|
ole_xl = win32ole_excel unless win32ole_excel.nil?
|
77
77
|
options = { :reuse => true }.merge(options)
|
78
|
-
#ole_xl = current_excel if options[:reuse] == true
|
79
78
|
if options[:reuse] == true && ole_xl.nil?
|
80
|
-
ole_xl = if
|
79
|
+
ole_xl = if JRUBY_BUG_CONNECTEXCEL
|
81
80
|
excel_instance = known_excel_instance
|
82
81
|
excel_instance.ole_excel unless excel_instance.nil?
|
83
82
|
else
|
@@ -185,7 +184,7 @@ module RobustExcelOle
|
|
185
184
|
def ole_workbooks
|
186
185
|
ole_workbooks = begin
|
187
186
|
@ole_excel.Workbooks
|
188
|
-
rescue WIN32OLERuntimeError => msg
|
187
|
+
rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException => msg
|
189
188
|
if msg.message =~ /failed to get Dispatch Interface/
|
190
189
|
raise ExcelDamaged, 'Excel instance not alive or damaged'
|
191
190
|
else
|
@@ -724,14 +723,18 @@ module RobustExcelOle
|
|
724
723
|
# @private
|
725
724
|
def method_missing(name, *args)
|
726
725
|
if name.to_s[0,1] =~ /[A-Z]/
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
726
|
+
raise ObjectNotAlive, 'method missing: Excel not alive' unless alive?
|
727
|
+
if JRUBY_BUG_ERRORMESSAGE
|
728
|
+
begin
|
729
|
+
@ole_excel.send(name, *args)
|
730
|
+
rescue Java::OrgRacobCom::ComFailException => msg
|
731
|
+
raise VBAMethodMissingError, "unknown VBA property or method #{name.inspect}"
|
732
|
+
end
|
733
|
+
else
|
734
|
+
begin
|
735
|
+
@ole_excel.send(name, *args)
|
736
|
+
rescue NoMethodError
|
732
737
|
raise VBAMethodMissingError, "unknown VBA property or method #{name.inspect}"
|
733
|
-
else
|
734
|
-
raise msg
|
735
738
|
end
|
736
739
|
end
|
737
740
|
else
|
@@ -2,6 +2,14 @@
|
|
2
2
|
|
3
3
|
module General
|
4
4
|
|
5
|
+
IS_JRUBY_PLATFORM = (RUBY_PLATFORM =~ /java/)
|
6
|
+
JRUBY_BUG_CONNECT = IS_JRUBY_PLATFORM && true
|
7
|
+
JRUBY_BUG_COPYSHEETS = IS_JRUBY_PLATFORM && true
|
8
|
+
JRUBY_BUG_ERRORMESSAGE = IS_JRUBY_PLATFORM && true
|
9
|
+
JRUBY_BUG_CONNECTEXCEL = IS_JRUBY_PLATFORM && true
|
10
|
+
JRUBY_BUG_RANGES = IS_JRUBY_PLATFORM && true
|
11
|
+
|
12
|
+
|
5
13
|
# @private
|
6
14
|
def absolute_path(file)
|
7
15
|
file = File.expand_path(file)
|
@@ -27,7 +27,7 @@ module RobustExcelOle
|
|
27
27
|
# @returns [Array] the values
|
28
28
|
def values(range = nil)
|
29
29
|
#result = map { |x| x.Value }.flatten
|
30
|
-
result_unflatten = if
|
30
|
+
result_unflatten = if !JRUBY_BUG_RANGES
|
31
31
|
map { |x| x.v }
|
32
32
|
else
|
33
33
|
self.v
|
@@ -44,7 +44,7 @@ module RobustExcelOle
|
|
44
44
|
|
45
45
|
def v
|
46
46
|
begin
|
47
|
-
if
|
47
|
+
if !JRUBY_BUG_RANGES
|
48
48
|
self.Value
|
49
49
|
else
|
50
50
|
address_r1c1 = self.AddressLocal(true,true,XlR1C1)
|
@@ -57,14 +57,15 @@ module RobustExcelOle
|
|
57
57
|
end
|
58
58
|
values
|
59
59
|
end
|
60
|
-
rescue WIN32OLERuntimeError
|
60
|
+
rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException => msg
|
61
61
|
raise RangeNotEvaluatable, 'cannot read value'
|
62
62
|
end
|
63
|
+
|
63
64
|
end
|
64
65
|
|
65
66
|
def v=(value)
|
66
67
|
begin
|
67
|
-
if
|
68
|
+
if !JRUBY_BUG_RANGES
|
68
69
|
ole_range.Value = value
|
69
70
|
else
|
70
71
|
address_r1c1 = ole_range.AddressLocal(true,true,XlR1C1)
|
@@ -76,7 +77,7 @@ module RobustExcelOle
|
|
76
77
|
end
|
77
78
|
end
|
78
79
|
value
|
79
|
-
rescue
|
80
|
+
rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException => msg
|
80
81
|
raise RangeNotEvaluatable, "cannot assign value to range #{address_r1c1.inspect}"
|
81
82
|
end
|
82
83
|
end
|
@@ -156,7 +157,7 @@ module RobustExcelOle
|
|
156
157
|
end
|
157
158
|
end
|
158
159
|
end
|
159
|
-
rescue WIN32OLERuntimeError
|
160
|
+
rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException => msg
|
160
161
|
raise RangeNotCopied, 'cannot copy range'
|
161
162
|
end
|
162
163
|
end
|
@@ -208,7 +209,7 @@ module RobustExcelOle
|
|
208
209
|
end
|
209
210
|
end
|
210
211
|
end
|
211
|
-
rescue WIN32OLERuntimeError
|
212
|
+
rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException => msg
|
212
213
|
raise RangeNotCopied, 'cannot copy range'
|
213
214
|
end
|
214
215
|
end
|
@@ -239,13 +240,17 @@ module RobustExcelOle
|
|
239
240
|
# @private
|
240
241
|
def method_missing(name, *args)
|
241
242
|
if name.to_s[0,1] =~ /[A-Z]/
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
243
|
+
if JRUBY_BUG_ERRORMESSAGE
|
244
|
+
begin
|
245
|
+
@ole_range.send(name, *args)
|
246
|
+
rescue Java::OrgRacobCom::ComFailException
|
247
|
+
raise VBAMethodMissingError, "unknown VBA property or method #{name.inspect}"
|
248
|
+
end
|
249
|
+
else
|
250
|
+
begin
|
251
|
+
@ole_range.send(name, *args)
|
252
|
+
rescue NoMethodError
|
246
253
|
raise VBAMethodMissingError, "unknown VBA property or method #{name.inspect}"
|
247
|
-
else
|
248
|
-
raise msg
|
249
254
|
end
|
250
255
|
end
|
251
256
|
else
|
@@ -24,13 +24,13 @@ module RobustExcelOle
|
|
24
24
|
ole_range = name_obj.RefersToRange
|
25
25
|
value = begin
|
26
26
|
#name_obj.RefersToRange.Value
|
27
|
-
if
|
27
|
+
if !JRUBY_BUG_RANGES
|
28
28
|
ole_range.Value
|
29
29
|
else
|
30
30
|
values = RobustExcelOle::Range.new(ole_range).v
|
31
31
|
(values.size==1 && values.first.size==1) ? values.first.first : values
|
32
32
|
end
|
33
|
-
rescue WIN32OLERuntimeError
|
33
|
+
rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException
|
34
34
|
sheet = if self.is_a?(Worksheet) then self
|
35
35
|
elsif self.is_a?(Workbook) then self.sheet(1)
|
36
36
|
elsif self.is_a?(Excel) then self.workbook.sheet(1)
|
@@ -39,13 +39,13 @@ module RobustExcelOle
|
|
39
39
|
#sheet.Evaluate(name_obj.Name).Value
|
40
40
|
# does it result in a range?
|
41
41
|
ole_range = sheet.Evaluate(name_obj.Name)
|
42
|
-
if
|
42
|
+
if !JRUBY_BUG_RANGES
|
43
43
|
ole_range.Value
|
44
44
|
else
|
45
45
|
values = RobustExcelOle::Range.new(ole_range).v
|
46
46
|
(values.size==1 && values.first.size==1) ? values.first.first : values
|
47
47
|
end
|
48
|
-
rescue
|
48
|
+
rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException
|
49
49
|
return opts[:default] unless opts[:default] == :__not_provided
|
50
50
|
raise RangeNotEvaluatable, "cannot evaluate range named #{name.inspect} in #{self}"
|
51
51
|
end
|
@@ -71,7 +71,7 @@ module RobustExcelOle
|
|
71
71
|
ole_range = name_object(name).RefersToRange
|
72
72
|
workbook.color_if_modified = opts[:color] unless opts[:color].nil?
|
73
73
|
ole_range.Interior.ColorIndex = workbook.color_if_modified unless workbook.color_if_modified.nil?
|
74
|
-
if
|
74
|
+
if !JRUBY_BUG_RANGES
|
75
75
|
ole_range.Value = value
|
76
76
|
else
|
77
77
|
address_r1c1 = ole_range.AddressLocal(true,true,XlR1C1)
|
@@ -83,7 +83,7 @@ module RobustExcelOle
|
|
83
83
|
end
|
84
84
|
end
|
85
85
|
value
|
86
|
-
rescue #
|
86
|
+
rescue #WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException
|
87
87
|
raise RangeNotEvaluatable, "cannot assign value to range named #{name.inspect} in #{self.inspect}"
|
88
88
|
end
|
89
89
|
end
|
@@ -100,19 +100,19 @@ module RobustExcelOle
|
|
100
100
|
return namevalue_glob(name, opts) if self.is_a?(Workbook)
|
101
101
|
begin
|
102
102
|
ole_range = self.Range(name)
|
103
|
-
rescue # WIN32OLERuntimeError
|
103
|
+
rescue # WIN32OLERuntimeError, VBAMethodMissingError, Java::OrgRacobCom::ComFailException
|
104
104
|
return opts[:default] unless opts[:default] == :__not_provided
|
105
105
|
raise NameNotFound, "name #{name.inspect} not in #{self.inspect}"
|
106
106
|
end
|
107
107
|
begin
|
108
108
|
#value = ole_range.Value
|
109
|
-
value = if
|
109
|
+
value = if !JRUBY_BUG_RANGES
|
110
110
|
ole_range.Value
|
111
111
|
else
|
112
112
|
values = RobustExcelOle::Range.new(ole_range).v
|
113
113
|
(values.size==1 && values.first.size==1) ? values.first.first : values
|
114
114
|
end
|
115
|
-
rescue
|
115
|
+
rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException
|
116
116
|
return opts[:default] unless opts[:default] == :__not_provided
|
117
117
|
raise RangeNotEvaluatable, "cannot determine value of range named #{name.inspect} in #{self.inspect}"
|
118
118
|
end
|
@@ -131,13 +131,13 @@ module RobustExcelOle
|
|
131
131
|
begin
|
132
132
|
return set_namevalue_glob(name, value, opts) if self.is_a?(Workbook) # opts deprecated
|
133
133
|
ole_range = self.Range(name)
|
134
|
-
rescue
|
134
|
+
rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException
|
135
135
|
raise NameNotFound, "name #{name.inspect} not in #{self.inspect}"
|
136
136
|
end
|
137
137
|
begin
|
138
138
|
workbook.color_if_modified = opts[:color] unless opts[:color].nil?
|
139
139
|
ole_range.Interior.ColorIndex = workbook.color_if_modified unless workbook.color_if_modified.nil?
|
140
|
-
if
|
140
|
+
if !JRUBY_BUG_RANGES
|
141
141
|
ole_range.Value = value
|
142
142
|
else
|
143
143
|
address_r1c1 = ole_range.AddressLocal(true,true,XlR1C1)
|
@@ -149,7 +149,7 @@ module RobustExcelOle
|
|
149
149
|
end
|
150
150
|
end
|
151
151
|
value
|
152
|
-
rescue
|
152
|
+
rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException
|
153
153
|
raise RangeNotEvaluatable, "cannot assign value to range named #{name.inspect} in #{self.inspect}"
|
154
154
|
end
|
155
155
|
end
|
@@ -199,7 +199,7 @@ module RobustExcelOle
|
|
199
199
|
workbook.save
|
200
200
|
range
|
201
201
|
end
|
202
|
-
rescue WIN32OLERuntimeError
|
202
|
+
rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException
|
203
203
|
address2_string = address2.nil? ? "" : ", #{address2.inspect}"
|
204
204
|
raise RangeNotCreated, "cannot create range (#{name_or_address.inspect}#{address2_string})"
|
205
205
|
end
|
@@ -217,7 +217,7 @@ module RobustExcelOle
|
|
217
217
|
addr = [addr,addr_deprecated] unless addr_deprecated == :__not_provided
|
218
218
|
begin
|
219
219
|
self.Names.Add(name, nil, true, nil, nil, nil, nil, nil, nil, '=' + Address.r1c1(addr))
|
220
|
-
rescue
|
220
|
+
rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException
|
221
221
|
raise RangeNotEvaluatable, "cannot add name #{name.inspect} to range #{addr.inspect}"
|
222
222
|
end
|
223
223
|
name
|
@@ -233,12 +233,12 @@ module RobustExcelOle
|
|
233
233
|
def rename_range(name, new_name)
|
234
234
|
begin
|
235
235
|
item = self.Names.Item(name)
|
236
|
-
rescue
|
236
|
+
rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException => msg
|
237
237
|
raise NameNotFound, "name #{name.inspect} not in #{File.basename(self.stored_filename).inspect}"
|
238
238
|
end
|
239
239
|
begin
|
240
240
|
item.Name = new_name
|
241
|
-
rescue
|
241
|
+
rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException => msg
|
242
242
|
raise UnexpectedREOError, "name error in #{File.basename(self.stored_filename).inspect}"
|
243
243
|
end
|
244
244
|
end
|
@@ -249,12 +249,12 @@ module RobustExcelOle
|
|
249
249
|
def delete_name(name)
|
250
250
|
begin
|
251
251
|
item = self.Names.Item(name)
|
252
|
-
rescue WIN32OLERuntimeError
|
252
|
+
rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException
|
253
253
|
raise NameNotFound, "name #{name.inspect} not in #{File.basename(self.stored_filename).inspect}"
|
254
254
|
end
|
255
255
|
begin
|
256
256
|
item.Delete
|
257
|
-
rescue WIN32OLERuntimeError
|
257
|
+
rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException
|
258
258
|
raise UnexpectedREOError, "name error in #{File.basename(self.stored_filename).inspect}"
|
259
259
|
end
|
260
260
|
end
|
@@ -263,10 +263,10 @@ module RobustExcelOle
|
|
263
263
|
|
264
264
|
def name_object(name)
|
265
265
|
self.Names.Item(name)
|
266
|
-
rescue
|
266
|
+
rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException
|
267
267
|
begin
|
268
268
|
self.Parent.Names.Item(name)
|
269
|
-
rescue
|
269
|
+
rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException
|
270
270
|
raise RobustExcelOle::NameNotFound, "name #{name.inspect} not in #{self.inspect}"
|
271
271
|
end
|
272
272
|
end
|
@@ -22,16 +22,15 @@ module RobustExcelOle
|
|
22
22
|
DEFAULT_OPEN_OPTS = {
|
23
23
|
:default => {:excel => :current},
|
24
24
|
:force => {},
|
25
|
+
:update_links => :never,
|
25
26
|
:if_unsaved => :raise,
|
26
27
|
:if_obstructed => :raise,
|
27
28
|
:if_absent => :raise,
|
28
|
-
|
29
|
-
:check_compatibility => false
|
30
|
-
:update_links => :never,
|
31
|
-
:if_exists => :raise
|
29
|
+
:if_exists => :raise,
|
30
|
+
:check_compatibility => false
|
32
31
|
}.freeze
|
33
32
|
|
34
|
-
|
33
|
+
CORE_DEFAULT_OPEN_OPTS = {
|
35
34
|
:default => {:excel => :current}, :force => {}, :update_links => :never
|
36
35
|
}.freeze
|
37
36
|
|
@@ -83,16 +82,22 @@ module RobustExcelOle
|
|
83
82
|
# :check_compatibility true -> check compatibility when saving
|
84
83
|
# :update_links true -> user is being asked how to update links, false -> links are never updated
|
85
84
|
# @return [Workbook] a representation of a workbook
|
86
|
-
def self.
|
87
|
-
|
88
|
-
|
89
|
-
|
85
|
+
def self.new(file_or_workbook, opts = { }, &block)
|
86
|
+
options = process_options(opts)
|
87
|
+
if file_or_workbook.is_a? WIN32OLE
|
88
|
+
file = file_or_workbook.Fullname.tr('\\','/')
|
89
|
+
else
|
90
|
+
file = file_or_workbook
|
91
|
+
raise(FileNameNotGiven, 'filename is nil') if file.nil?
|
92
|
+
raise(FileNotFound, "file #{General.absolute_path(file).inspect} is a directory") if File.directory?(file)
|
93
|
+
end
|
94
|
+
# try to fetch the workbook from the bookstore
|
90
95
|
book = nil
|
91
96
|
if options[:force][:excel] != :new
|
92
97
|
# if readonly is true, then prefer a book that is given in force_excel if this option is set
|
93
98
|
forced_excel =
|
94
99
|
(options[:force][:excel].nil? || options[:force][:excel] == :current) ?
|
95
|
-
(excel_class.new(:reuse => true) if
|
100
|
+
(excel_class.new(:reuse => true) if !JRUBY_BUG_CONNECT) : excel_of(options[:force][:excel])
|
96
101
|
begin
|
97
102
|
book = if File.exists?(file)
|
98
103
|
bookstore.fetch(file, :prefer_writable => !(options[:read_only]),
|
@@ -108,13 +113,18 @@ module RobustExcelOle
|
|
108
113
|
!(book.alive? && !book.saved && (options[:if_unsaved] != :accept))
|
109
114
|
options[:force][:excel] = book.excel if book.excel && book.excel.alive?
|
110
115
|
book.ensure_workbook(file,options)
|
116
|
+
book.set_options(file,options)
|
111
117
|
return book
|
112
118
|
end
|
113
119
|
end
|
114
|
-
end
|
115
|
-
|
120
|
+
end
|
121
|
+
super(file_or_workbook, options, &block)
|
116
122
|
end
|
117
|
-
|
123
|
+
|
124
|
+
def self.open(file_or_workbook, opts = { }, &block)
|
125
|
+
new(file_or_workbook, opts, &block)
|
126
|
+
end
|
127
|
+
|
118
128
|
# creates a new Workbook object, if a file name is given
|
119
129
|
# Promotes the win32ole workbook to a Workbook object, if a win32ole-workbook is given
|
120
130
|
# @param [Variant] file_or_workbook file name or workbook
|
@@ -122,22 +132,21 @@ module RobustExcelOle
|
|
122
132
|
# @option opts [Symbol] see above
|
123
133
|
# @return [Workbook] a workbook
|
124
134
|
def initialize(file_or_workbook, options = { }, &block)
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
135
|
+
if file_or_workbook.is_a? WIN32OLE
|
136
|
+
@ole_workbook = file_or_workbook
|
137
|
+
ole_excel = begin
|
138
|
+
WIN32OLE.connect(@ole_workbook.Fullname).Application
|
139
|
+
rescue
|
140
|
+
raise ExcelREOError, 'could not determine the Excel instance'
|
141
|
+
end
|
131
142
|
@excel = excel_class.new(ole_excel)
|
132
|
-
filename =
|
133
|
-
set_options(filename, options)
|
143
|
+
filename = file_or_workbook.Fullname.tr('\\','/')
|
134
144
|
else
|
135
|
-
filename = file_or_workbook
|
136
|
-
|
137
|
-
|
138
|
-
|
145
|
+
filename = file_or_workbook
|
146
|
+
ensure_workbook(filename, options)
|
147
|
+
end
|
148
|
+
set_options(filename, options)
|
139
149
|
bookstore.store(self)
|
140
|
-
@modified_cells = []
|
141
150
|
@workbook = @excel.workbook = self
|
142
151
|
r1c1_letters = @ole_workbook.Worksheets.Item(1).Cells.Item(1,1).Address(true,true,XlR1C1).gsub(/[0-9]/,'') #('ReferenceStyle' => XlR1C1).gsub(/[0-9]/,'')
|
143
152
|
address_class.new(r1c1_letters)
|
@@ -149,7 +158,7 @@ module RobustExcelOle
|
|
149
158
|
end
|
150
159
|
end
|
151
160
|
end
|
152
|
-
|
161
|
+
|
153
162
|
private
|
154
163
|
|
155
164
|
# translates abbreviations and synonyms and merges with default options
|
@@ -181,7 +190,7 @@ module RobustExcelOle
|
|
181
190
|
erg
|
182
191
|
end
|
183
192
|
opts = translator.call(options)
|
184
|
-
default_open_opts = proc_opts[:use_defaults] ? DEFAULT_OPEN_OPTS :
|
193
|
+
default_open_opts = proc_opts[:use_defaults] ? DEFAULT_OPEN_OPTS : CORE_DEFAULT_OPEN_OPTS
|
185
194
|
default_opts = translator.call(default_open_opts)
|
186
195
|
opts = default_opts.merge(opts)
|
187
196
|
opts[:default] = default_opts[:default].merge(opts[:default]) unless opts[:default].nil?
|
@@ -210,8 +219,8 @@ module RobustExcelOle
|
|
210
219
|
@excel = if excel_option == :new
|
211
220
|
excel_class.new(:reuse => false)
|
212
221
|
elsif excel_option.nil? || excel_option == :current
|
213
|
-
excel_class.new(:reuse => true)
|
214
|
-
else
|
222
|
+
excel_class.new(:reuse => true)
|
223
|
+
else
|
215
224
|
self.class.excel_of(excel_option)
|
216
225
|
end
|
217
226
|
raise ExcelREOError, "excel is not alive" unless @excel && @excel.alive?
|
@@ -220,14 +229,15 @@ module RobustExcelOle
|
|
220
229
|
# @private
|
221
230
|
# restriction for jruby: does not manage conflicts with blocking or unsaved workbooks
|
222
231
|
def ensure_workbook(filename, options)
|
223
|
-
if options[:if_unsaved]==:accept &&
|
224
|
-
|
232
|
+
if options[:if_unsaved]==:accept &&
|
233
|
+
((options[:read_only]==true && self.ReadOnly==false) || (options[:read_only]==false && self.ReadOnly==true))
|
234
|
+
raise OptionInvalid, ":if_unsaved:accept and change of read-only mode is not possible"
|
225
235
|
end
|
226
236
|
unless @ole_workbook && alive?
|
227
237
|
filename = @stored_filename ? @stored_filename : filename
|
228
238
|
manage_nonexisting_file(filename,options)
|
229
|
-
excel_option = options[:force][:excel].nil? ? options[:default][:excel] : options[:force][:excel]
|
230
|
-
if
|
239
|
+
excel_option = options[:force][:excel].nil? ? options[:default][:excel] : options[:force][:excel]
|
240
|
+
if JRUBY_BUG_CONNECT
|
231
241
|
(excel_option.nil? || excel_option == :current) && filename[0] != '/'
|
232
242
|
begin
|
233
243
|
connect(filename,options)
|
@@ -247,8 +257,8 @@ module RobustExcelOle
|
|
247
257
|
if @ole_workbook
|
248
258
|
manage_blocking_or_unsaved_workbook(filename,options)
|
249
259
|
else
|
250
|
-
if excel_option.nil? || excel_option == :current &&
|
251
|
-
(
|
260
|
+
if excel_option.nil? || excel_option == :current &&
|
261
|
+
(!JRUBY_BUG_CONNECT || filename[0] != '/')
|
252
262
|
connect(filename,options)
|
253
263
|
else
|
254
264
|
open_or_create_workbook(filename,options)
|
@@ -256,7 +266,20 @@ module RobustExcelOle
|
|
256
266
|
end
|
257
267
|
end
|
258
268
|
end
|
259
|
-
|
269
|
+
end
|
270
|
+
|
271
|
+
# @private
|
272
|
+
def set_options(filename, options)
|
273
|
+
if (!options[:read_only].nil?) && options[:read_only] != @ole_workbook.ReadOnly
|
274
|
+
@excel.with_displayalerts(false) { @ole_workbook.Close }
|
275
|
+
@ole_workbook = nil
|
276
|
+
open_or_create_workbook(filename, options)
|
277
|
+
end
|
278
|
+
retain_saved do
|
279
|
+
self.visible = options[:force][:visible].nil? ? @excel.Visible : options[:force][:visible]
|
280
|
+
@excel.calculation = options[:calculation] unless options[:calculation].nil?
|
281
|
+
@ole_workbook.CheckCompatibility = options[:check_compatibility] unless options[:check_compatibility].nil?
|
282
|
+
end
|
260
283
|
end
|
261
284
|
|
262
285
|
private
|
@@ -296,7 +319,7 @@ module RobustExcelOle
|
|
296
319
|
empty_ole_workbook = excel.Workbooks.Item(excel.Workbooks.Count)
|
297
320
|
begin
|
298
321
|
empty_ole_workbook.SaveAs(abs_filename)
|
299
|
-
rescue
|
322
|
+
rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException => msg
|
300
323
|
raise FileNotFound, "could not save workbook with filename #{filename.inspect}"
|
301
324
|
end
|
302
325
|
else
|
@@ -398,7 +421,7 @@ module RobustExcelOle
|
|
398
421
|
abs_filename = General.absolute_path(filename)
|
399
422
|
begin
|
400
423
|
workbooks = @excel.Workbooks
|
401
|
-
rescue WIN32OLERuntimeError => msg
|
424
|
+
rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException => msg
|
402
425
|
raise UnexpectedREOError, "cannot access workbooks: #{msg.message} #{msg.backtrace}"
|
403
426
|
end
|
404
427
|
begin
|
@@ -424,21 +447,7 @@ module RobustExcelOle
|
|
424
447
|
raise UnexpectedREOError, "WIN32OLERuntimeError: #{msg.message} #{msg.backtrace}"
|
425
448
|
end
|
426
449
|
end
|
427
|
-
end
|
428
|
-
|
429
|
-
# @private
|
430
|
-
def set_options(filename, options)
|
431
|
-
if (!options[:read_only].nil?) && options[:read_only] != @ole_workbook.ReadOnly
|
432
|
-
@excel.with_displayalerts(false) { @ole_workbook.Close }
|
433
|
-
@ole_workbook = nil
|
434
|
-
open_or_create_workbook(filename, options)
|
435
|
-
end
|
436
|
-
retain_saved do
|
437
|
-
self.visible = options[:force][:visible].nil? ? @excel.Visible : options[:force][:visible]
|
438
|
-
@excel.calculation = options[:calculation] unless options[:calculation].nil?
|
439
|
-
@ole_workbook.CheckCompatibility = options[:check_compatibility] unless options[:check_compatibility].nil?
|
440
|
-
end
|
441
|
-
end
|
450
|
+
end
|
442
451
|
|
443
452
|
# @private
|
444
453
|
# translating the option UpdateLinks from REO to VBA
|
@@ -599,14 +608,12 @@ module RobustExcelOle
|
|
599
608
|
if change_rw_mode
|
600
609
|
opts = opts.merge({:force => {:excel => opts[:rw_change_excel]}, :read_only => do_not_write})
|
601
610
|
open(file, opts)
|
602
|
-
#open(file, :force => {:excel => opts[:rw_change_excel]}, :read_only => do_not_write)
|
603
611
|
else
|
604
612
|
book
|
605
613
|
end
|
606
614
|
else
|
607
615
|
opts = opts.merge({:force => {:excel => opts[:if_closed]}, :read_only => do_not_write})
|
608
616
|
open(file, opts)
|
609
|
-
#open(file, :force => {:excel => opts[:if_closed]}, :read_only => do_not_write)
|
610
617
|
end
|
611
618
|
yield book
|
612
619
|
ensure
|
@@ -646,9 +653,8 @@ module RobustExcelOle
|
|
646
653
|
# otherwise the workbook may already be open writable in an another Excel instance
|
647
654
|
# then you could use this workbook or close the workbook there
|
648
655
|
begin
|
649
|
-
@modified_cells = []
|
650
656
|
@ole_workbook.Save
|
651
|
-
rescue WIN32OLERuntimeError => msg
|
657
|
+
rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException => msg
|
652
658
|
if msg.message =~ /SaveAs/ && msg.message =~ /Workbook/
|
653
659
|
raise WorkbookNotSaved, 'workbook not saved'
|
654
660
|
else
|
@@ -744,10 +750,9 @@ module RobustExcelOle
|
|
744
750
|
when '.xlsx' then RobustExcelOle::XlOpenXMLWorkbook
|
745
751
|
when '.xlsm' then RobustExcelOle::XlOpenXMLWorkbookMacroEnabled
|
746
752
|
end
|
747
|
-
@modified_cells = []
|
748
753
|
@ole_workbook.SaveAs(General.absolute_path(file), file_format)
|
749
754
|
bookstore.store(self)
|
750
|
-
rescue WIN32OLERuntimeError => msg
|
755
|
+
rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException => msg
|
751
756
|
if msg.message =~ /SaveAs/ && msg.message =~ /Workbook/
|
752
757
|
# trace "save: canceled by user" if options[:if_exists] == :alert || options[:if_exists] == :excel
|
753
758
|
# another possible semantics. raise WorkbookREOError, "could not save Workbook"
|
@@ -790,7 +795,7 @@ module RobustExcelOle
|
|
790
795
|
# @returns [Worksheet]
|
791
796
|
def sheet(name)
|
792
797
|
worksheet_class.new(@ole_workbook.Worksheets.Item(name))
|
793
|
-
rescue WIN32OLERuntimeError => msg
|
798
|
+
rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException => msg
|
794
799
|
raise NameNotFound, "could not return a sheet with name #{name.inspect}"
|
795
800
|
end
|
796
801
|
|
@@ -825,7 +830,7 @@ module RobustExcelOle
|
|
825
830
|
last_sheet_local = last_sheet
|
826
831
|
after_or_before, base_sheet = opts.to_a.first || [:after, last_sheet_local]
|
827
832
|
begin
|
828
|
-
if
|
833
|
+
if !JRUBY_BUG_COPYSHEETS
|
829
834
|
if sheet
|
830
835
|
sheet.Copy({ after_or_before.to_s => base_sheet.ole_worksheet })
|
831
836
|
else
|
@@ -833,7 +838,6 @@ module RobustExcelOle
|
|
833
838
|
#@ole_workbook.Worksheets.Item(ole_workbook.Worksheets.Count).Activate
|
834
839
|
end
|
835
840
|
else
|
836
|
-
# workaround for jruby
|
837
841
|
if after_or_before == :before
|
838
842
|
if sheet
|
839
843
|
sheet.Copy(base_sheet.ole_worksheet)
|
@@ -860,8 +864,7 @@ module RobustExcelOle
|
|
860
864
|
end
|
861
865
|
end
|
862
866
|
end
|
863
|
-
rescue
|
864
|
-
#trace "#{$!.message}"
|
867
|
+
rescue WIN32OLERuntimeError, NameNotFound, Java::OrgRacobCom::ComFailException
|
865
868
|
raise WorksheetREOError, "could not add given worksheet #{sheet.inspect}"
|
866
869
|
end
|
867
870
|
#ole_sheet = @excel.Activesheet
|
@@ -995,7 +998,7 @@ module RobustExcelOle
|
|
995
998
|
end
|
996
999
|
end
|
997
1000
|
|
998
|
-
# @return [Boolean] true, if the full
|
1001
|
+
# @return [Boolean] true, if the full workbook names and excel Instances are identical, false otherwise
|
999
1002
|
def == other_book
|
1000
1003
|
other_book.is_a?(Workbook) &&
|
1001
1004
|
@excel == other_book.excel &&
|
@@ -1076,23 +1079,27 @@ module RobustExcelOle
|
|
1076
1079
|
|
1077
1080
|
private
|
1078
1081
|
|
1079
|
-
|
1080
|
-
def method_missing(name, *args)
|
1082
|
+
def method_missing(name, *args)
|
1081
1083
|
if name.to_s[0,1] =~ /[A-Z]/
|
1082
|
-
|
1083
|
-
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
1084
|
+
raise ObjectNotAlive, 'method missing: workbook not alive' unless alive?
|
1085
|
+
if JRUBY_BUG_ERRORMESSAGE
|
1086
|
+
begin
|
1087
|
+
@ole_workbook.send(name, *args)
|
1088
|
+
rescue Java::OrgRacobCom::ComFailException
|
1089
|
+
raise VBAMethodMissingError, "unknown VBA property or method #{name.inspect}"
|
1090
|
+
end
|
1091
|
+
else
|
1092
|
+
begin
|
1093
|
+
@ole_workbook.send(name, *args)
|
1094
|
+
rescue NoMethodError
|
1087
1095
|
raise VBAMethodMissingError, "unknown VBA property or method #{name.inspect}"
|
1088
|
-
else
|
1089
|
-
raise msg
|
1090
1096
|
end
|
1091
1097
|
end
|
1092
1098
|
else
|
1093
1099
|
super
|
1094
1100
|
end
|
1095
1101
|
end
|
1102
|
+
|
1096
1103
|
end
|
1097
1104
|
|
1098
1105
|
public
|
@@ -47,8 +47,8 @@ module RobustExcelOle
|
|
47
47
|
# @param [String] new_name the new name of the sheet
|
48
48
|
def name= (new_name)
|
49
49
|
@ole_worksheet.Name = new_name
|
50
|
-
rescue WIN32OLERuntimeError => msg
|
51
|
-
if msg.message =~ /800A03EC/
|
50
|
+
rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException => msg
|
51
|
+
if msg.message =~ /800A03EC/ || msg.message =~ /Visual Basic/
|
52
52
|
raise NameAlreadyExists, "sheet name #{new_name.inspect} already exists"
|
53
53
|
else
|
54
54
|
raise UnexpectedREOError, "unexpected WIN32OLERuntimeError: #{msg.message}"
|
@@ -123,7 +123,7 @@ module RobustExcelOle
|
|
123
123
|
workbook.color_if_modified = opts[:color] unless opts[:color].nil?
|
124
124
|
cell.Interior.ColorIndex = workbook.color_if_modified unless workbook.color_if_modified.nil?
|
125
125
|
cell.Value = value
|
126
|
-
rescue WIN32OLERuntimeError
|
126
|
+
rescue # WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException
|
127
127
|
raise RangeNotEvaluatable, "cannot assign value #{value.inspect} to cell (#{y.inspect},#{x.inspect})"
|
128
128
|
end
|
129
129
|
|
@@ -220,13 +220,17 @@ module RobustExcelOle
|
|
220
220
|
# @private
|
221
221
|
def method_missing(name, *args)
|
222
222
|
if name.to_s[0,1] =~ /[A-Z]/
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
223
|
+
if JRUBY_BUG_ERRORMESSAGE
|
224
|
+
begin
|
225
|
+
@ole_worksheet.send(name, *args)
|
226
|
+
rescue Java::OrgRacobCom::ComFailException
|
227
|
+
raise VBAMethodMissingError, "unknown VBA property or method #{name.inspect}"
|
228
|
+
end
|
229
|
+
else
|
230
|
+
begin
|
231
|
+
@ole_worksheet.send(name, *args)
|
232
|
+
rescue NoMethodError
|
227
233
|
raise VBAMethodMissingError, "unknown VBA property or method #{name.inspect}"
|
228
|
-
else
|
229
|
-
raise msg
|
230
234
|
end
|
231
235
|
end
|
232
236
|
else
|
data/robust_excel_ole.gemspec
CHANGED
@@ -11,11 +11,13 @@ Gem::Specification.new do |s|
|
|
11
11
|
|
12
12
|
s.summary = "RobustExcelOle automates processing Excel workbooks in Windows by using the win32ole library."
|
13
13
|
s.description = "RobustExcelOle helps controlling Excel.
|
14
|
-
It is designed to manage simultaneously running
|
15
|
-
Excel instances, even with simultanously happening user interactions.
|
16
14
|
This obviously includes standard tasks like reading and writing Excel workbooks.
|
17
|
-
|
18
|
-
|
15
|
+
The gem is designed to manage simultaneously running
|
16
|
+
Excel instances, even with simultanously happening user interactions.
|
17
|
+
|
18
|
+
RobustExcelOle deals with various cases of Excel (and user) behaviour, and
|
19
|
+
supplies workarounds for some Excel and JRuby bugs.
|
20
|
+
Library references are supported.
|
19
21
|
It runs on Windows and uses the win32ole library."
|
20
22
|
|
21
23
|
s. licenses = ['MIT']
|
data/spec/bookstore_spec.rb
CHANGED
data/spec/cell_spec.rb
CHANGED
data/spec/data/workbook.xls
CHANGED
Binary file
|
data/spec/excel_spec.rb
CHANGED
@@ -1839,44 +1839,45 @@ module RobustExcelOle
|
|
1839
1839
|
|
1840
1840
|
it "should set options to true for a workbook" do
|
1841
1841
|
book1 = Workbook.open(@simple_file1)
|
1842
|
-
book1.excel
|
1843
|
-
|
1844
|
-
|
1845
|
-
|
1846
|
-
|
1847
|
-
|
1848
|
-
|
1849
|
-
|
1842
|
+
excel1 = book1.excel
|
1843
|
+
excel1.for_all_workbooks(:visible => true, :read_only => true, :check_compatibility => true)
|
1844
|
+
excel1.Visible.should be true
|
1845
|
+
ole_workbook1 = book1.ole_workbook
|
1846
|
+
ole_workbook1.Windows(ole_workbook1.Name).Visible.should be true
|
1847
|
+
ole_workbook1.ReadOnly.should be true
|
1848
|
+
ole_workbook1.CheckCompatibility.should be true
|
1849
|
+
excel1.for_all_workbooks(:visible => false, :read_only => false, :check_compatibility => false)
|
1850
|
+
excel1.Visible.should be true
|
1851
|
+
ole_workbook1 = book1.ole_workbook
|
1852
|
+
ole_workbook1.Windows(ole_workbook1.Name).Visible.should be false
|
1853
|
+
ole_workbook1.ReadOnly.should be false
|
1854
|
+
ole_workbook1.CheckCompatibility.should be false
|
1850
1855
|
end
|
1851
1856
|
|
1852
1857
|
it "should set options for two workbooks" do
|
1853
1858
|
book1 = Workbook.open(@simple_file1)
|
1854
1859
|
book2 = Workbook.open(@different_file1)
|
1855
1860
|
excel = book1.excel
|
1856
|
-
|
1857
|
-
excel.for_all_workbooks(:visible => true, :check_compatibility => true)
|
1861
|
+
excel.for_all_workbooks(:visible => true, :check_compatibility => true, :read_only => true)
|
1858
1862
|
excel.Visible.should be true
|
1859
|
-
|
1860
|
-
|
1861
|
-
|
1862
|
-
|
1863
|
-
|
1864
|
-
|
1865
|
-
|
1866
|
-
|
1867
|
-
|
1868
|
-
book4.CheckCompatibility.should be true
|
1869
|
-
#excel.for_all_workbooks(:visible => false, :read_only => false, :check_compatibility => false)
|
1870
|
-
excel.for_all_workbooks(:visible => false, :check_compatibility => false)
|
1863
|
+
ole_workbook1 = book1.ole_workbook
|
1864
|
+
ole_workbook2 = book2.ole_workbook
|
1865
|
+
ole_workbook1.Windows(ole_workbook1.Name).Visible.should be true
|
1866
|
+
ole_workbook2.Windows(ole_workbook2.Name).Visible.should be true
|
1867
|
+
ole_workbook1.CheckCompatibility.should be true
|
1868
|
+
ole_workbook2.CheckCompatibility.should be true
|
1869
|
+
ole_workbook1.ReadOnly.should be true
|
1870
|
+
ole_workbook2.ReadOnly.should be true
|
1871
|
+
excel.for_all_workbooks(:visible => false, :check_compatibility => false, :read_only => false)
|
1871
1872
|
excel.Visible.should be true
|
1872
|
-
|
1873
|
-
|
1874
|
-
|
1875
|
-
|
1876
|
-
|
1877
|
-
|
1878
|
-
|
1879
|
-
|
1873
|
+
ole_workbook1 = book1.ole_workbook
|
1874
|
+
ole_workbook2 = book2.ole_workbook
|
1875
|
+
ole_workbook1.Windows(ole_workbook1.Name).Visible.should be false
|
1876
|
+
ole_workbook2.Windows(ole_workbook2.Name).Visible.should be false
|
1877
|
+
ole_workbook1.CheckCompatibility.should be false
|
1878
|
+
ole_workbook2.CheckCompatibility.should be false
|
1879
|
+
ole_workbook1.ReadOnly.should be false
|
1880
|
+
ole_workbook2.ReadOnly.should be false
|
1880
1881
|
end
|
1881
1882
|
|
1882
1883
|
end
|
data/spec/range_spec.rb
CHANGED
data/spec/workbook_spec.rb
CHANGED
@@ -67,6 +67,44 @@ describe Workbook do
|
|
67
67
|
|
68
68
|
end
|
69
69
|
|
70
|
+
describe "open and new" do
|
71
|
+
|
72
|
+
context "with standard" do
|
73
|
+
|
74
|
+
it "should yield identical objects" do
|
75
|
+
book1 = Workbook.open(@simple_file1)
|
76
|
+
ole_workbook1 = book1.ole_workbook
|
77
|
+
book2 = Workbook.new(ole_workbook1)
|
78
|
+
book1.equal?(book2).should be true
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "connecting to unknown workbooks" do
|
86
|
+
|
87
|
+
context "with one unknown workbook" do
|
88
|
+
|
89
|
+
before do
|
90
|
+
ole_e1 = WIN32OLE.new('Excel.Application')
|
91
|
+
ws = ole_e1.Workbooks
|
92
|
+
abs_filename = General.absolute_path(@simple_file1)
|
93
|
+
@ole_wb = ws.Open(abs_filename)
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should connect to an unknown workbook" do
|
97
|
+
Workbook.open(@simple_file1) do |book|
|
98
|
+
book.filename.should == @simple_file1
|
99
|
+
book.should be_alive
|
100
|
+
book.should be_a Workbook
|
101
|
+
book.excel.ole_excel.Hwnd.should == @ole_wb.Application.Hwnd
|
102
|
+
Excel.excels_number.should == 1
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
70
108
|
describe "Workbook::save" do
|
71
109
|
|
72
110
|
it "should save a file, if it is open" do
|
@@ -43,6 +43,30 @@ describe Workbook do
|
|
43
43
|
rm_tmp(@dir)
|
44
44
|
end
|
45
45
|
|
46
|
+
describe "open and new" do
|
47
|
+
|
48
|
+
context "with standard" do
|
49
|
+
|
50
|
+
before do
|
51
|
+
@book1 = Workbook.new(@simple_file1)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should yield identical Workbook objects for a file name" do
|
55
|
+
book2 = Workbook.open(@simple_file1)
|
56
|
+
book2.equal?(@book1).should be true
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should yield identical Workbook objects for a win32ole-workbook" do
|
60
|
+
ole_workbook1 = @book1.ole_workbook
|
61
|
+
book2 = Workbook.new(ole_workbook1)
|
62
|
+
book3 = Workbook.open(ole_workbook1)
|
63
|
+
book3.equal?(book2).should be true
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
46
70
|
describe "connecting to unknown workbooks" do
|
47
71
|
|
48
72
|
context "with none workbook" do
|
@@ -1999,7 +2023,7 @@ describe Workbook do
|
|
1999
2023
|
|
2000
2024
|
it "should open the new book and close the unsaved book, if user answers 'yes'" do
|
2001
2025
|
# "Yes" is the default. --> language independent
|
2002
|
-
|
2026
|
+
@key_sender.puts "{enter}"
|
2003
2027
|
@new_book = Workbook.open(@simple_file1, :if_unsaved => :alert)
|
2004
2028
|
@new_book.should be_alive
|
2005
2029
|
@new_book.filename.downcase.should == @simple_file1.downcase
|
@@ -2269,7 +2293,7 @@ describe Workbook do
|
|
2269
2293
|
|
2270
2294
|
context "with :read_only" do
|
2271
2295
|
|
2272
|
-
it "should
|
2296
|
+
it "should raise error, when :if_unsaved => :accept and change readonly to false" do
|
2273
2297
|
book = Workbook.open(@simple_file1, :read_only => true)
|
2274
2298
|
book.ReadOnly.should be true
|
2275
2299
|
book.should be_alive
|
@@ -2277,11 +2301,22 @@ describe Workbook do
|
|
2277
2301
|
old_cell_value = sheet[1,1].Value
|
2278
2302
|
sheet[1,1] = sheet[1,1].Value == "foo" ? "bar" : "foo"
|
2279
2303
|
book.Saved.should be false
|
2280
|
-
|
2281
|
-
|
2282
|
-
|
2283
|
-
|
2284
|
-
|
2304
|
+
expect{
|
2305
|
+
new_book = Workbook.open(@simple_file1, :read_only => false, :if_unsaved => :accept)
|
2306
|
+
}.to raise_error(OptionInvalid)
|
2307
|
+
end
|
2308
|
+
|
2309
|
+
it "should raise error, when :if_unsaved => :accept and change readonly to false" do
|
2310
|
+
book = Workbook.open(@simple_file1, :read_only => false)
|
2311
|
+
book.ReadOnly.should be false
|
2312
|
+
book.should be_alive
|
2313
|
+
sheet = book.sheet(1)
|
2314
|
+
old_cell_value = sheet[1,1].Value
|
2315
|
+
sheet[1,1] = sheet[1,1].Value == "foo" ? "bar" : "foo"
|
2316
|
+
book.Saved.should be false
|
2317
|
+
expect{
|
2318
|
+
new_book = Workbook.open(@simple_file1, :read_only => true, :if_unsaved => :accept)
|
2319
|
+
}.to raise_error(OptionInvalid)
|
2285
2320
|
end
|
2286
2321
|
|
2287
2322
|
it "should not reopen the book with writable" do
|
@@ -561,6 +561,7 @@ describe Workbook do
|
|
561
561
|
new_book.close
|
562
562
|
@book.excel.DisplayAlerts.should == displayalert_value
|
563
563
|
end
|
564
|
+
|
564
565
|
it "should not save if user answers 'no'" do
|
565
566
|
# Just give the "Enter" key, because "No" is the default. --> language independent
|
566
567
|
# strangely, in the "no" case, the question will sometimes be repeated three times
|
data/spec/worksheet_spec.rb
CHANGED
@@ -160,12 +160,12 @@ describe Worksheet do
|
|
160
160
|
end
|
161
161
|
end
|
162
162
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
163
|
+
# context "supplying nil as parameter" do
|
164
|
+
# it "should access [1,1]" do
|
165
|
+
# @sheet[1, nil].Value.should eq 'foo'
|
166
|
+
# @sheet[nil, 1].Value.should eq 'foo'
|
167
|
+
# end
|
168
|
+
# end
|
169
169
|
|
170
170
|
end
|
171
171
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: robust_excel_ole
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '1.
|
4
|
+
version: '1.13'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- traths
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-01-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -24,13 +24,13 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 2.6.0
|
27
|
-
description: "RobustExcelOle helps controlling Excel. \n
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
deals with various cases of Excel (and user) behaviour
|
32
|
-
workarounds for some Excel
|
33
|
-
runs on Windows and uses the win32ole library."
|
27
|
+
description: "RobustExcelOle helps controlling Excel. \n This obviously
|
28
|
+
includes standard tasks like reading and writing Excel workbooks.\n The
|
29
|
+
gem is designed to manage simultaneously running\n Excel instances,
|
30
|
+
even with simultanously happening user interactions.\n \n RobustExcelOle
|
31
|
+
deals with various cases of Excel (and user) behaviour, and\n supplies
|
32
|
+
workarounds for some Excel and JRuby bugs.\n Library references
|
33
|
+
are supported.\n It runs on Windows and uses the win32ole library."
|
34
34
|
email:
|
35
35
|
- Thomas.Raths@gmx.net
|
36
36
|
executables: []
|