robust_excel_ole 1.31 → 1.32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Changelog +20 -1
- data/README.rdoc +118 -18
- data/___dummy_workbook.xls +0 -0
- data/benchmarking/creek_example.rb +1 -1
- data/benchmarking/roo_example.rb +1 -1
- data/benchmarking/simple_xlsx_reader_example.rb +1 -1
- data/benchmarking/spreadsheet_example.rb +1 -1
- data/docs/README_excel.rdoc +16 -24
- data/docs/README_listobjects.rdoc +176 -0
- data/docs/README_open.rdoc +12 -12
- data/docs/README_ranges.rdoc +72 -55
- data/docs/README_save_close.rdoc +3 -3
- data/docs/README_sheet.rdoc +18 -13
- data/examples/example_ruby_library.rb +2 -2
- data/examples/introductory_examples/example_range.rb +2 -2
- data/examples/modifying_sheets/example_access_sheets_and_cells.rb +6 -6
- data/examples/modifying_sheets/example_add_names.rb +1 -1
- data/examples/modifying_sheets/example_concating.rb +1 -1
- data/examples/modifying_sheets/example_copying.rb +2 -2
- data/examples/modifying_sheets/example_listobjects.rb +86 -0
- data/examples/modifying_sheets/example_naming.rb +1 -1
- data/examples/modifying_sheets/example_ranges.rb +1 -1
- data/examples/open_save_close/example_control_to_excel.rb +1 -1
- data/examples/open_save_close/example_if_obstructed_closeifsaved.rb +1 -1
- data/examples/open_save_close/example_if_obstructed_save.rb +3 -3
- data/examples/open_save_close/example_if_unsaved_accept.rb +1 -1
- data/examples/open_save_close/example_if_unsaved_forget.rb +3 -3
- data/examples/open_save_close/example_if_unsaved_forget_more.rb +4 -4
- data/examples/open_save_close/example_read_only.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/address_tool.rb +54 -44
- data/lib/robust_excel_ole/base.rb +4 -6
- data/lib/robust_excel_ole/bookstore.rb +2 -16
- data/lib/robust_excel_ole/cell.rb +16 -21
- data/lib/robust_excel_ole/excel.rb +131 -186
- data/lib/robust_excel_ole/general.rb +82 -55
- data/lib/robust_excel_ole/list_object.rb +182 -109
- data/lib/robust_excel_ole/list_row.rb +65 -38
- data/lib/robust_excel_ole/range.rb +125 -93
- data/lib/robust_excel_ole/range_owners.rb +52 -66
- data/lib/robust_excel_ole/version.rb +1 -1
- data/lib/robust_excel_ole/workbook.rb +168 -176
- data/lib/robust_excel_ole/worksheet.rb +177 -141
- data/robust_excel_ole.gemspec +4 -3
- data/spec/bookstore_spec.rb +2 -3
- data/spec/cell_spec.rb +9 -9
- data/spec/data/more_data/workbook.xls +0 -0
- data/spec/excel_spec.rb +132 -85
- data/spec/general_spec.rb +47 -15
- data/spec/list_object_spec.rb +258 -145
- data/spec/list_row_spec.rb +218 -0
- data/spec/range_spec.rb +76 -29
- data/spec/spec_helper.rb +15 -1
- data/spec/workbook_spec.rb +75 -34
- data/spec/workbook_specs/workbook_all_spec.rb +2 -1
- data/spec/workbook_specs/workbook_misc_spec.rb +20 -13
- data/spec/workbook_specs/workbook_open_spec.rb +47 -45
- data/spec/workbook_specs/workbook_save_spec.rb +21 -22
- data/spec/workbook_specs/workbook_sheet_spec.rb +3 -3
- data/spec/workbook_specs/workbook_unobtr_spec.rb +303 -303
- data/spec/worksheet_spec.rb +522 -318
- metadata +37 -2
@@ -11,6 +11,8 @@ module RobustExcelOle
|
|
11
11
|
# worksheet: see https://github.com/Thomas008/robust_excel_ole/blob/master/lib/robust_excel_ole/worksheet.rb
|
12
12
|
class Worksheet < RangeOwners
|
13
13
|
|
14
|
+
include Enumerable
|
15
|
+
|
14
16
|
using ToReoRefinement
|
15
17
|
|
16
18
|
attr_reader :ole_worksheet
|
@@ -49,9 +51,9 @@ module RobustExcelOle
|
|
49
51
|
# sheet name
|
50
52
|
# @returns name of the sheet
|
51
53
|
def name
|
52
|
-
@ole_worksheet.Name
|
54
|
+
@ole_worksheet.Name.encode('utf-8')
|
53
55
|
rescue
|
54
|
-
raise WorksheetREOError, "name could not be determined"
|
56
|
+
raise WorksheetREOError, "name could not be determined\n#{$!.message}"
|
55
57
|
end
|
56
58
|
|
57
59
|
# sets sheet name
|
@@ -66,49 +68,69 @@ module RobustExcelOle
|
|
66
68
|
end
|
67
69
|
end
|
68
70
|
|
69
|
-
#
|
70
|
-
# @params
|
71
|
-
# @returns
|
72
|
-
def []
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
71
|
+
# value of a range given its defined name or address
|
72
|
+
# @params [Variant] defined name or address
|
73
|
+
# @returns [Variant] value (contents) of the range
|
74
|
+
def [](name_or_address, address2 = :__not_provided)
|
75
|
+
range(name_or_address, address2).value
|
76
|
+
end
|
77
|
+
|
78
|
+
# sets the value of a range given its defined name or address, and the value
|
79
|
+
# @params [Variant] defined name or address of the range
|
80
|
+
# @params [Variant] value (contents) of the range
|
81
|
+
# @returns [Variant] value (contents) of the range
|
82
|
+
def []=(name_or_address, value_or_address2, remaining_arg = :__not_provided)
|
83
|
+
if remaining_arg != :__not_provided
|
84
|
+
name_or_address, value = [name_or_address, value_or_address2], remaining_arg
|
82
85
|
else
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
86
|
+
value = value_or_address2
|
87
|
+
end
|
88
|
+
begin
|
89
|
+
range(name_or_address).value = value
|
90
|
+
rescue #WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException
|
91
|
+
raise RangeNotEvaluatable, "cannot assign value to range with name or address #{name_or_address.inspect}\n#{$!.message}"
|
89
92
|
end
|
90
93
|
end
|
91
94
|
|
92
|
-
#
|
93
|
-
# @params
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
95
|
+
# a range given a defined name or address
|
96
|
+
# @params [Variant] defined name or address
|
97
|
+
# @return [Range] a range
|
98
|
+
def range(name_or_address, address2 = :__not_provided)
|
99
|
+
if name_or_address.respond_to?(:gsub) && address2 == :__not_provided
|
100
|
+
name = name_or_address
|
101
|
+
range = get_name_object(name).RefersToRange rescue nil
|
102
|
+
end
|
103
|
+
unless range
|
104
|
+
address = normalize_address(name_or_address, address2)
|
105
|
+
workbook.retain_saved do
|
103
106
|
begin
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
+
self.Names.Add('__dummy001',nil,true,nil,nil,nil,nil,nil,nil,'=' + address_tool.as_r1c1(address))
|
108
|
+
range = get_name_object('__dummy001').RefersToRange
|
109
|
+
self.Names.Item('__dummy001').Delete
|
110
|
+
rescue
|
111
|
+
address2_string = (address2.nil? || address2 == :__not_provided) ? "" : ", #{address2.inspect}"
|
112
|
+
raise RangeNotCreated, "cannot find name or address #{name_or_address.inspect}#{address2_string})"
|
107
113
|
end
|
108
114
|
end
|
109
115
|
end
|
116
|
+
range.to_reo
|
117
|
+
end
|
118
|
+
|
119
|
+
private
|
120
|
+
|
121
|
+
def normalize_address(address, address2)
|
122
|
+
address = [address,address2] unless address2 == :__not_provided
|
123
|
+
address = if address.is_a?(Integer) || address.is_a?(::Range)
|
124
|
+
[address, nil]
|
125
|
+
elsif address.is_a?(Array) && address.size == 1 && (address.first.is_a?(Integer) || address.first.is_a?(::Range))
|
126
|
+
[address.first, nil]
|
127
|
+
else
|
128
|
+
address
|
129
|
+
end
|
110
130
|
end
|
111
131
|
|
132
|
+
public
|
133
|
+
|
112
134
|
# returns the contents of a range with a locally defined name
|
113
135
|
# evaluates the formula if the contents is a formula
|
114
136
|
# if the name could not be found or the range or value could not be determined,
|
@@ -117,7 +139,7 @@ module RobustExcelOle
|
|
117
139
|
# @param [Hash] opts the options
|
118
140
|
# @option opts [Symbol] :default the default value that is provided if no contents could be returned
|
119
141
|
# @return [Variant] the contents of a range with given name
|
120
|
-
def namevalue(name, opts = { :
|
142
|
+
def namevalue(name, opts = { default: :__not_provided })
|
121
143
|
begin
|
122
144
|
ole_range = self.Range(name)
|
123
145
|
rescue # WIN32OLERuntimeError, VBAMethodMissingError, Java::OrgRacobCom::ComFailException
|
@@ -135,11 +157,11 @@ module RobustExcelOle
|
|
135
157
|
end
|
136
158
|
rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException
|
137
159
|
return opts[:default] unless opts[:default] == :__not_provided
|
138
|
-
raise RangeNotEvaluatable, "cannot determine value of range named #{name.inspect} in #{self.inspect}"
|
160
|
+
raise RangeNotEvaluatable, "cannot determine value of range named #{name.inspect} in #{self.inspect}\n#{$!.message}"
|
139
161
|
end
|
140
162
|
if value == -2146828288 + RobustExcelOle::XlErrName
|
141
163
|
return opts[:default] unless opts[:default] == __not_provided
|
142
|
-
raise RangeNotEvaluatable, "cannot evaluate range named #{name.inspect} in #{File.basename(workbook.stored_filename).inspect rescue nil}"
|
164
|
+
raise RangeNotEvaluatable, "cannot evaluate range named #{name.inspect} in #{File.basename(workbook.stored_filename).inspect rescue nil}\n#{$!.message}"
|
143
165
|
end
|
144
166
|
return opts[:default] unless (opts[:default] == :__not_provided) || value.nil?
|
145
167
|
value
|
@@ -164,25 +186,23 @@ module RobustExcelOle
|
|
164
186
|
row, col = address_tool.as_integer_ranges(address_r1c1)
|
165
187
|
row.each_with_index do |r,i|
|
166
188
|
col.each_with_index do |c,j|
|
167
|
-
ole_range.Cells(i+1,j+1).Value = (value.respond_to?(:
|
189
|
+
ole_range.Cells(i+1,j+1).Value = (value.respond_to?(:pop) ? value[i][j] : value)
|
168
190
|
end
|
169
191
|
end
|
170
192
|
end
|
171
193
|
value
|
172
194
|
rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException
|
173
|
-
raise RangeNotEvaluatable, "cannot assign value to range named #{name.inspect} in #{self.inspect}"
|
195
|
+
raise RangeNotEvaluatable, "cannot assign value to range named #{name.inspect} in #{self.inspect}\n#{$!.message}"
|
174
196
|
end
|
175
197
|
end
|
176
198
|
|
177
199
|
# value of a cell, if row and column are given
|
178
200
|
# @params row and column
|
179
201
|
# @returns value of the cell
|
180
|
-
def cellval(x,y)
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
raise RangeNotEvaluatable, "cannot read cell (#{x.inspect},#{y.inspect})"
|
185
|
-
end
|
202
|
+
def cellval(x,y) # :deprecated :#
|
203
|
+
@ole_worksheet.Cells.Item(x, y).Value
|
204
|
+
rescue
|
205
|
+
raise RangeNotEvaluatable, "cannot read cell (#{x.inspect},#{y.inspect})\n#{$!.message}"
|
186
206
|
end
|
187
207
|
|
188
208
|
# sets the value of a cell, if row, column and color of the cell are given
|
@@ -193,73 +213,93 @@ module RobustExcelOle
|
|
193
213
|
cell.Interior.ColorIndex = opts[:color] unless opts[:color].nil?
|
194
214
|
cell.Value = value
|
195
215
|
rescue # WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException
|
196
|
-
raise RangeNotEvaluatable, "cannot assign value #{value.inspect} to cell (#{y.inspect},#{x.inspect})"
|
216
|
+
raise RangeNotEvaluatable, "cannot assign value #{value.inspect} to cell (#{y.inspect},#{x.inspect})\n#{$!.message}"
|
197
217
|
end
|
198
218
|
|
199
|
-
#
|
219
|
+
# @return [Array] a 2-dimensional array that contains the values in each row of the used range
|
200
220
|
def values
|
201
221
|
@ole_worksheet.UsedRange.Value
|
202
222
|
end
|
203
223
|
|
204
|
-
#
|
224
|
+
# @return [Enumerator] traversing the rows values
|
205
225
|
def each
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
|
-
def each_with_index(offset = 0)
|
214
|
-
i = offset
|
215
|
-
each_row do |row_range|
|
216
|
-
row_range.each do |cell|
|
217
|
-
yield cell, i
|
218
|
-
i += 1
|
226
|
+
if block_given?
|
227
|
+
@ole_worksheet.UsedRange.Rows.lazy.each do |ole_row|
|
228
|
+
row_value = ole_row.Value
|
229
|
+
yield (row_value.nil? ? [] : row_value.first)
|
219
230
|
end
|
231
|
+
else
|
232
|
+
to_enum(:each).lazy
|
220
233
|
end
|
221
234
|
end
|
222
235
|
|
223
|
-
#
|
236
|
+
# @return [Enumerator] traversing the rows
|
224
237
|
def each_row(offset = 0)
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
238
|
+
if block_given?
|
239
|
+
offset += 1
|
240
|
+
1.upto(@end_row) do |row|
|
241
|
+
next if row < offset
|
242
|
+
yield RobustExcelOle::Range.new(@ole_worksheet.Range(@ole_worksheet.Cells(row, 1), @ole_worksheet.Cells(row, @end_column)), self)
|
243
|
+
end
|
244
|
+
else
|
245
|
+
to_enum(:each_row).lazy
|
229
246
|
end
|
230
247
|
end
|
231
248
|
|
232
|
-
def each_row_with_index(offset = 0)
|
249
|
+
def each_row_with_index(offset = 0) # :nodoc: # # :deprecated :#
|
233
250
|
each_row(offset) do |row_range|
|
234
251
|
yield RobustExcelOle::Range.new(row_range, self), (row_range.Row - 1 - offset)
|
235
252
|
end
|
236
253
|
end
|
237
254
|
|
238
|
-
#
|
255
|
+
# @return [Enumerator] traversing the columns
|
239
256
|
def each_column(offset = 0)
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
257
|
+
if block_given?
|
258
|
+
offset += 1
|
259
|
+
1.upto(@end_column) do |column|
|
260
|
+
next if column < offset
|
261
|
+
yield RobustExcelOle::Range.new(@ole_worksheet.Range(@ole_worksheet.Cells(1, column), @ole_worksheet.Cells(@end_row, column)), self)
|
262
|
+
end
|
263
|
+
else
|
264
|
+
to_enum(:each_column).lazy
|
244
265
|
end
|
245
266
|
end
|
246
267
|
|
247
|
-
def each_column_with_index(offset = 0)
|
268
|
+
def each_column_with_index(offset = 0) # :nodoc: # # :deprecated :#
|
248
269
|
each_column(offset) do |column_range|
|
249
270
|
yield RobustExcelOle::Range.new(column_range, self), (column_range.Column - 1 - offset)
|
250
271
|
end
|
251
272
|
end
|
252
273
|
|
274
|
+
# @return [Enumerator] traversing the cells
|
275
|
+
def each_cell
|
276
|
+
if block_given?
|
277
|
+
each_row do |row_range|
|
278
|
+
row_range.lazy.each do |cell|
|
279
|
+
yield cell
|
280
|
+
end
|
281
|
+
end
|
282
|
+
else
|
283
|
+
to_enum(:each_cell).lazy
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
def each_cell_with_index(offset = 0) # :nodoc: # # :deprecated :#
|
288
|
+
i = offset
|
289
|
+
each_row do |row_range|
|
290
|
+
row_range.each do |cell|
|
291
|
+
yield cell, i
|
292
|
+
i += 1
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
253
297
|
def each_rowvalue # :deprecated: #
|
254
298
|
values.each do |row_values|
|
255
299
|
yield row_values
|
256
300
|
end
|
257
301
|
end
|
258
302
|
|
259
|
-
def each_value # :deprecated: #
|
260
|
-
each_rowvalue
|
261
|
-
end
|
262
|
-
|
263
303
|
def each_rowvalue_with_index(offset = 0) # :deprecated: #
|
264
304
|
i = offset
|
265
305
|
values.each do |row_values|
|
@@ -268,6 +308,8 @@ module RobustExcelOle
|
|
268
308
|
end
|
269
309
|
end
|
270
310
|
|
311
|
+
alias each_value each_rowvalue # :deprecated: #
|
312
|
+
|
271
313
|
def row_range(row, integer_range = nil)
|
272
314
|
integer_range ||= 1..@end_column
|
273
315
|
RobustExcelOle::Range.new(@ole_worksheet.Range(@ole_worksheet.Cells(row, integer_range.min), @ole_worksheet.Cells(row, integer_range.max)), self)
|
@@ -280,44 +322,17 @@ module RobustExcelOle
|
|
280
322
|
|
281
323
|
def == other_worksheet
|
282
324
|
other_worksheet.is_a?(Worksheet) &&
|
283
|
-
|
284
|
-
|
285
|
-
end
|
286
|
-
|
287
|
-
# creates a range from a given defined name or address
|
288
|
-
# @params [Variant] defined name or address
|
289
|
-
# @return [Range] a range
|
290
|
-
def range(name_or_address, address2 = :__not_provided)
|
291
|
-
if name_or_address.respond_to?(:gsub) && address2 == :__not_provided
|
292
|
-
name = name_or_address
|
293
|
-
range = RobustExcelOle::Range.new(name_object(name).RefersToRange, self) rescue nil
|
294
|
-
end
|
295
|
-
unless range
|
296
|
-
address = name_or_address
|
297
|
-
address = [name_or_address,address2] unless address2 == :__not_provided
|
298
|
-
workbook.retain_saved do
|
299
|
-
begin
|
300
|
-
self.Names.Add('__dummy001',nil,true,nil,nil,nil,nil,nil,nil,'=' + address_tool.as_r1c1(address))
|
301
|
-
range = RobustExcelOle::Range.new(name_object('__dummy001').RefersToRange, self)
|
302
|
-
self.Names.Item('__dummy001').Delete
|
303
|
-
rescue
|
304
|
-
address2_string = address2.nil? ? "" : ", #{address2.inspect}"
|
305
|
-
raise RangeNotCreated, "cannot create range (#{name_or_address.inspect}#{address2_string})"
|
306
|
-
end
|
307
|
-
end
|
308
|
-
end
|
309
|
-
range
|
325
|
+
self.workbook == other_worksheet.workbook &&
|
326
|
+
self.Name == other_worksheet.Name
|
310
327
|
end
|
311
328
|
|
329
|
+
|
312
330
|
# @params [Variant] table (listobject) name or number
|
313
331
|
# @return [ListObject] a table (listobject)
|
314
332
|
def table(number_or_name)
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
raise WorksheetREOError, "table #{number_or_name} not found"
|
319
|
-
end
|
320
|
-
ListObject.new(ole_listobject)
|
333
|
+
listobject_class.new(@ole_worksheet.ListObjects.Item(number_or_name))
|
334
|
+
rescue
|
335
|
+
raise WorksheetREOError, "table #{number_or_name} not found"
|
321
336
|
end
|
322
337
|
|
323
338
|
# @private
|
@@ -330,6 +345,29 @@ module RobustExcelOle
|
|
330
345
|
false
|
331
346
|
end
|
332
347
|
|
348
|
+
# last_row, last_column:
|
349
|
+
# the last row and last column in a worksheet can be determined with help of
|
350
|
+
# UsedRange.SpecialCells and UsedRange.Rows/Columns
|
351
|
+
# both values can differ in certain cases:
|
352
|
+
# - if the worksheet contains a table, then UsedRange starts at the table, not in the first cell
|
353
|
+
# therefore we use SpecialCells.
|
354
|
+
# - if the worksheet contains merged cells, then SpecialCells considers the merged cells only,
|
355
|
+
# therefor we use UsedRange here.
|
356
|
+
|
357
|
+
# @private
|
358
|
+
def last_row
|
359
|
+
special_last_row = @ole_worksheet.UsedRange.SpecialCells(RobustExcelOle::XlLastCell).Row
|
360
|
+
used_last_row = @ole_worksheet.UsedRange.Rows.Count
|
361
|
+
[special_last_row, used_last_row].max
|
362
|
+
end
|
363
|
+
|
364
|
+
# @private
|
365
|
+
def last_column
|
366
|
+
special_last_column = @ole_worksheet.UsedRange.SpecialCells(RobustExcelOle::XlLastCell).Column
|
367
|
+
used_last_column = @ole_worksheet.UsedRange.Columns.Count
|
368
|
+
[special_last_column, used_last_column].max
|
369
|
+
end
|
370
|
+
|
333
371
|
using ParentRefinement
|
334
372
|
using StringRefinement
|
335
373
|
|
@@ -348,9 +386,24 @@ module RobustExcelOle
|
|
348
386
|
self.class.workbook_class
|
349
387
|
end
|
350
388
|
|
389
|
+
# @private
|
390
|
+
def self.listobject_class
|
391
|
+
@listobject_class ||= begin
|
392
|
+
module_name = self.parent_name
|
393
|
+
"#{module_name}::ListObject".constantize
|
394
|
+
rescue NameError => e
|
395
|
+
ListObject
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
# @private
|
400
|
+
def listobject_class
|
401
|
+
self.class.listobject_class
|
402
|
+
end
|
403
|
+
|
351
404
|
# @private
|
352
405
|
def to_s
|
353
|
-
|
406
|
+
"#<Worksheet: #{(workbook.nil? ? "not alive " : (name + ' ' + File.basename(workbook.stored_filename)))}>"
|
354
407
|
end
|
355
408
|
|
356
409
|
# @private
|
@@ -363,39 +416,22 @@ module RobustExcelOle
|
|
363
416
|
private
|
364
417
|
|
365
418
|
def method_missing(name, *args)
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
end
|
373
|
-
else
|
374
|
-
begin
|
375
|
-
@ole_worksheet.send(name, *args)
|
376
|
-
rescue NoMethodError
|
377
|
-
raise VBAMethodMissingError, "unknown VBA property or method #{name.inspect}"
|
378
|
-
end
|
419
|
+
super unless name.to_s[0,1] =~ /[A-Z]/
|
420
|
+
if ::ERRORMESSAGE_JRUBY_BUG
|
421
|
+
begin
|
422
|
+
@ole_worksheet.send(name, *args)
|
423
|
+
rescue Java::OrgRacobCom::ComFailException
|
424
|
+
raise VBAMethodMissingError, "unknown VBA property or method #{name.inspect}"
|
379
425
|
end
|
380
426
|
else
|
381
|
-
|
427
|
+
begin
|
428
|
+
@ole_worksheet.send(name, *args)
|
429
|
+
rescue NoMethodError
|
430
|
+
raise VBAMethodMissingError, "unknown VBA property or method #{name.inspect}"
|
431
|
+
end
|
382
432
|
end
|
383
433
|
end
|
384
|
-
|
385
|
-
def last_row
|
386
|
-
special_last_row = @ole_worksheet.UsedRange.SpecialCells(RobustExcelOle::XlLastCell).Row
|
387
|
-
used_last_row = @ole_worksheet.UsedRange.Rows.Count
|
388
|
-
|
389
|
-
special_last_row >= used_last_row ? special_last_row : used_last_row
|
390
|
-
end
|
391
|
-
|
392
|
-
def last_column
|
393
|
-
special_last_column = @ole_worksheet.UsedRange.SpecialCells(RobustExcelOle::XlLastCell).Column
|
394
|
-
used_last_column = @ole_worksheet.UsedRange.Columns.Count
|
395
|
-
|
396
|
-
special_last_column >= used_last_column ? special_last_column : used_last_column
|
397
|
-
end
|
398
|
-
|
434
|
+
|
399
435
|
end
|
400
436
|
|
401
437
|
public
|