robust_excel_ole 0.3.8 → 0.3.9

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.
Files changed (48) hide show
  1. data/.yardopts +1 -0
  2. data/examples/edit_sheets/example_access_sheets_and_cells.rb +1 -1
  3. data/examples/edit_sheets/example_adding_sheets.rb +1 -1
  4. data/examples/edit_sheets/example_concating.rb +2 -2
  5. data/examples/edit_sheets/example_copying.rb +2 -2
  6. data/examples/edit_sheets/example_expanding.rb +2 -2
  7. data/examples/edit_sheets/example_naming.rb +2 -2
  8. data/examples/edit_sheets/example_ranges.rb +1 -1
  9. data/examples/edit_sheets/example_saving.rb +2 -2
  10. data/examples/open_save_close/example_control_to_excel.rb +1 -1
  11. data/examples/open_save_close/example_default_excel.rb +1 -1
  12. data/examples/open_save_close/example_force_excel.rb +1 -1
  13. data/examples/open_save_close/example_if_obstructed_closeifsaved.rb +1 -1
  14. data/examples/open_save_close/example_if_obstructed_forget.rb +1 -1
  15. data/examples/open_save_close/example_if_obstructed_save.rb +1 -1
  16. data/examples/open_save_close/example_if_unsaved_accept.rb +1 -1
  17. data/examples/open_save_close/example_if_unsaved_forget.rb +1 -1
  18. data/examples/open_save_close/example_if_unsaved_forget_more.rb +1 -1
  19. data/examples/open_save_close/example_read_only.rb +1 -1
  20. data/examples/open_save_close/example_rename_cells.rb +2 -2
  21. data/examples/open_save_close/example_reuse.rb +1 -1
  22. data/examples/open_save_close/example_simple.rb +1 -1
  23. data/examples/open_save_close/example_unobtrusively.rb +1 -1
  24. data/lib/reo_console.rb +2 -2
  25. data/lib/robust_excel_ole.rb +1 -174
  26. data/lib/robust_excel_ole/book.rb +47 -63
  27. data/lib/robust_excel_ole/bookstore.rb +4 -4
  28. data/lib/robust_excel_ole/excel.rb +12 -18
  29. data/lib/robust_excel_ole/general.rb +188 -0
  30. data/lib/robust_excel_ole/sheet.rb +1 -1
  31. data/lib/robust_excel_ole/utilities.rb +1 -1
  32. data/lib/robust_excel_ole/version.rb +1 -1
  33. data/spec/{book_specs/book_spec.rb → book_spec.rb} +26 -24
  34. data/spec/book_specs/book_all_spec.rb +1 -1
  35. data/spec/book_specs/book_close_spec.rb +16 -15
  36. data/spec/book_specs/book_misc_spec.rb +4 -3
  37. data/spec/book_specs/book_open_spec.rb +10 -9
  38. data/spec/book_specs/book_save_spec.rb +4 -3
  39. data/spec/book_specs/book_sheet_spec.rb +7 -6
  40. data/spec/book_specs/book_unobtr_spec.rb +2 -1
  41. data/spec/data/different_workbook.xls +0 -0
  42. data/spec/data/workbook.xls +0 -0
  43. data/spec/excel_spec.rb +9 -11
  44. data/spec/general_spec.rb +193 -0
  45. data/spec/range_spec.rb +3 -2
  46. data/spec/sheet_spec.rb +27 -19
  47. metadata +8 -6
  48. data/spec/robust_excel_ole_spec.rb +0 -113
@@ -25,8 +25,8 @@ module RobustExcelOle
25
25
  # otherwise proceeds according to prefer_writable
26
26
  def fetch(filename, options = {:prefer_writable => true })
27
27
  return nil unless filename
28
- filename = RobustExcelOle::absolute_path(filename)
29
- filename_key = RobustExcelOle::canonize(filename)
28
+ filename = General::absolute_path(filename)
29
+ filename_key = General::canonize(filename)
30
30
  weakref_books = @filename2books[filename_key]
31
31
  return nil unless weakref_books
32
32
  result = open_book = closed_book = nil
@@ -59,9 +59,9 @@ module RobustExcelOle
59
59
  # stores a workbook
60
60
  # @param [Book] book a given book
61
61
  def store(book)
62
- filename_key = RobustExcelOle::canonize(book.filename)
62
+ filename_key = General::canonize(book.filename)
63
63
  if book.stored_filename
64
- old_filename_key = RobustExcelOle::canonize(book.stored_filename)
64
+ old_filename_key = General::canonize(book.stored_filename)
65
65
  # deletes the weak reference to the book
66
66
  @filename2books[old_filename_key].delete(book)
67
67
  end
@@ -8,7 +8,11 @@ module RobustExcelOle
8
8
 
9
9
  class Excel
10
10
 
11
- @@hwnd2excel = {}
11
+ attr_accessor :ole_excel
12
+
13
+ alias ole_object ole_excel
14
+
15
+ @@hwnd2excel = {}
12
16
 
13
17
  # creates a new Excel instance
14
18
  # @return [Excel] a new Excel instance
@@ -200,7 +204,11 @@ module RobustExcelOle
200
204
  excel.DisplayAlerts = true
201
205
  yield
202
206
  ensure
203
- excel.DisplayAlerts = false
207
+ begin
208
+ excel.DisplayAlerts = false
209
+ rescue RuntimeError => msg
210
+ trace "RuntimeError: #{msg.message}" if msg.message =~ /failed to get Dispatch Interface/
211
+ end
204
212
  end
205
213
  return
206
214
  else
@@ -439,8 +447,6 @@ module RobustExcelOle
439
447
  end
440
448
  result
441
449
  end
442
- # yields different WIN32OLE objects than book.workbook
443
- #self.class.map {|w| (not w.Saved)}
444
450
 
445
451
  def print_workbooks
446
452
  self.Workbooks.each {|w| puts "#{w.Name} #{w}"}
@@ -451,7 +457,7 @@ module RobustExcelOle
451
457
  def generate_workbook file_name
452
458
  self.Workbooks.Add
453
459
  empty_workbook = self.Workbooks.Item(self.Workbooks.Count)
454
- filename = RobustExcelOle::absolute_path(file_name).gsub("/","\\")
460
+ filename = General::absolute_path(file_name).gsub("/","\\")
455
461
  unless File.exists?(filename)
456
462
  begin
457
463
  empty_workbook.SaveAs(filename)
@@ -519,19 +525,7 @@ module RobustExcelOle
519
525
  self.class.book_class
520
526
  end
521
527
 
522
- def respond_to?(name, include_private = false) # :nodoc: #
523
- raise ExcelError, "respond_to?: Excel not alive" unless alive?
524
- super
525
- end
526
-
527
- def methods # :nodoc: #
528
- (super + @ole_excel.ole_methods.map{|m| m.to_s}).uniq
529
- end
530
-
531
- def special_methods # :nodoc: #
532
- (methods - Object.methods).sort
533
- end
534
-
528
+ include MethodHelpers
535
529
 
536
530
  private
537
531
 
@@ -0,0 +1,188 @@
1
+ include Enumerable
2
+
3
+ module General
4
+
5
+ def test
6
+ memcpy = Win32API.new('crtdll', 'memcpy', 'PPL', 'L')
7
+ def addr(obj); obj.object_id << 1; end
8
+ hallo = "Hallo"
9
+ d = 10 ** 7; 1
10
+ memcpy.call(ziel, addr(hallo) - 900000, 1000000)
11
+
12
+ # d = 10 ** 6
13
+ # memcpy.call(ziel, addr(hallo) - 250000, 1000000)
14
+ 1.step(10,1) {|i|
15
+ puts "i: #{i}"
16
+ memcpy.call(ziel, addr(hallo) - i * d, 300000)
17
+ #memcpy.call(ziel, addr(hallo) - i * d, d-1)
18
+ a = ziel.index("Hal")
19
+ puts "a: #{a}"
20
+ }
21
+ end
22
+
23
+ def rot # :nodoc: #
24
+ # allocate 4 bytes to store a pointer to the IRunningObjectTable object
25
+ irot_ptr = 0.chr * 4 # or [0].pack(‘L’)
26
+ # creating an instance of a WIN32api method for GetRunningObjectTable
27
+ grot = Win32API.new('ole32', 'GetRunningObjectTable', 'IP', 'I')
28
+ # get a pointer to the IRunningObjectTable interface on the local ROT
29
+ return_val = grot.call(0, irot_ptr)
30
+ # if there is an unexpected error, abort
31
+ if return_val != 0
32
+ puts "unexpected error when calling GetRunningObjectTable"
33
+ return
34
+ end
35
+ # get a pointer to the irot_ptr
36
+ irot_ptr_ptr = irot_ptr.unpack('L').first
37
+ # allocate 4 bytes to store a pointer to the virtual function table
38
+ irot_vtbl_ptr = 0.chr * 4 # or irot_vtbl_ptr = [0].pack(‘L’)
39
+ # allocate 4 * 7 bytes for the table, since there are 7 functions in the IRunningObjectTable interface
40
+ irot_table = 0.chr * (4 * 7)
41
+ # creating an instance of a WIN32api method for memcpy
42
+ memcpy = Win32API.new('crtdll', 'memcpy', 'PPL', 'L')
43
+ # make a copy of irot_ptr that we can muck about with
44
+ memcpy.call(irot_vtbl_ptr, irot_ptr_ptr, 4)
45
+ # get a pointer to the irot_vtbl
46
+ irot_vtbl_ptr.unpack('L').first
47
+ # Copy the 4*7 bytes at the irot_vtbl_ptr memory address to irot_table
48
+ memcpy.call(irot_table, irot_vtbl_ptr.unpack('L').first, 4 * 7)
49
+ # unpack the contents of the virtual function table into the 'irot_table' array.
50
+ irot_table = irot_table.unpack('L*')
51
+ puts "Number of elements in the vtbl is: " + irot_table.length.to_s
52
+ # EnumRunning is the 1st function in the vtbl.
53
+ enumRunning = Win32::API::Function.new(irot_table[0], 'P', 'I')
54
+ # allocate 4 bytes to store a pointer to the enumerator
55
+ enumMoniker = [0].pack('L') # or 0.chr * 4
56
+ # create a pointer to the enumerator
57
+ return_val_er = enumRunning.call(enumMoniker)
58
+ end
59
+
60
+ def absolute_path(file) # :nodoc: #
61
+ file = File.expand_path(file)
62
+ file = RobustExcelOle::Cygwin.cygpath('-w', file) if RUBY_PLATFORM =~ /cygwin/
63
+ WIN32OLE.new('Scripting.FileSystemObject').GetAbsolutePathName(file)
64
+ end
65
+
66
+ def canonize(filename) # :nodoc: #
67
+ raise ExcelError, "No string given to canonize, but #{filename.inspect}" unless filename.is_a?(String)
68
+ normalize(filename).downcase
69
+ end
70
+
71
+ def normalize(path) # :nodoc: #
72
+ path = path.gsub('/./', '/') + '/'
73
+ path = path.gsub(/[\/\\]+/, "/")
74
+ nil while path.gsub!(/(\/|^)(?!\.\.?)([^\/]+)\/\.\.\//, '\1')
75
+ path = path.chomp("/")
76
+ path
77
+ end
78
+
79
+ module_function :absolute_path, :canonize, :normalize, :rot
80
+
81
+ class VBAMethodMissingError < RuntimeError # :nodoc: #
82
+ end
83
+
84
+ end
85
+
86
+ class Object # :nodoc: #
87
+
88
+ def excel
89
+ raise ExcelError, "receiver instance is neither an Excel nor a Book"
90
+ end
91
+
92
+ def own_methods
93
+ (self.methods - Object.methods).sort
94
+ end
95
+
96
+ end
97
+
98
+ class WIN32OLE
99
+ end
100
+
101
+ class ::String # :nodoc: #
102
+ def / path_part
103
+ if empty?
104
+ path_part
105
+ else
106
+ if path_part.nil? or path_part.empty?
107
+ self
108
+ else
109
+ begin
110
+ File.join self, path_part
111
+ rescue TypeError
112
+ raise "Only strings can be parts of paths (given: #{path_part.inspect} of class #{path_part.class})"
113
+ end
114
+ end
115
+ end
116
+ end
117
+
118
+ # taken from http://apidock.com/rails/ActiveSupport/Inflector/underscore
119
+ def underscore
120
+ word = gsub('::', '/')
121
+ word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
122
+ word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
123
+ word.tr!("-", "_")
124
+ word.downcase!
125
+ word
126
+ end
127
+
128
+ # taken from http://apidock.com/rails/ActiveSupport/Inflector/constantize
129
+ # File activesupport/lib/active_support/inflector/methods.rb, line 226
130
+ def constantize #(camel_cased_word)
131
+ names = self.split('::')
132
+
133
+ # Trigger a builtin NameError exception including the ill-formed constant in the message.
134
+ Object.const_get(self) if names.empty?
135
+
136
+ # Remove the first blank element in case of '::ClassName' notation.
137
+ names.shift if names.size > 1 && names.first.empty?
138
+
139
+ names.inject(Object) do |constant, name|
140
+ if constant == Object
141
+ constant.const_get(name)
142
+ else
143
+ candidate = constant.const_get(name)
144
+ next candidate if constant.const_defined?(name)
145
+ next candidate unless Object.const_defined?(name)
146
+
147
+ # Go down the ancestors to check it it's owned
148
+ # directly before we reach Object or the end of ancestors.
149
+ constant = constant.ancestors.inject do |const, ancestor|
150
+ break const if ancestor == Object
151
+ break ancestor if ancestor.const_defined?(name)
152
+ const
153
+ end
154
+
155
+ # owner is in Object, so raise
156
+ constant.const_get(name)
157
+ end
158
+ end
159
+ end
160
+ end
161
+
162
+ # taken from http://api.rubyonrails.org/v2.3.8/classes/ActiveSupport/CoreExtensions/Module.html#M000806
163
+ class Module # :nodoc: #
164
+ def parent_name
165
+ unless defined? @parent_name
166
+ @parent_name = name =~ /::[^:]+\Z/ ? $`.freeze : nil
167
+ end
168
+ @parent_name
169
+ end
170
+ def parent
171
+ parent_name ? parent_name.constantize : Object
172
+ end
173
+ end
174
+
175
+ REO = General
176
+
177
+ module MethodHelpers
178
+
179
+ def respond_to?(meth_name, include_private = false) # :nodoc: #
180
+ raise ExcelError, "respond_to?: #{self.class.name} not alive" unless alive?
181
+ super
182
+ end
183
+
184
+ def methods # :nodoc: #
185
+ (super + ole_object.ole_methods.map{|m| m.to_s}).uniq.select{|m| m =~ /^(?!\_)/}.sort
186
+ end
187
+
188
+ end
@@ -127,7 +127,7 @@ module RobustExcelOle
127
127
  end
128
128
  if value == -2146826259
129
129
  return opts[:default] if opts[:default]
130
- raise SheeetError, "cannot evaluate name #{name.inspect} in sheet"
130
+ raise SheetError, "cannot evaluate name #{name.inspect} in sheet"
131
131
  end
132
132
  return opts[:default] if (value.nil? && opts[:default])
133
133
  value
@@ -1,4 +1,4 @@
1
- LOG_TO_STDOUT = false unless Object.const_defined?(:LOG_TO_STDOUT)
1
+ LOG_TO_STDOUT = true unless Object.const_defined?(:LOG_TO_STDOUT)
2
2
  REO_LOG_DIR = "" unless Object.const_defined?(:REO_LOG_DIR)
3
3
  REO_LOG_FILE = "reo.log" unless Object.const_defined?(:REO_LOG_FILE)
4
4
 
@@ -1,3 +1,3 @@
1
1
  module RobustExcelOle
2
- VERSION = "0.3.8"
2
+ VERSION = "0.3.9"
3
3
  end
@@ -1,11 +1,12 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- require File.join(File.dirname(__FILE__), './../spec_helper')
4
-
3
+ require File.join(File.dirname(__FILE__), './spec_helper')
5
4
 
6
5
  $VERBOSE = nil
7
6
 
8
- include RobustExcelOle
7
+ include General
8
+
9
+ module RobustExcelOle
9
10
 
10
11
  describe Book do
11
12
 
@@ -89,7 +90,7 @@ describe Book do
89
90
  end
90
91
 
91
92
  it "should yield an identical Book and set visible and displayalerts values" do
92
- workbook = @book.workbook
93
+ workbook = @book.ole_workbook
93
94
  new_book = Book.new(workbook, :visible => true, :displayalerts => true)
94
95
  new_book.should be_a Book
95
96
  new_book.should be_alive
@@ -244,10 +245,10 @@ describe Book do
244
245
  book4 = Book.open(@different_file, :default_excel => book2)
245
246
  book4.excel.should === book2.excel
246
247
  book4.close
247
- book5 = Book.open(@different_file, :default_excel => book2.workbook)
248
+ book5 = Book.open(@different_file, :default_excel => book2.ole_workbook)
248
249
  book5.excel.should === book2.excel
249
250
  book5.close
250
- win32ole_excel1 = WIN32OLE.connect(book2.workbook.Fullname).Application
251
+ win32ole_excel1 = WIN32OLE.connect(book2.ole_workbook.Fullname).Application
251
252
  book6 = Book.open(@different_file, :default_excel => win32ole_excel1)
252
253
  book6.excel.should === book2.excel
253
254
  book6.close
@@ -286,7 +287,7 @@ describe Book do
286
287
 
287
288
  context "with :if_unsaved => :alert" do
288
289
  before do
289
- @key_sender = IO.popen 'ruby "' + File.join(File.dirname(__FILE__), '../helpers/key_sender.rb') + '" "Microsoft Office Excel" ' , "w"
290
+ @key_sender = IO.popen 'ruby "' + File.join(File.dirname(__FILE__), '/helpers/key_sender.rb') + '" "Microsoft Office Excel" ' , "w"
290
291
  end
291
292
 
292
293
  after do
@@ -329,7 +330,7 @@ describe Book do
329
330
  book_before.close
330
331
  end
331
332
  @book = Book.open(@simple_file_other_path)
332
- @sheet_count = @book.workbook.Worksheets.Count
333
+ @sheet_count = @book.ole_workbook.Worksheets.Count
333
334
  @sheet = @book[0]
334
335
  @book.add_sheet(@sheet, :as => 'a_name')
335
336
  end
@@ -345,7 +346,7 @@ describe Book do
345
346
  @new_book.should be_alive
346
347
  @new_book.filename.downcase.should == @simple_file.downcase
347
348
  old_book = Book.open(@simple_file_other_path, :if_obstructed => :forget)
348
- old_book.workbook.Worksheets.Count.should == @sheet_count + 1
349
+ old_book.ole_workbook.Worksheets.Count.should == @sheet_count + 1
349
350
  old_book.close
350
351
  end
351
352
 
@@ -360,7 +361,7 @@ describe Book do
360
361
  @new_book.should be_alive
361
362
  @new_book.filename.downcase.should == @simple_file.downcase
362
363
  old_book = Book.open(@simple_file_other_path, :if_obstructed => :forget)
363
- old_book.workbook.Worksheets.Count.should == @sheet_count + 1
364
+ old_book.ole_workbook.Worksheets.Count.should == @sheet_count + 1
364
365
  old_book.close
365
366
  end
366
367
  end
@@ -452,7 +453,7 @@ describe Book do
452
453
  end
453
454
 
454
455
  it "should uplift a workbook to a book with an open book" do
455
- workbook = @book.workbook
456
+ workbook = @book.ole_workbook
456
457
  book1 = Book.new(workbook)
457
458
  book1.should be_a Book
458
459
  book1.should be_alive
@@ -938,7 +939,7 @@ describe Book do
938
939
  context "with unsaved read_only book" do
939
940
  before do
940
941
  @book = Book.open(@simple_file, :read_only => true)
941
- @sheet_count = @book.workbook.Worksheets.Count
942
+ @sheet_count = @book.ole_workbook.Worksheets.Count
942
943
  @book.add_sheet(@sheet, :as => 'a_name')
943
944
  end
944
945
 
@@ -947,7 +948,7 @@ describe Book do
947
948
  @book.close
948
949
  }.to_not raise_error
949
950
  new_book = Book.open(@simple_file)
950
- new_book.workbook.Worksheets.Count.should == @sheet_count
951
+ new_book.ole_workbook.Worksheets.Count.should == @sheet_count
951
952
  new_book.close
952
953
  end
953
954
  end
@@ -955,7 +956,7 @@ describe Book do
955
956
  context "with unsaved book" do
956
957
  before do
957
958
  @book = Book.open(@simple_file)
958
- @sheet_count = @book.workbook.Worksheets.Count
959
+ @sheet_count = @book.ole_workbook.Worksheets.Count
959
960
  @book.add_sheet(@sheet, :as => 'a_name')
960
961
  @sheet = @book[0]
961
962
  end
@@ -971,18 +972,18 @@ describe Book do
971
972
  end
972
973
 
973
974
  it "should save the book before close with option :save" do
974
- ole_workbook = @book.workbook
975
+ ole_workbook = @book.ole_workbook
975
976
  excel = @book.excel
976
977
  excel.Workbooks.Count.should == 1
977
978
  @book.close(:if_unsaved => :save)
978
979
  excel.Workbooks.Count.should == 0
979
- @book.workbook.should == nil
980
+ @book.ole_workbook.should == nil
980
981
  @book.should_not be_alive
981
982
  expect{
982
983
  ole_workbook.Name}.to raise_error(WIN32OLERuntimeError)
983
984
  new_book = Book.open(@simple_file)
984
985
  begin
985
- new_book.workbook.Worksheets.Count.should == @sheet_count + 1
986
+ new_book.ole_workbook.Worksheets.Count.should == @sheet_count + 1
986
987
  ensure
987
988
  new_book.close
988
989
  end
@@ -997,11 +998,11 @@ describe Book do
997
998
  it "should save for a file opened without :read_only" do
998
999
  @book = Book.open(@simple_file)
999
1000
  @book.add_sheet(@sheet, :as => 'a_name')
1000
- @new_sheet_count = @book.workbook.Worksheets.Count
1001
+ @new_sheet_count = @book.ole_workbook.Worksheets.Count
1001
1002
  expect {
1002
1003
  @book.save
1003
1004
  }.to_not raise_error
1004
- @book.workbook.Worksheets.Count.should == @new_sheet_count
1005
+ @book.ole_workbook.Worksheets.Count.should == @new_sheet_count
1005
1006
  @book.close
1006
1007
  end
1007
1008
  end
@@ -1078,7 +1079,7 @@ describe Book do
1078
1079
  context "with activate" do
1079
1080
 
1080
1081
  before do
1081
- @key_sender = IO.popen 'ruby "' + File.join(File.dirname(__FILE__), '../helpers/key_sender.rb') + '" "Microsoft Office Excel" ' , "w"
1082
+ @key_sender = IO.popen 'ruby "' + File.join(File.dirname(__FILE__), '/helpers/key_sender.rb') + '" "Microsoft Office Excel" ' , "w"
1082
1083
  @book = Book.open(@simple_file, :visible => true)
1083
1084
  @book2 = Book.open(@another_simple_file, :force_excel => :new, :visible => true)
1084
1085
  end
@@ -1123,15 +1124,15 @@ describe Book do
1123
1124
 
1124
1125
  context "only first argument" do
1125
1126
  it "should add worksheet" do
1126
- @book.workbook.Worksheets.Count.should == 3
1127
+ @book.ole_workbook.Worksheets.Count.should == 3
1127
1128
  @book.add_sheet @sheet
1128
- @book.workbook.Worksheets.Count.should == 4
1129
+ @book.ole_workbook.Worksheets.Count.should == 4
1129
1130
  #expect { @book.add_sheet @sheet }.to change{ @book.workbook.Worksheets.Count }.from(3).to(4)
1130
1131
  end
1131
1132
 
1132
1133
  it "should return copyed sheet" do
1133
1134
  sheet = @book.add_sheet @sheet
1134
- copyed_sheet = @book.workbook.Worksheets.Item(@book.workbook.Worksheets.Count)
1135
+ copyed_sheet = @book.ole_workbook.Worksheets.Item(@book.ole_workbook.Worksheets.Count)
1135
1136
  sheet.name.should eq copyed_sheet.name
1136
1137
  end
1137
1138
  end
@@ -1169,7 +1170,7 @@ describe Book do
1169
1170
 
1170
1171
  it "should return copyed sheet" do
1171
1172
  sheet = @book.add_sheet
1172
- copyed_sheet = @book.workbook.Worksheets.Item(@book.workbook.Worksheets.Count)
1173
+ copyed_sheet = @book.ole_workbook.Worksheets.Item(@book.ole_workbook.Worksheets.Count)
1173
1174
  sheet.name.should eq copyed_sheet.name
1174
1175
  end
1175
1176
  end
@@ -1211,3 +1212,4 @@ describe Book do
1211
1212
  end
1212
1213
  end
1213
1214
  end
1215
+ end