robust_excel_ole 1.19.9 → 1.20
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 +1 -1
- data/README.rdoc +110 -18
- data/bin/jreo +23 -2
- data/bin/{reo.rb → reo} +4 -1
- data/lib/reo_console.rb +1 -1
- data/lib/robust_excel_ole/cell.rb +10 -0
- data/lib/robust_excel_ole/general.rb +79 -19
- data/lib/robust_excel_ole/list_object.rb +255 -4
- data/lib/robust_excel_ole/version.rb +1 -1
- data/lib/robust_excel_ole/workbook.rb +3 -0
- data/spec/bookstore_spec.rb +1 -1
- data/spec/general_spec.rb +13 -1
- data/spec/list_object_spec.rb +213 -8
- data/spec/workbook_spec.rb +12 -0
- metadata +4 -6
- data/bin/reo_old +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1cbad43d74758e37eb8e8d17e0297ead9f7cda838f5a157832145d41bacb743a
|
4
|
+
data.tar.gz: 80a112947a96132e8f8bb5ccccdccace4b7c1227418475aac51d6aa771b2e876
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4983b1d7e31e09873bf70e9903e3bdcd7a438e238283c5f2bae9198b5ed53c83fd5726f55b7e9ad4559b820dca65f2c82cb82f85091b199f4b58adfa98064c6b
|
7
|
+
data.tar.gz: 6c1c920de4c68699a10e87241121a01e66884317f06ad8ce9962b049c024658b797e014ef0aaaa297287065e80d85514d384925f24412bf1175aa8d97c252865
|
data/Changelog
CHANGED
data/README.rdoc
CHANGED
@@ -11,7 +11,7 @@ It supports handling workbooks across Excel instances by keeping track of workbo
|
|
11
11
|
|
12
12
|
Library references are supported.
|
13
13
|
|
14
|
-
RobustExcelOle works by sending VBA methods via
|
14
|
+
RobustExcelOle works by sending VBA methods via WIN32OlE.
|
15
15
|
Therefore, it runs on Windows only.
|
16
16
|
|
17
17
|
== Features
|
@@ -77,10 +77,10 @@ Let's open a workbook.
|
|
77
77
|
|
78
78
|
workbook = Workbook.open 'spec/data/workbook.xls'
|
79
79
|
|
80
|
-
Now we have a Workbook object that wraps a WIN32OLE object. That is,
|
80
|
+
Now we have a Workbook object that wraps a WIN32OLE object. That is, we can send any WIN32OLE (VBA) method to it. See
|
81
81
|
https://docs.microsoft.com/en-us/office/vba/api/excel.workbook#methods.
|
82
82
|
|
83
|
-
For example,
|
83
|
+
For example, we can determine the name of the workbook.
|
84
84
|
|
85
85
|
workbook.Name
|
86
86
|
# => "workbook.xls"
|
@@ -122,11 +122,11 @@ RobustExcelOle allows unobtrusively reading and modifying workbooks, i.e. access
|
|
122
122
|
# do something
|
123
123
|
end
|
124
124
|
|
125
|
-
|
125
|
+
We can also create a new, empty workbook.
|
126
126
|
|
127
127
|
Workbook.create('spec/data/new_workbook.xls', :visible => true)
|
128
128
|
|
129
|
-
Moreover,
|
129
|
+
Moreover, we can open the workbook using a block, similar to, e.g., +File.open+.
|
130
130
|
|
131
131
|
Workbook.open('spec/data/workbook.xls') do |workbook|
|
132
132
|
# do something
|
@@ -318,7 +318,9 @@ and set another value to that range.
|
|
318
318
|
|
319
319
|
For more details about reading and writing contents of cells and ranges see {README_ranges}[https://github.com/Thomas008/robust_excel_ole/blob/master/docs/README_ranges.rdoc]
|
320
320
|
|
321
|
-
===
|
321
|
+
=== List Objects
|
322
|
+
|
323
|
+
=== Creating list objects
|
322
324
|
|
323
325
|
We can define a list object (or table) from scratch.
|
324
326
|
|
@@ -326,25 +328,115 @@ We can define a list object (or table) from scratch.
|
|
326
328
|
|
327
329
|
This command creates a list object in worksheet named "table 1", with upper left corner at position [1,1] (first cell), with 3 rows and the columns "Person" and "Amount".
|
328
330
|
|
329
|
-
|
331
|
+
Likewise we can get a RobustExcelOle list object with help of an existing WIN32OlE list object.
|
332
|
+
|
333
|
+
ole_listobject = worksheet.ListObjects.Item("Table 1")
|
334
|
+
table = ListObject.new(ole_listobject)
|
335
|
+
|
336
|
+
or
|
337
|
+
|
338
|
+
table = ole_listobject.to_reo
|
330
339
|
|
331
|
-
|
340
|
+
Now we have a RobustExcelOle ListObject that wraps a WIN32OLE ListObject. So we can send any WIN32OLE (VBA) method to it. See
|
341
|
+
https://docs.microsoft.com/en-us/office/vba/api/excel.listobject#methods.
|
332
342
|
|
333
|
-
|
343
|
+
A row in this table can be accessed with help of #[], e.g.
|
334
344
|
|
335
|
-
table[1]
|
336
|
-
|
345
|
+
row1 = table[1]
|
346
|
+
|
347
|
+
=== Reading and setting values
|
348
|
+
|
349
|
+
Now we can set and get the value of a cell of the table with help of methods that are underscored versions of the column names, e.g.
|
350
|
+
|
351
|
+
row1.person = "John"
|
352
|
+
row1.person
|
337
353
|
# => "John"
|
338
354
|
|
339
|
-
|
355
|
+
We can also read and set values in a whole row, e.g.
|
340
356
|
|
341
|
-
|
342
|
-
|
357
|
+
table.row_values(1)
|
358
|
+
# => ["John", 40]
|
359
|
+
|
360
|
+
or
|
361
|
+
|
362
|
+
table[1].values
|
363
|
+
# => ["John", 40]
|
364
|
+
|
365
|
+
and
|
366
|
+
|
367
|
+
table.set_row_values(1, ["Herbert", 80])
|
368
|
+
# => ["Herbert", 80]
|
369
|
+
|
370
|
+
or
|
371
|
+
|
372
|
+
table[1].set_values(["Herbert", 80])
|
373
|
+
|
374
|
+
If the number of given values is less than the number of cells in the row, only the first values are written. The remaining values keep their value.
|
375
|
+
|
376
|
+
Similarly, we can read and set the values in a whole column, e.g.
|
377
|
+
|
378
|
+
table.column_values("Person")
|
379
|
+
# => ["John", "Peter"]
|
380
|
+
|
381
|
+
and
|
382
|
+
|
383
|
+
table.set_column_values(1, ["Herbert","Paul"])
|
384
|
+
|
385
|
+
The column names we can get with help of
|
386
|
+
|
387
|
+
table.column_names
|
388
|
+
|
389
|
+
A column can be renamed.
|
390
|
+
|
391
|
+
table.rename_column("Person", "Enterprise")
|
392
|
+
|
393
|
+
or
|
394
|
+
|
395
|
+
table.rename_column(1, "Enterprise")
|
396
|
+
|
397
|
+
=== Adding and Deleting rows and columns
|
398
|
+
|
399
|
+
We can add rows and columns, supplying optionally their name, the position and contents.
|
400
|
+
|
401
|
+
table.add_column("column_name")
|
402
|
+
table.add_column("column_name", 3)
|
403
|
+
table.add_column("column_name", 3, ["John", "Paul"])
|
404
|
+
|
405
|
+
table.add_row(3)
|
406
|
+
table.add_row(3, ["John", 40, 2, 2004])
|
407
|
+
|
408
|
+
Deleting columns and rows is done by
|
409
|
+
|
410
|
+
table.delete_column("column_name")
|
411
|
+
table.delete_row(3)
|
412
|
+
|
413
|
+
We can delete only the contents of a column
|
414
|
+
|
415
|
+
table.delete_column_values("column_name")
|
416
|
+
|
417
|
+
Similarly can delete only the contents of a row.
|
418
|
+
|
419
|
+
table.delete_row_values(2)
|
420
|
+
|
421
|
+
or
|
422
|
+
|
423
|
+
table[2].delete_values
|
424
|
+
|
425
|
+
Finally we can delete empty rows and columns.
|
426
|
+
|
427
|
+
table.delete_empty_rows
|
428
|
+
table.delete_empty_columns
|
429
|
+
|
430
|
+
=== Finding values and sorting
|
431
|
+
|
432
|
+
You can find all cells containing a given value, e.g.
|
433
|
+
|
434
|
+
table.find_value(value)
|
435
|
+
#=> [#<Cell: (5,8)>#, #<Cell: (9,6)>#]
|
436
|
+
|
437
|
+
You can sort a table according to a given column and sort order, e.g.
|
343
438
|
|
344
|
-
|
345
|
-
r4.person
|
346
|
-
# =>
|
347
|
-
r.person = "John"
|
439
|
+
table.sort("Person", :ascending)
|
348
440
|
|
349
441
|
=== More things
|
350
442
|
|
data/bin/jreo
CHANGED
@@ -1,3 +1,24 @@
|
|
1
|
-
|
1
|
+
#!/usr/bin/env jruby
|
2
|
+
# -*- jruby -*-
|
2
3
|
|
3
|
-
|
4
|
+
require 'pry'
|
5
|
+
require 'robust_excel_ole'
|
6
|
+
|
7
|
+
include REO
|
8
|
+
include General
|
9
|
+
|
10
|
+
puts 'REO console started'
|
11
|
+
puts
|
12
|
+
|
13
|
+
# some pry configuration
|
14
|
+
Pry.config.windows_console_warning = false
|
15
|
+
Pry.config.history.should_save = true
|
16
|
+
Pry.config.color = false
|
17
|
+
#Pry.editor = 'notepad' # 'subl', 'vi'
|
18
|
+
#Pry.config.prompt =
|
19
|
+
# [
|
20
|
+
# ->(_obj, _nest_level, _) { ">> " },
|
21
|
+
# ->(*) { " " }
|
22
|
+
# ]
|
23
|
+
|
24
|
+
pry
|
data/bin/{reo.rb → reo}
RENAMED
data/lib/reo_console.rb
CHANGED
@@ -24,6 +24,16 @@ module RobustExcelOle
|
|
24
24
|
@ole_range = @ole_range.MergeArea.Item(1,1) if @ole_range.MergeCells
|
25
25
|
end
|
26
26
|
|
27
|
+
# @private
|
28
|
+
def to_s
|
29
|
+
@ole_table.Name.to_s
|
30
|
+
end
|
31
|
+
|
32
|
+
# @private
|
33
|
+
def inspect
|
34
|
+
"#<Cell:" + " (#{@ole_range.Row},#{@ole_range.Column})" + ">#"
|
35
|
+
end
|
36
|
+
|
27
37
|
private
|
28
38
|
|
29
39
|
# @private
|
@@ -10,28 +10,77 @@ module General
|
|
10
10
|
::CONNECT_EXCEL_JRUBY_BUG = IS_JRUBY_PLATFORM && true
|
11
11
|
::RANGES_JRUBY_BUG = IS_JRUBY_PLATFORM && true
|
12
12
|
|
13
|
+
NetworkDrive = Struct.new(:drive_letter, :network_name) do
|
14
|
+
|
15
|
+
def self.get_all(drives)
|
16
|
+
ndrives = []
|
17
|
+
count = drives.Count
|
18
|
+
(0..(count - 1)).step(2) do |i|
|
19
|
+
ndrives << NetworkDrive.new( drives.Item(i), drives.Item(i + 1))
|
20
|
+
end
|
21
|
+
ndrives
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
13
26
|
@private
|
14
27
|
def network2hostnamesharepath(filename)
|
15
28
|
network = WIN32OLE.new('WScript.Network')
|
16
29
|
drives = network.enumnetworkdrives
|
17
|
-
drive_letter, filename_after_drive_letter = filename.split(':')
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
30
|
+
drive_letter, filename_after_drive_letter = filename.split(':')
|
31
|
+
drive_letter = normalize_drive_letter(drive_letter)
|
32
|
+
network_drives = NetworkDrive.get_all(drives)
|
33
|
+
network_drive = network_drives.find{ |d| d.drive_letter == drive_letter }
|
34
|
+
return filename unless network_drive
|
35
|
+
return network_drive.network_name + filename_after_drive_letter
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.normalize_drive_letter(drive)
|
39
|
+
drive.upcase.end_with?(':') ? drive : "#{drive}:"
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
=begin
|
44
|
+
NetworkDrive = Struct.new(:drive_letter, :network_name)
|
45
|
+
|
46
|
+
@private
|
47
|
+
def network2hostnamesharepath(filename)
|
48
|
+
puts "network2hostnamesharepath:"
|
49
|
+
puts "filename: #{filename}"
|
50
|
+
network = WIN32OLE.new('WScript.Network')
|
51
|
+
drives = network.enumnetworkdrives
|
52
|
+
puts "drives: #{drives.inspect}"
|
53
|
+
drive_letter, filename_after_drive_letter = filename.split(':')
|
54
|
+
puts "drive_letter: #{drive_letter.inspect}"
|
55
|
+
puts "filename_after_drive_letter: #{filename_after_drive_letter.inspect}"
|
56
|
+
drive_letter = normalize_drive_letter(drive_letter)
|
57
|
+
puts "drive_letter: #{drive_letter.inspect}"
|
58
|
+
network_drives = get_network_drives
|
59
|
+
puts "network_drives: #{network_drives.inspect}"
|
60
|
+
network_drive = network_drives.find{ |d| d.drive_letter == drive_letter }
|
61
|
+
puts "network_drive: #{network_drive.inspect}"
|
62
|
+
return filename unless network_drive
|
63
|
+
#return (File.exists?(filename) ? filename : nil) unless network_drive
|
64
|
+
return network_drive.network_name + filename_after_drive_letter
|
65
|
+
end
|
66
|
+
|
67
|
+
def get_network_drives
|
68
|
+
network = WIN32OLE.new('WScript.Network')
|
69
|
+
drives = network.enumnetworkdrives
|
70
|
+
ndrives = []
|
71
|
+
count = drives.Count
|
72
|
+
(0..(count - 1)).step(2) do |i|
|
73
|
+
ndrives << NetworkDrive.new( drives.Item(i), drives.Item(i + 1))
|
32
74
|
end
|
75
|
+
ndrives
|
33
76
|
end
|
34
77
|
|
78
|
+
def normalize_drive_letter(drive)
|
79
|
+
drive.upcase.end_with?(':') ? drive : "#{drive}:"
|
80
|
+
end
|
81
|
+
|
82
|
+
=end
|
83
|
+
|
35
84
|
# @private
|
36
85
|
def absolute_path(file)
|
37
86
|
file[0,2] = './' if ::EXPANDPATH_JRUBY_BUG && file =~ /[A-Z]:[^\/]/
|
@@ -44,11 +93,12 @@ module General
|
|
44
93
|
def canonize(filename)
|
45
94
|
raise TypeREOError, "No string given to canonize, but #{filename.inspect}" unless filename.is_a?(String)
|
46
95
|
filename = network2hostnamesharepath(filename)
|
47
|
-
normalize(filename).downcase
|
96
|
+
normalize(filename).downcase if filename
|
48
97
|
end
|
49
98
|
|
50
99
|
# @private
|
51
|
-
def normalize(path)
|
100
|
+
def normalize(path)
|
101
|
+
return unless path
|
52
102
|
path = path.gsub('/./', '/') + '/'
|
53
103
|
path = path.gsub(/[\/\\]+/, '/')
|
54
104
|
nil while path.gsub!(/(\/|^)(?!\.\.?)([^\/]+)\/\.\.\//, '\1')
|
@@ -90,9 +140,19 @@ class Array
|
|
90
140
|
end
|
91
141
|
end
|
92
142
|
|
143
|
+
def find_each_index find
|
144
|
+
found, index, q = -1, -1, []
|
145
|
+
while found
|
146
|
+
found = self[index+1..-1].index(find)
|
147
|
+
if found
|
148
|
+
index = index + found + 1
|
149
|
+
q << index
|
150
|
+
end
|
151
|
+
end
|
152
|
+
q
|
153
|
+
end
|
93
154
|
end
|
94
155
|
|
95
|
-
|
96
156
|
# @private
|
97
157
|
class WIN32OLE
|
98
158
|
|
@@ -113,7 +173,7 @@ class WIN32OLE
|
|
113
173
|
begin
|
114
174
|
self.send(method)
|
115
175
|
if classname == RobustExcelOle::Range && self.Rows.Count == 1 && self.Columns.Count == 1
|
116
|
-
return Cell.new(self)
|
176
|
+
return Cell.new(self, self.Parent)
|
117
177
|
else
|
118
178
|
return classname.new(self)
|
119
179
|
end
|
@@ -58,6 +58,63 @@ module RobustExcelOle
|
|
58
58
|
def initialize(row_number)
|
59
59
|
@ole_listrow = @@ole_table.ListRows.Item(row_number)
|
60
60
|
end
|
61
|
+
|
62
|
+
# returns the value of the cell with given column name or number
|
63
|
+
# @param [Variant] column number or column name
|
64
|
+
# @return [Variant] value of the cell
|
65
|
+
def [] column_number_or_name
|
66
|
+
begin
|
67
|
+
ole_cell = @@ole_table.Application.Intersect(
|
68
|
+
@ole_listrow.Range, @@ole_table.ListColumns.Item(column_number_or_name).Range)
|
69
|
+
ole_cell.Value
|
70
|
+
rescue WIN32OLERuntimeError
|
71
|
+
raise TableRowError, "could not determine the value at column #{column_number_or_name}"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
def []=(column_number_or_name, value)
|
77
|
+
begin
|
78
|
+
ole_cell = @@ole_table.Application.Intersect(
|
79
|
+
@ole_listrow.Range, @@ole_table.ListColumns.Item(column_number_or_name).Range)
|
80
|
+
ole_cell.Value = value
|
81
|
+
rescue WIN32OLERuntimeError
|
82
|
+
raise TableRowError, "could not assign value #{value.inspect} to cell at column #{column_number_or_name}"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# values of the row
|
87
|
+
# @return [Array] values of the row
|
88
|
+
def values
|
89
|
+
begin
|
90
|
+
@ole_listrow.Range.Value.first
|
91
|
+
rescue WIN32OLERuntimeError
|
92
|
+
raise TableError, "could not read values"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# sets the values of the row
|
97
|
+
# @param [Array] values of the row
|
98
|
+
def set_values values
|
99
|
+
begin
|
100
|
+
updated_values = self.values
|
101
|
+
updated_values[0,values.length] = values
|
102
|
+
@ole_listrow.Range.Value = [updated_values]
|
103
|
+
values
|
104
|
+
rescue WIN32OLERuntimeError
|
105
|
+
raise TableError, "could not set values #{values.inspect}"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# deletes the values of the row
|
110
|
+
def delete_values
|
111
|
+
begin
|
112
|
+
@ole_listrow.Range.Value = [[].fill(nil,0..(@@ole_table.ListColumns.Count)-1)]
|
113
|
+
nil
|
114
|
+
rescue WIN32OLERuntimeError
|
115
|
+
raise TableError, "could not delete values"
|
116
|
+
end
|
117
|
+
end
|
61
118
|
|
62
119
|
def method_missing(name, *args)
|
63
120
|
name_before_last_equal = name.to_s.split('=').first
|
@@ -66,7 +123,7 @@ module RobustExcelOle
|
|
66
123
|
column_name = column_names[method_names.index(name_before_last_equal)]
|
67
124
|
if column_name
|
68
125
|
ole_cell = @@ole_table.Application.Intersect(
|
69
|
-
@ole_listrow.Range, @@ole_table.ListColumns(column_name).Range)
|
126
|
+
@ole_listrow.Range, @@ole_table.ListColumns.Item(column_name).Range)
|
70
127
|
define_getting_setting_method(ole_cell,name.to_s)
|
71
128
|
self.send(name, *args)
|
72
129
|
else
|
@@ -98,8 +155,198 @@ module RobustExcelOle
|
|
98
155
|
|
99
156
|
end
|
100
157
|
|
158
|
+
# @return [Array] a list of column names
|
101
159
|
def column_names
|
102
|
-
|
160
|
+
begin
|
161
|
+
@ole_table.HeaderRowRange.Value.first
|
162
|
+
rescue WIN32OLERuntimeError
|
163
|
+
raise TableError, "could not determine column names"
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
# adds a row
|
168
|
+
# @param [Integer] position of the new row
|
169
|
+
# @param [Array] values of the column
|
170
|
+
def add_row(position = nil, contents = nil)
|
171
|
+
begin
|
172
|
+
@ole_table.ListRows.Add(position)
|
173
|
+
set_row_values(position, contents) if contents
|
174
|
+
rescue WIN32OLERuntimeError
|
175
|
+
raise TableError, ("could not add row" + (" at position #{position.inspect}" if position))
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
# adds a column
|
180
|
+
# @param [String] name of the column
|
181
|
+
# @param [Integer] position of the new column
|
182
|
+
# @param [Array] values of the column
|
183
|
+
def add_column(column_name = nil, position = nil, contents = nil)
|
184
|
+
begin
|
185
|
+
new_column = @ole_table.ListColumns.Add(position)
|
186
|
+
new_column.Name = column_name if column_name
|
187
|
+
set_column_values(column_name, contents) if contents
|
188
|
+
rescue WIN32OLERuntimeError, TableError
|
189
|
+
raise TableError, ("could not add column"+ ("at position #{position.inspect} with name #{column_name.inspect}" if position))
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
# deletes a row
|
194
|
+
# @param [Integer] position of the old row
|
195
|
+
def delete_row(row_number)
|
196
|
+
begin
|
197
|
+
@ole_table.ListRows.Item(row_number).Delete
|
198
|
+
rescue WIN32OLERuntimeError
|
199
|
+
raise TableError, "could not delete row #{row_number.inspect}"
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
# deletes a column
|
204
|
+
# @param [Variant] column number or column name
|
205
|
+
def delete_column(column_number_or_name)
|
206
|
+
begin
|
207
|
+
@ole_table.ListColumns.Item(column_number_or_name).Delete
|
208
|
+
rescue WIN32OLERuntimeError
|
209
|
+
raise TableError, "could not delete column #{column_number_or_name.inspect}"
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
# deletes the contents of a row
|
214
|
+
# @param [Integer] row number
|
215
|
+
def delete_row_values(row_number)
|
216
|
+
begin
|
217
|
+
@ole_table.ListRows.Item(row_number).Range.Value = [[].fill(nil,0..(@ole_table.ListColumns.Count-1))]
|
218
|
+
nil
|
219
|
+
rescue WIN32OLERuntimeError
|
220
|
+
raise TableError, "could not delete contents of row #{row_number.inspect}"
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
# deletes the contents of a column
|
225
|
+
# @param [Variant] column number or column name
|
226
|
+
def delete_column_values(column_number_or_name)
|
227
|
+
begin
|
228
|
+
column_name = @ole_table.ListColumns.Item(column_number_or_name).Range.Value.first
|
229
|
+
@ole_table.ListColumns.Item(column_number_or_name).Range.Value = [column_name] + [].fill([nil],0..(@ole_table.ListRows.Count-1))
|
230
|
+
nil
|
231
|
+
rescue WIN32OLERuntimeError
|
232
|
+
raise TableError, "could not delete contents of column #{column_number_or_name.inspect}"
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
# renames a row
|
237
|
+
# @param [String] previous name or number of the column
|
238
|
+
# @param [String] new name of the column
|
239
|
+
def rename_column(name_or_number, new_name)
|
240
|
+
begin
|
241
|
+
@ole_table.ListColumns.Item(name_or_number).Name = new_name
|
242
|
+
rescue
|
243
|
+
raise TableError, "could not rename column #{name_or_number.inspect} to #{new_name.inspect}"
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
# contents of a row
|
248
|
+
# @param [Integer] row number
|
249
|
+
# @return [Array] contents of a row
|
250
|
+
def row_values(row_number)
|
251
|
+
begin
|
252
|
+
@ole_table.ListRows.Item(row_number).Range.Value.first
|
253
|
+
rescue WIN32OLERuntimeError
|
254
|
+
raise TableError, "could not read the values of row #{row_number.inspect}"
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
# sets the contents of a row
|
259
|
+
# @param [Integer] row number
|
260
|
+
# @param [Array] values of the row
|
261
|
+
def set_row_values(row_number, values)
|
262
|
+
begin
|
263
|
+
updated_values = row_values(row_number)
|
264
|
+
updated_values[0,values.length] = values
|
265
|
+
@ole_table.ListRows.Item(row_number).Range.Value = [updated_values]
|
266
|
+
values
|
267
|
+
rescue WIN32OLERuntimeError
|
268
|
+
raise TableError, "could not set the values of row #{row_number.inspect}"
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
# @return [Array] contents of a column
|
273
|
+
def column_values(column_number_or_name)
|
274
|
+
begin
|
275
|
+
@ole_table.ListColumns.Item(column_number_or_name).Range.Value[1,@ole_table.ListRows.Count].flatten
|
276
|
+
rescue WIN32OLERuntimeError
|
277
|
+
raise TableError, "could not read the values of column #{column_number_or_name.inspect}"
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
# sets the contents of a column
|
282
|
+
# @param [Integer] column name or column number
|
283
|
+
# @param [Array] contents of the column
|
284
|
+
def set_column_values(column_number_or_name, values)
|
285
|
+
begin
|
286
|
+
updated_values = column_values(column_number_or_name)
|
287
|
+
updated_values[0,values.length] = values
|
288
|
+
column_name = @ole_table.ListColumns.Item(column_number_or_name).Range.Value.first
|
289
|
+
@ole_table.ListColumns.Item(column_number_or_name).Range.Value = column_name + updated_values.map{|v| [v]}
|
290
|
+
values
|
291
|
+
rescue WIN32OLERuntimeError
|
292
|
+
raise TableError, "could not read the values of column #{column_number_or_name.inspect}"
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
# deletes rows that have an empty contents
|
297
|
+
def delete_empty_rows
|
298
|
+
listrows = @ole_table.ListRows
|
299
|
+
nil_array = [[].fill(nil,0..(@ole_table.ListColumns.Count-1))]
|
300
|
+
i = 1
|
301
|
+
while i <= listrows.Count do
|
302
|
+
row = listrows.Item(i)
|
303
|
+
if row.Range.Value == nil_array
|
304
|
+
row.Delete
|
305
|
+
else
|
306
|
+
i = i+1
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
# deletes columns that have an empty contents
|
312
|
+
def delete_empty_columns
|
313
|
+
listcolumns = @ole_table.ListColumns
|
314
|
+
nil_array = [].fill([nil],0..(@ole_table.ListRows.Count-1))
|
315
|
+
i = 1
|
316
|
+
while i <= listcolumns.Count do
|
317
|
+
column = listcolumns.Item(i)
|
318
|
+
if column.Range.Value[1..-1] == nil_array
|
319
|
+
column.Delete
|
320
|
+
else
|
321
|
+
i = i+1
|
322
|
+
end
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
# finds all cells containing a given value
|
327
|
+
# @param[Variant] value to find
|
328
|
+
# @return [Array] win32ole cells containing the given value
|
329
|
+
def find_cells(value)
|
330
|
+
listrows = @ole_table.ListRows
|
331
|
+
result = []
|
332
|
+
(1..listrows.Count).each do |row_number|
|
333
|
+
row_values(row_number).find_each_index(value).each do |col_number|
|
334
|
+
result << @ole_table.Application.Intersect(listrows.Item(row_number).Range,
|
335
|
+
@ole_table.ListColumns.Item(col_number+1).Range).to_reo
|
336
|
+
end
|
337
|
+
end
|
338
|
+
result
|
339
|
+
end
|
340
|
+
|
341
|
+
# sorts the rows of the list object according to the given column
|
342
|
+
# @param [Variant] column number or name
|
343
|
+
# @option opts [Symbol] sort order
|
344
|
+
def sort(column_number_or_name, sort_order = :ascending)
|
345
|
+
key_range = @ole_table.ListColumns.Item(column_number_or_name).Range
|
346
|
+
@ole_table.Sort.SortFields.Clear
|
347
|
+
sort_order_option = sort_order == :ascending ? XlAscending : XlDescending
|
348
|
+
@ole_table.Sort.SortFields.Add(key_range, XlSortOnValues,sort_order_option,XlSortNormal)
|
349
|
+
@ole_table.Sort.Apply
|
103
350
|
end
|
104
351
|
|
105
352
|
# @private
|
@@ -110,8 +357,8 @@ module RobustExcelOle
|
|
110
357
|
# @private
|
111
358
|
def inspect
|
112
359
|
"#<ListObject:" + "#{@ole_table.Name}" +
|
113
|
-
"
|
114
|
-
"
|
360
|
+
" #{@ole_table.ListRows.Count}x#{@ole_table.ListColumns.Count}" +
|
361
|
+
" #{@ole_table.Parent.Name}" + " #{@ole_table.Parent.Parent.Name}" + ">"
|
115
362
|
end
|
116
363
|
|
117
364
|
private
|
@@ -141,6 +388,10 @@ module RobustExcelOle
|
|
141
388
|
class TableError < WorksheetREOError
|
142
389
|
end
|
143
390
|
|
391
|
+
# @private
|
392
|
+
class TableRowError < WorksheetREOError
|
393
|
+
end
|
394
|
+
|
144
395
|
Table = ListObject
|
145
396
|
TableRow = ListRow
|
146
397
|
|
@@ -97,6 +97,9 @@ module RobustExcelOle
|
|
97
97
|
when String
|
98
98
|
file = file_or_workbook
|
99
99
|
raise FileNotFound, "file #{General.absolute_path(file).inspect} is a directory" if File.directory?(file)
|
100
|
+
when ->(n){ n.respond_to? :to_path }
|
101
|
+
file = file_or_workbook.to_path
|
102
|
+
raise FileNotFound, "file #{General.absolute_path(file).inspect} is a directory" if File.directory?(file)
|
100
103
|
else
|
101
104
|
raise TypeREOError, 'given object is neither a filename, a Win32ole, nor a Workbook object'
|
102
105
|
end
|
data/spec/bookstore_spec.rb
CHANGED
@@ -59,7 +59,7 @@ describe Bookstore do
|
|
59
59
|
@file_path = "spec/data/workbook.xls"
|
60
60
|
@absolute_file_path = "C:/gim/ats/aSrc/gems/robust_excel_ole/spec/data/workbook.xls"
|
61
61
|
@network_path = "N:/data/workbook.xls"
|
62
|
-
@hostname_share_path = "DESKTOP-A3C5CJ6/spec/workbook.xls"
|
62
|
+
@hostname_share_path = "DESKTOP-A3C5CJ6/spec/data/workbook.xls"
|
63
63
|
end
|
64
64
|
|
65
65
|
after do
|
data/spec/general_spec.rb
CHANGED
@@ -29,6 +29,10 @@ module RobustExcelOle
|
|
29
29
|
@linked_file = @dir + '/workbook_linked.xlsm'
|
30
30
|
@simple_file_xlsm = @dir + '/workbook.xls'
|
31
31
|
@simple_file_xlsx = @dir + '/workbook.xlsx'
|
32
|
+
@network_path = "N:/data/workbook.xls"
|
33
|
+
@hostname_share_path = "//DESKTOP-A3C5CJ6/spec/data/workbook.xls"
|
34
|
+
@simple_file_extern = "D:/data/workbook.xls"
|
35
|
+
@hostname_share_path = "//DESKTOP-A3C5CJ6/spec/data/workbook.xls"
|
32
36
|
end
|
33
37
|
|
34
38
|
after do
|
@@ -186,7 +190,7 @@ module RobustExcelOle
|
|
186
190
|
filename = 'C:/Dokumente und Einstellungen/Zauberthomas/Eigene Dateien/robust_excel_ole/spec/book_spec.rb'
|
187
191
|
absolute_path(filename).gsub("\\","/").should == filename
|
188
192
|
end
|
189
|
-
end
|
193
|
+
end
|
190
194
|
end
|
191
195
|
|
192
196
|
describe "canonize" do
|
@@ -230,6 +234,14 @@ module RobustExcelOle
|
|
230
234
|
}.to raise_error(TypeREOError, "No string given to canonize, but 1")
|
231
235
|
end
|
232
236
|
|
237
|
+
it "should yield the hostname share path" do
|
238
|
+
General.canonize(@network_path).should == normalize(@hostname_share_path).downcase
|
239
|
+
General.canonize(@hostname_share_path).should == normalize(@hostname_share_path).downcase
|
240
|
+
General.canonize(@simple_file).should == normalize(@simple_file).downcase
|
241
|
+
General.canonize(@simple_file_extern).should == normalize(@simple_file_extern).downcase
|
242
|
+
end
|
243
|
+
|
244
|
+
|
233
245
|
end
|
234
246
|
end
|
235
247
|
|
data/spec/list_object_spec.rb
CHANGED
@@ -45,7 +45,7 @@ describe ListObject do
|
|
45
45
|
ole_table = @sheet.ListObjects.Item(1)
|
46
46
|
table = Table.new(ole_table)
|
47
47
|
table.Name.should == "table3"
|
48
|
-
table.HeaderRowRange.Value.first.should == ["Number","Person","Amount","Time","
|
48
|
+
table.HeaderRowRange.Value.first.should == ["Number","Person","Amount","Time","Price"]
|
49
49
|
table.ListRows.Count.should == 6
|
50
50
|
@sheet[3,4].Value.should == "Number"
|
51
51
|
end
|
@@ -54,7 +54,7 @@ describe ListObject do
|
|
54
54
|
ole_table = @sheet.ListObjects.Item(1)
|
55
55
|
table = Table.new(@sheet, "table3")
|
56
56
|
table.Name.should == "table3"
|
57
|
-
table.HeaderRowRange.Value.first.should == ["Number","Person","Amount","Time","
|
57
|
+
table.HeaderRowRange.Value.first.should == ["Number","Person","Amount","Time","Price"]
|
58
58
|
table.ListRows.Count.should == 6
|
59
59
|
@sheet[3,4].Value.should == "Number"
|
60
60
|
end
|
@@ -63,7 +63,7 @@ describe ListObject do
|
|
63
63
|
ole_table = @sheet.ListObjects.Item(1)
|
64
64
|
table = Table.new(@sheet, 1)
|
65
65
|
table.Name.should == "table3"
|
66
|
-
table.HeaderRowRange.Value.first.should == ["Number","Person","Amount","Time","
|
66
|
+
table.HeaderRowRange.Value.first.should == ["Number","Person","Amount","Time","Price"]
|
67
67
|
table.ListRows.Count.should == 6
|
68
68
|
@sheet[3,4].Value.should == "Number"
|
69
69
|
end
|
@@ -80,7 +80,7 @@ describe ListObject do
|
|
80
80
|
ole_table = @sheet.ListObjects.Item(1)
|
81
81
|
table = Table.new(@sheet.ole_worksheet, "table3")
|
82
82
|
table.Name.should == "table3"
|
83
|
-
table.HeaderRowRange.Value.first.should == ["Number","Person","Amount","Time","
|
83
|
+
table.HeaderRowRange.Value.first.should == ["Number","Person","Amount","Time","Price"]
|
84
84
|
table.ListRows.Count.should == 6
|
85
85
|
@sheet[3,4].Value.should == "Number"
|
86
86
|
end
|
@@ -89,7 +89,7 @@ describe ListObject do
|
|
89
89
|
ole_table = @sheet.ListObjects.Item(1)
|
90
90
|
table = Table.new(@sheet.ole_worksheet, 1)
|
91
91
|
table.Name.should == "table3"
|
92
|
-
table.HeaderRowRange.Value.first.should == ["Number","Person","Amount","Time","
|
92
|
+
table.HeaderRowRange.Value.first.should == ["Number","Person","Amount","Time","Price"]
|
93
93
|
table.ListRows.Count.should == 6
|
94
94
|
@sheet[3,4].Value.should == "Number"
|
95
95
|
end
|
@@ -117,6 +117,7 @@ describe ListObject do
|
|
117
117
|
@table_row1.amount.should == 42
|
118
118
|
@sheet[2,2].Value.should == 42
|
119
119
|
end
|
120
|
+
|
120
121
|
end
|
121
122
|
|
122
123
|
context "with type-lifted ole list object" do
|
@@ -132,12 +133,216 @@ describe ListObject do
|
|
132
133
|
@table_row1.number = 1
|
133
134
|
@table_row1.number.should == 1
|
134
135
|
@sheet[4,4].Value.should == 1
|
135
|
-
@table_row1.person.should == "Herbert"
|
136
|
-
@table_row1.person = "John"
|
137
136
|
@table_row1.person.should == "John"
|
138
|
-
@
|
137
|
+
@table_row1.person = "Herbert"
|
138
|
+
@table_row1.person.should == "Herbert"
|
139
|
+
@sheet[4,5].Value.should == "Herbert"
|
139
140
|
end
|
140
141
|
end
|
141
142
|
|
142
143
|
end
|
144
|
+
|
145
|
+
describe "reading and setting contents of rows and columns" do
|
146
|
+
|
147
|
+
before do
|
148
|
+
ole_table = @sheet.ListObjects.Item(1)
|
149
|
+
@table = Table.new(ole_table)
|
150
|
+
end
|
151
|
+
|
152
|
+
it "should read contents of a column" do
|
153
|
+
@table.column_values("Person").should == ["John","Fred",nil,"Angel",nil,"Werner"]
|
154
|
+
expect{
|
155
|
+
@table.column_values("P")
|
156
|
+
}.to raise_error(TableError)
|
157
|
+
end
|
158
|
+
|
159
|
+
it "should set contents of a column" do
|
160
|
+
@table.set_column_values("Person",["H",nil,nil,nil,"G","W"])
|
161
|
+
@table.ListColumns.Item(2).Range.Value.should == [["Person"],["H"],[nil],[nil],[nil],["G"],["W"]]
|
162
|
+
@table.set_column_values("Person",["T","Z"])
|
163
|
+
@table.ListColumns.Item(2).Range.Value.should == [["Person"],["T"],["Z"],[nil],[nil],["G"],["W"]]
|
164
|
+
expect{
|
165
|
+
@table.set_column_values("P",["H",nil,nil,nil,"G","W"])
|
166
|
+
}.to raise_error(TableError)
|
167
|
+
end
|
168
|
+
|
169
|
+
it "should read contents of a row" do
|
170
|
+
@table.row_values(1).should == [3.0, "John", 50.0, 0.5, 30]
|
171
|
+
@table[1].values.should == [3.0, "John", 50.0, 0.5, 30]
|
172
|
+
expect{
|
173
|
+
@table.row_values(9)
|
174
|
+
}.to raise_error(TableError)
|
175
|
+
end
|
176
|
+
|
177
|
+
it "should set contents of a row" do
|
178
|
+
@table.set_row_values(1, [5, "George", 30.0, 0.2, 50])
|
179
|
+
@table.ListRows.Item(1).Range.Value.first.should == [5, "George", 30.0, 0.2, 50]
|
180
|
+
@table.set_row_values(1, [6, "Martin"])
|
181
|
+
@table.ListRows.Item(1).Range.Value.first.should == [6, "Martin", 30.0, 0.2, 50]
|
182
|
+
@table[1].set_values([2, "Merlin", 20.0, 0.1, 40])
|
183
|
+
@table[1].set_values([4, "John"])
|
184
|
+
@table.ListRows.Item(1).Range.Value.first.should == [4, "John", 20.0, 0.1, 40]
|
185
|
+
expect{
|
186
|
+
@table.set_row_values(9, [5, "George", 30.0, 0.2, 50])
|
187
|
+
}.to raise_error(TableError)
|
188
|
+
end
|
189
|
+
|
190
|
+
end
|
191
|
+
|
192
|
+
describe "renaming, adding and deleting columns and rows" do
|
193
|
+
|
194
|
+
before do
|
195
|
+
ole_table = @sheet.ListObjects.Item(1)
|
196
|
+
@table = Table.new(ole_table)
|
197
|
+
end
|
198
|
+
|
199
|
+
it "should list column names" do
|
200
|
+
@table.column_names.should == @table.HeaderRowRange.Value.first
|
201
|
+
end
|
202
|
+
|
203
|
+
it "should rename a column name" do
|
204
|
+
@table.rename_column("Person", "P")
|
205
|
+
@table.HeaderRowRange.Value.first.should == ["Number","P","Amount","Time","Price"]
|
206
|
+
end
|
207
|
+
|
208
|
+
it "should append a column" do
|
209
|
+
@table.add_column("column_name")
|
210
|
+
column_names = @table.HeaderRowRange.Value.first.should == ["Number","Person", "Amount","Time","Price", "column_name"]
|
211
|
+
end
|
212
|
+
|
213
|
+
it "should add a column" do
|
214
|
+
@table.add_column("column_name", 3)
|
215
|
+
column_names = @table.HeaderRowRange.Value.first.should == ["Number","Person","column_name","Amount","Time","Price"]
|
216
|
+
expect{
|
217
|
+
@table.add_column(8, "column_name")
|
218
|
+
}.to raise_error(TableError)
|
219
|
+
end
|
220
|
+
|
221
|
+
it "should add a column with contents" do
|
222
|
+
@table.add_column("column_name", 3, ["a","b","c","d","e","f"])
|
223
|
+
column_names = @table.HeaderRowRange.Value.first.should == ["Number","Person","column_name","Amount","Time","Price"]
|
224
|
+
@table.ListColumns.Item(3).Range.Value.should == [["column_name"],["a"],["b"],["c"],["d"],["e"],["f"]]
|
225
|
+
end
|
226
|
+
|
227
|
+
it "should delete a column" do
|
228
|
+
@table.delete_column(4)
|
229
|
+
@table.HeaderRowRange.Value.first.should == ["Number","Person", "Amount","Price"]
|
230
|
+
expect{
|
231
|
+
@table.delete_column(6)
|
232
|
+
}.to raise_error(TableError)
|
233
|
+
end
|
234
|
+
|
235
|
+
it "should append a row" do
|
236
|
+
@table.add_row
|
237
|
+
listrows = @table.ListRows
|
238
|
+
listrows.Item(listrows.Count).Range.Value.first.should == [nil,nil,nil,nil,nil]
|
239
|
+
end
|
240
|
+
|
241
|
+
it "should add a row" do
|
242
|
+
@table.add_row(2)
|
243
|
+
listrows = @table.ListRows
|
244
|
+
listrows.Item(1).Range.Value.first.should == [3.0, "John", 50.0, 0.5, 30]
|
245
|
+
listrows.Item(2).Range.Value.first.should == [nil,nil,nil,nil,nil]
|
246
|
+
listrows.Item(3).Range.Value.first.should == [2.0, "Fred", nil, 0.5416666666666666, 40]
|
247
|
+
expect{
|
248
|
+
@table.add_row(9)
|
249
|
+
}.to raise_error(TableError)
|
250
|
+
end
|
251
|
+
|
252
|
+
it "should add a row with contents" do
|
253
|
+
@table.add_row(2, [2.0, "Herbert", 30.0, 0.25, 40])
|
254
|
+
listrows = @table.ListRows
|
255
|
+
listrows.Item(1).Range.Value.first.should == [3.0, "John", 50.0, 0.5, 30]
|
256
|
+
listrows.Item(2).Range.Value.first.should == [2.0, "Herbert", 30.0, 0.25, 40]
|
257
|
+
listrows.Item(3).Range.Value.first.should == [2.0, "Fred", nil, 0.5416666666666666, 40]
|
258
|
+
end
|
259
|
+
|
260
|
+
it "should delete a row" do
|
261
|
+
@table.delete_row(4)
|
262
|
+
listrows = @table.ListRows
|
263
|
+
listrows.Item(5).Range.Value.first.should == [1,"Werner",40,0.5, 80]
|
264
|
+
listrows.Item(4).Range.Value.first.should == [nil,nil,nil,nil,nil]
|
265
|
+
expect{
|
266
|
+
@table.delete_row(8)
|
267
|
+
}.to raise_error(TableError)
|
268
|
+
end
|
269
|
+
|
270
|
+
it "should delete the contents of a column" do
|
271
|
+
@table.ListColumns.Item(3).Range.Value.should == [["Amount"],[50],[nil],[nil],[100],[nil],[40]]
|
272
|
+
@table.delete_column_values(3)
|
273
|
+
@table.HeaderRowRange.Value.first.should == ["Number","Person", "Amount", "Time","Price"]
|
274
|
+
@table.ListColumns.Item(3).Range.Value.should == [["Amount"],[nil],[nil],[nil],[nil],[nil],[nil]]
|
275
|
+
@table.ListColumns.Item(1).Range.Value.should == [["Number"],[3],[2],[nil],[3],[nil],[1]]
|
276
|
+
@table.delete_column_values("Number")
|
277
|
+
@table.ListColumns.Item(1).Range.Value.should == [["Number"],[nil],[nil],[nil],[nil],[nil],[nil]]
|
278
|
+
expect{
|
279
|
+
@table.delete_column_values("N")
|
280
|
+
}.to raise_error(TableError)
|
281
|
+
end
|
282
|
+
|
283
|
+
it "should delete the contents of a row" do
|
284
|
+
@table.ListRows.Item(2).Range.Value.first.should == [2.0, "Fred", nil, 0.5416666666666666, 40]
|
285
|
+
@table.delete_row_values(2)
|
286
|
+
@table.ListRows.Item(2).Range.Value.first.should == [nil,nil,nil,nil,nil]
|
287
|
+
@table.ListRows.Item(1).Range.Value.first.should == [3.0, "John", 50.0, 0.5, 30]
|
288
|
+
@table[1].delete_values
|
289
|
+
@table.ListRows.Item(1).Range.Value.first.should == [nil,nil,nil,nil,nil]
|
290
|
+
expect{
|
291
|
+
@table.delete_row_values(9)
|
292
|
+
}.to raise_error(TableError)
|
293
|
+
end
|
294
|
+
|
295
|
+
it "should delete empty rows" do
|
296
|
+
@table.delete_empty_rows
|
297
|
+
@table.ListRows.Count.should == 4
|
298
|
+
@table.ListRows.Item(1).Range.Value.first.should == [3.0, "John", 50.0, 0.5, 30]
|
299
|
+
@table.ListRows.Item(2).Range.Value.first.should == [2.0, "Fred", nil, 0.5416666666666666, 40]
|
300
|
+
@table.ListRows.Item(3).Range.Value.first.should == [3, "Angel", 100, 0.6666666666666666, 60]
|
301
|
+
@table.ListRows.Item(4).Range.Value.first.should == [1,"Werner",40,0.5, 80]
|
302
|
+
end
|
303
|
+
|
304
|
+
it "should delete empty columns" do
|
305
|
+
@table.delete_column_values(4)
|
306
|
+
@table.ListColumns.Count.should == 5
|
307
|
+
@table.HeaderRowRange.Value.first.should == ["Number","Person", "Amount", "Time","Price"]
|
308
|
+
@table.delete_empty_columns
|
309
|
+
@table.ListColumns.Count.should == 4
|
310
|
+
@table.HeaderRowRange.Value.first.should == ["Number","Person", "Amount","Price"]
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
describe "find all cells of a given value" do
|
315
|
+
|
316
|
+
before do
|
317
|
+
ole_table = @sheet.ListObjects.Item(1)
|
318
|
+
@table = Table.new(ole_table)
|
319
|
+
end
|
320
|
+
|
321
|
+
it "should find all cells" do
|
322
|
+
cells = @table.find_cells(40)
|
323
|
+
cells[0].Row.should == 5
|
324
|
+
cells[0].Column.should == 8
|
325
|
+
cells[1].Row.should == 9
|
326
|
+
cells[1].Column.should == 6
|
327
|
+
end
|
328
|
+
|
329
|
+
end
|
330
|
+
|
331
|
+
describe "sort the table" do
|
332
|
+
|
333
|
+
before do
|
334
|
+
ole_table = @sheet.ListObjects.Item(1)
|
335
|
+
@table = Table.new(ole_table)
|
336
|
+
end
|
337
|
+
|
338
|
+
it "should sort the table according to first table" do
|
339
|
+
@table.sort("Number")
|
340
|
+
@table.ListRows.Item(1).Range.Value.first.should == [1,"Werner",40,0.5, 80]
|
341
|
+
@table.ListRows.Item(2).Range.Value.first.should == [2, "Fred", nil, 0.5416666666666666, 40]
|
342
|
+
@table.ListRows.Item(3).Range.Value.first.should == [3, "John", 50.0, 0.5, 30]
|
343
|
+
@table.ListRows.Item(4).Range.Value.first.should == [3, "Angel", 100, 0.6666666666666666, 60]
|
344
|
+
end
|
345
|
+
|
346
|
+
end
|
347
|
+
|
143
348
|
end
|
data/spec/workbook_spec.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
|
3
3
|
require File.join(File.dirname(__FILE__), './spec_helper')
|
4
|
+
require 'pathname'
|
4
5
|
|
5
6
|
$VERBOSE = nil
|
6
7
|
|
@@ -20,6 +21,7 @@ describe Workbook do
|
|
20
21
|
before do
|
21
22
|
@dir = create_tmpdir
|
22
23
|
@simple_file = @dir + '/workbook.xls'
|
24
|
+
@pathname_file = Pathname(@dir) + 'workbook.xls'
|
23
25
|
@simple_save_file = @dir + '/workbook_save.xls'
|
24
26
|
@different_file = @dir + '/different_workbook.xls'
|
25
27
|
@simple_file_other_path = @dir + '/more_data/workbook.xls'
|
@@ -47,6 +49,16 @@ describe Workbook do
|
|
47
49
|
@book.close
|
48
50
|
end
|
49
51
|
end
|
52
|
+
|
53
|
+
context "with pathname" do
|
54
|
+
it "open an existing file" do
|
55
|
+
expect {
|
56
|
+
@book = Workbook.open(@pathname_file)
|
57
|
+
}.to_not raise_error
|
58
|
+
@book.should be_a Workbook
|
59
|
+
@book.close
|
60
|
+
end
|
61
|
+
end
|
50
62
|
end
|
51
63
|
|
52
64
|
describe "Book" do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: robust_excel_ole
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: '1.20'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- traths
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-07-
|
11
|
+
date: 2020-07-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pry
|
@@ -49,8 +49,7 @@ email:
|
|
49
49
|
- Thomas.Raths@gmx.net
|
50
50
|
executables:
|
51
51
|
- jreo
|
52
|
-
- reo
|
53
|
-
- reo_old
|
52
|
+
- reo
|
54
53
|
extensions: []
|
55
54
|
extra_rdoc_files:
|
56
55
|
- README.rdoc
|
@@ -80,8 +79,7 @@ files:
|
|
80
79
|
- benchmarking/simple_xlsx_reader_example.rb
|
81
80
|
- benchmarking/spreadsheet_example.rb
|
82
81
|
- bin/jreo
|
83
|
-
- bin/reo
|
84
|
-
- bin/reo_old
|
82
|
+
- bin/reo
|
85
83
|
- docs/README_excel.rdoc
|
86
84
|
- docs/README_open.rdoc
|
87
85
|
- docs/README_ranges.rdoc
|
data/bin/reo_old
DELETED