robust_excel_ole 1.16 → 1.17

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 87f0b689fc32747c5adbeaeff32f823b2153dc613a2dc27ae6b3a52060241ca0
4
- data.tar.gz: 2d89ef58db655b2a84b95b9dc3622fe1daae6bfafc37c1f03f9de1984cf7958e
3
+ metadata.gz: c268eff75271d48aae54af54c03c138e8a965a6c6965b6fc9b5fd330a346888d
4
+ data.tar.gz: '0921d96d9d20546523acb5ea5e419d8e2351307c23d25abe8b8d96010364b643'
5
5
  SHA512:
6
- metadata.gz: 2a0074c2f763882481cdc43bb9a99b0c3b62d8ed2bfea646fc5d6d581719f01df7bb8a223c0d3629d698695b56629f1813b26f363a962707df91c42b51bebee0
7
- data.tar.gz: 863b6380c04612c239bec9ce6998be0e9ed59ec884e2f57107aa2833f11b0ba4bca7258621bc48e818591a6c6d973fe961a5ca591b2dc85cd5a15fa13dbf1ed6
6
+ metadata.gz: c98669d651a2ff192bab0767ea16085a08cab8e0c656c3123b684080b96b62899967f3c4998637002dddf72eb1dbbd635f2ef102153d53842977adeba11d32c6
7
+ data.tar.gz: 1ac22fd73f4dae16142c1dc1d81bd9d9f8eeb5fbf95f85b4bcf26d99293b474c544aae863af4d40cc64052535ab40541956b69db8301274aade5afcacea37534
@@ -153,6 +153,7 @@ The method +General.to_reo+ enables type-lifting WIN32OLE objects to RobustExcel
153
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
 
@@ -166,6 +167,9 @@ 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
 
@@ -3,16 +3,17 @@ 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')
13
14
  require File.join(File.dirname(__FILE__), 'robust_excel_ole/worksheet')
14
- require File.join(File.dirname(__FILE__), 'robust_excel_ole/cell')
15
15
  require File.join(File.dirname(__FILE__), 'robust_excel_ole/range')
16
+ require File.join(File.dirname(__FILE__), 'robust_excel_ole/cell')
16
17
  require File.join(File.dirname(__FILE__), 'robust_excel_ole/cygwin') if RUBY_PLATFORM =~ /cygwin/
17
18
  require File.join(File.dirname(__FILE__), 'robust_excel_ole/version')
18
19
 
@@ -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
@@ -50,94 +50,10 @@ module RobustExcelOle
50
50
  class MiscREOError < REOError
51
51
  end
52
52
 
53
- # @private
54
- class ExcelDamaged < ExcelREOError
55
- end
56
-
57
- # @private
58
- class UnsavedWorkbooks < ExcelREOError
59
- end
60
-
61
- # @private
62
- class WorkbookBlocked < WorkbookREOError
63
- end
64
-
65
- # @private
66
- class WorkbookNotSaved < WorkbookREOError
67
- end
68
-
69
- # @private
70
- class WorkbookReadOnly < WorkbookREOError
71
- end
72
-
73
- # @private
74
- class WorkbookBeingUsed < WorkbookREOError
75
- end
76
-
77
- # @private
78
- class WorkbookConnectingUnsavedError < WorkbookREOError
79
- end
80
-
81
- # @private
82
- class WorkbookConnectingBlockingError < WorkbookREOError
83
- end
84
-
85
- # @private
86
- class WorkbookConnectingUnknownError < WorkbookREOError
87
- end
88
-
89
- # @private
90
- class FileNotFound < FileREOError
91
- end
92
-
93
- # @private
94
- class FileNameNotGiven < FileREOError
95
- end
96
-
97
- # @private
98
- class FileAlreadyExists < FileREOError
99
- end
100
-
101
- # @private
102
- class NameNotFound < NamesREOError
103
- end
104
-
105
- # @private
106
- class NameAlreadyExists < NamesREOError
107
- end
108
-
109
- # @private
110
- class RangeNotEvaluatable < MiscREOError
111
- end
112
-
113
- # @private
114
- class RangeNotCreated < MiscREOError
115
- end
116
-
117
- # @private
118
- class RangeNotCopied < MiscREOError
119
- end
120
-
121
- # @private
122
- class OptionInvalid < MiscREOError
123
- end
124
-
125
- # @private
126
- class ObjectNotAlive < MiscREOError
127
- end
128
-
129
53
  # @private
130
54
  class TypeREOError < REOError
131
55
  end
132
56
 
133
- # @private
134
- class TimeOut < REOError
135
- end
136
-
137
- # @private
138
- class AddressInvalid < REOError
139
- end
140
-
141
57
  # @private
142
58
  class UnexpectedREOError < REOError
143
59
  end
@@ -145,13 +61,9 @@ module RobustExcelOle
145
61
  # @private
146
62
  class NotImplementedREOError < REOError
147
63
  end
64
+
148
65
 
149
- class REOCommon
150
-
151
- # @private
152
- def excel
153
- raise TypeREOError, 'receiver instance is neither an Excel nor a Workbook'
154
- end
66
+ class Base
155
67
 
156
68
  # @private
157
69
  def own_methods
@@ -2,7 +2,8 @@
2
2
 
3
3
  module RobustExcelOle
4
4
 
5
- class Bookstore < REOCommon
5
+ class Bookstore < Base
6
+
6
7
  def initialize
7
8
  @filename2books ||= Hash.new { |hash, key| hash[key] = [] }
8
9
  @hidden_excel_instance = nil
@@ -103,7 +104,6 @@ module RobustExcelOle
103
104
 
104
105
  private
105
106
 
106
- # @private
107
107
  def try_hidden_excel
108
108
  @hidden_excel_instance.__getobj__ if @hidden_excel_instance && @hidden_excel_instance.weakref_alive? && @hidden_excel_instance.__getobj__.alive?
109
109
  end
@@ -1,11 +1,13 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
3
  module RobustExcelOle
4
- class Cell < REOCommon
5
- attr_reader :cell
4
+
5
+ class Cell < Range
6
+ attr_reader :ole_cell
6
7
 
7
8
  def initialize(win32_cell)
8
- @cell = win32_cell.MergeCells ? win32_cell.MergeArea.Item(1,1) : win32_cell
9
+ @ole_cell = win32_cell.MergeCells ? win32_cell.MergeArea.Item(1,1) : win32_cell
10
+ super
9
11
  end
10
12
 
11
13
  def v
@@ -16,25 +18,27 @@ module RobustExcelOle
16
18
  self.Value = value
17
19
  end
18
20
 
21
+ private
22
+
19
23
  # @private
20
24
  def method_missing(name, *args)
21
- #if name.to_s[0,1] =~ /[A-Z]/
22
- if ::ERRORMESSAGE_JRUBY_BUG
23
- begin
24
- @cell.send(name, *args)
25
- rescue Java::OrgRacobCom::ComFailException
26
- raise VBAMethodMissingError, "unknown VBA property or method #{name.inspect}"
25
+ if name.to_s[0,1] =~ /[A-Z]/
26
+ if ::ERRORMESSAGE_JRUBY_BUG
27
+ begin
28
+ @ole_cell.send(name, *args)
29
+ rescue Java::OrgRacobCom::ComFailException
30
+ raise VBAMethodMissingError, "unknown VBA property or method #{name.inspect}"
31
+ end
32
+ else
33
+ begin
34
+ @ole_cell.send(name, *args)
35
+ rescue NoMethodError
36
+ raise VBAMethodMissingError, "unknown VBA property or method #{name.inspect}"
37
+ end
27
38
  end
28
39
  else
29
- begin
30
- @cell.send(name, *args)
31
- rescue NoMethodError
32
- raise VBAMethodMissingError, "unknown VBA property or method #{name.inspect}"
33
- end
40
+ super
34
41
  end
35
- # else
36
- # super
37
- # end
38
42
  end
39
43
  end
40
44
  end
@@ -16,9 +16,10 @@ module RobustExcelOle
16
16
  # that you would apply for an Application object.
17
17
  # See https://docs.microsoft.com/en-us/office/vba/api/excel.application(object)#methods
18
18
 
19
- class Excel < RangeOwners
19
+ class Excel < VbaObjects
20
20
  attr_reader :ole_excel
21
21
  attr_reader :properties
22
+ attr_reader :address_tool
22
23
 
23
24
  alias ole_object ole_excel
24
25
 
@@ -125,10 +126,18 @@ module RobustExcelOle
125
126
  self
126
127
  end
127
128
 
129
+ # @private
130
+ def address_tool
131
+ raise(ExcelREOError, "Excel contains no workbook") unless @ole_excel.Workbooks.Count > 0
132
+ @address_tool ||= begin
133
+ address_string = @ole_excel.Workbooks.Item(1).Worksheets.Item(1).Cells.Item(1,1).Address(true,true,XlR1C1)
134
+ address_tool_class.new(address_string)
135
+ end
136
+ end
137
+
128
138
  private
129
139
 
130
140
  # retain the saved status of all workbooks
131
- # @private
132
141
  def retain_saved_workbooks
133
142
  saved_stati = @ole_excel.Workbooks.map { |w| w.Saved }
134
143
  begin
@@ -138,7 +147,6 @@ module RobustExcelOle
138
147
  end
139
148
  end
140
149
 
141
- # @private
142
150
  def ole_workbooks
143
151
  ole_workbooks = begin
144
152
  @ole_excel.Workbooks
@@ -153,11 +161,13 @@ module RobustExcelOle
153
161
 
154
162
  public
155
163
 
164
+ # @private
156
165
  def self.contains_unsaved_workbooks?
157
166
  !Excel.current.unsaved_workbooks.empty?
158
167
  end
159
168
 
160
169
  # returns unsaved workbooks (win32ole objects)
170
+ # @private
161
171
  def unsaved_workbooks
162
172
  unsaved_workbooks = []
163
173
  begin
@@ -175,6 +185,7 @@ module RobustExcelOle
175
185
  # :forget -> closes the Excel instance without saving the workbooks
176
186
  # :save -> saves the workbooks before closing
177
187
  # :alert -> let Excel do it
188
+ # @private
178
189
  def close_workbooks(options = { :if_unsaved => :raise })
179
190
  return unless alive?
180
191
 
@@ -382,12 +393,11 @@ module RobustExcelOle
382
393
  @@hwnd2excel.size
383
394
  end
384
395
 
385
- #private
396
+ private
386
397
 
387
398
  # returns a Win32OLE object that represents a Excel instance to which Excel connects
388
399
  # connects to the first opened Excel instance
389
400
  # if this Excel instance is being closed, then Excel creates a new Excel instance
390
- # @private
391
401
  def self.current_ole_excel
392
402
  if ::CONNECT_EXCEL_JRUBY_BUG
393
403
  result = known_excel_instance
@@ -430,6 +440,25 @@ module RobustExcelOle
430
440
  nil
431
441
  end
432
442
 
443
+ def self.hwnd2excel(hwnd)
444
+ excel_weakref = @@hwnd2excel[hwnd]
445
+ if excel_weakref
446
+ if excel_weakref.weakref_alive?
447
+ excel_weakref.__getobj__
448
+ else
449
+ trace 'dead reference to an Excel'
450
+ begin
451
+ @@hwnd2excel.delete(hwnd)
452
+ nil
453
+ rescue
454
+ trace "Warning: deleting dead reference failed! (hwnd: #{hwnd.inspect})"
455
+ end
456
+ end
457
+ end
458
+ end
459
+
460
+ public
461
+
433
462
  # returns all Excel objects for all Excel instances opened with RobustExcelOle
434
463
  def self.known_excel_instances
435
464
  pid2excel = {}
@@ -464,24 +493,6 @@ module RobustExcelOle
464
493
  self
465
494
  end
466
495
 
467
- # @private
468
- def self.hwnd2excel(hwnd)
469
- excel_weakref = @@hwnd2excel[hwnd]
470
- if excel_weakref
471
- if excel_weakref.weakref_alive?
472
- excel_weakref.__getobj__
473
- else
474
- trace 'dead reference to an Excel'
475
- begin
476
- @@hwnd2excel.delete(hwnd)
477
- nil
478
- rescue
479
- trace "Warning: deleting dead reference failed! (hwnd: #{hwnd.inspect})"
480
- end
481
- end
482
- end
483
- end
484
-
485
496
  # @private
486
497
  def hwnd
487
498
  self.Hwnd
@@ -700,7 +711,9 @@ module RobustExcelOle
700
711
  def workbook
701
712
  return @workbook unless @workbook.nil?
702
713
  @workbook = workbook_class.new(@ole_excel.ActiveWorkbook)
703
- end
714
+ end
715
+
716
+ alias_method :active_workbook, :workbook
704
717
 
705
718
  # @private
706
719
  def to_s
@@ -727,11 +740,26 @@ module RobustExcelOle
727
740
  self.class.workbook_class
728
741
  end
729
742
 
743
+ # @private
744
+ def self.address_tool_class
745
+ @address_tool_class ||= begin
746
+ module_name = parent_name
747
+ "#{module_name}::AddressTool".constantize
748
+ rescue NameError => e
749
+ AddressTool
750
+ end
751
+ end
752
+
753
+ # @private
754
+ def address_tool_class
755
+ self.class.address_tool_class
756
+ end
757
+
758
+
730
759
  include MethodHelpers
731
760
 
732
761
  private
733
762
 
734
- # @private
735
763
  def method_missing(name, *args)
736
764
  if name.to_s[0,1] =~ /[A-Z]/
737
765
  raise ObjectNotAlive, 'method missing: Excel not alive' unless alive?
@@ -754,7 +782,16 @@ module RobustExcelOle
754
782
  end
755
783
  end
756
784
 
757
- public
785
+ public
786
+
787
+ # @private
788
+ class ExcelDamaged < ExcelREOError
789
+ end
790
+
791
+ # @private
792
+ class UnsavedWorkbooks < ExcelREOError
793
+ end
794
+
758
795
 
759
796
  Application = Excel
760
797
 
@@ -763,3 +800,4 @@ end
763
800
  class WIN32OLE
764
801
  include Enumerable
765
802
  end
803
+