robust_excel_ole 0.3.3 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
-
|