robust_excel_ole 1.27 → 1.32

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.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/Changelog +36 -2
  3. data/README.rdoc +121 -19
  4. data/___dummy_workbook.xls +0 -0
  5. data/benchmarking/creek_example.rb +1 -1
  6. data/benchmarking/reo_example.rb +1 -1
  7. data/benchmarking/reo_example1.rb +1 -1
  8. data/benchmarking/reo_example2.rb +1 -1
  9. data/benchmarking/roo_example.rb +1 -1
  10. data/benchmarking/simple_xlsx_reader_example.rb +1 -1
  11. data/benchmarking/spreadsheet_example.rb +1 -1
  12. data/bin/jreo +19 -0
  13. data/bin/reo +19 -0
  14. data/docs/README_excel.rdoc +16 -24
  15. data/docs/README_listobjects.rdoc +176 -0
  16. data/docs/README_open.rdoc +20 -16
  17. data/docs/README_ranges.rdoc +72 -55
  18. data/docs/README_save_close.rdoc +3 -3
  19. data/docs/README_sheet.rdoc +19 -20
  20. data/examples/example_ruby_library.rb +2 -2
  21. data/examples/introductory_examples/example_open.rb +11 -0
  22. data/examples/introductory_examples/example_range.rb +2 -2
  23. data/examples/modifying_sheets/example_access_sheets_and_cells.rb +6 -6
  24. data/examples/modifying_sheets/example_add_names.rb +1 -1
  25. data/examples/modifying_sheets/example_concating.rb +1 -1
  26. data/examples/modifying_sheets/example_copying.rb +2 -2
  27. data/examples/modifying_sheets/example_listobjects.rb +86 -0
  28. data/examples/modifying_sheets/example_naming.rb +1 -1
  29. data/examples/modifying_sheets/example_ranges.rb +1 -1
  30. data/examples/open_save_close/example_control_to_excel.rb +1 -1
  31. data/examples/open_save_close/example_if_obstructed_closeifsaved.rb +1 -1
  32. data/examples/open_save_close/example_if_obstructed_save.rb +3 -3
  33. data/examples/open_save_close/example_if_unsaved_accept.rb +1 -1
  34. data/examples/open_save_close/example_if_unsaved_forget.rb +3 -3
  35. data/examples/open_save_close/example_if_unsaved_forget_more.rb +4 -4
  36. data/examples/open_save_close/example_read_only.rb +1 -1
  37. data/examples/open_save_close/example_simple.rb +1 -1
  38. data/examples/open_save_close/example_unobtrusively.rb +3 -3
  39. data/lib/robust_excel_ole.rb +19 -16
  40. data/lib/robust_excel_ole/address_tool.rb +54 -44
  41. data/lib/robust_excel_ole/base.rb +9 -6
  42. data/lib/robust_excel_ole/bookstore.rb +3 -17
  43. data/lib/robust_excel_ole/cell.rb +17 -22
  44. data/lib/robust_excel_ole/cygwin.rb +2 -0
  45. data/lib/robust_excel_ole/excel.rb +136 -201
  46. data/lib/robust_excel_ole/general.rb +249 -238
  47. data/lib/robust_excel_ole/list_object.rb +186 -210
  48. data/lib/robust_excel_ole/list_row.rb +155 -0
  49. data/lib/robust_excel_ole/range.rb +130 -94
  50. data/lib/robust_excel_ole/range_owners.rb +54 -135
  51. data/lib/robust_excel_ole/version.rb +1 -1
  52. data/lib/robust_excel_ole/workbook.rb +230 -196
  53. data/lib/robust_excel_ole/worksheet.rb +254 -133
  54. data/lib/spec_helper.rb +1 -1
  55. data/robust_excel_ole.gemspec +4 -3
  56. data/spec/address_tool_spec.rb +2 -2
  57. data/spec/base_spec.rb +19 -17
  58. data/spec/bookstore_spec.rb +3 -4
  59. data/spec/cell_spec.rb +10 -10
  60. data/spec/cygwin_spec.rb +1 -1
  61. data/spec/data/more_data/workbook.xls +0 -0
  62. data/spec/excel_spec.rb +133 -86
  63. data/spec/general_spec.rb +79 -18
  64. data/spec/list_object_spec.rb +259 -81
  65. data/spec/list_row_spec.rb +218 -0
  66. data/spec/range_spec.rb +75 -41
  67. data/spec/spec_helper.rb +16 -2
  68. data/spec/workbook_spec.rb +87 -46
  69. data/spec/workbook_specs/workbook_all_spec.rb +9 -28
  70. data/spec/workbook_specs/workbook_close_spec.rb +1 -1
  71. data/spec/workbook_specs/workbook_misc_spec.rb +52 -45
  72. data/spec/workbook_specs/workbook_open_spec.rb +103 -50
  73. data/spec/workbook_specs/workbook_save_spec.rb +22 -23
  74. data/spec/workbook_specs/workbook_sheet_spec.rb +4 -4
  75. data/spec/workbook_specs/workbook_subclass_spec.rb +1 -1
  76. data/spec/workbook_specs/workbook_unobtr_spec.rb +553 -395
  77. data/spec/worksheet_spec.rb +544 -308
  78. metadata +38 -3
  79. data/lib/reo_console.rb +0 -42
@@ -11,6 +11,10 @@ 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
+
16
+ using ToReoRefinement
17
+
14
18
  attr_reader :ole_worksheet
15
19
  attr_reader :workbook
16
20
 
@@ -47,9 +51,9 @@ module RobustExcelOle
47
51
  # sheet name
48
52
  # @returns name of the sheet
49
53
  def name
50
- @ole_worksheet.Name
54
+ @ole_worksheet.Name.encode('utf-8')
51
55
  rescue
52
- raise WorksheetREOError, "name could not be determined"
56
+ raise WorksheetREOError, "name could not be determined\n#{$!.message}"
53
57
  end
54
58
 
55
59
  # sets sheet name
@@ -64,58 +68,141 @@ module RobustExcelOle
64
68
  end
65
69
  end
66
70
 
67
- # returns a cell given the defined name or row and column
68
- # @params row, column, or name
69
- # @returns cell, if row and column are given
70
- def [] p1, p2 = :__not_provided
71
- if p2 != :__not_provided
72
- x, y = p1, p2
73
- xy = "#{x}_#{y}"
74
- @cells = { }
75
- begin
76
- @cells[xy] = RobustExcelOle::Cell.new(@ole_worksheet.Cells.Item(x, y), @worksheet)
77
- rescue
78
- raise RangeNotEvaluatable, "cannot read cell (#{x.inspect},#{y.inspect})"
79
- end
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
80
85
  else
81
- name = p1
82
- begin
83
- namevalue_glob(name)
84
- rescue REOError
85
- namevalue(name)
86
- end
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}"
87
92
  end
88
93
  end
89
94
 
90
- # sets the value of a cell
91
- # @params row and column, or defined name
92
- def []= (p1, p2, p3 = :__not_provided)
93
- if p3 != :__not_provided
94
- x, y, value = p1, p2, p3
95
- set_cellval(x,y,value)
96
- else
97
- name, value = p1, p2
98
- begin
99
- set_namevalue_glob(name, value)
100
- rescue REOError
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
101
106
  begin
102
- workbook.set_namevalue_glob(name, value)
103
- rescue REOError
104
- set_namevalue(name, value)
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})"
113
+ end
114
+ end
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
130
+ end
131
+
132
+ public
133
+
134
+ # returns the contents of a range with a locally defined name
135
+ # evaluates the formula if the contents is a formula
136
+ # if the name could not be found or the range or value could not be determined,
137
+ # then return default value, if provided, raise error otherwise
138
+ # @param [String] name the name of a range
139
+ # @param [Hash] opts the options
140
+ # @option opts [Symbol] :default the default value that is provided if no contents could be returned
141
+ # @return [Variant] the contents of a range with given name
142
+ def namevalue(name, opts = { default: :__not_provided })
143
+ begin
144
+ ole_range = self.Range(name)
145
+ rescue # WIN32OLERuntimeError, VBAMethodMissingError, Java::OrgRacobCom::ComFailException
146
+ return opts[:default] unless opts[:default] == :__not_provided
147
+ raise NameNotFound, "name #{name.inspect} not in #{self.inspect}"
148
+ end
149
+ begin
150
+ worksheet = self if self.is_a?(Worksheet)
151
+ #value = ole_range.Value
152
+ value = if !::RANGES_JRUBY_BUG
153
+ ole_range.Value
154
+ else
155
+ values = RobustExcelOle::Range.new(ole_range, worksheet).v
156
+ (values.size==1 && values.first.size==1) ? values.first.first : values
157
+ end
158
+ rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException
159
+ return opts[:default] unless opts[:default] == :__not_provided
160
+ raise RangeNotEvaluatable, "cannot determine value of range named #{name.inspect} in #{self.inspect}\n#{$!.message}"
161
+ end
162
+ if value == -2146828288 + RobustExcelOle::XlErrName
163
+ return opts[:default] unless opts[:default] == __not_provided
164
+ raise RangeNotEvaluatable, "cannot evaluate range named #{name.inspect} in #{File.basename(workbook.stored_filename).inspect rescue nil}\n#{$!.message}"
165
+ end
166
+ return opts[:default] unless (opts[:default] == :__not_provided) || value.nil?
167
+ value
168
+ end
169
+
170
+ # assigns a value to a range given a locally defined name
171
+ # @param [String] name the name of a range
172
+ # @param [Variant] value the assigned value
173
+ # @option opts [Symbol] :color the color of the cell when set
174
+ def set_namevalue(name, value, opts = { })
175
+ begin
176
+ ole_range = self.Range(name)
177
+ rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException, VBAMethodMissingError
178
+ raise NameNotFound, "name #{name.inspect} not in #{self.inspect}"
179
+ end
180
+ begin
181
+ ole_range.Interior.ColorIndex = opts[:color] unless opts[:color].nil?
182
+ if !::RANGES_JRUBY_BUG
183
+ ole_range.Value = value
184
+ else
185
+ address_r1c1 = ole_range.AddressLocal(true,true,XlR1C1)
186
+ row, col = address_tool.as_integer_ranges(address_r1c1)
187
+ row.each_with_index do |r,i|
188
+ col.each_with_index do |c,j|
189
+ ole_range.Cells(i+1,j+1).Value = (value.respond_to?(:pop) ? value[i][j] : value)
190
+ end
105
191
  end
106
192
  end
193
+ value
194
+ rescue WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException
195
+ raise RangeNotEvaluatable, "cannot assign value to range named #{name.inspect} in #{self.inspect}\n#{$!.message}"
107
196
  end
108
197
  end
109
198
 
110
199
  # value of a cell, if row and column are given
111
200
  # @params row and column
112
201
  # @returns value of the cell
113
- def cellval(x,y)
114
- begin
115
- @ole_worksheet.Cells.Item(x, y).Value
116
- rescue
117
- raise RangeNotEvaluatable, "cannot read cell (#{x.inspect},#{y.inspect})"
118
- 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}"
119
206
  end
120
207
 
121
208
  # sets the value of a cell, if row, column and color of the cell are given
@@ -126,77 +213,103 @@ module RobustExcelOle
126
213
  cell.Interior.ColorIndex = opts[:color] unless opts[:color].nil?
127
214
  cell.Value = value
128
215
  rescue # WIN32OLERuntimeError, Java::OrgRacobCom::ComFailException
129
- 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}"
130
217
  end
131
218
 
219
+ # @return [Array] a 2-dimensional array that contains the values in each row of the used range
132
220
  def values
133
221
  @ole_worksheet.UsedRange.Value
134
222
  end
135
223
 
224
+ # @return [Enumerator] traversing the rows values
136
225
  def each
137
- each_row do |row_range|
138
- row_range.each do |cell|
139
- yield cell
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)
140
230
  end
231
+ else
232
+ to_enum(:each).lazy
141
233
  end
142
234
  end
143
235
 
144
- def each_with_index(offset = 0)
145
- i = offset
146
- each_row do |row_range|
147
- row_range.each do |cell|
148
- yield cell, i
149
- i += 1
236
+ # @return [Enumerator] traversing the rows
237
+ def each_row(offset = 0)
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)
150
243
  end
244
+ else
245
+ to_enum(:each_row).lazy
151
246
  end
152
247
  end
153
248
 
154
- def each_rowvalue
155
- @ole_worksheet.UsedRange.Value.each do |row_values|
156
- yield row_values
249
+ def each_row_with_index(offset = 0) # :nodoc: # # :deprecated :#
250
+ each_row(offset) do |row_range|
251
+ yield RobustExcelOle::Range.new(row_range, self), (row_range.Row - 1 - offset)
157
252
  end
158
253
  end
159
254
 
160
- def each_value # :deprecated: #
161
- each_rowvalue
255
+ # @return [Enumerator] traversing the columns
256
+ def each_column(offset = 0)
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
265
+ end
162
266
  end
163
267
 
164
- def each_rowvalue_with_index(offset = 0)
165
- i = offset
166
- @ole_worksheet.UsedRange.Value.each do |row_values|
167
- yield row_values, i
168
- i += 1
268
+ def each_column_with_index(offset = 0) # :nodoc: # # :deprecated :#
269
+ each_column(offset) do |column_range|
270
+ yield RobustExcelOle::Range.new(column_range, self), (column_range.Column - 1 - offset)
169
271
  end
170
272
  end
171
273
 
172
- def each_row(offset = 0)
173
- offset += 1
174
- 1.upto(@end_row) do |row|
175
- next if row < offset
176
- yield RobustExcelOle::Range.new(@ole_worksheet.Range(@ole_worksheet.Cells(row, 1), @ole_worksheet.Cells(row, @end_column)), self)
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
177
284
  end
178
285
  end
179
286
 
180
- def each_row_with_index(offset = 0)
181
- each_row(offset) do |row_range|
182
- yield RobustExcelOle::Range.new(row_range, self), (row_range.Row - 1 - offset)
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
183
294
  end
184
295
  end
185
296
 
186
- def each_column(offset = 0)
187
- offset += 1
188
- 1.upto(@end_column) do |column|
189
- next if column < offset
190
- yield RobustExcelOle::Range.new(@ole_worksheet.Range(@ole_worksheet.Cells(1, column), @ole_worksheet.Cells(@end_row, column)), self)
297
+ def each_rowvalue # :deprecated: #
298
+ values.each do |row_values|
299
+ yield row_values
191
300
  end
192
301
  end
193
302
 
194
- def each_column_with_index(offset = 0)
195
- each_column(offset) do |column_range|
196
- yield RobustExcelOle::Range.new(column_range, self), (column_range.Column - 1 - offset)
303
+ def each_rowvalue_with_index(offset = 0) # :deprecated: #
304
+ i = offset
305
+ values.each do |row_values|
306
+ yield row_values, i
307
+ i += 1
197
308
  end
198
309
  end
199
310
 
311
+ alias each_value each_rowvalue # :deprecated: #
312
+
200
313
  def row_range(row, integer_range = nil)
201
314
  integer_range ||= 1..@end_column
202
315
  RobustExcelOle::Range.new(@ole_worksheet.Range(@ole_worksheet.Cells(row, integer_range.min), @ole_worksheet.Cells(row, integer_range.max)), self)
@@ -209,33 +322,17 @@ module RobustExcelOle
209
322
 
210
323
  def == other_worksheet
211
324
  other_worksheet.is_a?(Worksheet) &&
212
- self.workbook == other_worksheet.workbook &&
213
- self.Name == other_worksheet.Name
325
+ self.workbook == other_worksheet.workbook &&
326
+ self.Name == other_worksheet.Name
214
327
  end
215
328
 
216
- # creates a range from a given defined name or address
217
- # @params [Variant] defined name or address
218
- # @return [Range] a range
219
- def range(name_or_address, address2 = :__not_provided)
220
- if name_or_address.respond_to?(:gsub) && address2 == :__not_provided
221
- name = name_or_address
222
- range = RobustExcelOle::Range.new(name_object(name).RefersToRange, self) rescue nil
223
- end
224
- unless range
225
- address = name_or_address
226
- address = [name_or_address,address2] unless address2 == :__not_provided
227
- workbook.retain_saved do
228
- begin
229
- self.Names.Add('__dummy001',nil,true,nil,nil,nil,nil,nil,nil,'=' + address_tool.as_r1c1(address))
230
- range = RobustExcelOle::Range.new(name_object('__dummy001').RefersToRange, self)
231
- self.Names.Item('__dummy001').Delete
232
- rescue
233
- address2_string = address2.nil? ? "" : ", #{address2.inspect}"
234
- raise RangeNotCreated, "cannot create range (#{name_or_address.inspect}#{address2_string})"
235
- end
236
- end
237
- end
238
- range
329
+
330
+ # @params [Variant] table (listobject) name or number
331
+ # @return [ListObject] a table (listobject)
332
+ def table(number_or_name)
333
+ listobject_class.new(@ole_worksheet.ListObjects.Item(number_or_name))
334
+ rescue
335
+ raise WorksheetREOError, "table #{number_or_name} not found"
239
336
  end
240
337
 
241
338
  # @private
@@ -248,11 +345,37 @@ module RobustExcelOle
248
345
  false
249
346
  end
250
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
+
371
+ using ParentRefinement
372
+ using StringRefinement
373
+
251
374
  # @private
252
375
  def self.workbook_class
253
376
  @workbook_class ||= begin
254
377
  module_name = self.parent_name
255
- "#{module_name}::Workbook".constantize
378
+ "#{module_name}::Workbook".constantize
256
379
  rescue NameError => e
257
380
  Workbook
258
381
  end
@@ -263,9 +386,24 @@ module RobustExcelOle
263
386
  self.class.workbook_class
264
387
  end
265
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
+
266
404
  # @private
267
405
  def to_s
268
- '#<Worksheet: ' + (workbook.nil? ? 'not alive ' : (name + ' ' + File.basename(workbook.stored_filename)).to_s) + ">"
406
+ "#<Worksheet: #{(workbook.nil? ? "not alive " : (name + ' ' + File.basename(workbook.stored_filename)))}>"
269
407
  end
270
408
 
271
409
  # @private
@@ -278,39 +416,22 @@ module RobustExcelOle
278
416
  private
279
417
 
280
418
  def method_missing(name, *args)
281
- if name.to_s[0,1] =~ /[A-Z]/
282
- if ::ERRORMESSAGE_JRUBY_BUG
283
- begin
284
- @ole_worksheet.send(name, *args)
285
- rescue Java::OrgRacobCom::ComFailException
286
- raise VBAMethodMissingError, "unknown VBA property or method #{name.inspect}"
287
- end
288
- else
289
- begin
290
- @ole_worksheet.send(name, *args)
291
- rescue NoMethodError
292
- raise VBAMethodMissingError, "unknown VBA property or method #{name.inspect}"
293
- 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}"
294
425
  end
295
426
  else
296
- super
427
+ begin
428
+ @ole_worksheet.send(name, *args)
429
+ rescue NoMethodError
430
+ raise VBAMethodMissingError, "unknown VBA property or method #{name.inspect}"
431
+ end
297
432
  end
298
433
  end
299
-
300
- def last_row
301
- special_last_row = @ole_worksheet.UsedRange.SpecialCells(RobustExcelOle::XlLastCell).Row
302
- used_last_row = @ole_worksheet.UsedRange.Rows.Count
303
-
304
- special_last_row >= used_last_row ? special_last_row : used_last_row
305
- end
306
-
307
- def last_column
308
- special_last_column = @ole_worksheet.UsedRange.SpecialCells(RobustExcelOle::XlLastCell).Column
309
- used_last_column = @ole_worksheet.UsedRange.Columns.Count
310
-
311
- special_last_column >= used_last_column ? special_last_column : used_last_column
312
- end
313
-
434
+
314
435
  end
315
436
 
316
437
  public