robust_excel_ole 1.9 → 1.10

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: 3cf45dfa8d36893f06b8196d99990c94b76056fdfd8b98e2a1cff18f11dedec5
4
- data.tar.gz: 2fb8ee7deb7bb700c9a7557340933b0a60a6ee38a8eaff9ed2c2f4b4669cadc0
3
+ metadata.gz: e9645dff34f91fdb38da9b5a8375e17170bace4159355b126b142cb4ab6689bf
4
+ data.tar.gz: d0ca3dbd87bca685ecb98ba1ac747b427c430e52bfe3de5b14beccfefd30d94c
5
5
  SHA512:
6
- metadata.gz: 6b8c23bf581b8ec11b9e510bf0bf805e2309a089a307c01bdcaf4aead8dc1aa31becd972e94beedb5e7ac82183ac4f84bd0c5ea6883a4a15baa2d2f95fd13dba
7
- data.tar.gz: 6958f89f6a6204f359a2f16469ca602a33b1572588b31944a073ffbc48936a9e9412edd4b742bb57ecff4e3b96756e99258924f60d5d2b7aaf8fefabafc0c697
6
+ metadata.gz: ae0be8a8538c3dd3c27a44c3d11d781be260cb2898e1cf221925d0902160ef4104b9142fd99c106ee5f210aa83688fa062d4ee1a13c8ae49dcb96b150b3baaeb
7
+ data.tar.gz: c21be14de79476461692a475685e518f478947051ac9cc8d417952646690b642e8dc2e52999a16b56c2cb8e337ac58b21ae2a28dfffbd8f89260aeced27d216b
data/.gitignore CHANGED
@@ -9,3 +9,4 @@ doc/*
9
9
  *.sublime-workspace
10
10
  .yardoc
11
11
  TodoList.md
12
+ spec/data/*.xls*
data/Changelog CHANGED
@@ -1,6 +1,12 @@
1
1
  # Change Log
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
+ ## [1.10]
5
+
6
+ ### Added
7
+ - workarounds for running in Jruby
8
+ - Range,Cell#v
9
+
4
10
  ## [1.9]
5
11
 
6
12
  ### Added
data/README.rdoc CHANGED
@@ -36,6 +36,12 @@ and go into the path of the gem 'robust_excel_ole'. There you start the console
36
36
 
37
37
  reo
38
38
 
39
+ or
40
+
41
+ jreo
42
+
43
+ depending on whether you are using ruby or jruby.
44
+
39
45
  The call of the console will include RobustExcelOle for you.
40
46
 
41
47
  The following examples can be used for both scripts and console. If you have started the console in the gem path, you can just put these examples.
@@ -299,6 +305,14 @@ and set another value to that range.
299
305
 
300
306
  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]
301
307
 
308
+ === Running in jruby
309
+
310
+ RobustExcelOle runs in jruby as well. You can call the console via the command +jreo+. However, note that, due to some restrictions of the library jruby-win32ole, there are some restrictions. So we had implemented some adaptions and workarounds. Some issues still remain when running under jruby:
311
+
312
+ 1. Excel.current or Excel.new(:reuse => true) does not connect to an already running Excel instance, unless some workbook has been opened via RobustExcelOle. 2. Excel.kill_all does work, Excel.close_all does not work. 3. When providing an absolute path, you have to state the "/" ("C:/abc.xls" works, "C:abc" does not work)
313
+
314
+
315
+
302
316
  === More things
303
317
 
304
318
  You can convert a win32ole object into a RobustExcelOle object.
@@ -57,6 +57,14 @@ or as flat array
57
57
  range.values
58
58
  => ["foo", "workbook", "sheet1", nil, "foo", nil, "foobaaa", nil, "matz", "is", "nice", nil]
59
59
 
60
+ You can set values with help of range#Value or range#v, e.g.
61
+
62
+ range.Value = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
63
+
64
+ or
65
+
66
+ range.v = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
67
+
60
68
  Now we copy the range. With help of VBA methods you would do
61
69
 
62
70
  range.Copy(:destination => sheet.range([4..6,5..8]).ole_range)
@@ -67,12 +67,14 @@ Additionally you can specify a name and a position.
67
67
 
68
68
  book.copy_sheet(sheet, :as => 'new_name', :after => another_sheet)
69
69
 
70
- If you want to copy a worksheet, if a sheet is given, and add an empty worksheet, if no worksheet is given, then use
70
+ If you want to copy a worksheet, if a worksheet +sheet+ is given, and add an empty worksheet, if no worksheet is given, then use
71
71
 
72
72
  book.add_or_copy_sheet
73
73
 
74
74
  book.add_or_copy_sheet(sheet, :as => 'new_name', :after => another_sheet)
75
75
 
76
+ Note, that running in jruby, due to some restrictions of jruby, there is a workaround when adding or copy a worksheet at the end (appending): the last worksheet is being copied and deleted afterwards, in order to serve as a dummy worksheet. This may cause a different behaviour.
77
+
76
78
  == Code
77
79
 
78
80
  worksheet.rb[https://github.com/Thomas008/robust_excel_ole/blob/master/lib/robust_excel_ole/worksheet.rb]
@@ -46,7 +46,7 @@ begin
46
46
  book.close # close the book
47
47
 
48
48
  ensure
49
- Excel.close_all
49
+ Excel.close_all(:if_unsaved => :forget)
50
50
  rm_tmp(dir)
51
51
  end
52
52
 
@@ -7,7 +7,7 @@ require "fileutils"
7
7
 
8
8
  include RobustExcelOle
9
9
 
10
- Excel.close_all
10
+ Excel.kill_all
11
11
  begin
12
12
  dir = create_tmpdir
13
13
  simple_file = dir + 'workbook.xls'
@@ -63,7 +63,7 @@ begin
63
63
  @book.close(:if_unsaved => :forget) # close the book without saving it
64
64
 
65
65
  ensure
66
- Excel.close_all
66
+ Excel.close_all(:if_unsaved => :forget)
67
67
  rm_tmp(dir)
68
68
  end
69
69
 
@@ -20,7 +20,7 @@ begin
20
20
  sleep 1
21
21
  begin
22
22
  new_book = Workbook.open(other_file_name, :if_obstructed => :close_if_saved) # raises an exception since the file is not saved
23
- rescue WorkbookNotSaved => msg
23
+ rescue WorkbookBlocked => msg
24
24
  puts "error: open: #{msg.message}"
25
25
  end
26
26
  book.save # save the unsaved book
data/jreo.bat ADDED
@@ -0,0 +1,3 @@
1
+ @echo off
2
+
3
+ jirb -f -r ./lib/robust_excel_ole -r ./lib/jreo_console.rb
@@ -0,0 +1,67 @@
1
+ # require '../robust_excel_ole/lib/robust_excel_ole'
2
+ include REO
3
+ # include RobustExcelOle
4
+ include General
5
+
6
+ require 'irb/completion'
7
+ require 'irb/ext/save-history'
8
+ gem 'jruby-readline'
9
+
10
+ ARGV.concat ['--readline',
11
+ '--prompt-mode',
12
+ 'simple',
13
+ '-rjruby-readline']
14
+
15
+ #IRB.conf[:PROMPT_MODE] = :SIMPLE
16
+ #IRB.conf[:USE_READLINE] = true
17
+ #IRB.conf[:AUTO_INDENT] = true
18
+
19
+
20
+
21
+
22
+ # 250 entries in the list
23
+ IRB.conf[:SAVE_HISTORY] = 250
24
+
25
+ # Store results in home directory with specified file name
26
+ # IRB.conf[:HISTORY_FILE] = "#{ENV['HOME']}/.irb-history"
27
+ #IRB.conf[:HISTORY_FILE] = "#{ENV['HOME']}/.irb-save-history"
28
+
29
+ IRB.conf[:HISTORY_FILE] = "#{ENV['HOME']}/.reo-history"
30
+
31
+ # @private
32
+ module Readline
33
+ module Hist
34
+ LOG = IRB.conf[:HISTORY_FILE]
35
+ # LOG = "#{ENV['HOME']}/.irb-history"
36
+
37
+ def self.write_log(line)
38
+ File.open(LOG, 'ab') do |f|
39
+ f << "#{line}
40
+ "
41
+ end
42
+ end
43
+
44
+ def self.start_session_log
45
+ timestamp = proc { Time.now.strftime('%Y-%m-%d, %H:%M:%S') }
46
+ # @private
47
+ class <<timestamp
48
+ alias_method :to_s, :call
49
+ end
50
+ write_log("###### session start: #{timestamp}")
51
+ at_exit { write_log("###### session stop: #{timestamp}") }
52
+ end
53
+ end
54
+
55
+ alias old_readline readline
56
+ def readline(*args)
57
+ ln = old_readline(*args)
58
+ begin
59
+ Hist.write_log(ln)
60
+ rescue StandardError
61
+ end
62
+ ln
63
+ end
64
+ end
65
+
66
+ Readline::Hist.start_session_log
67
+ puts 'JREO console started'
@@ -1,4 +1,8 @@
1
- require 'win32ole'
1
+ if RUBY_PLATFORM =~ /java/
2
+ require 'jruby-win32ole'
3
+ else
4
+ require 'win32ole'
5
+ end
2
6
  require File.join(File.dirname(__FILE__), 'robust_excel_ole/reo_common')
3
7
  require File.join(File.dirname(__FILE__), 'robust_excel_ole/range_owners')
4
8
  require File.join(File.dirname(__FILE__), 'robust_excel_ole/address')
@@ -4,12 +4,16 @@ module RobustExcelOle
4
4
 
5
5
  class Address < REOCommon
6
6
 
7
+ # hack
8
+ #@@row_letter = "Z"
9
+ #@@col_letter = "S"
10
+
7
11
  def self.new(r1c1_letters)
8
12
  @@row_letter = r1c1_letters[0..0]
9
13
  @@col_letter = r1c1_letters[1..1]
10
14
  end
11
15
 
12
- # address formats taht are valid:
16
+ # address formats that are valid:
13
17
  # r1c1-format: e.g. "Z3S1", "Z3S1:Z5S2", "Z[3]S1", "Z3S[-1]:Z[5]S1", "Z[3]", "S[-2]"
14
18
  # infinite ranges are not possible, e.g. "Z3:Z5", "S2:S5", "Z2", "S3", "Z[2]"
15
19
  # int_range: e.g. [3,1], [3,"A"], [3..5,1..2], [3..5, "A".."B"],
@@ -8,6 +8,14 @@ module RobustExcelOle
8
8
  @hidden_excel_instance = nil
9
9
  end
10
10
 
11
+ # returns an excel
12
+ def excel
13
+ fn2books = @filename2books.first
14
+ return nil if fn2books.nil? || fn2books.empty? || fn2books[1].empty?
15
+ book = fn2books[1].first.__getobj__
16
+ book.excel
17
+ end
18
+
11
19
  # returns a book with the given filename, if it was open once
12
20
  # @param [String] filename the file name
13
21
  # @param [Hash] options the options
@@ -5,17 +5,17 @@ module RobustExcelOle
5
5
  attr_reader :cell
6
6
 
7
7
  def initialize(win32_cell)
8
- @cell = if win32_cell.MergeCells
9
- win32_cell.MergeArea.Item(1,1)
10
- else
11
- win32_cell
12
- end
8
+ @cell = win32_cell.MergeCells ? win32_cell.MergeArea.Item(1,1) : win32_cell
13
9
  end
14
10
 
15
11
  def v
16
12
  self.Value
17
13
  end
18
14
 
15
+ def v=(value)
16
+ self.Value = value
17
+ end
18
+
19
19
  # @private
20
20
  def method_missing(name, *args)
21
21
  #if name.to_s[0,1] =~ /[A-Z]/
@@ -75,7 +75,15 @@ module RobustExcelOle
75
75
  end
76
76
  ole_xl = win32ole_excel unless win32ole_excel.nil?
77
77
  options = { :reuse => true }.merge(options)
78
- ole_xl = current_excel if options[:reuse] == true
78
+ #ole_xl = current_excel if options[:reuse] == true
79
+ if options[:reuse] == true
80
+ ole_xl = if RUBY_PLATFORM =~ /java/
81
+ excel_instance = known_excel_instance
82
+ ole_xl = excel_instance.ole_excel unless excel_instance.nil?
83
+ else
84
+ current_excel
85
+ end
86
+ end
79
87
  ole_xl ||= WIN32OLE.new('Excel.Application')
80
88
  hwnd = ole_xl.HWnd
81
89
  stored = hwnd2excel(hwnd)
@@ -102,7 +110,7 @@ module RobustExcelOle
102
110
  end
103
111
  end
104
112
  result
105
- end
113
+ end
106
114
 
107
115
  def initialize(options = {}); end
108
116
 
@@ -141,12 +149,14 @@ module RobustExcelOle
141
149
  # connects to the first opened Excel instance
142
150
  # if this Excel instance is being closed, then Excel creates a new Excel instance
143
151
  # @private
144
- def self.current_excel
145
- result = begin
146
- WIN32OLE.connect('Excel.Application')
147
- rescue
148
- nil
149
- end
152
+ def self.current_excel
153
+ result = if result.nil?
154
+ begin
155
+ WIN32OLE.connect('Excel.Application')
156
+ rescue
157
+ nil
158
+ end
159
+ end
150
160
  if result
151
161
  begin
152
162
  result.Visible # send any method, just to see if it responds
@@ -413,7 +423,18 @@ module RobustExcelOle
413
423
  processes.select { |p| p.name == 'EXCEL.EXE' }.size
414
424
  end
415
425
 
416
- # returns all Excel objects for all Excel instances opened with RobustExcelOle,
426
+ # returns an Excel instance
427
+ def self.known_excel_instance
428
+ @@hwnd2excel.each do |hwnd, wr_excel|
429
+ if wr_excel.weakref_alive?
430
+ excel = wr_excel.__getobj__
431
+ return excel if excel.alive?
432
+ end
433
+ end
434
+ nil
435
+ end
436
+
437
+ # returns all Excel objects for all Excel instances opened with RobustExcelOle
417
438
  def self.known_excel_instances
418
439
  pid2excel = {}
419
440
  @@hwnd2excel.each do |hwnd,wr_excel|
@@ -427,8 +448,6 @@ module RobustExcelOle
427
448
  pid2excel[pid] = excel
428
449
  end
429
450
  processes = WIN32OLE.connect('winmgmts:\\\\.').InstancesOf('win32_process')
430
- # excel_processes = processes.select{ |p| p.name == "EXCEL.EXE" && pid2excel.include?(p.processid)}
431
- # excel_processes.map{ |p| Excel.new(pid2excel[p.processid]) }
432
451
  processes.select { |p| Excel.new(pid2excel[p.processid]) if p.name == 'EXCEL.EXE' && pid2excel.include?(p.processid) }
433
452
  result = []
434
453
  processes.each do |p|
@@ -27,10 +27,6 @@ module General
27
27
 
28
28
  module_function :absolute_path, :canonize, :normalize
29
29
 
30
- # @private
31
- class VBAMethodMissingError < RuntimeError
32
- end
33
-
34
30
  end
35
31
 
36
32
  # @private
@@ -26,7 +26,13 @@ module RobustExcelOle
26
26
  # @params [Range] a range
27
27
  # @returns [Array] the values
28
28
  def values(range = nil)
29
- result = map { |x| x.Value }.flatten
29
+ #result = map { |x| x.Value }.flatten
30
+ result_unflatten = if RUBY_PLATFORM !~ /java/
31
+ map { |x| x.v }
32
+ else
33
+ self.v
34
+ end
35
+ result = result_unflatten.flatten
30
36
  if range
31
37
  relevant_result = []
32
38
  result.each_with_index { |row_or_column, i| relevant_result << row_or_column if range.include?(i) }
@@ -37,7 +43,42 @@ module RobustExcelOle
37
43
  end
38
44
 
39
45
  def v
40
- self.Value
46
+ begin
47
+ if RUBY_PLATFORM !~ /java/
48
+ self.Value
49
+ else
50
+ address_r1c1 = self.AddressLocal(true,true,XlR1C1)
51
+ row, col = Address.int_range(address_r1c1)
52
+ values = []
53
+ row.each do |r|
54
+ values_col = []
55
+ col.each{ |c| values_col << worksheet.Cells(r,c).Value}
56
+ values << values_col
57
+ end
58
+ values
59
+ end
60
+ rescue WIN32OLERuntimeError
61
+ raise RangeNotEvaluatable, 'cannot read value'
62
+ end
63
+ end
64
+
65
+ def v=(value)
66
+ begin
67
+ if RUBY_PLATFORM !~ /java/
68
+ ole_range.Value = value
69
+ else
70
+ address_r1c1 = ole_range.AddressLocal(true,true,XlR1C1)
71
+ row, col = Address.int_range(address_r1c1)
72
+ row.each_with_index do |r,i|
73
+ col.each_with_index do |c,j|
74
+ ole_range.Cells(i+1,j+1).Value = (value.respond_to?(:first) ? value[i][j] : value)
75
+ end
76
+ end
77
+ end
78
+ value
79
+ rescue # WIN32OLERuntimeError
80
+ raise RangeNotEvaluatable, "cannot assign value to range #{address_r1c1.inspect}"
81
+ end
41
82
  end
42
83
 
43
84
  def [] index
@@ -74,7 +115,7 @@ module RobustExcelOle
74
115
  end
75
116
  end
76
117
  rows, columns = Address.int_range(dest_address)
77
- dest_sheet = @worksheet if dest_sheet == :__not_provided
118
+ #dest_sheet = @worksheet if dest_sheet == :__not_provided
78
119
  dest_address_is_position = (rows.min == rows.max && columns.min == columns.max)
79
120
  dest_range_address = if (not dest_address_is_position)
80
121
  [rows.min..rows.max,columns.min..columns.max]
@@ -90,14 +131,17 @@ module RobustExcelOle
90
131
  dest_range = dest_sheet.range(dest_range_address)
91
132
  begin
92
133
  if options[:values_only]
93
- dest_range.Value = options[:transpose] ? self.Value.transpose : self.Value
134
+ # dest_range.Value = options[:transpose] ? self.Value.transpose : self.Value
135
+ dest_range.v = options[:transpose] ? self.v.transpose : self.v
94
136
  else
95
137
  if dest_range.worksheet.workbook.excel == @worksheet.workbook.excel
96
138
  if options[:transpose]
97
- self.Copy
98
- dest_range.PasteSpecial('transpose' => true)
139
+ self.Copy
140
+ #dest_range.PasteSpecial('transpose' => true)
141
+ dest_range.PasteSpecial(XlPasteAll,XlPasteSpecialOperationNone,false,true)
99
142
  else
100
- self.Copy('destination' => dest_range.ole_range)
143
+ #self.Copy('destination' => dest_range.ole_range)
144
+ self.Copy(dest_range.ole_range)
101
145
  end
102
146
  else
103
147
  if options[:transpose]
@@ -107,7 +151,8 @@ module RobustExcelOle
107
151
  @worksheet.workbook.excel.with_displayalerts(false) {added_sheet.Delete}
108
152
  else
109
153
  self.Copy
110
- dest_sheet.Paste('destination' => dest_range.ole_range)
154
+ #dest_sheet.Paste('destination' => dest_range.ole_range)
155
+ dest_sheet.Paste(dest_range.ole_range)
111
156
  end
112
157
  end
113
158
  end
@@ -144,9 +189,11 @@ module RobustExcelOle
144
189
  if dest_range.worksheet.workbook.excel == @worksheet.workbook.excel
145
190
  if options[:transpose]
146
191
  self.Copy
147
- dest_range.PasteSpecial('transpose' => true)
192
+ #dest_range.PasteSpecial('transpose' => true)
193
+ dest_range.PasteSpecial(XlPasteAll,XlPasteSpecialOperationNone,false,true)
148
194
  else
149
- self.Copy('destination' => dest_range.ole_range)
195
+ #self.Copy('destination' => dest_range.ole_range)
196
+ self.Copy(dest_range.ole_range)
150
197
  end
151
198
  else
152
199
  if options[:transpose]
@@ -156,7 +203,8 @@ module RobustExcelOle
156
203
  @worksheet.workbook.excel.with_displayalerts(false) {added_sheet.Delete}
157
204
  else
158
205
  self.Copy
159
- dest_sheet.Paste('destination' => dest_range.ole_range)
206
+ #dest_sheet.Paste('destination' => dest_range.ole_range)
207
+ dest_sheet.Paste(dest_range.ole_range)
160
208
  end
161
209
  end
162
210
  end
@@ -184,7 +232,7 @@ module RobustExcelOle
184
232
 
185
233
  # @private
186
234
  def method_missing(name, *args)
187
- #if name.to_s[0,1] =~ /[A-Z]/
235
+ if name.to_s[0,1] =~ /[A-Z]/
188
236
  begin
189
237
  @ole_range.send(name, *args)
190
238
  rescue WIN32OLERuntimeError => msg
@@ -194,9 +242,9 @@ module RobustExcelOle
194
242
  raise msg
195
243
  end
196
244
  end
197
- # else
198
- # super
199
- # end
245
+ else
246
+ super
247
+ end
200
248
  end
201
249
  end
202
250
  end