robust_excel_ole 1.19.10 → 1.21

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 614de074c7752061f3544fd8501eaa7c13e84be83540388886d33afedc1ae736
4
- data.tar.gz: e499ec767f61227f8256cb4b0779bb25bccdefe8bda26b28a59d60b48308cc47
3
+ metadata.gz: 7598173082d025a168f3c4e8021eb41c97fb1af36943e35cf2a812fcc0f39672
4
+ data.tar.gz: 2e1e0585da1b1369d323b218b0817f23679b71f99f637a269a6abf14673df615
5
5
  SHA512:
6
- metadata.gz: 5a4d5db7e4d68d2ab0cb7fae6dd589dbebbab6582a2b9a9583241cabd5af4d06632cf1b350fc503c3b444fab8acc0c394c2b74cd3dfc64d90c612c2b956c1611
7
- data.tar.gz: 47b6118c63a036db294f2cd15de8e05dd929b4553a25bc61176b0f8d57f5d7accf3be196b7c9d1ebae5f909ef51a2dd8ed784c40b340be07250f32dbf46e8f0c
6
+ metadata.gz: '09581d754af617dcbe58149087d78c0281e7aa1e6d5feb27f4b58a0b08a0cc5967d15398d85952174143a2e867133b2d1dbf352fd0656bc7488183c7edca94ab'
7
+ data.tar.gz: bc6c1bed4f9b3370a376b875fa5a4f64b690ef6df6da70efde30a5caa49447b32b28ba09864adcb4c0ca9ea861ddeb28b5af851e30db826e749c6c97cc0153de
data/Changelog CHANGED
@@ -2,7 +2,7 @@
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
4
 
5
- ## [1.20] 2020-12-07
5
+ ## [1.20] 2020-23-07
6
6
 
7
7
  ### Changed
8
8
  - using pry in console
@@ -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 Win32OlE.
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, you can send any WIN32OLE (VBA) method to it. See
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, you can determine the name of the workbook.
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
- You can also create a new, empty workbook.
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, you can open the workbook using a block, similar to, e.g., +File.open+.
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,33 +318,139 @@ 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
- === Reading and writing list objects
321
+ === List Objects
322
+
323
+ === Creating List Objects
322
324
 
323
325
  We can define a list object (or table) from scratch.
324
326
 
325
- table = ListObject.new(worksheet, "table 1", [1,1], 3,["Person","Amount"])
327
+ table = ListObject.new(worksheet, "table 1", [1,1], 3,["Person","AmountSales"])
328
+
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 "Amoun%tSales".
326
330
 
327
- 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".
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)
328
335
 
329
- A row in this table can be accessed with help of [], e.g.
336
+ or
330
337
 
331
- table[1]
338
+ table = ole_listobject.to_reo
332
339
 
333
- Now we can set and get the value of a cell of the table, e.g.
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.
334
342
 
335
- table[1].person = "John"
336
- table[1].person
337
- # => "John"
343
+ A row in this table can be accessed with help of #[], e.g.
338
344
 
339
- Likewise we can get a table with help of an existing Win32OlE table.
345
+ row1 = table[1]
340
346
 
341
- ole_listobject = worksheet.ListObjects.Item("Table 1")
342
- table = ListObject.new(ole_listobject)
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 equal to or are underscored variants of the column names, e.g.
350
+
351
+ row1.AmountSales = 40
352
+
353
+ or
354
+
355
+ row1.amount_sales = 40
356
+
357
+ and
358
+
359
+ row1.AmountSales
360
+ # => 40
361
+
362
+ or
363
+
364
+ row1.amount_sales
365
+ # => 40
366
+
367
+ Special characters in the colare being ignored.
368
+
369
+ We can also read and set values in a whole row, e.g.
370
+
371
+ table.row_values(1)
372
+ # => ["John", 40]
373
+
374
+ or
375
+
376
+ table[1].values
377
+ # => ["John", 40]
378
+
379
+ and
380
+
381
+ table.set_row_values(1, ["Herbert", 80])
382
+ # => ["Herbert", 80]
383
+
384
+ or
385
+
386
+ table[1].set_values(["Herbert", 80])
387
+
388
+ 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.
389
+
390
+ Similarly, we can read and set the values in a whole column, e.g.
391
+
392
+ table.column_values("Person")
393
+ # => ["John", "Peter"]
394
+
395
+ and
396
+
397
+ table.set_column_values(1, ["Herbert","Paul"])
398
+
399
+ The column names we can get with help of
400
+
401
+ table.column_names
402
+
403
+ A column can be renamed.
404
+
405
+ table.rename_column("Person", "Enterprise")
406
+
407
+ or
408
+
409
+ table.rename_column(1, "Enterprise")
410
+
411
+ === Adding and Deleting rows and columns
412
+
413
+ We can add rows and columns, supplying optionally their name, the position and contents.
414
+
415
+ table.add_column("column_name")
416
+ table.add_column("column_name", 3)
417
+ table.add_column("column_name", 3, ["John", "Paul"])
418
+
419
+ table.add_row(3)
420
+ table.add_row(3, ["John", 40, 2, 2004])
421
+
422
+ Deleting columns and rows is done by
423
+
424
+ table.delete_column("column_name")
425
+ table.delete_row(3)
426
+
427
+ We can delete only the contents of a column
428
+
429
+ table.delete_column_values("column_name")
430
+
431
+ Similarly can delete only the contents of a row.
432
+
433
+ table.delete_row_values(2)
434
+
435
+ or
436
+
437
+ table[2].delete_values
438
+
439
+ Finally we can delete empty rows and columns.
440
+
441
+ table.delete_empty_rows
442
+ table.delete_empty_columns
443
+
444
+ === Finding values and sorting
445
+
446
+ You can find all cells containing a given value, e.g.
447
+
448
+ table.find_value(value)
449
+ #=> [#<Cell: (5,8)>#, #<Cell: (9,6)>#]
450
+
451
+ You can sort a table according to a given column and sort order, e.g.
343
452
 
344
- r4 = t4[1]
345
- r4.person
346
- # =>
347
- r.person = "John"
453
+ table.sort("Person", :ascending)
348
454
 
349
455
  === More things
350
456
 
data/bin/jreo CHANGED
@@ -1,3 +1,24 @@
1
- @echo off
1
+ #!/usr/bin/env jruby
2
+ # -*- jruby -*-
2
3
 
3
- jruby ../lib/reo_console.rb
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 ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- ruby -*-
3
+
4
+ require 'pry'
5
+ require '../robust_excel_ole/lib/robust_excel_ole'
6
+
7
+ include REO
8
+ include General
9
+
10
+ # some pry configuration
11
+ Pry.config.windows_console_warning = false
12
+ #Pry.config.history_save = true
13
+ Pry.config.color = false
14
+ #Pry.editor = 'notepad' # 'subl', 'vi'
15
+ #Pry.config.prompt =
16
+ #[
17
+ #->(_obj, _nest_level, _) { ">> " },
18
+ #->(*) { " " }
19
+ #]
20
+
21
+ hooks = Pry::Hooks.new
22
+
23
+ hooks.add_hook :when_started, :hook12 do
24
+ puts 'REO console started'
25
+ puts
26
+ end
27
+ Pry.start(nil, hooks: hooks)
@@ -1,21 +1,24 @@
1
1
  require 'pry'
2
- require 'robust_excel_ole'
2
+ require '../robust_excel_ole/lib/robust_excel_ole'
3
3
 
4
4
  include REO
5
5
  include General
6
6
 
7
- puts 'REO console started'
8
- puts
9
-
10
7
  # some pry configuration
11
8
  Pry.config.windows_console_warning = false
12
- Pry.config.history.should_save = true
9
+ #Pry.config.history_save = true
13
10
  Pry.config.color = false
14
11
  #Pry.editor = 'notepad' # 'subl', 'vi'
15
12
  #Pry.config.prompt =
16
- # [
17
- # ->(_obj, _nest_level, _) { ">> " },
18
- # ->(*) { " " }
19
- # ]
13
+ #[
14
+ #->(_obj, _nest_level, _) { ">> " },
15
+ #->(*) { " " }
16
+ #]
20
17
 
21
- pry
18
+ hooks = Pry::Hooks.new
19
+
20
+ hooks.add_hook :when_started, :hook12 do
21
+ puts 'REO console started'
22
+ puts
23
+ end
24
+ Pry.start(nil, hooks: hooks)
@@ -2,6 +2,7 @@
2
2
 
3
3
  module RobustExcelOle
4
4
 
5
+ # @private
5
6
  class Bookstore < Base
6
7
 
7
8
  def initialize
@@ -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_range.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,35 @@ 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
- # if filename starts with a drive letter not c and this drive exists,
19
- # then determine the corresponding host_share_path
20
- default_drive = File.absolute_path(".")[0]
21
- if drive_letter != default_drive && drive_letter != filename
22
- for i in 0 .. drives.Count-1
23
- next if i % 2 == 1
24
- if drives.Item(i).gsub(':','') == drive_letter
25
- hostname_share = drives.Item(i+1) #.gsub('\\','/').gsub('//','')
26
- break
27
- end
28
- end
29
- hostname_share + filename_after_drive_letter if hostname_share
30
- else
31
- return filename
32
- end
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
33
36
  end
34
37
 
38
+ def self.normalize_drive_letter(drive)
39
+ drive.upcase.end_with?(':') ? drive : "#{drive}:"
40
+ end
41
+
35
42
  # @private
36
43
  def absolute_path(file)
37
44
  file[0,2] = './' if ::EXPANDPATH_JRUBY_BUG && file =~ /[A-Z]:[^\/]/
@@ -44,11 +51,12 @@ module General
44
51
  def canonize(filename)
45
52
  raise TypeREOError, "No string given to canonize, but #{filename.inspect}" unless filename.is_a?(String)
46
53
  filename = network2hostnamesharepath(filename)
47
- normalize(filename).downcase
54
+ normalize(filename).downcase if filename
48
55
  end
49
56
 
50
57
  # @private
51
- def normalize(path)
58
+ def normalize(path)
59
+ return unless path
52
60
  path = path.gsub('/./', '/') + '/'
53
61
  path = path.gsub(/[\/\\]+/, '/')
54
62
  nil while path.gsub!(/(\/|^)(?!\.\.?)([^\/]+)\/\.\.\//, '\1')
@@ -90,9 +98,19 @@ class Array
90
98
  end
91
99
  end
92
100
 
101
+ def find_each_index find
102
+ found, index, q = -1, -1, []
103
+ while found
104
+ found = self[index+1..-1].index(find)
105
+ if found
106
+ index = index + found + 1
107
+ q << index
108
+ end
109
+ end
110
+ q
111
+ end
93
112
  end
94
113
 
95
-
96
114
  # @private
97
115
  class WIN32OLE
98
116
 
@@ -103,7 +121,7 @@ class WIN32OLE
103
121
  class2method = [
104
122
  {Excel => :Hwnd},
105
123
  {Workbook => :FullName},
106
- {Worksheet => :Copy},
124
+ {Worksheet => :UsedRange},
107
125
  {RobustExcelOle::Range => :Row},
108
126
  {ListObject => :ListRows}
109
127
  ]
@@ -113,7 +131,7 @@ class WIN32OLE
113
131
  begin
114
132
  self.send(method)
115
133
  if classname == RobustExcelOle::Range && self.Rows.Count == 1 && self.Columns.Count == 1
116
- return Cell.new(self)
134
+ return Cell.new(self, self.Parent)
117
135
  else
118
136
  return classname.new(self)
119
137
  end
@@ -164,6 +182,31 @@ class ::String
164
182
  word
165
183
  end
166
184
 
185
+ def delete_multiple_underscores
186
+ word = self
187
+ while word.index('__') do
188
+ word.gsub!('__','_')
189
+ end
190
+ word
191
+ end
192
+
193
+ def replace_umlauts
194
+ word = self
195
+ word.gsub!('ä','ae')
196
+ word.gsub!('Ä','Ae')
197
+ word.gsub!('ö','oe')
198
+ word.gsub!('Ö','Oe')
199
+ word.gsub!('ü','ue')
200
+ word.gsub!('Ü','Ue')
201
+ #word.gsub!(/\x84/,'ae')
202
+ #word.gsub!(/\x8E/,'Ae')
203
+ #word.gsub!(/\x94/,'oe')
204
+ #word.gsub!(/\x99/,'Oe')
205
+ #word.gsub!(/\x81/,'ue')
206
+ #word.gsub!(/\x9A/,'Ue')
207
+ word
208
+ end
209
+
167
210
  # taken from http://apidock.com/rails/ActiveSupport/Inflector/constantize
168
211
  # File activesupport/lib/active_support/inflector/methods.rb, line 226
169
212
  def constantize # (camel_cased_word)