robust_excel_ole 1.0.3 → 1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Changelog +4 -0
- data/README.rdoc +55 -25
- data/README_detail.rdoc +18 -0
- data/lib/robust_excel_ole/book.rb +24 -11
- data/lib/robust_excel_ole/excel.rb +19 -11
- data/lib/robust_excel_ole/general.rb +2 -3
- data/lib/robust_excel_ole/reo_common.rb +2 -0
- data/lib/robust_excel_ole/version.rb +1 -1
- data/spec/book_spec.rb +84 -0
- data/spec/data/another_workbook.xls +0 -0
- data/spec/data/workbook.xls +0 -0
- data/spec/excel_spec.rb +8 -0
- metadata +4 -5
data/Changelog
CHANGED
data/README.rdoc
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
= RobustExcelOle
|
2
2
|
|
3
|
-
This ruby gem automates modifying,
|
3
|
+
This ruby gem automates reading, modifying, and writing Excel files.
|
4
4
|
It supports simultaneously running Excel instances and user interactions.
|
5
5
|
RobustExcelOle deals with various cases of Excel and user behaviour,
|
6
6
|
and implements workarounds for some Excel bugs.
|
@@ -9,7 +9,7 @@ It supports Excel 2010.
|
|
9
9
|
|
10
10
|
RobustExcelOle works by sending VBA methods via Win32OLE.
|
11
11
|
Moreover, it implements a management system and keeps track of Excel files and Excel instances.
|
12
|
-
The tool is optimised with help of rcov.
|
12
|
+
The tool is optimised with help of the rcov tool.
|
13
13
|
|
14
14
|
== Requirements
|
15
15
|
|
@@ -28,40 +28,71 @@ The tool is optimised with help of rcov.
|
|
28
28
|
|
29
29
|
In the following, some features of RobustExcelOle are depicted.
|
30
30
|
|
31
|
-
RobustExcelOle
|
31
|
+
RobustExcelOle enables opening and processing Excel files (or 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.
|
32
32
|
|
33
|
-
For example, suppose you want to
|
33
|
+
For example, suppose you want to open a workbook and make it visible.
|
34
34
|
|
35
|
-
book1 = Book.open('workbook.xls')
|
36
|
-
|
37
|
-
|
35
|
+
book1 = Book.open('workbook.xls', :visible => true)
|
36
|
+
|
37
|
+
Now we want to open another workbook in a different Excel instance.
|
38
|
+
|
39
|
+
book2 = Book.open('workbook2.xls', :force => {:excel => :new}, :visible => true)
|
40
|
+
|
41
|
+
We can also create a third Excel instance and open another workbook in this instance.
|
42
|
+
|
43
|
+
excel1 = Excel.create
|
44
|
+
book3 = Book.open('workbook3.xls', :force => {:excel => excel1}, :visible => true)
|
45
|
+
|
46
|
+
Another feature that RobustExcelOle povides is reopening workbooks after closing them.
|
47
|
+
|
48
|
+
book1.close
|
49
|
+
book1.reopen
|
50
|
+
|
51
|
+
A workbook is opened by default in the Excel instance where it was open before most recently.
|
52
|
+
|
53
|
+
book1.close
|
54
|
+
book1 = Book.open('workbook.xls')
|
55
|
+
|
56
|
+
If this Excel instance is damaged or closed, then options control whether the workbook shall be opened in the current (active), a new or a given Excel instance.
|
57
|
+
|
58
|
+
book1 = Book.open('workbook.xls', :default => {:excel => :new})
|
38
59
|
|
39
|
-
|
60
|
+
The workbook can also be forced to be opened in the current, new or given Excel instance, no matter if and where it was opened before, e.g.
|
61
|
+
|
62
|
+
book2 = Book.open('workbook.xls', :force => {:excel => excel1})
|
63
|
+
|
64
|
+
As a further feature, RobustExcelOle allows processing workbooks, while still supporting user's interactions: The commands enable to open, close, reopen, read, modify, write and save Excel files, without the need of the user's interaction, and even without the user noticing. Thus, while running a script containing RobustExcelOle commands, the user can open and process Excel files in any Excel instances at any time. RobustExcelOle manages the complex cases of conflicts that might occur such that the user does not need to interfere and the script can continue.
|
65
|
+
|
66
|
+
For example, suppose you want to process a list of workbooks. RobustExcelOle allows to rapidly open, manipulate, close and save these workbooks. Now assume, the workbook "workbook.xls" is being processed, while the user has opened this workbook, has modified but not saved it yet. Excel would prompt a message and ask the user what to do. RobustExcelOle solves this conflict by using an option that states whether the changes of the user should be saved (accepted) or discarded before opening the workbook:
|
67
|
+
|
68
|
+
book = Book.open('workbook.xls', :if_unsaved => :accept)
|
69
|
+
|
70
|
+
Similarly, if the user has opened a workbook that has the same name but a different path, the conflict is solved via an option.
|
40
71
|
|
41
72
|
book1 = Book.open('path1/workbook.xls')
|
42
73
|
...
|
43
74
|
book2 = Book.open('workbook.xls', :if_obstructed => :forget)
|
44
75
|
|
45
|
-
|
76
|
+
There are twelve options that control opening workbooks.
|
46
77
|
|
47
|
-
|
48
|
-
|
49
|
-
Moreover, RobustExcelOle allows unobtrusively reading and modifying workbooks, i.e. accessing workbooks without changing their "status". The status comprises whether the workbook is open or closed, saved or unsaved, read-only or writable, visible or invisible, calculation mode is manual or automatic, and checking compatibility is done or not done.
|
78
|
+
Finally, RobustExcelOle allows unobtrusively reading and modifying workbooks, i.e. accessing workbooks without changing their "status". The status comprises whether the workbook is open or closed, saved or unsaved, read-only or writable, visible or invisible, whether the calculation mode is manual or automatic, and checking compatibility is done or not done.
|
50
79
|
|
51
80
|
Book.for_modifying('workbook.xls') do |book|
|
52
|
-
|
81
|
+
# do something
|
53
82
|
end
|
54
83
|
|
55
84
|
Book.for_reading('workbook.xls') do |book|
|
56
|
-
|
85
|
+
# do something
|
57
86
|
end
|
58
87
|
|
59
|
-
=== The Book objects and
|
88
|
+
=== The Book objects and identity transparency
|
60
89
|
|
61
|
-
An Excel file (or workbook) is represented by a Book object. A Book object is defined by the full name of the workbook and the Excel instance in which it is opened. RobustExcelOle aims to ensure identity
|
62
|
-
Identity
|
90
|
+
An Excel file (or workbook) is represented by a Book object. A Book object is defined by the full name of the workbook and the Excel instance in which it is opened. RobustExcelOle aims to ensure identity transparency.
|
91
|
+
Identity transparency means that the same Book objects refer to the same Excel files, and vice versa.
|
63
92
|
In other words, a Book objects is a proxy of an Excel file.
|
64
93
|
|
94
|
+
Here are some more details about opening, closing, reading, writing and modifying Excel files.
|
95
|
+
|
65
96
|
=== Opening and closing workbooks
|
66
97
|
|
67
98
|
Let's have a look at an example. Suppose, we want to open a workbook.
|
@@ -98,7 +129,7 @@ Reopening this workbook is done by
|
|
98
129
|
|
99
130
|
book2.reopen
|
100
131
|
|
101
|
-
===
|
132
|
+
=== Reading and modifying workbooks
|
102
133
|
|
103
134
|
We can get the value of a named range.
|
104
135
|
|
@@ -116,7 +147,7 @@ or
|
|
116
147
|
|
117
148
|
book2.set_nameval("new", "bar")
|
118
149
|
|
119
|
-
|
150
|
+
Then we access the first worksheet by
|
120
151
|
|
121
152
|
sheet1 = book2.sheet(1)
|
122
153
|
|
@@ -156,7 +187,7 @@ and set the value
|
|
156
187
|
|
157
188
|
sheet1.set_nameval("firstcell", "foo")
|
158
189
|
|
159
|
-
We get the value of a range of a locally defined name.
|
190
|
+
We get the value of a range of a locally defined name.
|
160
191
|
|
161
192
|
sheet1.rangeval("firstcell") # => "foo"
|
162
193
|
|
@@ -172,7 +203,7 @@ We can copy the first worksheet, name it and add it before the third worksheet.
|
|
172
203
|
|
173
204
|
book2.add_or_copy_sheet(sheet1, :as => "copied_name, :before => book2.last_sheet)
|
174
205
|
|
175
|
-
=== Saving workbooks
|
206
|
+
=== Saving (writing) workbooks
|
176
207
|
|
177
208
|
Simple save is done by
|
178
209
|
|
@@ -200,7 +231,6 @@ or
|
|
200
231
|
|
201
232
|
excel1 = Excel.new(:reuse => true)
|
202
233
|
|
203
|
-
|
204
234
|
Now we want to start a new, visible Excel instance.
|
205
235
|
|
206
236
|
excel2 = Excel.create(:visible => true)
|
@@ -213,7 +243,7 @@ We open a workbook in this Excel instance.
|
|
213
243
|
|
214
244
|
book4 = Book.open('more_data/workbook', {:force => {:excel => excel2}})
|
215
245
|
|
216
|
-
We
|
246
|
+
We close the Excel instance by
|
217
247
|
|
218
248
|
excel1.close
|
219
249
|
|
@@ -245,7 +275,7 @@ and set its value by
|
|
245
275
|
|
246
276
|
excel2.set_rangeval("firstcell, "bar")
|
247
277
|
|
248
|
-
Closing all Excel instances
|
278
|
+
Closing all Excel instances is done by
|
249
279
|
|
250
280
|
Excel.close_all(:if_unsaved => :forget)
|
251
281
|
|
@@ -255,7 +285,7 @@ Hard terminating all Excel processes is done by
|
|
255
285
|
|
256
286
|
=== More details
|
257
287
|
|
258
|
-
{
|
288
|
+
{README_detail.rdoc}[https://github.com/Thomas008/robust_excel_ole/blob/master/README_detail.rdoc]
|
259
289
|
|
260
290
|
=== Want to do more things
|
261
291
|
|
data/README_detail.rdoc
CHANGED
@@ -219,6 +219,24 @@ If a workbook blocks the workbook that should be saved, then the former one can
|
|
219
219
|
book2 = Book.open('another_workbook.xls')
|
220
220
|
book2.save_as('dir/workbook.xls', :if_exists => :overwrite, :if_obstructed => :save)
|
221
221
|
|
222
|
+
=== Opening, closing and saving a workbook under a certain name
|
223
|
+
|
224
|
+
You can open a workbook with given file name.
|
225
|
+
|
226
|
+
book = Book.open('workbook.xls')
|
227
|
+
|
228
|
+
You can save a workbook with given file name, if it is open.
|
229
|
+
|
230
|
+
Book.save('workbook.xls')
|
231
|
+
|
232
|
+
The workbook can be saved under a new file name, if it is open.
|
233
|
+
|
234
|
+
Book.save_as('workbook.xls', 'new_workbook.xls')
|
235
|
+
|
236
|
+
Finally the workbook can be closed with a given filename.
|
237
|
+
|
238
|
+
Book.close('workbook.xls')
|
239
|
+
|
222
240
|
=== Unobtrusively modifying a workbook
|
223
241
|
|
224
242
|
The method +unobtrusively+ enables the user to read or modify a workbook, no matter if it is open in some Excel instance, if it is saved or unsaved, and if it is writable or not. When opening a workbook unobtrusively, its status remains unchanged. This status includes, whether the workbook is opened or closed, saved or unsaved, readonly or writable, visible or invisible, calculation mode is automatic or manual, and checking compatibility is turned on or off.
|
@@ -328,12 +328,8 @@ module RobustExcelOle
|
|
328
328
|
filename = General::absolute_path(file)
|
329
329
|
begin
|
330
330
|
workbooks = @excel.Workbooks
|
331
|
-
rescue
|
332
|
-
|
333
|
-
raise ExcelDamaged, "Excel instance not alive or damaged"
|
334
|
-
else
|
335
|
-
raise UnexpectedError, "unknown RuntimeError: #{msg.message}"
|
336
|
-
end
|
331
|
+
rescue WIN32OLERuntimeError => msg
|
332
|
+
raise UnexpectedError, "WIN32OLERuntimeError: #{msg.message} #{msg.backtrace}"
|
337
333
|
end
|
338
334
|
begin
|
339
335
|
with_workaround_linked_workbooks_excel2007(options) do
|
@@ -343,15 +339,14 @@ module RobustExcelOle
|
|
343
339
|
rescue WIN32OLERuntimeError => msg
|
344
340
|
# for Excel2007: for option :if_unsaved => :alert and user cancels: this error appears?
|
345
341
|
# if yes: distinguish these events
|
346
|
-
#
|
347
|
-
# trace "WIN32OLERuntimeError: #{msg.message}"
|
342
|
+
raise UnexpectedError, "WIN32OLERuntimeError: #{msg.message} #{msg.backtrace}"
|
348
343
|
end
|
349
344
|
begin
|
350
345
|
# workaround for bug in Excel 2010: workbook.Open does not always return the workbook when given file name
|
351
346
|
begin
|
352
347
|
@ole_workbook = workbooks.Item(File.basename(filename))
|
353
348
|
rescue WIN32OLERuntimeError => msg
|
354
|
-
raise UnexpectedError, "
|
349
|
+
raise UnexpectedError, "WIN32OLERuntimeError: #{msg.message}"
|
355
350
|
end
|
356
351
|
if options[:force][:visible].nil? && (not options[:default][:visible].nil?)
|
357
352
|
if @excel.created
|
@@ -366,7 +361,7 @@ module RobustExcelOle
|
|
366
361
|
@excel.calculation = options[:calculation] unless options[:calculation].nil?
|
367
362
|
self.Saved = true # unless self.Saved # ToDo: this is too hard
|
368
363
|
rescue WIN32OLERuntimeError => msg
|
369
|
-
raise UnexpectedError, "
|
364
|
+
raise UnexpectedError, "WIN32OLERuntimeError: #{msg.message} #{msg.backtrace}"
|
370
365
|
end
|
371
366
|
end
|
372
367
|
end
|
@@ -556,7 +551,7 @@ module RobustExcelOle
|
|
556
551
|
if msg.message =~ /SaveAs/ and msg.message =~ /Workbook/ then
|
557
552
|
raise WorkbookNotSaved, "workbook not saved"
|
558
553
|
else
|
559
|
-
raise UnexpectedError, "unknown
|
554
|
+
raise UnexpectedError, "unknown WIN32OLERuntimeError:\n#{msg.message}"
|
560
555
|
end
|
561
556
|
end
|
562
557
|
true
|
@@ -656,6 +651,24 @@ module RobustExcelOle
|
|
656
651
|
|
657
652
|
public
|
658
653
|
|
654
|
+
# closes a given file if it is open
|
655
|
+
def self.close(file, opts = {:if_unsaved => :raise})
|
656
|
+
book = bookstore.fetch(file) rescue nil
|
657
|
+
book.close(opts) if book && book.alive?
|
658
|
+
end
|
659
|
+
|
660
|
+
# saves a given file if it is open
|
661
|
+
def self.save(file)
|
662
|
+
book = bookstore.fetch(file) rescue nil
|
663
|
+
book.save if book && book.alive?
|
664
|
+
end
|
665
|
+
|
666
|
+
# saves a given file under a new name if it is open
|
667
|
+
def self.save_as(file, new_file, opts = { })
|
668
|
+
book = bookstore.fetch(file) rescue nil
|
669
|
+
book.save_as(new_file, opts) if book && book.alive?
|
670
|
+
end
|
671
|
+
|
659
672
|
# returns a sheet, if a sheet name or a number is given
|
660
673
|
# @param [String] or [Number]
|
661
674
|
# @returns [Sheet]
|
@@ -350,7 +350,7 @@ module RobustExcelOle
|
|
350
350
|
#trace $!.backtrace.first(9).join "\n"
|
351
351
|
end
|
352
352
|
end
|
353
|
-
trace "went through #{anz_objekte} OLE objects"
|
353
|
+
#trace "went through #{anz_objekte} OLE objects"
|
354
354
|
end
|
355
355
|
|
356
356
|
|
@@ -361,12 +361,13 @@ module RobustExcelOle
|
|
361
361
|
# kill all Excel instances
|
362
362
|
# @return [Fixnum] number of killed Excel processes
|
363
363
|
def self.kill_all
|
364
|
-
|
365
|
-
|
366
|
-
number = processes.select{|p| (p.name == "EXCEL.EXE")}.size
|
367
|
-
procs.InstancesOf("win32_process").each do |p|
|
364
|
+
number = 0
|
365
|
+
WIN32OLE.connect("winmgmts:\\\\.").InstancesOf("win32_process").each do |p|
|
368
366
|
begin
|
369
|
-
|
367
|
+
if p.name == "EXCEL.EXE"
|
368
|
+
Process.kill('KILL', p.processid)
|
369
|
+
number += 1
|
370
|
+
end
|
370
371
|
rescue
|
371
372
|
#trace "kill error: #{$!}"
|
372
373
|
end
|
@@ -376,7 +377,8 @@ module RobustExcelOle
|
|
376
377
|
end
|
377
378
|
|
378
379
|
def self.excels_number
|
379
|
-
WIN32OLE.connect("winmgmts:\\\\.").InstancesOf("win32_process")
|
380
|
+
processes = WIN32OLE.connect("winmgmts:\\\\.").InstancesOf("win32_process")
|
381
|
+
processes.select{ |p| p.name == "EXCEL.EXE"}.size
|
380
382
|
end
|
381
383
|
|
382
384
|
# provide Excel objects
|
@@ -394,8 +396,10 @@ module RobustExcelOle
|
|
394
396
|
pid2excel[pid] = excel
|
395
397
|
end
|
396
398
|
end
|
397
|
-
|
398
|
-
|
399
|
+
processes = WIN32OLE.connect("winmgmts:\\\\.").InstancesOf("win32_process")
|
400
|
+
#excel_processes = processes.select{ |p| p.name == "EXCEL.EXE" && pid2excel.include?(p.processid)}
|
401
|
+
#excel_processes.map{ |p| Excel.new(pid2excel[p.processid]) }
|
402
|
+
processes.select{ |p| Excel.new(pid2excel[p.processid]) if p.name == "EXCEL.EXE" && pid2excel.include?(p.processid)}
|
399
403
|
result = []
|
400
404
|
processes.each do |p|
|
401
405
|
if p.name == "EXCEL.EXE"
|
@@ -486,7 +490,7 @@ module RobustExcelOle
|
|
486
490
|
raise FileNotFound, "could not save workbook with filename #{file_name.inspect}"
|
487
491
|
else
|
488
492
|
# todo some time: find out when this occurs :
|
489
|
-
raise UnexpectedError, "unknown
|
493
|
+
raise UnexpectedError, "unknown WIN32OLERuntimeError with filename #{file_name.inspect}: \n#{msg.message}"
|
490
494
|
end
|
491
495
|
end
|
492
496
|
end
|
@@ -730,5 +734,9 @@ module RobustExcelOle
|
|
730
734
|
end
|
731
735
|
end
|
732
736
|
|
733
|
-
end
|
737
|
+
end
|
734
738
|
end
|
739
|
+
|
740
|
+
class WIN32OLE
|
741
|
+
include Enumerable
|
742
|
+
end
|
data/spec/book_spec.rb
CHANGED
@@ -29,6 +29,7 @@ describe Book do
|
|
29
29
|
@simple_file_xlsx = @dir + '/workbook.xlsx'
|
30
30
|
@simple_file1 = @simple_file
|
31
31
|
@simple_file_other_path1 = @simple_file_other_path
|
32
|
+
@simple_save_file1 = @simple_save_file
|
32
33
|
end
|
33
34
|
|
34
35
|
after do
|
@@ -48,6 +49,89 @@ describe Book do
|
|
48
49
|
end
|
49
50
|
end
|
50
51
|
|
52
|
+
describe "Book::save" do
|
53
|
+
|
54
|
+
it "should save a file, if it is open" do
|
55
|
+
@book = Book.open(@simple_file)
|
56
|
+
@book.add_sheet(@sheet, :as => 'a_name')
|
57
|
+
@new_sheet_count = @book.ole_workbook.Worksheets.Count
|
58
|
+
expect {
|
59
|
+
Book.save(@simple_file)
|
60
|
+
}.to_not raise_error
|
61
|
+
@book.ole_workbook.Worksheets.Count.should == @new_sheet_count
|
62
|
+
@book.close
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should not save a file, if it is not open" do
|
66
|
+
@book = Book.open(@simple_file)
|
67
|
+
@book.add_sheet(@sheet, :as => 'a_name')
|
68
|
+
@new_sheet_count = @book.ole_workbook.Worksheets.Count
|
69
|
+
@book.close(:if_unsaved => :forget)
|
70
|
+
expect {
|
71
|
+
Book.save(@simple_file)
|
72
|
+
}.to_not raise_error
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "Book::save_as" do
|
78
|
+
|
79
|
+
it "should save to 'simple_save_file.xls'" do
|
80
|
+
book = Book.open(@simple_file1)
|
81
|
+
Book.save_as(@simple_file1, @simple_save_file1, :if_exists => :overwrite)
|
82
|
+
File.exist?(@simple_save_file1).should be_true
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "Book::close" do
|
87
|
+
|
88
|
+
it "should close the book if it is open" do
|
89
|
+
book = Book.open(@simple_file1)
|
90
|
+
Book.close(@simple_file1)
|
91
|
+
book.should_not be_alive
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should not close the book if it is not open" do
|
95
|
+
book = Book.open(@simple_file1, :visible => true)
|
96
|
+
book.close
|
97
|
+
Book.close(@simple_file1)
|
98
|
+
book.should_not be_alive
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should raise error if the book is unsaved and open" do
|
102
|
+
book = Book.open(@simple_file1)
|
103
|
+
sheet = book.sheet(1)
|
104
|
+
book.add_sheet(sheet, :as => 'a_name')
|
105
|
+
expect{
|
106
|
+
Book.close(@simple_file1)
|
107
|
+
}.to raise_error(WorkbookNotSaved, /workbook is unsaved: "workbook.xls"/)
|
108
|
+
expect{
|
109
|
+
Book.close(@simple_file, :if_unsaved => :raise)
|
110
|
+
}.to raise_error(WorkbookNotSaved, /workbook is unsaved: "workbook.xls"/)
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should save and close the book" do
|
114
|
+
book = Book.open(@simple_file1)
|
115
|
+
sheet_count = book.ole_workbook.Worksheets.Count
|
116
|
+
sheet = book.sheet(1)
|
117
|
+
book.add_sheet(sheet, :as => 'a_name')
|
118
|
+
ole_workbook = book.ole_workbook
|
119
|
+
excel = book.excel
|
120
|
+
excel.Workbooks.Count.should == 1
|
121
|
+
Book.close(@simple_file1, {:if_unsaved => :save})
|
122
|
+
excel.Workbooks.Count.should == 0
|
123
|
+
book.ole_workbook.should == nil
|
124
|
+
book.should_not be_alive
|
125
|
+
expect{ole_workbook.Name}.to raise_error(WIN32OLERuntimeError)
|
126
|
+
new_book = Book.open(@simple_file1)
|
127
|
+
begin
|
128
|
+
new_book.ole_workbook.Worksheets.Count.should == sheet_count + 1
|
129
|
+
ensure
|
130
|
+
new_book.close
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
51
135
|
describe "open" do
|
52
136
|
|
53
137
|
context "with various file formats" do
|
Binary file
|
data/spec/data/workbook.xls
CHANGED
Binary file
|
data/spec/excel_spec.rb
CHANGED
@@ -1568,6 +1568,12 @@ module RobustExcelOle
|
|
1568
1568
|
excel.close
|
1569
1569
|
end
|
1570
1570
|
|
1571
|
+
it "should return list of two Excel processes" do
|
1572
|
+
excel1 = Excel.create
|
1573
|
+
excel2 = Excel.create
|
1574
|
+
Excel.excel_processes.should == [excel1,excel2]
|
1575
|
+
end
|
1576
|
+
|
1571
1577
|
it "should return list of two Excel processes" do
|
1572
1578
|
excel1 = Excel.new
|
1573
1579
|
excel2 = Excel.current
|
@@ -1575,6 +1581,8 @@ module RobustExcelOle
|
|
1575
1581
|
Excel.excel_processes.should == [excel1,excel3]
|
1576
1582
|
end
|
1577
1583
|
|
1584
|
+
|
1585
|
+
|
1578
1586
|
end
|
1579
1587
|
|
1580
1588
|
context "with hwnd and hwnd2excel" do
|
metadata
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: robust_excel_ole
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 13
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
|
10
|
-
version: 1.0.3
|
8
|
+
- 1
|
9
|
+
version: "1.1"
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
13
12
|
- traths
|
@@ -15,7 +14,7 @@ autorequire:
|
|
15
14
|
bindir: bin
|
16
15
|
cert_chain: []
|
17
16
|
|
18
|
-
date: 2017-
|
17
|
+
date: 2017-10-02 00:00:00 +02:00
|
19
18
|
default_executable:
|
20
19
|
dependencies:
|
21
20
|
- !ruby/object:Gem::Dependency
|