robust_excel_ole 0.3.4 → 0.3.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/README.rdoc +73 -26
  2. data/README_detail.rdoc +92 -27
  3. data/examples/edit_sheets/example_access_sheets_and_cells.rb +3 -3
  4. data/examples/edit_sheets/example_concating.rb +12 -12
  5. data/examples/edit_sheets/example_copying.rb +47 -0
  6. data/examples/edit_sheets/example_expanding.rb +17 -26
  7. data/examples/edit_sheets/example_naming.rb +13 -10
  8. data/examples/edit_sheets/example_ranges.rb +2 -2
  9. data/examples/edit_sheets/example_saving.rb +8 -14
  10. data/examples/open_save_close/example_control_to_excel.rb +1 -1
  11. data/examples/open_save_close/example_if_obstructed_closeifsaved.rb +3 -3
  12. data/examples/open_save_close/example_if_obstructed_save.rb +3 -3
  13. data/examples/open_save_close/example_if_unsaved_accept.rb +1 -1
  14. data/examples/open_save_close/example_if_unsaved_forget.rb +4 -4
  15. data/examples/open_save_close/example_if_unsaved_forget_more.rb +5 -5
  16. data/examples/open_save_close/example_read_only.rb +1 -1
  17. data/examples/open_save_close/example_rename_cells.rb +1 -13
  18. data/examples/open_save_close/example_simple.rb +1 -1
  19. data/examples/open_save_close/example_unobtrusively.rb +3 -3
  20. data/lib/robust_excel_ole.rb +81 -2
  21. data/lib/robust_excel_ole/book.rb +171 -118
  22. data/lib/robust_excel_ole/{book_store.rb → bookstore.rb} +2 -2
  23. data/lib/robust_excel_ole/excel.rb +153 -24
  24. data/lib/robust_excel_ole/range.rb +2 -2
  25. data/lib/robust_excel_ole/sheet.rb +84 -35
  26. data/lib/robust_excel_ole/version.rb +1 -1
  27. data/reo.bat +3 -0
  28. data/spec/book_close_spec.rb +179 -0
  29. data/spec/book_misc_spec.rb +365 -0
  30. data/spec/book_open_spec.rb +793 -0
  31. data/spec/book_save_spec.rb +257 -0
  32. data/spec/book_sheet_spec.rb +160 -0
  33. data/spec/book_spec.rb +145 -1533
  34. data/spec/book_subclass_spec.rb +50 -0
  35. data/spec/book_unobtr_spec.rb +950 -0
  36. data/spec/{book_store_spec.rb → bookstore_spec.rb} +5 -5
  37. data/spec/cell_spec.rb +6 -6
  38. data/spec/data/{more_workbook.xls → another_workbook.xls} +0 -0
  39. data/spec/data/different_workbook.xls +0 -0
  40. data/spec/data/workbook.xls +0 -0
  41. data/spec/data/workbook.xlsm +0 -0
  42. data/spec/data/workbook.xlsx +0 -0
  43. data/spec/data/workbook_linked.xlsm +0 -0
  44. data/spec/data/workbook_linked_sub.xlsm +0 -0
  45. data/spec/excel_spec.rb +204 -5
  46. data/spec/range_spec.rb +6 -6
  47. data/spec/sheet_spec.rb +122 -34
  48. metadata +18 -8
  49. data/spec/data/workbook_connected_sub.xlsm +0 -0
@@ -1,4 +1,3 @@
1
-
2
1
  # -*- coding: utf-8 -*-
3
2
 
4
3
  require 'weakref'
@@ -11,12 +10,14 @@ module RobustExcelOle
11
10
  attr_accessor :stored_filename
12
11
  attr_accessor :options
13
12
 
13
+
14
14
  DEFAULT_OPEN_OPTS = {
15
15
  :excel => :reuse,
16
16
  :default_excel => :reuse,
17
- :if_locked => :readonly,
17
+ :if_lockraiseed => :readonly,
18
18
  :if_unsaved => :raise,
19
19
  :if_obstructed => :raise,
20
+ :if_absent => :raise,
20
21
  :read_only => false
21
22
  }
22
23
 
@@ -51,8 +52,9 @@ module RobustExcelOle
51
52
  # :close_if_saved -> close the old book and open the new book, if the old book is saved,
52
53
  # otherwise raise an exception.
53
54
  # :new_excel -> open the new book in a new Excel
54
- # :if_absent :create (default) -> creates a new Excel file, if it does not exists
55
- # :raise -> raises an exception , if the file does not exists
55
+ # :if_absent :raise (default) -> raises an exception , if the file does not exists
56
+ # :create -> creates a new Excel file, if it does not exists
57
+ #
56
58
  # :read_only open in read-only mode (default: false)
57
59
  # :displayalerts enable DisplayAlerts in Excel (default: false)
58
60
  # :visible make visible in Excel (default: false)
@@ -63,19 +65,18 @@ module RobustExcelOle
63
65
  book = nil
64
66
  if (not (current_options[:force_excel] == :new && (not current_options[:if_locked] == :take_writable)))
65
67
  # 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,
68
+ book = bookstore.fetch(file,
67
69
  :prefer_writable => (not current_options[:read_only]),
68
- :prefer_excel => (current_options[:read_only] ? Book.excel(current_options[:force_excel]) : nil)) rescue nil
70
+ :prefer_excel => (current_options[:read_only] ? current_options[:force_excel].excel : nil)) rescue nil
69
71
  if book
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)) &&
72
+ if (((not current_options[:force_excel]) || (current_options[:force_excel].excel == book.excel)) &&
72
73
  (not (book.alive? && (not book.saved) && (not current_options[:if_unsaved] == :accept))))
73
74
  book.options = DEFAULT_OPEN_OPTS.merge(opts)
74
75
  book.get_excel unless book.excel.alive?
75
76
  # 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
76
77
  book.close if (book.alive? && (not book.writable) && (not current_options[:read_only]))
77
78
  # reopen the book
78
- book.get_workbook unless book.alive?
79
+ book.get_workbook(file) unless book.alive?
79
80
  return book
80
81
  end
81
82
  end
@@ -86,11 +87,10 @@ module RobustExcelOle
86
87
  end
87
88
 
88
89
  def initialize(file, opts={ }, &block)
89
- @options = DEFAULT_OPEN_OPTS.merge(opts)
90
- @file = file
90
+ @options = DEFAULT_OPEN_OPTS.merge(opts)
91
91
  get_excel
92
- get_workbook
93
- book_store.store(self)
92
+ get_workbook file
93
+ bookstore.store(self)
94
94
  if block
95
95
  begin
96
96
  yield self
@@ -99,20 +99,33 @@ module RobustExcelOle
99
99
  end
100
100
  end
101
101
  end
102
+
103
+ def self.excel_class
104
+ @excel_class ||= begin
105
+ module_name = self.parent_name
106
+ "#{module_name}::Excel".constantize
107
+ rescue NameError => e
108
+ Excel
109
+ end
110
+ end
111
+
112
+ def excel_class
113
+ self.class.excel_class
114
+ end
115
+
102
116
 
103
117
  def get_excel
104
118
  if @options[:excel] == :reuse
105
- @excel = Excel.new(:reuse => true)
119
+ @excel = excel_class.new(:reuse => true)
106
120
  end
107
121
  @excel_options = nil
108
122
  if (not @excel)
109
123
  if @options[:excel] == :new
110
124
  @excel_options = {:displayalerts => false, :visible => false}.merge(@options)
111
125
  @excel_options[:reuse] = false
112
- @excel = Excel.new(@excel_options)
126
+ @excel = excel_class.new(@excel_options)
113
127
  else
114
- @excel = @options[:excel]
115
- @excel = Book.excel(@options[:excel])
128
+ @excel = @options[:excel].excel
116
129
  end
117
130
  end
118
131
  # if :excel => :new or (:excel => :reuse but could not reuse)
@@ -123,39 +136,46 @@ module RobustExcelOle
123
136
  end
124
137
  end
125
138
 
126
- def get_workbook
127
- raise ExcelErrorOpen, "file #{@file} not found" if ((not File.exist?(@file)) && @options[:if_absent] == :raise)
128
- @workbook = @excel.Workbooks.Item(File.basename(@file)) rescue nil
139
+ def get_workbook file
140
+ file = @stored_filename ? @stored_filename : file
141
+ unless File.exist?(file)
142
+ if @options[:if_absent] == :create
143
+ @workbook = excel_class.current.generate_workbook(file)
144
+ else
145
+ raise ExcelErrorOpen, "file #{file} not found"
146
+ end
147
+ end
148
+ @workbook = @excel.Workbooks.Item(File.basename(file)) rescue nil
129
149
  if @workbook then
130
- obstructed_by_other_book = (File.basename(@file) == File.basename(@workbook.Fullname)) &&
131
- (not (RobustExcelOle::absolute_path(@file) == @workbook.Fullname))
150
+ obstructed_by_other_book = (File.basename(file) == File.basename(@workbook.Fullname)) &&
151
+ (not (RobustExcelOle::absolute_path(file) == @workbook.Fullname))
132
152
  # if book is obstructed by a book with same name and different path
133
153
  if obstructed_by_other_book then
134
154
  case @options[:if_obstructed]
135
155
  when :raise
136
- raise ExcelErrorOpen, "blocked by a book with the same name in a different path: #{File.basename(@file)}"
156
+ raise ExcelErrorOpen, "blocked by a book with the same name in a different path: #{File.basename(file)}"
137
157
  when :forget
138
158
  @workbook.Close
139
159
  @workbook = nil
140
- open_or_create_workbook
160
+ open_or_create_workbook file
141
161
  when :save
142
162
  save unless @workbook.Saved
143
163
  @workbook.Close
144
164
  @workbook = nil
145
- open_or_create_workbook
165
+ open_or_create_workbook file
146
166
  when :close_if_saved
147
167
  if (not @workbook.Saved) then
148
- raise ExcelErrorOpen, "book with the same name in a different path is unsaved: #{File.basename(@file)}"
168
+ raise ExcelErrorOpen, "book with the same name in a different path is unsaved: #{File.basename(file)}"
149
169
  else
150
170
  @workbook.Close
151
171
  @workbook = nil
152
- open_or_create_workbook
172
+ open_or_create_workbook file
153
173
  end
154
174
  when :new_excel
155
175
  @excel_options = {:displayalerts => false, :visible => false}.merge(@options)
156
176
  @excel_options[:reuse] = false
157
- @excel = Excel.new(@excel_options)
158
- open_or_create_workbook
177
+ @excel = excel_class.new(@excel_options)
178
+ open_or_create_workbook file
159
179
  else
160
180
  raise ExcelErrorOpen, ":if_obstructed: invalid option: #{@options[:if_obstructed]}"
161
181
  end
@@ -164,22 +184,22 @@ module RobustExcelOle
164
184
  if (not @workbook.Saved) then
165
185
  case @options[:if_unsaved]
166
186
  when :raise
167
- raise ExcelErrorOpen, "book is already open but not saved (#{File.basename(@file)})"
187
+ raise ExcelErrorOpen, "book is already open but not saved (#{File.basename(file)})"
168
188
  when :forget
169
189
  @workbook.Close
170
190
  @workbook = nil
171
- open_or_create_workbook
191
+ open_or_create_workbook file
172
192
  when :accept
173
193
  # do nothing
174
194
  when :alert
175
195
  @excel.with_displayalerts true do
176
- open_or_create_workbook
196
+ open_or_create_workbook file
177
197
  end
178
198
  when :new_excel
179
199
  @excel_options = {:displayalerts => false, :visible => false}.merge(@options)
180
200
  @excel_options[:reuse] = false
181
- @excel = Excel.new(@excel_options)
182
- open_or_create_workbook
201
+ @excel = excel_class.new(@excel_options)
202
+ open_or_create_workbook file
183
203
  else
184
204
  raise ExcelErrorOpen, ":if_unsaved: invalid option: #{@options[:if_unsaved]}"
185
205
  end
@@ -187,23 +207,24 @@ module RobustExcelOle
187
207
  end
188
208
  else
189
209
  # book is not open
190
- open_or_create_workbook
210
+ open_or_create_workbook file
191
211
  end
192
212
  end
193
213
 
194
- def open_or_create_workbook
195
- if (not File.exist?(@file))
196
- @workbook = Excel.current.generate_workbook(@file)
197
- return
198
- end
214
+ def open_or_create_workbook file
199
215
  if ((not @workbook) || (@options[:if_unsaved] == :alert) || @options[:if_obstructed]) then
200
216
  begin
201
- filename = RobustExcelOle::absolute_path(@file)
202
- workbooks = @excel.Workbooks
217
+ filename = RobustExcelOle::absolute_path(file)
218
+ begin
219
+ workbooks = @excel.Workbooks
220
+ rescue RuntimeError => msg
221
+ puts "RuntimeError: #{msg.message}"
222
+ raise ExcelErrorOpen, "Excel instance not alive or damaged" if msg.message =~ /failed to get Dispatch Interface/
223
+ end
203
224
  workbooks.Open(filename,{ 'ReadOnly' => @options[:read_only] })
204
225
  rescue WIN32OLERuntimeError => msg
205
- puts "msg: #{msg}"
206
- raise ExcelErrorOpen, "open: user canceled or open error" if msg.message =~ /OLE error code:800A03EC/
226
+ puts "WIN32OLERuntimeError: #{msg.message}"
227
+ raise ExcelErrorOpen, "open: user canceled or open error" if msg.message =~ /800A03EC/
207
228
  end
208
229
  begin
209
230
  # workaround for bug in Excel 2010: workbook.Open does not always return
@@ -215,20 +236,6 @@ module RobustExcelOle
215
236
  end
216
237
  end
217
238
 
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
-
232
239
  # closes the book, if it is alive
233
240
  #
234
241
  # options:
@@ -269,91 +276,113 @@ module RobustExcelOle
269
276
 
270
277
  public
271
278
 
279
+ def self.for_reading(*args, &block)
280
+ args = args.dup
281
+ opts = args.last.is_a?(Hash) ? args.pop : {}
282
+ opts = {:read_only => true}.merge(opts)
283
+ args.push opts
284
+ unobtrusively(*args, &block)
285
+ end
286
+
287
+ def self.for_modifying(*args, &block)
288
+ args = args.dup
289
+ opts = args.last.is_a?(Hash) ? args.pop : {}
290
+ opts = {:read_only => false}.merge(opts)
291
+ args.push opts
292
+ unobtrusively(*args, &block)
293
+ end
294
+
272
295
  # modify a book such that its state (open/close, saved/unsaved, readonly/writable) remains unchanged.
273
- # options:
274
- # :if_closed : :hidden (default) : open closed books in one separate Excel instance that is not visible and has no displayaslerts
275
- # :reuse : open closed books in the Excel instance of the book, if it exists, reuse another Excel, otherwise
276
- # <excel-instance> : open closed books in the given Excel instance
296
+ # options:
297
+ # :reuse (default) : open closed books in the Excel instance of the book, if it exists, reuse another Excel, otherwise
298
+ # :hidden : open closed books in one separate Excel instance that is not visible and has no displayaslerts
299
+ # <excel-instance> : open closed books in the given Excel instance
277
300
  # :read_only: Open the book unobtrusively for reading only (default: false)
278
- # :use_readonly_excel: if the book is opened only as ReadOnly and shall be modified, then
279
- # true: close it and open it as writable in the excel instance where it was open so far
280
- # false (default) open it as writable in another running excel instance, if it exists,
281
- # otherwise open in a new excel instance.
301
+ # :readonly_excel: if the book is opened only as ReadOnly and shall be modified, then
302
+ # true: close it and open it as writable in the excel instance where it was open so far
303
+ # false (default) open it as writable in another running excel instance, if it exists,
304
+ # otherwise open in a new excel instance.
282
305
  # :keep_open: let the book open after unobtrusively opening (default: false)
283
- def self.unobtrusively(file, opts = { })
306
+ def self.unobtrusively(file, if_closed = nil, opts = { }, &block)
307
+ if if_closed.is_a? Hash
308
+ opts = if_closed
309
+ if_closed = nil
310
+ end
311
+ if_closed = :reuse unless if_closed
284
312
  options = {
285
- :if_closed => :hidden,
286
313
  :read_only => false,
287
- :use_readonly_excel => false,
314
+ :readonly_excel => false,
288
315
  :keep_open => false,
289
316
  }.merge(opts)
290
- book = book_store.fetch(file, :prefer_writable => (not options[:read_only]))
317
+ book = bookstore.fetch(file, :prefer_writable => (not options[:read_only]))
291
318
  was_not_alive_or_nil = book.nil? || (not book.alive?)
292
319
  was_saved = was_not_alive_or_nil ? true : book.saved
293
320
  was_writable = book.writable unless was_not_alive_or_nil
294
321
  begin
295
322
  book =
296
323
  if was_not_alive_or_nil
297
- case options[:if_closed]
298
- when :hidden
299
- open(file, :force_excel => book_store.hidden_excel)
324
+ case if_closed
300
325
  when :reuse
301
- open(file)
326
+ open(file, :read_only => options[:read_only])
327
+ when :hidden
328
+ open(file, :force_excel => bookstore.hidden_excel, :read_only => options[:read_only])
302
329
  else
303
- open(file, :force_excel => options[:if_closed])
330
+ open(file, :force_excel => if_closed, :read_only => options[:read_only])
304
331
  end
305
332
  else
306
333
  if was_writable || options[:read_only]
307
334
  book
308
335
  else
309
- options[:use_readonly_excel] ? open(file, :force_excel => book.excel) : open(file, :force_excel => :new)
336
+ options[:readonly_excel] ? open(file, :force_excel => book.excel, :read_only => options[:read_only]) :
337
+ open(file, :force_excel => :new, :read_only => options[:read_only])
310
338
  end
311
339
  end
312
340
  yield book
313
341
  ensure
314
- book.save if (was_not_alive_or_nil || was_saved || ((not was_writable) && (not options[:read_only]))) && (book && (not book.saved))
342
+ book.save if (was_not_alive_or_nil || was_saved || ((not options[:read_only]) && (not was_writable))) && (not options[:read_only]) && book && (not book.saved)
315
343
  # book was open, readonly and shoud be modified
316
- if (not was_not_alive_or_nil) && (not options[:read_only]) && (not was_writable) && options[:use_readonly_excel]
344
+ if (not was_not_alive_or_nil) && (not options[:read_only]) && (not was_writable) && options[:readonly_excel]
317
345
  open(file, :force_excel => book.excel, :if_obstructed => :new_excel, :read_only => true)
318
346
  end
319
347
  book.close if (was_not_alive_or_nil && (not opts[:keep_open]) && book)
320
348
  end
321
349
  end
322
350
 
351
+ def reopen
352
+ self.class.open(self.stored_filename)
353
+ end
354
+
323
355
  # rename a range
324
356
  def rename_range(name,new_name)
325
357
  begin
326
- p "name: #{name}"
327
- p "new_name: #{new_name}"
328
358
  item = self.Names.Item(name)
329
- p "nil" if item.nil?
330
359
  rescue WIN32OLERuntimeError
331
- raise ExcelErrorRename, "name #{name} not in #{File.basename(self.stored_filename)}"
360
+ raise ExcelError, "name #{name} not in #{File.basename(self.stored_filename)}"
332
361
  end
333
362
  begin
334
363
  item.Name = new_name
335
364
  rescue WIN32OLERuntimeError
336
- raise ExcelErrorRename, "name error in #{File.basename(self.stored_filename)}"
365
+ raise ExcelError, "name error in #{File.basename(self.stored_filename)}"
337
366
  end
338
367
  end
339
368
 
340
369
  # returns the contents of a range with given name
341
- def nvalue(name)
370
+ # if no contents could returned, then return default value, if a default value was provided
371
+ # raise an error, otherwise
372
+ def nvalue(name, opts = {:default => nil})
342
373
  begin
343
374
  item = self.Names.Item(name)
344
375
  rescue WIN32OLERuntimeError
345
- raise ExcelErrorNValue, "name #{name} not in #{File.basename(self.stored_filename)}"
376
+ return opts[:default] if opts[:default]
377
+ raise ExcelErrorNValue, "name #{name} not in #{File.basename(self.stored_filename)}"
346
378
  end
347
379
  begin
348
- referstorange = item.RefersToRange
349
- rescue WIN32OLERuntimeError
350
- raise ExcelErrorNValue, "range error in #{File.basename(self.stored_filename)}"
351
- end
352
- begin
353
- referstorange.Value
354
- rescue WIN32OLERuntimeError
355
- raise ExcelErrorNValue, "value error in #{File.basename(self.stored_filename)}"
380
+ value = item.RefersToRange.Value
381
+ rescue WIN32OLERuntimeError
382
+ return opts[:default] if opts[:default]
383
+ raise ExcelErrorNValue, "RefersToRange error of name #{name} in #{File.basename(self.stored_filename)}"
356
384
  end
385
+ value
357
386
  end
358
387
 
359
388
  # set the contents of a range with given name
@@ -364,14 +393,19 @@ module RobustExcelOle
364
393
  raise ExcelErrorNValue, "name #{name} not in #{File.basename(self.stored_filename)}"
365
394
  end
366
395
  begin
367
- referstorange = item.RefersToRange
396
+ item.RefersToRange.Value = value
368
397
  rescue WIN32OLERuntimeError
369
- raise ExcelErrorNValue, "range error in #{File.basename(self.stored_filename)}"
398
+ raise ExcelErrorNValue, "RefersToRange error of name #{name} in #{File.basename(self.stored_filename)}"
370
399
  end
400
+ end
401
+
402
+ def activate
403
+ @excel.visible = true
371
404
  begin
372
- referstorange.Value = value
405
+ self.Activate
406
+ self.ActiveSheet.Activate
373
407
  rescue WIN32OLERuntimeError
374
- raise ExcelErrorNValue, "value error in #{File.basename(self.stored_filename)}"
408
+ raise ExcelError, "cannot activate"
375
409
  end
376
410
  end
377
411
 
@@ -474,7 +508,7 @@ module RobustExcelOle
474
508
  when '.xlsm': RobustExcelOle::XlOpenXMLWorkbookMacroEnabled
475
509
  end
476
510
  @workbook.SaveAs(RobustExcelOle::absolute_path(file), file_format)
477
- book_store.store(self)
511
+ bookstore.store(self)
478
512
  rescue WIN32OLERuntimeError => msg
479
513
  if msg.message =~ /SaveAs/ and msg.message =~ /Workbook/ then
480
514
  if @opts[:if_exists] == :alert then
@@ -491,9 +525,24 @@ module RobustExcelOle
491
525
 
492
526
  public
493
527
 
494
- def [] sheet
495
- sheet += 1 if sheet.is_a? Numeric
496
- RobustExcelOle::Sheet.new(@workbook.Worksheets.Item(sheet))
528
+ # returns a sheet, if a name of a sheet or a number is given
529
+ # returns the value of the range, if a global name of a range in the book is given
530
+ def [] name
531
+ name += 1 if name.is_a? Numeric
532
+ begin
533
+ RobustExcelOle::Sheet.new(@workbook.Worksheets.Item(name))
534
+ rescue WIN32OLERuntimeError => msg
535
+ if msg.message =~ /8002000B/
536
+ nvalue(name)
537
+ else
538
+ raise ExcelError, "could neither return a sheet nor a value of a range when giving the name #{name}"
539
+ end
540
+ end
541
+ end
542
+
543
+ # set the value of a range given its name
544
+ def []= (name, value)
545
+ set_nvalue(name,value)
497
546
  end
498
547
 
499
548
  def each
@@ -507,35 +556,40 @@ module RobustExcelOle
507
556
  opts = sheet
508
557
  sheet = nil
509
558
  end
510
-
511
559
  new_sheet_name = opts.delete(:as)
512
-
513
560
  ws = @workbook.Worksheets
514
- after_or_before, base_sheet = opts.to_a.first ||
515
- [:after, Sheet.new(ws.Item(ws.Count))]
516
- base_sheet = base_sheet.sheet
561
+ after_or_before, base_sheet = opts.to_a.first || [:after, Sheet.new(ws.Item(ws.Count))]
562
+ base_sheet = base_sheet.worksheet
517
563
  sheet ? sheet.Copy({ after_or_before.to_s => base_sheet }) : @workbook.WorkSheets.Add({ after_or_before.to_s => base_sheet })
518
564
  new_sheet = RobustExcelOle::Sheet.new(@excel.Activesheet)
519
565
  begin
520
566
  new_sheet.name = new_sheet_name if new_sheet_name
521
567
  rescue WIN32OLERuntimeError => msg
522
- if msg.message =~ /OLE error code:800A03EC/
568
+ if msg.message =~ /800A03EC/
523
569
  raise ExcelErrorSheet, "sheet name already exists"
570
+ else
571
+ puts "#{msg.message}"
572
+ raise ExcelErrorSheetUnknown
524
573
  end
525
574
  end
526
575
  new_sheet
527
- end
576
+ end
528
577
 
529
- def add_name name
578
+ def self.bookstore
579
+ @@bookstore ||= Bookstore.new
530
580
  end
531
581
 
532
- def self.book_store
533
- @@bookstore ||= BookStore.new
582
+ def bookstore
583
+ self.class.bookstore
584
+ end
585
+
586
+ def to_s
587
+ "<#BOOK:" + "#{"not alive " unless alive?}" + "#{File.basename(@stored_filename)}" + " #{@workbook} #{@excel}" + ">"
534
588
  end
535
589
 
536
- def book_store
537
- self.class.book_store
538
- end
590
+ def inspect
591
+ self.to_s
592
+ end
539
593
 
540
594
  private
541
595
 
@@ -577,10 +631,7 @@ public
577
631
  class ExcelErrorSaveUnknown < ExcelErrorSave # :nodoc: #
578
632
  end
579
633
 
580
- class ExcelErrorRename < WIN32OLERuntimeError # :nodoc: #
581
- end
582
-
583
- class ExcelErrorNValue < WIN32OLERuntimeError # :nodoc: #
634
+ class ExcelErrorNValue < ExcelError # :nodoc: #
584
635
  end
585
636
 
586
637
  class ExcelUserCanceled < RuntimeError # :nodoc: #
@@ -589,4 +640,6 @@ public
589
640
  class ExcelErrorSheet < ExcelError # :nodoc: #
590
641
  end
591
642
 
643
+ class ExcelErrorSheetUnknown < ExcelErrorSheet # :nodoc: #
644
+ end
592
645
  end