robust_excel_ole 1.9 → 1.10

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.
@@ -21,15 +21,30 @@ module RobustExcelOle
21
21
  return opts[:default] unless opts[:default] == :__not_provided
22
22
  raise
23
23
  end
24
+ ole_range = name_obj.RefersToRange
24
25
  value = begin
25
- name_obj.RefersToRange.Value
26
+ #name_obj.RefersToRange.Value
27
+ if RUBY_PLATFORM !~ /java/
28
+ ole_range.Value
29
+ else
30
+ values = RobustExcelOle::Range.new(ole_range).v
31
+ (values.size==1 && values.first.size==1) ? values.first.first : values
32
+ end
26
33
  rescue WIN32OLERuntimeError
27
34
  sheet = if self.is_a?(Worksheet) then self
28
35
  elsif self.is_a?(Workbook) then self.sheet(1)
29
36
  elsif self.is_a?(Excel) then self.workbook.sheet(1)
30
37
  end
31
38
  begin
32
- sheet.Evaluate(name_obj.Name).Value
39
+ #sheet.Evaluate(name_obj.Name).Value
40
+ # does it result in a range?
41
+ ole_range = sheet.Evaluate(name_obj.Name)
42
+ if RUBY_PLATFORM !~ /java/
43
+ ole_range.Value
44
+ else
45
+ values = RobustExcelOle::Range.new(ole_range).v
46
+ (values.size==1 && values.first.size==1) ? values.first.first : values
47
+ end
33
48
  rescue # WIN32OLERuntimeError
34
49
  return opts[:default] unless opts[:default] == :__not_provided
35
50
  raise RangeNotEvaluatable, "cannot evaluate range named #{name.inspect} in #{self}"
@@ -49,12 +64,30 @@ module RobustExcelOle
49
64
  # @param [FixNum] color the color when setting a value
50
65
  # @param [Hash] opts :color [FixNum] the color when setting the contents
51
66
  def set_namevalue_glob(name, value, opts = { :color => 0 })
52
- cell = name_object(name).RefersToRange
53
- cell.Interior.ColorIndex = opts[:color]
54
- workbook.modified_cells << cell if workbook # unless cell_modified?(cell)
55
- cell.Value = value
56
- rescue WIN32OLERuntimeError
57
- raise RangeNotEvaluatable, "cannot assign value to range named #{name.inspect} in #{self.inspect}"
67
+ begin
68
+ name_obj = begin
69
+ name_object(name)
70
+ rescue NameNotFound => msg
71
+ raise
72
+ end
73
+ ole_range = name_object(name).RefersToRange
74
+ ole_range.Interior.ColorIndex = opts[:color]
75
+ workbook.modified_cells << ole_range if workbook # unless cell_modified?(cell)
76
+ if RUBY_PLATFORM !~ /java/
77
+ ole_range.Value = value
78
+ else
79
+ address_r1c1 = ole_range.AddressLocal(true,true,XlR1C1)
80
+ row, col = Address.int_range(address_r1c1)
81
+ row.each_with_index do |r,i|
82
+ col.each_with_index do |c,j|
83
+ ole_range.Cells(i+1,j+1).Value = (value.respond_to?(:first) ? value[i][j] : value )
84
+ end
85
+ end
86
+ end
87
+ value
88
+ rescue # WIN32OLERuntimeError
89
+ raise RangeNotEvaluatable, "cannot assign value to range named #{name.inspect} in #{self.inspect}"
90
+ end
58
91
  end
59
92
 
60
93
  # returns the contents of a range with a locally defined name
@@ -68,14 +101,20 @@ module RobustExcelOle
68
101
  def namevalue(name, opts = { :default => :__not_provided })
69
102
  return namevalue_glob(name, opts) if self.is_a?(Workbook)
70
103
  begin
71
- range = self.Range(name)
72
- rescue WIN32OLERuntimeError
104
+ ole_range = self.Range(name)
105
+ rescue # WIN32OLERuntimeError
73
106
  return opts[:default] unless opts[:default] == :__not_provided
74
107
  raise NameNotFound, "name #{name.inspect} not in #{self.inspect}"
75
108
  end
76
109
  begin
77
- value = range.Value
78
- rescue WIN32OLERuntimeError
110
+ #value = ole_range.Value
111
+ value = if RUBY_PLATFORM !~ /java/
112
+ ole_range.Value
113
+ else
114
+ values = RobustExcelOle::Range.new(ole_range).v
115
+ (values.size==1 && values.first.size==1) ? values.first.first : values
116
+ end
117
+ rescue #WIN32OLERuntimeError
79
118
  return opts[:default] unless opts[:default] == :__not_provided
80
119
  raise RangeNotEvaluatable, "cannot determine value of range named #{name.inspect} in #{self.inspect}"
81
120
  end
@@ -94,15 +133,27 @@ module RobustExcelOle
94
133
  def set_namevalue(name, value, opts = { :color => 0 })
95
134
  begin
96
135
  return set_namevalue_glob(name, value, opts) if self.is_a?(Workbook)
97
- range = self.Range(name)
98
- rescue WIN32OLERuntimeError
136
+ ole_range = self.Range(name)
137
+ rescue # WIN32OLERuntimeError
99
138
  raise NameNotFound, "name #{name.inspect} not in #{self.inspect}"
100
139
  end
101
140
  begin
102
- range.Interior.ColorIndex = opts[:color]
103
- workbook.modified_cells << range if workbook # unless cell_modified?(range)
104
- range.Value = value
105
- rescue WIN32OLERuntimeError
141
+ ole_range.Interior.ColorIndex = opts[:color]
142
+ workbook.modified_cells << ole_range if workbook # unless cell_modified?(range)
143
+ #range.Value = value
144
+ if RUBY_PLATFORM !~ /java/
145
+ ole_range.Value = value
146
+ else
147
+ address_r1c1 = ole_range.AddressLocal(true,true,XlR1C1)
148
+ row, col = Address.int_range(address_r1c1)
149
+ row.each_with_index do |r,i|
150
+ col.each_with_index do |c,j|
151
+ ole_range.Cells(i+1,j+1).Value = (value.respond_to?(:first) ? value[i][j] : value)
152
+ end
153
+ end
154
+ end
155
+ value
156
+ rescue # WIN32OLERuntimeError
106
157
  raise RangeNotEvaluatable, "cannot assign value to range named #{name.inspect} in #{self.inspect}"
107
158
  end
108
159
  end
@@ -134,30 +185,26 @@ module RobustExcelOle
134
185
  def range(name_or_address, address2 = :__not_provided)
135
186
  begin
136
187
  if address2 == :__not_provided
137
- range = begin
138
- RobustExcelOle::Range.new(name_object(name_or_address).RefersToRange)
139
- rescue NameNotFound
140
- nil
188
+ range = if name_or_address.is_a?(String)
189
+ begin
190
+ RobustExcelOle::Range.new(name_object(name_or_address).RefersToRange)
191
+ rescue NameNotFound
192
+ nil
193
+ end
141
194
  end
142
195
  end
143
196
  if self.is_a?(Worksheet) && (range.nil? || (address2 != :__not_provided))
144
197
  address = name_or_address
145
198
  address = [name_or_address,address2] unless address2 == :__not_provided
146
- self.Names.Add('Name' => '__dummy001', 'RefersToR1C1' => '=' + Address.r1c1(address))
199
+ #self.Names.Add('Name' => '__dummy001', 'RefersToR1C1' => '=' + Address.r1c1(address))
200
+ #not_given = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_NULL)
201
+ #self.Names.Add('__dummy001',not_given,true,not_given,not_given,not_given,not_given,not_given,not_given,'=' + Address.r1c1(address))
202
+ self.Names.Add('__dummy001',nil,true,nil,nil,nil,nil,nil,nil,'=' + Address.r1c1(address))
147
203
  range = RobustExcelOle::Range.new(name_object('__dummy001').RefersToRange)
148
204
  self.Names.Item('__dummy001').Delete
149
- range
150
- # variant via rows, columns:
151
- #rows, columns = Address.int_range(address)
152
- #ole_range = if rows.nil?
153
- # self.Range(self.Columns(columns.min), self.Columns(columns.max))
154
- #elsif columns.nil?
155
- # self.Range(self.Rows(rows.min), self.Rows(rows.max))
156
- #else
157
- # self.Range(self.Cells(rows.min, columns.min), self.Cells(rows.max, columns.max))
158
- #end
159
- ##range = ole_range.to_reo
160
- #range = Range.new(ole_range)
205
+ workbook = self.is_a?(Workbook) ? self : self.workbook
206
+ workbook.save
207
+ range
161
208
  end
162
209
  rescue WIN32OLERuntimeError
163
210
  address2_string = address2.nil? ? "" : ", #{address2.inspect}"
@@ -176,8 +223,11 @@ module RobustExcelOle
176
223
  def add_name(name, addr, addr_deprecated = :__not_provided)
177
224
  addr = [addr,addr_deprecated] unless addr_deprecated == :__not_provided
178
225
  begin
179
- self.Names.Add('Name' => name, 'RefersToR1C1' => '=' + Address.r1c1(addr))
180
- rescue WIN32OLERuntimeError => msg
226
+ #self.Names.Add('Name' => name, 'RefersToR1C1' => '=' + Address.r1c1(addr))
227
+ #not_given = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_NULL)
228
+ #self.Names.Add(name, not_given, true, not_given, not_given, not_given, not_given, not_given, not_given, '=' + Address.r1c1(addr))
229
+ self.Names.Add(name, nil, true, nil, nil, nil, nil, nil, nil, '=' + Address.r1c1(addr))
230
+ rescue # WIN32OLERuntimeError => msg
181
231
  raise RangeNotEvaluatable, "cannot add name #{name.inspect} to range #{addr.inspect}"
182
232
  end
183
233
  name
@@ -223,10 +273,10 @@ module RobustExcelOle
223
273
 
224
274
  def name_object(name)
225
275
  self.Names.Item(name)
226
- rescue WIN32OLERuntimeError
276
+ rescue #WIN32OLERuntimeError
227
277
  begin
228
278
  self.Parent.Names.Item(name)
229
- rescue WIN32OLERuntimeError
279
+ rescue #WIN32OLERuntimeError
230
280
  raise RobustExcelOle::NameNotFound, "name #{name.inspect} not in #{self.inspect}"
231
281
  end
232
282
  end
@@ -18,6 +18,10 @@ end
18
18
 
19
19
  module RobustExcelOle
20
20
 
21
+ # @private
22
+ class VBAMethodMissingError < RuntimeError
23
+ end
24
+
21
25
  # @private
22
26
  class REOError < RuntimeError
23
27
  end
@@ -1,3 +1,3 @@
1
1
  module RobustExcelOle
2
- VERSION = "1.9"
2
+ VERSION = "1.10"
3
3
  end
@@ -166,7 +166,7 @@ module RobustExcelOle
166
166
  bookstore.store(self)
167
167
  @modified_cells = []
168
168
  @workbook = @excel.workbook = self
169
- r1c1_letters = @ole_workbook.Worksheets.Item(1).Cells.Item(1,1).Address('ReferenceStyle' => XlR1C1).gsub(/[0-9]/,'')
169
+ r1c1_letters = @ole_workbook.Worksheets.Item(1).Cells.Item(1,1).Address(true,true,XlR1C1).gsub(/[0-9]/,'') #('ReferenceStyle' => XlR1C1).gsub(/[0-9]/,'')
170
170
  address_class.new(r1c1_letters)
171
171
  if block
172
172
  begin
@@ -255,7 +255,7 @@ module RobustExcelOle
255
255
 
256
256
 
257
257
  # @private
258
- def ensure_workbook(filename, options)
258
+ def ensure_workbook(filename, options)
259
259
  filename = @stored_filename ? @stored_filename : filename
260
260
  raise(FileNameNotGiven, 'filename is nil') if filename.nil?
261
261
  if File.directory?(filename)
@@ -282,7 +282,7 @@ module RobustExcelOle
282
282
  abs_filename = General.absolute_path(filename).tr('/','\\')
283
283
  begin
284
284
  empty_ole_workbook.SaveAs(abs_filename)
285
- rescue WIN32OLERuntimeError => msg
285
+ rescue # WIN32OLERuntimeError => msg
286
286
  raise FileNotFound, "could not save workbook with filename #{filename.inspect}"
287
287
  end
288
288
  else
@@ -387,8 +387,10 @@ module RobustExcelOle
387
387
  end
388
388
  begin
389
389
  with_workaround_linked_workbooks_excel2007(options) do
390
- workbooks.Open(abs_filename, { 'ReadOnly' => options[:read_only] })
391
- # 'UpdateLinks' => updatelinks_vba(options[:update_links]) })
390
+ # temporary workaround until jruby-win32ole implements named parameters (Java::JavaLang::RuntimeException (createVariant() not implemented for class org.jruby.RubyHash)
391
+ workbooks.Open(abs_filename,
392
+ updatelinks_vba(options[:update_links]),
393
+ options[:read_only] )
392
394
  end
393
395
  rescue WIN32OLERuntimeError => msg
394
396
  # for Excel2007: for option :if_unsaved => :alert and user cancels: this error appears?
@@ -783,41 +785,6 @@ module RobustExcelOle
783
785
  end
784
786
  end
785
787
 
786
- # copies a sheet to another position
787
- # default: copied sheet is appended
788
- # @param [Worksheet] sheet a sheet that shall be copied
789
- # @param [Hash] opts the options
790
- # @option opts [Symbol] :as new name of the copied sheet
791
- # @option opts [Symbol] :before a sheet before which the sheet shall be inserted
792
- # @option opts [Symbol] :after a sheet after which the sheet shall be inserted
793
- # @raise NameAlreadyExists if the sheet name already exists
794
- # @return [Worksheet] the copied sheet
795
- def copy_sheet(sheet, opts = { })
796
- new_sheet_name = opts.delete(:as)
797
- after_or_before, base_sheet = opts.to_a.first || [:after, last_sheet]
798
- sheet.Copy({ after_or_before.to_s => base_sheet.ole_worksheet })
799
- new_sheet = worksheet_class.new(@excel.Activesheet)
800
- new_sheet.name = new_sheet_name if new_sheet_name
801
- new_sheet
802
- end
803
-
804
- # adds an empty sheet
805
- # default: empty sheet is appended
806
- # @param [Hash] opts the options
807
- # @option opts [Symbol] :as new name of the copied added sheet
808
- # @option opts [Symbol] :before a sheet before which the sheet shall be inserted
809
- # @option opts [Symbol] :after a sheet after which the sheet shall be inserted
810
- # @raise NameAlreadyExists if the sheet name already exists
811
- # @return [Worksheet] the added sheet
812
- def add_empty_sheet(opts = { })
813
- new_sheet_name = opts.delete(:as)
814
- after_or_before, base_sheet = opts.to_a.first || [:after, last_sheet]
815
- @ole_workbook.Worksheets.Add({ after_or_before.to_s => base_sheet.ole_worksheet })
816
- new_sheet = worksheet_class.new(@excel.Activesheet)
817
- new_sheet.name = new_sheet_name if new_sheet_name
818
- new_sheet
819
- end
820
-
821
788
  # copies a sheet to another position if a sheet is given, or adds an empty sheet
822
789
  # default: copied or empty sheet is appended, i.e. added behind the last sheet
823
790
  # @param [Worksheet] sheet a sheet that shall be copied (optional)
@@ -831,7 +798,49 @@ module RobustExcelOle
831
798
  opts = sheet
832
799
  sheet = nil
833
800
  end
834
- sheet ? copy_sheet(sheet, opts) : add_empty_sheet(opts)
801
+ new_sheet_name = opts.delete(:as)
802
+ last_sheet_local = last_sheet
803
+ after_or_before, base_sheet = opts.to_a.first || [:after, last_sheet_local]
804
+ begin
805
+ if RUBY_PLATFORM !~ /java/
806
+ if sheet
807
+ sheet.Copy({ after_or_before.to_s => base_sheet.ole_worksheet })
808
+ else
809
+ @ole_workbook.Worksheets.Add({ after_or_before.to_s => base_sheet.ole_worksheet })
810
+ end
811
+ else
812
+ # workaround for jruby
813
+ if after_or_before == :before
814
+ if sheet
815
+ sheet.Copy(base_sheet.ole_worksheet)
816
+ else
817
+ ole_workbook.Worksheets.Add(base_sheet.ole_worksheet)
818
+ end
819
+ else
820
+ #not_given = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_NULL)
821
+ #ole_workbook.Worksheets.Add(not_given,base_sheet.ole_worksheet)
822
+ if base_sheet.name != last_sheet_local.name
823
+ if sheet
824
+ sheet.Copy(base_sheet.Next)
825
+ else
826
+ ole_workbook.Worksheets.Add(base_sheet.Next)
827
+ end
828
+ else
829
+ if sheet
830
+ sheet.Copy(base_sheet.ole_worksheet)
831
+ else
832
+ ole_workbook.Worksheets.Add(base_sheet.ole_worksheet)
833
+ end
834
+ base_sheet.Move(ole_workbook.Worksheets.Item(ole_workbook.Worksheets.Count-1))
835
+ end
836
+ end
837
+ end
838
+ rescue WIN32OLERuntimeError
839
+ raise WorksheetREOError, "given sheet #{sheet.inspect} not found"
840
+ end
841
+ new_sheet = worksheet_class.new(@excel.Activesheet)
842
+ new_sheet.name = new_sheet_name if new_sheet_name
843
+ new_sheet
835
844
  end
836
845
 
837
846
  # for compatibility to older versions
@@ -839,6 +848,11 @@ module RobustExcelOle
839
848
  add_or_copy_sheet(sheet, opts)
840
849
  end
841
850
 
851
+ # for compatibility to older versions
852
+ def copy_sheet(sheet, opts = { })
853
+ add_or_copy_sheet(sheet, opts)
854
+ end
855
+
842
856
  def last_sheet
843
857
  worksheet_class.new(@ole_workbook.Worksheets.Item(@ole_workbook.Worksheets.Count))
844
858
  end
@@ -87,6 +87,47 @@ describe Bookstore do
87
87
  end
88
88
  end
89
89
 
90
+ describe "excel" do
91
+
92
+ context "with one open book" do
93
+
94
+ before do
95
+ @book = Workbook.open(@simple_file)
96
+ @bookstore.store(@book)
97
+ end
98
+
99
+ after do
100
+ @book.close rescue nil
101
+ end
102
+
103
+ it "should return the excel" do
104
+ @bookstore.excel.should == @book.excel
105
+ end
106
+ end
107
+
108
+ context "with one closed book" do
109
+
110
+ before do
111
+ @book = Workbook.open(@simple_file)
112
+ @bookstore.store(@book)
113
+ @book.close
114
+ end
115
+
116
+ it "should return the excel of the closed book" do
117
+ @bookstore.excel.should == @book.excel
118
+ end
119
+ end
120
+
121
+ context "with no book" do
122
+
123
+ it "should return nil" do
124
+ @bookstore.excel.should == nil
125
+ end
126
+ end
127
+
128
+
129
+ end
130
+
90
131
 
91
132
  describe "fetch" do
92
133
 
@@ -472,7 +513,8 @@ describe Bookstore do
472
513
  book1 = Workbook.open(@simple_file, :force_excel => @bookstore.hidden_excel)
473
514
  book1.excel.should === h_excel1
474
515
  book1.excel.should_not === @book.excel
475
- Excel.close_all
516
+ #Excel.close_all
517
+ Excel.kill_all
476
518
  h_excel2 = @bookstore.hidden_excel
477
519
  h_excel2.should_not == @book.excel
478
520
  h_excel2.should_not == book1.excel
Binary file
Binary file
Binary file
Binary file
data/spec/excel_spec.rb CHANGED
@@ -35,7 +35,8 @@ module RobustExcelOle
35
35
  before do
36
36
  @ole_excel1 = WIN32OLE.new('Excel.Application')
37
37
  @ole_excel2 = WIN32OLE.new('Excel.Application')
38
- ole_workbook1 = @ole_excel1.Workbooks.Open(@another_simple_file, { 'ReadOnly' => false })
38
+ #ole_workbook1 = @ole_excel1.Workbooks.Open(@another_simple_file, { 'ReadOnly' => false })
39
+ ole_workbook1 = @ole_excel1.Workbooks.Open(@another_simple_file, nil, false)
39
40
  ole_workbook1.Names.Item("firstcell").RefersToRange.Value = "foo"
40
41
  end
41
42
 
@@ -1720,7 +1721,7 @@ module RobustExcelOle
1720
1721
  end
1721
1722
 
1722
1723
  it "should set options in the Excel instance" do
1723
- @excel.for_this_instance(:displayalerts => true, :visible => true, :screenupdating => true, :calculaiton => :manual)
1724
+ @excel.for_this_instance(:displayalerts => true, :visible => true, :screenupdating => true, :calculation => :manual)
1724
1725
  @excel.DisplayAlerts.should be true
1725
1726
  @excel.Visible.should be true
1726
1727
  @excel.ScreenUpdating.should be true
@@ -1,5 +1,6 @@
1
1
 
2
2
  require 'win32ole'
3
+ #require 'jruby-win32ole'
3
4
 
4
5
  # @private
5
6
  class KeySender