robust_excel_ole 0.3.3 → 0.3.4
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +11 -10
- data/README_detail.rdoc +10 -6
- data/examples/edit_sheets/example_concating.rb +33 -0
- data/examples/edit_sheets/example_expanding.rb +57 -0
- data/examples/edit_sheets/example_naming.rb +33 -0
- data/examples/edit_sheets/example_saving.rb +44 -0
- data/lib/robust_excel_ole/book.rb +96 -29
- data/lib/robust_excel_ole/excel.rb +15 -8
- data/lib/robust_excel_ole/version.rb +1 -1
- data/spec/book_spec.rb +140 -54
- data/spec/cell_spec.rb +1 -1
- data/spec/data/more_data/{simple.xls → workbook.xls} +0 -0
- data/spec/data/protected_sheet.xls +0 -0
- data/spec/data/workbook.xls +0 -0
- data/spec/data/workbook_connected.xlsm +0 -0
- data/spec/data/workbook_connected_sub.xlsm +0 -0
- data/spec/excel_spec.rb +44 -15
- data/spec/range_spec.rb +1 -1
- data/spec/sheet_spec.rb +2 -2
- metadata +11 -6
- data/examples/save_sheets/example_save_sheets.rb +0 -34
data/README.rdoc
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
= RobustExcelOle
|
2
2
|
|
3
|
-
robust_excel_ole
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
robust_excel_ole can manage Excel workbooks that are open in several Excel instances.
|
8
|
-
It allows to automatically perform Excel operations while the user can operate with Excel manually.
|
9
|
-
|
3
|
+
robust_excel_ole helps to automate modifying and reading Excel files.
|
4
|
+
This is done by sending VBA methods via Win32OLE.
|
5
|
+
Moreover, robust_excel_ole implements a management system of Excel files and Excel instances and keeps track of all workbooks.
|
10
6
|
|
7
|
+
Goals:
|
8
|
+
- support both fully automated operations as well as simultaneous user interactions during the automation
|
9
|
+
- be able to cope with all cases of Excel (and user) behaviour, encapsulate errors
|
10
|
+
- provide convenient methods for frequent (common) tasks
|
11
|
+
- support the use of simultaneously running Excel instances
|
12
|
+
- allow the presence of referenced libraries and provide some support for that
|
11
13
|
|
12
14
|
This is work in progress.
|
13
15
|
|
@@ -38,7 +40,6 @@ The semantics is similar to, e.g., +File.open+.
|
|
38
40
|
Options are
|
39
41
|
|
40
42
|
+:default_excel+, +:force_excel+, +:if_absent+, +:if_unsaved+, +:if_obstructed+,
|
41
|
-
|
42
43
|
+:read_only+, +:visible+, +:displayalerts+.
|
43
44
|
|
44
45
|
Here are a few examples:
|
@@ -72,7 +73,7 @@ Closing the workbook and saving it before if it has unsaved changes.
|
|
72
73
|
|
73
74
|
=== Reopening workbooks.
|
74
75
|
|
75
|
-
A special feature of robust_excel_ole is that it allows
|
76
|
+
A special feature of robust_excel_ole is that it allows tog reopen books after closing them.
|
76
77
|
|
77
78
|
book = Book.open('workbook.xls')
|
78
79
|
book.close
|
@@ -442,7 +443,7 @@ The book is modified, but its status is unchanged.
|
|
442
443
|
|
443
444
|
=== More Details
|
444
445
|
|
445
|
-
For more details about usage: see link:
|
446
|
+
For more details about usage: see link:https://github.com/Thomas008/robust_excel_ole/blob/master/README_detail.rdoc
|
446
447
|
|
447
448
|
=== Development
|
448
449
|
|
data/README_detail.rdoc
CHANGED
@@ -1,11 +1,15 @@
|
|
1
1
|
= RobustExcelOle
|
2
2
|
|
3
|
-
robust_excel_ole
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
robust_excel_ole helps to automate modifying and reading Excel files.
|
4
|
+
This is done by sending VBA methods via Win32OLE.
|
5
|
+
Moreover, robust_excel_ole implements a management system of Excel files and Excel instances and keeps track of all workbooks.
|
6
|
+
|
7
|
+
Goals:
|
8
|
+
- support both fully automated operations as well as simultaneous user interactions during the automation
|
9
|
+
- be able to cope with all cases of Excel (and user) behaviour, encapsulate errors
|
10
|
+
- provide convenient methods for frequent (common) tasks
|
11
|
+
- support the use of simultaneously running Excel instances
|
12
|
+
- allow the presence of referenced libraries and provide some support for that
|
9
13
|
|
10
14
|
This is work in progress.
|
11
15
|
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# example_concatening.rb:
|
2
|
+
# each named cell gets the value of cell right to it appended to its own value
|
3
|
+
# the new workbook's name is extended by the suffix "_concat"
|
4
|
+
|
5
|
+
require 'rubygems'
|
6
|
+
require 'robust_excel_ole'
|
7
|
+
require "fileutils"
|
8
|
+
|
9
|
+
include RobustExcelOle
|
10
|
+
|
11
|
+
begin
|
12
|
+
Excel.close_all
|
13
|
+
dir = "C:/data"
|
14
|
+
workbook_name = 'workbook_named.xls'
|
15
|
+
base_name = workbook_name[0,workbook_name.rindex('.')]
|
16
|
+
suffix = workbook_name[workbook_name.rindex('.')+1,workbook_name.length]
|
17
|
+
file_name = dir + "/" + workbook_name
|
18
|
+
extended_file_name = dir + "/" + base_name + "_concat" + "." + suffix
|
19
|
+
book_orig = Book.open(file_name)
|
20
|
+
book_orig.save_as(extended_file_name, :if_exists => :overwrite)
|
21
|
+
book_orig.close
|
22
|
+
Book.unobtrusively(extended_file_name) do |book|
|
23
|
+
book.each do |sheet|
|
24
|
+
sheet.each do |cell_orig|
|
25
|
+
name = cell_orig.Name.Name rescue nil
|
26
|
+
if name
|
27
|
+
sheet[cell_orig.Row-1, cell_orig.Column-1].Value = cell_orig.Value.to_s + cell_orig.Offset(0,1).Value.to_s
|
28
|
+
sheet.Names.Add("Name" => name, "RefersTo" => "=" + cell_orig.Address)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# example_expanding.rb:
|
2
|
+
# create a workbook which is named like the old one, expect that the suffix "_expanded" is appended to the base name
|
3
|
+
# for each (global or local) Excel name of the workbook that refers to a range in a single sheet
|
4
|
+
# this sheet is to be copied into the new workbook
|
5
|
+
# the sheet's name shall be the name of the Excel name
|
6
|
+
# in addition to that, the cell B2 shall be named "name" and get the sheet name as its value
|
7
|
+
|
8
|
+
require 'rubygems'
|
9
|
+
require 'robust_excel_ole'
|
10
|
+
require "fileutils"
|
11
|
+
|
12
|
+
include RobustExcelOle
|
13
|
+
|
14
|
+
begin
|
15
|
+
Excel.close_all
|
16
|
+
dir = "C:/data"
|
17
|
+
workbook_name = 'workbook_named_concat.xls'
|
18
|
+
base_name = workbook_name[0,workbook_name.rindex('.')]
|
19
|
+
suffix = workbook_name[workbook_name.rindex('.')+1,workbook_name.length]
|
20
|
+
file_name = dir + "/" + workbook_name
|
21
|
+
extended_file_name = dir + "/" + base_name + "_expanded" + "." + suffix
|
22
|
+
book_orig = Book.open(file_name)
|
23
|
+
book_orig.save_as(extended_file_name, :if_exists => :overwrite)
|
24
|
+
book_orig.close
|
25
|
+
sheet_names = []
|
26
|
+
Book.unobtrusively(extended_file_name) do |book|
|
27
|
+
book.each do |sheet|
|
28
|
+
sheet_names << sheet.name
|
29
|
+
end
|
30
|
+
book.Names.each do |excel_name|
|
31
|
+
full_name = excel_name.Name
|
32
|
+
sheet_name, short_name = full_name.split("!")
|
33
|
+
sheet = excel_name.RefersToRange.Worksheet
|
34
|
+
sheet_name = short_name ? short_name : full_name
|
35
|
+
begin
|
36
|
+
sheet_new = book.add_sheet(sheet, :as => sheet_name)
|
37
|
+
rescue ExcelErrorSheet => msg
|
38
|
+
if msg.message == "sheet name already exists"
|
39
|
+
sheet_new = book.add_sheet(sheet, :as => (sheet_name+sheet.name))
|
40
|
+
else
|
41
|
+
puts msg.message
|
42
|
+
end
|
43
|
+
end
|
44
|
+
sheet_new.Names.Add("Name" => "name", "RefersTo" => "=" + "$B$2")
|
45
|
+
sheet_new[1,1].Value = sheet_name
|
46
|
+
begin
|
47
|
+
sheet_new.name = sheet_name
|
48
|
+
rescue
|
49
|
+
sheet_new.name = (sheet_name+sheet.name)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
sheet_names.each do |sheet_name|
|
53
|
+
book[sheet_name].Delete()
|
54
|
+
end
|
55
|
+
end
|
56
|
+
Excel.close_all
|
57
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# example_naming.rb:
|
2
|
+
# each cell is named with the name equaling its value unless it is empty or not a string
|
3
|
+
# the contents of each cell is copied
|
4
|
+
# the new workbook's name is extended by the suffix "_named"
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
require 'robust_excel_ole'
|
8
|
+
require "fileutils"
|
9
|
+
|
10
|
+
include RobustExcelOle
|
11
|
+
|
12
|
+
begin
|
13
|
+
Excel.close_all
|
14
|
+
dir = "C:/data"
|
15
|
+
workbook_name = 'workbook.xls'
|
16
|
+
base_name = workbook_name[0,workbook_name.rindex('.')]
|
17
|
+
suffix = workbook_name[workbook_name.rindex('.')+1,workbook_name.length]
|
18
|
+
file_name = dir + "/" + workbook_name
|
19
|
+
extended_file_name = dir + "/" + base_name + "_named" + "." + suffix
|
20
|
+
book_orig = Book.open(file_name)
|
21
|
+
book_orig.save_as(extended_file_name, :if_exists => :overwrite)
|
22
|
+
book_orig.close
|
23
|
+
Book.unobtrusively(extended_file_name) do |book|
|
24
|
+
book.each do |sheet|
|
25
|
+
sheet.each do |cell_orig|
|
26
|
+
contents = cell_orig.Value
|
27
|
+
if contents && contents.class == String
|
28
|
+
sheet.Names.Add("Name" => contents, "RefersTo" => "=" + cell_orig.Address)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# example_saving.rb:
|
2
|
+
# save the sheets of a book as separate workbooks
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'robust_excel_ole'
|
6
|
+
require "fileutils"
|
7
|
+
|
8
|
+
include RobustExcelOle
|
9
|
+
|
10
|
+
begin
|
11
|
+
Excel.close_all
|
12
|
+
dir = "C:/data"
|
13
|
+
workbook_name = 'workbook.xls'
|
14
|
+
base_name = workbook_name[0,workbook_name.rindex('.')]
|
15
|
+
suffix = workbook_name[workbook_name.rindex('.')+1,workbook_name.length]
|
16
|
+
file_name = dir + "/" + workbook_name
|
17
|
+
Book.unobtrusively(file_name) do |book_orig|
|
18
|
+
book_orig.each do |sheet_orig|
|
19
|
+
file_sheet_name = dir + "/" + base_name + "_" + sheet_orig.name + "." + suffix
|
20
|
+
Excel.current.generate_workbook(file_sheet_name)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
Book.unobtrusively(file_name) do |book_orig|
|
24
|
+
book_orig.each do |sheet_orig|
|
25
|
+
file_sheet_name = dir + "/" + base_name + "_" + sheet_orig.name + "." + suffix
|
26
|
+
# delete all existing sheets, and add the sheet
|
27
|
+
book = Book.open(file_sheet_name)
|
28
|
+
book.add_sheet sheet_orig
|
29
|
+
book.each do |sheet|
|
30
|
+
sheet.Delete() unless sheet.name == sheet_orig.name
|
31
|
+
end
|
32
|
+
book.close(:if_unsaved => :save)
|
33
|
+
# alternative: delete all other sheets
|
34
|
+
#book = Book.open(file_sheet_name, :force_excel => :new, :visible => true)
|
35
|
+
#book.each do |sheet|
|
36
|
+
# p "sheet.Name: #{sheet.Name}"
|
37
|
+
# book[sheet.Name].Delete() unless sheet.Name == sheet_orig.Name
|
38
|
+
#end
|
39
|
+
#sleep 3
|
40
|
+
#book.save_as(file_sheet_name, :if_exists => :overwrite)
|
41
|
+
#book.close
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -34,10 +34,10 @@ module RobustExcelOle
|
|
34
34
|
# excluding the hidden Excel instance, if it exists,
|
35
35
|
# otherwise open in a new Excel instance.
|
36
36
|
# :new -> open in a new Excel instance
|
37
|
-
# <instance>
|
37
|
+
# <excel-instance> -> open in the given Excel instance
|
38
38
|
# :force_excel no matter whether the book was already open
|
39
39
|
# :new (default) -> open in a new Excel
|
40
|
-
# <instance>
|
40
|
+
# <excel-instance> -> open in the given Excel instance
|
41
41
|
# :if_unsaved if an unsaved book with the same name is open, then
|
42
42
|
# :raise (default) -> raise an exception
|
43
43
|
# :forget -> close the unsaved book, open the new book
|
@@ -51,11 +51,11 @@ module RobustExcelOle
|
|
51
51
|
# :close_if_saved -> close the old book and open the new book, if the old book is saved,
|
52
52
|
# otherwise raise an exception.
|
53
53
|
# :new_excel -> open the new book in a new Excel
|
54
|
-
# :if_absent :create
|
54
|
+
# :if_absent :create (default) -> creates a new Excel file, if it does not exists
|
55
55
|
# :raise -> raises an exception , if the file does not exists
|
56
56
|
# :read_only open in read-only mode (default: false)
|
57
57
|
# :displayalerts enable DisplayAlerts in Excel (default: false)
|
58
|
-
# :visible make visible in Excel
|
58
|
+
# :visible make visible in Excel (default: false)
|
59
59
|
# if :default_excel is set, then DisplayAlerts and Visible are set only if these parameters are given
|
60
60
|
|
61
61
|
def open(file, opts={ }, &block)
|
@@ -63,10 +63,12 @@ module RobustExcelOle
|
|
63
63
|
book = nil
|
64
64
|
if (not (current_options[:force_excel] == :new && (not current_options[:if_locked] == :take_writable)))
|
65
65
|
# if readonly is true, then prefer a book that is given in force_excel if this option is set
|
66
|
-
book = book_store.fetch(file,
|
67
|
-
|
66
|
+
book = book_store.fetch(file,
|
67
|
+
:prefer_writable => (not current_options[:read_only]),
|
68
|
+
:prefer_excel => (current_options[:read_only] ? Book.excel(current_options[:force_excel]) : nil)) rescue nil
|
68
69
|
if book
|
69
|
-
if (((not current_options[:force_excel]) || (current_options[:force_excel] == book.excel)) &&
|
70
|
+
#if (((not current_options[:force_excel]) || (current_options[:force_excel].excel == book.excel)) &&
|
71
|
+
if (((not current_options[:force_excel]) || (Book.excel(current_options[:force_excel]) == book.excel)) &&
|
70
72
|
(not (book.alive? && (not book.saved) && (not current_options[:if_unsaved] == :accept))))
|
71
73
|
book.options = DEFAULT_OPEN_OPTS.merge(opts)
|
72
74
|
book.get_excel unless book.excel.alive?
|
@@ -110,6 +112,7 @@ module RobustExcelOle
|
|
110
112
|
@excel = Excel.new(@excel_options)
|
111
113
|
else
|
112
114
|
@excel = @options[:excel]
|
115
|
+
@excel = Book.excel(@options[:excel])
|
113
116
|
end
|
114
117
|
end
|
115
118
|
# if :excel => :new or (:excel => :reuse but could not reuse)
|
@@ -130,7 +133,7 @@ module RobustExcelOle
|
|
130
133
|
if obstructed_by_other_book then
|
131
134
|
case @options[:if_obstructed]
|
132
135
|
when :raise
|
133
|
-
raise ExcelErrorOpen, "blocked by a book with the same name in a different path"
|
136
|
+
raise ExcelErrorOpen, "blocked by a book with the same name in a different path: #{File.basename(@file)}"
|
134
137
|
when :forget
|
135
138
|
@workbook.Close
|
136
139
|
@workbook = nil
|
@@ -142,7 +145,7 @@ module RobustExcelOle
|
|
142
145
|
open_or_create_workbook
|
143
146
|
when :close_if_saved
|
144
147
|
if (not @workbook.Saved) then
|
145
|
-
raise ExcelErrorOpen, "book with the same name in a different path is unsaved"
|
148
|
+
raise ExcelErrorOpen, "book with the same name in a different path is unsaved: #{File.basename(@file)}"
|
146
149
|
else
|
147
150
|
@workbook.Close
|
148
151
|
@workbook = nil
|
@@ -154,7 +157,7 @@ module RobustExcelOle
|
|
154
157
|
@excel = Excel.new(@excel_options)
|
155
158
|
open_or_create_workbook
|
156
159
|
else
|
157
|
-
raise ExcelErrorOpen, ":if_obstructed: invalid option"
|
160
|
+
raise ExcelErrorOpen, ":if_obstructed: invalid option: #{@options[:if_obstructed]}"
|
158
161
|
end
|
159
162
|
else
|
160
163
|
# book open, not obstructed by an other book, but not saved and writable
|
@@ -178,7 +181,7 @@ module RobustExcelOle
|
|
178
181
|
@excel = Excel.new(@excel_options)
|
179
182
|
open_or_create_workbook
|
180
183
|
else
|
181
|
-
raise ExcelErrorOpen, ":if_unsaved: invalid option"
|
184
|
+
raise ExcelErrorOpen, ":if_unsaved: invalid option: #{@options[:if_unsaved]}"
|
182
185
|
end
|
183
186
|
end
|
184
187
|
end
|
@@ -191,7 +194,6 @@ module RobustExcelOle
|
|
191
194
|
def open_or_create_workbook
|
192
195
|
if (not File.exist?(@file))
|
193
196
|
@workbook = Excel.current.generate_workbook(@file)
|
194
|
-
#@workbook = Excel.new(:reuse => true).generate_workbook(@file)
|
195
197
|
return
|
196
198
|
end
|
197
199
|
if ((not @workbook) || (@options[:if_unsaved] == :alert) || @options[:if_obstructed]) then
|
@@ -199,7 +201,8 @@ module RobustExcelOle
|
|
199
201
|
filename = RobustExcelOle::absolute_path(@file)
|
200
202
|
workbooks = @excel.Workbooks
|
201
203
|
workbooks.Open(filename,{ 'ReadOnly' => @options[:read_only] })
|
202
|
-
rescue WIN32OLERuntimeError => msg
|
204
|
+
rescue WIN32OLERuntimeError => msg
|
205
|
+
puts "msg: #{msg}"
|
203
206
|
raise ExcelErrorOpen, "open: user canceled or open error" if msg.message =~ /OLE error code:800A03EC/
|
204
207
|
end
|
205
208
|
begin
|
@@ -212,6 +215,20 @@ module RobustExcelOle
|
|
212
215
|
end
|
213
216
|
end
|
214
217
|
|
218
|
+
private
|
219
|
+
|
220
|
+
# return an Excel.
|
221
|
+
# return the given instance if it is an Excel and alive. If the given instance is a Book then take the Excel of the Book
|
222
|
+
def self.excel(instance)
|
223
|
+
raise ExcelErrorOpen, "provided instance is neither an Excel nor a Book: #{instance}" \
|
224
|
+
unless instance.is_a?(Excel) || instance.is_a?(Book)
|
225
|
+
excel = instance.is_a?(Book) ? instance.excel : instance
|
226
|
+
raise ExcelErrorOpen, "provided Excel instance is not alive" unless excel.alive?
|
227
|
+
excel
|
228
|
+
end
|
229
|
+
|
230
|
+
public
|
231
|
+
|
215
232
|
# closes the book, if it is alive
|
216
233
|
#
|
217
234
|
# options:
|
@@ -235,7 +252,7 @@ module RobustExcelOle
|
|
235
252
|
close_workbook
|
236
253
|
end
|
237
254
|
else
|
238
|
-
raise ExcelErrorClose, ":if_unsaved: invalid option"
|
255
|
+
raise ExcelErrorClose, ":if_unsaved: invalid option: #{opts[:if_unsaved]}"
|
239
256
|
end
|
240
257
|
else
|
241
258
|
close_workbook
|
@@ -274,7 +291,6 @@ module RobustExcelOle
|
|
274
291
|
was_not_alive_or_nil = book.nil? || (not book.alive?)
|
275
292
|
was_saved = was_not_alive_or_nil ? true : book.saved
|
276
293
|
was_writable = book.writable unless was_not_alive_or_nil
|
277
|
-
old_visible = (book && book.excel.alive?) ? book.excel.visible : false
|
278
294
|
begin
|
279
295
|
book =
|
280
296
|
if was_not_alive_or_nil
|
@@ -284,7 +300,7 @@ module RobustExcelOle
|
|
284
300
|
when :reuse
|
285
301
|
open(file)
|
286
302
|
else
|
287
|
-
|
303
|
+
open(file, :force_excel => options[:if_closed])
|
288
304
|
end
|
289
305
|
else
|
290
306
|
if was_writable || options[:read_only]
|
@@ -295,17 +311,33 @@ module RobustExcelOle
|
|
295
311
|
end
|
296
312
|
yield book
|
297
313
|
ensure
|
298
|
-
book.save if (was_not_alive_or_nil || was_saved || ((not was_writable) && (not options[:read_only]))) && (not book.saved)
|
314
|
+
book.save if (was_not_alive_or_nil || was_saved || ((not was_writable) && (not options[:read_only]))) && (book && (not book.saved))
|
299
315
|
# book was open, readonly and shoud be modified
|
300
316
|
if (not was_not_alive_or_nil) && (not options[:read_only]) && (not was_writable) && options[:use_readonly_excel]
|
301
317
|
open(file, :force_excel => book.excel, :if_obstructed => :new_excel, :read_only => true)
|
302
318
|
end
|
303
|
-
book.
|
304
|
-
book.close if (was_not_alive_or_nil && (not opts[:keep_open]))
|
319
|
+
book.close if (was_not_alive_or_nil && (not opts[:keep_open]) && book)
|
305
320
|
end
|
306
321
|
end
|
307
322
|
|
308
|
-
#
|
323
|
+
# rename a range
|
324
|
+
def rename_range(name,new_name)
|
325
|
+
begin
|
326
|
+
p "name: #{name}"
|
327
|
+
p "new_name: #{new_name}"
|
328
|
+
item = self.Names.Item(name)
|
329
|
+
p "nil" if item.nil?
|
330
|
+
rescue WIN32OLERuntimeError
|
331
|
+
raise ExcelErrorRename, "name #{name} not in #{File.basename(self.stored_filename)}"
|
332
|
+
end
|
333
|
+
begin
|
334
|
+
item.Name = new_name
|
335
|
+
rescue WIN32OLERuntimeError
|
336
|
+
raise ExcelErrorRename, "name error in #{File.basename(self.stored_filename)}"
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
# returns the contents of a range with given name
|
309
341
|
def nvalue(name)
|
310
342
|
begin
|
311
343
|
item = self.Names.Item(name)
|
@@ -318,7 +350,26 @@ module RobustExcelOle
|
|
318
350
|
raise ExcelErrorNValue, "range error in #{File.basename(self.stored_filename)}"
|
319
351
|
end
|
320
352
|
begin
|
321
|
-
|
353
|
+
referstorange.Value
|
354
|
+
rescue WIN32OLERuntimeError
|
355
|
+
raise ExcelErrorNValue, "value error in #{File.basename(self.stored_filename)}"
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
# set the contents of a range with given name
|
360
|
+
def set_nvalue(name,value)
|
361
|
+
begin
|
362
|
+
item = self.Names.Item(name)
|
363
|
+
rescue WIN32OLERuntimeError
|
364
|
+
raise ExcelErrorNValue, "name #{name} not in #{File.basename(self.stored_filename)}"
|
365
|
+
end
|
366
|
+
begin
|
367
|
+
referstorange = item.RefersToRange
|
368
|
+
rescue WIN32OLERuntimeError
|
369
|
+
raise ExcelErrorNValue, "range error in #{File.basename(self.stored_filename)}"
|
370
|
+
end
|
371
|
+
begin
|
372
|
+
referstorange.Value = value
|
322
373
|
rescue WIN32OLERuntimeError
|
323
374
|
raise ExcelErrorNValue, "value error in #{File.basename(self.stored_filename)}"
|
324
375
|
end
|
@@ -361,7 +412,15 @@ module RobustExcelOle
|
|
361
412
|
def save
|
362
413
|
raise ExcelErrorSave, "Not opened for writing (opened with :read_only option)" if @options[:read_only]
|
363
414
|
if @workbook then
|
364
|
-
|
415
|
+
begin
|
416
|
+
@workbook.Save
|
417
|
+
rescue WIN32OLERuntimeError => msg
|
418
|
+
if msg.message =~ /SaveAs/ and msg.message =~ /Workbook/ then
|
419
|
+
raise ExcelErrorSave, "workbook not saved"
|
420
|
+
else
|
421
|
+
raise ExcelErrorSaveUnknown, "unknown WIN32OELERuntimeError:\n#{msg.message}"
|
422
|
+
end
|
423
|
+
end
|
365
424
|
true
|
366
425
|
else
|
367
426
|
nil
|
@@ -395,7 +454,7 @@ module RobustExcelOle
|
|
395
454
|
when :raise
|
396
455
|
raise ExcelErrorSave, "book already exists: #{File.basename(file)}"
|
397
456
|
else
|
398
|
-
raise ExcelErrorSave, ":if_exists: invalid option"
|
457
|
+
raise ExcelErrorSave, ":if_exists: invalid option: #{@opts[:if_exists]}"
|
399
458
|
end
|
400
459
|
else
|
401
460
|
save_as_workbook(file)
|
@@ -451,7 +510,9 @@ module RobustExcelOle
|
|
451
510
|
|
452
511
|
new_sheet_name = opts.delete(:as)
|
453
512
|
|
454
|
-
|
513
|
+
ws = @workbook.Worksheets
|
514
|
+
after_or_before, base_sheet = opts.to_a.first ||
|
515
|
+
[:after, Sheet.new(ws.Item(ws.Count))]
|
455
516
|
base_sheet = base_sheet.sheet
|
456
517
|
sheet ? sheet.Copy({ after_or_before.to_s => base_sheet }) : @workbook.WorkSheets.Add({ after_or_before.to_s => base_sheet })
|
457
518
|
new_sheet = RobustExcelOle::Sheet.new(@excel.Activesheet)
|
@@ -465,6 +526,9 @@ module RobustExcelOle
|
|
465
526
|
new_sheet
|
466
527
|
end
|
467
528
|
|
529
|
+
def add_name name
|
530
|
+
end
|
531
|
+
|
468
532
|
def self.book_store
|
469
533
|
@@bookstore ||= BookStore.new
|
470
534
|
end
|
@@ -495,13 +559,13 @@ module RobustExcelOle
|
|
495
559
|
|
496
560
|
public
|
497
561
|
|
498
|
-
class
|
562
|
+
class ExcelError < RuntimeError # :nodoc: #
|
499
563
|
end
|
500
564
|
|
501
|
-
class
|
565
|
+
class ExcelErrorOpen < ExcelError # :nodoc: #
|
502
566
|
end
|
503
567
|
|
504
|
-
class
|
568
|
+
class ExcelErrorClose < ExcelError # :nodoc: #
|
505
569
|
end
|
506
570
|
|
507
571
|
class ExcelErrorSave < ExcelError # :nodoc: #
|
@@ -513,12 +577,15 @@ public
|
|
513
577
|
class ExcelErrorSaveUnknown < ExcelErrorSave # :nodoc: #
|
514
578
|
end
|
515
579
|
|
516
|
-
class
|
580
|
+
class ExcelErrorRename < WIN32OLERuntimeError # :nodoc: #
|
517
581
|
end
|
518
582
|
|
519
|
-
class
|
583
|
+
class ExcelErrorNValue < WIN32OLERuntimeError # :nodoc: #
|
520
584
|
end
|
521
585
|
|
586
|
+
class ExcelUserCanceled < RuntimeError # :nodoc: #
|
587
|
+
end
|
588
|
+
|
522
589
|
class ExcelErrorSheet < ExcelError # :nodoc: #
|
523
590
|
end
|
524
591
|
|
@@ -62,15 +62,26 @@ module RobustExcelOle
|
|
62
62
|
result
|
63
63
|
end
|
64
64
|
|
65
|
-
def initialize(options= {}) # :nodoc:
|
65
|
+
def initialize(options= {}) # :nodoc: #
|
66
66
|
end
|
67
67
|
|
68
68
|
# generate, save and close an empty workbook
|
69
69
|
def generate_workbook file_name
|
70
70
|
self.Workbooks.Add
|
71
|
-
empty_workbook = self.Workbooks.Item(
|
72
|
-
filename = RobustExcelOle::absolute_path(file_name)
|
73
|
-
|
71
|
+
empty_workbook = self.Workbooks.Item(self.Workbooks.Count)
|
72
|
+
filename = RobustExcelOle::absolute_path(file_name).gsub("/","\\")
|
73
|
+
unless File.exists?(filename)
|
74
|
+
begin
|
75
|
+
empty_workbook.SaveAs(filename)
|
76
|
+
rescue WIN32OLERuntimeError => msg
|
77
|
+
if msg.message =~ /SaveAs/ and msg.message =~ /Workbook/ then
|
78
|
+
raise ExcelErrorSave, "could not save workbook with filename #{file_name}"
|
79
|
+
else
|
80
|
+
# todo some time: find out when this occurs :
|
81
|
+
raise ExcelErrorSaveUnknown, "unknown WIN32OELERuntimeError with filename #{file_name}: \n#{msg.message}"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
74
85
|
empty_workbook
|
75
86
|
end
|
76
87
|
|
@@ -230,8 +241,4 @@ module RobustExcelOle
|
|
230
241
|
end
|
231
242
|
|
232
243
|
end
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
244
|
end
|
data/spec/book_spec.rb
CHANGED
@@ -16,7 +16,6 @@ describe Book do
|
|
16
16
|
Excel.close_all
|
17
17
|
end
|
18
18
|
|
19
|
-
|
20
19
|
before do
|
21
20
|
@dir = create_tmpdir
|
22
21
|
@simple_file = @dir + '/workbook.xls'
|
@@ -24,6 +23,7 @@ describe Book do
|
|
24
23
|
@different_file = @dir + '/different_workbook.xls'
|
25
24
|
@simple_file_other_path = @dir + '/more_data/workbook.xls'
|
26
25
|
@more_simple_file = @dir + '/more_workbook.xls'
|
26
|
+
@connected_file = @dir + '/workbook.xlsx'
|
27
27
|
end
|
28
28
|
|
29
29
|
after do
|
@@ -31,7 +31,6 @@ describe Book do
|
|
31
31
|
rm_tmp(@dir)
|
32
32
|
end
|
33
33
|
|
34
|
-
|
35
34
|
describe "create file" do
|
36
35
|
context "with standard" do
|
37
36
|
it "open an existing file" do
|
@@ -46,6 +45,13 @@ describe Book do
|
|
46
45
|
|
47
46
|
describe "open" do
|
48
47
|
|
48
|
+
context "with connected workbook" do
|
49
|
+
it "should open connected workbook" do
|
50
|
+
book = Book.open(@connected_file, :visible => true)
|
51
|
+
book.close
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
49
55
|
context "standard use cases" do
|
50
56
|
|
51
57
|
it "should read in a seperate excel instance" do
|
@@ -238,12 +244,20 @@ describe Book do
|
|
238
244
|
book4.Readonly.should == true
|
239
245
|
book4.should_not == book2
|
240
246
|
book4.close
|
247
|
+
book5 = Book.open(@simple_file, :force_excel => book2)
|
248
|
+
book5.should be_alive
|
249
|
+
book5.should be_a Book
|
250
|
+
book5.excel.should == book2.excel
|
251
|
+
book5.Readonly.should == true
|
252
|
+
book5.should_not == book2
|
253
|
+
book5.close
|
241
254
|
book3.close
|
242
255
|
end
|
243
256
|
|
244
257
|
it "should open in a given Excel, provide identity transparency, because book can be readonly, such that the old and the new book are readonly" do
|
245
258
|
book2 = Book.open(@simple_file, :force_excel => :new)
|
246
259
|
book2.excel.should_not == @book.excel
|
260
|
+
p "book2.excel: #{book2.excel}"
|
247
261
|
book3 = Book.open(@simple_file, :force_excel => :new)
|
248
262
|
book3.excel.should_not == book2.excel
|
249
263
|
book3.excel.should_not == @book.excel
|
@@ -257,9 +271,30 @@ describe Book do
|
|
257
271
|
book4.ReadOnly.should be_true
|
258
272
|
book4.should == book2
|
259
273
|
book4.close
|
274
|
+
book5 = Book.open(@simple_file, :force_excel => book2, :read_only => true)
|
275
|
+
book5.should be_alive
|
276
|
+
book5.should be_a Book
|
277
|
+
book5.excel.should == book2.excel
|
278
|
+
book5.ReadOnly.should be_true
|
279
|
+
book5.should == book2
|
280
|
+
book5.close
|
260
281
|
book3.close
|
261
282
|
end
|
262
283
|
|
284
|
+
it "should open in a given Excel, provide identity transparency, because book can be readonly, such that the old and the new book are readonly" do
|
285
|
+
book2 = Book.open(@simple_file, :force_excel => :new)
|
286
|
+
book2.excel.should_not == @book.excel
|
287
|
+
book2.close
|
288
|
+
@book.close
|
289
|
+
book4 = Book.open(@simple_file, :force_excel => book2, :read_only => true)
|
290
|
+
book4.should be_alive
|
291
|
+
book4.should be_a Book
|
292
|
+
book4.excel.should == book2.excel
|
293
|
+
book4.ReadOnly.should be_true
|
294
|
+
book4.should == book2
|
295
|
+
book4.close
|
296
|
+
end
|
297
|
+
|
263
298
|
it "should do force_excel even if both force_ and default_excel is given" do
|
264
299
|
book2 = Book.open(@simple_file, :default_excel => @book.excel, :force_excel => :new)
|
265
300
|
book2.should be_alive
|
@@ -390,6 +425,17 @@ describe Book do
|
|
390
425
|
book2.close
|
391
426
|
end
|
392
427
|
|
428
|
+
it "should open a given excel, if the book cannot be reopened" do
|
429
|
+
@book.close
|
430
|
+
new_excel = Excel.new(:reuse => false)
|
431
|
+
book2 = Book.open(@different_file, :default_excel => @book)
|
432
|
+
book2.should be_alive
|
433
|
+
book2.should be_a Book
|
434
|
+
book2.excel.should_not == new_excel
|
435
|
+
book2.excel.should == @book.excel
|
436
|
+
book2.close
|
437
|
+
end
|
438
|
+
|
393
439
|
it "should reuse an open book by default" do
|
394
440
|
book2 = Book.open(@simple_file)
|
395
441
|
book2.excel.should == @book.excel
|
@@ -482,7 +528,7 @@ describe Book do
|
|
482
528
|
it "should raise an error, if :if_unsaved is invalid option" do
|
483
529
|
expect {
|
484
530
|
@new_book = Book.open(@simple_file, :if_unsaved => :invalid_option)
|
485
|
-
}.to raise_error(ExcelErrorOpen, ":if_unsaved: invalid option")
|
531
|
+
}.to raise_error(ExcelErrorOpen, ":if_unsaved: invalid option: invalid_option")
|
486
532
|
end
|
487
533
|
end
|
488
534
|
|
@@ -511,7 +557,7 @@ describe Book do
|
|
511
557
|
it "should raise an error, if :if_obstructed is :raise" do
|
512
558
|
expect {
|
513
559
|
@new_book = Book.open(@simple_file, :if_obstructed => :raise)
|
514
|
-
}.to raise_error(ExcelErrorOpen, "blocked by a book with the same name in a different path")
|
560
|
+
}.to raise_error(ExcelErrorOpen, "blocked by a book with the same name in a different path: workbook.xls")
|
515
561
|
end
|
516
562
|
|
517
563
|
it "should close the other book and open the new book, if :if_obstructed is :forget" do
|
@@ -535,7 +581,7 @@ describe Book do
|
|
535
581
|
if :if_obstructed is :close_if_saved" do
|
536
582
|
expect{
|
537
583
|
@new_book = Book.open(@simple_file, :if_obstructed => :close_if_saved)
|
538
|
-
}.to raise_error(ExcelErrorOpen, "book with the same name in a different path is unsaved")
|
584
|
+
}.to raise_error(ExcelErrorOpen, "book with the same name in a different path is unsaved: workbook.xls")
|
539
585
|
@book.save
|
540
586
|
@new_book = Book.open(@simple_file, :if_obstructed => :close_if_saved)
|
541
587
|
@book.should_not be_alive
|
@@ -557,13 +603,13 @@ describe Book do
|
|
557
603
|
it "should raise an error, if :if_obstructed is default" do
|
558
604
|
expect {
|
559
605
|
@new_book = Book.open(@simple_file)
|
560
|
-
}.to raise_error(ExcelErrorOpen, "blocked by a book with the same name in a different path")
|
606
|
+
}.to raise_error(ExcelErrorOpen, "blocked by a book with the same name in a different path: workbook.xls")
|
561
607
|
end
|
562
608
|
|
563
609
|
it "should raise an error, if :if_obstructed is invalid option" do
|
564
610
|
expect {
|
565
611
|
@new_book = Book.open(@simple_file, :if_obstructed => :invalid_option)
|
566
|
-
}.to raise_error(ExcelErrorOpen, ":if_obstructed: invalid option")
|
612
|
+
}.to raise_error(ExcelErrorOpen, ":if_obstructed: invalid option: invalid_option")
|
567
613
|
end
|
568
614
|
end
|
569
615
|
end
|
@@ -620,7 +666,7 @@ describe Book do
|
|
620
666
|
|
621
667
|
it "should create a workbook by default" do
|
622
668
|
File.delete @simple_save_file rescue nil
|
623
|
-
book = Book.open(@simple_save_file
|
669
|
+
book = Book.open(@simple_save_file)
|
624
670
|
book.should be_a Book
|
625
671
|
book.close
|
626
672
|
File.exist?(@simple_save_file).should be_true
|
@@ -822,6 +868,13 @@ describe Book do
|
|
822
868
|
|
823
869
|
context "with no open book" do
|
824
870
|
|
871
|
+
it "should open unobtrusively if no Excel is open" do
|
872
|
+
Excel.close_all
|
873
|
+
Book.unobtrusively(@simple_file, :if_closed => :reuse) do |book|
|
874
|
+
book.should be_a Book
|
875
|
+
end
|
876
|
+
end
|
877
|
+
|
825
878
|
it "should open unobtrusively in a new Excel" do
|
826
879
|
expect{ unobtrusively_ok? }.to_not raise_error
|
827
880
|
end
|
@@ -855,9 +908,38 @@ describe Book do
|
|
855
908
|
book.should be_a Book
|
856
909
|
book.should be_alive
|
857
910
|
book.excel.should_not == excel
|
911
|
+
book.excel.should == new_excel
|
912
|
+
end
|
913
|
+
end
|
914
|
+
|
915
|
+
it "should open unobtrusively in a given Excel via a book" do
|
916
|
+
book1 = Book.open(@different_file)
|
917
|
+
book2 = Book.open(@more_simple_file, :force_excel => :new)
|
918
|
+
Book.unobtrusively(@simple_file, :if_closed => book2) do |book|
|
919
|
+
book.should be_a Book
|
920
|
+
book.should be_alive
|
921
|
+
book.excel.should_not == book1.excel
|
922
|
+
book.excel.should == book2.excel
|
858
923
|
end
|
859
924
|
end
|
860
925
|
|
926
|
+
it "should raise an error if the excel instance is not alive" do
|
927
|
+
excel = Excel.new(:reuse => false)
|
928
|
+
new_excel = Excel.new(:reuse => false)
|
929
|
+
Excel.close_all
|
930
|
+
expect{
|
931
|
+
Book.unobtrusively(@simple_file, :if_closed => new_excel) do |book|
|
932
|
+
end
|
933
|
+
}.to raise_error(ExcelErrorOpen, "provided Excel instance is not alive")
|
934
|
+
end
|
935
|
+
|
936
|
+
it "should raise an error if the option is invalid" do
|
937
|
+
expect{
|
938
|
+
Book.unobtrusively(@simple_file, :if_closed => :invalid_option) do |book|
|
939
|
+
end
|
940
|
+
}.to raise_error(ExcelErrorOpen, "provided instance is neither an Excel nor a Book: invalid_option")
|
941
|
+
end
|
942
|
+
|
861
943
|
end
|
862
944
|
|
863
945
|
context "with an open book" do
|
@@ -1038,33 +1120,8 @@ describe Book do
|
|
1038
1120
|
book.excel.should == new_excel
|
1039
1121
|
end
|
1040
1122
|
end
|
1041
|
-
|
1042
|
-
it "should use not the given excel if the Excels are closed" do
|
1043
|
-
excel = Excel.new(:reuse => false)
|
1044
|
-
sheet = @book[0]
|
1045
|
-
old_cell_value = sheet[0,0].value
|
1046
|
-
old_excel = @book.excel
|
1047
|
-
@book.close
|
1048
|
-
@book.should_not be_alive
|
1049
|
-
Excel.close_all
|
1050
|
-
Book.unobtrusively(@simple_file, :if_closed => excel, :keep_open => true) do |book|
|
1051
|
-
book.should be_a Book
|
1052
|
-
book.excel.should_not == old_excel
|
1053
|
-
book.excel.should == @book.excel
|
1054
|
-
book.excel.should_not == excel
|
1055
|
-
sheet = book[0]
|
1056
|
-
cell = sheet[0,0]
|
1057
|
-
sheet[0,0] = cell.value == "simple" ? "complex" : "simple"
|
1058
|
-
book.Saved.should be_false
|
1059
|
-
end
|
1060
|
-
@book.should be_alive
|
1061
|
-
new_book = Book.open(@simple_file)
|
1062
|
-
sheet = new_book[0]
|
1063
|
-
sheet[0,0].value.should_not == old_cell_value
|
1064
|
-
end
|
1065
1123
|
end
|
1066
1124
|
|
1067
|
-
|
1068
1125
|
context "with a read_only book" do
|
1069
1126
|
|
1070
1127
|
before do
|
@@ -1405,24 +1462,6 @@ describe Book do
|
|
1405
1462
|
@book1.excel.Visible.should be_true
|
1406
1463
|
end
|
1407
1464
|
|
1408
|
-
it "should open the book unobtrusively visible" do
|
1409
|
-
@book1 = Book.open(@simple_file)
|
1410
|
-
@book1.excel.Visible.should be_false
|
1411
|
-
Book.unobtrusively(@simple_file, :visible => true) do |book|
|
1412
|
-
book.excel.Visible.should be_true
|
1413
|
-
end
|
1414
|
-
@book1.excel.Visible.should be_false
|
1415
|
-
end
|
1416
|
-
|
1417
|
-
it "should open the book unobtrusively invisible" do
|
1418
|
-
@book1 = Book.open(@simple_file, :visible => true)
|
1419
|
-
@book1.excel.Visible.should be_true
|
1420
|
-
Book.unobtrusively(@simple_file, :visible => false) do |book|
|
1421
|
-
book.excel.Visible.should be_false
|
1422
|
-
end
|
1423
|
-
@book1.excel.Visible.should be_true
|
1424
|
-
end
|
1425
|
-
|
1426
1465
|
end
|
1427
1466
|
|
1428
1467
|
context "with several Excel instances" do
|
@@ -1576,8 +1615,10 @@ describe Book do
|
|
1576
1615
|
end
|
1577
1616
|
end
|
1578
1617
|
|
1579
|
-
describe "nvalue" do
|
1580
|
-
|
1618
|
+
describe "nvalue, set_nvalue, rename_range" do
|
1619
|
+
|
1620
|
+
context "nvalue" do
|
1621
|
+
|
1581
1622
|
before do
|
1582
1623
|
@book1 = Book.open(@more_simple_file)
|
1583
1624
|
end
|
@@ -1606,6 +1647,42 @@ describe Book do
|
|
1606
1647
|
}.to raise_error(ExcelErrorNValue, "range error in more_workbook.xls")
|
1607
1648
|
end
|
1608
1649
|
end
|
1650
|
+
|
1651
|
+
context "set_nvalue" do
|
1652
|
+
|
1653
|
+
before do
|
1654
|
+
@book1 = Book.open(@more_simple_file)
|
1655
|
+
end
|
1656
|
+
|
1657
|
+
after do
|
1658
|
+
@book1.close(:if_unsaved => :forget)
|
1659
|
+
end
|
1660
|
+
|
1661
|
+
it "should set value of a range" do
|
1662
|
+
@book1.nvalue("new").should == "foo"
|
1663
|
+
@book1.set_nvalue("new","bar")
|
1664
|
+
@book1.nvalue("new").should == "bar"
|
1665
|
+
end
|
1666
|
+
end
|
1667
|
+
|
1668
|
+
context "rename_range" do
|
1669
|
+
|
1670
|
+
before do
|
1671
|
+
@book1 = Book.open(@more_simple_file)
|
1672
|
+
end
|
1673
|
+
|
1674
|
+
after do
|
1675
|
+
@book1.close(:if_unsaved => :forget)
|
1676
|
+
end
|
1677
|
+
|
1678
|
+
it "should rename a range" do
|
1679
|
+
@book1.rename_range("four","five")
|
1680
|
+
@book1.nvalue("five").should == [[1,2],[3,4]]
|
1681
|
+
expect {
|
1682
|
+
@book1.rename_range("four","five")
|
1683
|
+
}.to raise_error(ExcelErrorRename, "name four not in more_workbook.xls")
|
1684
|
+
end
|
1685
|
+
end
|
1609
1686
|
end
|
1610
1687
|
|
1611
1688
|
describe "close" do
|
@@ -1683,6 +1760,13 @@ describe Book do
|
|
1683
1760
|
end
|
1684
1761
|
end
|
1685
1762
|
|
1763
|
+
it "should raise an error for invalid option" do
|
1764
|
+
expect {
|
1765
|
+
@book.close(:if_unsaved => :invalid_option)
|
1766
|
+
}.to raise_error(ExcelErrorClose, ":if_unsaved: invalid option: invalid_option")
|
1767
|
+
end
|
1768
|
+
|
1769
|
+
|
1686
1770
|
it "should save the book before close with option :save" do
|
1687
1771
|
ole_workbook = @book.workbook
|
1688
1772
|
excel = @book.excel
|
@@ -1749,6 +1833,7 @@ describe Book do
|
|
1749
1833
|
describe "save" do
|
1750
1834
|
|
1751
1835
|
context "with simple save" do
|
1836
|
+
|
1752
1837
|
it "should save for a file opened without :read_only" do
|
1753
1838
|
@book = Book.open(@simple_file)
|
1754
1839
|
@book.add_sheet(@sheet, :as => 'a_name')
|
@@ -1767,6 +1852,7 @@ describe Book do
|
|
1767
1852
|
}.to raise_error(ExcelErrorSave, "Not opened for writing (opened with :read_only option)")
|
1768
1853
|
@book.close
|
1769
1854
|
end
|
1855
|
+
|
1770
1856
|
end
|
1771
1857
|
|
1772
1858
|
context "with open with read only" do
|
@@ -1959,7 +2045,7 @@ describe Book do
|
|
1959
2045
|
@book.save_as(@simple_save_file)
|
1960
2046
|
expect {
|
1961
2047
|
@book.save_as(@simple_save_file, :if_exists => :invalid_option)
|
1962
|
-
}.to raise_error(ExcelErrorSave, ':if_exists: invalid option')
|
2048
|
+
}.to raise_error(ExcelErrorSave, ':if_exists: invalid option: invalid_option')
|
1963
2049
|
end
|
1964
2050
|
end
|
1965
2051
|
end
|
data/spec/cell_spec.rb
CHANGED
@@ -20,7 +20,7 @@ describe RobustExcelOle::Cell do
|
|
20
20
|
|
21
21
|
context "open simple.xls" do
|
22
22
|
before do
|
23
|
-
@book = RobustExcelOle::Book.open(@dir + '/
|
23
|
+
@book = RobustExcelOle::Book.open(@dir + '/workbook.xls', :read_only => true)
|
24
24
|
@sheet = @book[1]
|
25
25
|
@cell = @sheet[0, 0]
|
26
26
|
end
|
File without changes
|
Binary file
|
data/spec/data/workbook.xls
CHANGED
Binary file
|
Binary file
|
Binary file
|
data/spec/excel_spec.rb
CHANGED
@@ -15,6 +15,7 @@ module RobustExcelOle
|
|
15
15
|
before do
|
16
16
|
@dir = create_tmpdir
|
17
17
|
@simple_file = @dir + '/simple.xls'
|
18
|
+
@invalid_name_file = 'b/simple.xls'
|
18
19
|
end
|
19
20
|
|
20
21
|
after do
|
@@ -56,23 +57,17 @@ module RobustExcelOle
|
|
56
57
|
|
57
58
|
it "should create different excel" do
|
58
59
|
excel2 = Excel.create
|
59
|
-
#puts "@excel1 #{@excel1.Hwnd}"
|
60
|
-
#puts "excel2 #{excel2.Hwnd}"
|
61
60
|
excel2.Hwnd.should_not == @excel1.Hwnd
|
62
61
|
end
|
63
62
|
|
64
63
|
it "should reuse existing excel" do
|
65
64
|
excel2 = Excel.current
|
66
|
-
#puts "@excel1 #{@excel1.Hwnd}"
|
67
|
-
#puts "excel2 #{excel2.Hwnd}"
|
68
65
|
excel2.Hwnd.should == @excel1.Hwnd
|
69
66
|
end
|
70
67
|
|
71
68
|
it "should reuse existing excel with default options for 'new'" do
|
72
69
|
excel2 = Excel.new
|
73
70
|
excel2.should be_a Excel
|
74
|
-
#puts "@excel1 #{@excel1.Hwnd}"
|
75
|
-
#puts "excel2 #{excel2.Hwnd}"
|
76
71
|
excel2.Hwnd.should == @excel1.Hwnd
|
77
72
|
end
|
78
73
|
|
@@ -173,7 +168,6 @@ module RobustExcelOle
|
|
173
168
|
|
174
169
|
end
|
175
170
|
|
176
|
-
|
177
171
|
context "with displayalerts" do
|
178
172
|
before do
|
179
173
|
@excel1 = Excel.new(:displayalerts => true)
|
@@ -248,21 +242,56 @@ module RobustExcelOle
|
|
248
242
|
|
249
243
|
before do
|
250
244
|
@excel1 = Excel.create
|
245
|
+
@file_name = @dir + '/bar.xls'
|
251
246
|
end
|
252
247
|
|
253
248
|
it "should generate a workbook" do
|
254
|
-
|
255
|
-
workbook
|
256
|
-
|
249
|
+
workbook = @excel1.generate_workbook(@file_name)
|
250
|
+
workbook.should be_a WIN32OLE
|
251
|
+
workbook.Name.should == File.basename(@file_name)
|
252
|
+
workbook.FullName.should == RobustExcelOle::absolute_path(@file_name)
|
253
|
+
workbook.Saved.should be_true
|
254
|
+
workbook.ReadOnly.should be_false
|
255
|
+
workbook.Sheets.Count.should == 3
|
256
|
+
workbooks = @excel1.Workbooks
|
257
|
+
workbooks.Count.should == 1
|
258
|
+
end
|
259
|
+
|
260
|
+
it "should generate the same workbook twice" do
|
261
|
+
workbook = @excel1.generate_workbook(@file_name)
|
257
262
|
workbook.should be_a WIN32OLE
|
258
|
-
workbook.Name.should == File.basename(@
|
259
|
-
workbook.FullName.should == RobustExcelOle::absolute_path(@
|
263
|
+
workbook.Name.should == File.basename(@file_name)
|
264
|
+
workbook.FullName.should == RobustExcelOle::absolute_path(@file_name)
|
260
265
|
workbook.Saved.should be_true
|
261
266
|
workbook.ReadOnly.should be_false
|
262
|
-
workbook.Sheets.Count ==
|
263
|
-
workbooks =
|
267
|
+
workbook.Sheets.Count.should == 3
|
268
|
+
workbooks = @excel1.Workbooks
|
264
269
|
workbooks.Count.should == 1
|
270
|
+
workbook2 = @excel1.generate_workbook(@file_name)
|
271
|
+
workbook2.should be_a WIN32OLE
|
272
|
+
workbooks = @excel1.Workbooks
|
273
|
+
workbooks.Count.should == 2
|
265
274
|
end
|
275
|
+
|
276
|
+
it "should generate a workbook if one is already existing" do
|
277
|
+
book = Book.open(@simple_file)
|
278
|
+
workbook = @excel1.generate_workbook(@file_name)
|
279
|
+
workbook.should be_a WIN32OLE
|
280
|
+
workbook.Name.should == File.basename(@file_name)
|
281
|
+
workbook.FullName.should == RobustExcelOle::absolute_path(@file_name)
|
282
|
+
workbook.Saved.should be_true
|
283
|
+
workbook.ReadOnly.should be_false
|
284
|
+
workbook.Sheets.Count.should == 3
|
285
|
+
workbooks = @excel1.Workbooks
|
286
|
+
workbooks.Count.should == 2
|
287
|
+
end
|
288
|
+
|
289
|
+
it "should raise error when book cannot be saved" do
|
290
|
+
expect{
|
291
|
+
workbook = @excel1.generate_workbook(@invalid_name_file)
|
292
|
+
}.to raise_error(ExcelErrorSaveUnknown)
|
293
|
+
end
|
294
|
+
|
266
295
|
end
|
267
296
|
end
|
268
297
|
end
|
@@ -284,5 +313,5 @@ module RobustExcelOle
|
|
284
313
|
end
|
285
314
|
end
|
286
315
|
|
287
|
-
class TestError < RuntimeError
|
316
|
+
class TestError < RuntimeError # :nodoc: #
|
288
317
|
end
|
data/spec/range_spec.rb
CHANGED
@@ -12,7 +12,7 @@ describe RobustExcelOle::Range do
|
|
12
12
|
|
13
13
|
before do
|
14
14
|
@dir = create_tmpdir
|
15
|
-
@book = RobustExcelOle::Book.open(@dir + '/
|
15
|
+
@book = RobustExcelOle::Book.open(@dir + '/workbook.xls')
|
16
16
|
@sheet = @book[1]
|
17
17
|
@range = RobustExcelOle::Range.new(@sheet.sheet.UsedRange.Rows(1))
|
18
18
|
end
|
data/spec/sheet_spec.rb
CHANGED
@@ -7,7 +7,7 @@ describe RobustExcelOle::Sheet do
|
|
7
7
|
|
8
8
|
before do
|
9
9
|
@dir = create_tmpdir
|
10
|
-
@book = RobustExcelOle::Book.open(@dir + '/
|
10
|
+
@book = RobustExcelOle::Book.open(@dir + '/workbook.xls', :read_only => true)
|
11
11
|
@sheet = @book[0]
|
12
12
|
end
|
13
13
|
|
@@ -351,7 +351,7 @@ describe RobustExcelOle::Sheet do
|
|
351
351
|
describe "nvalue" do
|
352
352
|
context "with standard" do
|
353
353
|
before do
|
354
|
-
@book1 = RobustExcelOle::Book.open(@dir + '/
|
354
|
+
@book1 = RobustExcelOle::Book.open(@dir + '/more_workbook.xls', :read_only => true)
|
355
355
|
@sheet1 = @book1[0]
|
356
356
|
end
|
357
357
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: robust_excel_ole
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 3
|
9
|
-
-
|
10
|
-
version: 0.3.
|
9
|
+
- 4
|
10
|
+
version: 0.3.4
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- traths
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2015-
|
18
|
+
date: 2015-07-03 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -55,7 +55,11 @@ files:
|
|
55
55
|
- TodoList.md
|
56
56
|
- examples/edit_sheets/example_access_sheets_and_cells.rb
|
57
57
|
- examples/edit_sheets/example_adding_sheets.rb
|
58
|
+
- examples/edit_sheets/example_concating.rb
|
59
|
+
- examples/edit_sheets/example_expanding.rb
|
60
|
+
- examples/edit_sheets/example_naming.rb
|
58
61
|
- examples/edit_sheets/example_ranges.rb
|
62
|
+
- examples/edit_sheets/example_saving.rb
|
59
63
|
- examples/open_save_close/example_control_to_excel.rb
|
60
64
|
- examples/open_save_close/example_default_excel.rb
|
61
65
|
- examples/open_save_close/example_force_excel.rb
|
@@ -70,7 +74,6 @@ files:
|
|
70
74
|
- examples/open_save_close/example_reuse.rb
|
71
75
|
- examples/open_save_close/example_simple.rb
|
72
76
|
- examples/open_save_close/example_unobtrusively.rb
|
73
|
-
- examples/save_sheets/example_save_sheets.rb
|
74
77
|
- lib/robust_excel_ole.rb
|
75
78
|
- lib/robust_excel_ole/book.rb
|
76
79
|
- lib/robust_excel_ole/book_store.rb
|
@@ -91,12 +94,14 @@ files:
|
|
91
94
|
- spec/data/book_with_blank.xls
|
92
95
|
- spec/data/different_workbook.xls
|
93
96
|
- spec/data/merge_cells.xls
|
94
|
-
- spec/data/more_data/
|
97
|
+
- spec/data/more_data/workbook.xls
|
95
98
|
- spec/data/more_workbook.xls
|
96
99
|
- spec/data/protected_sheet.xls
|
97
100
|
- spec/data/workbook.xls
|
98
101
|
- spec/data/workbook.xlsm
|
99
102
|
- spec/data/workbook.xlsx
|
103
|
+
- spec/data/workbook_connected.xlsm
|
104
|
+
- spec/data/workbook_connected_sub.xlsm
|
100
105
|
- spec/excel_spec.rb
|
101
106
|
- spec/helpers/create_temporary_dir.rb
|
102
107
|
- spec/helpers/key_sender.rb
|
@@ -1,34 +0,0 @@
|
|
1
|
-
# example_save_sheets.rb:
|
2
|
-
# save the sheets of a book as separate books
|
3
|
-
|
4
|
-
require File.join(File.dirname(__FILE__), '../../lib/robust_excel_ole')
|
5
|
-
require File.join(File.dirname(__FILE__), '../../spec/helpers/create_temporary_dir')
|
6
|
-
require "fileutils"
|
7
|
-
|
8
|
-
include RobustExcelOle
|
9
|
-
|
10
|
-
Excel.close_all
|
11
|
-
begin
|
12
|
-
dir = create_tmpdir
|
13
|
-
suffix = '.xls'
|
14
|
-
book_name = dir + 'book_with_blank'
|
15
|
-
book = Book.open(book_name + suffix) # open a book with several sheets
|
16
|
-
book.visible = true # make Excel visible
|
17
|
-
i = 0
|
18
|
-
book.each do |sheet|
|
19
|
-
i = i + 1
|
20
|
-
puts "#{i}. sheet:"
|
21
|
-
sheet_name = book_name + "_sheet#{i}"
|
22
|
-
puts "sheet_name: #{sheet_name}"
|
23
|
-
Excel.generate_workbook absolute_path(sheet_name) # generate an empty workbook
|
24
|
-
sheet_book = Book.open(absolute_path(sheet_name) + suffix) # open the book
|
25
|
-
sheet_book.add_sheet sheet # add the sheet
|
26
|
-
sheet_book.save # save it
|
27
|
-
sheet_book.close # close it
|
28
|
-
end
|
29
|
-
|
30
|
-
ensure
|
31
|
-
Excel.close_all # close workbooks, quit Excel application
|
32
|
-
rm_tmp(dir)
|
33
|
-
end
|
34
|
-
|