robust_excel_ole 1.14 → 1.18.1

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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/Changelog +34 -1
  3. data/README.rdoc +20 -6
  4. data/___dummy_workbook.xls +0 -0
  5. data/docs/README_excel.rdoc +7 -1
  6. data/docs/README_open.rdoc +45 -20
  7. data/docs/README_ranges.rdoc +11 -2
  8. data/examples/example_ruby_library.rb +27 -0
  9. data/extconf.rb +13 -0
  10. data/lib/robust_excel_ole.rb +4 -3
  11. data/lib/robust_excel_ole/{address.rb → address_tool.rb} +23 -22
  12. data/lib/robust_excel_ole/{reo_common.rb → base.rb} +2 -90
  13. data/lib/robust_excel_ole/bookstore.rb +14 -77
  14. data/lib/robust_excel_ole/cell.rb +30 -18
  15. data/lib/robust_excel_ole/excel.rb +105 -64
  16. data/lib/robust_excel_ole/general.rb +40 -15
  17. data/lib/robust_excel_ole/range.rb +42 -19
  18. data/lib/robust_excel_ole/range_owners.rb +40 -25
  19. data/lib/robust_excel_ole/vba_objects.rb +30 -0
  20. data/lib/robust_excel_ole/version.rb +1 -1
  21. data/lib/robust_excel_ole/workbook.rb +310 -336
  22. data/lib/robust_excel_ole/worksheet.rb +51 -25
  23. data/robust_excel_ole.gemspec +1 -0
  24. data/spec/address_tool_spec.rb +175 -0
  25. data/spec/{reo_common_spec.rb → base_spec.rb} +19 -34
  26. data/spec/bookstore_spec.rb +3 -3
  27. data/spec/cell_spec.rb +67 -25
  28. data/spec/data/more_data/workbook.xls +0 -0
  29. data/spec/excel_spec.rb +137 -369
  30. data/spec/general_spec.rb +21 -27
  31. data/spec/range_spec.rb +57 -3
  32. data/spec/workbook_spec.rb +11 -79
  33. data/spec/workbook_specs/workbook_misc_spec.rb +29 -40
  34. data/spec/workbook_specs/workbook_open_spec.rb +570 -30
  35. data/spec/workbook_specs/workbook_unobtr_spec.rb +440 -136
  36. data/spec/worksheet_spec.rb +36 -4
  37. metadata +11 -7
  38. data/spec/address_spec.rb +0 -174
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b63b8ec97e714c16c5b4e3f1bb60f7e160aba0469ad14d47b766fa1778919c1f
4
- data.tar.gz: 1e0af619c00875ae92782cfa25a091335de3e1235723be9c2ecef2924b4f3cf9
3
+ metadata.gz: c966421c6f926cf0b4eec9b0c294a5a8544dcc129d24b5f7bbe34ced993baea9
4
+ data.tar.gz: 0e410b3f9a975a62dd671835eed6dcc06403acd0fc448e69019619ffc48cd8ed
5
5
  SHA512:
6
- metadata.gz: 54d8101340e7a2c82af0a761998a466a931df0dc5eaf0bd5117a513f89ebf3e38fa6e27dd04af909f0d8cf8125117b126c8df7d642843c993862f6af2966afbd
7
- data.tar.gz: 9f92d1018a35b7d018b7b3c3f7f3bb71383b7cb3914429a7986fe097a3ea9e8ac7ae77c011adff4075d4b56946c08ae8d9fdb9c69a51abb65b6109ea4f66cd00
6
+ metadata.gz: 670204220b0507239c8a4d31dd57085361bd60275a47bc228c5182bedb07e416ae1a414b65d73a416bfc826270445e450bf8aa841e6230829fa8072e6385aa93
7
+ data.tar.gz: 5cebdfb964bd8c87288059f6da7479bd8612482efddb7ce7f3d4818d51b911ce091b4b8ae576dd60d427c17db1a6a49eace85607112ad986aef2d32f5aa19ff0
data/Changelog CHANGED
@@ -1,11 +1,44 @@
1
1
  # Change Log
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
- ## [1.14]
4
+ ## [1.18] 2020-30-4
5
+
6
+ ### Added
7
+ - Workbook#worksheets, worksheets_count
8
+ - Worksheet#each_value
9
+ - Range#value, value=
10
+
11
+ ### Changed
12
+ - Range#initialize: optional paramter worksheet
13
+
14
+ ## [1.17]
15
+
16
+ ### Added
17
+ - Excel#active_workbook
18
+
19
+ ### Changed
20
+ - Excel#namevalue, set_namevalue, namevalue_glob, set_namevalue_glob are being removed
21
+
22
+ ## [1.16]
23
+
24
+ ### Added
25
+ - RangeOwners#set_namevalue, set_namevalue_glob, Worksheet#set_cellval:
26
+ optional parameter for color
27
+
28
+ ### Changed
29
+ - Workbook#color_if_modified removed
30
+
31
+ ## [1.15]
32
+
33
+ ### Added
34
+ - Workbook#unobtrusively, Workbook#for_reading, Workbook#for_modifying
5
35
 
6
36
  ### Changed
7
37
  - Workbook.unobtrusively: removed parameter :rw_change_excel
8
38
 
39
+ ## [1.14]
40
+
41
+ - no interface change
9
42
 
10
43
  ## [1.13]
11
44
 
@@ -14,10 +14,27 @@ Library references are supported.
14
14
  RobustExcelOle works by sending VBA methods via Win32OLE.
15
15
  Therefore, it runs on Windows only.
16
16
 
17
+ == Feature list
18
+
19
+ - opening and processing workbooks across various Excel instances
20
+ - reading and writing workbooks (cells and ranges)
21
+ - reopening and unobtrusively opening workbooks
22
+ - convenient methods for standard tasks (like opening, reading, writing, closing, saving workbooks, naming, adding, and copying ranges and worksheets)
23
+ - dealing with various cases of Excel and user behaviour, e.g. managing conflicts when opening workbooks (e.g. blocking or unsaved workbooks),
24
+ even with simultanously happening user interactions
25
+ - workarounds for Excel bugs and JRuby bugs
26
+ - various workbook formats, e.g. .xlsx, .xls, .xlsm are supported
27
+ - library references are supported
28
+ - console for convenient usage
29
+
30
+ == What's new?
31
+
32
+ - removing methods to operate on ranges directly from an Excel instance. However, you can use the method Excel.active_workbook to do so.
33
+ See ChangeLogs.
17
34
 
18
35
  == Requirements
19
36
 
20
- Ruby 2.1 or higher. Most functions run on Ruby 1.8.6, too.
37
+ Ruby 2.1 or higher.
21
38
 
22
39
  == Installation
23
40
 
@@ -61,14 +78,11 @@ Let's open a workbook.
61
78
  Now we have a Workbook object that wraps a WIN32OLE object. That is, you can send any WIN32OLE (VBA) method to it. See
62
79
  https://docs.microsoft.com/en-us/office/vba/api/excel.workbook#methods.
63
80
 
64
- For example, you can determine the name and whether the workbook is visible.
81
+ For example, you can determine the name of the workbook.
65
82
 
66
83
  workbook.Name
67
84
  # => "workbook.xls"
68
85
 
69
- workbook.Visible
70
- # => false
71
-
72
86
  For some common tasks and for considering various complex cases of Excel and user behaviour, more convenient methods are implemented. For example, RobustExcelOle provides methods for reading and writing the contents of ranges, for opening, saving, closing, reopening and unobtrusively opening workbooks, and for setting options.
73
87
 
74
88
  First we want to make the workbook visible.
@@ -92,7 +106,7 @@ Then we'll save the workbook.
92
106
 
93
107
  === More features when opening, modifying, creating, saving and closing workbooks
94
108
 
95
- RobustExcelOle allows unobtrusively reading and modifying workbooks, i.e. accessing workbooks without changing their "status". The status comprises whether the workbook is open or closed, saved or unsaved, read-only or writable, visible or invisible, whether the calculation mode is manual or automatic, and checking compatibility is done or not done (the Workbook object remembers its properties).
109
+ RobustExcelOle allows unobtrusively reading and modifying workbooks, i.e. accessing workbooks without changing their "status". The status comprises whether the workbook is open or closed, saved or unsaved, read-only or writable, visible or invisible, whether the calculation mode is manual or automatic, and checking compatibility is done or not done.
96
110
 
97
111
  Workbook.unobtrusively('spec/data/workbook.xls') do |workbook|
98
112
  # do something
Binary file
@@ -26,7 +26,7 @@ Options of the methods +create+ and +new+ are +:reuse+ (+true+, +false+), +:visi
26
26
 
27
27
  The option +:calculation+ specifies, whether the calculation mode is being forced to be manual (:manual), automatic (+:automatic+) or is not being forced (+nil+).
28
28
 
29
- You can also promote an Excel instance represented as WIN32OLE object to an Excel object.
29
+ You can also type-lift an Excel instance represented as WIN32OLE object to an Excel object.
30
30
 
31
31
  excel = Excel.new(win32ole_object, :visible => true)
32
32
 
@@ -124,6 +124,12 @@ or, with a block,
124
124
 
125
125
  excel.each_workbook(:visible => true) {|w| puts w}
126
126
 
127
+ === Accessing the active workbook
128
+
129
+ You can operate on the active workbook with help of the method Workbook#active_workbook, e.g.
130
+
131
+ workbook = excel.active_workbook
132
+
127
133
  === Bringing an Excel instance to the foreground
128
134
 
129
135
  excel1.focus
@@ -142,21 +142,22 @@ A special feature of RobustExcelOle is that it allows to reopen workbooks after
142
142
 
143
143
  The closed workbook is now alive again, i.e. is open and responds to Excel methods.
144
144
 
145
- === Promoting WIN32OLE objects to RobustExcelOle objects
145
+ === Type-lifting WIN32OLE objects to RobustExcelOle objects
146
146
 
147
- Promoting means here: enriching a given object of a certain class by properties and methods of another class.
148
- The method +General.to_reo+ enables promoting WIN32OLE objects to RobustExcelOle objects such that the attributes and methods of RobustExcelOle can be applied to these objects. For example, assume we have a WIN32OLE workbook +win32ole_workbook+:
147
+ Type-lifting means here: enriching a given object of a certain class by properties and methods of another class.
148
+ The method +General.to_reo+ enables type-lifting WIN32OLE objects to RobustExcelOle objects, in the sense that the attributes and methods of RobustExcelOle can be applied to these objects. For example, assume we have a WIN32OLE workbook +win32ole_workbook+:
149
149
 
150
150
  win32ole_workbook.to_class
151
151
  => WIN32OLE
152
152
 
153
- This object can be promoted to a RobustExcelOle workbook.
153
+ This object can be type-lifted to a RobustExcelOle workbook.
154
154
 
155
155
  workbook = win32ole_workbook.to_reo
156
+
156
157
  workbook.to_class
157
158
  => RobustExcelOle::Workbook
158
159
 
159
- Similarly, Excel, Worksheet, and Range WIN32OLE objects can be promoted to corresponding RobustExcelOle objects.
160
+ Similarly, Excel, Worksheet, and Range WIN32OLE objects can be type-lifted to corresponding RobustExcelOle objects.
160
161
 
161
162
  The method +to_reo+ uses the method +new+. You can apply the method +new+ directly.
162
163
 
@@ -166,45 +167,69 @@ You can supply options, e.g. +:visible+.
166
167
 
167
168
  workbook = Workbook.new(win32ole_workbook, :visible => true)
168
169
 
170
+ You can also supply a workbook and options, e.g.
171
+
172
+ new_workbook = Workbook.new(workbook, :visible => true)
169
173
 
170
174
  === Identity transperence ===
171
175
 
172
- A RobustExcelOle Workbook object is a proxy of an Excel WIN32OLE workbook. A Workbook object is defined by the full workbook name and the Excel instance in which it is opened. RobustExcelOle ensures identity transparency which means that identical Workbook objects refer to identical Excel workbooks, and vice versa. Identity transperence ensures that, no matter how a Workbook object was created - by filename or by promoting an Excel workbook - two Workbook objects are identical, if and only if the Excel workbooks, they are referring to, are identical.
176
+ A RobustExcelOle Workbook object is a proxy of an Excel WIN32OLE workbook. A Workbook object is defined by the full workbook name and the Excel instance in which it is opened. RobustExcelOle ensures identity transparency which means that identical Workbook objects refer to identical Excel workbooks, and vice versa. Identity transperence ensures that, no matter how a Workbook object was created - by filename or by type-lifting an Excel workbook - two Workbook objects are identical, if and only if the Excel workbooks, they are referring to, are identical.
173
177
 
174
178
  Similarly, each Excel, Worksheet and a Range object in RobustExcelOle is a proxy of a corresponding Excel, Worksheet and a Range object in WIN32OLE. For these objects identity transperence holds as well.
175
179
 
180
+ === Opening workbooks given a network path and a hostname share path ===
181
+
182
+ RobustExcelOle allows opening workbooks via a network path starting with a drive letter different from the default drive (mostly 'C'), e.g.
183
+
184
+ workbook = Workbook.open('N:/data workbook.xls')
185
+
186
+ Likewise the corresponding hostname share path can be used, starting with '//', e.g.
187
+
188
+ workbook = Workbook.open("//DESKTOP-A5D5GJ5/spec/data/workbook.xls")
189
+
190
+ where 'DESKTOP-A5D5GJ5' shall be the hostname, and 'data' be the share.
191
+
176
192
  === Unobtrusively modifying a workbook
177
193
 
178
194
  The method +unobtrusively+ enables the user to read or modify a workbook, no matter if it is open in some Excel instance, if it is saved or unsaved, and if it is writable or not. When opening a workbook unobtrusively, its status remains unchanged. This status includes, whether the workbook is opened or closed, saved or unsaved, readonly or writable, visible or invisible, calculation mode is automatic or manual, and checking compatibility is turned on or off.
179
195
 
180
196
  Options are the following:
181
197
 
182
- +:if_closed+:: +:current+ (or +:active, or +:reuse+:): (default) : open a closed workbook in the Excel instance where it was opened most recently, if such an Excel instance exists, otherwise open it in the current (first opened) Excel instance
183
-
198
+ +:if_closed+:: the Excel instance in which to open the workbook, if it was closed (default: +:current+). (Note: this option works workbooks opened via RobustExcelOle only.)
199
+
184
200
  +:read_only+:: Whether the workbook shall be forced to be open in ReadOnly mode
185
201
  +:writable+:: Whether changes in the workbook shall be saved
186
202
 
187
- +:rw_change_excel+:: Excel instance in which the workbook with the
188
- changed read-write permissions shall be opened
189
- :current (default), :new or an Excel instance
190
-
191
- +:keep_open+:: Whether the workbook shall be open after unobtrusively opening (default: false)
203
+ +:keep_open+:: Whether the workbook shall be open after unobtrusively opening (default: false)
192
204
 
205
+ There are the class method and the instance method of +unobtrusively+. Here is an example of the class method:
193
206
 
194
207
  Workbook.unobtrusively('spec/data/workbook.xls') do |book|
195
208
  # some modification
196
- worksheet = book[0]
197
- worksheet[1,1] = "c"
209
+ book.sheet(1)[1,1] = "c"
198
210
  end
199
-
200
- The methods +for_reading+ and +for_modifying+ indicate unobtrusively reading or modifying.
211
+
212
+ Here is an example of the instance method:
213
+
214
+ book.unobtrusively do
215
+ # some modification
216
+ book.sheet(1)[1,1] = "c"
217
+ end
218
+
219
+ The methods +for_reading+ and +for_modifying+ indicate unobtrusively reading or modifying.
201
220
 
202
221
  Workbook.for_modifying('spec/data/workbook.xls') do |book|
203
222
  # some modification
204
- worksheet = book[0]
205
- worksheet[1,1] = "c"
223
+ book.sheet(1)[1,1] = "c"
206
224
  end
207
225
 
226
+ An example of the instance method would be
227
+
228
+ book.for_modifying do
229
+ # some modification
230
+ book.sheet(1)[1,1] = "c"
231
+ end
232
+
208
233
  Note, that the methods +unobtrusively+, +for_reading+ and +for_modifying+ work not only for workbooks opened via RobustExcelOle, but connect to workbooks opened outside RobustExcelOle as well.
209
234
 
210
235
  === Retaining the saved-status
@@ -218,7 +243,7 @@ This method ensures keeping the save status of the workbook
218
243
 
219
244
  === Checking whether the workbook is alive.
220
245
 
221
- This method finds out whether the Excel workbook that is referenced by the Workbook object responds to methods.
246
+ The method +alive?+ finds out whether the Excel workbook that is referenced by the Workbook object responds to methods. For example
222
247
 
223
248
  workbook.alive?
224
249
  # => true
@@ -306,9 +306,12 @@ or
306
306
 
307
307
  workbook.set_namevalue_glob("name", "new_value")
308
308
 
309
- The method []= colors the written cell, if you have specified the color of the changed range via the method Workbook#color before, e.g.
309
+ You can color the range when setting the contents of a range.
310
+
311
+ workbook.set_namevalue_glob("name", "new_value", :color => 4)
312
+
313
+ The method []= sets the contents of a range and colors the range via some default color.
310
314
 
311
- workbook.color_if_modified = 4
312
315
  workbook["name"] = "new_value"
313
316
 
314
317
  Similarly, the contents of a named range can be read and modified in a worksheet
@@ -391,6 +394,12 @@ The methods Worksheet#each, Worksheet#each_row and Worksheet#each_column enable
391
394
  # do something with column
392
395
  end
393
396
 
397
+ The method Worksheet#each_value accesses the values of each row.
398
+
399
+ worksheet.each_value do |row_values|
400
+ # do something with the row_values
401
+ end
402
+
394
403
  You access a range of a row by giving the number of the row, and optionally, the range of the cell numbers.
395
404
 
396
405
  worksheet.row_range(1) # => first row
@@ -0,0 +1,27 @@
1
+ #require 'robust_excel_ole'
2
+
3
+ #workbook = Workbook.open './sample_excel_files/xlsx_500_rows.xlsx'
4
+
5
+ require_relative '../lib/robust_excel_ole'
6
+
7
+ include RobustExcelOle
8
+
9
+ workbook = Workbook.open './../spec/data/workbook.xls'
10
+
11
+ puts "Found #{workbook.worksheets_count} worksheets"
12
+
13
+ workbook.each do |worksheet|
14
+ puts "Reading: #{worksheet.name}"
15
+ num_rows = 0
16
+
17
+ worksheet.each do |row|
18
+ row_cells = row.map{ |cell| cell.value }
19
+ num_rows += 1
20
+
21
+ # uncomment to print out row values
22
+ # puts row_cells.join " "
23
+ end
24
+ puts "Read #{num_rows} rows"
25
+ end
26
+
27
+ puts 'Done'
@@ -0,0 +1,13 @@
1
+ dummy_make_content = "make:\n" \
2
+ "\t:\n" \
3
+ "install:\n" \
4
+ "\t:\n" \
5
+ "clean:\n" \
6
+ "\t:\n"
7
+ File.write('Makefile', dummy_make_content)
8
+
9
+ puts "hello"
10
+
11
+ a = 2
12
+
13
+ puts a
@@ -3,10 +3,11 @@ if RUBY_PLATFORM =~ /java/
3
3
  else
4
4
  require 'win32ole'
5
5
  end
6
- require File.join(File.dirname(__FILE__), 'robust_excel_ole/reo_common')
7
- require File.join(File.dirname(__FILE__), 'robust_excel_ole/range_owners')
8
- require File.join(File.dirname(__FILE__), 'robust_excel_ole/address')
6
+ require File.join(File.dirname(__FILE__), 'robust_excel_ole/base')
9
7
  require File.join(File.dirname(__FILE__), 'robust_excel_ole/general')
8
+ require File.join(File.dirname(__FILE__), 'robust_excel_ole/vba_objects')
9
+ require File.join(File.dirname(__FILE__), 'robust_excel_ole/range_owners')
10
+ require File.join(File.dirname(__FILE__), 'robust_excel_ole/address_tool')
10
11
  require File.join(File.dirname(__FILE__), 'robust_excel_ole/excel')
11
12
  require File.join(File.dirname(__FILE__), 'robust_excel_ole/bookstore')
12
13
  require File.join(File.dirname(__FILE__), 'robust_excel_ole/workbook')
@@ -2,37 +2,38 @@
2
2
 
3
3
  module RobustExcelOle
4
4
 
5
- class Address < REOCommon
5
+ class AddressTool < Base
6
6
 
7
- def self.new(r1c1_letters)
8
- @@row_letter = r1c1_letters[0..0]
9
- @@col_letter = r1c1_letters[1..1]
7
+ def initialize(address_string)
8
+ r1c1_letters = address_string.gsub(/[0-9]/,'')
9
+ @row_letter = r1c1_letters[0..0]
10
+ @col_letter = r1c1_letters[1..1]
10
11
  end
11
12
 
12
13
  # address formats that are valid:
13
14
  # r1c1-format: e.g. "Z3S1", "Z3S1:Z5S2", "Z[3]S1", "Z3S[-1]:Z[5]S1", "Z[3]", "S[-2]"
14
15
  # infinite ranges are not possible, e.g. "Z3:Z5", "S2:S5", "Z2", "S3", "Z[2]"
15
- # int_range: e.g. [3,1], [3,"A"], [3..5,1..2], [3..5, "A".."B"],
16
- # [3..4, nil], [nil, 2..4], [2,nil], [nil,4]
16
+ # integer_ranges-fromat: e.g. [3,1], [3,"A"], [3..5,1..2], [3..5, "A".."B"],
17
+ # [3..4, nil], [nil, 2..4], [2,nil], [nil,4]
17
18
  # a1-format: e.g. "A3", "A3:B5", "A:B", "3:5", "A", "3"
18
19
 
19
- def self.r1c1(address)
20
+ def as_r1c1(address)
20
21
  transform_address(address,:r1c1)
21
22
  end
22
23
 
23
- def self.a1(address)
24
+ def as_a1(address)
24
25
  transform_address(address,:a1)
25
26
  end
26
27
 
27
28
  # valid address formats: e.g. [3,1], [3,"A"], [3..5,1..2], [3..5, "A".."B"],
28
29
  # [3..4, nil], [nil, 2..4], [2,nil], [nil,4]
29
- def self.int_range(address)
30
+ def as_integer_ranges(address)
30
31
  transform_address(address,:int_range)
31
32
  end
32
33
 
33
34
  private
34
35
 
35
- def self.transform_address(address, format)
36
+ def transform_address(address, format)
36
37
  address = address.is_a?(Array) ? address : [address]
37
38
  raise AddressInvalid, "address #{address.inspect} has more than two components" if address.size > 2
38
39
  begin
@@ -70,8 +71,8 @@ module RobustExcelOle
70
71
  raise AddressInvalid, "address (#{address.inspect}) format not correct"
71
72
  end
72
73
  if format==:r1c1
73
- r1c1_string(@@row_letter,rows,:min) + r1c1_string(@@col_letter,columns,:min) + ":" +
74
- r1c1_string(@@row_letter,rows,:max) + r1c1_string(@@col_letter,columns,:max)
74
+ r1c1_string(@row_letter,rows,:min) + r1c1_string(@col_letter,columns,:min) + ":" +
75
+ r1c1_string(@row_letter,rows,:max) + r1c1_string(@col_letter,columns,:max)
75
76
  elsif format==:int_range
76
77
  [rows,columns]
77
78
  else
@@ -79,8 +80,7 @@ module RobustExcelOle
79
80
  end
80
81
  end
81
82
 
82
- # @private
83
- def self.r1c1_string(letter,int_range,type)
83
+ def r1c1_string(letter,int_range,type)
84
84
  return "" if int_range.nil? || int_range.begin.nil?
85
85
  parameter = type == :min ? int_range.begin : int_range.end
86
86
  is_relative = parameter.is_a?(Array)
@@ -88,27 +88,28 @@ module RobustExcelOle
88
88
  letter + (is_relative ? "(" : "") + parameter.to_s + (is_relative ? ")" : "")
89
89
  end
90
90
 
91
- # @private
92
- def self.analyze(comp,format)
91
+ def analyze(comp,format)
93
92
  row_comp, col_comp = if format==:a1
94
93
  [comp.gsub(/[A-Z]/,''), comp.gsub(/[0-9]/,'')]
95
94
  else
96
- a,b = comp.split(@@row_letter)
97
- c,d = b.split(@@col_letter)
95
+ a,b = comp.split(@row_letter)
96
+ c,d = b.split(@col_letter)
98
97
  b.nil? ? ["",b] : (d.nil? ? [c,""] : [c,d])
99
98
  end
100
- def self.s2n(s)
99
+ def s2n(s)
101
100
  s!="" ? (s[0] == "[" ? [s.gsub(/\[|\]/,'').to_i] : (s.to_i!=0 ? s.to_i : s)) : nil
102
101
  end
103
102
  [s2n(row_comp), s2n(col_comp)]
104
103
  end
105
104
 
106
-
107
- # @private
108
- def self.str2num(str)
105
+ def str2num(str)
109
106
  str.tr("A-Z","0-9A-P").to_i(26) + (26**str.size-1)/25
110
107
  end
111
108
 
112
109
  end
113
110
 
111
+ # @private
112
+ class AddressInvalid < REOError
113
+ end
114
+
114
115
  end