robust_excel_ole 0.3.8 → 0.3.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.yardopts +1 -0
- data/examples/edit_sheets/example_access_sheets_and_cells.rb +1 -1
- data/examples/edit_sheets/example_adding_sheets.rb +1 -1
- data/examples/edit_sheets/example_concating.rb +2 -2
- data/examples/edit_sheets/example_copying.rb +2 -2
- data/examples/edit_sheets/example_expanding.rb +2 -2
- data/examples/edit_sheets/example_naming.rb +2 -2
- 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_default_excel.rb +1 -1
- data/examples/open_save_close/example_force_excel.rb +1 -1
- data/examples/open_save_close/example_if_obstructed_closeifsaved.rb +1 -1
- data/examples/open_save_close/example_if_obstructed_forget.rb +1 -1
- data/examples/open_save_close/example_if_obstructed_save.rb +1 -1
- data/examples/open_save_close/example_if_unsaved_accept.rb +1 -1
- data/examples/open_save_close/example_if_unsaved_forget.rb +1 -1
- data/examples/open_save_close/example_if_unsaved_forget_more.rb +1 -1
- data/examples/open_save_close/example_read_only.rb +1 -1
- data/examples/open_save_close/example_rename_cells.rb +2 -2
- data/examples/open_save_close/example_reuse.rb +1 -1
- data/examples/open_save_close/example_simple.rb +1 -1
- data/examples/open_save_close/example_unobtrusively.rb +1 -1
- data/lib/reo_console.rb +2 -2
- data/lib/robust_excel_ole.rb +1 -174
- data/lib/robust_excel_ole/book.rb +47 -63
- data/lib/robust_excel_ole/bookstore.rb +4 -4
- data/lib/robust_excel_ole/excel.rb +12 -18
- data/lib/robust_excel_ole/general.rb +188 -0
- data/lib/robust_excel_ole/sheet.rb +1 -1
- data/lib/robust_excel_ole/utilities.rb +1 -1
- data/lib/robust_excel_ole/version.rb +1 -1
- data/spec/{book_specs/book_spec.rb → book_spec.rb} +26 -24
- data/spec/book_specs/book_all_spec.rb +1 -1
- data/spec/book_specs/book_close_spec.rb +16 -15
- data/spec/book_specs/book_misc_spec.rb +4 -3
- data/spec/book_specs/book_open_spec.rb +10 -9
- data/spec/book_specs/book_save_spec.rb +4 -3
- data/spec/book_specs/book_sheet_spec.rb +7 -6
- data/spec/book_specs/book_unobtr_spec.rb +2 -1
- data/spec/data/different_workbook.xls +0 -0
- data/spec/data/workbook.xls +0 -0
- data/spec/excel_spec.rb +9 -11
- data/spec/general_spec.rb +193 -0
- data/spec/range_spec.rb +3 -2
- data/spec/sheet_spec.rb +27 -19
- metadata +8 -6
- data/spec/robust_excel_ole_spec.rb +0 -113
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--legacy
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# example_access_sheets_and_cells.rb:
|
2
2
|
# access sheets, print cells, rows, and columns of a sheet
|
3
3
|
|
4
|
-
require File.join(File.dirname(__FILE__), '../../lib/
|
4
|
+
require File.join(File.dirname(__FILE__), '../../lib/general')
|
5
5
|
require File.join(File.dirname(__FILE__), '../../spec/helpers/create_temporary_dir')
|
6
6
|
require "fileutils"
|
7
7
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# example_adding_sheets.rb:
|
2
2
|
# adding new and copied at various positions with various sheet names
|
3
3
|
|
4
|
-
require File.join(File.dirname(__FILE__), '../../lib/
|
4
|
+
require File.join(File.dirname(__FILE__), '../../lib/general')
|
5
5
|
require File.join(File.dirname(__FILE__), '../../spec/helpers/create_temporary_dir')
|
6
6
|
require "fileutils"
|
7
7
|
|
@@ -3,8 +3,8 @@
|
|
3
3
|
# the new workbook's name is extended by the suffix "_concat"
|
4
4
|
|
5
5
|
require 'rubygems'
|
6
|
-
#require '
|
7
|
-
require File.join(File.dirname(__FILE__), '../../lib/
|
6
|
+
#require 'general'
|
7
|
+
require File.join(File.dirname(__FILE__), '../../lib/general')
|
8
8
|
require "fileutils"
|
9
9
|
|
10
10
|
include RobustExcelOle
|
@@ -4,8 +4,8 @@
|
|
4
4
|
# if a sheet does not contain any named cell, then the sheet shall not be copied
|
5
5
|
|
6
6
|
require 'rubygems'
|
7
|
-
#require '
|
8
|
-
require File.join(File.dirname(__FILE__), '../../lib/
|
7
|
+
#require 'general'
|
8
|
+
require File.join(File.dirname(__FILE__), '../../lib/general')
|
9
9
|
require "fileutils"
|
10
10
|
|
11
11
|
include RobustExcelOle
|
@@ -6,8 +6,8 @@
|
|
6
6
|
# in addition to that, the cell B2 shall be named "name" and get the sheet name as its value
|
7
7
|
|
8
8
|
require 'rubygems'
|
9
|
-
#require '
|
10
|
-
require File.join(File.dirname(__FILE__), '../../lib/
|
9
|
+
#require 'general'
|
10
|
+
require File.join(File.dirname(__FILE__), '../../lib/general')
|
11
11
|
require "fileutils"
|
12
12
|
|
13
13
|
include RobustExcelOle
|
@@ -4,8 +4,8 @@
|
|
4
4
|
# the new workbook's name is extended by the suffix "_named"
|
5
5
|
|
6
6
|
require 'rubygems'
|
7
|
-
#require '
|
8
|
-
require File.join(File.dirname(__FILE__), '../../lib/
|
7
|
+
#require 'general'
|
8
|
+
require File.join(File.dirname(__FILE__), '../../lib/general')
|
9
9
|
require "fileutils"
|
10
10
|
|
11
11
|
include RobustExcelOle
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# example_ranges.rb:
|
2
2
|
# access row and column ranges of a sheet.
|
3
3
|
|
4
|
-
require File.join(File.dirname(__FILE__), '../../lib/
|
4
|
+
require File.join(File.dirname(__FILE__), '../../lib/general')
|
5
5
|
require File.join(File.dirname(__FILE__), '../../spec/helpers/create_temporary_dir')
|
6
6
|
require "fileutils"
|
7
7
|
|
@@ -2,8 +2,8 @@
|
|
2
2
|
# save the sheets of a book as separate workbooks
|
3
3
|
|
4
4
|
require 'rubygems'
|
5
|
-
#require '
|
6
|
-
require File.join(File.dirname(__FILE__), '../../lib/
|
5
|
+
#require 'general'
|
6
|
+
require File.join(File.dirname(__FILE__), '../../lib/general')
|
7
7
|
require "fileutils"
|
8
8
|
|
9
9
|
include RobustExcelOle
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# example_give_control_to_excel.rb:
|
2
2
|
# open, close, save with giving control to Excel
|
3
3
|
|
4
|
-
require File.join(File.dirname(__FILE__), '../../lib/
|
4
|
+
require File.join(File.dirname(__FILE__), '../../lib/general')
|
5
5
|
require File.join(File.dirname(__FILE__), '../../spec/helpers/create_temporary_dir')
|
6
6
|
require "fileutils"
|
7
7
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# example_default_excel.rb:
|
2
2
|
# reopening books using :default_excel
|
3
3
|
|
4
|
-
require File.join(File.dirname(__FILE__), '../../lib/
|
4
|
+
require File.join(File.dirname(__FILE__), '../../lib/general')
|
5
5
|
require File.join(File.dirname(__FILE__), '../../spec/helpers/create_temporary_dir')
|
6
6
|
require "fileutils"
|
7
7
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# example_force_excel.rb:
|
2
2
|
# opening books in new or given Excel instances using :force_excel
|
3
3
|
|
4
|
-
require File.join(File.dirname(__FILE__), '../../lib/
|
4
|
+
require File.join(File.dirname(__FILE__), '../../lib/general')
|
5
5
|
require File.join(File.dirname(__FILE__), '../../spec/helpers/create_temporary_dir')
|
6
6
|
require "fileutils"
|
7
7
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# example_if_obstructed_close_if_saved.rb:
|
2
2
|
# open with :if_obstructed: :close_if_saved
|
3
3
|
|
4
|
-
require File.join(File.dirname(__FILE__), '../../lib/
|
4
|
+
require File.join(File.dirname(__FILE__), '../../lib/general')
|
5
5
|
require File.join(File.dirname(__FILE__), '../../spec/helpers/create_temporary_dir')
|
6
6
|
require "fileutils"
|
7
7
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# example_if_obstructed_forget.rb:
|
2
2
|
# open with :if_obstructed: :forget, :new_excel
|
3
3
|
|
4
|
-
require File.join(File.dirname(__FILE__), '../../lib/
|
4
|
+
require File.join(File.dirname(__FILE__), '../../lib/general')
|
5
5
|
require File.join(File.dirname(__FILE__), '../../spec/helpers/create_temporary_dir')
|
6
6
|
require "fileutils"
|
7
7
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# example_if_obstructed_save.rb:
|
2
2
|
# open with :if_obstructed: :save
|
3
3
|
|
4
|
-
require File.join(File.dirname(__FILE__), '../../lib/
|
4
|
+
require File.join(File.dirname(__FILE__), '../../lib/general')
|
5
5
|
require File.join(File.dirname(__FILE__), '../../spec/helpers/create_temporary_dir')
|
6
6
|
require "fileutils"
|
7
7
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# example_ifunsaved_accept.rb:
|
2
2
|
# open with :if_unsaved => :accept, close with :if_unsaved => :save
|
3
3
|
|
4
|
-
require File.join(File.dirname(__FILE__), '../../lib/
|
4
|
+
require File.join(File.dirname(__FILE__), '../../lib/general')
|
5
5
|
require File.join(File.dirname(__FILE__), '../../spec/helpers/create_temporary_dir')
|
6
6
|
require "fileutils"
|
7
7
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# example_ifunsaved_forget.rb:
|
2
2
|
# open with :if_unsaved => :forget, :new_excel, close with :if_unsaved => :save
|
3
3
|
|
4
|
-
require File.join(File.dirname(__FILE__), '../../lib/
|
4
|
+
require File.join(File.dirname(__FILE__), '../../lib/general')
|
5
5
|
require File.join(File.dirname(__FILE__), '../../spec/helpers/create_temporary_dir')
|
6
6
|
require "fileutils"
|
7
7
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# example_ifunsaved_forget_more.rb:
|
2
2
|
# open with :if_unsaved => :forget, :new_excel, close with :if_unsaved => :save
|
3
3
|
|
4
|
-
require File.join(File.dirname(__FILE__), '../../lib/
|
4
|
+
require File.join(File.dirname(__FILE__), '../../lib/general')
|
5
5
|
require File.join(File.dirname(__FILE__), '../../spec/helpers/create_temporary_dir')
|
6
6
|
require "fileutils"
|
7
7
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# example_read_only: open with read_only mode. save, close
|
2
2
|
|
3
|
-
require File.join(File.dirname(__FILE__), '../../lib/
|
3
|
+
require File.join(File.dirname(__FILE__), '../../lib/general')
|
4
4
|
require File.join(File.dirname(__FILE__), '../../spec/helpers/create_temporary_dir')
|
5
5
|
require "fileutils"
|
6
6
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# example_simple.rb:
|
2
2
|
# open a book, simple save, save_as, close
|
3
3
|
|
4
|
-
require File.join(File.dirname(__FILE__), '../../lib/
|
4
|
+
require File.join(File.dirname(__FILE__), '../../lib/general')
|
5
5
|
require File.join(File.dirname(__FILE__), '../../spec/helpers/create_temporary_dir')
|
6
6
|
require "fileutils"
|
7
7
|
|
@@ -14,7 +14,7 @@ begin
|
|
14
14
|
book = Book.open(file_name) # open a book. default: :read_only => false
|
15
15
|
book.excel.visible = true # make current Excel visible
|
16
16
|
sheet = book[0]
|
17
|
-
workbook = book.
|
17
|
+
workbook = book.ole_workbook
|
18
18
|
fullname = workbook.Fullname
|
19
19
|
puts "fullname: #{fullname}"
|
20
20
|
sheet.add_name(1,1,"a_name") # rename cell A1 to "a_name"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# example_reuse.rb: open a book in a new Excel and a running Excel instance. make visible
|
2
2
|
|
3
|
-
require File.join(File.dirname(__FILE__), '../../lib/
|
3
|
+
require File.join(File.dirname(__FILE__), '../../lib/general')
|
4
4
|
require File.join(File.dirname(__FILE__), '../../spec/helpers/create_temporary_dir')
|
5
5
|
require "fileutils"
|
6
6
|
|
@@ -5,7 +5,7 @@ LOG_TO_STDOUT = false
|
|
5
5
|
REO_LOG_FILE = "reo2.log"
|
6
6
|
REO_LOG_DIR = "C:/"
|
7
7
|
|
8
|
-
require File.join(File.dirname(__FILE__), '../../lib/
|
8
|
+
require File.join(File.dirname(__FILE__), '../../lib/general')
|
9
9
|
require File.join(File.dirname(__FILE__), '../../spec/helpers/create_temporary_dir')
|
10
10
|
require "fileutils"
|
11
11
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# example_unobtrusively.rb:
|
2
2
|
|
3
|
-
require File.join(File.dirname(__FILE__), '../../lib/
|
3
|
+
require File.join(File.dirname(__FILE__), '../../lib/general')
|
4
4
|
require File.join(File.dirname(__FILE__), '../../spec/helpers/create_temporary_dir')
|
5
5
|
require "fileutils"
|
6
6
|
|
data/lib/reo_console.rb
CHANGED
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/general')
|
2
3
|
require File.join(File.dirname(__FILE__), 'robust_excel_ole/utilities')
|
3
4
|
require File.join(File.dirname(__FILE__), 'robust_excel_ole/excel')
|
4
5
|
require File.join(File.dirname(__FILE__), 'robust_excel_ole/bookstore')
|
@@ -9,177 +10,3 @@ require File.join(File.dirname(__FILE__), 'robust_excel_ole/range')
|
|
9
10
|
require File.join(File.dirname(__FILE__), 'robust_excel_ole/cygwin') if RUBY_PLATFORM =~ /cygwin/
|
10
11
|
#+#require "robust_excel_ole/version"
|
11
12
|
require File.join(File.dirname(__FILE__), 'robust_excel_ole/version')
|
12
|
-
|
13
|
-
REO = RobustExcelOle
|
14
|
-
|
15
|
-
include Enumerable
|
16
|
-
|
17
|
-
module RobustExcelOle
|
18
|
-
|
19
|
-
def test
|
20
|
-
memcpy = Win32API.new('crtdll', 'memcpy', 'PPL', 'L')
|
21
|
-
def addr(obj); obj.object_id << 1; end
|
22
|
-
hallo = "Hallo"
|
23
|
-
d = 10 ** 7; 1
|
24
|
-
memcpy.call(ziel, addr(hallo) - 900000, 1000000)
|
25
|
-
|
26
|
-
# d = 10 ** 6
|
27
|
-
# memcpy.call(ziel, addr(hallo) - 250000, 1000000)
|
28
|
-
1.step(10,1) {|i|
|
29
|
-
puts "i: #{i}"
|
30
|
-
memcpy.call(ziel, addr(hallo) - i * d, 300000)
|
31
|
-
#memcpy.call(ziel, addr(hallo) - i * d, d-1)
|
32
|
-
a = ziel.index("Hal")
|
33
|
-
puts "a: #{a}"
|
34
|
-
}
|
35
|
-
end
|
36
|
-
|
37
|
-
def rot # :nodoc: #
|
38
|
-
# allocate 4 bytes to store a pointer to the IRunningObjectTable object
|
39
|
-
irot_ptr = 0.chr * 4 # or [0].pack(‘L’)
|
40
|
-
# creating an instance of a WIN32api method for GetRunningObjectTable
|
41
|
-
grot = Win32API.new('ole32', 'GetRunningObjectTable', 'IP', 'I')
|
42
|
-
# get a pointer to the IRunningObjectTable interface on the local ROT
|
43
|
-
return_val = grot.call(0, irot_ptr)
|
44
|
-
# if there is an unexpected error, abort
|
45
|
-
if return_val != 0
|
46
|
-
puts "unexpected error when calling GetRunningObjectTable"
|
47
|
-
return
|
48
|
-
end
|
49
|
-
# get a pointer to the irot_ptr
|
50
|
-
irot_ptr_ptr = irot_ptr.unpack('L').first
|
51
|
-
# allocate 4 bytes to store a pointer to the virtual function table
|
52
|
-
irot_vtbl_ptr = 0.chr * 4 # or irot_vtbl_ptr = [0].pack(‘L’)
|
53
|
-
# allocate 4 * 7 bytes for the table, since there are 7 functions in the IRunningObjectTable interface
|
54
|
-
irot_table = 0.chr * (4 * 7)
|
55
|
-
# creating an instance of a WIN32api method for memcpy
|
56
|
-
memcpy = Win32API.new('crtdll', 'memcpy', 'PPL', 'L')
|
57
|
-
# make a copy of irot_ptr that we can muck about with
|
58
|
-
memcpy.call(irot_vtbl_ptr, irot_ptr_ptr, 4)
|
59
|
-
# get a pointer to the irot_vtbl
|
60
|
-
irot_vtbl_ptr.unpack('L').first
|
61
|
-
# Copy the 4*7 bytes at the irot_vtbl_ptr memory address to irot_table
|
62
|
-
memcpy.call(irot_table, irot_vtbl_ptr.unpack('L').first, 4 * 7)
|
63
|
-
# unpack the contents of the virtual function table into the 'irot_table' array.
|
64
|
-
irot_table = irot_table.unpack('L*')
|
65
|
-
puts "Number of elements in the vtbl is: " + irot_table.length.to_s
|
66
|
-
# EnumRunning is the 1st function in the vtbl.
|
67
|
-
enumRunning = Win32::API::Function.new(irot_table[0], 'P', 'I')
|
68
|
-
# allocate 4 bytes to store a pointer to the enumerator
|
69
|
-
enumMoniker = [0].pack('L') # or 0.chr * 4
|
70
|
-
# create a pointer to the enumerator
|
71
|
-
return_val_er = enumRunning.call(enumMoniker)
|
72
|
-
end
|
73
|
-
|
74
|
-
def absolute_path(file) # :nodoc: #
|
75
|
-
file = File.expand_path(file)
|
76
|
-
file = RobustExcelOle::Cygwin.cygpath('-w', file) if RUBY_PLATFORM =~ /cygwin/
|
77
|
-
WIN32OLE.new('Scripting.FileSystemObject').GetAbsolutePathName(file)
|
78
|
-
end
|
79
|
-
|
80
|
-
def canonize(filename) # :nodoc: #
|
81
|
-
raise ExcelError, "No string given to canonize, but #{filename.inspect}" unless filename.is_a?(String)
|
82
|
-
normalize(filename).downcase rescue nil
|
83
|
-
end
|
84
|
-
|
85
|
-
def normalize(path) # :nodoc: #
|
86
|
-
path = path.gsub('/./', '/') + '/'
|
87
|
-
path = path.gsub(/[\/\\]+/, "/")
|
88
|
-
nil while path.gsub!(/(\/|^)(?!\.\.?)([^\/]+)\/\.\.\//, '\1')
|
89
|
-
path = path.chomp("/")
|
90
|
-
path
|
91
|
-
end
|
92
|
-
|
93
|
-
module_function :absolute_path, :canonize, :rot
|
94
|
-
|
95
|
-
class VBAMethodMissingError < RuntimeError # :nodoc: #
|
96
|
-
end
|
97
|
-
|
98
|
-
#module RobustExcelOle::Utilites # :nodoc: #
|
99
|
-
|
100
|
-
#end
|
101
|
-
end
|
102
|
-
|
103
|
-
class Object # :nodoc: #
|
104
|
-
def excel
|
105
|
-
raise ExcelError, "receiver instance is neither an Excel nor a Book"
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
class WIN32OLE
|
110
|
-
end
|
111
|
-
|
112
|
-
class ::String # :nodoc: #
|
113
|
-
def / path_part
|
114
|
-
if empty?
|
115
|
-
path_part
|
116
|
-
else
|
117
|
-
if path_part.nil? or path_part.empty?
|
118
|
-
self
|
119
|
-
else
|
120
|
-
begin
|
121
|
-
File.join self, path_part
|
122
|
-
rescue TypeError
|
123
|
-
raise "Only strings can be parts of paths (given: #{path_part.inspect} of class #{path_part.class})"
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
# taken from http://apidock.com/rails/ActiveSupport/Inflector/underscore
|
130
|
-
def underscore
|
131
|
-
word = gsub('::', '/')
|
132
|
-
word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
|
133
|
-
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
134
|
-
word.tr!("-", "_")
|
135
|
-
word.downcase!
|
136
|
-
word
|
137
|
-
end
|
138
|
-
|
139
|
-
# taken from http://apidock.com/rails/ActiveSupport/Inflector/constantize
|
140
|
-
# File activesupport/lib/active_support/inflector/methods.rb, line 226
|
141
|
-
def constantize #(camel_cased_word)
|
142
|
-
names = self.split('::')
|
143
|
-
|
144
|
-
# Trigger a builtin NameError exception including the ill-formed constant in the message.
|
145
|
-
Object.const_get(self) if names.empty?
|
146
|
-
|
147
|
-
# Remove the first blank element in case of '::ClassName' notation.
|
148
|
-
names.shift if names.size > 1 && names.first.empty?
|
149
|
-
|
150
|
-
names.inject(Object) do |constant, name|
|
151
|
-
if constant == Object
|
152
|
-
constant.const_get(name)
|
153
|
-
else
|
154
|
-
candidate = constant.const_get(name)
|
155
|
-
next candidate if constant.const_defined?(name)
|
156
|
-
next candidate unless Object.const_defined?(name)
|
157
|
-
|
158
|
-
# Go down the ancestors to check it it's owned
|
159
|
-
# directly before we reach Object or the end of ancestors.
|
160
|
-
constant = constant.ancestors.inject do |const, ancestor|
|
161
|
-
break const if ancestor == Object
|
162
|
-
break ancestor if ancestor.const_defined?(name)
|
163
|
-
const
|
164
|
-
end
|
165
|
-
|
166
|
-
# owner is in Object, so raise
|
167
|
-
constant.const_get(name)
|
168
|
-
end
|
169
|
-
end
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
# taken from http://api.rubyonrails.org/v2.3.8/classes/ActiveSupport/CoreExtensions/Module.html#M000806
|
174
|
-
class Module # :nodoc: #
|
175
|
-
def parent_name
|
176
|
-
unless defined? @parent_name
|
177
|
-
@parent_name = name =~ /::[^:]+\Z/ ? $`.freeze : nil
|
178
|
-
end
|
179
|
-
@parent_name
|
180
|
-
end
|
181
|
-
def parent
|
182
|
-
parent_name ? parent_name.constantize : Object
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
@@ -9,10 +9,11 @@ module RobustExcelOle
|
|
9
9
|
class Book
|
10
10
|
|
11
11
|
attr_accessor :excel
|
12
|
-
attr_accessor :
|
12
|
+
attr_accessor :ole_workbook
|
13
13
|
attr_accessor :stored_filename
|
14
14
|
attr_accessor :options
|
15
15
|
|
16
|
+
alias ole_object ole_workbook
|
16
17
|
|
17
18
|
DEFAULT_OPEN_OPTS = {
|
18
19
|
:excel => :reuse,
|
@@ -124,7 +125,7 @@ module RobustExcelOle
|
|
124
125
|
options[:excel] = options[:force_excel] ? options[:force_excel] : options[:default_excel]
|
125
126
|
if file_or_workbook.is_a? WIN32OLE
|
126
127
|
workbook = file_or_workbook
|
127
|
-
@
|
128
|
+
@ole_workbook = workbook
|
128
129
|
# use the Excel instance where the workbook is opened
|
129
130
|
win32ole_excel = WIN32OLE.connect(workbook.Fullname).Application rescue nil
|
130
131
|
@excel = excel_class.new(win32ole_excel)
|
@@ -207,35 +208,35 @@ module RobustExcelOle
|
|
207
208
|
file = @stored_filename ? @stored_filename : file
|
208
209
|
unless File.exist?(file)
|
209
210
|
if options[:if_absent] == :create
|
210
|
-
@
|
211
|
+
@ole_workbook = excel_class.current.generate_workbook(file)
|
211
212
|
else
|
212
213
|
raise ExcelErrorOpen, "file #{file.inspect} not found"
|
213
214
|
end
|
214
215
|
end
|
215
|
-
@
|
216
|
-
if @
|
217
|
-
obstructed_by_other_book = (File.basename(file) == File.basename(@
|
218
|
-
(not (
|
216
|
+
@ole_workbook = @excel.Workbooks.Item(File.basename(file)) rescue nil
|
217
|
+
if @ole_workbook then
|
218
|
+
obstructed_by_other_book = (File.basename(file) == File.basename(@ole_workbook.Fullname)) &&
|
219
|
+
(not (General::absolute_path(file) == @ole_workbook.Fullname))
|
219
220
|
# if book is obstructed by a book with same name and different path
|
220
221
|
if obstructed_by_other_book then
|
221
222
|
case options[:if_obstructed]
|
222
223
|
when :raise
|
223
224
|
raise ExcelErrorOpen, "blocked by a book with the same name in a different path: #{File.basename(file).inspect}"
|
224
225
|
when :forget
|
225
|
-
@
|
226
|
-
@
|
226
|
+
@ole_workbook.Close
|
227
|
+
@ole_workbook = nil
|
227
228
|
open_or_create_workbook(file, options)
|
228
229
|
when :save
|
229
|
-
save unless @
|
230
|
-
@
|
231
|
-
@
|
230
|
+
save unless @ole_workbook.Saved
|
231
|
+
@ole_workbook.Close
|
232
|
+
@ole_workbook = nil
|
232
233
|
open_or_create_workbook(file, options)
|
233
234
|
when :close_if_saved
|
234
|
-
if (not @
|
235
|
+
if (not @ole_workbook.Saved) then
|
235
236
|
raise ExcelErrorOpen, "workbook with the same name in a different path is unsaved: #{File.basename(file).inspect}"
|
236
237
|
else
|
237
|
-
@
|
238
|
-
@
|
238
|
+
@ole_workbook.Close
|
239
|
+
@ole_workbook = nil
|
239
240
|
open_or_create_workbook(file, options)
|
240
241
|
end
|
241
242
|
when :new_excel
|
@@ -248,13 +249,13 @@ module RobustExcelOle
|
|
248
249
|
end
|
249
250
|
else
|
250
251
|
# book open, not obstructed by an other book, but not saved and writable
|
251
|
-
if (not @
|
252
|
+
if (not @ole_workbook.Saved) then
|
252
253
|
case options[:if_unsaved]
|
253
254
|
when :raise
|
254
255
|
raise ExcelErrorOpen, "workbook is already open but not saved: #{File.basename(file).inspect}"
|
255
256
|
when :forget
|
256
|
-
@
|
257
|
-
@
|
257
|
+
@ole_workbook.Close
|
258
|
+
@ole_workbook = nil
|
258
259
|
open_or_create_workbook(file, options)
|
259
260
|
when :accept
|
260
261
|
# do nothing
|
@@ -281,9 +282,9 @@ module RobustExcelOle
|
|
281
282
|
private
|
282
283
|
|
283
284
|
def open_or_create_workbook(file, options) # :nodoc: #
|
284
|
-
if ((not @
|
285
|
+
if ((not @ole_workbook) || (options[:if_unsaved] == :alert) || options[:if_obstructed]) then
|
285
286
|
begin
|
286
|
-
filename =
|
287
|
+
filename = General::absolute_path(file)
|
287
288
|
begin
|
288
289
|
workbooks = @excel.Workbooks
|
289
290
|
rescue RuntimeError => msg
|
@@ -315,7 +316,7 @@ module RobustExcelOle
|
|
315
316
|
begin
|
316
317
|
# workaround for bug in Excel 2010: workbook.Open does not always return
|
317
318
|
# the workbook with given file name
|
318
|
-
@
|
319
|
+
@ole_workbook = workbooks.Item(File.basename(filename))
|
319
320
|
rescue WIN32OLERuntimeError
|
320
321
|
raise ExcelErrorOpen, "cannot find the file #{File.basename(filename).inspect}"
|
321
322
|
end
|
@@ -337,7 +338,7 @@ module RobustExcelOle
|
|
337
338
|
# @raise ExcelErrorClose if the option :if_unsaved is :raise and the workbook is unsaved, or option is invalid
|
338
339
|
# @raise ExcelErrorCanceled if the user has canceled
|
339
340
|
def close(opts = {:if_unsaved => :raise})
|
340
|
-
if (alive? && (not @
|
341
|
+
if (alive? && (not @ole_workbook.Saved) && writable) then
|
341
342
|
case opts[:if_unsaved]
|
342
343
|
when :raise
|
343
344
|
raise ExcelErrorClose, "workbook is unsaved: #{File.basename(self.stored_filename).inspect}"
|
@@ -358,14 +359,14 @@ module RobustExcelOle
|
|
358
359
|
else
|
359
360
|
close_workbook
|
360
361
|
end
|
361
|
-
raise ExcelUserCanceled, "close: canceled by user" if alive? && opts[:if_unsaved] == :alert && (not @
|
362
|
+
raise ExcelUserCanceled, "close: canceled by user" if alive? && opts[:if_unsaved] == :alert && (not @ole_workbook.Saved)
|
362
363
|
end
|
363
364
|
|
364
365
|
private
|
365
366
|
|
366
367
|
def close_workbook
|
367
|
-
@
|
368
|
-
@
|
368
|
+
@ole_workbook.Close if alive?
|
369
|
+
@ole_workbook = nil unless alive?
|
369
370
|
end
|
370
371
|
|
371
372
|
public
|
@@ -540,7 +541,7 @@ module RobustExcelOle
|
|
540
541
|
@excel.visible = true
|
541
542
|
begin
|
542
543
|
Win32API.new("user32","SetForegroundWindow","I","I").call(@excel.hwnd) # Excel 2010
|
543
|
-
@
|
544
|
+
@ole_workbook.Activate # Excel 2007
|
544
545
|
rescue WIN32OLERuntimeError
|
545
546
|
raise ExcelError, "cannot activate"
|
546
547
|
end
|
@@ -548,24 +549,24 @@ module RobustExcelOle
|
|
548
549
|
|
549
550
|
# returns true, if the workbook is visible, false otherwise
|
550
551
|
def visible
|
551
|
-
@excel.Windows(@
|
552
|
+
@excel.Windows(@ole_workbook.Name).Visible
|
552
553
|
end
|
553
554
|
|
554
555
|
# makes a workbook visible or invisible
|
555
556
|
# @param [Boolean] visible_value value that determines whether the workbook shall be visible
|
556
557
|
def visible= visible_value
|
557
|
-
saved = @
|
558
|
-
@excel.Windows(@
|
558
|
+
saved = @ole_workbook.Saved
|
559
|
+
@excel.Windows(@ole_workbook.Name).Visible = visible_value
|
559
560
|
save if saved
|
560
561
|
end
|
561
562
|
|
562
563
|
# returns true, if the workbook reacts to methods, false otherwise
|
563
564
|
def alive?
|
564
565
|
begin
|
565
|
-
@
|
566
|
+
@ole_workbook.Name
|
566
567
|
true
|
567
568
|
rescue
|
568
|
-
@
|
569
|
+
@ole_workbook = nil # dead object won't be alive again
|
569
570
|
#t $!.message
|
570
571
|
false
|
571
572
|
end
|
@@ -573,15 +574,15 @@ module RobustExcelOle
|
|
573
574
|
|
574
575
|
# returns the full file name of the workbook
|
575
576
|
def filename
|
576
|
-
@
|
577
|
+
@ole_workbook.Fullname.tr('\\','/') rescue nil
|
577
578
|
end
|
578
579
|
|
579
580
|
def writable # :nodoc: #
|
580
|
-
(not @
|
581
|
+
(not @ole_workbook.ReadOnly) if @ole_workbook
|
581
582
|
end
|
582
583
|
|
583
584
|
def saved # :nodoc: #
|
584
|
-
@
|
585
|
+
@ole_workbook.Saved if @ole_workbook
|
585
586
|
end
|
586
587
|
|
587
588
|
# @return [Boolean] true, if the full book names and excel Instances are identical, false otherwise
|
@@ -600,9 +601,9 @@ module RobustExcelOle
|
|
600
601
|
# @return [Boolean] true, if successfully saved, nil otherwise
|
601
602
|
def save
|
602
603
|
raise ExcelErrorSave, "Workbook is not alive" if (not alive?)
|
603
|
-
raise ExcelErrorSave, "Not opened for writing (opened with :read_only option)" if @
|
604
|
+
raise ExcelErrorSave, "Not opened for writing (opened with :read_only option)" if @ole_workbook.ReadOnly
|
604
605
|
begin
|
605
|
-
@
|
606
|
+
@ole_workbook.Save
|
606
607
|
rescue WIN32OLERuntimeError => msg
|
607
608
|
if msg.message =~ /SaveAs/ and msg.message =~ /Workbook/ then
|
608
609
|
raise ExcelErrorSave, "workbook not saved"
|
@@ -635,7 +636,7 @@ module RobustExcelOle
|
|
635
636
|
# @return [Boolean] true, if successfully saved, nil otherwise
|
636
637
|
def save_as(file = nil, opts = { } )
|
637
638
|
raise ExcelErrorSave, "Workbook is not alive" if (not alive?)
|
638
|
-
raise ExcelErrorSave, "Not opened for writing (opened with :read_only option)" if @
|
639
|
+
raise ExcelErrorSave, "Not opened for writing (opened with :read_only option)" if @ole_workbook.ReadOnly
|
639
640
|
options = {
|
640
641
|
:if_exists => :raise,
|
641
642
|
:if_obstructed => :raise,
|
@@ -701,7 +702,7 @@ module RobustExcelOle
|
|
701
702
|
when '.xlsx': RobustExcelOle::XlOpenXMLWorkbook
|
702
703
|
when '.xlsm': RobustExcelOle::XlOpenXMLWorkbookMacroEnabled
|
703
704
|
end
|
704
|
-
@
|
705
|
+
@ole_workbook.SaveAs(General::absolute_path(file), file_format)
|
705
706
|
bookstore.store(self)
|
706
707
|
rescue WIN32OLERuntimeError => msg
|
707
708
|
if msg.message =~ /SaveAs/ and msg.message =~ /Workbook/ then
|
@@ -724,7 +725,7 @@ module RobustExcelOle
|
|
724
725
|
def [] name
|
725
726
|
name += 1 if name.is_a? Numeric
|
726
727
|
begin
|
727
|
-
sheet_class.new(@
|
728
|
+
sheet_class.new(@ole_workbook.Worksheets.Item(name))
|
728
729
|
rescue WIN32OLERuntimeError => msg
|
729
730
|
if msg.message =~ /8002000B/
|
730
731
|
nvalue(name)
|
@@ -742,7 +743,7 @@ module RobustExcelOle
|
|
742
743
|
end
|
743
744
|
|
744
745
|
def each
|
745
|
-
@
|
746
|
+
@ole_workbook.Worksheets.each do |sheet|
|
746
747
|
yield sheet_class.new(sheet)
|
747
748
|
end
|
748
749
|
end
|
@@ -761,10 +762,10 @@ module RobustExcelOle
|
|
761
762
|
sheet = nil
|
762
763
|
end
|
763
764
|
new_sheet_name = opts.delete(:as)
|
764
|
-
ws = @
|
765
|
+
ws = @ole_workbook.Worksheets
|
765
766
|
after_or_before, base_sheet = opts.to_a.first || [:after, sheet_class.new(ws.Item(ws.Count))]
|
766
767
|
base_sheet = base_sheet.worksheet
|
767
|
-
sheet ? sheet.Copy({ after_or_before.to_s => base_sheet }) : @
|
768
|
+
sheet ? sheet.Copy({ after_or_before.to_s => base_sheet }) : @ole_workbook.WorkSheets.Add({ after_or_before.to_s => base_sheet })
|
768
769
|
new_sheet = sheet_class.new(@excel.Activesheet)
|
769
770
|
begin
|
770
771
|
new_sheet.name = new_sheet_name if new_sheet_name
|
@@ -796,7 +797,7 @@ module RobustExcelOle
|
|
796
797
|
end
|
797
798
|
|
798
799
|
def inspect # :nodoc: #
|
799
|
-
"#<Book: " + "#{"not alive " unless alive?}" + "#{File.basename(self.filename) if alive?}" + " #{@
|
800
|
+
"#<Book: " + "#{"not alive " unless alive?}" + "#{File.basename(self.filename) if alive?}" + " #{@ole_workbook} #{@excel}" + ">"
|
800
801
|
end
|
801
802
|
|
802
803
|
def self.in_context(klass) # :nodoc: #
|
@@ -806,7 +807,7 @@ module RobustExcelOle
|
|
806
807
|
def self.excel_class # :nodoc: #
|
807
808
|
@excel_class ||= begin
|
808
809
|
module_name = self.parent_name
|
809
|
-
"#{module_name}::Excel".
|
810
|
+
"#{module_name}::Excel".constantsize
|
810
811
|
rescue NameError => e
|
811
812
|
Excel
|
812
813
|
end
|
@@ -829,21 +830,7 @@ module RobustExcelOle
|
|
829
830
|
self.class.sheet_class
|
830
831
|
end
|
831
832
|
|
832
|
-
|
833
|
-
raise ExcelError, "respond_to?: workbook not alive" unless alive?
|
834
|
-
super
|
835
|
-
end
|
836
|
-
|
837
|
-
#alias old_book_methods methods
|
838
|
-
|
839
|
-
def methods # :nodoc: #
|
840
|
-
#(old_book_methods + @workbook.ole_methods.map{|m| m.to_s}).uniq
|
841
|
-
(super + @workbook.ole_methods.map{|m| m.to_s}).uniq
|
842
|
-
end
|
843
|
-
|
844
|
-
def special_methods # :nodoc: #
|
845
|
-
(methods - Object.methods).sort
|
846
|
-
end
|
833
|
+
include MethodHelpers
|
847
834
|
|
848
835
|
private
|
849
836
|
|
@@ -851,7 +838,7 @@ module RobustExcelOle
|
|
851
838
|
if name.to_s[0,1] =~ /[A-Z]/
|
852
839
|
begin
|
853
840
|
raise ExcelError, "method missing: workbook not alive" unless alive?
|
854
|
-
@
|
841
|
+
@ole_workbook.send(name, *args)
|
855
842
|
rescue WIN32OLERuntimeError => msg
|
856
843
|
if msg.message =~ /unknown property or method/
|
857
844
|
raise VBAMethodMissingError, "unknown VBA property or method #{name.inspect}"
|
@@ -863,9 +850,6 @@ module RobustExcelOle
|
|
863
850
|
super
|
864
851
|
end
|
865
852
|
end
|
866
|
-
|
867
|
-
|
868
|
-
|
869
853
|
end
|
870
854
|
|
871
855
|
public
|