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.
- checksums.yaml +4 -4
- data/Changelog +36 -2
- data/README.rdoc +121 -19
- data/___dummy_workbook.xls +0 -0
- data/benchmarking/creek_example.rb +1 -1
- data/benchmarking/reo_example.rb +1 -1
- data/benchmarking/reo_example1.rb +1 -1
- data/benchmarking/reo_example2.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/bin/jreo +19 -0
- data/bin/reo +19 -0
- data/docs/README_excel.rdoc +16 -24
- data/docs/README_listobjects.rdoc +176 -0
- data/docs/README_open.rdoc +20 -16
- data/docs/README_ranges.rdoc +72 -55
- data/docs/README_save_close.rdoc +3 -3
- data/docs/README_sheet.rdoc +19 -20
- data/examples/example_ruby_library.rb +2 -2
- data/examples/introductory_examples/example_open.rb +11 -0
- 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.rb +19 -16
- data/lib/robust_excel_ole/address_tool.rb +54 -44
- data/lib/robust_excel_ole/base.rb +9 -6
- data/lib/robust_excel_ole/bookstore.rb +3 -17
- data/lib/robust_excel_ole/cell.rb +17 -22
- data/lib/robust_excel_ole/cygwin.rb +2 -0
- data/lib/robust_excel_ole/excel.rb +136 -201
- data/lib/robust_excel_ole/general.rb +249 -238
- data/lib/robust_excel_ole/list_object.rb +186 -210
- data/lib/robust_excel_ole/list_row.rb +155 -0
- data/lib/robust_excel_ole/range.rb +130 -94
- data/lib/robust_excel_ole/range_owners.rb +54 -135
- data/lib/robust_excel_ole/version.rb +1 -1
- data/lib/robust_excel_ole/workbook.rb +230 -196
- data/lib/robust_excel_ole/worksheet.rb +254 -133
- data/lib/spec_helper.rb +1 -1
- data/robust_excel_ole.gemspec +4 -3
- data/spec/address_tool_spec.rb +2 -2
- data/spec/base_spec.rb +19 -17
- data/spec/bookstore_spec.rb +3 -4
- data/spec/cell_spec.rb +10 -10
- data/spec/cygwin_spec.rb +1 -1
- data/spec/data/more_data/workbook.xls +0 -0
- data/spec/excel_spec.rb +133 -86
- data/spec/general_spec.rb +79 -18
- data/spec/list_object_spec.rb +259 -81
- data/spec/list_row_spec.rb +218 -0
- data/spec/range_spec.rb +75 -41
- data/spec/spec_helper.rb +16 -2
- data/spec/workbook_spec.rb +87 -46
- data/spec/workbook_specs/workbook_all_spec.rb +9 -28
- data/spec/workbook_specs/workbook_close_spec.rb +1 -1
- data/spec/workbook_specs/workbook_misc_spec.rb +52 -45
- data/spec/workbook_specs/workbook_open_spec.rb +103 -50
- data/spec/workbook_specs/workbook_save_spec.rb +22 -23
- data/spec/workbook_specs/workbook_sheet_spec.rb +4 -4
- data/spec/workbook_specs/workbook_subclass_spec.rb +1 -1
- data/spec/workbook_specs/workbook_unobtr_spec.rb +553 -395
- data/spec/worksheet_spec.rb +544 -308
- metadata +38 -3
- data/lib/reo_console.rb +0 -42
@@ -1,10 +1,9 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
|
-
|
3
2
|
module RobustExcelOle
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
using ToReoRefinement
|
5
|
+
using FindAllIndicesRefinement
|
6
|
+
|
8
7
|
# This class essentially wraps a Win32Ole ListObject.
|
9
8
|
# You can apply all VBA methods (starting with a capital letter)
|
10
9
|
# that you would apply for a ListObject.
|
@@ -12,6 +11,8 @@ module RobustExcelOle
|
|
12
11
|
|
13
12
|
class ListObject < VbaObjects
|
14
13
|
|
14
|
+
include Enumerable
|
15
|
+
|
15
16
|
attr_reader :ole_table
|
16
17
|
|
17
18
|
alias ole_object ole_table
|
@@ -55,146 +56,137 @@ module RobustExcelOle
|
|
55
56
|
@ole_table.Name = table_name_or_number
|
56
57
|
@ole_table.HeaderRowRange.Value = [column_names] unless column_names.empty?
|
57
58
|
rescue WIN32OLERuntimeError => msg # , Java::OrgRacobCom::ComFailException => msg
|
58
|
-
raise TableError, "
|
59
|
+
raise TableError, "#{$!.message}"
|
59
60
|
end
|
60
61
|
end
|
61
62
|
|
62
|
-
|
63
63
|
ole_table = @ole_table
|
64
|
+
|
64
65
|
@row_class = Class.new(ListRow) do
|
65
66
|
|
66
67
|
@@ole_table = ole_table
|
67
68
|
|
68
|
-
def
|
69
|
-
|
70
|
-
end
|
71
|
-
|
72
|
-
# returns the value of the cell with given column name or number
|
73
|
-
# @param [Variant] column number or column name
|
74
|
-
# @return [Variant] value of the cell
|
75
|
-
def [] column_number_or_name
|
76
|
-
begin
|
77
|
-
ole_cell = @@ole_table.Application.Intersect(
|
78
|
-
@ole_listrow.Range, @@ole_table.ListColumns.Item(column_number_or_name).Range)
|
79
|
-
ole_cell.Value
|
80
|
-
rescue WIN32OLERuntimeError
|
81
|
-
raise TableRowError, "could not determine the value at column #{column_number_or_name}"
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
|
86
|
-
def []=(column_number_or_name, value)
|
87
|
-
begin
|
88
|
-
ole_cell = @@ole_table.Application.Intersect(
|
89
|
-
@ole_listrow.Range, @@ole_table.ListColumns.Item(column_number_or_name).Range)
|
90
|
-
ole_cell.Value = value
|
91
|
-
rescue WIN32OLERuntimeError
|
92
|
-
raise TableRowError, "could not assign value #{value.inspect} to cell at column #{column_number_or_name}"
|
93
|
-
end
|
69
|
+
def ole_table
|
70
|
+
@@ole_table
|
94
71
|
end
|
72
|
+
|
73
|
+
end
|
95
74
|
|
96
|
-
|
97
|
-
# @return [Array] values of the row
|
98
|
-
def values
|
99
|
-
begin
|
100
|
-
@ole_listrow.Range.Value.first
|
101
|
-
rescue WIN32OLERuntimeError
|
102
|
-
raise TableError, "could not read values"
|
103
|
-
end
|
104
|
-
end
|
75
|
+
end
|
105
76
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
updated_values[0,values.length] = values
|
112
|
-
@ole_listrow.Range.Value = [updated_values]
|
113
|
-
values
|
114
|
-
rescue WIN32OLERuntimeError
|
115
|
-
raise TableError, "could not set values #{values.inspect}"
|
116
|
-
end
|
77
|
+
# @return [Enumerator] traversing all list row objects
|
78
|
+
def each
|
79
|
+
if block_given?
|
80
|
+
@ole_table.ListRows.lazy.each do |ole_listrow|
|
81
|
+
yield @row_class.new(ole_listrow)
|
117
82
|
end
|
83
|
+
else
|
84
|
+
to_enum(:each).lazy
|
85
|
+
end
|
86
|
+
end
|
118
87
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
88
|
+
# accesses a table row object
|
89
|
+
# @param [Variant] a hash of key (key column: value) or a row number (>= 1)
|
90
|
+
# @option opts [Variant] limit: maximal number of matching table rows to return, or return the first matching table row (default :first)
|
91
|
+
# @return [Variant] a listrow, if limit == :first
|
92
|
+
# an array of listrows, with maximal number=limit, if list rows were found and limit is not :first
|
93
|
+
# nil, if no list object was found
|
94
|
+
def [] (key_hash_or_number, options = { })
|
95
|
+
return @row_class.new(key_hash_or_number) if key_hash_or_number.respond_to?(:succ)
|
96
|
+
options = {limit: :first}.merge(options)
|
97
|
+
opts = options.dup
|
98
|
+
opts[:limit] = 1 if options[:limit] == :first
|
99
|
+
key_hash = key_hash_or_number.transform_keys{|k| k.downcase.to_sym}
|
100
|
+
matching = if @ole_table.ListRows.Count < 150
|
101
|
+
matching_via_traversing(key_hash, opts)
|
102
|
+
else
|
103
|
+
matching_via_filter(key_hash, opts)
|
104
|
+
end
|
105
|
+
matching_listrows = matching.map{ |r| @row_class.new(r) }
|
106
|
+
options[:limit] == :first ? matching_listrows.first : matching_listrows
|
107
|
+
end
|
128
108
|
|
129
|
-
|
130
|
-
name_str = name.to_s
|
131
|
-
core_name = name_str[-1]!='=' ? name_str : name_str[0..-2]
|
132
|
-
column_names = @@ole_table.HeaderRowRange.Value.first
|
133
|
-
column_name = column_names.find do |c|
|
134
|
-
c == core_name ||
|
135
|
-
c.gsub(/\W/,'') == core_name ||
|
136
|
-
c.replace_umlauts == core_name ||
|
137
|
-
c.gsub(/\W/,'').replace_umlauts == core_name ||
|
138
|
-
c.gsub(/\W/,'').replace_umlauts.underscore.gsub(/[^[\w\d]]/, '_').delete_multiple_underscores == core_name
|
139
|
-
end
|
140
|
-
if column_name
|
141
|
-
method_name = core_name.gsub(/\W/,'') + (name_str[-1]!='=' ? "" : "=")
|
142
|
-
define_and_call_method(column_name,method_name,*args)
|
143
|
-
else
|
144
|
-
super(name, *args)
|
145
|
-
end
|
146
|
-
end
|
109
|
+
private
|
147
110
|
|
148
|
-
|
111
|
+
def matching_via_traversing(key_hash, opts)
|
112
|
+
encode_utf8 = ->(val) {val.respond_to?(:gsub) ? val.encode('utf-8') : val}
|
113
|
+
cn2i = column_names_to_index
|
114
|
+
max_matching_num = opts[:limit] || 65536
|
115
|
+
matching_rows = @ole_table.ListRows.lazy.select { |listrow|
|
116
|
+
rowvalues = listrow.Range.Value.first
|
117
|
+
key_hash.all?{ |key,val| encode_utf8.(rowvalues[cn2i[key]])==val}
|
118
|
+
}.take(max_matching_num).to_a
|
119
|
+
rescue
|
120
|
+
raise(TableError, "cannot find row with key #{key_hash}")
|
121
|
+
end
|
149
122
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
123
|
+
def matching_via_filter(key_hash, opts)
|
124
|
+
ole_worksheet = self.Parent
|
125
|
+
ole_workbook = ole_worksheet.Parent
|
126
|
+
row_numbers = []
|
127
|
+
ole_workbook.retain_saved do
|
128
|
+
added_ole_worksheet = ole_workbook.Worksheets.Add
|
129
|
+
criteria = Table.new(added_ole_worksheet, "criteria", [2,1], 2, key_hash.keys.map{|s| s.to_s})
|
130
|
+
criteria[1].values = key_hash.values
|
131
|
+
self.Range.AdvancedFilter({
|
132
|
+
Action: XlFilterInPlace,
|
133
|
+
CriteriaRange: added_ole_worksheet.range([2..3,1..key_hash.length]).ole_range, Unique: false})
|
134
|
+
filtered_ole_range = self.DataBodyRange.SpecialCells(XlCellTypeVisible) rescue nil
|
135
|
+
ole_worksheet.ShowAllData
|
136
|
+
self.Range.AdvancedFilter({Action: XlFilterInPlace,
|
137
|
+
CriteriaRange: added_ole_worksheet.range([1,1]).ole_range, Unique: false})
|
138
|
+
ole_workbook.Parent.with_displayalerts(false){added_ole_worksheet.Delete}
|
139
|
+
if filtered_ole_range
|
140
|
+
filtered_ole_range.Areas.each do |area|
|
141
|
+
break if area.Rows.each do |row|
|
142
|
+
row_numbers << row.Row-position.first
|
143
|
+
break true if row_numbers.count == opts[:limit]
|
165
144
|
end
|
166
145
|
end
|
167
|
-
end
|
168
|
-
|
146
|
+
end
|
147
|
+
@ole_table = ole_worksheet.table(self.Name)
|
148
|
+
end
|
149
|
+
row_numbers
|
150
|
+
rescue
|
151
|
+
raise(TableError, "cannot find row with key #{key_hash}")
|
152
|
+
end
|
169
153
|
|
170
|
-
|
171
|
-
# @param [Integer] a row number (>= 1)
|
172
|
-
# @return [ListRow] a object of dynamically constructed class with superclass ListRow
|
173
|
-
def [] row_number
|
174
|
-
@row_class.new(row_number)
|
175
|
-
end
|
154
|
+
public
|
176
155
|
|
156
|
+
# @return [Integer] number of rows
|
157
|
+
def rows_number
|
158
|
+
@ole_table.ListRows.Count
|
177
159
|
end
|
178
160
|
|
161
|
+
# @return [Array] values of the table
|
162
|
+
def value
|
163
|
+
[column_names] + self.DataBodyRange.Value
|
164
|
+
end
|
165
|
+
|
179
166
|
# @return [Array] a list of column names
|
180
167
|
def column_names
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
raise TableError, "could not determine column names"
|
185
|
-
end
|
168
|
+
@ole_table.HeaderRowRange.Value.first.map{|v| v.encode('utf-8')}
|
169
|
+
rescue WIN32OLERuntimeError
|
170
|
+
raise TableError, "could not determine column names\n#{$!.message}"
|
186
171
|
end
|
187
172
|
|
173
|
+
# @return [Hash] pairs of column names and index
|
174
|
+
def column_names_to_index
|
175
|
+
header_row_values = @ole_table.HeaderRowRange.Value.first
|
176
|
+
header_row_values.map{|v| v.encode('utf-8').downcase.to_sym}.zip(0..header_row_values.size-1).to_h
|
177
|
+
rescue WIN32OLERuntimeError
|
178
|
+
raise TableError, "could not determine column names\n#{$!.message}"
|
179
|
+
end
|
180
|
+
|
181
|
+
|
188
182
|
# adds a row
|
189
183
|
# @param [Integer] position of the new row
|
190
184
|
# @param [Array] values of the column
|
191
185
|
def add_row(position = nil, contents = nil)
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
raise TableError, ("could not add row" + (" at position #{position.inspect}" if position))
|
197
|
-
end
|
186
|
+
@ole_table.ListRows.Add(position)
|
187
|
+
set_row_values(position, contents) if contents
|
188
|
+
rescue WIN32OLERuntimeError
|
189
|
+
raise TableError, ("could not add row" + (" at position #{position.inspect}" if position) + "\n#{$!.message}")
|
198
190
|
end
|
199
191
|
|
200
192
|
# adds a column
|
@@ -202,116 +194,96 @@ module RobustExcelOle
|
|
202
194
|
# @param [Integer] position of the new column
|
203
195
|
# @param [Array] values of the column
|
204
196
|
def add_column(column_name = nil, position = nil, contents = nil)
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
raise TableError, ("could not add column"+ ("at position #{position.inspect} with name #{column_name.inspect}" if position))
|
211
|
-
end
|
197
|
+
new_column = @ole_table.ListColumns.Add(position)
|
198
|
+
new_column.Name = column_name if column_name
|
199
|
+
set_column_values(column_name, contents) if contents
|
200
|
+
rescue WIN32OLERuntimeError, TableError
|
201
|
+
raise TableError, ("could not add column"+ ("at position #{position.inspect} with name #{column_name.inspect}" if position) + "\n#{$!.message}")
|
212
202
|
end
|
213
203
|
|
214
204
|
# deletes a row
|
215
205
|
# @param [Integer] position of the old row
|
216
|
-
def delete_row(row_number)
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
raise TableError, "could not delete row #{row_number.inspect}"
|
221
|
-
end
|
206
|
+
def delete_row(row_number) # :nodoc: #
|
207
|
+
@ole_table.ListRows.Item(row_number).Delete
|
208
|
+
rescue WIN32OLERuntimeError
|
209
|
+
raise TableError, "could not delete row #{row_number.inspect}\n#{$!.message}"
|
222
210
|
end
|
223
211
|
|
224
212
|
# deletes a column
|
225
213
|
# @param [Variant] column number or column name
|
226
|
-
def delete_column(column_number_or_name)
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
raise TableError, "could not delete column #{column_number_or_name.inspect}"
|
231
|
-
end
|
214
|
+
def delete_column(column_number_or_name) # :nodoc: #
|
215
|
+
@ole_table.ListColumns.Item(column_number_or_name).Delete
|
216
|
+
rescue WIN32OLERuntimeError
|
217
|
+
raise TableError, "could not delete column #{column_number_or_name.inspect}\n#{$!.message}"
|
232
218
|
end
|
233
219
|
|
234
220
|
# deletes the contents of a row
|
235
221
|
# @param [Integer] row number
|
236
222
|
def delete_row_values(row_number)
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
raise TableError, "could not delete contents of row #{row_number.inspect}"
|
242
|
-
end
|
223
|
+
@ole_table.ListRows.Item(row_number).Range.Value = [[].fill(nil,0..(@ole_table.ListColumns.Count-1))]
|
224
|
+
nil
|
225
|
+
rescue WIN32OLERuntimeError
|
226
|
+
raise TableError, "could not delete contents of row #{row_number.inspect}\n#{$!.message}"
|
243
227
|
end
|
244
228
|
|
245
229
|
# deletes the contents of a column
|
246
230
|
# @param [Variant] column number or column name
|
247
231
|
def delete_column_values(column_number_or_name)
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
raise TableError, "could not delete contents of column #{column_number_or_name.inspect}"
|
254
|
-
end
|
232
|
+
column_name = @ole_table.ListColumns.Item(column_number_or_name).Range.Value.first
|
233
|
+
@ole_table.ListColumns.Item(column_number_or_name).Range.Value = [column_name] + [].fill([nil],0..(@ole_table.ListRows.Count-1))
|
234
|
+
nil
|
235
|
+
rescue WIN32OLERuntimeError
|
236
|
+
raise TableError, "could not delete contents of column #{column_number_or_name.inspect}\n#{$!.message}"
|
255
237
|
end
|
256
238
|
|
257
239
|
# renames a row
|
258
240
|
# @param [String] previous name or number of the column
|
259
241
|
# @param [String] new name of the column
|
260
|
-
def rename_column(name_or_number, new_name)
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
raise TableError, "could not rename column #{name_or_number.inspect} to #{new_name.inspect}"
|
265
|
-
end
|
242
|
+
def rename_column(name_or_number, new_name) # :nodoc: #
|
243
|
+
@ole_table.ListColumns.Item(name_or_number).Name = new_name
|
244
|
+
rescue
|
245
|
+
raise TableError, "could not rename column #{name_or_number.inspect} to #{new_name.inspect}\n#{$!.message}"
|
266
246
|
end
|
267
247
|
|
268
248
|
# contents of a row
|
269
249
|
# @param [Integer] row number
|
270
250
|
# @return [Array] contents of a row
|
271
251
|
def row_values(row_number)
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
raise TableError, "could not read the values of row #{row_number.inspect}"
|
276
|
-
end
|
252
|
+
@ole_table.ListRows.Item(row_number).Range.Value.first.map{|v| v.respond_to?(:gsub) ? v.encode('utf-8') : v}
|
253
|
+
rescue WIN32OLERuntimeError
|
254
|
+
raise TableError, "could not read the values of row #{row_number.inspect}\n#{$!.message}"
|
277
255
|
end
|
278
256
|
|
279
257
|
# sets the contents of a row
|
280
258
|
# @param [Integer] row number
|
281
259
|
# @param [Array] values of the row
|
282
260
|
def set_row_values(row_number, values)
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
raise TableError, "could not set the values of row #{row_number.inspect}"
|
290
|
-
end
|
261
|
+
updated_values = row_values(row_number)
|
262
|
+
updated_values[0,values.length] = values
|
263
|
+
@ole_table.ListRows.Item(row_number).Range.Value = [updated_values]
|
264
|
+
values
|
265
|
+
rescue WIN32OLERuntimeError
|
266
|
+
raise TableError, "could not set the values of row #{row_number.inspect}\n#{$!.message}"
|
291
267
|
end
|
292
268
|
|
293
269
|
# @return [Array] contents of a column
|
294
270
|
def column_values(column_number_or_name)
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
raise TableError, "could not read the values of column #{column_number_or_name.inspect}"
|
299
|
-
end
|
271
|
+
@ole_table.ListColumns.Item(column_number_or_name).Range.Value[1,@ole_table.ListRows.Count].flatten.map{|v| v.respond_to?(:gsub) ? v.encode('utf-8') : v}
|
272
|
+
rescue WIN32OLERuntimeError
|
273
|
+
raise TableError, "could not read the values of column #{column_number_or_name.inspect}\n#{$!.message}"
|
300
274
|
end
|
301
275
|
|
302
276
|
# sets the contents of a column
|
303
277
|
# @param [Integer] column name or column number
|
304
278
|
# @param [Array] contents of the column
|
305
279
|
def set_column_values(column_number_or_name, values)
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
raise TableError, "could not read the values of column #{column_number_or_name.inspect}"
|
314
|
-
end
|
280
|
+
updated_values = column_values(column_number_or_name)
|
281
|
+
updated_values[0,values.length] = values
|
282
|
+
column_name = @ole_table.ListColumns.Item(column_number_or_name).Range.Value.first
|
283
|
+
@ole_table.ListColumns.Item(column_number_or_name).Range.Value = column_name + updated_values.map{|v| [v]}
|
284
|
+
values
|
285
|
+
rescue WIN32OLERuntimeError
|
286
|
+
raise TableError, "could not read the values of column #{column_number_or_name.inspect}\n#{$!.message}"
|
315
287
|
end
|
316
288
|
|
317
289
|
# deletes rows that have an empty contents
|
@@ -324,7 +296,7 @@ module RobustExcelOle
|
|
324
296
|
if row.Range.Value == nil_array
|
325
297
|
row.Delete
|
326
298
|
else
|
327
|
-
i
|
299
|
+
i += 1
|
328
300
|
end
|
329
301
|
end
|
330
302
|
end
|
@@ -339,7 +311,7 @@ module RobustExcelOle
|
|
339
311
|
if column.Range.Value[1..-1] == nil_array
|
340
312
|
column.Delete
|
341
313
|
else
|
342
|
-
i
|
314
|
+
i += 1
|
343
315
|
end
|
344
316
|
end
|
345
317
|
end
|
@@ -348,15 +320,14 @@ module RobustExcelOle
|
|
348
320
|
# @param[Variant] value to find
|
349
321
|
# @return [Array] win32ole cells containing the given value
|
350
322
|
def find_cells(value)
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
323
|
+
encode_utf8 = ->(val) {val.respond_to?(:gsub) ? val.encode('utf-8') : val}
|
324
|
+
listrows = @ole_table.ListRows
|
325
|
+
listrows.map { |listrow|
|
326
|
+
listrow_range = listrow.Range
|
327
|
+
listrow_range.Value.first.map{ |v| encode_utf8.(v) }.find_all_indices(value).map do |col_number|
|
328
|
+
listrow_range.Cells(1,col_number+1).to_reo
|
357
329
|
end
|
358
|
-
|
359
|
-
result
|
330
|
+
}.flatten
|
360
331
|
end
|
361
332
|
|
362
333
|
# sorts the rows of the list object according to the given column
|
@@ -370,6 +341,19 @@ module RobustExcelOle
|
|
370
341
|
@ole_table.Sort.Apply
|
371
342
|
end
|
372
343
|
|
344
|
+
# @return [Array] position of the first cell of the table
|
345
|
+
def position
|
346
|
+
first_cell = self.Range.Cells(1,1)
|
347
|
+
@position = [first_cell.Row, first_cell.Column]
|
348
|
+
end
|
349
|
+
|
350
|
+
def == other_table
|
351
|
+
other_table.is_a?(ListObject) &&
|
352
|
+
self.HeaderRowRange.Value == other_table.HeaderRowRange.Value &&
|
353
|
+
self.DataBodyRange.Value == other_table.DataBodyRange.Value
|
354
|
+
end
|
355
|
+
|
356
|
+
|
373
357
|
# @private
|
374
358
|
# returns true, if the list object responds to VBA methods, false otherwise
|
375
359
|
def alive?
|
@@ -387,9 +371,9 @@ module RobustExcelOle
|
|
387
371
|
|
388
372
|
# @private
|
389
373
|
def inspect
|
390
|
-
"#<ListObject
|
374
|
+
"#<ListObject:#{@ole_table.Name}" +
|
391
375
|
" #{@ole_table.ListRows.Count}x#{@ole_table.ListColumns.Count}" +
|
392
|
-
" #{@ole_table.Parent.Name}
|
376
|
+
" #{@ole_table.Parent.Name} #{@ole_table.Parent.Parent.Name}>"
|
393
377
|
end
|
394
378
|
|
395
379
|
include MethodHelpers
|
@@ -397,22 +381,19 @@ module RobustExcelOle
|
|
397
381
|
private
|
398
382
|
|
399
383
|
def method_missing(name, *args)
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
end
|
407
|
-
else
|
408
|
-
begin
|
409
|
-
@ole_table.send(name, *args)
|
410
|
-
rescue NoMethodError
|
411
|
-
raise VBAMethodMissingError, "unknown VBA property or method #{name.inspect}"
|
412
|
-
end
|
384
|
+
super unless name.to_s[0,1] =~ /[A-Z]/
|
385
|
+
if ::ERRORMESSAGE_JRUBY_BUG
|
386
|
+
begin
|
387
|
+
@ole_table.send(name, *args)
|
388
|
+
rescue Java::OrgRacobCom::ComFailException
|
389
|
+
raise VBAMethodMissingError, "unknown VBA property or method #{name.inspect}"
|
413
390
|
end
|
414
391
|
else
|
415
|
-
|
392
|
+
begin
|
393
|
+
@ole_table.send(name, *args)
|
394
|
+
rescue NoMethodError
|
395
|
+
raise VBAMethodMissingError, "unknown VBA property or method #{name.inspect}"
|
396
|
+
end
|
416
397
|
end
|
417
398
|
end
|
418
399
|
end
|
@@ -421,11 +402,6 @@ module RobustExcelOle
|
|
421
402
|
class TableError < WorksheetREOError
|
422
403
|
end
|
423
404
|
|
424
|
-
# @private
|
425
|
-
class TableRowError < WorksheetREOError
|
426
|
-
end
|
427
|
-
|
428
405
|
Table = ListObject
|
429
|
-
TableRow = ListRow
|
430
406
|
|
431
407
|
end
|