robust_excel_ole 0.5 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Changelog +14 -1
- data/README.rdoc +18 -4
- data/README_detail.rdoc +45 -7
- data/lib/robust_excel_ole/book.rb +35 -43
- data/lib/robust_excel_ole/excel.rb +18 -11
- data/lib/robust_excel_ole/sheet.rb +40 -16
- data/lib/robust_excel_ole/version.rb +1 -1
- data/spec/book_spec.rb +1 -1
- data/spec/book_specs/book_open_spec.rb +88 -10
- data/spec/book_specs/book_save_spec.rb +3 -3
- data/spec/book_specs/book_unobtr_spec.rb +2 -2
- data/spec/data/another_workbook.xls +0 -0
- data/spec/data/different_workbook.xls +0 -0
- data/spec/data/workbook.xls +0 -0
- data/spec/excel_spec.rb +79 -35
- data/spec/sheet_spec.rb +59 -17
- metadata +4 -3
data/Changelog
CHANGED
@@ -1,19 +1,32 @@
|
|
1
1
|
# Change Log
|
2
2
|
All notable changes to this project will be documented in this file.
|
3
3
|
|
4
|
+
## [0.5.1] - 2016-18-06
|
5
|
+
|
6
|
+
### Added
|
7
|
+
- Book#open :force_excel => :active
|
8
|
+
|
9
|
+
### Changed
|
10
|
+
- Book: open: :default_excel, :force_excel => :active, (:reuse as alias), bug fix in :default
|
11
|
+
unobtrusively: :if_closed => :active (:reuse as alias)
|
12
|
+
- Excel: with_calculation: bug fix
|
13
|
+
- Sheet: [], []= broader implementation
|
14
|
+
|
15
|
+
|
4
16
|
## [0.5.0] - 2016-31-05
|
5
17
|
|
6
18
|
### Added
|
7
19
|
- Book: sheet, add_empty_sheet, copy_sheet
|
8
20
|
rangeval, set_rangeval, nameval, set_nameval
|
9
21
|
open: option check_compatibility
|
10
|
-
- Sheet: last_sheet, first_sheet, rangeval, nameval
|
22
|
+
- Sheet: last_sheet, first_sheet, rangeval, nameval, [], []=
|
11
23
|
- Excel: with_calculaiton, rangeval, set_rangeval, nameval, set_nameval, [], []=
|
12
24
|
|
13
25
|
### Changed
|
14
26
|
- Book: book.sheet(<sheet_name>) replaces book[<sheet-name>]
|
15
27
|
add_or_copy_sheet replaces add_sheet
|
16
28
|
name_val, set_name_val replaces n_value, set_n_value
|
29
|
+
[], []= via nameval, set_nameval
|
17
30
|
|
18
31
|
|
19
32
|
## [0.4] - 2016-03-16
|
data/README.rdoc
CHANGED
@@ -43,14 +43,28 @@ Options are
|
|
43
43
|
+:default_excel+, +:force_excel+, +:if_absent+, +:if_unsaved+, +:if_obstructed+,
|
44
44
|
+:read_only+, +:check_compatibility, +:visible+, +:displayalerts+.
|
45
45
|
|
46
|
-
Valid values for +:default_excel+ are +:reuse
|
46
|
+
Valid values for +:default_excel+ are +:active+ (or +:reuse+), +:new+ or some Excel instance, for +:force_excel+ : +:active (or +:reuse+), +:new+ or some Excel instance, for +:if_unsaved+ : +:raise+, +:accept+, +:forget+, +:alert+ and +:new_excel+, for +:if_obstructed+ : +:raise+, +:save+, +:close_if_saved+, +:forget+, +:alert+ and +:new_excel+ , for +:if_absent+ : +:raise+ and +:create+.
|
47
47
|
|
48
48
|
Here are a few examples:
|
49
49
|
|
50
|
-
Opening a workbook in the Excel instance where it was opened before,
|
50
|
+
Opening a workbook in the Excel instance where it was opened before most recently, if it was opened before and this Excel instance is alive. Otherwise opening it in a running Excel, if it exists, or in a new Excel.
|
51
|
+
|
52
|
+
Opening a workbook in the Excel instance where it was opened before most recently, if it was opened before and this Excel instance is alive. Otherwise opening it in a new Excel instance.
|
51
53
|
|
52
54
|
book = Book.open('workbook.xls', :default_excel => :new)
|
53
55
|
|
56
|
+
Opening a workbook in the Excel instance where it was opened before most recently, if it was opened before and this Excel instance is alive. Otherwise opening it in a given Excel instance.
|
57
|
+
|
58
|
+
book = Book.open('workbook.xls', :default_excel => excel1)
|
59
|
+
|
60
|
+
Opening a workbook in a new Excel instance, no matter if the workbook was opened before and if the old Excel instance is alive.
|
61
|
+
|
62
|
+
book = Book.open('workbook.xls', :force_excel => :new)
|
63
|
+
|
64
|
+
Opening a workbook in a given Excel instance, no matter if the workbook was opened before and if the old Excel instance is alive.
|
65
|
+
|
66
|
+
book = Book.open('workbook.xls', :force_excel => excel1)
|
67
|
+
|
54
68
|
Opening a workbook in a new Excel instance and make it visible.
|
55
69
|
|
56
70
|
book = Book.open('workbook.xls', :force_excel => :new, :visible => true)
|
@@ -123,11 +137,11 @@ If a workbook is blocking the workbook that should be saved, then the former one
|
|
123
137
|
|
124
138
|
The method +unobtrusively+ enables the user to read or modify a workbook, no matter if it is open in some Excel instance, if it is saved or unsaved, and if it is writable or not. When opening a workbook unobtrusively, its status remains unchanged. This status includes, whether the workbook is opened or closed, saved or unsaved, readonly or writable.
|
125
139
|
|
126
|
-
Some options determine the Excel instance in which a closed workbook is opened. The options +:reuse (default) indicates that the closed workbook is opened in the Excel instance where the workbooks is opened, if such an Excel instance exists, otherwise that another Excel instance is reused. The option +:hidden+ provokes that the closed workbook is opened in a separate Excel instance that is not visible and has no DisplayAlerts. Any following closed workbook would be opened in this Excel instance as well when using this option. Moreover, an Excel instance can be given directly where to open the closed workbook.
|
140
|
+
Some options determine the Excel instance in which a closed workbook is opened. The options +:active+ (or +:reuse+) (default) indicates that the closed workbook is opened in the Excel instance where the workbooks is opened, if such an Excel instance exists, otherwise that another Excel instance is reused. The option +:hidden+ provokes that the closed workbook is opened in a separate Excel instance that is not visible and has no DisplayAlerts. Any following closed workbook would be opened in this Excel instance as well when using this option. Moreover, an Excel instance can be given directly where to open the closed workbook.
|
127
141
|
|
128
142
|
Further options are +:read_only+, +:readonly_excel+, and +:keep_open. The option +:readonly_excel+ chooses whether a book that is opened in read only mode. If the workbook is opened as read only, then the option +:readonly_excel+ determines whether to close the workbook and open it as writable in the Excel instance where it was open so far, or to open it as writable in another running Excel instance, if such an instance exists, or to open it in a new Excel instance. Moreover, there are the options +:visible+, +:displayalerts+ and +:check_compatiblity.
|
129
143
|
|
130
|
-
Book.unobtrusively('workbook.xls', :
|
144
|
+
Book.unobtrusively('workbook.xls', :active, :read_only => false, :keep_open => false) do |book|
|
131
145
|
# some modification
|
132
146
|
sheet = book[0]
|
133
147
|
sheet[1,1] = "c"
|
data/README_detail.rdoc
CHANGED
@@ -41,8 +41,9 @@ The semantics is similar to, e.g., +File.open+.
|
|
41
41
|
|
42
42
|
Options are the following:
|
43
43
|
|
44
|
-
+:default_excel+:: open the workbook in the Excel instance where it was opened before
|
45
|
-
|
44
|
+
+:default_excel+:: open the workbook in the Excel instance where it was opened before most recently,
|
45
|
+
if the book was opened before and this Excel instance is alive. Otherwise open it in the active (+:active+ or +:reuse+), a new (+:new+) or a given Excel instance (default: +reuse+)
|
46
|
+
+:force_excel+:: open the workbook in the active, a new or given Excel instance
|
46
47
|
+:if_absent+:: specify behaviour if the workbook with the given file name does not exist if the workbook does not exist (default: +create+)
|
47
48
|
+:if_unsaved+:: specify behaviour if the workbook was unsaved (default: +new_excel+)
|
48
49
|
+:if_obstructed+:: specidy behaviour if the workbook is blocked by another book (default: +new_excel+)
|
@@ -53,15 +54,16 @@ Options are the following:
|
|
53
54
|
|
54
55
|
The option +:defaut_excel+ :
|
55
56
|
|
56
|
-
If the workbook was open before, then open it in the Excel instance where it was open before. If the workbook cannot be reopened,
|
57
|
+
If the workbook was open before, then open it in the Excel instance where it was open before most recently. If the workbook cannot be reopened, i.e., the book was not opened before, or the Excel is not alive anymore,
|
58
|
+
then
|
57
59
|
|
58
|
-
+:reuse
|
60
|
+
+:active+ (or :reuse+:): Connect to a running Excel, if it exists, otherwise open a new Excel.
|
59
61
|
+:new+:: Open in a new Excel.
|
60
62
|
[instance]:: Open in a given Excel instance.
|
61
63
|
|
62
64
|
The option +:force_excel :
|
63
65
|
|
64
|
-
No matter if the workbook was open before,
|
66
|
+
No matter if the workbook was open before, or the Excel instance is alive
|
65
67
|
|
66
68
|
+:new+:: Open in a new Excel instance.
|
67
69
|
[instance]:: Open in a given Excel instance.
|
@@ -95,6 +97,41 @@ If a workbook is open and a new workbook with same name and a different path is
|
|
95
97
|
|
96
98
|
The values :displayalerts and :visible are reached to the class Excel that controls opening and closing Excel instances.
|
97
99
|
|
100
|
+
Here are a few examples:
|
101
|
+
|
102
|
+
Opening a workbook in the Excel instance where it was opened before most recently, if it was opened before and this Excel instance is alive. Otherwise opening it in a running Excel, if it exists, or in a new Excel.
|
103
|
+
|
104
|
+
Opening a workbook in the Excel instance where it was opened before most recently, if it was opened before and this Excel instance is alive. Otherwise opening it in a new Excel instance.
|
105
|
+
|
106
|
+
book = Book.open('workbook.xls', :default_excel => :new)
|
107
|
+
|
108
|
+
Opening a workbook in the Excel instance where it was opened before most recently, if it was opened before and this Excel instance is alive. Otherwise opening it in a given Excel instance.
|
109
|
+
|
110
|
+
book = Book.open('workbook.xls', :default_excel => excel1)
|
111
|
+
|
112
|
+
Opening a workbook in a new Excel instance, no matter if the workbook was opened before and if the old Excel instance is alive.
|
113
|
+
|
114
|
+
book = Book.open('workbook.xls', :force_excel => :new)
|
115
|
+
|
116
|
+
Opening a workbook in a given Excel instance, no matter if the workbook was opened before and if the old Excel instance is alive.
|
117
|
+
|
118
|
+
book = Book.open('workbook.xls', :force_excel => excel1)
|
119
|
+
|
120
|
+
Opening a workbook in a new Excel instance and make it visible.
|
121
|
+
|
122
|
+
book = Book.open('workbook.xls', :force_excel => :new, :visible => true)
|
123
|
+
|
124
|
+
If a workbook contains unsaved changes and a workbook with the same filename shall be opened, then Excel gives an alert message.
|
125
|
+
The option +:if_unsaved+ manages this case. For example, +:if_unsaved+ => +:accept+ indicates that the workbook remains open, but no error is raised, i.e. the program can continue.
|
126
|
+
|
127
|
+
book = Book.open('workbook.xls', :if_unsaved => :accept)
|
128
|
+
|
129
|
+
If a workbook is open and a workbook with the same name but in different path shall be opened, then the first workbook blocks opening the other workbook. The option +:if_obstructed+ handles this situation. For example, +:if_obstructed+ => +:forget+ causes the old workbook to close and to open the new workbook.
|
130
|
+
|
131
|
+
book = Book.open('path/workbook.xls', :if_obstructed => :forget)
|
132
|
+
|
133
|
+
Opening linked workbooks for EXCEL 2007 is supported
|
134
|
+
|
98
135
|
=== Closing a workbook.
|
99
136
|
|
100
137
|
Simple close.
|
@@ -176,11 +213,11 @@ If a workbook is blocking the workbook that should be saved, then the former one
|
|
176
213
|
|
177
214
|
The method +unobtrusively+ enables the user to read or modify a workbook, no matter if it is open in some Excel instance, if it is saved or unsaved, and if it is writable or not. When opening a workbook unobtrusively, its status remains unchanged. This status includes, whether the workbook is opened or closed, saved or unsaved, readonly or writable.
|
178
215
|
|
179
|
-
One option chooses the Excel instance in which a closed workbook is opened. The options +:reuse (default) indicates that the closed workbook is opened in the Excel instance of the workbook, if it exists, or that another Excel instance is reused. The option +:hidden+ provokes that the closed workbook is opened in a separate Excel instance that is not visible and has no DisplayAlerts. Any following closed workbook would be opened in this Excel instance as well when using this option. Moreover, an Excel instance can be given directly where to open the closed workbook.
|
216
|
+
One option chooses the Excel instance in which a closed workbook is opened. The options +:active+ (or +:reuse) (default) indicates that the closed workbook is opened in the Excel instance of the workbook, if it exists, or that another Excel instance is reused. The option +:hidden+ provokes that the closed workbook is opened in a separate Excel instance that is not visible and has no DisplayAlerts. Any following closed workbook would be opened in this Excel instance as well when using this option. Moreover, an Excel instance can be given directly where to open the closed workbook.
|
180
217
|
|
181
218
|
Options are the following:
|
182
219
|
|
183
|
-
+:reuse
|
220
|
+
+:active (or +:reuse+:): (default) : open a closed workbook in the Excel instance of the workbook, if it exists, otherwise reuse another Excel
|
184
221
|
+:hidden+:: : open a closed workbook in one separate Excel instance that is not visible and has no displayalerts
|
185
222
|
<excel-instance> : open a closed workbooks in the given Excel instance
|
186
223
|
|
@@ -413,6 +450,7 @@ Creating a new Excel.
|
|
413
450
|
excel1 = Excel.create
|
414
451
|
|
415
452
|
Getting a running Excel instance and reusing it.
|
453
|
+
Connecting to the first opened Excel instance. If this Excel instance is being closed, then Excel creates a new Excel instance that has the same Hwnd
|
416
454
|
|
417
455
|
excel2 = Excel.current
|
418
456
|
|
@@ -15,9 +15,8 @@ module RobustExcelOle
|
|
15
15
|
alias ole_object ole_workbook
|
16
16
|
|
17
17
|
DEFAULT_OPEN_OPTS = {
|
18
|
-
:excel => :
|
19
|
-
:default_excel => :
|
20
|
-
:if_lockraiseed => :readonly,
|
18
|
+
:excel => :active,
|
19
|
+
:default_excel => :active,
|
21
20
|
:if_unsaved => :raise,
|
22
21
|
:if_obstructed => :raise,
|
23
22
|
:if_absent => :raise,
|
@@ -30,8 +29,8 @@ module RobustExcelOle
|
|
30
29
|
# opens a workbook.
|
31
30
|
# @param [String] file the file name
|
32
31
|
# @param [Hash] opts the options
|
33
|
-
# @option opts [Variant] :default_excel :
|
34
|
-
# @option opts [Variant] :force_excel :new
|
32
|
+
# @option opts [Variant] :default_excel :active (default), :new, or <excel-instance>
|
33
|
+
# @option opts [Variant] :force_excel :active, :new, or <excel-instance>
|
35
34
|
# @option opts [Symbol] :if_unsaved :raise (default), :forget, :accept, :alert, :excel, or :new_excel
|
36
35
|
# @option opts [Symbol] :if_obstructed :raise (default), :forget, :save, :close_if_saved, or _new_excel
|
37
36
|
# @option opts [Symbol] :if_absent :raise (default), or :create
|
@@ -39,15 +38,17 @@ module RobustExcelOle
|
|
39
38
|
# @option opts [Boolean] :displayalerts true, or false (default)
|
40
39
|
# @option opts [Boolean] :visible true, or false (default)
|
41
40
|
# options:
|
42
|
-
# :default_excel if the workbook was already open in an Excel instance, then open it
|
41
|
+
# :default_excel if the workbook was already open in an Excel instance, then open it in that Excel instance,
|
42
|
+
# where it was opened most recently
|
43
43
|
# Otherwise, i.e. if the workbook was not open before or the Excel instance is not alive
|
44
|
-
# :reuse
|
44
|
+
# :active or :reuse -> connects to a running (the first opened) Excel instance,
|
45
45
|
# excluding the hidden Excel instance, if it exists,
|
46
46
|
# otherwise opens in a new Excel instance.
|
47
47
|
# :new -> opens in a new Excel instance
|
48
48
|
# <excel-instance> -> opens in the given Excel instance
|
49
49
|
# :force_excel no matter whether the workbook was already open
|
50
|
-
# :new ->
|
50
|
+
# :new -> connects to a running (the first opened) Excel instance
|
51
|
+
# :active or :reuse -> opens in the active Excel instance
|
51
52
|
# <excel-instance> -> opens in the given Excel instance
|
52
53
|
# :if_unsaved if an unsaved workbook with the same name is open, then
|
53
54
|
# :raise -> raises an exception
|
@@ -73,14 +74,19 @@ module RobustExcelOle
|
|
73
74
|
# @return [Book] a workbook
|
74
75
|
def open(file, opts={ }, &block)
|
75
76
|
options = DEFAULT_OPEN_OPTS.merge(opts)
|
77
|
+
options[:default_excel] = :active if options[:default_excel] == :reuse
|
78
|
+
options[:force_excel] = :active if options[:force_excel] == :reuse
|
76
79
|
book = nil
|
77
|
-
if (not (options[:force_excel] == :new
|
80
|
+
if (not (options[:force_excel] == :new))
|
78
81
|
# if readonly is true, then prefer a book that is given in force_excel if this option is set
|
82
|
+
forced_excel = if options[:force_excel]
|
83
|
+
options[:force_excel] == :active ? excel_class.new(:reuse => true) : excel_of(options[:force_excel])
|
84
|
+
end
|
79
85
|
book = bookstore.fetch(file,
|
80
86
|
:prefer_writable => (not options[:read_only]),
|
81
|
-
:prefer_excel => (options[:read_only] ?
|
87
|
+
:prefer_excel => (options[:read_only] ? forced_excel : nil)) rescue nil
|
82
88
|
if book
|
83
|
-
if (((not options[:force_excel]) || (
|
89
|
+
if (((not options[:force_excel]) || (forced_excel == book.excel)) &&
|
84
90
|
(not (book.alive? && (not book.saved) && (not options[:if_unsaved] == :accept))))
|
85
91
|
book.options = DEFAULT_OPEN_OPTS.merge(opts)
|
86
92
|
book.ensure_excel(options) unless book.excel.alive?
|
@@ -122,8 +128,7 @@ module RobustExcelOle
|
|
122
128
|
# @option opts [Symbol] see above
|
123
129
|
# @return [Book] a workbook
|
124
130
|
def initialize(file_or_workbook, opts={ }, &block)
|
125
|
-
options = DEFAULT_OPEN_OPTS.merge(opts)
|
126
|
-
options[:excel] = options[:force_excel] ? options[:force_excel] : options[:default_excel]
|
131
|
+
options = DEFAULT_OPEN_OPTS.merge(opts)
|
127
132
|
if file_or_workbook.is_a? WIN32OLE
|
128
133
|
workbook = file_or_workbook
|
129
134
|
@ole_workbook = workbook
|
@@ -170,7 +175,7 @@ module RobustExcelOle
|
|
170
175
|
begin
|
171
176
|
object.excel
|
172
177
|
rescue
|
173
|
-
raise ExcelErrorOpen, "given object is neither an Excel, a
|
178
|
+
raise ExcelErrorOpen, "given object is neither an Excel, a Workbook, nor a Win32ole"
|
174
179
|
end
|
175
180
|
end
|
176
181
|
#rescue
|
@@ -181,27 +186,13 @@ module RobustExcelOle
|
|
181
186
|
|
182
187
|
def ensure_excel(options) # :nodoc: #
|
183
188
|
return if @excel && @excel.alive?
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
excel_options =
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
rescue WeakRef::RefError => msg
|
192
|
-
true
|
193
|
-
end
|
194
|
-
end
|
195
|
-
if (not @excel) || dead_or_recycled
|
196
|
-
if options[:excel] == :new || dead_or_recycled
|
197
|
-
excel_options = {:displayalerts => false, :visible => false}.merge(options)
|
198
|
-
excel_options[:reuse] = false
|
199
|
-
@excel = excel_class.new(excel_options)
|
200
|
-
else
|
201
|
-
@excel = self.class.excel_of(options[:excel])
|
202
|
-
end
|
203
|
-
end
|
204
|
-
apply_options(options) unless excel_options
|
189
|
+
options[:excel] = options[:force_excel] ? options[:force_excel] : options[:default_excel]
|
190
|
+
options[:excel] = :active if options[:excel == :reuse]
|
191
|
+
excel_options = {:displayalerts => false, :visible => false}.merge(options)
|
192
|
+
excel_options[:reuse] = (options[:excel] == :active)
|
193
|
+
@excel = self.class.excel_of(options[:excel]) unless (options[:excel] == :active || options[:excel] == :new)
|
194
|
+
@excel = excel_class.new(excel_options) unless (@excel && @excel.alive?)
|
195
|
+
apply_options unless excel_options
|
205
196
|
end
|
206
197
|
|
207
198
|
def ensure_workbook(file, options) # :nodoc: #
|
@@ -394,7 +385,7 @@ module RobustExcelOle
|
|
394
385
|
# @param [String] file the file name
|
395
386
|
# @param [Hash] if_closed an option
|
396
387
|
# @param [Hash] opts the options
|
397
|
-
# @option opts [Variant] :if_closed :reuse (default), :hidden or a Excel instance
|
388
|
+
# @option opts [Variant] :if_closed :active or :reuse (default), :hidden or a Excel instance
|
398
389
|
# @option opts [Boolean] :read_only whether the file is opened for read-only
|
399
390
|
# @option opts [Boolean] :readonly_excel behaviour when workbook is opened read-only and shall be modified
|
400
391
|
# @option opts [Boolean] :keep_open whether the workbook shall be kept open after unobtrusively opening
|
@@ -402,8 +393,8 @@ module RobustExcelOle
|
|
402
393
|
# @option opts [Boolean] :visible true, or false (default)
|
403
394
|
# options:
|
404
395
|
# :if_closed : if the workbook is closed, then open it in
|
405
|
-
# :reuse
|
406
|
-
#
|
396
|
+
# :active or :reuse -> the Excel instance of the workbook, if it exists,
|
397
|
+
# reuse another Excel, otherwise
|
407
398
|
# :hidden -> a separate Excel instance that is not visible and has no displayaslerts
|
408
399
|
# <excel-instance> -> the given Excel instance
|
409
400
|
# :read_only : opens the workbook unobtrusively for reading only (default: false)
|
@@ -420,7 +411,8 @@ module RobustExcelOle
|
|
420
411
|
opts = if_closed
|
421
412
|
if_closed = nil
|
422
413
|
end
|
423
|
-
if_closed = :
|
414
|
+
if_closed = :active if if_closed == :reuse
|
415
|
+
if_closed = :active unless if_closed
|
424
416
|
options = {
|
425
417
|
:read_only => false,
|
426
418
|
:readonly_excel => false,
|
@@ -443,7 +435,7 @@ module RobustExcelOle
|
|
443
435
|
book =
|
444
436
|
if was_not_alive_or_nil
|
445
437
|
case if_closed
|
446
|
-
when :
|
438
|
+
when :active
|
447
439
|
open(file, :read_only => options[:read_only])
|
448
440
|
when :hidden
|
449
441
|
open(file, :force_excel => bookstore.hidden_excel, :read_only => options[:read_only])
|
@@ -582,9 +574,9 @@ module RobustExcelOle
|
|
582
574
|
dirname, basename = File.split(file)
|
583
575
|
file_format =
|
584
576
|
case File.extname(basename)
|
585
|
-
when '.xls'
|
586
|
-
when '.xlsx'
|
587
|
-
when '.xlsm'
|
577
|
+
when '.xls' ; RobustExcelOle::XlExcel8
|
578
|
+
when '.xlsx'; RobustExcelOle::XlOpenXMLWorkbook
|
579
|
+
when '.xlsm'; RobustExcelOle::XlOpenXMLWorkbookMacroEnabled
|
588
580
|
end
|
589
581
|
@ole_workbook.SaveAs(General::absolute_path(file), file_format)
|
590
582
|
bookstore.store(self)
|
@@ -18,7 +18,9 @@ module RobustExcelOle
|
|
18
18
|
new(:reuse => false)
|
19
19
|
end
|
20
20
|
|
21
|
-
#
|
21
|
+
# returns (connects to) the current Excel instance, if such a running Excel instance exists
|
22
|
+
# more specific: connects to the first opened Excel instance
|
23
|
+
# if this Excel instance is being closed, then Excel creates a new Excel instance that has the same Hwnd
|
22
24
|
# creates a new one, otherwise
|
23
25
|
# @return [Excel] an Excel instance
|
24
26
|
def self.current
|
@@ -26,7 +28,7 @@ module RobustExcelOle
|
|
26
28
|
end
|
27
29
|
|
28
30
|
# returns an Excel instance
|
29
|
-
# given a WIN32OLE object representing an Excel instance, or a Hash representing options
|
31
|
+
# given a WIN32OLE object representing an Excel instance, or a Hash representing options
|
30
32
|
# @param [Hash] options the options
|
31
33
|
# @option options [Boolean] :reuse
|
32
34
|
# @option options [Boolean] :displayalerts
|
@@ -107,11 +109,11 @@ module RobustExcelOle
|
|
107
109
|
|
108
110
|
private
|
109
111
|
|
110
|
-
# returns
|
112
|
+
# returns (connects to) a running Excel instance
|
113
|
+
# connects to the first opened Excel instance
|
114
|
+
# if this Excel instance is being closed, then Excel creates a new Excel instance that has the same Hwnd
|
111
115
|
def self.current_excel # :nodoc: #
|
112
|
-
#p "current_excel:"
|
113
116
|
result = WIN32OLE.connect('Excel.Application') rescue nil
|
114
|
-
#p "result: #{result}"
|
115
117
|
if result
|
116
118
|
begin
|
117
119
|
result.Visible # send any method, just to see if it responds
|
@@ -120,7 +122,6 @@ module RobustExcelOle
|
|
120
122
|
return nil
|
121
123
|
end
|
122
124
|
end
|
123
|
-
#p "result: #{result}"
|
124
125
|
result
|
125
126
|
end
|
126
127
|
|
@@ -324,7 +325,6 @@ module RobustExcelOle
|
|
324
325
|
end
|
325
326
|
@@hwnd2excel.delete(excel_hwnd)
|
326
327
|
if options[:hard] then
|
327
|
-
Excel.free_all_ole_objects
|
328
328
|
process_id = Win32API.new("user32", "GetWindowThreadProcessId", ["I","P"], "I")
|
329
329
|
pid_puffer = " " * 32
|
330
330
|
process_id.call(excel_hwnd, pid_puffer)
|
@@ -501,8 +501,7 @@ module RobustExcelOle
|
|
501
501
|
@visible = @ole_excel.Visible
|
502
502
|
end
|
503
503
|
|
504
|
-
# sets calculation mode
|
505
|
-
# does not reset the calculation mode after block
|
504
|
+
# sets calculation mode in a block
|
506
505
|
def with_calculation(calculation_mode = :automatic)
|
507
506
|
if @ole_excel.Workbooks.Count > 0
|
508
507
|
old_calculation_mode = @ole_excel.Calculation
|
@@ -512,12 +511,20 @@ module RobustExcelOle
|
|
512
511
|
begin
|
513
512
|
yield self
|
514
513
|
ensure
|
515
|
-
|
516
|
-
|
514
|
+
@ole_excel.Calculation = old_calculation_mode if alive?
|
515
|
+
@ole_excel.CalculateBeforeSave = old_calculation_before_save_mode if alive?
|
517
516
|
end
|
518
517
|
end
|
519
518
|
end
|
520
519
|
|
520
|
+
# sets calculation mode
|
521
|
+
def set_calculation(calculation_mode = :automatic)
|
522
|
+
if @ole_excel.Workbooks.Count > 0
|
523
|
+
@ole_excel.Calculation = calculation_mode == :automatic ? XlCalculationAutomatic : XlCalculationManual
|
524
|
+
@ole_excel.CalculateBeforeSave = (calculation_mode == :automatic)
|
525
|
+
end
|
526
|
+
end
|
527
|
+
|
521
528
|
# returns the value of a range
|
522
529
|
# @param [String] name the name of a range
|
523
530
|
# @returns [Variant] the value of the range
|
@@ -48,7 +48,10 @@ module RobustExcelOle
|
|
48
48
|
@cells[yx] = RobustExcelOle::Cell.new(@worksheet.Cells.Item(y, x))
|
49
49
|
else
|
50
50
|
name = p1
|
51
|
-
nameval(name)
|
51
|
+
value = nameval(name) rescue nil
|
52
|
+
value = book_class.new(self.Parent).nameval(name) rescue nil unless value
|
53
|
+
value = rangeval(name) unless value
|
54
|
+
value
|
52
55
|
end
|
53
56
|
end
|
54
57
|
|
@@ -60,7 +63,15 @@ module RobustExcelOle
|
|
60
63
|
@worksheet.Cells.Item(y, x).Value = value
|
61
64
|
else
|
62
65
|
name, value = p1, p2
|
63
|
-
|
66
|
+
begin
|
67
|
+
set_nameval(name, value)
|
68
|
+
rescue SheetError
|
69
|
+
begin
|
70
|
+
book_class.new(self.Parent).set_nameval(name, value)
|
71
|
+
rescue ExcelError
|
72
|
+
set_rangeval(name, value)
|
73
|
+
end
|
74
|
+
end
|
64
75
|
end
|
65
76
|
end
|
66
77
|
|
@@ -116,30 +127,30 @@ module RobustExcelOle
|
|
116
127
|
# @param [String] name the name of a range
|
117
128
|
# @param [Hash] opts the options
|
118
129
|
# @option opts [Variant] :default default value (default: nil)
|
119
|
-
# @raise SheetError if name is not defined or if value of the range cannot be evaluated
|
130
|
+
# @raise SheetError if name is not defined or if value of the range cannot be evaluated
|
120
131
|
def nameval(name, opts = {:default => nil})
|
121
132
|
begin
|
122
133
|
name_obj = self.Names.Item(name)
|
123
134
|
rescue WIN32OLERuntimeError
|
135
|
+
return opts[:default] if opts[:default]
|
136
|
+
raise SheetError, "name #{name.inspect} not in #{self.Name}"
|
137
|
+
end
|
138
|
+
begin
|
139
|
+
value = name_obj.RefersToRange.Value
|
140
|
+
rescue WIN32OLERuntimeError
|
124
141
|
begin
|
125
|
-
value = self.Evaluate(
|
142
|
+
value = self.Evaluate(name_obj.Name)
|
126
143
|
rescue WIN32OLERuntimeError
|
127
144
|
return opts[:default] if opts[:default]
|
128
|
-
raise SheetError, "cannot
|
129
|
-
end
|
130
|
-
end
|
131
|
-
begin
|
132
|
-
value = name_obj.RefersToRange.Value unless value
|
133
|
-
rescue WIN32OLERuntimeError
|
134
|
-
return opts[:default] if opts[:default]
|
135
|
-
raise SheetError, "cannot evaluate name #{name.inspect} in #{self.Name}"
|
145
|
+
raise SheetError, "cannot evaluate name #{name.inspect} in #{self.Name}"
|
146
|
+
end
|
136
147
|
end
|
137
148
|
if value == -2146826259
|
138
149
|
return opts[:default] if opts[:default]
|
139
|
-
raise SheetError, "cannot
|
140
|
-
end
|
150
|
+
raise SheetError, "cannot evaluate name #{name.inspect} in #{self.Name}"
|
151
|
+
end
|
141
152
|
return opts[:default] if (value.nil? && opts[:default])
|
142
|
-
value
|
153
|
+
value
|
143
154
|
end
|
144
155
|
|
145
156
|
# assigns a value to a range
|
@@ -192,7 +203,7 @@ module RobustExcelOle
|
|
192
203
|
begin
|
193
204
|
range = self.Range(name)
|
194
205
|
rescue WIN32OLERuntimeError
|
195
|
-
raise SheetError, "
|
206
|
+
raise SheetError, "name #{name.inspect} not in #{self.name}"
|
196
207
|
end
|
197
208
|
begin
|
198
209
|
range.Value = value
|
@@ -228,6 +239,19 @@ module RobustExcelOle
|
|
228
239
|
super
|
229
240
|
end
|
230
241
|
|
242
|
+
def self.book_class # :nodoc: #
|
243
|
+
@book_class ||= begin
|
244
|
+
module_name = self.parent_name
|
245
|
+
"#{module_name}::Book".constantize
|
246
|
+
rescue NameError => e
|
247
|
+
book
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
def book_class # :nodoc: #
|
252
|
+
self.class.book_class
|
253
|
+
end
|
254
|
+
|
231
255
|
private
|
232
256
|
|
233
257
|
def method_missing(name, *args) # :nodoc: #
|
data/spec/book_spec.rb
CHANGED
@@ -319,7 +319,7 @@ describe Book do
|
|
319
319
|
it "should raise an error if no Excel or Book is given" do
|
320
320
|
expect{
|
321
321
|
Book.open(@simple_file, :force_excel => :b)
|
322
|
-
}.to raise_error(
|
322
|
+
}.to raise_error(ExcelErrorOpen, "given object is neither an Excel, a Workbook, nor a Win32ole")
|
323
323
|
end
|
324
324
|
|
325
325
|
it "should do force_excel even if both force_ and default_excel is given" do
|
@@ -329,21 +329,54 @@ describe Book do
|
|
329
329
|
book2.excel.should_not == @book.excel
|
330
330
|
book2.should_not == @book
|
331
331
|
end
|
332
|
-
end
|
333
332
|
|
334
|
-
|
335
|
-
|
336
|
-
book2
|
333
|
+
it "should do default_excel if force_excel is nil" do
|
334
|
+
book2 = Book.open(@another_simple_file, :force_excel => nil)
|
335
|
+
book2.should be_alive
|
336
|
+
book2.should be_a Book
|
337
|
+
book2.excel.should == @book.excel
|
338
|
+
end
|
339
|
+
|
340
|
+
it "should force_excel with :reuse" do
|
341
|
+
book2 = Book.open(@different_file, :force_excel => :reuse)
|
337
342
|
book2.should be_alive
|
338
343
|
book2.should be_a Book
|
344
|
+
book2.excel.should == @book.excel
|
345
|
+
end
|
346
|
+
|
347
|
+
it "should force_excel with :reuse even if :default_excel says sth. else" do
|
348
|
+
book2 = Book.open(@different_file, :force_excel => :reuse, :default_excel => :new)
|
349
|
+
book2.should be_alive
|
350
|
+
book2.should be_a Book
|
351
|
+
book2.excel.should == @book.excel
|
339
352
|
end
|
353
|
+
|
354
|
+
it "should open force_excel with :reuse when reopening and the Excel is not alive even if :default_excel says sth. else" do
|
355
|
+
excel2 = Excel.new(:reuse => false)
|
356
|
+
excel1_hwnd = @book.excel.hwnd
|
357
|
+
@book.excel.close
|
358
|
+
book2 = Book.open(@simple_file, :force_excel => :reuse, :default_excel => :new)
|
359
|
+
book2.should be_alive
|
360
|
+
book2.should be_a Book
|
361
|
+
book2.excel.should_not == excel2
|
362
|
+
book2.excel.hwnd.should == excel1_hwnd
|
363
|
+
end
|
364
|
+
|
365
|
+
it "should force_excel with :reuse when reopening and the Excel is not alive even if :default_excel says sth. else" do
|
366
|
+
book2 = Book.open(@different_file, :force_excel => :new)
|
367
|
+
book2.excel.close
|
368
|
+
book3 = Book.open(@different_file, :force_excel => :reuse, :default_excel => :new)
|
369
|
+
book3.should be_alive
|
370
|
+
book3.should be_a Book
|
371
|
+
book3.excel.should == @book.excel
|
372
|
+
end
|
373
|
+
|
340
374
|
end
|
341
375
|
|
342
376
|
context "with :default_excel" do
|
343
377
|
|
344
378
|
before do
|
345
|
-
|
346
|
-
@book = Book.open(@simple_file)
|
379
|
+
@book = Book.open(@simple_file, :visible => true)
|
347
380
|
end
|
348
381
|
|
349
382
|
after do
|
@@ -417,6 +450,20 @@ describe Book do
|
|
417
450
|
book2.close
|
418
451
|
end
|
419
452
|
|
453
|
+
it "should reopen the book in the Excel where it was opened most recently" do
|
454
|
+
excel1 = @book.excel
|
455
|
+
excel2 = Excel.new(:reuse => false)
|
456
|
+
@book.close
|
457
|
+
book2 = Book.open(@simple_file, :default_excel => :reuse)
|
458
|
+
book2.excel.should == excel1
|
459
|
+
book2.close
|
460
|
+
book3 = Book.open(@simple_file, :force_excel => excel2)
|
461
|
+
book3.close
|
462
|
+
book3 = Book.open(@simple_file, :default_excel => :reuse)
|
463
|
+
book3.excel.should == excel2
|
464
|
+
book3.close
|
465
|
+
end
|
466
|
+
|
420
467
|
it "should reopen a book in the excel instance where it was opened most recently" do
|
421
468
|
book2 = Book.open(@simple_file, :force_excel => :new)
|
422
469
|
@book.close
|
@@ -430,6 +477,37 @@ describe Book do
|
|
430
477
|
book3.should_not == @book
|
431
478
|
end
|
432
479
|
|
480
|
+
it "should open the book in a new excel if the book was not opened before" do
|
481
|
+
book2 = Book.open(@different_file, :default_excel => :reuse)
|
482
|
+
book2.excel.should == @book.excel
|
483
|
+
book3 = Book.open(@another_simple_file, :default_excel => :new)
|
484
|
+
book3.excel.should_not == @book.excel
|
485
|
+
end
|
486
|
+
|
487
|
+
it "should open the book in a new excel if the book was opened before but the excel has been closed" do
|
488
|
+
excel = @book.excel
|
489
|
+
excel2 = Excel.new(:reuse => false)
|
490
|
+
excel.close
|
491
|
+
book2 = Book.open(@simple_file, :default_excel => :new)
|
492
|
+
book2.excel.should_not == excel2
|
493
|
+
book2.close
|
494
|
+
end
|
495
|
+
|
496
|
+
it "should open the book in a given excel if the book was not opened before" do
|
497
|
+
book2 = Book.open(@different_file, :default_excel => :reuse)
|
498
|
+
book2.excel.should == @book.excel
|
499
|
+
excel = Excel.new(:reuse => false)
|
500
|
+
book3 = Book.open(@another_simple_file, :default_excel => excel)
|
501
|
+
book3.excel.should == excel
|
502
|
+
end
|
503
|
+
|
504
|
+
it "should open the book in a given excel if the book was opened before but the excel has been closed" do
|
505
|
+
excel2 = Excel.new(:reuse => false, :visible => true)
|
506
|
+
@book.excel.close
|
507
|
+
book2 = Book.open(@simple_file, :visible => true, :default_excel => excel2)
|
508
|
+
book2.excel.should == excel2
|
509
|
+
end
|
510
|
+
|
433
511
|
it "should open a new excel, if the book cannot be reopened" do
|
434
512
|
@book.close
|
435
513
|
new_excel = Excel.new(:reuse => false)
|
@@ -616,7 +694,7 @@ describe Book do
|
|
616
694
|
it "should raise an error, if :if_obstructed is :raise" do
|
617
695
|
expect {
|
618
696
|
@new_book = Book.open(@simple_file, :if_obstructed => :raise)
|
619
|
-
}.to raise_error(ExcelErrorOpen, /blocked by a book with the same name in a different path
|
697
|
+
}.to raise_error(ExcelErrorOpen, /blocked by a book with the same name in a different path/)
|
620
698
|
end
|
621
699
|
|
622
700
|
it "should close the other book and open the new book, if :if_obstructed is :forget" do
|
@@ -640,7 +718,7 @@ describe Book do
|
|
640
718
|
if :if_obstructed is :close_if_saved" do
|
641
719
|
expect{
|
642
720
|
@new_book = Book.open(@simple_file, :if_obstructed => :close_if_saved)
|
643
|
-
}.to raise_error(ExcelErrorOpen, /workbook with the same name in a different path is unsaved
|
721
|
+
}.to raise_error(ExcelErrorOpen, /workbook with the same name in a different path is unsaved/)
|
644
722
|
@book.save
|
645
723
|
@new_book = Book.open(@simple_file, :if_obstructed => :close_if_saved)
|
646
724
|
@book.should_not be_alive
|
@@ -662,7 +740,7 @@ describe Book do
|
|
662
740
|
it "should raise an error, if :if_obstructed is default" do
|
663
741
|
expect {
|
664
742
|
@new_book = Book.open(@simple_file)
|
665
|
-
}.to raise_error(ExcelErrorOpen, /blocked by a book with the same name in a different path
|
743
|
+
}.to raise_error(ExcelErrorOpen, /blocked by a book with the same name in a different path/)
|
666
744
|
end
|
667
745
|
|
668
746
|
it "should raise an error, if :if_obstructed is invalid option" do
|
@@ -131,7 +131,7 @@ describe Book do
|
|
131
131
|
File.exist?(@simple_file_other_path).should be_true
|
132
132
|
expect{
|
133
133
|
@book2.save_as(@simple_file_other_path, :if_exists => :overwrite, :if_obstructed => :raise)
|
134
|
-
}.to raise_error(ExcelErrorSave, /blocked by another workbook
|
134
|
+
}.to raise_error(ExcelErrorSave, /blocked by another workbook/)
|
135
135
|
end
|
136
136
|
|
137
137
|
it "should close the blocking workbook without saving, and save the current workbook with :if_obstructed => :forget" do
|
@@ -235,7 +235,7 @@ describe Book do
|
|
235
235
|
File.exist?(@simple_file_other_path).should be_true
|
236
236
|
expect{
|
237
237
|
@book2.save_as(@simple_file_other_path, :if_exists => :overwrite)
|
238
|
-
}.to raise_error(ExcelErrorSave, /blocked by another workbook
|
238
|
+
}.to raise_error(ExcelErrorSave, /blocked by another workbook/)
|
239
239
|
end
|
240
240
|
|
241
241
|
it "should raise an error if the file does not exist and an workbook with the same name and other path exists" do
|
@@ -243,7 +243,7 @@ describe Book do
|
|
243
243
|
File.exist?(@simple_file_other_path).should be_false
|
244
244
|
expect{
|
245
245
|
@book2.save_as(@simple_file_other_path, :if_exists => :overwrite, :if_obstructed => :raise)
|
246
|
-
}.to raise_error(ExcelErrorSave, /blocked by another workbook
|
246
|
+
}.to raise_error(ExcelErrorSave, /blocked by another workbook/)
|
247
247
|
end
|
248
248
|
|
249
249
|
it "should raise an error if the file exists and an workbook with the same name and other path exists" do
|
@@ -121,7 +121,7 @@ describe Book do
|
|
121
121
|
expect{
|
122
122
|
Book.unobtrusively(@simple_file, :invalid_option) do |book|
|
123
123
|
end
|
124
|
-
}.to raise_error(ExcelErrorOpen, "given object is neither an Excel, a
|
124
|
+
}.to raise_error(ExcelErrorOpen, "given object is neither an Excel, a Workbook, nor a Win32ole")
|
125
125
|
end
|
126
126
|
|
127
127
|
it "should be visible and displayalerts" do
|
@@ -383,7 +383,7 @@ describe Book do
|
|
383
383
|
old_cell_value = sheet[1,1].value
|
384
384
|
@book.close
|
385
385
|
@book.should_not be_alive
|
386
|
-
Excel.
|
386
|
+
Excel.kill_all
|
387
387
|
Book.unobtrusively(@simple_file, :hidden, :keep_open => true) do |book|
|
388
388
|
book.should be_a Book
|
389
389
|
book.excel.should_not == @book.excel
|
Binary file
|
Binary file
|
data/spec/data/workbook.xls
CHANGED
Binary file
|
data/spec/excel_spec.rb
CHANGED
@@ -133,6 +133,27 @@ module RobustExcelOle
|
|
133
133
|
end
|
134
134
|
end
|
135
135
|
|
136
|
+
context "current" do
|
137
|
+
|
138
|
+
it "should reuse the first opened Excel instance if not the first opened Excel instance was closed" do
|
139
|
+
excel1 = Excel.create
|
140
|
+
excel2 = Excel.create
|
141
|
+
excel2.close
|
142
|
+
excel3 = Excel.current
|
143
|
+
excel3.should === excel1
|
144
|
+
end
|
145
|
+
|
146
|
+
it "should create a new Excel with the same hwnd as the first opened Excel if the first opened Excel was closed" do
|
147
|
+
excel1 = Excel.create
|
148
|
+
excel1_hwnd = excel1.hwnd
|
149
|
+
excel2 = Excel.create
|
150
|
+
excel1.close
|
151
|
+
excel3 = Excel.current
|
152
|
+
excel3.should_not === excel2
|
153
|
+
excel3.hwnd.should == excel1_hwnd
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
136
157
|
context "excel_processes" do
|
137
158
|
|
138
159
|
before do
|
@@ -383,19 +404,12 @@ module RobustExcelOle
|
|
383
404
|
context "with :if_unsaved => :alert" do
|
384
405
|
before do
|
385
406
|
@key_sender = IO.popen 'ruby "' + File.join(File.dirname(__FILE__), '/helpers/key_sender.rb') + '" "Microsoft Excel" ' , "w"
|
386
|
-
#book1 = Book.open(@simple_file, :read_only => true)
|
387
407
|
book2 = Book.open(@simple_file, :force_excel => :new)
|
388
|
-
#book3 = Book.open(@another_simple_file, :force_excel => book2.excel)
|
389
|
-
#book4 = Book.open(@different_file, :force_excel => :new)
|
390
408
|
#@excel1 = book1.excel
|
391
409
|
@excel2 = book2.excel
|
392
|
-
#@excel4 = book4.excel
|
393
410
|
sheet2 = book2.sheet(1)
|
394
411
|
@old_cell_value2 = sheet2[1,1].value
|
395
412
|
sheet2[1,1] = sheet2[1,1].value == "foo" ? "bar" : "foo"
|
396
|
-
#sheet3 = book3[0]
|
397
|
-
#@old_cell_value3 = sheet3[1,1].value
|
398
|
-
#sheet3[1,1] = sheet3[1,1].value == "foo" ? "bar" : "foo"
|
399
413
|
end
|
400
414
|
|
401
415
|
after do
|
@@ -405,47 +419,31 @@ module RobustExcelOle
|
|
405
419
|
it "should save if user answers 'yes'" do
|
406
420
|
@key_sender.puts "{enter}"
|
407
421
|
Excel.close_all(:if_unsaved => :alert)
|
408
|
-
#@excel1.should_not be_alive
|
409
|
-
@excel2.should_not be_alive
|
410
|
-
#@excel4.should_not be_alive
|
411
|
-
#@excel5.should_not be_alive
|
412
422
|
new_book2 = Book.open(@simple_file)
|
413
423
|
new_sheet2 = new_book2.sheet(1)
|
414
424
|
new_sheet2[1,1].value.should_not == @old_cell_value2
|
415
425
|
new_book2.close
|
416
|
-
#new_book3 = Book.open(@another_simple_file)
|
417
|
-
#new_sheet3 = new_book3[0]
|
418
|
-
#new_sheet3[1,1].value.should == @old_cell_value3
|
419
|
-
#new_book3.close
|
420
426
|
end
|
421
427
|
|
422
428
|
it "should not save if user answers 'no'" do
|
423
429
|
@key_sender.puts "{right}{enter}"
|
424
430
|
@key_sender.puts "{right}{enter}"
|
425
431
|
Excel.close_all(:if_unsaved => :alert)
|
426
|
-
#@excel1.should_not be_alive
|
427
432
|
@excel2.should_not be_alive
|
428
|
-
#@excel4.should_not be_alive
|
429
|
-
#@excel5.should_not be_alive
|
430
433
|
new_book2 = Book.open(@simple_file)
|
431
434
|
new_sheet2 = new_book2.sheet(1)
|
432
435
|
new_sheet2[1,1].value.should == @old_cell_value2
|
433
436
|
new_book2.close
|
434
|
-
#new_book4 = Book.open(@different_file)
|
435
|
-
#new_sheet4 = new_book4[0]
|
436
|
-
#new_sheet4[1,1].value.should_not == @old_cell_value4
|
437
|
-
#new_book4.close
|
438
437
|
end
|
439
438
|
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
# end
|
439
|
+
#it "should not save if user answers 'cancel'" do
|
440
|
+
# @key_sender.puts "{left}{enter}"
|
441
|
+
# @key_sender.puts "{left}{enter}"
|
442
|
+
# @key_sender.puts "{left}{enter}"
|
443
|
+
# expect{
|
444
|
+
# Excel.close_all(:if_unsaved => :alert)
|
445
|
+
# }.to raise_error(ExcelUserCanceled, "close: canceled by user")
|
446
|
+
# end
|
449
447
|
end
|
450
448
|
end
|
451
449
|
|
@@ -465,6 +463,30 @@ module RobustExcelOle
|
|
465
463
|
@excel.should_not be_alive
|
466
464
|
@book.should_not be_alive
|
467
465
|
end
|
466
|
+
|
467
|
+
it "should close the Excel hard" do
|
468
|
+
@excel.should be_alive
|
469
|
+
@book.should be_alive
|
470
|
+
@excel.close(:hard => true)
|
471
|
+
@excel.should_not be_alive
|
472
|
+
@book.should_not be_alive
|
473
|
+
end
|
474
|
+
|
475
|
+
it "should close the Excel without destroying the others" do
|
476
|
+
@excel.should be_alive
|
477
|
+
excel2 = Excel.create
|
478
|
+
@excel.close
|
479
|
+
@excel.should_not be_alive
|
480
|
+
excel2.should be_alive
|
481
|
+
end
|
482
|
+
|
483
|
+
it "should close the Excel hard without destroying the others" do
|
484
|
+
@excel.should be_alive
|
485
|
+
excel2 = Excel.create
|
486
|
+
@excel.close(:hard => true)
|
487
|
+
@excel.should_not be_alive
|
488
|
+
excel2.should be_alive
|
489
|
+
end
|
468
490
|
end
|
469
491
|
|
470
492
|
context "with unsaved workbooks" do
|
@@ -490,7 +512,7 @@ module RobustExcelOle
|
|
490
512
|
expect{
|
491
513
|
@excel.close(:if_unsaved => :raise)
|
492
514
|
}.to raise_error(ExcelErrorClose, "Excel contains unsaved workbooks")
|
493
|
-
end
|
515
|
+
end
|
494
516
|
|
495
517
|
it "should close the Excel without saving the workbook" do
|
496
518
|
@excel.should be_alive
|
@@ -560,6 +582,7 @@ module RobustExcelOle
|
|
560
582
|
end
|
561
583
|
result.should be_empty
|
562
584
|
end
|
585
|
+
|
563
586
|
end
|
564
587
|
|
565
588
|
context "with :if_unsaved => :alert" do
|
@@ -741,21 +764,42 @@ module RobustExcelOle
|
|
741
764
|
context "with calculation" do
|
742
765
|
|
743
766
|
before do
|
744
|
-
@excel1 = Excel.new
|
767
|
+
@excel1 = Excel.new
|
745
768
|
end
|
746
769
|
|
747
770
|
it "should not set calculation mode when no workbook is opened" do
|
771
|
+
old_calculation_mode = @excel1.Calculation
|
748
772
|
@excel1.with_calculation(:automatic) do
|
749
|
-
@excel1.Calculation.
|
773
|
+
@excel1.Calculation.should == old_calculation_mode
|
750
774
|
end
|
775
|
+
@excel1.with_calculation(:manual) do
|
776
|
+
@excel1.Calculation.should == old_calculation_mode
|
777
|
+
end
|
778
|
+
@excel1.set_calculation(:automatic)
|
779
|
+
@excel1.Calculation.should == old_calculation_mode
|
780
|
+
@excel1.set_calculation(:manual)
|
781
|
+
@excel1.Calculation.should == old_calculation_mode
|
751
782
|
end
|
752
783
|
|
753
|
-
it "should set calculation mode to manual" do
|
784
|
+
it "should set calculation mode to manual and reset to the previous value" do
|
754
785
|
b = Book.open(@simple_file)
|
786
|
+
calculation_mode_old = @excel1.Calculation
|
787
|
+
calculation_before_save_old = @excel1.CalculateBeforeSave
|
755
788
|
@excel1.with_calculation(:manual) do
|
756
789
|
@excel1.Calculation.should == -4135
|
757
790
|
@excel1.CalculateBeforeSave.should be_false
|
758
791
|
end
|
792
|
+
@excel1.Calculation.should == calculation_mode_old
|
793
|
+
@excel1.CalculateBeforeSave.should == calculation_before_save_old
|
794
|
+
end
|
795
|
+
|
796
|
+
it "should set calculation mode to manual" do
|
797
|
+
b = Book.open(@simple_file)
|
798
|
+
calculation_mode_old = @excel1.Calculation
|
799
|
+
calculation_before_save_old = @excel1.CalculateBeforeSave
|
800
|
+
@excel1.set_calculation(:manual)
|
801
|
+
@excel1.Calculation.should == -4135
|
802
|
+
@excel1.CalculateBeforeSave.should be_false
|
759
803
|
end
|
760
804
|
|
761
805
|
it "should set calculation mode automatic" do
|
data/spec/sheet_spec.rb
CHANGED
@@ -95,7 +95,7 @@ describe Sheet do
|
|
95
95
|
|
96
96
|
describe 'access cell' do
|
97
97
|
|
98
|
-
describe "#[]" do
|
98
|
+
describe "#[,]" do
|
99
99
|
|
100
100
|
context "access [1,1]" do
|
101
101
|
|
@@ -388,7 +388,57 @@ describe Sheet do
|
|
388
388
|
end
|
389
389
|
end
|
390
390
|
|
391
|
-
describe "
|
391
|
+
describe "[], []=" do
|
392
|
+
before do
|
393
|
+
@book1 = Book.open(@dir + '/another_workbook.xls')
|
394
|
+
@sheet1 = @book1.sheet(1)
|
395
|
+
end
|
396
|
+
|
397
|
+
after do
|
398
|
+
@book1.close(:if_unsaved => :forget)
|
399
|
+
end
|
400
|
+
|
401
|
+
it "should return value of a defined name" do
|
402
|
+
@sheet1["firstcell"].should == "foo"
|
403
|
+
end
|
404
|
+
|
405
|
+
it "should return value of a defined name" do
|
406
|
+
@sheet1["new"].should == "foo"
|
407
|
+
@sheet1["one"].should == 1.0
|
408
|
+
@sheet1["four"].should == [[1,2],[3,4]]
|
409
|
+
@sheet1["firstrow"].should == [[1,2]]
|
410
|
+
end
|
411
|
+
|
412
|
+
it "should evaluate named formula" do
|
413
|
+
@sheet1["named_formula"].should == 4
|
414
|
+
end
|
415
|
+
|
416
|
+
it "should evaluate a formula" do
|
417
|
+
@sheet1["another_formula"].should == 5
|
418
|
+
end
|
419
|
+
|
420
|
+
it "should raise an error if name not defined" do
|
421
|
+
expect {
|
422
|
+
@sheet1["foo"]
|
423
|
+
}.to raise_error(SheetError, /name "foo" not in Sheet1/)
|
424
|
+
end
|
425
|
+
|
426
|
+
it "should set a range to a value" do
|
427
|
+
@sheet1[1,1].Value.should == "foo"
|
428
|
+
@sheet1["firstcell"] = "bar"
|
429
|
+
@sheet1[1,1].Value.should == "bar"
|
430
|
+
@sheet1["new"] = "bar"
|
431
|
+
@sheet1["new"].should == "bar"
|
432
|
+
end
|
433
|
+
|
434
|
+
it "should raise an error if name cannot be evaluated" do
|
435
|
+
expect{
|
436
|
+
@sheet1["foo"] = 1
|
437
|
+
}.to raise_error(SheetError, /name "foo" not in Sheet1/)
|
438
|
+
end
|
439
|
+
end
|
440
|
+
|
441
|
+
describe "nameval, set_nameval" do
|
392
442
|
|
393
443
|
before do
|
394
444
|
@book1 = Book.open(@dir + '/another_workbook.xls')
|
@@ -401,25 +451,23 @@ describe Sheet do
|
|
401
451
|
|
402
452
|
it "should return value of a defined name" do
|
403
453
|
@sheet1.nameval("firstcell").should == "foo"
|
404
|
-
|
405
|
-
end
|
454
|
+
end
|
406
455
|
|
407
456
|
it "should return default value if name not defined and default value is given" do
|
408
457
|
@sheet1.nameval("foo", :default => 2).should == 2
|
409
458
|
end
|
410
459
|
|
411
460
|
it "should evaluate a formula" do
|
412
|
-
@sheet1.nameval("
|
413
|
-
|
414
|
-
end
|
461
|
+
@sheet1.nameval("another_formula").should == 5
|
462
|
+
end
|
415
463
|
|
416
464
|
it "should raise an error if name not defined" do
|
417
465
|
expect {
|
418
466
|
@sheet1.nameval("foo")
|
419
|
-
}.to raise_error(SheetError, /
|
467
|
+
}.to raise_error(SheetError, /name "foo" not in Sheet1/)
|
420
468
|
expect {
|
421
|
-
@sheet1
|
422
|
-
}.to raise_error(SheetError, /
|
469
|
+
@sheet1.nameval("named_formula")
|
470
|
+
}.to raise_error(SheetError, /name "named_formula" not in Sheet1/)
|
423
471
|
end
|
424
472
|
|
425
473
|
it "should set a range to a value" do
|
@@ -428,18 +476,12 @@ describe Sheet do
|
|
428
476
|
@sheet1.set_nameval("firstcell","bar")
|
429
477
|
@sheet1.nameval("firstcell").should == "bar"
|
430
478
|
@sheet1[1,1].Value.should == "bar"
|
431
|
-
@sheet1["firstcell"] = "foo"
|
432
|
-
@sheet1.nameval("firstcell").should == "foo"
|
433
|
-
@sheet1[1,1].Value.should == "foo"
|
434
479
|
end
|
435
480
|
|
436
481
|
it "should raise an error if name cannot be evaluated" do
|
437
482
|
expect{
|
438
483
|
@sheet1.set_nameval("foo", 1)
|
439
|
-
|
440
|
-
expect{
|
441
|
-
@sheet1["foo"] = 1
|
442
|
-
}.to raise_error(SheetError, /name "foo" not in Sheet1/)
|
484
|
+
}.to raise_error(SheetError, /name "foo" not in Sheet1/)
|
443
485
|
end
|
444
486
|
end
|
445
487
|
|
metadata
CHANGED
@@ -1,12 +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: 9
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 5
|
9
|
-
|
9
|
+
- 1
|
10
|
+
version: 0.5.1
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- traths
|
@@ -14,7 +15,7 @@ autorequire:
|
|
14
15
|
bindir: bin
|
15
16
|
cert_chain: []
|
16
17
|
|
17
|
-
date: 2016-06-
|
18
|
+
date: 2016-06-17 00:00:00 +02:00
|
18
19
|
default_executable:
|
19
20
|
dependencies:
|
20
21
|
- !ruby/object:Gem::Dependency
|