robust_excel_ole 1.33 → 1.34

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: c1c1d70d522034dc16bc609e2578e02b556396051ec7fdd14e2f11bd5aea85cd
4
- data.tar.gz: e14ac932aae718dd25d3a3ddc9ab487d63dc934c6e1d136a1adb069b0c57c81e
3
+ metadata.gz: 367d0c217ed968287f98cbf62cc786df14d364799f2dec633848af78eb6ce1f0
4
+ data.tar.gz: de1a58c99a761ae005142a7bf302cab13b3b64021605e000e05ec2d783246fa2
5
5
  SHA512:
6
- metadata.gz: 77e8abbfee1226d86e58d75aa4e1625b3a7d385333974c4cb9e854527d1c6e2cfdcb827a55749343e34dfae0867bc843ac609ebb1541f71960dd08ffbdf7d1fd
7
- data.tar.gz: f3b02fa7307c8d7031fdf65d246d3e22a800d39f476a24f227abba0dc2eb058b119dc29c249285392013a8d0de73735c176030d39fd8f97f7ea9150b7a8d0b61
6
+ metadata.gz: 65361e347cb55f05bc6d24c6a85f3f3b19696cf057dbc71c14cb86a7c3d8bfc28aca247231cc3a90409d933ca3944104f40e006d2591dfe55f60f84a30f75619
7
+ data.tar.gz: db86b776ff9359c8ebb3893d1bbc103aacfae6f408dc0358f7b32367312b80096d47a3aed682b7ec367f2a41eb64cef9ac8c3aa9fcc021c8ac05b9e8babb70cf
data/README.rdoc CHANGED
@@ -1,24 +1,3 @@
1
- = News
2
-
3
- == New Interface of #[]
4
-
5
- Worksheet#[] now returns a value instead of a range, e.g.
6
-
7
- worksheet[1,1]
8
- # => "foo"
9
-
10
- Transformation: To yield the range, write range() instead of (). For example,
11
-
12
- worksheet.range(1,1)
13
-
14
- or
15
-
16
- worksheet.range([1,1])
17
-
18
- This returns the range of cell with address 1,1.
19
-
20
- With this new interface, we want to be compatible with the standard syntax of other known Excel libraries, e.g. +spreadsheet+ or +axlsx+.
21
-
22
1
  = RobustExcelOle
23
2
 
24
3
  RobustExcelOle helps controlling Excel.
@@ -126,7 +105,7 @@ Then we'll save the workbook.
126
105
 
127
106
  workbook.save
128
107
 
129
- === More features when opening, modifying, creating, saving and closing workbooks
108
+ === Unobtrusively opening workbooks
130
109
 
131
110
  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.
132
111
 
@@ -142,7 +121,9 @@ RobustExcelOle allows unobtrusively reading and modifying workbooks, i.e. access
142
121
  # do something
143
122
  end
144
123
 
145
- We can also create a new, empty workbook.
124
+ === More featrues about creating, opening, saving and closing workbooks
125
+
126
+ We can create a new, empty workbook.
146
127
 
147
128
  Workbook.create('spec/data/new_workbook.xls', visible: true)
148
129
 
@@ -178,7 +159,7 @@ or save the workbook under a different name.
178
159
 
179
160
  Finally we can close the workbook
180
161
 
181
- workbook.save
162
+ workbook.close
182
163
 
183
164
  or save and close the workbook in one step.
184
165
 
@@ -210,10 +191,6 @@ We close the Excel instance using
210
191
 
211
192
  excel1.close
212
193
 
213
- Closed Excel instances can be reopened.
214
-
215
- excel1.recreate(reopen_workbooks: true, visible: true)
216
-
217
194
  Closing all Excel instances is done by
218
195
 
219
196
  Excel.close_all(if_unsaved: :forget)
@@ -237,17 +214,12 @@ Now we want to open another workbook in a different Excel instance.
237
214
 
238
215
  workbook2 = Workbook.open('spec/data/different_workbook.xls', excel: :new)
239
216
 
240
- We can also create a third Excel instance and open another workbook in this instance.
241
-
242
- excel1 = Excel.create
243
- workbook3 = Workbook.open('spec/data/another_workbook.xls', excel: excel1)
244
-
245
217
  A workbook is opened by default in the Excel instance where it was open before most recently.
246
218
 
247
219
  workbook1.close
248
220
  workbook1 = Workbook.open('spec/data/workbook.xls')
249
221
 
250
- If this Excel instance is damaged or closed, then options control whether the workbook shall be opened in the current (active), a new or a given Excel instance.
222
+ If the Excel instance is damaged or closed, then options control whether the workbook shall be opened in the current (active), a new or a given Excel instance.
251
223
 
252
224
  workbook1 = Workbook.open('spec/data/workbook.xls', default: {excel: new})
253
225
 
@@ -257,7 +229,7 @@ Without the option +:default+, the workbook can be forced to be opened in the cu
257
229
 
258
230
  === Managing conflicts with unsaved and blocking workbooks
259
231
 
260
- RobustExcelOle enables processing workbooks, while still supporting user's interactions: The commands enable to open, close, reopen, read, modify, write and save Excel workbooks, without the need of the user's interaction, and even without the user noticing. Thus, while running a script containing RobustExcelOle commands, the user can open and process workbooks in any Excel instances at any time. RobustExcelOle manages the complex cases of conflicts that might occur such that the user does not need to interfere and the script can continue.
232
+ RobustExcelOle enables processing workbooks, while supporting user's interactions: The commands enable to open, close, reopen, read, modify, write and save Excel workbooks, without the need of the user's interaction, and even without the user noticing. Thus, while running a script containing RobustExcelOle commands, the user can open and process workbooks in any Excel instances at any time. RobustExcelOle manages the complex cases of conflicts that might occur such that the user does not need to interfere and the script can continue.
261
233
 
262
234
  For example, suppose we want to process a list of workbooks. RobustExcelOle allows to rapidly open, manipulate, close and save these workbooks. Now assume, the workbook "workbook.xls" is being processed, while the user has already opened this workbook, has modified but not saved it yet. Excel would prompt a message and ask the user what to do. RobustExcelOle solves this conflict by using an option that states whether the changes of the user should be saved (accepted) or discarded (forgotten) before opening the workbook, e.g.
263
235
 
@@ -308,22 +280,10 @@ We can define a rectangular range by providing the top left and the bottum down
308
280
 
309
281
  worksheet.range([1..3,1..4])
310
282
 
311
- We can read the first three cells of the first row
312
-
313
- worksheet.row_range(1, 1..3).values # => ["foo","workbook","sheet1"]
314
-
315
- and the third column
316
-
317
- worksheet.col_range(3).values # => ["sheet1", 2.0, 4.0]
318
-
319
283
  We can read the first cell, using
320
284
 
321
285
  worksheet[1,1]. # => "foo"
322
286
 
323
- or
324
-
325
- worksheet.row_range(1)[0].value # => "foo"
326
-
327
287
  Then we modify it.
328
288
 
329
289
  worksheet[1,1] = "hello"
@@ -338,7 +298,6 @@ and set another value to that range.
338
298
 
339
299
  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]
340
300
 
341
-
342
301
  === List Objects (Tables)
343
302
 
344
303
  We can define a list object (or table) from scratch
@@ -349,10 +308,6 @@ or get a given list object in a worksheet given its table number or name.
349
308
 
350
309
  table = worksheet.table(1)
351
310
 
352
- or
353
-
354
- table = worksheet.table("table1")
355
-
356
311
  A list row can be accessed by providing either the row number or a key, i.e. hash of column name - value pairs, e.g.
357
312
 
358
313
  row1 = table[1]
@@ -361,8 +316,8 @@ A list row can be accessed by providing either the row number or a key, i.e. has
361
316
 
362
317
  You can get all or a maximal number of list rows matching the key.
363
318
 
364
- rows = table[{"Number": 1}, limit: 2]
365
319
  rows = table[{"Number": 1}, limit: nil]
320
+ rows = table[{"Number": 1}, limit: 2]
366
321
 
367
322
  Now we can set 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.
368
323
 
@@ -393,25 +348,21 @@ and
393
348
 
394
349
  table.set_column_values(1, ["Herbert","Paul"])
395
350
 
396
- We can add and delete rows and columns, supplying optionally their name, the position and contents.
351
+ For more details about using and processing list objects see {README_listobjects}[https://github.com/Thomas008/robust_excel_ole/blob/master/docs/README_listobjects.rdoc]
397
352
 
398
- table.add_column("column_name", 3, ["John", "Paul"])
399
- table.add_row(3, ["John", 40, 2, 2004])
353
+ === More features
400
354
 
401
- table.delete_column_values("column_name")
402
- table[2].delete_values
355
+ 1. The class WIN32OLE is being extended such that RobustExcelOle methods can be applied to WIN32OLE objects. As mentioned above, the RobustExcelOle objects are wrapper of corresponding WIN32OLE objects. So now the RobustExcelOle objects and their wrapped WIN32OLE objects are interchangeable. One example would be
403
356
 
404
- Finally we can delete empty rows and columns.
357
+ range.ole_range.copy([4,3])
405
358
 
406
- table.delete_empty_rows
407
- table.delete_empty_columns
359
+ Likewise it is possible to convert ("type-lift") WIN32OLE objects into the corresponding RobustExcelOle object, using the method +to_reo+. It is a refinement of the class WIN32OLE. So you can write
408
360
 
409
- For more details about using and processing list objects see {README_listobjects}[https://github.com/Thomas008/robust_excel_ole/blob/master/docs/README_listobjects.rdoc]
410
-
361
+ using ToReoRefinement
411
362
 
412
- === More features
363
+ range = sheet.Names.Item("firstcell").to_reo
413
364
 
414
- 1. The method +General.change_current_binding+ allows to change the value of self within the current binding, while preserving the local variables, without starting another repl. Assume, +object+ shall be the self, then you would put
365
+ 2. The method +General.change_current_binding+ allows to change the value of self within the current binding, while preserving the local variables, without starting another repl. Assume, +object+ shall be the self, then you would put
415
366
 
416
367
  General.change_current_binding(object)
417
368
 
@@ -425,17 +376,6 @@ or
425
376
 
426
377
  However, this command also starts another pry repl (with another binding). Moreover, local variables in the previous binding are forgotten.
427
378
 
428
-
429
- 2. The class Win32Ole is being extended such that RobustExcelOle methods can be applied to WIN32OLE objects. As mentioned above, the RobustExcelOle objects are wrapper of corresponding WIN32OLE objects. So the RobustExcelOle objects and their wrapped WIN32OLE objects are interchangeable. One example would be
430
-
431
- range.ole_range.copy([4,3])
432
-
433
- Likewise it is possible to convert ("type-lift") Win32Ole objects into the corresponding RobustExcelOle object, using the method +to_reo+. It is a refinement of the class WIN32OLE. So you can write
434
-
435
- using ToReoRefinement
436
-
437
- range = sheet.Names.Item("firstcell").to_reo
438
-
439
379
  === Design issues
440
380
 
441
381
  We don't consider active worksheets or workbooks in our implementation, because this has been proven to be very error-prone.
@@ -130,7 +130,13 @@ module RobustExcelOle
130
130
  private
131
131
 
132
132
  def define_and_call_method(column_name,method_name,*args)
133
- column_name = column_name.force_encoding('cp850')
133
+ puts "define_and_call_method:"
134
+ puts "column_name: #{column_name} #{column_name.inspect}"
135
+ #column_name = column_name.force_encoding('cp850')
136
+ puts "after force_encoding: column_name: #{column_name} #{column_name.inspect}"
137
+ puts "ole_table.ListColumns: #{ole_table.ListColumns.inspect}"
138
+ column1 = ole_table.ListColumns.Item(column_name)
139
+ puts "column1: #{column1.inspect}"
134
140
  ole_cell = ole_table.Application.Intersect(
135
141
  @ole_tablerow.Range, ole_table.ListColumns.Item(column_name).Range)
136
142
  define_getting_setting_method(ole_cell,method_name)
@@ -80,14 +80,17 @@ module RobustExcelOle
80
80
  end
81
81
  end
82
82
 
83
- # returns values of a given range
83
+ # returns value of a given range restricted to used range
84
84
  # @returns [Array] values of the range (as a nested array)
85
- =begin
86
85
  def value
87
86
  value = begin
88
87
  if !::RANGES_JRUBY_BUG
89
- ole_range.Value[0,[ole_range.Rows.Count,worksheet.last_row].min].inject([]) do |res, row|
90
- res << (!row.nil? ? row[0,[ole_range.Columns.Count,worksheet.last_column].min] : nil)
88
+ intersection_range = ole_range.Application.Intersect(ole_range, worksheet.Range(
89
+ worksheet.Cells(1,1),worksheet.Cells(worksheet.last_row,worksheet.last_column)))
90
+ begin
91
+ intersection_range.Value
92
+ rescue
93
+ nil
91
94
  end
92
95
  else
93
96
  # optimization is possible here
@@ -104,28 +107,6 @@ module RobustExcelOle
104
107
  end
105
108
  value
106
109
  end
107
- =end
108
-
109
- def value
110
- value = begin
111
- if !::RANGES_JRUBY_BUG
112
- ole_range.Application.Intersect(ole_range, worksheet.Range(
113
- worksheet.Cells(1,1),worksheet.Cells(worksheet.last_row,worksheet.last_column))).Value
114
- else
115
- # optimization is possible here
116
- rows_used_range = [rows, last_row].min
117
- columns_used_rage = [columns, last_column].min
118
- values = rows_used_range.map{|r| columns_used_range.map {|c| worksheet.Cells(r,c).Value} }
119
- (values.size==1 && values.first.size==1) ? values.first.first : values
120
- end
121
- rescue
122
- raise RangeNotEvaluatable, "cannot evaluate range #{self.inspect}\n#{$!.message}"
123
- end
124
- if value == -2146828288 + RobustExcelOle::XlErrName
125
- raise RangeNotEvaluatable, "cannot evaluate range #{self.inspect}"
126
- end
127
- value
128
- end
129
110
 
130
111
  # sets the values if the range
131
112
  # @param [Variant] value
@@ -1,3 +1,3 @@
1
1
  module RobustExcelOle
2
- VERSION = "1.33"
2
+ VERSION = "1.34"
3
3
  end
@@ -278,6 +278,7 @@ module RobustExcelOle
278
278
  # changing read-only mode
279
279
  if (!options[:read_only].nil?) && options[:read_only] != @ole_workbook.ReadOnly
280
280
  ensure_workbook(filename, options)
281
+ raise WorkbookReadOnly, "could not change read-only mode" if options[:read_only] != @ole_workbook.ReadOnly
281
282
  end
282
283
  retain_saved do
283
284
  self.visible = options[:force][:visible].nil? ? @excel.Visible : options[:force][:visible]
@@ -108,11 +108,13 @@ module RobustExcelOle
108
108
  if a1_address
109
109
  range = self.Range(a1_address)
110
110
  else
111
+ saved = self.Parent.Saved
111
112
  begin
112
113
  self.Names.Add('__dummy_name_object_001__',nil,true,nil,nil,nil,nil,nil,nil,'=' + address_tool.as_r1c1(address))
113
114
  range = get_name_object('__dummy_name_object_001__').RefersToRange
114
115
  ensure
115
116
  self.Names.Item('__dummy_name_object_001__').Delete
117
+ self.Parent.Saved = saved
116
118
  end
117
119
  end
118
120
  rescue
data/spec/excel_spec.rb CHANGED
@@ -1925,7 +1925,7 @@ module RobustExcelOle
1925
1925
  excel_instances.first.should == excel
1926
1926
  excel_instances.to_a.should == [excel]
1927
1927
  res = []
1928
- excel_instances.each_with_index{|e,i| res << [e,i]}
1928
+ excel_instances.each.with_index{|e,i| res << [e,i]}.to_a
1929
1929
  res.should == [[excel,0]]
1930
1930
  end
1931
1931
 
@@ -1937,7 +1937,7 @@ module RobustExcelOle
1937
1937
  excel_instances.first.should == excel1
1938
1938
  excel_instances.to_a.should == [excel1, excel2]
1939
1939
  res = []
1940
- excel_instances.each_with_index{|e,i| res << [e,i]}
1940
+ excel_instances.each.with_index{|e,i| res << [e,i]}.to_a
1941
1941
  res.should == [[excel1,0],[excel2,1]]
1942
1942
  end
1943
1943
 
Binary file
data/spec/range_spec.rb CHANGED
@@ -69,7 +69,7 @@ describe RobustExcelOle::Range do
69
69
 
70
70
  it "should concatenate" do
71
71
  values = []
72
- @range2.each.with_index{|c,i| values << [c.v, i]}
72
+ @range2.each.with_index{|c,i| values << [c.v, i]}.to_a
73
73
  values.should == [["simple", 0], ["file", 1], ["sheet2", 2], [nil, 3], [nil, 4], [nil, 5]]
74
74
  end
75
75
 
@@ -225,7 +225,7 @@ describe RobustExcelOle::Range do
225
225
 
226
226
  it "should return value" do
227
227
  @sheet[1,1].should == 'simple'
228
- @sheet.range(1..2,3..4).v.should == [["sheet2", nil], [nil, nil]]
228
+ @sheet.range(1..2,3..4).v.should == "sheet2"
229
229
  end
230
230
 
231
231
  it "should set value of a cell and return its value" do
@@ -237,7 +237,7 @@ describe RobustExcelOle::Range do
237
237
  end
238
238
 
239
239
  it "should set value and return value of a rectangular range" do
240
- @sheet1.range([1..2,3..5]).v.should == [["sheet1",nil,nil],["foobaaa",nil,nil]]
240
+ @sheet1.range([1..2,3..5]).v.should == [["sheet1"], ["foobaaa"]]
241
241
  @sheet1.range([1..2,3..5]).v = [[1,2,3],[4,5,6]]
242
242
  @sheet1.range([1..2,3..5]).v.should == [[1,2,3],[4,5,6]]
243
243
  end
@@ -1425,7 +1425,7 @@ describe Workbook do
1425
1425
 
1426
1426
  it "should concatenate" do
1427
1427
  names = ""
1428
- @book.each.with_index{|s,i| names << "#{s.name} #{i} " }
1428
+ @book.each.with_index{|s,i| names << "#{s.name} #{i} " }.to_a
1429
1429
  names.should == "Sheet1 0 Sheet2 1 Sheet3 2 "
1430
1430
  end
1431
1431
 
@@ -33,9 +33,11 @@ describe Workbook do
33
33
  @simple_file_direct = File.join(File.dirname(__FILE__), 'data') + '/workbook.xls'
34
34
  #@simple_file_via_network = File.join('N:/', 'data') + '/workbook.xls'
35
35
  @simple_file_network_path = "N:/data/workbook.xls"
36
- @simple_file_hostname_share_path = '//DESKTOP-A3C5CJ6/spec/data/workbook.xls'
36
+ network = WIN32OLE.new('WScript.Network')
37
+ computer_name = network.ComputerName
38
+ @simple_file_hostname_share_path = "//#{computer_name}/#{absolute_path('spec/data/workbook.xls').tr('\\','/').gsub('C:','c$')}"
37
39
  @simple_file_network_path_other_path = "N:/data/more_data/workbook.xls"
38
- @simple_file_hostname_share_path_other_path = '//DESKTOP-A3C5CJ6/spec/data/more_data/workbook.xls'
40
+ @simple_file_hostname_share_path_other_path = "//#{computer_name}/#{absolute_path('spec/more_data/workbook.xls').tr('\\','/').gsub('C:','c$')}"
39
41
  @simple_file_network_path1 = @simple_file_network_path
40
42
  @simple_file_hostname_share_path1 = @simple_file_hostname_share_path
41
43
  @simple_file_network_path_other_path1 = @simple_file_network_path_other_path
@@ -87,8 +89,8 @@ describe Workbook do
87
89
 
88
90
  it "should raise error when trying to change the read-only mode of the linked workbook" do
89
91
  expect{
90
- book2 = Workbook.open(@sub_file, :read_only => true)
91
- }.to raise_error(WorkbookLinked)
92
+ Workbook.open(@sub_file, :read_only => true)
93
+ }.to raise_error(WorkbookReadOnly, /could not change read-only mode/)
92
94
  end
93
95
  end
94
96
  end
@@ -464,7 +466,7 @@ describe Workbook do
464
466
  Workbook.open(@simple_file_network_path1) do |book|
465
467
  book.should be_alive
466
468
  book.should be_a Workbook
467
- book.filename.should == @simple_file_hostname_share_path1.downcase
469
+ book.filename.should == @simple_file_network_path1 #@simple_file_hostname_share_path1.downcase
468
470
  book.Fullname.should == @ole_wb.Fullname
469
471
  book.excel.ole_excel.Hwnd.should == @ole_wb.Application.Hwnd
470
472
  Excel.instance_count.should == 1
@@ -536,7 +538,7 @@ describe Workbook do
536
538
  Workbook.open(@simple_file_hostname_share_path1) do |book|
537
539
  book.should be_alive
538
540
  book.should be_a Workbook
539
- book.filename.should == @simple_file_hostname_share_path1.downcase
541
+ book.filename.should == @simple_file_network_path1 # @simple_file_hostname_share_path1.downcase
540
542
  book.Fullname.should == @ole_wb.Fullname
541
543
  book.excel.ole_excel.Hwnd.should == @ole_wb.Application.Hwnd
542
544
  Excel.instance_count.should == 1
@@ -2773,7 +2775,7 @@ describe Workbook do
2773
2775
  new_book.should be_alive
2774
2776
  new_book.filename.should_not == @book.filename
2775
2777
  new_book.excel.should_not == @book.excel
2776
- new_book.sheet(1)[1,1].should == @book.sheet(1)[1,1]
2778
+ new_book.sheet(1)[1,1].should == @old_value
2777
2779
  end
2778
2780
 
2779
2781
  it "should raise an error, if :if_obstructed is default" do
@@ -363,7 +363,7 @@ describe Workbook do
363
363
  expect{
364
364
  Workbook.unobtrusively(@sub_file, :read_only => true) do
365
365
  end
366
- }.to raise_error(WorkbookLinked)
366
+ }.to raise_error(WorkbookReadOnly)
367
367
  end
368
368
  end
369
369
  end
@@ -505,6 +505,14 @@ describe Worksheet do
505
505
 
506
506
  describe "#range" do
507
507
 
508
+ it "should delete range, if it was defined before" do
509
+ @sheet.add_name("__dummy_name_object_001__", [1,1])
510
+ range = @sheet.range([2,2])
511
+ expect{
512
+ @sheet.Names.Item("__dummy_name_object_001__")
513
+ }.to raise_error
514
+ end
515
+
508
516
  it "should access a rectangular range [1..2,1..3]" do
509
517
  range1 = @sheet.range(1..2,1..3)
510
518
  range1.should be_kind_of RobustExcelOle::Range
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.33'
4
+ version: '1.34'
5
5
  platform: ruby
6
6
  authors:
7
7
  - traths
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-01 00:00:00.000000000 Z
11
+ date: 2021-06-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: win32api
@@ -210,6 +210,7 @@ files:
210
210
  - spec/helpers/key_sender.rb
211
211
  - spec/list_object_spec.rb
212
212
  - spec/list_row_spec.rb
213
+ - spec/more_data/workbook.xls
213
214
  - spec/range_spec.rb
214
215
  - spec/spec_helper.rb
215
216
  - spec/workbook_spec.rb