robust_excel_ole 1.1.1 → 1.1.3
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 +4 -4
- data/Changelog +7 -0
- data/README.rdoc +10 -4
- data/README_detail.rdoc +7 -4
- data/lib/robust_excel_ole/book.rb +11 -72
- data/lib/robust_excel_ole/excel.rb +5 -103
- data/lib/robust_excel_ole/reo_common.rb +159 -47
- data/lib/robust_excel_ole/sheet.rb +31 -125
- data/lib/robust_excel_ole/version.rb +1 -1
- data/robust_excel_ole.gemspec +2 -1
- data/spec/book_spec.rb +9 -9
- data/spec/book_specs/book_misc_spec.rb +11 -11
- data/spec/data/another_workbook.xls +0 -0
- data/spec/excel_spec.rb +8 -8
- data/spec/range_spec.rb +2 -2
- data/spec/sheet_spec.rb +18 -18
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9bc4f05390e7e89a7d95a262e280e94dff090063
|
4
|
+
data.tar.gz: db6443cf724e5f58acbe8607ab427fc1734afa08
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f789655b7ae560eecf54132d0470e2441b04d902b95c72c3fb165987e02ef7395235e4f0e3723519928a5df86897b6f6f7340adebb0dde9f66e7aeda493588ad
|
7
|
+
data.tar.gz: 7b4110169af5c687a5be28535b8c0359f95f4c30217df5d8d90f26e5a5c54dc28153bf4b8e0bfa9411961a44cc064118cbc681df68b95061a337b61efd247e27
|
data/Changelog
CHANGED
data/README.rdoc
CHANGED
@@ -1,15 +1,13 @@
|
|
1
1
|
= RobustExcelOle
|
2
2
|
|
3
|
-
This ruby gem automates reading, modifying, and writing Excel files.
|
4
|
-
It supports simultaneously running Excel instances and user interactions.
|
3
|
+
This ruby gem automates reading, modifying, and writing Excel files. It is designed to support several kinds of concurrency of both simultaneously running Excel instances and simultanously happening user interactions.
|
5
4
|
RobustExcelOle deals with various cases of Excel and user behaviour,
|
6
5
|
and implements workarounds for some Excel bugs.
|
7
6
|
The gem provides convenient methods for common tasks, and facilitates referenced libraries.
|
8
7
|
It supports Excel 2010.
|
9
8
|
|
10
9
|
RobustExcelOle works by sending VBA methods via Win32OLE.
|
11
|
-
|
12
|
-
The tool is optimised with help of the rcov tool.
|
10
|
+
It implements a management system and keeps track of Excel files and Excel instances.
|
13
11
|
|
14
12
|
== Requirements
|
15
13
|
|
@@ -24,6 +22,10 @@ The tool is optimised with help of the rcov tool.
|
|
24
22
|
require 'robust_excel_ole'
|
25
23
|
include RobustExcelOle
|
26
24
|
|
25
|
+
or call the console
|
26
|
+
|
27
|
+
reo.bat
|
28
|
+
|
27
29
|
== Description
|
28
30
|
|
29
31
|
In the following, some features of RobustExcelOle are depicted.
|
@@ -291,6 +293,10 @@ Hard terminating all Excel processes is done by
|
|
291
293
|
|
292
294
|
Excel.kill_all
|
293
295
|
|
296
|
+
=== Development
|
297
|
+
|
298
|
+
The tests of RobustExcelOle are optimised with help of the rcov tool.
|
299
|
+
|
294
300
|
=== More details
|
295
301
|
|
296
302
|
{README_detail.rdoc}[https://github.com/Thomas008/robust_excel_ole/blob/master/README_detail.rdoc]
|
data/README_detail.rdoc
CHANGED
@@ -1,15 +1,13 @@
|
|
1
1
|
= RobustExcelOle
|
2
2
|
|
3
|
-
This ruby gem automates modifying,
|
4
|
-
It supports simultaneously running Excel instances and user interactions.
|
3
|
+
This ruby gem automates reading, modifying, and writing Excel files. It is designed to support several kinds of concurrency of both simultaneously running Excel instances and simultanously happening user interactions.
|
5
4
|
RobustExcelOle deals with various cases of Excel and user behaviour,
|
6
5
|
and implements workarounds for some Excel bugs.
|
7
6
|
The gem provides convenient methods for common tasks, and facilitates referenced libraries.
|
8
7
|
It supports Excel 2010.
|
9
8
|
|
10
9
|
RobustExcelOle works by sending VBA methods via Win32OLE.
|
11
|
-
|
12
|
-
The tool is optimised with help of rcov.
|
10
|
+
It implements a management system and keeps track of Excel files and Excel instances.
|
13
11
|
|
14
12
|
== Requirements
|
15
13
|
|
@@ -21,8 +19,13 @@ The tool is optimised with help of rcov.
|
|
21
19
|
|
22
20
|
== Usage
|
23
21
|
|
22
|
+
require 'robust_excel_ole'
|
24
23
|
include RobustExcelOle
|
25
24
|
|
25
|
+
or call the console
|
26
|
+
|
27
|
+
reo.bat
|
28
|
+
|
26
29
|
=== Opening a workbook.
|
27
30
|
|
28
31
|
Example:
|
@@ -4,12 +4,14 @@ require 'weakref'
|
|
4
4
|
|
5
5
|
module RobustExcelOle
|
6
6
|
|
7
|
-
class Book <
|
7
|
+
class Book < RangeOwners
|
8
8
|
|
9
9
|
attr_accessor :excel
|
10
10
|
attr_accessor :ole_workbook
|
11
11
|
attr_accessor :stored_filename
|
12
12
|
attr_accessor :options
|
13
|
+
attr_accessor :modified_cells
|
14
|
+
attr_reader :workbook
|
13
15
|
|
14
16
|
alias ole_object ole_workbook
|
15
17
|
|
@@ -154,6 +156,8 @@ module RobustExcelOle
|
|
154
156
|
ensure_workbook(file, options)
|
155
157
|
end
|
156
158
|
bookstore.store(self)
|
159
|
+
@modified_cells = []
|
160
|
+
@workbook = @excel.workbook = self
|
157
161
|
if block
|
158
162
|
begin
|
159
163
|
yield self
|
@@ -548,6 +552,7 @@ module RobustExcelOle
|
|
548
552
|
raise WorkbookReadOnly, "Not opened for writing (opened with :read_only option)" if @ole_workbook.ReadOnly
|
549
553
|
begin
|
550
554
|
discoloring if opts[:discoloring]
|
555
|
+
@modified_cells = []
|
551
556
|
@ole_workbook.Save
|
552
557
|
rescue WIN32OLERuntimeError => msg
|
553
558
|
if msg.message =~ /SaveAs/ and msg.message =~ /Workbook/ then
|
@@ -632,7 +637,8 @@ module RobustExcelOle
|
|
632
637
|
private
|
633
638
|
|
634
639
|
def discoloring
|
635
|
-
self.each{|sheet| sheet.each{|cell| cell.Interior.ColorIndex = XlNone}}
|
640
|
+
# self.each{|sheet| sheet.UsedRange.each{|cell| cell.Interior.ColorIndex = XlNone}}
|
641
|
+
@modified_cells.each{|cell| cell.Interior.ColorIndex = XlNone}
|
636
642
|
end
|
637
643
|
|
638
644
|
def save_as_workbook(file, options) # :nodoc: #
|
@@ -645,6 +651,7 @@ module RobustExcelOle
|
|
645
651
|
when '.xlsm'; RobustExcelOle::XlOpenXMLWorkbookMacroEnabled
|
646
652
|
end
|
647
653
|
discoloring if options[:discoloring]
|
654
|
+
@modified_cells = []
|
648
655
|
@ole_workbook.SaveAs(General::absolute_path(file), file_format)
|
649
656
|
bookstore.store(self)
|
650
657
|
rescue WIN32OLERuntimeError => msg
|
@@ -661,15 +668,7 @@ module RobustExcelOle
|
|
661
668
|
|
662
669
|
# closes a given file if it is open
|
663
670
|
def self.close(file, opts = {:if_unsaved => :raise})
|
664
|
-
#puts "self.close:"
|
665
|
-
#puts "file: #{file}"
|
666
|
-
#begin
|
667
|
-
# bookstore.fetch(file)
|
668
|
-
#rescue
|
669
|
-
# puts "#{$!.message}"
|
670
|
-
#end
|
671
671
|
book = bookstore.fetch(file) rescue nil
|
672
|
-
#puts "book after fetch: #{book.inspect}"
|
673
672
|
book.close(opts) if book && book.alive?
|
674
673
|
end
|
675
674
|
|
@@ -722,7 +721,7 @@ module RobustExcelOle
|
|
722
721
|
def copy_sheet(sheet, opts = { })
|
723
722
|
new_sheet_name = opts.delete(:as)
|
724
723
|
after_or_before, base_sheet = opts.to_a.first || [:after, last_sheet]
|
725
|
-
sheet.Copy({ after_or_before.to_s => base_sheet.
|
724
|
+
sheet.Copy({ after_or_before.to_s => base_sheet.ole_worksheet })
|
726
725
|
new_sheet = sheet_class.new(@excel.Activesheet)
|
727
726
|
new_sheet.name = new_sheet_name if new_sheet_name
|
728
727
|
new_sheet
|
@@ -739,7 +738,7 @@ module RobustExcelOle
|
|
739
738
|
def add_empty_sheet(opts = { })
|
740
739
|
new_sheet_name = opts.delete(:as)
|
741
740
|
after_or_before, base_sheet = opts.to_a.first || [:after, last_sheet]
|
742
|
-
@ole_workbook.Worksheets.Add({ after_or_before.to_s => base_sheet.
|
741
|
+
@ole_workbook.Worksheets.Add({ after_or_before.to_s => base_sheet.ole_worksheet })
|
743
742
|
new_sheet = sheet_class.new(@excel.Activesheet)
|
744
743
|
new_sheet.name = new_sheet_name if new_sheet_name
|
745
744
|
new_sheet
|
@@ -788,66 +787,6 @@ module RobustExcelOle
|
|
788
787
|
set_nameval(name,value, :color => 42) # 42 - aqua-marin, 4-green
|
789
788
|
end
|
790
789
|
|
791
|
-
# returns the contents of a range with given name
|
792
|
-
# evaluates formula contents of the range is a formula
|
793
|
-
# if no contents could be returned, then return default value, if provided, raise error otherwise
|
794
|
-
# Excel Bug: if a local name without a qualifier is given, then by default Excel takes the first worksheet,
|
795
|
-
# even if a different worksheet is active
|
796
|
-
# @param [String] name the name of the range
|
797
|
-
# @param [Hash] opts the options
|
798
|
-
# @option opts [Symbol] :default the default value that is provided if no contents could be returned
|
799
|
-
# @return [Variant] the contents of a range with given name
|
800
|
-
def nameval(name, opts = {:default => nil})
|
801
|
-
name_obj = name_object(name)
|
802
|
-
value = begin
|
803
|
-
name_obj.RefersToRange.Value
|
804
|
-
rescue WIN32OLERuntimeError
|
805
|
-
begin
|
806
|
-
self.sheet(1).Evaluate(name_obj.Name)
|
807
|
-
rescue WIN32OLERuntimeError
|
808
|
-
return opts[:default] if opts[:default]
|
809
|
-
raise RangeNotEvaluatable, "cannot evaluate range named #{name.inspect} in #{File.basename(self.stored_filename).inspect}"
|
810
|
-
end
|
811
|
-
end
|
812
|
-
if value.is_a?(Bignum) #RobustExcelOle::XlErrName
|
813
|
-
return opts[:default] if opts[:default]
|
814
|
-
raise RangeNotEvaluatable, "cannot evaluate range named #{name.inspect} in #{File.basename(self.stored_filename).inspect}"
|
815
|
-
end
|
816
|
-
return opts[:default] if opts[:default] && value.nil?
|
817
|
-
value
|
818
|
-
end
|
819
|
-
|
820
|
-
# sets the contents of a range
|
821
|
-
# @param [String] name the name of a range
|
822
|
-
# @param [Variant] value the contents of the range
|
823
|
-
# @param [FixNum] color the color when setting a value
|
824
|
-
# @param [Hash] opts :color [FixNum] the color when setting the contents
|
825
|
-
def set_nameval(name, value, opts = {:color => 0})
|
826
|
-
begin
|
827
|
-
cell = name_object(name).RefersToRange
|
828
|
-
cell.Interior.ColorIndex = opts[:color]
|
829
|
-
cell.Value = value
|
830
|
-
rescue WIN32OLERuntimeError
|
831
|
-
raise RangeNotEvaluatable, "cannot assign value to range named #{name.inspect} in #{File.basename(self.stored_filename).inspect}"
|
832
|
-
end
|
833
|
-
end
|
834
|
-
|
835
|
-
private
|
836
|
-
|
837
|
-
def name_object(name)
|
838
|
-
begin
|
839
|
-
self.Parent.Names.Item(name)
|
840
|
-
rescue WIN32OLERuntimeError
|
841
|
-
begin
|
842
|
-
self.Names.Item(name)
|
843
|
-
rescue WIN32OLERuntimeError
|
844
|
-
raise NameNotFound, "name #{name.inspect} not in #{File.basename(self.stored_filename).inspect}"
|
845
|
-
end
|
846
|
-
end
|
847
|
-
end
|
848
|
-
|
849
|
-
public
|
850
|
-
|
851
790
|
# renames a range
|
852
791
|
# @param [String] name the previous range name
|
853
792
|
# @param [String] new_name the new range name
|
@@ -10,17 +10,18 @@ end
|
|
10
10
|
|
11
11
|
module RobustExcelOle
|
12
12
|
|
13
|
-
class Excel <
|
13
|
+
class Excel < RangeOwners
|
14
14
|
|
15
15
|
attr_accessor :ole_excel
|
16
16
|
attr_accessor :created
|
17
|
-
|
17
|
+
attr_accessor :workbook
|
18
|
+
|
18
19
|
# setter methods are implemented below
|
19
20
|
attr_reader :visible
|
20
21
|
attr_reader :displayalerts
|
21
22
|
attr_reader :calculation
|
22
23
|
attr_reader :screenupdating
|
23
|
-
|
24
|
+
|
24
25
|
alias ole_object ole_excel
|
25
26
|
|
26
27
|
@@hwnd2excel = {}
|
@@ -96,7 +97,7 @@ module RobustExcelOle
|
|
96
97
|
result.screenupdating = options[:screenupdating] unless options[:screenupdating].nil?
|
97
98
|
result.created = !reused
|
98
99
|
end
|
99
|
-
end
|
100
|
+
end
|
100
101
|
result
|
101
102
|
end
|
102
103
|
|
@@ -603,105 +604,6 @@ module RobustExcelOle
|
|
603
604
|
set_nameval(name,value, :color => 42) # 42 - aqua-marin, 7-green
|
604
605
|
end
|
605
606
|
|
606
|
-
# returns the contents of a range with given name
|
607
|
-
# evaluates the formula if the contents is a formula
|
608
|
-
# if no contents could be returned, then return default value, if provided, raise error otherwise
|
609
|
-
# @param [String] name the range name
|
610
|
-
# @param [Hash] opts the options
|
611
|
-
# @option opts [Variant] :default value (default: nil)
|
612
|
-
def nameval(name, opts = {:default => nil})
|
613
|
-
name_obj = name_object(name)
|
614
|
-
value = begin
|
615
|
-
name_obj.RefersToRange.Value
|
616
|
-
rescue WIN32OLERuntimeError
|
617
|
-
begin
|
618
|
-
self.Evaluate(name_obj.Name)
|
619
|
-
rescue WIN32OLERuntimeError
|
620
|
-
return opts[:default] if opts[:default]
|
621
|
-
raise RangeNotEvaluatable, "cannot evaluate range named #{name.inspect}"
|
622
|
-
end
|
623
|
-
end
|
624
|
-
if value.is_a?(Bignum)
|
625
|
-
return opts[:default] if opts[:default]
|
626
|
-
raise RangeNotEvaluatable, "cannot evaluate range named #{name.inspect}"
|
627
|
-
end
|
628
|
-
return opts[:default] if (value.nil? && opts[:default])
|
629
|
-
value
|
630
|
-
end
|
631
|
-
|
632
|
-
# assigns a value to a range with given name
|
633
|
-
# @param [String] name the range name
|
634
|
-
# @param [Variant] value the assigned value
|
635
|
-
# @param [Hash] opts :color [FixNum] the color when setting the contents
|
636
|
-
def set_nameval(name,value, opts = {:color => 0})
|
637
|
-
begin
|
638
|
-
cell = name_object(name).RefersToRange
|
639
|
-
cell.Interior.ColorIndex = opts[:color]
|
640
|
-
cell.Value = value
|
641
|
-
rescue WIN32OLERuntimeError
|
642
|
-
raise RangeNotEvaluatable, "cannot assign value to range named #{name.inspect}"
|
643
|
-
end
|
644
|
-
end
|
645
|
-
|
646
|
-
private
|
647
|
-
|
648
|
-
def name_object(name)
|
649
|
-
begin
|
650
|
-
self.Parent.Names.Item(name)
|
651
|
-
rescue WIN32OLERuntimeError
|
652
|
-
begin
|
653
|
-
self.Names.Item(name)
|
654
|
-
rescue WIN32OLERuntimeError
|
655
|
-
raise NameNotFound, "name #{name.inspect}"
|
656
|
-
end
|
657
|
-
end
|
658
|
-
end
|
659
|
-
|
660
|
-
public
|
661
|
-
|
662
|
-
# returns the contents of a range with a locally defined name
|
663
|
-
# evaluates the formula if the contents is a formula
|
664
|
-
# if no contents could be returned, then return default value, if provided, raise error otherwise
|
665
|
-
# @param [String] name the range name
|
666
|
-
# @param [Hash] opts the options
|
667
|
-
# @option opts [Symbol] :default the default value that is provided if no contents could be returned
|
668
|
-
# @return [Variant] the contents of a range with given name
|
669
|
-
def rangeval(name, opts = {:default => nil})
|
670
|
-
begin
|
671
|
-
range = self.Range(name)
|
672
|
-
rescue WIN32OLERuntimeError
|
673
|
-
return opts[:default] if opts[:default]
|
674
|
-
raise NameNotFound, "cannot find name #{name.inspect}"
|
675
|
-
end
|
676
|
-
begin
|
677
|
-
value = range.Value
|
678
|
-
rescue WIN32OLERuntimeError
|
679
|
-
return opts[:default] if opts[:default]
|
680
|
-
raise RangeNotEvaluatable, "cannot determine value of range named #{name.inspect}"
|
681
|
-
end
|
682
|
-
return opts[:default] if (value.nil? && opts[:default])
|
683
|
-
raise RangeNotEvaluatable, "cannot evaluate range named #{name.inspect}" if value.is_a?(Bignum)
|
684
|
-
value
|
685
|
-
end
|
686
|
-
|
687
|
-
# assigns a value to a range given a locally defined name
|
688
|
-
# @param [String] name the range name
|
689
|
-
# @param [Variant] value the assigned value
|
690
|
-
# @param [Hash] opts :color [FixNum] the color when setting the contents
|
691
|
-
def set_rangeval(name,value, opts = {:color => 0})
|
692
|
-
begin
|
693
|
-
range = self.Range(name)
|
694
|
-
rescue WIN32OLERuntimeError
|
695
|
-
raise NameNotFound, "cannot find name #{name.inspect}"
|
696
|
-
end
|
697
|
-
begin
|
698
|
-
range.Interior.ColorIndex = opts[:color]
|
699
|
-
range.Value = value
|
700
|
-
rescue WIN32OLERuntimeError
|
701
|
-
raise RangeNotEvaluatable, "cannot assign value to range named #{name.inspect} in #{self.name}"
|
702
|
-
end
|
703
|
-
end
|
704
|
-
|
705
607
|
def to_s # :nodoc: #
|
706
608
|
"#<Excel: " + "#{hwnd}" + ("#{"not alive" unless self.alive?}") + ">"
|
707
609
|
end
|
@@ -6,52 +6,6 @@ REO_LOG_FILE = "reo.log" unless Object.const_defined?(:REO_LOG_FILE)
|
|
6
6
|
|
7
7
|
File.delete REO_LOG_FILE rescue nil
|
8
8
|
|
9
|
-
class REOCommon
|
10
|
-
|
11
|
-
def excel
|
12
|
-
raise TypeErrorREO, "receiver instance is neither an Excel nor a Book"
|
13
|
-
end
|
14
|
-
|
15
|
-
def own_methods
|
16
|
-
(self.methods - Object.methods).sort
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.tr1(text)
|
20
|
-
puts :text
|
21
|
-
end
|
22
|
-
|
23
|
-
def self.trace(text)
|
24
|
-
if LOG_TO_STDOUT
|
25
|
-
puts text
|
26
|
-
else
|
27
|
-
if REO_LOG_DIR.empty?
|
28
|
-
homes = ["HOME", "HOMEPATH"]
|
29
|
-
home = homes.find {|h| ENV[h] != nil}
|
30
|
-
reo_log_dir = ENV[home]
|
31
|
-
else
|
32
|
-
reo_log_dir = REO_LOG_DIR
|
33
|
-
end
|
34
|
-
File.open(reo_log_dir + "/" + REO_LOG_FILE,"a") do | file |
|
35
|
-
file.puts text
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def self.puts_hash(hash)
|
41
|
-
hash.each do |e|
|
42
|
-
if e[1].is_a?(Hash)
|
43
|
-
puts "#{e[0]} =>"
|
44
|
-
e[1].each do |f|
|
45
|
-
puts " #{f[0]} => #{f[1]}"
|
46
|
-
end
|
47
|
-
else
|
48
|
-
puts "#{e[0]} => #{e[1]}"
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
end
|
54
|
-
|
55
9
|
module RobustExcelOle
|
56
10
|
|
57
11
|
class REOError < RuntimeError # :nodoc: #
|
@@ -123,5 +77,163 @@ module RobustExcelOle
|
|
123
77
|
class UnexpectedError < REOError # :nodoc: #
|
124
78
|
end
|
125
79
|
|
126
|
-
|
80
|
+
class REOCommon
|
81
|
+
|
82
|
+
def excel
|
83
|
+
raise TypeErrorREO, "receiver instance is neither an Excel nor a Book"
|
84
|
+
end
|
85
|
+
|
86
|
+
def own_methods
|
87
|
+
(self.methods - Object.methods).sort
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.tr1(text)
|
91
|
+
puts :text
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.trace(text)
|
95
|
+
if LOG_TO_STDOUT
|
96
|
+
puts text
|
97
|
+
else
|
98
|
+
if REO_LOG_DIR.empty?
|
99
|
+
homes = ["HOME", "HOMEPATH"]
|
100
|
+
home = homes.find {|h| ENV[h] != nil}
|
101
|
+
reo_log_dir = ENV[home]
|
102
|
+
else
|
103
|
+
reo_log_dir = REO_LOG_DIR
|
104
|
+
end
|
105
|
+
File.open(reo_log_dir + "/" + REO_LOG_FILE,"a") do | file |
|
106
|
+
file.puts text
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.puts_hash(hash)
|
112
|
+
hash.each do |e|
|
113
|
+
if e[1].is_a?(Hash)
|
114
|
+
puts "#{e[0]} =>"
|
115
|
+
e[1].each do |f|
|
116
|
+
puts " #{f[0]} => #{f[1]}"
|
117
|
+
end
|
118
|
+
else
|
119
|
+
puts "#{e[0]} => #{e[1]}"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
class RangeOwners < REOCommon
|
127
|
+
|
128
|
+
# returns the contents of a range with given name
|
129
|
+
# evaluates formula contents of the range is a formula
|
130
|
+
# if no contents could be returned, then return default value, if provided, raise error otherwise
|
131
|
+
# Excel Bug: if a local name without a qualifier is given, then by default Excel takes the first worksheet,
|
132
|
+
# even if a different worksheet is active
|
133
|
+
# @param [String] name the name of the range
|
134
|
+
# @param [Hash] opts the options
|
135
|
+
# @option opts [Symbol] :default the default value that is provided if no contents could be returned
|
136
|
+
# @return [Variant] the contents of a range with given name
|
137
|
+
def nameval(name, opts = {:default => nil})
|
138
|
+
name_obj = name_object(name)
|
139
|
+
value = begin
|
140
|
+
name_obj.RefersToRange.Value
|
141
|
+
rescue WIN32OLERuntimeError
|
142
|
+
#begin
|
143
|
+
# self.sheet(1).Evaluate(name_obj.Name)
|
144
|
+
#rescue WIN32OLERuntimeError
|
145
|
+
return opts[:default] if opts[:default]
|
146
|
+
raise RangeNotEvaluatable, "cannot evaluate range named #{name.inspect} in #{self}"
|
147
|
+
#end
|
148
|
+
end
|
149
|
+
if value.is_a?(Bignum) #RobustExcelOle::XlErrName
|
150
|
+
return opts[:default] if opts[:default]
|
151
|
+
raise RangeNotEvaluatable, "cannot evaluate range named #{name.inspect} in #{File.basename(workbook.stored_filename).inspect rescue nil}"
|
152
|
+
end
|
153
|
+
return opts[:default] if opts[:default] && value.nil?
|
154
|
+
value
|
155
|
+
end
|
156
|
+
|
157
|
+
# sets the contents of a range
|
158
|
+
# @param [String] name the name of a range
|
159
|
+
# @param [Variant] value the contents of the range
|
160
|
+
# @param [FixNum] color the color when setting a value
|
161
|
+
# @param [Hash] opts :color [FixNum] the color when setting the contents
|
162
|
+
def set_nameval(name, value, opts = {:color => 0})
|
163
|
+
begin
|
164
|
+
cell = name_object(name).RefersToRange
|
165
|
+
cell.Interior.ColorIndex = opts[:color]
|
166
|
+
workbook.modified_cells << cell unless cell_modified?(cell) if workbook
|
167
|
+
cell.Value = value
|
168
|
+
rescue WIN32OLERuntimeError
|
169
|
+
raise RangeNotEvaluatable, "cannot assign value to range named #{name.inspect} in #{self.inspect}"
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
# returns the contents of a range with a locally defined name
|
174
|
+
# evaluates the formula if the contents is a formula
|
175
|
+
# if no contents could be returned, then return default value, if provided, raise error otherwise
|
176
|
+
# @param [String] name the name of a range
|
177
|
+
# @param [Hash] opts the options
|
178
|
+
# @option opts [Symbol] :default the default value that is provided if no contents could be returned
|
179
|
+
# @return [Variant] the contents of a range with given name
|
180
|
+
def rangeval(name, opts = {:default => nil})
|
181
|
+
begin
|
182
|
+
range = self.Range(name)
|
183
|
+
rescue WIN32OLERuntimeError
|
184
|
+
return opts[:default] if opts[:default]
|
185
|
+
raise NameNotFound, "name #{name.inspect} not in #{self.inspect}"
|
186
|
+
end
|
187
|
+
begin
|
188
|
+
value = range.Value
|
189
|
+
rescue WIN32OLERuntimeError
|
190
|
+
return opts[:default] if opts[:default]
|
191
|
+
raise RangeNotEvaluatable, "cannot determine value of range named #{name.inspect} in #{self.inspect}"
|
192
|
+
end
|
193
|
+
return opts[:default] if (value.nil? && opts[:default])
|
194
|
+
raise RangeNotEvaluatable, "cannot evaluate range named #{name.inspect}" if value.is_a?(Bignum)
|
195
|
+
value
|
196
|
+
end
|
197
|
+
|
198
|
+
# assigns a value to a range given a locally defined name
|
199
|
+
# @param [String] name the name of a range
|
200
|
+
# @param [Variant] value the assigned value
|
201
|
+
# @param [Hash] opts :color [FixNum] the color when setting the contents
|
202
|
+
def set_rangeval(name,value, opts = {:color => 0})
|
203
|
+
begin
|
204
|
+
return set_nameval(name, value, opts) if self.is_a?(Book)
|
205
|
+
range = self.Range(name)
|
206
|
+
rescue WIN32OLERuntimeError
|
207
|
+
raise NameNotFound, "name #{name.inspect} not in #{self.inspect}"
|
208
|
+
end
|
209
|
+
begin
|
210
|
+
range.Interior.ColorIndex = opts[:color]
|
211
|
+
workbook.modified_cells << range unless cell_modified?(range) if workbook
|
212
|
+
range.Value = value
|
213
|
+
rescue WIN32OLERuntimeError
|
214
|
+
raise RangeNotEvaluatable, "cannot assign value to range named #{name.inspect} in #{self.inspect}"
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
private
|
219
|
+
|
220
|
+
def name_object(name)
|
221
|
+
begin
|
222
|
+
self.Parent.Names.Item(name)
|
223
|
+
rescue WIN32OLERuntimeError
|
224
|
+
begin
|
225
|
+
self.Names.Item(name)
|
226
|
+
rescue WIN32OLERuntimeError
|
227
|
+
raise RobustExcelOle::NameNotFound, "name #{name.inspect} not in #{self.inspect}"
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
def cell_modified?(cell)
|
233
|
+
workbook.modified_cells.each{|c| return true if c.Name.Value == cell.Name.Value}
|
234
|
+
false
|
235
|
+
end
|
236
|
+
|
237
|
+
end
|
127
238
|
|
239
|
+
end
|
@@ -2,36 +2,35 @@
|
|
2
2
|
|
3
3
|
module RobustExcelOle
|
4
4
|
|
5
|
-
class Sheet <
|
6
|
-
|
5
|
+
class Sheet < RangeOwners
|
6
|
+
|
7
|
+
attr_reader :ole_worksheet
|
8
|
+
attr_reader :workbook
|
7
9
|
|
8
10
|
def initialize(win32_worksheet)
|
9
|
-
@
|
10
|
-
if @
|
11
|
-
@
|
11
|
+
@ole_worksheet = win32_worksheet
|
12
|
+
if @ole_worksheet.ProtectContents
|
13
|
+
@ole_worksheet.Unprotect
|
12
14
|
@end_row = last_row
|
13
15
|
@end_column = last_column
|
14
|
-
@
|
16
|
+
@ole_worksheet.Protect
|
15
17
|
else
|
16
18
|
@end_row = last_row
|
17
19
|
@end_column = last_column
|
18
20
|
end
|
19
|
-
|
20
|
-
|
21
|
-
def workbook
|
22
|
-
book_class.new(self.Parent)
|
21
|
+
@workbook = book_class.new(self.Parent)
|
23
22
|
end
|
24
23
|
|
25
24
|
# returns name of the sheet
|
26
25
|
def name
|
27
|
-
@
|
26
|
+
@ole_worksheet.Name
|
28
27
|
end
|
29
28
|
|
30
29
|
# name the sheet
|
31
30
|
# @param [String] new_name the new name of the sheet
|
32
31
|
def name= (new_name)
|
33
32
|
begin
|
34
|
-
@
|
33
|
+
@ole_worksheet.Name = new_name
|
35
34
|
rescue WIN32OLERuntimeError => msg
|
36
35
|
if msg.message =~ /800A03EC/
|
37
36
|
raise NameAlreadyExists, "sheet name #{new_name.inspect} already exists"
|
@@ -49,7 +48,7 @@ module RobustExcelOle
|
|
49
48
|
yx = "#{y}_#{x}"
|
50
49
|
@cells = { }
|
51
50
|
begin
|
52
|
-
@cells[yx] = RobustExcelOle::Cell.new(@
|
51
|
+
@cells[yx] = RobustExcelOle::Cell.new(@ole_worksheet.Cells.Item(y, x))
|
53
52
|
rescue
|
54
53
|
raise RangeNotEvaluatable, "cannot read cell (#{p1.inspect},#{p2.inspect})"
|
55
54
|
end
|
@@ -73,7 +72,7 @@ module RobustExcelOle
|
|
73
72
|
if p3 != :__not_provided
|
74
73
|
y, x, value = p1, p2, p3
|
75
74
|
begin
|
76
|
-
cell = @
|
75
|
+
cell = @ole_worksheet.Cells.Item(y, x)
|
77
76
|
cell.Value = value
|
78
77
|
cell.Interior.ColorIndex = 42 # aqua-marin, 4-green
|
79
78
|
rescue WIN32OLERuntimeError
|
@@ -92,104 +91,6 @@ module RobustExcelOle
|
|
92
91
|
end
|
93
92
|
end
|
94
93
|
end
|
95
|
-
|
96
|
-
# returns the contents of a range
|
97
|
-
# evaluates the formula if the contents is a formula
|
98
|
-
# if no contents could be returned, then return default value, if provided, raise error otherwise
|
99
|
-
# @param [String] name the name of a range
|
100
|
-
# @param [Hash] opts the options
|
101
|
-
# @option opts [Variant] :default default value (default: nil)
|
102
|
-
def nameval(name, opts = {:default => nil})
|
103
|
-
name_obj = name_object(name)
|
104
|
-
value = begin
|
105
|
-
name_obj.RefersToRange.Value
|
106
|
-
rescue WIN32OLERuntimeError
|
107
|
-
begin
|
108
|
-
self.Evaluate(name_obj.Name)
|
109
|
-
rescue WIN32OLERuntimeError
|
110
|
-
return opts[:default] if opts[:default]
|
111
|
-
raise RangeNotEvaluatable, "cannot evaluate range named #{name.inspect} in #{self.Name}"
|
112
|
-
end
|
113
|
-
end
|
114
|
-
if value.is_a?(Bignum) # RobustExcelOle::XlErrName
|
115
|
-
return opts[:default] if opts[:default]
|
116
|
-
raise RangeNotEvaluatable, "cannot evaluate range named #{name.inspect} in #{self.Name}"
|
117
|
-
end
|
118
|
-
return opts[:default] if (value.nil? && opts[:default])
|
119
|
-
value
|
120
|
-
end
|
121
|
-
|
122
|
-
# assigns a value to a range
|
123
|
-
# @param [String] name the name of a range
|
124
|
-
# @param [Variant] value the assigned value
|
125
|
-
# @param [Hash] opts :color [FixNum] the color when setting the contents
|
126
|
-
def set_nameval(name,value, opts = {:color => 0})
|
127
|
-
begin
|
128
|
-
cell = name_object(name).RefersToRange
|
129
|
-
cell.Interior.ColorIndex = opts[:color]
|
130
|
-
cell.Value = value
|
131
|
-
rescue WIN32OLERuntimeError
|
132
|
-
raise RangeNotEvaluatable, "cannot assign value to range named #{name.inspect} in #{self.name}"
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
private
|
137
|
-
|
138
|
-
def name_object(name)
|
139
|
-
begin
|
140
|
-
self.Parent.Names.Item(name)
|
141
|
-
rescue WIN32OLERuntimeError
|
142
|
-
begin
|
143
|
-
self.Names.Item(name)
|
144
|
-
rescue WIN32OLERuntimeError
|
145
|
-
raise NameNotFound, "name #{name.inspect} not in #{self.name}"
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
public
|
151
|
-
|
152
|
-
# returns the contents of a range with a locally defined name
|
153
|
-
# evaluates the formula if the contents is a formula
|
154
|
-
# if no contents could be returned, then return default value, if provided, raise error otherwise
|
155
|
-
# @param [String] name the name of a range
|
156
|
-
# @param [Hash] opts the options
|
157
|
-
# @option opts [Symbol] :default the default value that is provided if no contents could be returned
|
158
|
-
# @return [Variant] the contents of a range with given name
|
159
|
-
def rangeval(name, opts = {:default => nil})
|
160
|
-
begin
|
161
|
-
range = self.Range(name)
|
162
|
-
rescue WIN32OLERuntimeError
|
163
|
-
return opts[:default] if opts[:default]
|
164
|
-
raise NameNotFound, "name #{name.inspect} not in #{self.name}"
|
165
|
-
end
|
166
|
-
begin
|
167
|
-
value = range.Value
|
168
|
-
rescue WIN32OLERuntimeError
|
169
|
-
return opts[:default] if opts[:default]
|
170
|
-
raise RangeNotEvaluatable, "cannot determine value of range named #{name.inspect} in #{self.name}"
|
171
|
-
end
|
172
|
-
return opts[:default] if (value.nil? && opts[:default])
|
173
|
-
value
|
174
|
-
end
|
175
|
-
|
176
|
-
# assigns a value to a range given a locally defined name
|
177
|
-
# @param [String] name the name of a range
|
178
|
-
# @param [Variant] value the assigned value
|
179
|
-
# @param [Hash] opts :color [FixNum] the color when setting the contents
|
180
|
-
def set_rangeval(name,value, opts = {:color => 0})
|
181
|
-
begin
|
182
|
-
range = self.Range(name)
|
183
|
-
rescue WIN32OLERuntimeError
|
184
|
-
raise NameNotFound, "name #{name.inspect} not in #{self.name}"
|
185
|
-
end
|
186
|
-
begin
|
187
|
-
range.Interior.ColorIndex = opts[:color]
|
188
|
-
range.Value = value
|
189
|
-
rescue WIN32OLERuntimeError
|
190
|
-
raise RangeNotEvaluatable, "cannot assign value to range named #{name.inspect} in #{self.name}"
|
191
|
-
end
|
192
|
-
end
|
193
94
|
|
194
95
|
# assigns a name to a range (a cell) given by an address
|
195
96
|
# @param [String] name the range name
|
@@ -233,7 +134,7 @@ module RobustExcelOle
|
|
233
134
|
offset += 1
|
234
135
|
1.upto(@end_row) do |row|
|
235
136
|
next if row < offset
|
236
|
-
yield RobustExcelOle::Range.new(@
|
137
|
+
yield RobustExcelOle::Range.new(@ole_worksheet.Range(@ole_worksheet.Cells(row, 1), @ole_worksheet.Cells(row, @end_column)))
|
237
138
|
end
|
238
139
|
end
|
239
140
|
|
@@ -247,7 +148,7 @@ module RobustExcelOle
|
|
247
148
|
offset += 1
|
248
149
|
1.upto(@end_column) do |column|
|
249
150
|
next if column < offset
|
250
|
-
yield RobustExcelOle::Range.new(@
|
151
|
+
yield RobustExcelOle::Range.new(@ole_worksheet.Range(@ole_worksheet.Cells(1, column), @ole_worksheet.Cells(@end_row, column)))
|
251
152
|
end
|
252
153
|
end
|
253
154
|
|
@@ -259,12 +160,12 @@ module RobustExcelOle
|
|
259
160
|
|
260
161
|
def row_range(row, range = nil)
|
261
162
|
range ||= 1..@end_column
|
262
|
-
RobustExcelOle::Range.new(@
|
163
|
+
RobustExcelOle::Range.new(@ole_worksheet.Range(@ole_worksheet.Cells(row , range.min ), @ole_worksheet.Cells(row , range.max )))
|
263
164
|
end
|
264
165
|
|
265
166
|
def col_range(col, range = nil)
|
266
167
|
range ||= 1..@end_row
|
267
|
-
RobustExcelOle::Range.new(@
|
168
|
+
RobustExcelOle::Range.new(@ole_worksheet.Range(@ole_worksheet.Cells(range.min , col ), @ole_worksheet.Cells(range.max , col )))
|
268
169
|
end
|
269
170
|
|
270
171
|
|
@@ -281,12 +182,20 @@ module RobustExcelOle
|
|
281
182
|
self.class.book_class
|
282
183
|
end
|
283
184
|
|
284
|
-
|
185
|
+
def to_s # :nodoc: #
|
186
|
+
"#<Sheet: " + "#{"not alive " unless @workbook.alive?}" + "#{name}" + " #{File.basename(@workbook.stored_filename)} >"
|
187
|
+
end
|
188
|
+
|
189
|
+
def inspect # :nodoc: #
|
190
|
+
self.to_s
|
191
|
+
end
|
192
|
+
|
193
|
+
private
|
285
194
|
|
286
195
|
def method_missing(name, *args) # :nodoc: #
|
287
196
|
if name.to_s[0,1] =~ /[A-Z]/
|
288
197
|
begin
|
289
|
-
@
|
198
|
+
@ole_worksheet.send(name, *args)
|
290
199
|
rescue WIN32OLERuntimeError => msg
|
291
200
|
if msg.message =~ /unknown property or method/
|
292
201
|
raise VBAMethodMissingError, "unknown VBA property or method #{name.inspect}"
|
@@ -299,22 +208,19 @@ module RobustExcelOle
|
|
299
208
|
end
|
300
209
|
end
|
301
210
|
|
302
|
-
|
303
211
|
def last_row
|
304
|
-
special_last_row = @
|
305
|
-
used_last_row = @
|
212
|
+
special_last_row = @ole_worksheet.UsedRange.SpecialCells(RobustExcelOle::XlLastCell).Row
|
213
|
+
used_last_row = @ole_worksheet.UsedRange.Rows.Count
|
306
214
|
|
307
215
|
special_last_row >= used_last_row ? special_last_row : used_last_row
|
308
216
|
end
|
309
217
|
|
310
218
|
def last_column
|
311
|
-
special_last_column = @
|
312
|
-
used_last_column = @
|
219
|
+
special_last_column = @ole_worksheet.UsedRange.SpecialCells(RobustExcelOle::XlLastCell).Column
|
220
|
+
used_last_column = @ole_worksheet.UsedRange.Columns.Count
|
313
221
|
|
314
222
|
special_last_column >= used_last_column ? special_last_column : used_last_column
|
315
223
|
end
|
316
224
|
end
|
317
|
-
|
318
|
-
public
|
319
225
|
|
320
226
|
end
|
data/robust_excel_ole.gemspec
CHANGED
@@ -11,7 +11,8 @@ Gem::Specification.new do |s|
|
|
11
11
|
|
12
12
|
s.summary = "RobustExcelOle automates processing Excel files in Windows by using the win32ole library."
|
13
13
|
s.description = "RobustExcelOle automates modifying, reading and writing Excel files in Windows by using the win32ole library.
|
14
|
-
It
|
14
|
+
It is disigned to cope with several kinds of concurrency of both simultaneously running
|
15
|
+
Excel instances and simultanously happening user interactions.
|
15
16
|
RobustExcelOle deals with various cases of Excel (and user) behaviour,
|
16
17
|
supplies workarounds for some Excel bugs, and supports referenced libraries."
|
17
18
|
|
data/spec/book_spec.rb
CHANGED
@@ -1064,17 +1064,17 @@ describe Book do
|
|
1064
1064
|
@book1.nameval("new").should == "bar"
|
1065
1065
|
end
|
1066
1066
|
|
1067
|
-
it "should evaluate a formula" do
|
1068
|
-
|
1069
|
-
end
|
1067
|
+
#it "should evaluate a formula" do
|
1068
|
+
# @book1.nameval("named_formula").should == 4
|
1069
|
+
#end
|
1070
1070
|
|
1071
|
-
it "should evaluate a formula via []" do
|
1072
|
-
|
1073
|
-
end
|
1071
|
+
#it "should evaluate a formula via []" do
|
1072
|
+
# @book1["named_formula"].should == 4
|
1073
|
+
#end
|
1074
1074
|
|
1075
|
-
it "should return default value if name not defined" do
|
1076
|
-
|
1077
|
-
end
|
1075
|
+
#it "should return default value if name not defined" do
|
1076
|
+
# @book1.nameval("foo", :default => 2).should == 2
|
1077
|
+
#end
|
1078
1078
|
|
1079
1079
|
end
|
1080
1080
|
|
@@ -646,33 +646,33 @@ describe Book do
|
|
646
646
|
@book1.nameval("new").should == "bar"
|
647
647
|
end
|
648
648
|
|
649
|
-
it "should evaluate a formula" do
|
650
|
-
|
651
|
-
end
|
649
|
+
#it "should evaluate a formula" do
|
650
|
+
# @book1.nameval("named_formula").should == 4
|
651
|
+
#end
|
652
652
|
|
653
|
-
it "should evaluate a formula via []" do
|
654
|
-
|
655
|
-
end
|
653
|
+
#it "should evaluate a formula via []" do
|
654
|
+
# @book1["named_formula"].should == 4
|
655
|
+
#end
|
656
656
|
|
657
657
|
it "should raise an error if name not defined" do
|
658
658
|
expect {
|
659
659
|
@book1.nameval("foo")
|
660
|
-
}.to raise_error(NameNotFound, /name "foo" not in
|
660
|
+
}.to raise_error(NameNotFound, /name "foo" not in #<Book: another_workbook/)
|
661
661
|
expect {
|
662
662
|
@book1.set_nameval("foo","bar")
|
663
|
-
}.to raise_error(NameNotFound, /name "foo" not in
|
663
|
+
}.to raise_error(NameNotFound, /name "foo" not in #<Book: another_workbook/)
|
664
664
|
expect {
|
665
665
|
@book1["foo"] = "bar"
|
666
|
-
}.to raise_error(NameNotFound, /name "foo" not in
|
666
|
+
}.to raise_error(NameNotFound, /name "foo" not in #<Book: another_workbook/)
|
667
667
|
end
|
668
668
|
|
669
669
|
it "should raise an error if name was defined but contents is calcuated" do
|
670
670
|
expect {
|
671
671
|
@book1.set_nameval("named_formula","bar")
|
672
|
-
}.to raise_error(RangeNotEvaluatable, /cannot assign value to range named "named_formula" in
|
672
|
+
}.to raise_error(RangeNotEvaluatable, /cannot assign value to range named "named_formula" in #<Book: another_workbook/)
|
673
673
|
expect {
|
674
674
|
@book1["named_formula"] = "bar"
|
675
|
-
}.to raise_error(RangeNotEvaluatable, /cannot assign value to range named "named_formula" in
|
675
|
+
}.to raise_error(RangeNotEvaluatable, /cannot assign value to range named "named_formula" in #<Book: another_workbook/)
|
676
676
|
end
|
677
677
|
|
678
678
|
# Excel Bug: for local names without uqifier: takes the first sheet as default even if another sheet is activated
|
Binary file
|
data/spec/excel_spec.rb
CHANGED
@@ -1722,10 +1722,10 @@ module RobustExcelOle
|
|
1722
1722
|
@excel1["firstcell"].should == "foo"
|
1723
1723
|
end
|
1724
1724
|
|
1725
|
-
it "should evaluate a formula" do
|
1726
|
-
|
1727
|
-
|
1728
|
-
end
|
1725
|
+
#it "should evaluate a formula" do
|
1726
|
+
# @excel1.nameval("named_formula").should == 4
|
1727
|
+
# @excel1["named_formula"].should == 4
|
1728
|
+
#end
|
1729
1729
|
|
1730
1730
|
it "should raise an error if name not defined" do
|
1731
1731
|
expect {
|
@@ -1791,14 +1791,14 @@ module RobustExcelOle
|
|
1791
1791
|
it "should raise an error if name not defined for the sheet" do
|
1792
1792
|
expect {
|
1793
1793
|
@excel1.rangeval("foo")
|
1794
|
-
}.to raise_error(NameNotFound, /
|
1794
|
+
}.to raise_error(NameNotFound, /name "foo" not in/)
|
1795
1795
|
expect {
|
1796
1796
|
@excel1.rangeval("named_formula")
|
1797
|
-
}.to raise_error(NameNotFound, /
|
1797
|
+
}.to raise_error(NameNotFound, /name "named_formula" not in/)
|
1798
1798
|
expect {
|
1799
1799
|
excel2 = Excel.create
|
1800
1800
|
excel2.rangeval("one")
|
1801
|
-
}.to raise_error(NameNotFound, /
|
1801
|
+
}.to raise_error(NameNotFound, /name "one" not in/)
|
1802
1802
|
end
|
1803
1803
|
|
1804
1804
|
it "should set a range to a value" do
|
@@ -1810,7 +1810,7 @@ module RobustExcelOle
|
|
1810
1810
|
it "should raise an error if name cannot be evaluated" do
|
1811
1811
|
expect{
|
1812
1812
|
@excel1.set_nameval("foo", 1)
|
1813
|
-
}.to raise_error(NameNotFound, /
|
1813
|
+
}.to raise_error(NameNotFound, /name "foo" not in/)
|
1814
1814
|
end
|
1815
1815
|
|
1816
1816
|
end
|
data/spec/range_spec.rb
CHANGED
@@ -16,7 +16,7 @@ describe RobustExcelOle::Range do
|
|
16
16
|
@dir = create_tmpdir
|
17
17
|
@book = Book.open(@dir + '/workbook.xls', :force_excel => :new)
|
18
18
|
@sheet = @book.sheet(2)
|
19
|
-
@range = RobustExcelOle::Range.new(@sheet.
|
19
|
+
@range = RobustExcelOle::Range.new(@sheet.ole_worksheet.UsedRange.Rows(1))
|
20
20
|
end
|
21
21
|
|
22
22
|
after do
|
@@ -53,7 +53,7 @@ describe RobustExcelOle::Range do
|
|
53
53
|
context "when instance is column range" do
|
54
54
|
before do
|
55
55
|
@sheet = @book.sheet(1)
|
56
|
-
@range = RobustExcelOle::Range.new(@sheet.
|
56
|
+
@range = RobustExcelOle::Range.new(@sheet.ole_worksheet.UsedRange.Columns(1))
|
57
57
|
end
|
58
58
|
it { @range.values.should eq ['foo', 'foo', 'matz'] }
|
59
59
|
end
|
data/spec/sheet_spec.rb
CHANGED
@@ -443,18 +443,18 @@ describe Sheet do
|
|
443
443
|
@sheet1["another"].should == nil
|
444
444
|
end
|
445
445
|
|
446
|
-
it "should evaluate named formula" do
|
447
|
-
|
448
|
-
end
|
446
|
+
#it "should evaluate named formula" do
|
447
|
+
# @sheet1["named_formula"].should == 4
|
448
|
+
#end
|
449
449
|
|
450
|
-
it "should evaluate a formula" do
|
451
|
-
|
452
|
-
end
|
450
|
+
#it "should evaluate a formula" do
|
451
|
+
# @sheet1["another_formula"].should == 5
|
452
|
+
#end
|
453
453
|
|
454
454
|
it "should raise an error if name not defined" do
|
455
455
|
expect {
|
456
456
|
@sheet1["foo"]
|
457
|
-
}.to raise_error(NameNotFound, /name "foo" not in Sheet1/)
|
457
|
+
}.to raise_error(NameNotFound, /name "foo" not in #<Sheet: Sheet1/)
|
458
458
|
end
|
459
459
|
|
460
460
|
it "should set a range to a value" do
|
@@ -468,7 +468,7 @@ describe Sheet do
|
|
468
468
|
it "should raise an error if name cannot be evaluated" do
|
469
469
|
expect{
|
470
470
|
@sheet1["foo"] = 1
|
471
|
-
}.to raise_error(NameNotFound, /name "foo" not in Sheet1/)
|
471
|
+
}.to raise_error(NameNotFound, /name "foo" not in #<Sheet: Sheet1/)
|
472
472
|
end
|
473
473
|
end
|
474
474
|
|
@@ -487,20 +487,20 @@ describe Sheet do
|
|
487
487
|
@sheet1.nameval("firstcell").should == "foo"
|
488
488
|
end
|
489
489
|
|
490
|
-
it "should evaluate a formula" do
|
491
|
-
|
492
|
-
end
|
490
|
+
#it "should evaluate a formula" do
|
491
|
+
# @sheet1.nameval("another_formula").should == 5
|
492
|
+
#end
|
493
493
|
|
494
494
|
it "should raise an error if name not defined" do
|
495
495
|
expect {
|
496
496
|
@sheet1.nameval("foo")
|
497
|
-
}.to raise_error(NameNotFound, /name "foo" not in
|
497
|
+
}.to raise_error(NameNotFound, /name "foo" not in/)
|
498
498
|
end
|
499
499
|
|
500
500
|
it "should raise an error of coordinates are given instead of a defined name" do
|
501
501
|
expect {
|
502
502
|
@sheet1.nameval("A1")
|
503
|
-
}.to raise_error(NameNotFound, /name "A1" not in Sheet1/)
|
503
|
+
}.to raise_error(NameNotFound, /name "A1" not in #<Sheet: Sheet1/)
|
504
504
|
end
|
505
505
|
|
506
506
|
it "should return default value for a range with empty contents" do
|
@@ -518,7 +518,7 @@ describe Sheet do
|
|
518
518
|
it "should raise an error if name cannot be evaluated" do
|
519
519
|
expect{
|
520
520
|
@sheet1.set_nameval("foo", 1)
|
521
|
-
}.to raise_error(NameNotFound, /name "foo" not in Sheet1/)
|
521
|
+
}.to raise_error(NameNotFound, /name "foo" not in #<Sheet: Sheet1/)
|
522
522
|
end
|
523
523
|
end
|
524
524
|
|
@@ -560,13 +560,13 @@ describe Sheet do
|
|
560
560
|
it "should raise an error if name not defined for the sheet" do
|
561
561
|
expect {
|
562
562
|
@sheet1.rangeval("foo")
|
563
|
-
}.to raise_error(NameNotFound, /name "foo" not in Sheet1/)
|
563
|
+
}.to raise_error(NameNotFound, /name "foo" not in #<Sheet: Sheet1/)
|
564
564
|
expect {
|
565
565
|
@sheet1.rangeval("named_formula")
|
566
|
-
}.to raise_error(NameNotFound, /name "named_formula" not in Sheet1/)
|
566
|
+
}.to raise_error(NameNotFound, /name "named_formula" not in #<Sheet: Sheet1/)
|
567
567
|
expect {
|
568
568
|
@sheet2.rangeval("firstcell")
|
569
|
-
}.to raise_error(NameNotFound, /name "firstcell" not in Sheet2/)
|
569
|
+
}.to raise_error(NameNotFound, /name "firstcell" not in #<Sheet: Sheet2/)
|
570
570
|
end
|
571
571
|
|
572
572
|
it "should set a range to a value" do
|
@@ -580,7 +580,7 @@ describe Sheet do
|
|
580
580
|
it "should raise an error if name cannot be evaluated" do
|
581
581
|
expect{
|
582
582
|
@sheet1.set_nameval("foo", 1)
|
583
|
-
}.to raise_error(NameNotFound, /name "foo" not in Sheet1/)
|
583
|
+
}.to raise_error(NameNotFound, /name "foo" not in #<Sheet: Sheet1/)
|
584
584
|
end
|
585
585
|
|
586
586
|
end
|
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.1.
|
4
|
+
version: 1.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- traths
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-05-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -26,7 +26,8 @@ dependencies:
|
|
26
26
|
version: 2.6.0
|
27
27
|
description: |-
|
28
28
|
RobustExcelOle automates modifying, reading and writing Excel files in Windows by using the win32ole library.
|
29
|
-
It
|
29
|
+
It is disigned to cope with several kinds of concurrency of both simultaneously running
|
30
|
+
Excel instances and simultanously happening user interactions.
|
30
31
|
RobustExcelOle deals with various cases of Excel (and user) behaviour,
|
31
32
|
supplies workarounds for some Excel bugs, and supports referenced libraries.
|
32
33
|
email:
|