robust_excel_ole 0.4 → 0.5
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/.gitignore +1 -0
- data/Changelog +15 -0
- data/README.rdoc +128 -63
- data/README_detail.rdoc +130 -60
- data/examples/edit_sheets/example_access_sheets_and_cells.rb +1 -1
- data/examples/edit_sheets/example_adding_sheets.rb +2 -2
- data/examples/edit_sheets/example_copying.rb +1 -1
- data/examples/edit_sheets/example_expanding.rb +1 -1
- data/examples/edit_sheets/example_ranges.rb +1 -1
- data/examples/edit_sheets/example_saving.rb +2 -2
- data/examples/open_save_close/example_control_to_excel.rb +1 -1
- data/examples/open_save_close/example_if_obstructed_closeifsaved.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 +2 -2
- data/examples/open_save_close/example_if_unsaved_forget_more.rb +3 -3
- data/examples/open_save_close/example_read_only.rb +1 -1
- data/examples/open_save_close/example_rename_cells.rb +1 -1
- data/examples/open_save_close/example_simple.rb +1 -1
- data/examples/open_save_close/example_unobtrusively.rb +3 -3
- data/lib/robust_excel_ole.rb +1 -0
- data/lib/robust_excel_ole/book.rb +249 -193
- data/lib/robust_excel_ole/bookstore.rb +1 -1
- data/lib/robust_excel_ole/cell.rb +1 -1
- data/lib/robust_excel_ole/excel.rb +125 -4
- data/lib/robust_excel_ole/general.rb +1 -92
- data/lib/robust_excel_ole/range.rb +1 -1
- data/lib/robust_excel_ole/reo_common.rb +37 -0
- data/lib/robust_excel_ole/sheet.rb +77 -24
- data/lib/robust_excel_ole/version.rb +1 -1
- data/spec/book_spec.rb +112 -82
- data/spec/book_specs/book_close_spec.rb +44 -1
- data/spec/book_specs/book_misc_spec.rb +97 -92
- data/spec/book_specs/book_open_spec.rb +40 -8
- data/spec/book_specs/book_save_spec.rb +77 -7
- data/spec/book_specs/book_sheet_spec.rb +290 -66
- data/spec/book_specs/book_unobtr_spec.rb +99 -73
- data/spec/bookstore_spec.rb +1 -1
- data/spec/cell_spec.rb +2 -2
- data/spec/data/another_workbook.xls +0 -0
- data/spec/data/workbook.xls +0 -0
- data/spec/excel_spec.rb +174 -23
- data/spec/general_spec.rb +3 -18
- data/spec/range_spec.rb +3 -3
- data/spec/reo_common_spec.rb +104 -0
- data/spec/sheet_spec.rb +101 -60
- metadata +6 -4
| @@ -14,7 +14,7 @@ begin | |
| 14 14 | 
             
              simple_save_file = dir + 'workbook_save.xls'
         | 
| 15 15 | 
             
              File.delete simple_save_file rescue nil
         | 
| 16 16 | 
             
              book = Book.open(simple_file)      # open a book
         | 
| 17 | 
            -
              sheet = book | 
| 17 | 
            +
              sheet = book.sheet(1)                    # access a sheet via integer 
         | 
| 18 18 | 
             
              cell = sheet[1,1]                  # access the first cell
         | 
| 19 19 | 
             
              puts "1st cell: #{cell.Value}"     # put the value of the first cell
         | 
| 20 20 | 
             
              sheet[1,1] = "complex"             # write a value into a cell
         | 
| @@ -33,7 +33,7 @@ begin | |
| 33 33 | 
             
              show_sheets
         | 
| 34 34 |  | 
| 35 35 | 
             
              puts "adding a copy of the 2nd sheet"
         | 
| 36 | 
            -
              sheet = @book | 
| 36 | 
            +
              sheet = @book.sheet(2)
         | 
| 37 37 | 
             
              @book.add_sheet sheet
         | 
| 38 38 | 
             
              show_sheets
         | 
| 39 39 |  | 
| @@ -50,7 +50,7 @@ begin | |
| 50 50 | 
             
              show_sheets
         | 
| 51 51 |  | 
| 52 52 | 
             
              puts "adding a copy of the 4th sheet before the 7th sheet and name it 'sheet_copy'"
         | 
| 53 | 
            -
              @book.add_sheet(@book | 
| 53 | 
            +
              @book.add_sheet(@book.sheet(4), :as => 'sheet_copy', :after => @book.sheet(7))
         | 
| 54 54 | 
             
              show_sheets
         | 
| 55 55 |  | 
| 56 56 | 
             
              puts"adding a copy of the 2nd sheet and name it again 'second_sheet_copy'"
         | 
| @@ -14,7 +14,7 @@ begin | |
| 14 14 | 
             
              simple_save_file = dir + 'workbook_save.xls'
         | 
| 15 15 | 
             
              File.delete simple_save_file rescue nil
         | 
| 16 16 | 
             
              book = Book.open(simple_file)      # open a book
         | 
| 17 | 
            -
              sheet = book | 
| 17 | 
            +
              sheet = book.sheet('Sheet1')             # access a sheet via the name
         | 
| 18 18 | 
             
              row_r = sheet.row_range(1)         # access the whole range of the first row
         | 
| 19 19 | 
             
              col_r = sheet.col_range(1, 1..2)   # access the first two cells of the range of the first column
         | 
| 20 20 | 
             
              cell = col_r[0]                    # access the first cell of these cells 
         | 
| @@ -25,13 +25,13 @@ begin | |
| 25 25 | 
             
                  book = Book.open(file_sheet_name)
         | 
| 26 26 | 
             
                  book.add_sheet sheet_orig
         | 
| 27 27 | 
             
                  book.each do |sheet|
         | 
| 28 | 
            -
                    sheet.Delete | 
| 28 | 
            +
                    sheet.Delete unless sheet.name == sheet_orig.name 
         | 
| 29 29 | 
             
                  end
         | 
| 30 30 | 
             
                  book.close(:if_unsaved => :save)
         | 
| 31 31 | 
             
                  # alternative: delete all other sheets
         | 
| 32 32 | 
             
                  #book = Book.open(file_sheet_name, :force_excel => :new, :visible => true)
         | 
| 33 33 | 
             
                  #book.each do |sheet|
         | 
| 34 | 
            -
                  #  book | 
| 34 | 
            +
                  #  book.sheet(sheet.Name).Delete() unless sheet.Name == sheet_orig.Name
         | 
| 35 35 | 
             
                  #end
         | 
| 36 36 | 
             
                end
         | 
| 37 37 | 
             
              end
         | 
| @@ -14,7 +14,7 @@ begin | |
| 14 14 | 
             
              book = Book.open(file_name)          # open a book
         | 
| 15 15 | 
             
              book.excel.visible = true                   # make current Excel visible 
         | 
| 16 16 | 
             
              sleep 1
         | 
| 17 | 
            -
              sheet = book | 
| 17 | 
            +
              sheet = book.sheet(1)                                                        # access a sheet
         | 
| 18 18 | 
             
              sheet[1,1] = sheet[1,1].Value == "simple" ? "complex" : "simple"       # change a cell
         | 
| 19 19 | 
             
              sleep 1
         | 
| 20 20 | 
             
              begin
         | 
| @@ -14,7 +14,7 @@ begin | |
| 14 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 | 
            -
              sheet = book | 
| 17 | 
            +
              sheet = book.sheet(1)
         | 
| 18 18 | 
             
              first_cell = sheet[1,1].Value                                   # access a sheet
         | 
| 19 19 | 
             
              sheet[1,1] = first_cell == "simple" ? "complex" : "simple"      # change a cell
         | 
| 20 20 | 
             
              sleep 1
         | 
| @@ -26,7 +26,7 @@ begin | |
| 26 26 | 
             
              book.save                                                           # save the unsaved book
         | 
| 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 | 
            -
              new_sheet = new_book | 
| 29 | 
            +
              new_sheet = new_book.sheet(1)
         | 
| 30 30 | 
             
              new_first_cell = new_sheet[1,1].Value
         | 
| 31 31 | 
             
              puts "the old book was saved" unless new_first_cell == first_cell 
         | 
| 32 32 | 
             
              new_book.close                                 # close the books                  
         | 
| @@ -14,7 +14,7 @@ begin | |
| 14 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 | 
            -
              sheet = book | 
| 17 | 
            +
              sheet = book.sheet(1)
         | 
| 18 18 | 
             
              first_cell = sheet[1,1].value                                   # access a sheet
         | 
| 19 19 | 
             
              sheet[1,1] = first_cell == "simple" ? "complex" : "simple"      # change a cell
         | 
| 20 20 | 
             
              sleep 1
         | 
| @@ -22,7 +22,7 @@ begin | |
| 22 22 | 
             
              sleep 1                                                         #save the old book, close it, before
         | 
| 23 23 | 
             
              old_book = Book.open(file_name, :if_obstructed => :forget ,:visible => true) # open the old book    
         | 
| 24 24 | 
             
              sleep 1
         | 
| 25 | 
            -
              old_sheet = old_book | 
| 25 | 
            +
              old_sheet = old_book.sheet(1)
         | 
| 26 26 | 
             
              old_first_cell = old_sheet[1,1].value
         | 
| 27 27 | 
             
              puts "the old book was saved" unless old_first_cell == first_cell 
         | 
| 28 28 | 
             
              new_book.close                                 # close the books                      
         | 
| @@ -12,7 +12,7 @@ begin | |
| 12 12 | 
             
              dir = create_tmpdir
         | 
| 13 13 | 
             
              file_name = dir + 'workbook.xls' 
         | 
| 14 14 | 
             
              book = Book.open(file_name)                      # open a book 
         | 
| 15 | 
            -
              sheet = book | 
| 15 | 
            +
              sheet = book.sheet(1)                                                  # access a sheet
         | 
| 16 16 | 
             
              sheet[1,1] = sheet[1,1].value == "simple" ? "complex" : "simple" # change a cell
         | 
| 17 17 | 
             
              begin
         | 
| 18 18 | 
             
                new_book = Book.open(file_name)                # open another book with the same file name
         | 
| @@ -14,13 +14,13 @@ begin | |
| 14 14 | 
             
              book = Book.open(file_name)                      # open a book
         | 
| 15 15 | 
             
              book.excel.visible = true                        # make current Excel visible 
         | 
| 16 16 | 
             
              sleep 1
         | 
| 17 | 
            -
              sheet = book | 
| 17 | 
            +
              sheet = book.sheet(1)                                            # access a sheet
         | 
| 18 18 | 
             
              first_cell = sheet[1,1].value
         | 
| 19 19 | 
             
              sheet[1,1] = first_cell == "simple" ? "complex" : "simple" # change a cell
         | 
| 20 20 | 
             
              sleep 1
         | 
| 21 21 | 
             
              new_book = Book.open(file_name, :if_unsaved => :forget) # open another book with the same file name 
         | 
| 22 22 | 
             
                                                                      # and close the unsaved book without saving it
         | 
| 23 | 
            -
              sheet_new_book = new_book | 
| 23 | 
            +
              sheet_new_book = new_book.sheet(1)
         | 
| 24 24 | 
             
              if (not book.alive?) && new_book.alive? && sheet_new_book[1,1].value == first_cell then # check whether the unsaved book 
         | 
| 25 25 | 
             
                puts "open with :if_unsaved => :forget : the unsaved book is closed and not saved."     # is closed and was not saved
         | 
| 26 26 | 
             
              end
         | 
| @@ -14,12 +14,12 @@ begin | |
| 14 14 | 
             
              book = Book.open(file_name)                      # open a book
         | 
| 15 15 | 
             
              book.excel.visible = true                        # make current Excel visible 
         | 
| 16 16 | 
             
              sleep
         | 
| 17 | 
            -
              sheet = book | 
| 17 | 
            +
              sheet = book.sheet(1)                                            # access a sheet
         | 
| 18 18 | 
             
              first_cell = sheet[1,1].value
         | 
| 19 19 | 
             
              sheet[1,1] = first_cell == "simple" ? "complex" : "simple" # change a cell
         | 
| 20 20 | 
             
              sleep 1
         | 
| 21 21 | 
             
              new_book = Book.open(file_name, :if_unsaved => :new_excel, :visible => true) # open another book with the same file name in a new Excel
         | 
| 22 | 
            -
              sheet_new_book = new_book | 
| 22 | 
            +
              sheet_new_book = new_book.sheet(1)
         | 
| 23 23 | 
             
              if (not book.alive?) && new_book.alive? && sheet_new_book[1,1].value == first_cell then # check whether the unsaved book 
         | 
| 24 24 | 
             
                puts "open with :if_unsaved => :forget : the unsaved book is closed and not saved."     # is closed and was not saved
         | 
| 25 25 | 
             
              end
         | 
| @@ -28,7 +28,7 @@ begin | |
| 28 28 | 
             
              # open another book in the running Excel application, and make Excel visible, closing the unsaved book
         | 
| 29 29 | 
             
              another_book = Book.open(file_name, :if_unsaved => :forget, :visible => true)  
         | 
| 30 30 | 
             
              sleep 1
         | 
| 31 | 
            -
              sheet_another_book = another_book | 
| 31 | 
            +
              sheet_another_book = another_book.sheet(1)
         | 
| 32 32 | 
             
              sheet_another_book[1,1] = sheet_another_book[1,1].value == "simple" ? "complex" : "simple" # change a cell                                                                   
         | 
| 33 33 | 
             
              another_book.close(:if_unsaved => :forget )           # close the last book without saving it.                      
         | 
| 34 34 | 
             
              book.close(:if_unsaved => :save)                      # close the first book and save it before
         | 
| @@ -12,7 +12,7 @@ begin | |
| 12 12 | 
             
              file_name = dir + 'workbook.xls'
         | 
| 13 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 | 
            -
              sheet = book | 
| 15 | 
            +
              sheet = book.sheet(1)                                     			        # access a sheet
         | 
| 16 16 | 
             
              sleep 1     
         | 
| 17 17 | 
             
              sheet[1,1] = sheet[1,1].value == "simple" ? "complex" : "simple" # change a cell
         | 
| 18 18 | 
             
              sleep 1
         | 
| @@ -13,7 +13,7 @@ begin | |
| 13 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 | 
            -
              sheet = book | 
| 16 | 
            +
              sheet = book.sheet(1)
         | 
| 17 17 | 
             
              workbook = book.ole_workbook
         | 
| 18 18 | 
             
              fullname = workbook.Fullname
         | 
| 19 19 | 
             
              puts "fullname: #{fullname}"  
         | 
| @@ -19,7 +19,7 @@ begin | |
| 19 19 | 
             
              other_file_name = dir + 'different_workbook.xls'
         | 
| 20 20 | 
             
              book = Book.open(file_name)                                # open a book.  default:  :read_only => false
         | 
| 21 21 | 
             
              book.excel.visible = true                                  # make current Excel visible
         | 
| 22 | 
            -
              sheet = book | 
| 22 | 
            +
              sheet = book.sheet(1)                                            # access a sheet
         | 
| 23 23 | 
             
              sleep 1     
         | 
| 24 24 | 
             
              sheet[1,1] = sheet[1,1].value == "simple" ? "complex" : "simple"  # change a cell
         | 
| 25 25 | 
             
              sleep 1
         | 
| @@ -11,14 +11,14 @@ begin | |
| 11 11 | 
             
              dir = create_tmpdir
         | 
| 12 12 | 
             
              simple_file = dir + 'workbook.xls'
         | 
| 13 13 | 
             
              book = Book.open(simple_file, :visible => true)  # open a book, make Excel visible
         | 
| 14 | 
            -
              old_sheet = book | 
| 14 | 
            +
              old_sheet = book.sheet(1)
         | 
| 15 15 | 
             
              p "1st cell: #{old_sheet[1,1].value}"
         | 
| 16 16 | 
             
              sleep 2
         | 
| 17 17 | 
             
              Book.unobtrusively(simple_file) do |book|   # modify the book and keep its status unchanged
         | 
| 18 | 
            -
                sheet = book | 
| 18 | 
            +
                sheet = book.sheet(1)
         | 
| 19 19 | 
             
                sheet[1,1] = sheet[1,1].value == "simple" ? "complex" : "simple"
         | 
| 20 20 | 
             
              end
         | 
| 21 | 
            -
              new_sheet = book | 
| 21 | 
            +
              new_sheet = book.sheet(1)
         | 
| 22 22 | 
             
              p "1st cell: #{new_sheet[1,1].value}"
         | 
| 23 23 | 
             
              p "book saved" if book.Saved
         | 
| 24 24 | 
             
              book.close                                 # close the book                      
         | 
    
        data/lib/robust_excel_ole.rb
    CHANGED
    
    | @@ -1,4 +1,5 @@ | |
| 1 1 | 
             
            require "win32ole"
         | 
| 2 | 
            +
            require File.join(File.dirname(__FILE__), 'robust_excel_ole/reo_common')
         | 
| 2 3 | 
             
            require File.join(File.dirname(__FILE__), 'robust_excel_ole/general')
         | 
| 3 4 | 
             
            require File.join(File.dirname(__FILE__), 'robust_excel_ole/excel')
         | 
| 4 5 | 
             
            require File.join(File.dirname(__FILE__), 'robust_excel_ole/bookstore')
         | 
| @@ -4,7 +4,7 @@ require 'weakref' | |
| 4 4 |  | 
| 5 5 | 
             
            module RobustExcelOle
         | 
| 6 6 |  | 
| 7 | 
            -
              class Book
         | 
| 7 | 
            +
              class Book < REOCommon
         | 
| 8 8 |  | 
| 9 9 | 
             
                attr_accessor :excel
         | 
| 10 10 | 
             
                attr_accessor :ole_workbook
         | 
| @@ -21,7 +21,8 @@ module RobustExcelOle | |
| 21 21 | 
             
                    :if_unsaved    => :raise,
         | 
| 22 22 | 
             
                    :if_obstructed => :raise,
         | 
| 23 23 | 
             
                    :if_absent     => :raise,
         | 
| 24 | 
            -
                    :read_only => false
         | 
| 24 | 
            +
                    :read_only => false,
         | 
| 25 | 
            +
                    :check_compatibility => true
         | 
| 25 26 | 
             
                  }
         | 
| 26 27 |  | 
| 27 28 | 
             
                class << self
         | 
| @@ -31,7 +32,7 @@ module RobustExcelOle | |
| 31 32 | 
             
                  # @param [Hash] opts the options
         | 
| 32 33 | 
             
                  # @option opts [Variant] :default_excel  :reuse (default), :new, or <excel-instance>     
         | 
| 33 34 | 
             
                  # @option opts [Variant] :force_excel    :new (default), or <excel-instance>
         | 
| 34 | 
            -
                  # @option opts [Symbol]  :if_unsaved     :raise (default), :forget, :accept, :alert, or :new_excel
         | 
| 35 | 
            +
                  # @option opts [Symbol]  :if_unsaved     :raise (default), :forget, :accept, :alert, :excel, or :new_excel
         | 
| 35 36 | 
             
                  # @option opts [Symbol]  :if_obstructed  :raise (default), :forget, :save, :close_if_saved, or _new_excel
         | 
| 36 37 | 
             
                  # @option opts [Symbol]  :if_absent      :raise (default), or :create
         | 
| 37 38 | 
             
                  # @option opts [Boolean] :read_only      true (default), or false
         | 
| @@ -52,7 +53,7 @@ module RobustExcelOle | |
| 52 53 | 
             
                  #                  :raise               -> raises an exception
         | 
| 53 54 | 
             
                  #                  :forget              -> close the unsaved workbook, open the new workbook             
         | 
| 54 55 | 
             
                  #                  :accept              -> lets the unsaved workbook open                  
         | 
| 55 | 
            -
                  #                  :alert | 
| 56 | 
            +
                  #                  :alert or :excel     -> gives control to Excel
         | 
| 56 57 | 
             
                  #                  :new_excel           -> opens the new workbook in a new Excel instance
         | 
| 57 58 | 
             
                  # :if_obstructed  if a workbook with the same name in a different path is open, then
         | 
| 58 59 | 
             
                  #                  :raise               -> raises an exception 
         | 
| @@ -66,7 +67,8 @@ module RobustExcelOle | |
| 66 67 | 
             
                  #                  
         | 
| 67 68 | 
             
                  # :read_only     opens in read-only mode         
         | 
| 68 69 | 
             
                  # :displayalerts enables DisplayAlerts in Excel  
         | 
| 69 | 
            -
                  # :visible       makes visible in Excel | 
| 70 | 
            +
                  # :visible       makes visible in Excel        
         | 
| 71 | 
            +
                  # :check_compatibility  check compatibility when saving
         | 
| 70 72 | 
             
                  # if :default_excel is set, then DisplayAlerts and Visible are set only if these parameters are given
         | 
| 71 73 | 
             
                  # @return [Book] a workbook
         | 
| 72 74 | 
             
                  def open(file, opts={ }, &block)
         | 
| @@ -114,7 +116,7 @@ module RobustExcelOle | |
| 114 116 | 
             
                end
         | 
| 115 117 |  | 
| 116 118 | 
             
                # creates a new Book object, if a file name is given
         | 
| 117 | 
            -
                #  | 
| 119 | 
            +
                # Promotes the workbook to a Book object, if a win32ole-workbook is given    
         | 
| 118 120 | 
             
                # @param [Variant] file_or_workbook  file name or workbook
         | 
| 119 121 | 
             
                # @param [Hash]    opts              the options
         | 
| 120 122 | 
             
                # @option opts [Symbol] see above
         | 
| @@ -165,7 +167,11 @@ module RobustExcelOle | |
| 165 167 | 
             
                      object.excel
         | 
| 166 168 | 
             
                    end
         | 
| 167 169 | 
             
                  else
         | 
| 168 | 
            -
                     | 
| 170 | 
            +
                    begin
         | 
| 171 | 
            +
                      object.excel
         | 
| 172 | 
            +
                    rescue
         | 
| 173 | 
            +
                      raise ExcelErrorOpen, "given object is neither an Excel, a Book, nor a Win32ole"
         | 
| 174 | 
            +
                    end
         | 
| 169 175 | 
             
                  end
         | 
| 170 176 | 
             
                  #rescue
         | 
| 171 177 | 
             
                    # trace "no Excel, Book, or WIN32OLE object representing a Workbook or an Excel instance"
         | 
| @@ -215,7 +221,7 @@ module RobustExcelOle | |
| 215 221 | 
             
                    if obstructed_by_other_book then
         | 
| 216 222 | 
             
                      case options[:if_obstructed]
         | 
| 217 223 | 
             
                      when :raise
         | 
| 218 | 
            -
                        raise ExcelErrorOpen, "blocked by a book with the same name in a different path: #{ | 
| 224 | 
            +
                        raise ExcelErrorOpen, "blocked by a book with the same name in a different path: #{@ole_workbook.Fullname.tr('\\','/')}"
         | 
| 219 225 | 
             
                      when :forget
         | 
| 220 226 | 
             
                        @ole_workbook.Close
         | 
| 221 227 | 
             
                        @ole_workbook = nil
         | 
| @@ -227,7 +233,7 @@ module RobustExcelOle | |
| 227 233 | 
             
                        open_or_create_workbook(file, options)
         | 
| 228 234 | 
             
                      when :close_if_saved
         | 
| 229 235 | 
             
                        if (not @ole_workbook.Saved) then
         | 
| 230 | 
            -
                          raise ExcelErrorOpen, "workbook with the same name in a different path is unsaved: #{ | 
| 236 | 
            +
                          raise ExcelErrorOpen, "workbook with the same name in a different path is unsaved: #{@ole_workbook.Fullname.tr('\\','/')}"
         | 
| 231 237 | 
             
                        else 
         | 
| 232 238 | 
             
                          @ole_workbook.Close
         | 
| 233 239 | 
             
                          @ole_workbook = nil
         | 
| @@ -253,7 +259,7 @@ module RobustExcelOle | |
| 253 259 | 
             
                          open_or_create_workbook(file, options)
         | 
| 254 260 | 
             
                        when :accept
         | 
| 255 261 | 
             
                          # do nothing
         | 
| 256 | 
            -
                        when :alert
         | 
| 262 | 
            +
                        when :alert, :excel
         | 
| 257 263 | 
             
                          @excel.with_displayalerts true do
         | 
| 258 264 | 
             
                            open_or_create_workbook(file,options)
         | 
| 259 265 | 
             
                          end 
         | 
| @@ -299,7 +305,8 @@ module RobustExcelOle | |
| 299 305 | 
             
                      workbooks.Add if @excel.Version == "12.0" && count == 0
         | 
| 300 306 | 
             
                      workbooks.Open(filename,{ 'ReadOnly' => options[:read_only] })
         | 
| 301 307 | 
             
                      workbooks.Item(1).Close if @excel.Version == "12.0" && count == 0
         | 
| 302 | 
            -
                       | 
| 308 | 
            +
                      workbooks.Item(1).CheckCompatibility = options[:check_compatibility]
         | 
| 309 | 
            +
                      @can_be_closed = false if @can_be_closed.nil?
         | 
| 303 310 | 
             
                    rescue WIN32OLERuntimeError => msg
         | 
| 304 311 | 
             
                      trace "WIN32OLERuntimeError: #{msg.message}" 
         | 
| 305 312 | 
             
                      if msg.message =~ /800A03EC/
         | 
| @@ -329,7 +336,7 @@ module RobustExcelOle | |
| 329 336 | 
             
                #                      :save            -> saves the workbook before it is closed                  
         | 
| 330 337 | 
             
                #                      :forget          -> closes the workbook 
         | 
| 331 338 | 
             
                #                      :keep_open       -> keep the workbook open
         | 
| 332 | 
            -
                #                      :alert | 
| 339 | 
            +
                #                      :alert or :excel -> gives control to excel
         | 
| 333 340 | 
             
                # @raise ExcelErrorClose if the option :if_unsaved is :raise and the workbook is unsaved, or option is invalid
         | 
| 334 341 | 
             
                # @raise ExcelErrorCanceled if the user has canceled 
         | 
| 335 342 | 
             
                def close(opts = {:if_unsaved => :raise})
         | 
| @@ -344,7 +351,7 @@ module RobustExcelOle | |
| 344 351 | 
             
                      close_workbook
         | 
| 345 352 | 
             
                    when :keep_open
         | 
| 346 353 | 
             
                      # nothing
         | 
| 347 | 
            -
                    when :alert
         | 
| 354 | 
            +
                    when :alert, :excel
         | 
| 348 355 | 
             
                      @excel.with_displayalerts true do
         | 
| 349 356 | 
             
                        close_workbook
         | 
| 350 357 | 
             
                      end
         | 
| @@ -354,7 +361,8 @@ module RobustExcelOle | |
| 354 361 | 
             
                  else
         | 
| 355 362 | 
             
                    close_workbook
         | 
| 356 363 | 
             
                  end
         | 
| 357 | 
            -
                  raise ExcelUserCanceled, "close: canceled by user" if alive? &&  | 
| 364 | 
            +
                  raise ExcelUserCanceled, "close: canceled by user" if alive? && 
         | 
| 365 | 
            +
                  (opts[:if_unsaved] == :alert || opts[:if_unsaved] == :excel) && (not @ole_workbook.Saved)
         | 
| 358 366 | 
             
                end
         | 
| 359 367 |  | 
| 360 368 | 
             
              private
         | 
| @@ -403,8 +411,9 @@ module RobustExcelOle | |
| 403 411 | 
             
                #                    true:  closes it and open it as writable in the Excel instance where it was open so far
         | 
| 404 412 | 
             
                #                    false (default)   opens it as writable in another running excel instance, if it exists,
         | 
| 405 413 | 
             
                #                                      otherwise open in a new Excel instance.
         | 
| 406 | 
            -
                # :displayalerts | 
| 407 | 
            -
                # :visible | 
| 414 | 
            +
                # :displayalerts      enables DisplayAlerts in Excel  
         | 
| 415 | 
            +
                # :visible            makes visible in Excel 
         | 
| 416 | 
            +
                # :check_compatibility checks compatibility when saving
         | 
| 408 417 | 
             
                # @return [Book] a workbook
         | 
| 409 418 | 
             
                def self.unobtrusively(file, if_closed = nil, opts = { }, &block) 
         | 
| 410 419 | 
             
                  if if_closed.is_a? Hash
         | 
| @@ -415,7 +424,8 @@ module RobustExcelOle | |
| 415 424 | 
             
                  options = {
         | 
| 416 425 | 
             
                    :read_only => false,
         | 
| 417 426 | 
             
                    :readonly_excel => false,
         | 
| 418 | 
            -
                    :keep_open => false
         | 
| 427 | 
            +
                    :keep_open => false,
         | 
| 428 | 
            +
                    :check_compatibility => true
         | 
| 419 429 | 
             
                  }.merge(opts)
         | 
| 420 430 | 
             
                  book = bookstore.fetch(file, :prefer_writable => (not options[:read_only]))
         | 
| 421 431 | 
             
                  was_not_alive_or_nil = book.nil? || (not book.alive?)
         | 
| @@ -428,7 +438,7 @@ module RobustExcelOle | |
| 428 438 | 
             
                      false
         | 
| 429 439 | 
             
                    end
         | 
| 430 440 | 
             
                  was_saved = was_not_alive_or_nil ? true : book.saved
         | 
| 431 | 
            -
                  was_writable = book.writable unless was_not_alive_or_nil
         | 
| 441 | 
            +
                  was_writable = book.writable unless was_not_alive_or_nil      
         | 
| 432 442 | 
             
                  begin 
         | 
| 433 443 | 
             
                    book = 
         | 
| 434 444 | 
             
                      if was_not_alive_or_nil 
         | 
| @@ -450,15 +460,19 @@ module RobustExcelOle | |
| 450 460 | 
             
                      end
         | 
| 451 461 | 
             
                    book.excel.displayalerts = options[:displayalerts] unless options[:displayalerts].nil?
         | 
| 452 462 | 
             
                    book.excel.visible = options[:visible] unless options[:visible].nil?
         | 
| 463 | 
            +
                    old_check_compatibility = book.CheckCompatibility
         | 
| 464 | 
            +
                    book.CheckCompatibility = options[:check_compatibility]
         | 
| 453 465 | 
             
                    yield book
         | 
| 454 466 | 
             
                  ensure
         | 
| 455 | 
            -
                     | 
| 467 | 
            +
                    was_saved_or_appeared = was_saved || was_not_alive_or_nil || (not was_writable)
         | 
| 468 | 
            +
                    book.save if book && (not book.saved) && (not options[:read_only]) && was_saved_or_appeared
         | 
| 456 469 | 
             
                    # book was open, readonly and shoud be modified
         | 
| 457 470 | 
             
                    if (not was_not_alive_or_nil) && (not options[:read_only]) && (not was_writable) && options[:readonly_excel]
         | 
| 458 471 | 
             
                      open(file, :force_excel => book.excel, :if_obstructed => :new_excel, :read_only => true)
         | 
| 459 472 | 
             
                    end
         | 
| 460 473 | 
             
                    @can_be_closed = true if options[:keep_open] && book
         | 
| 461 474 | 
             
                    book.close if (was_not_alive_or_nil && (not now_alive) && (not options[:keep_open]) && book)
         | 
| 475 | 
            +
                    book.CheckCompatibility = old_check_compatibility if book && book.alive?
         | 
| 462 476 | 
             
                  end
         | 
| 463 477 | 
             
                end
         | 
| 464 478 |  | 
| @@ -467,136 +481,6 @@ module RobustExcelOle | |
| 467 481 | 
             
                  self.class.open(self.stored_filename)
         | 
| 468 482 | 
             
                end
         | 
| 469 483 |  | 
| 470 | 
            -
                # renames a range
         | 
| 471 | 
            -
                # @param [String] name     the previous range name
         | 
| 472 | 
            -
                # @param [String] new_name the new range name
         | 
| 473 | 
            -
                # @raise ExcelError if name is not in the file, or if new_name cannot be set
         | 
| 474 | 
            -
                def rename_range(name, new_name)
         | 
| 475 | 
            -
                  begin
         | 
| 476 | 
            -
                    item = self.Names.Item(name)
         | 
| 477 | 
            -
                  rescue WIN32OLERuntimeError
         | 
| 478 | 
            -
                    raise ExcelError, "name #{name.inspect} not in #{File.basename(self.stored_filename).inspect}"  
         | 
| 479 | 
            -
                  end
         | 
| 480 | 
            -
                  begin
         | 
| 481 | 
            -
                    item.Name = new_name
         | 
| 482 | 
            -
                  rescue WIN32OLERuntimeError
         | 
| 483 | 
            -
                    raise ExcelError, "name error in #{File.basename(self.stored_filename).inspect}"      
         | 
| 484 | 
            -
                  end
         | 
| 485 | 
            -
                end
         | 
| 486 | 
            -
             | 
| 487 | 
            -
                # returns the contents of a range with given name
         | 
| 488 | 
            -
                # @param  [String]      name      the range name
         | 
| 489 | 
            -
                # @param  [Hash]        opts      the options
         | 
| 490 | 
            -
                # @option opts [Symbol] :default  the default value that is provided if no contents could be returned
         | 
| 491 | 
            -
                # @raise  ExcelError if range name is not in the workbook
         | 
| 492 | 
            -
                # @raise  SheetError if range value could not be evaluated
         | 
| 493 | 
            -
                # @return [Variant] the contents of a range with given name
         | 
| 494 | 
            -
                # if no contents could be returned, then return default value, if a default value was provided
         | 
| 495 | 
            -
                #                                   raise an error, otherwise
         | 
| 496 | 
            -
                def nvalue(name, opts = {:default => nil})
         | 
| 497 | 
            -
                  begin
         | 
| 498 | 
            -
                    item = self.Names.Item(name)
         | 
| 499 | 
            -
                  rescue WIN32OLERuntimeError
         | 
| 500 | 
            -
                    return opts[:default] if opts[:default]
         | 
| 501 | 
            -
                    raise ExcelError, "name #{name.inspect} not in #{File.basename(self.stored_filename).inspect}"
         | 
| 502 | 
            -
                  end
         | 
| 503 | 
            -
                  begin
         | 
| 504 | 
            -
                    value = item.RefersToRange.Value
         | 
| 505 | 
            -
                  rescue  WIN32OLERuntimeError
         | 
| 506 | 
            -
                    begin
         | 
| 507 | 
            -
                      sheet = self[0]
         | 
| 508 | 
            -
                      value = sheet.Evaluate(name)
         | 
| 509 | 
            -
                    rescue WIN32OLERuntimeError
         | 
| 510 | 
            -
                      return opts[:default] if opts[:default]
         | 
| 511 | 
            -
                      raise SheetError, "cannot evaluate name #{name.inspect} in sheet"
         | 
| 512 | 
            -
                    end
         | 
| 513 | 
            -
                  end
         | 
| 514 | 
            -
                  if value == -2146826259
         | 
| 515 | 
            -
                    return opts[:default] if opts[:default]
         | 
| 516 | 
            -
                    raise SheetError, "cannot evaluate name #{name.inspect} in sheet"
         | 
| 517 | 
            -
                  end 
         | 
| 518 | 
            -
                  return opts[:default] if (value.nil? && opts[:default])
         | 
| 519 | 
            -
                  value      
         | 
| 520 | 
            -
                end
         | 
| 521 | 
            -
             | 
| 522 | 
            -
                # sets the contents of a range with given name
         | 
| 523 | 
            -
                # @param [String]  name  the range name
         | 
| 524 | 
            -
                # @param [Variant] value the contents of the range
         | 
| 525 | 
            -
                # @raise ExcelError if range name is not in the workbook or if a RefersToRange error occurs
         | 
| 526 | 
            -
                def set_nvalue(name, value) 
         | 
| 527 | 
            -
                  begin
         | 
| 528 | 
            -
                    item = self.Names.Item(name)
         | 
| 529 | 
            -
                  rescue WIN32OLERuntimeError
         | 
| 530 | 
            -
                    raise ExcelError, "name #{name.inspect} not in #{File.basename(self.stored_filename).inspect}"  
         | 
| 531 | 
            -
                  end
         | 
| 532 | 
            -
                  begin
         | 
| 533 | 
            -
                    item.RefersToRange.Value = value
         | 
| 534 | 
            -
                  rescue WIN32OLERuntimeError
         | 
| 535 | 
            -
                    raise ExcelError, "RefersToRange error of name #{name.inspect} in #{File.basename(self.stored_filename).inspect}"    
         | 
| 536 | 
            -
                  end
         | 
| 537 | 
            -
                end
         | 
| 538 | 
            -
             | 
| 539 | 
            -
                # brings workbook to foreground, makes it available for heyboard inputs, makes the Excel instance visible
         | 
| 540 | 
            -
                # @raise ExcelError if workbook cannot be activated    
         | 
| 541 | 
            -
                def activate      
         | 
| 542 | 
            -
                  @excel.visible = true
         | 
| 543 | 
            -
                  begin
         | 
| 544 | 
            -
                    Win32API.new("user32","SetForegroundWindow","I","I").call(@excel.hwnd)     # Excel  2010
         | 
| 545 | 
            -
                    @ole_workbook.Activate   # Excel 2007
         | 
| 546 | 
            -
                  rescue WIN32OLERuntimeError
         | 
| 547 | 
            -
                    raise ExcelError, "cannot activate"
         | 
| 548 | 
            -
                  end
         | 
| 549 | 
            -
                end
         | 
| 550 | 
            -
             | 
| 551 | 
            -
                # returns true, if the workbook is visible, false otherwise 
         | 
| 552 | 
            -
                def visible
         | 
| 553 | 
            -
                  @excel.Windows(@ole_workbook.Name).Visible
         | 
| 554 | 
            -
                end
         | 
| 555 | 
            -
             | 
| 556 | 
            -
                # makes a workbook visible or invisible
         | 
| 557 | 
            -
                # @param [Boolean] visible_value value that determines whether the workbook shall be visible
         | 
| 558 | 
            -
                def visible= visible_value
         | 
| 559 | 
            -
                  saved = @ole_workbook.Saved
         | 
| 560 | 
            -
                  @excel.Windows(@ole_workbook.Name).Visible = visible_value
         | 
| 561 | 
            -
                  save if saved 
         | 
| 562 | 
            -
                end
         | 
| 563 | 
            -
             | 
| 564 | 
            -
                # returns true, if the workbook reacts to methods, false otherwise
         | 
| 565 | 
            -
                def alive?
         | 
| 566 | 
            -
                  begin 
         | 
| 567 | 
            -
                    @ole_workbook.Name
         | 
| 568 | 
            -
                    true
         | 
| 569 | 
            -
                  rescue 
         | 
| 570 | 
            -
                    @ole_workbook = nil  # dead object won't be alive again
         | 
| 571 | 
            -
                    #t $!.message
         | 
| 572 | 
            -
                    false
         | 
| 573 | 
            -
                  end
         | 
| 574 | 
            -
                end
         | 
| 575 | 
            -
             | 
| 576 | 
            -
                # returns the full file name of the workbook
         | 
| 577 | 
            -
                def filename
         | 
| 578 | 
            -
                  @ole_workbook.Fullname.tr('\\','/') rescue nil
         | 
| 579 | 
            -
                end
         | 
| 580 | 
            -
             | 
| 581 | 
            -
                def writable   # :nodoc: #
         | 
| 582 | 
            -
                  (not @ole_workbook.ReadOnly) if @ole_workbook
         | 
| 583 | 
            -
                end
         | 
| 584 | 
            -
             | 
| 585 | 
            -
                def saved   # :nodoc: #
         | 
| 586 | 
            -
                  @ole_workbook.Saved if @ole_workbook
         | 
| 587 | 
            -
                end
         | 
| 588 | 
            -
             | 
| 589 | 
            -
                # @return [Boolean] true, if the full book names and excel Instances are identical, false otherwise  
         | 
| 590 | 
            -
                def == other_book
         | 
| 591 | 
            -
                  other_book.is_a?(Book) &&
         | 
| 592 | 
            -
                  @excel == other_book.excel &&
         | 
| 593 | 
            -
                  self.filename == other_book.filename  
         | 
| 594 | 
            -
                end
         | 
| 595 | 
            -
             | 
| 596 | 
            -
                def self.books
         | 
| 597 | 
            -
                  bookstore.books
         | 
| 598 | 
            -
                end
         | 
| 599 | 
            -
             | 
| 600 484 | 
             
                # simple save of a workbook.
         | 
| 601 485 | 
             
                # @raise ExcelErrorSave if workbook is not alive or opened for read-only, or another error occurs
         | 
| 602 486 | 
             
                # @return [Boolean] true, if successfully saved, nil otherwise
         | 
| @@ -618,13 +502,13 @@ module RobustExcelOle | |
| 618 502 | 
             
                # saves a workbook with a given file name.
         | 
| 619 503 | 
             
                # @param [String] file   file name
         | 
| 620 504 | 
             
                # @param [Hash]   opts   the options
         | 
| 621 | 
            -
                # @option opts [Symbol] :if_exists      :raise (default), :overwrite, or :alert
         | 
| 505 | 
            +
                # @option opts [Symbol] :if_exists      :raise (default), :overwrite, or :alert, :excel
         | 
| 622 506 | 
             
                # @option opts [Symbol] :if_obstructed  :raise (default), :forget, :save, or :close_if_saved
         | 
| 623 507 | 
             
                # options: 
         | 
| 624 508 | 
             
                # :if_exists  if a file with the same name exists, then  
         | 
| 625 509 | 
             
                #               :raise     -> raises an exception, dont't write the file  (default)
         | 
| 626 510 | 
             
                #               :overwrite -> writes the file, delete the old file
         | 
| 627 | 
            -
                #               :alert | 
| 511 | 
            +
                #               :alert or :excel -> gives control to Excel
         | 
| 628 512 | 
             
                #  :if_obstructed   if a workbook with the same name and different path is already open and blocks the saving, then
         | 
| 629 513 | 
             
                #                  :raise               -> raises an exception 
         | 
| 630 514 | 
             
                #                  :forget              -> closes the blocking workbook
         | 
| @@ -634,7 +518,7 @@ module RobustExcelOle | |
| 634 518 | 
             
                # @raise ExcelErrorSave if workbook is not alive, opened in read-only mode, invalid options,
         | 
| 635 519 | 
             
                #                          the file already exists (with option :if_exists :raise),
         | 
| 636 520 | 
             
                #                          the workbook is blocked by another one (with option :if_obstructed :raise)
         | 
| 637 | 
            -
                # @return [ | 
| 521 | 
            +
                # @return [Book], the book itself, if successfully saved, raises an exception otherwise
         | 
| 638 522 | 
             
                def save_as(file = nil, opts = { } )
         | 
| 639 523 | 
             
                  raise ExcelErrorSave, "Workbook is not alive" if (not alive?)
         | 
| 640 524 | 
             
                  raise ExcelErrorSave, "Not opened for writing (opened with :read_only option)" if @ole_workbook.ReadOnly
         | 
| @@ -647,7 +531,7 @@ module RobustExcelOle | |
| 647 531 | 
             
                    when :overwrite
         | 
| 648 532 | 
             
                      if file == self.filename
         | 
| 649 533 | 
             
                        save
         | 
| 650 | 
            -
                        return
         | 
| 534 | 
            +
                        return self
         | 
| 651 535 | 
             
                      else
         | 
| 652 536 | 
             
                        begin
         | 
| 653 537 | 
             
                          File.delete(file)
         | 
| @@ -655,12 +539,11 @@ module RobustExcelOle | |
| 655 539 | 
             
                          raise ExcelErrorSave, "workbook is open and used in Excel"
         | 
| 656 540 | 
             
                        end
         | 
| 657 541 | 
             
                      end
         | 
| 658 | 
            -
                    when :alert 
         | 
| 542 | 
            +
                    when :alert, :excel 
         | 
| 659 543 | 
             
                      @excel.with_displayalerts true do
         | 
| 660 544 | 
             
                        save_as_workbook(file, options)
         | 
| 661 545 | 
             
                      end
         | 
| 662 | 
            -
                       | 
| 663 | 
            -
                      return
         | 
| 546 | 
            +
                      return self
         | 
| 664 547 | 
             
                    when :raise
         | 
| 665 548 | 
             
                      raise ExcelErrorSave, "file already exists: #{File.basename(file).inspect}"
         | 
| 666 549 | 
             
                    else
         | 
| @@ -676,7 +559,7 @@ module RobustExcelOle | |
| 676 559 | 
             
                  if blocking_workbook then
         | 
| 677 560 | 
             
                    case options[:if_obstructed]
         | 
| 678 561 | 
             
                    when :raise
         | 
| 679 | 
            -
                      raise ExcelErrorSave, "blocked by another workbook: #{ | 
| 562 | 
            +
                      raise ExcelErrorSave, "blocked by another workbook: #{blocking_workbook.Fullname.tr('\\','/')}"
         | 
| 680 563 | 
             
                    when :forget
         | 
| 681 564 | 
             
                      # nothing
         | 
| 682 565 | 
             
                    when :save
         | 
| @@ -689,7 +572,7 @@ module RobustExcelOle | |
| 689 572 | 
             
                    blocking_workbook.Close
         | 
| 690 573 | 
             
                  end
         | 
| 691 574 | 
             
                  save_as_workbook(file, options)
         | 
| 692 | 
            -
                   | 
| 575 | 
            +
                  self
         | 
| 693 576 | 
             
                end
         | 
| 694 577 |  | 
| 695 578 | 
             
              private
         | 
| @@ -707,7 +590,7 @@ module RobustExcelOle | |
| 707 590 | 
             
                    bookstore.store(self)
         | 
| 708 591 | 
             
                  rescue WIN32OLERuntimeError => msg
         | 
| 709 592 | 
             
                    if msg.message =~ /SaveAs/ and msg.message =~ /Workbook/ then
         | 
| 710 | 
            -
                      if options[:if_exists] == :alert then 
         | 
| 593 | 
            +
                      if options[:if_exists] == :alert || options[:if_exists] == :excel then 
         | 
| 711 594 | 
             
                        raise ExcelErrorSave, "not saved or canceled by user"
         | 
| 712 595 | 
             
                      else
         | 
| 713 596 | 
             
                        return nil
         | 
| @@ -722,65 +605,238 @@ module RobustExcelOle | |
| 722 605 | 
             
              public
         | 
| 723 606 |  | 
| 724 607 | 
             
                # returns a sheet, if a sheet name or a number is given
         | 
| 725 | 
            -
                #  | 
| 726 | 
            -
                 | 
| 727 | 
            -
             | 
| 608 | 
            +
                # @param [String] or [Number]
         | 
| 609 | 
            +
                # @returns [Sheet]
         | 
| 610 | 
            +
                def sheet(name)
         | 
| 728 611 | 
             
                  begin
         | 
| 729 612 | 
             
                    sheet_class.new(@ole_workbook.Worksheets.Item(name))
         | 
| 730 613 | 
             
                  rescue WIN32OLERuntimeError => msg
         | 
| 731 | 
            -
                     | 
| 732 | 
            -
             | 
| 733 | 
            -
                    else
         | 
| 734 | 
            -
                      raise ExcelError, "could neither return a sheet nor a value of a range when giving the name #{name.inspect}"
         | 
| 735 | 
            -
                    end
         | 
| 614 | 
            +
                    raise ExcelError, "could not return a sheet with name #{name.inspect}"
         | 
| 615 | 
            +
                    trace "#{msg.message}"
         | 
| 736 616 | 
             
                  end
         | 
| 737 | 
            -
                end
         | 
| 738 | 
            -
             | 
| 739 | 
            -
                # sets the value of a range given its name
         | 
| 740 | 
            -
                # @param [String]  name  the name of the range
         | 
| 741 | 
            -
                # @param [Variant] value the contents of the range
         | 
| 742 | 
            -
                def []= (name, value)
         | 
| 743 | 
            -
                  set_nvalue(name,value)
         | 
| 744 | 
            -
                end
         | 
| 617 | 
            +
                end    
         | 
| 745 618 |  | 
| 746 619 | 
             
                def each
         | 
| 747 620 | 
             
                  @ole_workbook.Worksheets.each do |sheet|
         | 
| 748 621 | 
             
                    yield sheet_class.new(sheet)
         | 
| 749 622 | 
             
                  end
         | 
| 750 623 | 
             
                end
         | 
| 624 | 
            +
              
         | 
| 625 | 
            +
                # copies a sheet to another position
         | 
| 626 | 
            +
                # default: copied sheet is appended
         | 
| 627 | 
            +
                # @param [Sheet] sheet a sheet that shall be copied
         | 
| 628 | 
            +
                # @param [Hash]  opts  the options
         | 
| 629 | 
            +
                # @option opts [Symbol] :as     new name of the copied sheet
         | 
| 630 | 
            +
                # @option opts [Symbol] :before a sheet before which the sheet shall be inserted
         | 
| 631 | 
            +
                # @option opts [Symbol] :after  a sheet after which the sheet shall be inserted
         | 
| 632 | 
            +
                # @raise  ExcelErrorSheet if the sheet name already exists
         | 
| 633 | 
            +
                # @return [Sheet] the copied sheet
         | 
| 634 | 
            +
                def copy_sheet(sheet, opts = { })
         | 
| 635 | 
            +
                  new_sheet_name = opts.delete(:as)
         | 
| 636 | 
            +
                  after_or_before, base_sheet = opts.to_a.first || [:after, last_sheet]
         | 
| 637 | 
            +
                  sheet.Copy({ after_or_before.to_s => base_sheet.worksheet })
         | 
| 638 | 
            +
                  new_sheet = sheet_class.new(@excel.Activesheet)
         | 
| 639 | 
            +
                  begin
         | 
| 640 | 
            +
                    new_sheet.name = new_sheet_name if new_sheet_name
         | 
| 641 | 
            +
                  rescue WIN32OLERuntimeError => msg
         | 
| 642 | 
            +
                    msg.message =~ /800A03EC/ ? raise(ExcelErrorSheet, "sheet name already exists") : raise(ExcelErrorSheetUnknown)
         | 
| 643 | 
            +
                  end
         | 
| 644 | 
            +
                  new_sheet
         | 
| 645 | 
            +
                end      
         | 
| 751 646 |  | 
| 752 | 
            -
                # adds  | 
| 753 | 
            -
                #  | 
| 647 | 
            +
                # adds an empty sheet
         | 
| 648 | 
            +
                # default: empty sheet is appended
         | 
| 754 649 | 
             
                # @param [Hash]  opts  the options
         | 
| 755 | 
            -
                # @option opts [Symbol] :as     new name of the  | 
| 650 | 
            +
                # @option opts [Symbol] :as     new name of the copied added sheet
         | 
| 756 651 | 
             
                # @option opts [Symbol] :before a sheet before which the sheet shall be inserted
         | 
| 757 652 | 
             
                # @option opts [Symbol] :after  a sheet after which the sheet shall be inserted
         | 
| 758 653 | 
             
                # @raise  ExcelErrorSheet if the sheet name already exists
         | 
| 759 654 | 
             
                # @return [Sheet] the added sheet
         | 
| 760 | 
            -
                def  | 
| 761 | 
            -
                  if sheet.is_a? Hash
         | 
| 762 | 
            -
                    opts = sheet
         | 
| 763 | 
            -
                    sheet = nil
         | 
| 764 | 
            -
                  end
         | 
| 655 | 
            +
                def add_empty_sheet(opts = { })
         | 
| 765 656 | 
             
                  new_sheet_name = opts.delete(:as)
         | 
| 766 | 
            -
                   | 
| 767 | 
            -
                   | 
| 768 | 
            -
                  base_sheet = base_sheet.worksheet
         | 
| 769 | 
            -
                  sheet ? sheet.Copy({ after_or_before.to_s => base_sheet }) : @ole_workbook.WorkSheets.Add({ after_or_before.to_s => base_sheet })
         | 
| 657 | 
            +
                  after_or_before, base_sheet = opts.to_a.first || [:after, last_sheet]
         | 
| 658 | 
            +
                  @ole_workbook.Worksheets.Add({ after_or_before.to_s => base_sheet.worksheet })
         | 
| 770 659 | 
             
                  new_sheet = sheet_class.new(@excel.Activesheet)
         | 
| 771 660 | 
             
                  begin
         | 
| 772 661 | 
             
                    new_sheet.name = new_sheet_name if new_sheet_name
         | 
| 773 662 | 
             
                  rescue WIN32OLERuntimeError => msg
         | 
| 774 | 
            -
                     | 
| 775 | 
            -
                      raise ExcelErrorSheet, "sheet name already exists"
         | 
| 776 | 
            -
                    else
         | 
| 777 | 
            -
                      trace "#{msg.message}"
         | 
| 778 | 
            -
                      raise ExcelErrorSheetUnknown
         | 
| 779 | 
            -
                    end
         | 
| 663 | 
            +
                    msg.message =~ /800A03EC/ ? raise(ExcelErrorSheet, "sheet name already exists") : raise(ExcelErrorSheetUnknown)
         | 
| 780 664 | 
             
                  end
         | 
| 781 665 | 
             
                  new_sheet
         | 
| 666 | 
            +
                end    
         | 
| 667 | 
            +
             | 
| 668 | 
            +
                # copies a sheet to another position if a sheet is given, or adds an empty sheet
         | 
| 669 | 
            +
                # default: copied or empty sheet is appended, i.e. added behind the last sheet
         | 
| 670 | 
            +
                # @param [Sheet] sheet a sheet that shall be copied (optional)
         | 
| 671 | 
            +
                # @param [Hash]  opts  the options
         | 
| 672 | 
            +
                # @option opts [Symbol] :as     new name of the copied or added sheet
         | 
| 673 | 
            +
                # @option opts [Symbol] :before a sheet before which the sheet shall be inserted
         | 
| 674 | 
            +
                # @option opts [Symbol] :after  a sheet after which the sheet shall be inserted
         | 
| 675 | 
            +
                # @raise  ExcelErrorSheet if the sheet name already exists
         | 
| 676 | 
            +
                # @return [Sheet] the copied or added sheet
         | 
| 677 | 
            +
                def add_or_copy_sheet(sheet = nil, opts = { })
         | 
| 678 | 
            +
                  if sheet.is_a? Hash
         | 
| 679 | 
            +
                    opts = sheet
         | 
| 680 | 
            +
                    sheet = nil
         | 
| 681 | 
            +
                  end
         | 
| 682 | 
            +
                  sheet ? copy_sheet(sheet, opts) : add_empty_sheet(opts)
         | 
| 782 683 | 
             
                end      
         | 
| 783 684 |  | 
| 685 | 
            +
                # for compatibility to older versions
         | 
| 686 | 
            +
                def add_sheet(sheet = nil, opts = { })
         | 
| 687 | 
            +
                  add_or_copy_sheet(sheet, opts)
         | 
| 688 | 
            +
                end 
         | 
| 689 | 
            +
             | 
| 690 | 
            +
                def last_sheet
         | 
| 691 | 
            +
                  sheet_class.new(@ole_workbook.Worksheets.Item(@ole_workbook.Worksheets.Count))
         | 
| 692 | 
            +
                end
         | 
| 693 | 
            +
             | 
| 694 | 
            +
                def first_sheet
         | 
| 695 | 
            +
                  sheet_class.new(@ole_workbook.Worksheets.Item(1))
         | 
| 696 | 
            +
                end
         | 
| 697 | 
            +
             | 
| 698 | 
            +
                # returns the value of a range
         | 
| 699 | 
            +
                # @param [String] name the name of a range
         | 
| 700 | 
            +
                # @returns [Variant] the value of the range
         | 
| 701 | 
            +
                def [] name
         | 
| 702 | 
            +
                  nameval(name)
         | 
| 703 | 
            +
                end
         | 
| 704 | 
            +
             | 
| 705 | 
            +
                # sets the value of a range
         | 
| 706 | 
            +
                # @param [String]  name  the name of the range
         | 
| 707 | 
            +
                # @param [Variant] value the contents of the range
         | 
| 708 | 
            +
                def []= (name, value)
         | 
| 709 | 
            +
                  set_nameval(name,value)
         | 
| 710 | 
            +
                end
         | 
| 711 | 
            +
             | 
| 712 | 
            +
                # returns the contents of a range with given name
         | 
| 713 | 
            +
                # evaluates formula contents of the range is a formula
         | 
| 714 | 
            +
                # if no contents could be returned, then return default value, if provided, raise error otherwise
         | 
| 715 | 
            +
                # @param  [String]      name      the name of the range
         | 
| 716 | 
            +
                # @param  [Hash]        opts      the options
         | 
| 717 | 
            +
                # @option opts [Symbol] :default  the default value that is provided if no contents could be returned
         | 
| 718 | 
            +
                # @raise  ExcelError if range name is not in the workbook or if range value could not be evaluated
         | 
| 719 | 
            +
                # @return [Variant] the contents of a range with given name
         | 
| 720 | 
            +
                def nameval(name, opts = {:default => nil})
         | 
| 721 | 
            +
                  begin
         | 
| 722 | 
            +
                    name_obj = self.Names.Item(name)
         | 
| 723 | 
            +
                  rescue WIN32OLERuntimeError
         | 
| 724 | 
            +
                    return opts[:default] if opts[:default]
         | 
| 725 | 
            +
                    raise ExcelError, "name #{name.inspect} not in #{File.basename(self.stored_filename).inspect}"
         | 
| 726 | 
            +
                  end
         | 
| 727 | 
            +
                  begin
         | 
| 728 | 
            +
                    value = name_obj.RefersToRange.Value
         | 
| 729 | 
            +
                  rescue  WIN32OLERuntimeError
         | 
| 730 | 
            +
                    begin
         | 
| 731 | 
            +
                      value = self.sheet(1).Evaluate(name_obj.Name)
         | 
| 732 | 
            +
                    rescue WIN32OLERuntimeError
         | 
| 733 | 
            +
                      return opts[:default] if opts[:default]
         | 
| 734 | 
            +
                      raise SheetError, "cannot evaluate name #{name.inspect} in #{File.basename(self.stored_filename).inspect}"
         | 
| 735 | 
            +
                    end
         | 
| 736 | 
            +
                  end
         | 
| 737 | 
            +
                  if value == -2146826259
         | 
| 738 | 
            +
                    return opts[:default] if opts[:default]
         | 
| 739 | 
            +
                    raise SheetError, "cannot evaluate name #{name.inspect} in #{File.basename(self.stored_filename).inspect}"
         | 
| 740 | 
            +
                  end 
         | 
| 741 | 
            +
                  return opts[:default] if (value.nil? && opts[:default])
         | 
| 742 | 
            +
                  value      
         | 
| 743 | 
            +
                end
         | 
| 744 | 
            +
             | 
| 745 | 
            +
                # sets the contents of a range
         | 
| 746 | 
            +
                # @param [String]  name  the name of a range
         | 
| 747 | 
            +
                # @param [Variant] value the contents of the range
         | 
| 748 | 
            +
                # @raise ExcelError if range name is not in the workbook or if value could not be assigned to range
         | 
| 749 | 
            +
                def set_nameval(name, value) 
         | 
| 750 | 
            +
                  begin
         | 
| 751 | 
            +
                    name_obj = self.Names.Item(name)
         | 
| 752 | 
            +
                  rescue WIN32OLERuntimeError
         | 
| 753 | 
            +
                    raise ExcelError, "name #{name.inspect} not in #{File.basename(self.stored_filename).inspect}"  
         | 
| 754 | 
            +
                  end
         | 
| 755 | 
            +
                  begin
         | 
| 756 | 
            +
                    name_obj.RefersToRange.Value = value
         | 
| 757 | 
            +
                  rescue WIN32OLERuntimeError
         | 
| 758 | 
            +
                    raise ExcelError, "cannot assign value to range named #{name.inspect} in #{File.basename(self.stored_filename).inspect}"    
         | 
| 759 | 
            +
                  end
         | 
| 760 | 
            +
                end    
         | 
| 761 | 
            +
             | 
| 762 | 
            +
                # renames a range
         | 
| 763 | 
            +
                # @param [String] name     the previous range name
         | 
| 764 | 
            +
                # @param [String] new_name the new range name
         | 
| 765 | 
            +
                # @raise ExcelError if name is not in the file, or if new_name cannot be set
         | 
| 766 | 
            +
                def rename_range(name, new_name)
         | 
| 767 | 
            +
                  begin
         | 
| 768 | 
            +
                    item = self.Names.Item(name)
         | 
| 769 | 
            +
                  rescue WIN32OLERuntimeError
         | 
| 770 | 
            +
                    raise ExcelError, "name #{name.inspect} not in #{File.basename(self.stored_filename).inspect}"  
         | 
| 771 | 
            +
                  end
         | 
| 772 | 
            +
                  begin
         | 
| 773 | 
            +
                    item.Name = new_name
         | 
| 774 | 
            +
                  rescue WIN32OLERuntimeError
         | 
| 775 | 
            +
                    raise ExcelError, "name error in #{File.basename(self.stored_filename).inspect}"      
         | 
| 776 | 
            +
                  end
         | 
| 777 | 
            +
                end
         | 
| 778 | 
            +
             | 
| 779 | 
            +
                # brings workbook to foreground, makes it available for heyboard inputs, makes the Excel instance visible
         | 
| 780 | 
            +
                # @raise ExcelError if workbook cannot be activated    
         | 
| 781 | 
            +
                def activate      
         | 
| 782 | 
            +
                  @excel.visible = true
         | 
| 783 | 
            +
                  begin
         | 
| 784 | 
            +
                    Win32API.new("user32","SetForegroundWindow","I","I").call(@excel.hwnd)     # Excel  2010
         | 
| 785 | 
            +
                    @ole_workbook.Activate   # Excel 2007
         | 
| 786 | 
            +
                  rescue WIN32OLERuntimeError
         | 
| 787 | 
            +
                    raise ExcelError, "cannot activate"
         | 
| 788 | 
            +
                  end
         | 
| 789 | 
            +
                end
         | 
| 790 | 
            +
             | 
| 791 | 
            +
                # returns true, if the workbook is visible, false otherwise 
         | 
| 792 | 
            +
                def visible
         | 
| 793 | 
            +
                  @excel.Windows(@ole_workbook.Name).Visible
         | 
| 794 | 
            +
                end
         | 
| 795 | 
            +
             | 
| 796 | 
            +
                # makes a workbook visible or invisible
         | 
| 797 | 
            +
                # @param [Boolean] visible_value value that determines whether the workbook shall be visible
         | 
| 798 | 
            +
                def visible= visible_value
         | 
| 799 | 
            +
                  saved = @ole_workbook.Saved
         | 
| 800 | 
            +
                  @excel.Windows(@ole_workbook.Name).Visible = visible_value
         | 
| 801 | 
            +
                  save if saved 
         | 
| 802 | 
            +
                end
         | 
| 803 | 
            +
             | 
| 804 | 
            +
                # returns true, if the workbook reacts to methods, false otherwise
         | 
| 805 | 
            +
                def alive?
         | 
| 806 | 
            +
                  begin 
         | 
| 807 | 
            +
                    @ole_workbook.Name
         | 
| 808 | 
            +
                    true
         | 
| 809 | 
            +
                  rescue 
         | 
| 810 | 
            +
                    @ole_workbook = nil  # dead object won't be alive again
         | 
| 811 | 
            +
                    #t $!.message
         | 
| 812 | 
            +
                    false
         | 
| 813 | 
            +
                  end
         | 
| 814 | 
            +
                end
         | 
| 815 | 
            +
             | 
| 816 | 
            +
                # returns the full file name of the workbook
         | 
| 817 | 
            +
                def filename
         | 
| 818 | 
            +
                  @ole_workbook.Fullname.tr('\\','/') rescue nil
         | 
| 819 | 
            +
                end
         | 
| 820 | 
            +
             | 
| 821 | 
            +
                def writable   # :nodoc: #
         | 
| 822 | 
            +
                  (not @ole_workbook.ReadOnly) if @ole_workbook
         | 
| 823 | 
            +
                end
         | 
| 824 | 
            +
             | 
| 825 | 
            +
                def saved   # :nodoc: #
         | 
| 826 | 
            +
                  @ole_workbook.Saved if @ole_workbook
         | 
| 827 | 
            +
                end
         | 
| 828 | 
            +
             | 
| 829 | 
            +
                # @return [Boolean] true, if the full book names and excel Instances are identical, false otherwise  
         | 
| 830 | 
            +
                def == other_book
         | 
| 831 | 
            +
                  other_book.is_a?(Book) &&
         | 
| 832 | 
            +
                  @excel == other_book.excel &&
         | 
| 833 | 
            +
                  self.filename == other_book.filename  
         | 
| 834 | 
            +
                end
         | 
| 835 | 
            +
             | 
| 836 | 
            +
                def self.books
         | 
| 837 | 
            +
                  bookstore.books
         | 
| 838 | 
            +
                end
         | 
| 839 | 
            +
             | 
| 784 840 | 
             
                def self.bookstore   # :nodoc: #
         | 
| 785 841 | 
             
                  @@bookstore ||= Bookstore.new
         | 
| 786 842 | 
             
                end
         |