robust_excel_ole 0.3.1 → 0.3.2
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 +69 -56
- data/README_detail.rdoc +44 -34
- data/TodoList.md +8 -6
- data/examples/edit_sheets/example_access_sheets_and_cells.rb +6 -6
- data/examples/edit_sheets/example_adding_sheets.rb +2 -2
- data/examples/edit_sheets/example_ranges.rb +3 -3
- data/examples/open_save_close/example_control_to_excel.rb +2 -2
- data/examples/open_save_close/example_default_excel.rb +2 -2
- data/examples/open_save_close/example_force_excel.rb +1 -1
- data/examples/open_save_close/example_if_obstructed_closeifsaved.rb +4 -4
- data/examples/open_save_close/example_if_obstructed_forget.rb +2 -2
- data/examples/open_save_close/example_if_obstructed_save.rb +2 -2
- data/examples/open_save_close/example_if_unsaved_accept.rb +1 -1
- data/examples/open_save_close/example_if_unsaved_forget.rb +1 -1
- data/examples/open_save_close/example_if_unsaved_forget_more.rb +1 -1
- data/examples/open_save_close/example_read_only.rb +2 -2
- data/examples/open_save_close/example_rename_cells.rb +1 -1
- data/examples/open_save_close/example_reuse.rb +3 -3
- data/examples/open_save_close/example_simple.rb +2 -2
- data/examples/open_save_close/example_unobtrusively.rb +1 -1
- data/lib/robust_excel_ole/book.rb +97 -128
- data/lib/robust_excel_ole/book_store.rb +23 -23
- data/lib/robust_excel_ole/excel.rb +12 -14
- data/lib/robust_excel_ole/version.rb +1 -1
- data/spec/book_spec.rb +462 -289
- data/spec/book_store_spec.rb +36 -55
- data/spec/data/book_with_blank.xls +0 -0
- data/spec/data/{different_simple.xls → different_workbook.xls} +0 -0
- data/spec/data/merge_cells.xls +0 -0
- data/spec/data/{more_simple.xls → more_workbook.xls} +0 -0
- data/spec/data/protected_sheet.xls +0 -0
- data/spec/data/{simple.xls → workbook.xls} +0 -0
- data/spec/data/{simple.xlsm → workbook.xlsm} +0 -0
- data/spec/data/{simple.xlsx → workbook.xlsx} +0 -0
- data/spec/excel_spec.rb +40 -0
- metadata +9 -9
@@ -10,7 +10,7 @@ include RobustExcelOle
|
|
10
10
|
Excel.close_all
|
11
11
|
begin
|
12
12
|
dir = create_tmpdir
|
13
|
-
simple_file = dir + '
|
13
|
+
simple_file = dir + 'workbook.xls'
|
14
14
|
book1 = Book.open(simple_file) # open a book in a new Excel instance since no Excel is open
|
15
15
|
book1.excel.visible = true # make current Excel visible
|
16
16
|
sleep 2
|
@@ -10,12 +10,12 @@ include RobustExcelOle
|
|
10
10
|
Excel.close_all
|
11
11
|
begin
|
12
12
|
dir = create_tmpdir
|
13
|
-
file_name = dir + '
|
14
|
-
other_file_name = dir + 'more_data/
|
13
|
+
file_name = dir + 'workbook.xls'
|
14
|
+
other_file_name = dir + 'more_data/workbook.xls'
|
15
15
|
book = Book.open(file_name, :visible => true) # open a book, make Excel visible
|
16
16
|
sleep 1
|
17
17
|
sheet = book[0]
|
18
|
-
first_cell = sheet[0,0].
|
18
|
+
first_cell = sheet[0,0].Value # access a sheet
|
19
19
|
sheet[0,0] = first_cell == "simple" ? "complex" : "simple" # change a cell
|
20
20
|
sleep 1
|
21
21
|
begin
|
@@ -27,7 +27,7 @@ begin
|
|
27
27
|
new_book = Book.open(file_name, :if_obstructed => :close_if_saved) # open the new book, close the saved book
|
28
28
|
sleep 1
|
29
29
|
new_sheet = new_book[0]
|
30
|
-
new_first_cell = new_sheet[0,0].
|
30
|
+
new_first_cell = new_sheet[0,0].Value
|
31
31
|
puts "the old book was saved" unless new_first_cell == first_cell
|
32
32
|
new_book.close # close the books
|
33
33
|
ensure
|
@@ -10,8 +10,8 @@ include RobustExcelOle
|
|
10
10
|
Excel.close_all
|
11
11
|
begin
|
12
12
|
dir = create_tmpdir
|
13
|
-
file_name = dir + '
|
14
|
-
other_file_name = dir + 'more_data/
|
13
|
+
file_name = dir + 'workbook.xls'
|
14
|
+
other_file_name = dir + 'more_data/workbook.xls'
|
15
15
|
book = Book.open(file_name, :visible => true) # open a book, make Excel application visible
|
16
16
|
sleep 3
|
17
17
|
begin
|
@@ -10,8 +10,8 @@ include RobustExcelOle
|
|
10
10
|
Excel.close_all
|
11
11
|
begin
|
12
12
|
dir = create_tmpdir
|
13
|
-
file_name = dir + '
|
14
|
-
other_file_name = dir + 'more_data/
|
13
|
+
file_name = dir + 'workbook.xls'
|
14
|
+
other_file_name = dir + 'more_data/workbook.xls'
|
15
15
|
book = Book.open(file_name, :visible => true) # open a book, make Excel visible
|
16
16
|
sleep 1
|
17
17
|
sheet = book[0]
|
@@ -10,7 +10,7 @@ include RobustExcelOle
|
|
10
10
|
Excel.close_all
|
11
11
|
begin
|
12
12
|
dir = create_tmpdir
|
13
|
-
file_name = dir + '
|
13
|
+
file_name = dir + 'workbook.xls'
|
14
14
|
book = Book.open(file_name) # open a book
|
15
15
|
sheet = book[0] # access a sheet
|
16
16
|
sheet[0,0] = sheet[0,0].value == "simple" ? "complex" : "simple" # change a cell
|
@@ -9,8 +9,8 @@ include RobustExcelOle
|
|
9
9
|
Excel.close_all
|
10
10
|
begin
|
11
11
|
dir = create_tmpdir
|
12
|
-
file_name = dir + '
|
13
|
-
other_file_name = dir + '
|
12
|
+
file_name = dir + 'workbook.xls'
|
13
|
+
other_file_name = dir + 'different_workbook.xls'
|
14
14
|
book = Book.open(file_name, :read_only => true, :visible => true) # open a book with read_only and make Excel visible
|
15
15
|
sheet = book[0] # access a sheet
|
16
16
|
sleep 1
|
@@ -10,7 +10,7 @@ include RobustExcelOle
|
|
10
10
|
Excel.close_all
|
11
11
|
begin
|
12
12
|
dir = create_tmpdir
|
13
|
-
file_name = dir + '
|
13
|
+
file_name = dir + 'workbook.xls'
|
14
14
|
book = Book.open(file_name) # open a book. default: :read_only => false
|
15
15
|
book.excel.visible = true # make current Excel visible
|
16
16
|
sheet = book[0]
|
@@ -9,9 +9,9 @@ include RobustExcelOle
|
|
9
9
|
Excel.close_all
|
10
10
|
begin
|
11
11
|
dir = create_tmpdir
|
12
|
-
file_name1 = dir + '
|
13
|
-
file_name2 = dir + '
|
14
|
-
file_name3 = dir + '
|
12
|
+
file_name1 = dir + 'workbook.xls'
|
13
|
+
file_name2 = dir + 'different_workbook.xls'
|
14
|
+
file_name3 = dir + 'different_workbook.xls'
|
15
15
|
file_name4 = dir + 'book_with_blank.xls'
|
16
16
|
book1 = Book.open(file_name1) # open a book in a new Excel instance since no Excel is open
|
17
17
|
book1.excel.visible = true # make current Excel visible
|
@@ -10,8 +10,8 @@ include RobustExcelOle
|
|
10
10
|
Excel.close_all
|
11
11
|
begin
|
12
12
|
dir = create_tmpdir
|
13
|
-
file_name = dir + '
|
14
|
-
other_file_name = dir + '
|
13
|
+
file_name = dir + 'workbook.xls'
|
14
|
+
other_file_name = dir + 'different_workbook.xls'
|
15
15
|
book = Book.open(file_name) # open a book. default: :read_only => false
|
16
16
|
book.excel.visible = true # make current Excel visible
|
17
17
|
sheet = book[0] # access a sheet
|
@@ -9,7 +9,7 @@ include RobustExcelOle
|
|
9
9
|
Excel.close_all
|
10
10
|
begin
|
11
11
|
dir = create_tmpdir
|
12
|
-
simple_file = dir + '
|
12
|
+
simple_file = dir + 'workbook.xls'
|
13
13
|
book = Book.open(simple_file, :visible => true) # open a book, make Excel visible
|
14
14
|
old_sheet = book[0]
|
15
15
|
p "1st cell: #{old_sheet[0,0].value}"
|
@@ -9,6 +9,16 @@ module RobustExcelOle
|
|
9
9
|
attr_accessor :excel
|
10
10
|
attr_accessor :workbook
|
11
11
|
attr_accessor :stored_filename
|
12
|
+
attr_accessor :options
|
13
|
+
|
14
|
+
DEFAULT_OPEN_OPTS = {
|
15
|
+
:excel => :reuse,
|
16
|
+
:default_excel => :reuse,
|
17
|
+
:if_locked => :readonly,
|
18
|
+
:if_unsaved => :raise,
|
19
|
+
:if_obstructed => :raise,
|
20
|
+
:read_only => false
|
21
|
+
}
|
12
22
|
|
13
23
|
class << self
|
14
24
|
|
@@ -19,91 +29,63 @@ module RobustExcelOle
|
|
19
29
|
#
|
20
30
|
# options:
|
21
31
|
# :default_excel if the book was already open in an Excel instance, then open it there.
|
22
|
-
# Otherwise, i.e. if the book was not open before or the Excel instance
|
23
|
-
# :reuse (default) -> connect to a (the first opened) running Excel instance
|
24
|
-
#
|
32
|
+
# Otherwise, i.e. if the book was not open before or the Excel instance is not alive
|
33
|
+
# :reuse (default) -> connect to a (the first opened) running Excel instance,
|
34
|
+
# excluding the hidden Excel instance, if it exists,
|
35
|
+
# otherwise open in a new Excel instance.
|
25
36
|
# :new -> open in a new Excel instance
|
26
37
|
# <instance> -> open in the given Excel instance
|
27
38
|
# :force_excel no matter whether the book was already open
|
28
39
|
# :new (default) -> open in a new Excel
|
29
40
|
# <instance> -> open in the given Excel instance
|
30
|
-
# :if_locked if the book is open in another Excel instance, then
|
31
|
-
# :readonly (default) -> open the book as readonly, if is should be opened in a new Excel,
|
32
|
-
# use the old book otherwise
|
33
|
-
# :take_writable -> use the Excel instance in which the book is writable,
|
34
|
-
# if such an Excel instance exists
|
35
|
-
# :force_writability -> make it writable in the desired Excel
|
36
|
-
# (does not work yet)
|
37
|
-
# :if_locked_unsaved if the book is open in another Excel instance and contains unsaved changes
|
38
|
-
# :raise -> raise an exception
|
39
|
-
# :save -> save the unsaved book
|
40
|
-
# (not implemented yet)
|
41
41
|
# :if_unsaved if an unsaved book with the same name is open, then
|
42
|
-
# :raise
|
42
|
+
# :raise (default) -> raise an exception
|
43
43
|
# :forget -> close the unsaved book, open the new book
|
44
44
|
# :accept -> let the unsaved book open
|
45
45
|
# :alert -> give control to Excel
|
46
|
-
# :new_excel
|
46
|
+
# :new_excel -> open the new book in a new Excel
|
47
47
|
# :if_obstructed if a book with the same name in a different path is open, then
|
48
|
-
# :raise
|
48
|
+
# :raise (default) -> raise an exception
|
49
49
|
# :forget -> close the old book, open the new book
|
50
50
|
# :save -> save the old book, close it, open the new book
|
51
|
-
# :close_if_saved -> close the old book and open the new book, if the old book is saved
|
52
|
-
# raise an exception
|
53
|
-
# :new_excel
|
51
|
+
# :close_if_saved -> close the old book and open the new book, if the old book is saved,
|
52
|
+
# otherwise raise an exception.
|
53
|
+
# :new_excel -> open the new book in a new Excel
|
54
|
+
# :if_absent :create -> creates a new Excel file, if it does not exists
|
55
|
+
# :raise -> raises an exception , if the file does not exists
|
54
56
|
# :read_only open in read-only mode (default: false)
|
55
57
|
# :displayalerts enable DisplayAlerts in Excel (default: false)
|
56
|
-
# :visible make
|
58
|
+
# :visible make visible in Excel (default: false)
|
57
59
|
# if :default_excel is set, then DisplayAlerts and Visible are set only if these parameters are given
|
58
|
-
|
60
|
+
|
59
61
|
def open(file, opts={ }, &block)
|
60
|
-
|
61
|
-
:excel => :reuse,
|
62
|
-
:default_excel => :reuse,
|
63
|
-
:if_locked => :readonly,
|
64
|
-
:if_unsaved => :new_excel,
|
65
|
-
:if_obstructed => :new_excel,
|
66
|
-
:read_only => false
|
67
|
-
}.merge(opts)
|
68
|
-
#self.set_defaults(opts) ???
|
62
|
+
current_options = DEFAULT_OPEN_OPTS.merge(opts)
|
69
63
|
book = nil
|
70
|
-
if (not (
|
64
|
+
if (not (current_options[:force_excel] == :new && (not current_options[:if_locked] == :take_writable)))
|
71
65
|
# if readonly is true, then prefer a book that is given in force_excel if this option is set
|
72
|
-
book = book_store.fetch(file, :prefer_writable => (not
|
66
|
+
book = book_store.fetch(file, :prefer_writable => (not current_options[:read_only]),
|
67
|
+
:prefer_excel => (current_options[:read_only] ? current_options[:force_excel] : nil)) rescue nil
|
73
68
|
if book
|
74
|
-
if ((not
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
if book
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
# if the book is opened with a different readonly mode in the same Excel,
|
84
|
-
# then save it, close and open the book with the new readonly mode
|
85
|
-
if (book.alive? && (not book.readonly == @options[:read_only]))
|
86
|
-
book.Save unless (book.readonly || book.saved)
|
87
|
-
book.workbook.Close if book.alive?
|
88
|
-
book.workbook = nil unless book.alive?
|
89
|
-
end
|
90
|
-
# reopen the book
|
91
|
-
book.get_workbook
|
92
|
-
end
|
93
|
-
return book if book.alive? && if_unsaved_not_set_or_accept_or_workbook_saved
|
94
|
-
end
|
69
|
+
if (((not current_options[:force_excel]) || (current_options[:force_excel] == book.excel)) &&
|
70
|
+
(not (book.alive? && (not book.saved) && (not current_options[:if_unsaved] == :accept))))
|
71
|
+
book.options = DEFAULT_OPEN_OPTS.merge(opts)
|
72
|
+
book.get_excel unless book.excel.alive?
|
73
|
+
# if the book is opened as readonly and should be opened as writable, then close it and open the book with the new readonly mode
|
74
|
+
book.close if (book.alive? && (not book.writable) && (not current_options[:read_only]))
|
75
|
+
# reopen the book
|
76
|
+
book.get_workbook unless book.alive?
|
77
|
+
return book
|
95
78
|
end
|
96
79
|
end
|
97
80
|
end
|
98
|
-
|
99
|
-
new(file,
|
81
|
+
current_options[:excel] = current_options[:force_excel] ? current_options[:force_excel] : current_options[:default_excel]
|
82
|
+
new(file, current_options, &block)
|
100
83
|
end
|
101
84
|
end
|
102
85
|
|
103
86
|
def initialize(file, opts={ }, &block)
|
104
|
-
|
105
|
-
|
106
|
-
@file = file
|
87
|
+
@options = DEFAULT_OPEN_OPTS.merge(opts)
|
88
|
+
@file = file
|
107
89
|
get_excel
|
108
90
|
get_workbook
|
109
91
|
book_store.store(self)
|
@@ -115,17 +97,6 @@ module RobustExcelOle
|
|
115
97
|
end
|
116
98
|
end
|
117
99
|
end
|
118
|
-
|
119
|
-
def set_defaults(opts)
|
120
|
-
@options = {
|
121
|
-
:excel => :reuse,
|
122
|
-
:default_excel => :reuse,
|
123
|
-
:if_locked => :readonly,
|
124
|
-
:if_unsaved => :new_excel,
|
125
|
-
:if_obstructed => :new_excel,
|
126
|
-
:read_only => false
|
127
|
-
}.merge(opts)
|
128
|
-
end
|
129
100
|
|
130
101
|
def get_excel
|
131
102
|
if @options[:excel] == :reuse
|
@@ -150,6 +121,7 @@ module RobustExcelOle
|
|
150
121
|
end
|
151
122
|
|
152
123
|
def get_workbook
|
124
|
+
raise ExcelErrorOpen, "file #{@file} not found" if ((not File.exist?(@file)) && @options[:if_absent] == :raise)
|
153
125
|
@workbook = @excel.Workbooks.Item(File.basename(@file)) rescue nil
|
154
126
|
if @workbook then
|
155
127
|
obstructed_by_other_book = (File.basename(@file) == File.basename(@workbook.Fullname)) &&
|
@@ -162,30 +134,30 @@ module RobustExcelOle
|
|
162
134
|
when :forget
|
163
135
|
@workbook.Close
|
164
136
|
@workbook = nil
|
165
|
-
|
137
|
+
open_or_create_workbook
|
166
138
|
when :save
|
167
139
|
save unless @workbook.Saved
|
168
140
|
@workbook.Close
|
169
141
|
@workbook = nil
|
170
|
-
|
142
|
+
open_or_create_workbook
|
171
143
|
when :close_if_saved
|
172
144
|
if (not @workbook.Saved) then
|
173
145
|
raise ExcelErrorOpen, "book with the same name in a different path is unsaved"
|
174
146
|
else
|
175
147
|
@workbook.Close
|
176
148
|
@workbook = nil
|
177
|
-
|
149
|
+
open_or_create_workbook
|
178
150
|
end
|
179
151
|
when :new_excel
|
180
152
|
@excel_options = {:displayalerts => false, :visible => false}.merge(@options)
|
181
153
|
@excel_options[:reuse] = false
|
182
154
|
@excel = Excel.new(@excel_options)
|
183
|
-
|
155
|
+
open_or_create_workbook
|
184
156
|
else
|
185
157
|
raise ExcelErrorOpen, ":if_obstructed: invalid option"
|
186
158
|
end
|
187
159
|
else
|
188
|
-
# book open, not obstructed by an other book, but not saved
|
160
|
+
# book open, not obstructed by an other book, but not saved and writable
|
189
161
|
if (not @workbook.Saved) then
|
190
162
|
case @options[:if_unsaved]
|
191
163
|
when :raise
|
@@ -193,18 +165,18 @@ module RobustExcelOle
|
|
193
165
|
when :forget
|
194
166
|
@workbook.Close
|
195
167
|
@workbook = nil
|
196
|
-
|
168
|
+
open_or_create_workbook
|
197
169
|
when :accept
|
198
170
|
# do nothing
|
199
171
|
when :alert
|
200
172
|
@excel.with_displayalerts true do
|
201
|
-
|
173
|
+
open_or_create_workbook
|
202
174
|
end
|
203
175
|
when :new_excel
|
204
176
|
@excel_options = {:displayalerts => false, :visible => false}.merge(@options)
|
205
177
|
@excel_options[:reuse] = false
|
206
178
|
@excel = Excel.new(@excel_options)
|
207
|
-
|
179
|
+
open_or_create_workbook
|
208
180
|
else
|
209
181
|
raise ExcelErrorOpen, ":if_unsaved: invalid option"
|
210
182
|
end
|
@@ -212,37 +184,50 @@ module RobustExcelOle
|
|
212
184
|
end
|
213
185
|
else
|
214
186
|
# book is not open
|
215
|
-
|
187
|
+
open_or_create_workbook
|
216
188
|
end
|
217
189
|
end
|
218
190
|
|
219
|
-
def
|
191
|
+
def open_or_create_workbook
|
192
|
+
if (not File.exist?(@file))
|
193
|
+
@workbook = self.class.create(@file)
|
194
|
+
#@workbook = Excel.new(:reuse => true).generate_workbook(@file)
|
195
|
+
return
|
196
|
+
end
|
220
197
|
if ((not @workbook) || (@options[:if_unsaved] == :alert) || @options[:if_obstructed]) then
|
221
198
|
begin
|
222
199
|
filename = RobustExcelOle::absolute_path(@file)
|
223
200
|
workbooks = @excel.Workbooks
|
224
201
|
workbooks.Open(filename,{ 'ReadOnly' => @options[:read_only] })
|
202
|
+
rescue WIN32OLERuntimeError
|
203
|
+
raise ExcelUserCanceled, "open: canceled by user"
|
204
|
+
end
|
205
|
+
begin
|
225
206
|
# workaround for bug in Excel 2010: workbook.Open does not always return
|
226
207
|
# the workbook with given file name
|
227
208
|
@workbook = workbooks.Item(File.basename(filename))
|
228
|
-
|
229
|
-
|
230
|
-
rescue WIN32OLERuntimeError
|
231
|
-
raise ExcelUserCanceled, "open: canceled by user"
|
209
|
+
rescue WIN32OLERuntimeError
|
210
|
+
raise ExcelErrorOpen, "open: item error"
|
232
211
|
end
|
233
212
|
end
|
234
213
|
end
|
235
214
|
|
215
|
+
# generate, save and close an empty workbook
|
216
|
+
def self.create(file)
|
217
|
+
@workbook = Excel.new(:reuse => true).generate_workbook(file)
|
218
|
+
@workbook
|
219
|
+
end
|
220
|
+
|
236
221
|
# closes the book, if it is alive
|
237
222
|
#
|
238
223
|
# options:
|
239
224
|
# :if_unsaved if book is unsaved
|
240
|
-
# :raise
|
241
|
-
# :save
|
242
|
-
# :forget
|
243
|
-
# :alert
|
225
|
+
# :raise (default) -> raise an exception
|
226
|
+
# :save -> save the book before it is closed
|
227
|
+
# :forget -> close the book
|
228
|
+
# :alert -> give control to excel
|
244
229
|
def close(opts = {:if_unsaved => :raise})
|
245
|
-
if (
|
230
|
+
if (alive? && (not @workbook.Saved) && writable) then
|
246
231
|
case opts[:if_unsaved]
|
247
232
|
when :raise
|
248
233
|
raise ExcelErrorClose, "book is unsaved (#{File.basename(self.stored_filename)})"
|
@@ -275,38 +260,38 @@ module RobustExcelOle
|
|
275
260
|
|
276
261
|
# modify a book such that its state (open/close, saved/unsaved, readonly/writable) remains unchanged.
|
277
262
|
# options:
|
278
|
-
# :
|
279
|
-
#
|
263
|
+
# :if_closed : :hidden (default) : open closed books in one separate Excel instance that is not visible and has no displayaslerts
|
264
|
+
# :reuse : open closed books in the Excel instance of the book, if it exists, reuse another Excel, otherwise
|
280
265
|
# :read_only: Open the book unobtrusively for reading only (default: false)
|
281
|
-
# :
|
266
|
+
# :use_readonly_excel: if the book is opened only as ReadOnly and shall be modified, then
|
282
267
|
# true: close it and open it as writable in the excel instance where it was open so far
|
283
|
-
# false(default)
|
284
|
-
# in a new excel instance
|
268
|
+
# false (default) open it as writable in another running excel instance, if it exists,
|
269
|
+
# otherwise open in a new excel instance.
|
270
|
+
# :keep_open: let the book open after unobtrusively opening (default: false)
|
285
271
|
def self.unobtrusively(file, opts = { })
|
286
272
|
options = {
|
287
|
-
:
|
288
|
-
:visible => false,
|
273
|
+
:if_closed => :hidden,
|
289
274
|
:read_only => false,
|
290
|
-
:
|
275
|
+
:use_readonly_excel => false,
|
276
|
+
:keep_open => false,
|
291
277
|
}.merge(opts)
|
292
278
|
book = book_store.fetch(file, :prefer_writable => (not options[:read_only]))
|
293
279
|
was_not_alive_or_nil = book.nil? || (not book.alive?)
|
294
280
|
was_saved = was_not_alive_or_nil ? true : book.saved
|
295
|
-
|
296
|
-
old_book = book if was_readonly
|
281
|
+
was_writable = book.writable unless was_not_alive_or_nil
|
297
282
|
old_visible = (book && book.excel.alive?) ? book.excel.visible : false
|
298
283
|
begin
|
299
|
-
book = was_not_alive_or_nil ?
|
300
|
-
|
301
|
-
|
302
|
-
|
284
|
+
book = was_not_alive_or_nil ?
|
285
|
+
(options[:if_closed] == :hidden ? open(file, :force_excel => book_store.ensure_hidden_excel) : open(file)) :
|
286
|
+
((was_writable || options[:read_only]) ? book :
|
287
|
+
(options[:use_readonly_excel] ? open(file, :force_excel => book.excel) : open(file, :force_excel => :new)))
|
288
|
+
book.excel.visible = opts[:visible] unless opts[:visible].nil?
|
303
289
|
yield book
|
304
290
|
ensure
|
305
|
-
book.save if (was_not_alive_or_nil || was_saved || (
|
291
|
+
book.save if (was_not_alive_or_nil || was_saved || ((not was_writable) && (not options[:read_only]))) && (not book.saved)
|
306
292
|
# book was open, readonly and shoud be modified
|
307
|
-
if (not was_not_alive_or_nil) && (not options[:read_only]) &&
|
308
|
-
book.
|
309
|
-
open(file, :if_obstructed => :new_excel, :read_only => true)
|
293
|
+
if (not was_not_alive_or_nil) && (not options[:read_only]) && (not was_writable) && options[:use_readonly_excel]
|
294
|
+
open(file, :force_excel => book.excel, :if_obstructed => :new_excel, :read_only => true)
|
310
295
|
end
|
311
296
|
book.excel.visible = old_visible
|
312
297
|
book.close if (was_not_alive_or_nil && (not opts[:keep_open]))
|
@@ -349,15 +334,15 @@ module RobustExcelOle
|
|
349
334
|
@workbook.Fullname.tr('\\','/') rescue nil
|
350
335
|
end
|
351
336
|
|
352
|
-
def
|
353
|
-
@workbook.ReadOnly
|
337
|
+
def writable
|
338
|
+
(not @workbook.ReadOnly) if @workbook
|
354
339
|
end
|
355
340
|
|
356
341
|
def saved
|
357
|
-
@workbook.Saved
|
342
|
+
@workbook.Saved if @workbook
|
358
343
|
end
|
359
344
|
|
360
|
-
# returns true, if the full book names and excel appications are identical, false
|
345
|
+
# returns true, if the full book names and excel appications are identical, false otherwise
|
361
346
|
def == other_book
|
362
347
|
other_book.is_a?(Book) &&
|
363
348
|
@excel == other_book.excel &&
|
@@ -530,20 +515,4 @@ public
|
|
530
515
|
class ExcelErrorSheet < ExcelError # :nodoc: #
|
531
516
|
end
|
532
517
|
|
533
|
-
|
534
|
-
end
|
535
|
-
|
536
|
-
|
537
|
-
__END__
|
538
|
-
|
539
|
-
|
540
|
-
class Object
|
541
|
-
def update_extracted hash, key
|
542
|
-
value = hash[param_name]
|
543
|
-
self.send("#{key}=", value) if value
|
544
|
-
end
|
545
|
-
end
|
546
|
-
@excel.visible = @options[:visible] if @options[:visible]
|
547
|
-
@excel.displayalerts = @options[:dispayalerts]
|
548
|
-
@excel.update_extracted(@options, [:visible, :dispayalerts])
|
549
|
-
@excel.options.merge(@options.extract(:visible, :dispayalerts))
|
518
|
+
end
|
@@ -7,14 +7,16 @@ module RobustExcelOle
|
|
7
7
|
|
8
8
|
def initialize
|
9
9
|
@filename2books = Hash.new {|hash, key| hash[key] = [] }
|
10
|
+
@hidden_excel_instance = nil
|
10
11
|
end
|
11
12
|
|
12
13
|
# returns a book with the given filename, if it was open once
|
13
14
|
# prefers open books to closed books, and among them, prefers more recently opened books
|
15
|
+
# excludes hidden Excel instance
|
14
16
|
# options: :prefer_writable return the writable book, if it is open (default: true)
|
15
|
-
# return the book according to the preference order mentioned above
|
16
|
-
# :prefer_excel return the book in the given excel instance, if it exists
|
17
|
-
# proceed according to prefer_writable
|
17
|
+
# otherwise return the book according to the preference order mentioned above
|
18
|
+
# :prefer_excel return the book in the given excel instance, if it exists,
|
19
|
+
# otherwise proceed according to prefer_writable
|
18
20
|
def fetch(filename, options = {:prefer_writable => true })
|
19
21
|
filename_key = RobustExcelOle::canonize(filename)
|
20
22
|
weakref_books = @filename2books[filename_key]
|
@@ -24,20 +26,22 @@ module RobustExcelOle
|
|
24
26
|
if (not wr_book.weakref_alive?)
|
25
27
|
@filename2books[filename_key].delete(wr_book)
|
26
28
|
else
|
27
|
-
|
28
|
-
|
29
|
+
book = wr_book.__getobj__
|
30
|
+
next if book.excel == try_hidden_excel
|
31
|
+
if options[:prefer_excel] && book.excel == options[:prefer_excel]
|
32
|
+
result = book
|
29
33
|
break
|
30
34
|
end
|
31
|
-
if
|
32
|
-
open_book =
|
33
|
-
break if (
|
35
|
+
if book.alive?
|
36
|
+
open_book = book
|
37
|
+
break if (book.writable && options[:prefer_writable])
|
34
38
|
else
|
35
|
-
closed_book =
|
39
|
+
closed_book = book
|
36
40
|
end
|
37
41
|
end
|
38
42
|
end
|
39
43
|
result = result ? result : (open_book ? open_book : closed_book)
|
40
|
-
result
|
44
|
+
result if result
|
41
45
|
end
|
42
46
|
|
43
47
|
# stores a book
|
@@ -52,20 +56,16 @@ module RobustExcelOle
|
|
52
56
|
book.stored_filename = book.filename
|
53
57
|
end
|
54
58
|
|
55
|
-
#
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
if @filename2books
|
60
|
-
@filename2books.each do |filename,books|
|
61
|
-
if books
|
62
|
-
books.each do |book|
|
63
|
-
excel2books[book.excel] |= [book.workbook]
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
59
|
+
# creates and returns a separate Excel instance with Visible and DisplayAlerts false
|
60
|
+
def ensure_hidden_excel
|
61
|
+
unless (@hidden_excel_instance && @hidden_excel_instance.weakref_alive? && @hidden_excel_instance.__getobj__.alive?)
|
62
|
+
@hidden_excel_instance = WeakRef.new(Excel.create)
|
67
63
|
end
|
68
|
-
|
64
|
+
@hidden_excel_instance.__getobj__
|
65
|
+
end
|
66
|
+
|
67
|
+
def try_hidden_excel
|
68
|
+
@hidden_excel_instance.__getobj__ if (@hidden_excel_instance && @hidden_excel_instance.weakref_alive? && @hidden_excel_instance.__getobj__.alive?)
|
69
69
|
end
|
70
70
|
|
71
71
|
# prints the book store
|