robust_excel_ole 0.6.1 → 0.6.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/Changelog CHANGED
@@ -2,6 +2,14 @@
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
4
 
5
+ ## [0.6.2] - 2016-04-11
6
+
7
+ ### Changed
8
+ - Excel#focus (was Excel#activate)
9
+ - Book#focus (was Book#activate)
10
+
11
+ ### Added
12
+
5
13
  ## [0.6.1] - 2016-04-09
6
14
 
7
15
  ### Changed
data/README.rdoc CHANGED
@@ -184,12 +184,11 @@ or
184
184
 
185
185
  book.set_nameval("name") = "value"
186
186
 
187
- === Activating a workbook.
187
+ === Bringing a workbook to the focus.
188
188
 
189
- Bring the window of a workbook to the foreground, make it available for keyboard inputs, and make the Excel instance visible.
190
-
191
- book.activate
189
+ Make the Excel instance and the workbook visible and make it available for keyboard inputs.
192
190
 
191
+ book.focus
193
192
 
194
193
  === Making the window of the workbook visible
195
194
 
@@ -419,6 +418,10 @@ Making all workbooks invisible.
419
418
 
420
419
  excel1.workbooks_visible false
421
420
 
421
+ === Bringing an Excel instance to the focus
422
+
423
+ Set the window of an Excel instance to the foreground.
424
+
422
425
  === Closing an Excel
423
426
 
424
427
  excel = Excel.current
data/README_detail.rdoc CHANGED
@@ -268,11 +268,11 @@ or
268
268
 
269
269
  book.set_nameval("name") = "value"
270
270
 
271
- === Activating a workbook.
271
+ === Bringing a workbook to the focus.
272
272
 
273
- Bring the focus to a workbook. Make it available for keyboard inputs and make the Excel instance visible.
273
+ Make the Excel instance and the workbook visible and make it available for keyboard inputs.
274
274
 
275
- book.activate
275
+ book.focus
276
276
 
277
277
  === Make the window of the workbook visible.
278
278
 
@@ -496,6 +496,10 @@ Enabling DisplayAlerts whenever the Excel instance is visible.
496
496
 
497
497
  excel3 = Excel.current(:reuse => true, :displayalerts => :if_visible)
498
498
 
499
+ === Bringing an Excel instance to the focus
500
+
501
+ Set the window of an Excel instance to the foreground.
502
+
499
503
  === Closing an Excel
500
504
 
501
505
  excel = Excel.current
data/lib/reo_console.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  #require 'lib/robust_excel_ole'
2
2
  include REO
3
- include RobustExcelOle
3
+ #include RobustExcelOle
4
4
  include General
5
5
 
6
6
  require 'irb/completion'
@@ -10,3 +10,4 @@ require File.join(File.dirname(__FILE__), 'robust_excel_ole/range')
10
10
  require File.join(File.dirname(__FILE__), 'robust_excel_ole/cygwin') if RUBY_PLATFORM =~ /cygwin/
11
11
  #+#require "robust_excel_ole/version"
12
12
  require File.join(File.dirname(__FILE__), 'robust_excel_ole/version')
13
+ #
@@ -20,7 +20,7 @@ module RobustExcelOle
20
20
  :if_obstructed => :raise,
21
21
  :if_absent => :raise,
22
22
  :read_only => false,
23
- :check_compatibility => true,
23
+ :check_compatibility => false,
24
24
  :update_links => :never
25
25
  }
26
26
 
@@ -92,7 +92,8 @@ module RobustExcelOle
92
92
  book.close if (book.alive? && (not book.writable) && (not options[:read_only]))
93
93
  # reopens the book
94
94
  book.ensure_workbook(file,options) unless book.alive?
95
- book.visible = options[:visible] unless options[:visible].nil?
95
+ book.visible = options[:visible].nil? ? book.excel.visible : options[:visible]
96
+ #book.visible = options[:visible] unless options[:visible].nil?
96
97
  return book
97
98
  end
98
99
  end
@@ -113,7 +114,8 @@ module RobustExcelOle
113
114
  if filename
114
115
  book = bookstore.fetch(filename)
115
116
  if book && book.alive?
116
- book.visible = opts[:visible] unless opts[:visible].nil?
117
+ #book.visible = opts[:visible] unless opts[:visible].nil?
118
+ book.visible = opts[:visible].nil? ? book.excel.visible : opts[:visible]
117
119
  return book
118
120
  end
119
121
  end
@@ -183,7 +185,8 @@ module RobustExcelOle
183
185
  filename = General::absolute_path(file)
184
186
  ole_workbook = WIN32OLE.connect(filename)
185
187
  workbook = Book.new(ole_workbook)
186
- workbook.visible = options[:visible] unless options[:visible].nil?
188
+ #workbook.visible = options[:visible] unless options[:visible].nil?
189
+ workbook.visible = options[:visible].nil? ? workbook.excel.visible : options[:visible]
187
190
  update_links_opt =
188
191
  case options[:update_links]
189
192
  when :alert; RobustExcelOle::XlUpdateLinksUserSetting
@@ -212,7 +215,7 @@ module RobustExcelOle
212
215
  if options[:if_absent] == :create
213
216
  @ole_workbook = excel_class.current.generate_workbook(file)
214
217
  else
215
- raise FileNotFound, "file #{file.inspect} not found"
218
+ raise FileNotFound, "file #{General::absolute_path(file).inspect} not found"
216
219
  end
217
220
  end
218
221
  @ole_workbook = @excel.Workbooks.Item(File.basename(file)) rescue nil
@@ -295,13 +298,13 @@ module RobustExcelOle
295
298
  raise UnexpectedError, "unknown RuntimeError"
296
299
  end
297
300
  rescue WeakRef::RefError => msg
298
- raise ExcelWeakRef, "#{msg.message}"
301
+ raise WeakRef::RefError, "#{msg.message}"
299
302
  end
300
303
  # workaround for linked workbooks for Excel 2007:
301
304
  # opening and closing a dummy workbook if Excel has no workbooks.
302
305
  # delay: with visible: 0.2 sec, without visible almost none
303
306
  count = workbooks.Count
304
- if @excel.Version == "12.0" && count == 0
307
+ if @excel.Version.split(".").first.to_i >= 12 && count == 0
305
308
  workbooks.Add
306
309
  #@excel.set_calculation(:automatic)
307
310
  end
@@ -318,7 +321,7 @@ module RobustExcelOle
318
321
  @excel.with_displayalerts(update_links_opt == :alert ? true : @excel.displayalerts) do
319
322
  workbooks.Open(filename, { 'ReadOnly' => options[:read_only] , 'UpdateLinks' => update_links_opt } )
320
323
  end
321
- workbooks.Item(1).Close if @excel.Version == "12.0" && count == 0
324
+ workbooks.Item(1).Close if @excel.Version.split(".").first.to_i >= 12 && count == 0
322
325
  rescue WIN32OLERuntimeError => msg
323
326
  # trace "WIN32OLERuntimeError: #{msg.message}"
324
327
  if msg.message =~ /800A03EC/
@@ -330,7 +333,8 @@ module RobustExcelOle
330
333
  begin
331
334
  # workaround for bug in Excel 2010: workbook.Open does not always return the workbook with given file name
332
335
  @ole_workbook = workbooks.Item(File.basename(filename))
333
- self.visible = options[:visible] unless options[:visible].nil?
336
+ self.visible = options[:visible].nil? ? @excel.visible : options[:visible]
337
+ #self.visible = options[:visible] unless options[:visible].nil?
334
338
  #@ole_workbook.UpdateLinks = update_links_opt
335
339
  @ole_workbook.CheckCompatibility = options[:check_compatibility]
336
340
  rescue WIN32OLERuntimeError
@@ -434,7 +438,7 @@ module RobustExcelOle
434
438
  :read_only => false,
435
439
  :readonly_excel => false,
436
440
  :keep_open => false,
437
- :check_compatibility => true
441
+ :check_compatibility => false
438
442
  }.merge(opts)
439
443
  book = bookstore.fetch(file, :prefer_writable => (not options[:read_only]))
440
444
  was_not_alive_or_nil = book.nil? || (not book.alive?)
@@ -467,7 +471,8 @@ module RobustExcelOle
467
471
  open(file, :force_excel => :new, :read_only => options[:read_only])
468
472
  end
469
473
  end
470
- book.excel.visible = options[:visible] unless options[:visible].nil?
474
+ #book.excel.visible = options[:visible] unless options[:visible].nil?
475
+ book.visible = options[:visible].nil? ? book.excel.visible : options[:visible]
471
476
  old_check_compatibility = book.CheckCompatibility
472
477
  book.CheckCompatibility = options[:check_compatibility]
473
478
  yield book
@@ -525,7 +530,7 @@ module RobustExcelOle
525
530
  # @return [Book], the book itself, if successfully saved, raises an exception otherwise
526
531
  def save_as(file, opts = { } )
527
532
  raise FileNameNotGiven, "filename is nil" if file.nil?
528
- raise ObjectNotAlive, "workbook is not alive" if (not alive?)
533
+ raise ObjectNotAlive, "workbook is not alive" unless alive?
529
534
  raise WorkbookReadOnly, "Not opened for writing (opened with :read_only option)" if @ole_workbook.ReadOnly
530
535
  options = {
531
536
  :if_exists => :raise,
@@ -777,15 +782,10 @@ module RobustExcelOle
777
782
  end
778
783
 
779
784
  # brings workbook to foreground, makes it available for heyboard inputs, makes the Excel instance visible
780
- def activate
781
- @excel.visible = true
782
- begin
783
- Win32API.new("user32","SetForegroundWindow","I","I").call # Excel 2010
784
- SetForegroundWindow.call(@excel.Hwnd)
785
- @ole_workbook.Activate # Excel 2007
786
- rescue WIN32OLERuntimeError => msg
787
- raise UnexpectedError, "cannot activate: #{message.msg}"
788
- end
785
+ def focus
786
+ self.visible = true
787
+ @excel.focus
788
+ @ole_workbook.Activate
789
789
  end
790
790
 
791
791
  # returns true, if the workbook is visible, false otherwise
@@ -798,7 +798,11 @@ module RobustExcelOle
798
798
  def visible= visible_value
799
799
  saved = @ole_workbook.Saved
800
800
  @excel.visible = true if visible_value
801
- @ole_workbook.Windows(@ole_workbook.Name).Visible = visible_value if @excel.Visible
801
+ if @excel.Visible
802
+ if @ole_workbook.Windows.Count > 0
803
+ @ole_workbook.Windows(@ole_workbook.Name).Visible = visible_value
804
+ end
805
+ end
802
806
  @ole_workbook.Saved = saved
803
807
  end
804
808
 
@@ -65,6 +65,8 @@ module RobustExcelOle
65
65
  if stored
66
66
  result = stored
67
67
  else
68
+ options[:visible] = options[:visible].nil? ? ole_xl.Visible : options[:visible]
69
+ options[:displayalerts] = options[:displayalerts].nil? ? :if_visible : options[:displayalerts]
68
70
  result = super(options)
69
71
  result.instance_variable_set(:@ole_excel, ole_xl)
70
72
  WIN32OLE.const_load(ole_xl, RobustExcelOle) unless RobustExcelOle.const_defined?(:CONSTANTS)
@@ -72,16 +74,19 @@ module RobustExcelOle
72
74
  end
73
75
 
74
76
  unless options.is_a? WIN32OLE
75
- reused = options[:reuse] && (not stored.nil?)
76
- options = { :displayalerts => :if_visible, :visible => false}.merge(options) unless reused
77
- result.visible = result.Visible
78
- result.DisplayAlerts = result.DisplayAlerts
79
- visible_value = (reused && options[:visible].nil?) ? result.visible : options[:visible]
80
- displayalerts_value = (reused && options[:displayalerts].nil?) ? result.displayalerts : options[:displayalerts]
81
- ole_xl.Visible = visible_value
82
- ole_xl.DisplayAlerts = (displayalerts_value == :if_visible) ? visible_value : displayalerts_value
83
- result.instance_variable_set(:@visible, visible_value)
84
- result.instance_variable_set(:@displayalerts, displayalerts_value)
77
+ begin
78
+ reused = options[:reuse] && (not stored.nil?)
79
+ options = { :displayalerts => :if_visible, :visible => false}.merge(options) unless reused
80
+ visible_value = (reused && options[:visible].nil?) ? result.Visible : options[:visible]
81
+ displayalerts_value = (reused && options[:displayalerts].nil?) ?
82
+ ((result.displayalerts == :if_visible) ? :if_visible : result.DisplayAlerts) : options[:displayalerts]
83
+ ole_xl.Visible = visible_value
84
+ ole_xl.DisplayAlerts = (displayalerts_value == :if_visible) ? visible_value : displayalerts_value
85
+ result.instance_variable_set(:@visible, visible_value)
86
+ result.instance_variable_set(:@displayalerts, displayalerts_value)
87
+ rescue WIN32OLERuntimeError
88
+ raise ExcelError, "cannot access Excel"
89
+ end
85
90
  end
86
91
  result
87
92
  end
@@ -156,6 +161,7 @@ module RobustExcelOle
156
161
  end
157
162
 
158
163
  # closes Excel instances opened via RobustExcelOle
164
+ # @return [Fixnum] number of closed Excel instances
159
165
  # @param [Hash] options the options
160
166
  # @option options [Symbol] :if_unsaved :raise, :save, :forget, or :alert
161
167
  # @option options [Boolean] :hard
@@ -175,15 +181,21 @@ module RobustExcelOle
175
181
  :kill_if_timeout => false
176
182
  }.merge(options)
177
183
  timeout = false
178
- number = excels_number
184
+ number = @@hwnd2excel.size
185
+ unsaved_workbooks = false
179
186
  begin
180
187
  status = Timeout::timeout(60) {
181
188
  @@hwnd2excel.each do |hwnd, wr_excel|
182
189
  excel = wr_excel.__getobj__
183
- excel.close(options)
190
+ begin
191
+ excel.close(options)
192
+ rescue UnsavedWorkbooks
193
+ unsaved_workbooks = true
194
+ end
195
+ sleep 0.2
184
196
  end
185
- sleep 0.2
186
- free_all_ole_objects if excels_number > 0
197
+ raise UnsavedWorkbooks, "Excel contains unsaved workbooks" if unsaved_workbooks
198
+ free_all_ole_objects if excels_number > 0 #&& (not unsaved_workbooks)
187
199
  # close also interactively opened Excels, but for unsaved workbooks: hangs as soon sending a VBA method
188
200
  #while (n = excels_number) > 0 do
189
201
  # ole_xl = current_excel
@@ -416,11 +428,12 @@ module RobustExcelOle
416
428
  end
417
429
 
418
430
  def print_workbooks
419
- self.Workbooks.each {|w| puts "#{w.Name} #{w}"}
431
+ self.Workbooks.each {|w| trace "#{w.Name} #{w}"}
420
432
  end
421
433
 
422
434
  # generates, saves, and closes empty workbook
423
- def generate_workbook file_name
435
+ def generate_workbook file_name
436
+ raise FileNameNotGiven, "filename is nil" if file_name.nil?
424
437
  self.Workbooks.Add
425
438
  empty_workbook = self.Workbooks.Item(self.Workbooks.Count)
426
439
  filename = General::absolute_path(file_name).gsub("/","\\")
@@ -429,7 +442,7 @@ module RobustExcelOle
429
442
  empty_workbook.SaveAs(filename)
430
443
  rescue WIN32OLERuntimeError => msg
431
444
  if msg.message =~ /SaveAs/ and msg.message =~ /Workbook/ then
432
- raise WIN32OLERuntimeError, "could not save workbook with filename #{file_name.inspect}"
445
+ raise FileNotFound, "could not save workbook with filename #{file_name.inspect}"
433
446
  else
434
447
  # todo some time: find out when this occurs :
435
448
  raise UnexpectedError, "unknown WIN32OELERuntimeError with filename #{file_name.inspect}: \n#{msg.message}"
@@ -475,10 +488,13 @@ module RobustExcelOle
475
488
  end
476
489
  end
477
490
 
478
-
479
- def foremost_window
491
+ def focus
480
492
  self.visible = true
481
- #Win32API.new("user32","SetForegroundWindow","I","I").call(@ole_excel.Hwnd)
493
+ #if not Windows10 then
494
+ Win32API.new("user32","SetForegroundWindow","I","I").call(@ole_excel.Hwnd)
495
+ #else
496
+ #Win32API.new("user32","SetForegroundWindow","","I").call
497
+ #end
482
498
  end
483
499
 
484
500
  # sets calculation mode in a block
@@ -587,10 +603,11 @@ module RobustExcelOle
587
603
  raise RangeNotEvaluatable, "cannot determine value of range named #{name.inspect}"
588
604
  end
589
605
  return opts[:default] if (value.nil? && opts[:default])
606
+ raise RangeNotEvaluatable, "cannot evaluate range named #{name.inspect}" if value == -2146826259
590
607
  value
591
608
  end
592
609
 
593
- # assigns a value to a range given a defined loval name
610
+ # assigns a value to a range given a defined local name
594
611
  # @param [String] name the range name
595
612
  # @param [Variant] value the assigned value
596
613
  def set_rangeval(name,value)
@@ -118,4 +118,5 @@ module MethodHelpers
118
118
 
119
119
  end
120
120
 
121
- REO = General
121
+ #REO = General
122
+ REO = RobustExcelOle
@@ -63,9 +63,6 @@ module RobustExcelOle
63
63
  class ExcelDamaged < ExcelError # :nodoc: #
64
64
  end
65
65
 
66
- class ExcelWeakRef < ExcelError # :nodoc: #
67
- end
68
-
69
66
  class UnsavedWorkbooks < ExcelError # :nodoc: #
70
67
  end
71
68
 
@@ -1,3 +1,3 @@
1
1
  module RobustExcelOle
2
- VERSION = "0.6.1"
2
+ VERSION = "0.6.2"
3
3
  end
data/spec/book_spec.rb CHANGED
@@ -33,7 +33,7 @@ describe Book do
33
33
 
34
34
  after do
35
35
  Excel.kill_all
36
- rm_tmp(@dir)
36
+ #rm_tmp(@dir)
37
37
  end
38
38
 
39
39
  describe "create file" do
@@ -381,7 +381,7 @@ describe Book do
381
381
  if :if_obstructed is :close_if_saved" do
382
382
  expect{
383
383
  @new_book = Book.open(@simple_file1, :if_obstructed => :close_if_saved)
384
- }.to raise_error(WorkbookNotSaved, /workbook with the same name in a different path is unsaved/)
384
+ }.to raise_error(WorkbookBlocked, /workbook with the same name in a different path is unsaved/)
385
385
  @book.save
386
386
  @new_book = Book.open(@simple_file1, :if_obstructed => :close_if_saved)
387
387
  @book.should_not be_alive
@@ -409,7 +409,7 @@ describe Book do
409
409
  File.delete @simple_save_file rescue nil
410
410
  expect {
411
411
  Book.open(@simple_save_file)
412
- }.to raise_error(NameNotFound, /file "#{@simple_save_file}" not found/)
412
+ }.to raise_error(FileNotFound, "file #{General::absolute_path(@simple_save_file).gsub("/","\\").inspect} not found")
413
413
  end
414
414
  end
415
415
 
@@ -901,7 +901,7 @@ describe Book do
901
901
  book.excel.should_not == @book.excel
902
902
  book.excel.should_not == new_excel
903
903
  book.excel.visible.should be_false
904
- book.excel.displayalerts.should be_false
904
+ book.excel.displayalerts.should == :if_visible
905
905
  end
906
906
  new_book = Book.open(@simple_file1, :visible => true)
907
907
  sheet = new_book.sheet(1)
@@ -1077,7 +1077,7 @@ describe Book do
1077
1077
  end
1078
1078
  end
1079
1079
 
1080
- describe "alive?, filename, ==, activate, saved" do
1080
+ describe "alive?, filename, ==, focus, saved" do
1081
1081
 
1082
1082
  context "with alive?" do
1083
1083
 
@@ -1133,12 +1133,12 @@ describe Book do
1133
1133
  end
1134
1134
  end
1135
1135
 
1136
- context "with activate" do
1136
+ context "with focus" do
1137
1137
 
1138
1138
  before do
1139
1139
  @key_sender = IO.popen 'ruby "' + File.join(File.dirname(__FILE__), '/helpers/key_sender.rb') + '" "Microsoft Office Excel" ' , "w"
1140
1140
  @book = Book.open(@simple_file, :visible => true)
1141
- @book2 = Book.open(@another_simple_file, :force_excel => :new, :visible => true)
1141
+ @book2 = Book.open(@another_simple_file, :visible => true)
1142
1142
  end
1143
1143
 
1144
1144
  after do
@@ -1147,22 +1147,22 @@ describe Book do
1147
1147
  @key_sender.close
1148
1148
  end
1149
1149
 
1150
- it "should activate a book" do
1150
+ it "should bring a book to focus" do
1151
1151
  sheet = @book.sheet(2)
1152
1152
  sheet.Activate
1153
1153
  sheet[2,3].Activate
1154
1154
  sheet2 = @book2.sheet(2)
1155
1155
  sheet2.Activate
1156
1156
  sheet2[3,2].Activate
1157
- Excel.current.should == @book.excel
1158
- @book2.activate
1157
+ @book2.focus
1159
1158
  @key_sender.puts "{a}{enter}"
1160
- sleep 1
1159
+ sleep 0.2
1161
1160
  sheet2[3,2].Value.should == "a"
1162
- #Excel.current.should == @book2.excel
1163
- @book.activate
1161
+ @book.focus
1162
+ @book.Windows(1).Visible.should be_true
1163
+ @book.Windows(@book.Name).Visible.should be_true
1164
1164
  @key_sender.puts "{a}{enter}"
1165
- sleep 1
1165
+ sleep 0.2
1166
1166
  sheet[2,3].Value.should == "a"
1167
1167
  Excel.current.should == @book.excel
1168
1168
  end
@@ -1198,7 +1198,8 @@ describe Book do
1198
1198
 
1199
1199
  context "with second argument is {:before => @book.sheet(3), :after => @sheet}" do
1200
1200
  it "should arguments in the first is given priority" do
1201
- @book.add_sheet(@sheet, :before => @book.sheet(3), :after => @sheet).name.should eq @book.sheet(3).name
1201
+ @book.add_sheet(@sheet, :before => @book.sheet(3), :after => @sheet)
1202
+ @book.Worksheets.Count.should == 4
1202
1203
  end
1203
1204
  end
1204
1205
  end