robust_excel_ole 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +8 -0
- data/Gemfile +4 -0
- data/Guardfile +10 -0
- data/LICENSE +7 -0
- data/README.rdoc +148 -0
- data/Rakefile +9 -0
- data/lib/robust_excel_ole.rb +13 -0
- data/lib/robust_excel_ole/book.rb +310 -0
- data/lib/robust_excel_ole/cell.rb +19 -0
- data/lib/robust_excel_ole/cygwin.rb +40 -0
- data/lib/robust_excel_ole/excel_app.rb +182 -0
- data/lib/robust_excel_ole/range.rb +38 -0
- data/lib/robust_excel_ole/robustexcelole.sublime-project +8 -0
- data/lib/robust_excel_ole/robustexcelole.sublime-workspace +347 -0
- data/lib/robust_excel_ole/sheet.rb +103 -0
- data/lib/robust_excel_ole/sp +3 -0
- data/lib/robust_excel_ole/version.rb +3 -0
- data/lib/spec_helper.rb +35 -0
- data/robust_excel_ole.gemspec +32 -0
- data/robust_excel_ole_example.rb +29 -0
- data/spec/book_spec.rb +867 -0
- data/spec/cell_spec.rb +66 -0
- data/spec/cygwin_spec.rb +42 -0
- data/spec/data/book_with_blank.xls +0 -0
- data/spec/data/different_simple.xls +0 -0
- data/spec/data/merge_cells.xls +0 -0
- data/spec/data/more_data/simple.xls +0 -0
- data/spec/data/protected_sheet.xls +0 -0
- data/spec/data/simple.xls +0 -0
- data/spec/data/simple.xlsm +0 -0
- data/spec/data/simple.xlsx +0 -0
- data/spec/excel_app_spec.rb +168 -0
- data/spec/helpers/key_sender.rb +68 -0
- data/spec/range_spec.rb +120 -0
- data/spec/sheet_spec.rb +355 -0
- data/spec/spec_helper.rb +35 -0
- data/version.rb +3 -0
- metadata +203 -0
data/spec/cell_spec.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require File.join(File.dirname(__FILE__), './spec_helper')
|
3
|
+
|
4
|
+
describe RobustExcelOle::Cell do
|
5
|
+
before do
|
6
|
+
@dir = create_tmpdir
|
7
|
+
end
|
8
|
+
|
9
|
+
after do
|
10
|
+
rm_tmp(@dir)
|
11
|
+
end
|
12
|
+
|
13
|
+
context "open simple.xls" do
|
14
|
+
before do
|
15
|
+
@book = RobustExcelOle::Book.open(@dir + '/simple.xls')
|
16
|
+
@sheet = @book[1]
|
17
|
+
@cell = @sheet[0, 0]
|
18
|
+
end
|
19
|
+
|
20
|
+
after do
|
21
|
+
@book.close
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "#value" do
|
25
|
+
it "get cell's value" do
|
26
|
+
@cell.value.should eq 'simple'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#value=" do
|
31
|
+
it "change cell data to 'fooooo'" do
|
32
|
+
@cell.value = 'fooooo'
|
33
|
+
@cell.value.should eq 'fooooo'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#method_missing" do
|
38
|
+
context "unknown method" do
|
39
|
+
it { expect { @cell.hogehogefoo }.to raise_error }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
context "open merge_cells.xls" do
|
46
|
+
before do
|
47
|
+
@book = RobustExcelOle::Book.open(@dir + '/merge_cells.xls')
|
48
|
+
@sheet = @book[0]
|
49
|
+
end
|
50
|
+
|
51
|
+
after do
|
52
|
+
@book.close
|
53
|
+
end
|
54
|
+
|
55
|
+
it "merged cell get same value" do
|
56
|
+
@sheet[0, 0].value.should be_nil
|
57
|
+
@sheet[1, 0].value.should eq 'first merged'
|
58
|
+
end
|
59
|
+
|
60
|
+
it "set merged cell" do
|
61
|
+
@sheet[1, 0].value = "set merge cell"
|
62
|
+
@sheet[1, 0].value.should eq "set merge cell"
|
63
|
+
@sheet[1, 1].value.should eq "set merge cell"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/spec/cygwin_spec.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require File.join(File.dirname(__FILE__), './spec_helper')
|
3
|
+
|
4
|
+
describe "on cygwin", :if => RUBY_PLATFORM =~ /cygwin/ do
|
5
|
+
describe ".cygpath" do
|
6
|
+
context "cygwin path is '/cygdrive/c/Users'" do
|
7
|
+
context "with '-w' options" do
|
8
|
+
it { RobustExcelOle::Cygwin.cygpath('-w', '/cygdrive/c/Users').should eq 'C:\\Users' }
|
9
|
+
end
|
10
|
+
|
11
|
+
context "with '-wa' options" do
|
12
|
+
it { RobustExcelOle::Cygwin.cygpath('-wa', '/cygdrive/c/Users').should eq 'C:\\Users' }
|
13
|
+
end
|
14
|
+
|
15
|
+
context "with '-ws' options" do
|
16
|
+
it { RobustExcelOle::Cygwin.cygpath('-ws', '/cygdrive/c/Users').should eq 'C:\\Users' }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context "windows path is 'C:\\Users'" do
|
21
|
+
context "with '-u option" do
|
22
|
+
it { RobustExcelOle::Cygwin.cygpath('-u', 'C:\\Users').should eq '/cygdrive/c/Users'}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context "cygwin path is './'" do
|
27
|
+
context "with '-u' options" do
|
28
|
+
it { RobustExcelOle::Cygwin.cygpath('-u', './').should eq './' }
|
29
|
+
end
|
30
|
+
|
31
|
+
context "with '-ua' options" do
|
32
|
+
it { RobustExcelOle::Cygwin.cygpath('-ua', './').should eq File.expand_path('./') + '/' }
|
33
|
+
end
|
34
|
+
|
35
|
+
context "with '-us' options" do
|
36
|
+
it { RobustExcelOle::Cygwin.cygpath('-us', './').should eq './' }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,168 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), './spec_helper')
|
4
|
+
|
5
|
+
$VERBOSE = nil
|
6
|
+
|
7
|
+
module RobustExcelOle
|
8
|
+
|
9
|
+
describe ExcelApp do
|
10
|
+
before do
|
11
|
+
@dir = create_tmpdir
|
12
|
+
@simple_file = @dir + '/simple.xls'
|
13
|
+
end
|
14
|
+
|
15
|
+
after do
|
16
|
+
rm_tmp(@dir)
|
17
|
+
end
|
18
|
+
|
19
|
+
save_path = "C:" + "/" + "simple_save.xls"
|
20
|
+
|
21
|
+
context "app creation" do
|
22
|
+
after do
|
23
|
+
ExcelApp.close_all
|
24
|
+
end
|
25
|
+
|
26
|
+
def creation_ok?
|
27
|
+
@app.alive?.should == true
|
28
|
+
@app.Visible.should == false
|
29
|
+
@app.DisplayAlerts.should == false
|
30
|
+
@app.Name.should == "Microsoft Excel"
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should work with 'new' " do
|
34
|
+
@app = ExcelApp.new
|
35
|
+
creation_ok?
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should work with 'new' " do
|
39
|
+
@app = ExcelApp.new(:reuse => false)
|
40
|
+
creation_ok?
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should work with 'create' " do
|
44
|
+
@app = ExcelApp.create
|
45
|
+
creation_ok?
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
|
52
|
+
context "with existing app" do
|
53
|
+
|
54
|
+
before do
|
55
|
+
ExcelApp.close_all
|
56
|
+
@app1 = ExcelApp.create
|
57
|
+
end
|
58
|
+
|
59
|
+
after do
|
60
|
+
ExcelApp.close_all
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should create different app" do
|
64
|
+
app2 = ExcelApp.create
|
65
|
+
#puts "@app1 #{@app1.Hwnd}"
|
66
|
+
#puts "app2 #{app2.Hwnd}"
|
67
|
+
app2.Hwnd.should_not == @app1.Hwnd
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should reuse existing app" do
|
71
|
+
app2 = ExcelApp.reuse_if_possible
|
72
|
+
#puts "@app1 #{@app1.Hwnd}"
|
73
|
+
#puts "app2 #{app2.Hwnd}"
|
74
|
+
app2.Hwnd.should == @app1.Hwnd
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should reuse existing app with default options for 'new'" do
|
78
|
+
app2 = ExcelApp.new
|
79
|
+
#puts "@app1 #{@app1.Hwnd}"
|
80
|
+
#puts "app2 #{app2.Hwnd}"
|
81
|
+
app2.Hwnd.should == @app1.Hwnd
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
context "close excel instances" do
|
87
|
+
def direct_excel_creation_helper
|
88
|
+
expect { WIN32OLE.connect("Excel.Application") }.to raise_error
|
89
|
+
sleep 0.1
|
90
|
+
exl1 = WIN32OLE.new("Excel.Application")
|
91
|
+
exl1.Workbooks.Add
|
92
|
+
exl2 = WIN32OLE.new("Excel.Application")
|
93
|
+
exl2.Workbooks.Add
|
94
|
+
expect { WIN32OLE.connect("Excel.Application") }.to_not raise_error
|
95
|
+
end
|
96
|
+
|
97
|
+
it "simple file with default" do
|
98
|
+
RobustExcelOle::ExcelApp.close_all
|
99
|
+
direct_excel_creation_helper
|
100
|
+
RobustExcelOle::ExcelApp.close_all
|
101
|
+
sleep 0.1
|
102
|
+
expect { WIN32OLE.connect("Excel.Application") }.to raise_error
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe "==" do
|
107
|
+
before do
|
108
|
+
ExcelApp.close_all
|
109
|
+
@app1 = ExcelApp.create
|
110
|
+
end
|
111
|
+
|
112
|
+
after do
|
113
|
+
ExcelApp.close_all
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should be true with two identical excel applications" do
|
117
|
+
app2 = ExcelApp.reuse_if_possible
|
118
|
+
app2.should == @app1
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should be false with two different excel applications" do
|
122
|
+
app2 = ExcelApp.create
|
123
|
+
app2.should_not == @app1
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should be false with non-ExcelApp objects" do
|
127
|
+
@app1.should_not == "hallo"
|
128
|
+
@app1.should_not == 7
|
129
|
+
@app1.should_not == nil
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
context "with Visible and DisplayAlerts" do
|
135
|
+
|
136
|
+
before do
|
137
|
+
ExcelApp.close_all
|
138
|
+
end
|
139
|
+
|
140
|
+
after (:each) do
|
141
|
+
ExcelApp.close_all
|
142
|
+
end
|
143
|
+
|
144
|
+
it "should be visible" do
|
145
|
+
app = ExcelApp.new(:visible => true)
|
146
|
+
app.Visible.should == true
|
147
|
+
app.DisplayAlerts.should == false
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should displayalerts" do
|
151
|
+
app = ExcelApp.new(:displayalerts => true)
|
152
|
+
app.DisplayAlerts.should == true
|
153
|
+
app.Visible.should == false
|
154
|
+
end
|
155
|
+
|
156
|
+
it "should visible and displayalerts" do
|
157
|
+
app = ExcelApp.new(:visible => true)
|
158
|
+
app.Visible.should == true
|
159
|
+
app.DisplayAlerts.should == false
|
160
|
+
app2 = ExcelApp.new(:displayalerts => true)
|
161
|
+
app2.Visible.should == true
|
162
|
+
app2.DisplayAlerts.should == true
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
168
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
|
2
|
+
require 'win32ole'
|
3
|
+
|
4
|
+
class KeySender
|
5
|
+
def initialize(window_name, options={})
|
6
|
+
@window_name = window_name
|
7
|
+
@wsh = WIN32OLE.new('Wscript.Shell')
|
8
|
+
@initial_wait = options[:initial_wait] || 0.2
|
9
|
+
end
|
10
|
+
|
11
|
+
# options:
|
12
|
+
# :timeout, :initial_wait, :if_target_missing, :silent,
|
13
|
+
def send(key_seq, options={})
|
14
|
+
initial_wait = options[:initial_wait] || @initial_wait
|
15
|
+
timeout = options[:timeout] || 5
|
16
|
+
start_time = Time.now
|
17
|
+
sleep initial_wait
|
18
|
+
|
19
|
+
ready_to_send = if @window_name
|
20
|
+
loop do
|
21
|
+
akt = @wsh.AppActivate(@window_name)
|
22
|
+
break akt if akt
|
23
|
+
break false if Time.now - start_time > timeout
|
24
|
+
sleep 0.3
|
25
|
+
print "-" unless options[:silent]
|
26
|
+
end
|
27
|
+
else
|
28
|
+
true # Keine Window_name, immer senden'
|
29
|
+
end
|
30
|
+
|
31
|
+
if ready_to_send
|
32
|
+
@wsh.SendKeys(key_seq) if key_seq
|
33
|
+
yield if block_given?
|
34
|
+
else
|
35
|
+
else_aktion = options[:if_target_missing]
|
36
|
+
case else_aktion
|
37
|
+
when Proc
|
38
|
+
else_aktion.call
|
39
|
+
when nil
|
40
|
+
else
|
41
|
+
raise else_aktion
|
42
|
+
end
|
43
|
+
end
|
44
|
+
ready_to_send
|
45
|
+
end
|
46
|
+
|
47
|
+
def wait_for_window(windowname, timeout=30)
|
48
|
+
break_time = Time.now + timeout
|
49
|
+
loop do
|
50
|
+
windowname.each do |window_name|
|
51
|
+
ready_to_send = @wsh.AppActivate(window_name)
|
52
|
+
return window_name if ready_to_send
|
53
|
+
end
|
54
|
+
break false if Time.now > break_time
|
55
|
+
|
56
|
+
print " (noch #{'%.1f'%(break_time - Time.now)}s) " unless options[:silent]
|
57
|
+
sleep 0.813
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
if __FILE__ == $0
|
63
|
+
key_sender = KeySender.new(ARGV[1])
|
64
|
+
while not $stdin.eof? do
|
65
|
+
key_sequence = $stdin.gets.chomp
|
66
|
+
key_sender.send key_sequence
|
67
|
+
end
|
68
|
+
end
|
data/spec/range_spec.rb
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require File.join(File.dirname(__FILE__), './spec_helper')
|
3
|
+
|
4
|
+
describe RobustExcelOle::Range do
|
5
|
+
before do
|
6
|
+
@dir = create_tmpdir
|
7
|
+
@book = RobustExcelOle::Book.open(@dir + '/simple.xls')
|
8
|
+
@sheet = @book[1]
|
9
|
+
@range = RobustExcelOle::Range.new(@sheet.sheet.UsedRange.Rows(1))
|
10
|
+
end
|
11
|
+
|
12
|
+
after do
|
13
|
+
@book.close
|
14
|
+
rm_tmp(@dir)
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "#each" do
|
18
|
+
it "items is RobustExcelOle::Cell" do
|
19
|
+
@range.each do |cell|
|
20
|
+
cell.should be_kind_of RobustExcelOle::Cell
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#values" do
|
26
|
+
context "with (0..2)" do
|
27
|
+
it { @range.values(0..2).should eq ['simple', 'file', 'sheet2'] }
|
28
|
+
end
|
29
|
+
|
30
|
+
context "with (1..2)" do
|
31
|
+
it { @range.values(1..2).should eq ['file', 'sheet2'] }
|
32
|
+
end
|
33
|
+
|
34
|
+
context "with (2..2)" do
|
35
|
+
it { @range.values(2..2).should eq ['sheet2'] }
|
36
|
+
end
|
37
|
+
|
38
|
+
context "with no arguments" do
|
39
|
+
it { @range.values.should eq ['simple', 'file', 'sheet2'] }
|
40
|
+
end
|
41
|
+
|
42
|
+
context "when instance is column range" do
|
43
|
+
before do
|
44
|
+
@sheet = @book[0]
|
45
|
+
@range = RobustExcelOle::Range.new(@sheet.sheet.UsedRange.Columns(1))
|
46
|
+
end
|
47
|
+
it { @range.values.should eq ['simple', 'foo', 'matz'] }
|
48
|
+
end
|
49
|
+
|
50
|
+
context "read 'merge_cells.xls'" do
|
51
|
+
before do
|
52
|
+
@merge_cells_book = RobustExcelOle::Book.open("#{@dir}/merge_cells.xls")
|
53
|
+
@merge_cells_sheet = @merge_cells_book[0]
|
54
|
+
end
|
55
|
+
|
56
|
+
after do
|
57
|
+
@merge_cells_book.close
|
58
|
+
end
|
59
|
+
|
60
|
+
context "only merged_cell" do
|
61
|
+
before do
|
62
|
+
@only_merged_range = @merge_cells_sheet.row_range(3)
|
63
|
+
end
|
64
|
+
|
65
|
+
context "without argument" do
|
66
|
+
it { @only_merged_range.values.should eq ['merged', 'merged', 'merged', 'merged'] }
|
67
|
+
end
|
68
|
+
|
69
|
+
context "with (1..2)" do
|
70
|
+
it { @only_merged_range.values(1..2).should eq ['merged', 'merged'] }
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
context "mix merged cell and no merge cell" do
|
76
|
+
before do
|
77
|
+
@mix_merged_no_merged_range = @merge_cells_sheet.row_range(1)
|
78
|
+
end
|
79
|
+
|
80
|
+
context "without argument" do
|
81
|
+
it { @mix_merged_no_merged_range.values.should eq ['first merged', 'first merged', 'first merged', nil] }
|
82
|
+
end
|
83
|
+
|
84
|
+
context "with (2..3)" do
|
85
|
+
it { @mix_merged_no_merged_range.values(2..3).should eq ['first merged', nil] }
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe "#[]" do
|
93
|
+
context "access [0]" do
|
94
|
+
it { @range[0].should be_kind_of RobustExcelOle::Cell }
|
95
|
+
it { @range[0].value.should eq 'simple' }
|
96
|
+
end
|
97
|
+
|
98
|
+
context "access [2]" do
|
99
|
+
it { @range[2].value.should eq 'sheet2' }
|
100
|
+
end
|
101
|
+
|
102
|
+
context "access [0] and [1] and [2]" do
|
103
|
+
it "should get every values" do
|
104
|
+
@range[0].value.should eq 'simple'
|
105
|
+
@range[1].value.should eq 'file'
|
106
|
+
@range[2].value.should eq 'sheet2'
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe "#method_missing" do
|
112
|
+
it "can access COM method" do
|
113
|
+
@range.Range(@range.Cells.Item(1), @range.Cells.Item(3)).value.should eq [@range.values(0..2)]
|
114
|
+
end
|
115
|
+
|
116
|
+
context "unknown method" do
|
117
|
+
it { expect { @range.hogehogefoo}.to raise_error }
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|