robust_excel_ole 0.3.8 → 0.3.9
Sign up to get free protection for your applications and to get access to all the features.
- 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
|