robust_excel_ole 1.16 → 1.17

Sign up to get free protection for your applications and to get access to all the features.
data/spec/general_spec.rb CHANGED
@@ -60,9 +60,23 @@ module RobustExcelOle
60
60
  end
61
61
 
62
62
  it "should type-lift a range" do
63
- range = @book1.sheet(1).range([1,1]).ole_range.to_reo
63
+ range = @book1.sheet(1).range([1..2,1]).ole_range.to_reo
64
64
  range.should be_kind_of Range
65
- range.Value.should == "foo"
65
+ range.Value.should == [["foo"],["foo"]]
66
+ end
67
+
68
+ it "should type-lift a cell" do
69
+ cell = @book1.sheet(1).range([1,1]).ole_range.to_reo
70
+ #cell = @book1.sheet(1)[1,1].ole_cell.to_reo
71
+ cell.should be_kind_of Cell
72
+ cell.Value.should == "foo"
73
+ end
74
+
75
+ it "should not do anything with a REO object" do
76
+ @book1.to_reo.should == @book1
77
+ @book1.sheet(1).to_reo.should == @book1.sheet(1)
78
+ @book1.excel.to_reo.should == @book1.excel
79
+ @book1.sheet(1).range([1,1]).to_reo.should == @book1.sheet(1).range([1,1])
66
80
  end
67
81
 
68
82
  end
@@ -222,22 +236,5 @@ module RobustExcelOle
222
236
  end
223
237
  end
224
238
 
225
- describe "Object methods" do
226
-
227
- before do
228
- @book = Workbook.open(@simple_file)
229
- @sheet = @book.sheet(1)
230
- end
231
-
232
- before do
233
- @book.close
234
- end
235
-
236
- it "should raise an error when asking excel of a sheet" do
237
- expect{
238
- @sheet.excel
239
- }.to raise_error(TypeREOError, "receiver instance is neither an Excel nor a Workbook")
240
- end
241
- end
242
239
  end
243
240
  end
data/spec/range_spec.rb CHANGED
@@ -335,7 +335,7 @@ describe RobustExcelOle::Range do
335
335
  #end
336
336
 
337
337
  context "unknown method" do
338
- it { expect { @range.hogehogefoo}.to raise_error }
338
+ it { expect { @range.hogehogefoo}.to raise_error(NoMethodError) }
339
339
  end
340
340
  end
341
341
  end
@@ -625,16 +625,16 @@ describe Workbook do
625
625
  old_cell_value = sheet[1,1].Value
626
626
  sheet[1,1] = sheet[1,1].Value == "foo" ? "bar" : "foo"
627
627
  book.Saved.should be false
628
- new_book = Workbook.open(@simple_file1, :read_only => false, :if_unsaved => :accept)
628
+ new_book = Workbook.open(@simple_file1, :read_only => false, :if_unsaved => :forget)
629
629
  new_book.ReadOnly.should be false
630
630
  new_book.should be_alive
631
- book.should be_alive
632
- new_book.should == book
631
+ book.should_not be_alive
633
632
  new_sheet = new_book.sheet(1)
634
633
  new_cell_value = new_sheet[1,1].Value
635
634
  new_cell_value.should == old_cell_value
636
635
  end
637
636
 
637
+
638
638
  context "with block" do
639
639
  it 'block parameter should be instance of Workbook' do
640
640
  Workbook.open(@simple_file) do |book|
@@ -927,31 +927,6 @@ describe Workbook do
927
927
  after do
928
928
  @book.close
929
929
  end
930
-
931
- it "should open unobtrusively the book in a new Excel such that the book is writable" do
932
- book2 = Workbook.open(@simple_file1, :force => {:excel => :new}, :read_only => true)
933
- @book.ReadOnly.should be true
934
- book2.Readonly.should be true
935
- sheet = @book.sheet(1)
936
- cell_value = sheet[1,1].Value
937
- Workbook.unobtrusively(@simple_file1, :rw_change_excel => :new, :if_closed => :current, :writable => true) do |book|
938
- book.should be_a Workbook
939
- book.excel.should_not == book2.excel
940
- book.excel.should_not == @book.excel
941
- sheet = book.sheet(1)
942
- sheet[1,1] = sheet[1,1].Value == "foo" ? "bar" : "foo"
943
- book.should be_alive
944
- book.Saved.should be false
945
- end
946
- @book.Saved.should be true
947
- @book.ReadOnly.should be true
948
- @book.close
949
- book2.close
950
- book3 = Workbook.open(@simple_file1)
951
- new_sheet = book3.sheet(1)
952
- new_sheet[1,1].Value.should_not == cell_value
953
- book3.close
954
- end
955
930
  end
956
931
 
957
932
  context "with a virgin Workbook class" do
@@ -1001,7 +976,7 @@ describe Workbook do
1001
976
 
1002
977
  before do
1003
978
  @book1 = Workbook.open(@simple_file1)
1004
- @book2 = Workbook.open(@simple_file1, :force => {:excel => :new})
979
+ @book2 = Workbook.open(@simple_file1, :force_excel => :new)
1005
980
  @book1.Readonly.should == false
1006
981
  @book2.Readonly.should == true
1007
982
  old_sheet = @book1.sheet(1)
@@ -1013,9 +988,9 @@ describe Workbook do
1013
988
  end
1014
989
 
1015
990
  it "should open unobtrusively the closed book in the most recent Excel where it was open before" do
1016
- Workbook.unobtrusively(@simple_file) do |book|
1017
- book.excel.should_not == @book2.excel
1018
- book.excel.should == @book1.excel
991
+ Workbook.unobtrusively(@simple_file1, :if_closed => :current) do |book|
992
+ book.excel.should == @book2.excel
993
+ book.excel.should_not == @book1.excel
1019
994
  book.ReadOnly.should == false
1020
995
  sheet = book.sheet(1)
1021
996
  cell = sheet[1,1]
@@ -1027,52 +1002,9 @@ describe Workbook do
1027
1002
  sheet[1,1].Value.should_not == @old_cell_value
1028
1003
  end
1029
1004
 
1030
- it "should open unobtrusively the closed book in the new hidden Excel" do
1031
- Workbook.unobtrusively(@simple_file, :if_closed => :current) do |book|
1032
- book.excel.should_not == @book2.excel
1033
- book.excel.should == @book1.excel
1034
- book.ReadOnly.should == false
1035
- sheet = book.sheet(1)
1036
- cell = sheet[1,1]
1037
- sheet[1,1] = cell.Value == "foo" ? "bar" : "foo"
1038
- book.Saved.should be false
1039
- end
1040
- new_book = Workbook.open(@simple_file1)
1041
- sheet = new_book.sheet(1)
1042
- sheet[1,1].Value.should_not == @old_cell_value
1043
- end
1044
1005
  end
1045
1006
  end
1046
-
1047
- =begin
1048
- context "with :hidden" do
1049
-
1050
- before do
1051
- @book1 = Workbook.open(@simple_file1)
1052
- @book1.close
1053
- end
1054
1007
 
1055
- it "should create a new hidden Excel instance and use this afterwards" do
1056
- hidden_excel = nil
1057
- Workbook.unobtrusively(@simple_file1, :hidden) do |book|
1058
- book.should be_a Workbook
1059
- book.should be_alive
1060
- book.excel.Visible.should be false
1061
- book.excel.DisplayAlerts.should be false
1062
- hidden_excel = book.excel
1063
- end
1064
- Workbook.unobtrusively(@different_file, :hidden) do |book|
1065
- book.should be_a Workbook
1066
- book.should be_alive
1067
- book.excel.Visible.should be false
1068
- book.excel.DisplayAlerts.should be false
1069
- book.excel.should == hidden_excel
1070
- end
1071
- end
1072
- end
1073
- end
1074
- =end
1075
-
1076
1008
  describe "for_reading, for_modifying" do
1077
1009
 
1078
1010
  context "open unobtrusively for reading and modifying" do
@@ -59,25 +59,25 @@ describe Workbook do
59
59
  @book.Windows(@book.Name).Visible.should be true
60
60
  @book.visible.should be true
61
61
  @book.ReadOnly.should be false
62
- @book.CheckCompatibility.should be false
62
+ @book.CheckCompatibility.should be true
63
63
  @book.for_this_workbook(:visible => false)
64
64
  @book.excel.Visible.should be true
65
65
  @book.Windows(@book.Name).Visible.should be false
66
66
  @book.visible.should be false
67
67
  @book.ReadOnly.should be false
68
- @book.CheckCompatibility.should be false
68
+ @book.CheckCompatibility.should be true
69
69
  @book.for_this_workbook(:read_only => true)
70
70
  @book.excel.Visible.should be true
71
- @book.Windows(@book.Name).Visible.should be false
72
- @book.visible.should be false
71
+ @book.Windows(@book.Name).Visible.should be true
72
+ @book.visible.should be true
73
73
  @book.ReadOnly.should be true
74
- @book.CheckCompatibility.should be false
74
+ @book.CheckCompatibility.should be true
75
75
  @book.for_this_workbook(:visible => true)
76
76
  @book.excel.Visible.should be true
77
77
  @book.Windows(@book.Name).Visible.should be true
78
78
  @book.visible.should be true
79
79
  @book.ReadOnly.should be true
80
- @book.CheckCompatibility.should be false
80
+ @book.CheckCompatibility.should be true
81
81
  @book.for_this_workbook(:check_compatibility => true)
82
82
  @book.excel.Visible.should be true
83
83
  @book.Windows(@book.Name).Visible.should be true
@@ -106,7 +106,7 @@ describe Workbook do
106
106
 
107
107
  end
108
108
 
109
- describe "excel_of" do
109
+ describe "to_reo.excel" do
110
110
 
111
111
  before do
112
112
  @book = Workbook.open(@simple_file)
@@ -118,19 +118,19 @@ describe Workbook do
118
118
 
119
119
  it "should access the excel" do
120
120
  workbook = @book.ole_workbook
121
- excel = Workbook.excel_of(workbook)
121
+ excel = workbook.to_reo.excel
122
122
  excel.should be_a Excel
123
123
  excel.should == @book.excel
124
124
  end
125
125
 
126
126
  it "should access the Excel of the ole_excel" do
127
- excel = Workbook.excel_of(@book.excel.ole_excel)
127
+ excel = @book.excel.ole_excel.to_reo.excel
128
128
  excel.should be_a Excel
129
129
  excel.should == @book.excel
130
130
  end
131
131
 
132
132
  it "should access the Excel of a Workbook" do
133
- excel = Workbook.excel_of(@book)
133
+ excel = @book.to_reo.excel
134
134
  excel.should be_a Excel
135
135
  excel.should == @book.excel
136
136
  end
@@ -41,6 +41,9 @@ describe Workbook do
41
41
  @simple_file_hostname_share_path1 = @simple_file_hostname_share_path
42
42
  @simple_file_network_path_other_path1 = @simple_file_network_path_other_path
43
43
  @simple_file_hostname_share_path_other_path1 = @simple_file_hostname_share_path_other_path
44
+ @simple_file_xlsm1 = @simple_file_xlsm
45
+ @simple_file_xlsx1 = @simple_file_xlsx
46
+ @error_message_excel = "provided Excel option value is neither an Excel object nor a valid option"
44
47
  end
45
48
 
46
49
  after do
@@ -48,6 +51,198 @@ describe Workbook do
48
51
  rm_tmp(@dir)
49
52
  end
50
53
 
54
+ describe "basic tests with xlsx-workbooks" do
55
+
56
+ context "with simple file" do
57
+
58
+ it "should simply create a new workbook given a file" do
59
+ book = Workbook.new(@simple_file_xlsx1)
60
+ book.should be_alive
61
+ book.should be_a Workbook
62
+ book.filename.should == @simple_file_xlsx1
63
+ end
64
+
65
+ end
66
+
67
+ context "with transparency identity" do
68
+
69
+ before do
70
+ @book = Workbook.open(@simple_file_xlsx1)
71
+ end
72
+
73
+ after do
74
+ @book.close
75
+ end
76
+
77
+ it "should yield identical Workbook objects referring to identical WIN32OLE objects" do
78
+ book2 = Workbook.new(@book.ole_workbook)
79
+ book2.equal?(@book).should be true
80
+ end
81
+
82
+ end
83
+
84
+ context "with connecting to one unknown workbook" do
85
+
86
+ before do
87
+ ole_e1 = WIN32OLE.new('Excel.Application')
88
+ ws = ole_e1.Workbooks
89
+ abs_filename = General.absolute_path(@simple_file_xlsx1)
90
+ @ole_wb = ws.Open(abs_filename)
91
+ end
92
+
93
+ it "should connect to an unknown workbook" do
94
+ Workbook.open(@simple_file_xlsx1) do |book|
95
+ book.filename.should == @simple_file_xlsx1
96
+ book.should be_alive
97
+ book.should be_a Workbook
98
+ book.excel.ole_excel.Hwnd.should == @ole_wb.Application.Hwnd
99
+ Excel.excels_number.should == 1
100
+ end
101
+ end
102
+ end
103
+
104
+ context "with :force => excel" do
105
+
106
+ before do
107
+ @book = Workbook.open(@simple_file_xlsx1)
108
+ end
109
+
110
+ it "should open in a new Excel" do
111
+ book2 = Workbook.open(@simple_file_xlsx1, :force => {:excel => :new})
112
+ book2.should be_alive
113
+ book2.should be_a Workbook
114
+ book2.excel.should_not == @book.excel
115
+ book2.should_not == @book
116
+ @book.Readonly.should be false
117
+ book2.Readonly.should be true
118
+ book2.close
119
+ end
120
+
121
+ end
122
+
123
+ context "with :if_unsaved" do
124
+
125
+ before do
126
+ @book = Workbook.open(@simple_file_xlsx1)
127
+ @sheet = @book.sheet(1)
128
+ @book.add_sheet(@sheet, :as => 'a_name')
129
+ @book.visible = true
130
+ end
131
+
132
+ after do
133
+ @book.close(:if_unsaved => :forget)
134
+ @new_book.close rescue nil
135
+ end
136
+
137
+ it "should let the book open, if :if_unsaved is :accept" do
138
+ expect {
139
+ @new_book = Workbook.open(@simple_file_xlsx1, :if_unsaved => :accept)
140
+ }.to_not raise_error
141
+ @book.should be_alive
142
+ @new_book.should be_alive
143
+ @new_book.should == @book
144
+ end
145
+
146
+ end
147
+
148
+ end
149
+
150
+ describe "basic tests with xlsm-workbooks" do
151
+
152
+ context "with simple file" do
153
+
154
+ it "should simply create a new workbook given a file" do
155
+ book = Workbook.new(@simple_file_xlsm1)
156
+ book.should be_alive
157
+ book.should be_a Workbook
158
+ book.filename.should == @simple_file_xlsm1
159
+ end
160
+
161
+ end
162
+
163
+ context "with transparency identity" do
164
+
165
+ before do
166
+ @book = Workbook.open(@simple_file_xlsm1)
167
+ end
168
+
169
+ after do
170
+ @book.close
171
+ end
172
+
173
+ it "should yield identical Workbook objects referring to identical WIN32OLE objects" do
174
+ book2 = Workbook.new(@book.ole_workbook)
175
+ book2.equal?(@book).should be true
176
+ end
177
+
178
+ end
179
+
180
+ context "connecting to one unknown workbook" do
181
+
182
+ before do
183
+ ole_e1 = WIN32OLE.new('Excel.Application')
184
+ ws = ole_e1.Workbooks
185
+ abs_filename = General.absolute_path(@simple_file_xlsm1)
186
+ @ole_wb = ws.Open(abs_filename)
187
+ end
188
+
189
+ it "should connect to an unknown workbook" do
190
+ Workbook.open(@simple_file_xlsm1) do |book|
191
+ book.filename.should == @simple_file_xlsm1
192
+ book.should be_alive
193
+ book.should be_a Workbook
194
+ book.excel.ole_excel.Hwnd.should == @ole_wb.Application.Hwnd
195
+ Excel.excels_number.should == 1
196
+ end
197
+ end
198
+ end
199
+
200
+ context "with :force => excel" do
201
+
202
+ before do
203
+ @book = Workbook.open(@simple_file_xlsm1)
204
+ end
205
+
206
+ it "should open in a new Excel" do
207
+ book2 = Workbook.open(@simple_file_xlsm1, :force => {:excel => :new})
208
+ book2.should be_alive
209
+ book2.should be_a Workbook
210
+ book2.excel.should_not == @book.excel
211
+ book2.should_not == @book
212
+ @book.Readonly.should be false
213
+ book2.Readonly.should be true
214
+ book2.close
215
+ end
216
+
217
+ end
218
+
219
+ context "with :if_unsaved" do
220
+
221
+ before do
222
+ @book = Workbook.open(@simple_file_xlsm1)
223
+ @sheet = @book.sheet(1)
224
+ @book.add_sheet(@sheet, :as => 'a_name')
225
+ @book.visible = true
226
+ end
227
+
228
+ after do
229
+ @book.close(:if_unsaved => :forget)
230
+ @new_book.close rescue nil
231
+ end
232
+
233
+ it "should let the book open, if :if_unsaved is :accept" do
234
+ expect {
235
+ @new_book = Workbook.open(@simple_file_xlsm1, :if_unsaved => :accept)
236
+ }.to_not raise_error
237
+ @book.should be_alive
238
+ @new_book.should be_alive
239
+ @new_book.should == @book
240
+ end
241
+
242
+ end
243
+
244
+ end
245
+
51
246
  describe "open and new" do
52
247
 
53
248
  context "with standard" do
@@ -415,7 +610,7 @@ describe Workbook do
415
610
  Excel.excels_number.should == 1
416
611
  book1.ReadOnly.should be false
417
612
  book1.excel.Visible.should be false
418
- book1.CheckCompatibility.should be false
613
+ book1.CheckCompatibility.should be true
419
614
  book1.Saved.should be true
420
615
  end
421
616
 
@@ -717,7 +912,7 @@ describe Workbook do
717
912
  excel1.close
718
913
  expect{
719
914
  book1 = Workbook.open(@simple_file1, :force => {:excel => excel1})
720
- }.to raise_error(ExcelREOError, "excel is not alive")
915
+ }.to raise_error(ExcelREOError, "Excel is not alive")
721
916
  end
722
917
 
723
918
  it "should open in a provided Excel" do
@@ -836,7 +1031,26 @@ describe Workbook do
836
1031
  book2.excel.should_not == book.excel
837
1032
  end
838
1033
 
839
- it "should type-lift an open known workbook" do
1034
+ it "should type-lift an workbook" do
1035
+ book = Workbook.open(@simple_file)
1036
+ new_book = Workbook.new(book)
1037
+ new_book.should == book
1038
+ new_book.equal?(book).should be true
1039
+ new_book.Fullname.should == book.Fullname
1040
+ new_book.excel.should == book.excel
1041
+ end
1042
+
1043
+ it "should type-lift an workbook and supply option" do
1044
+ book = Workbook.open(@simple_file)
1045
+ new_book = Workbook.new(book, :visible => true)
1046
+ new_book.should == book
1047
+ new_book.equal?(book).should be true
1048
+ new_book.Fullname.should == book.Fullname
1049
+ new_book.excel.should == book.excel
1050
+ new_book.visible.should be true
1051
+ end
1052
+
1053
+ it "should type-lift an open known win32ole workbook" do
840
1054
  book = Workbook.open(@simple_file)
841
1055
  ole_workbook = book.ole_workbook
842
1056
  new_book = Workbook.new(ole_workbook)
@@ -846,7 +1060,7 @@ describe Workbook do
846
1060
  new_book.excel.should == book.excel
847
1061
  end
848
1062
 
849
- it "should type-lift an open known workbook and let it be visible" do
1063
+ it "should type-lift an open known win32ole workbook and let it be visible" do
850
1064
  book = Workbook.open(@simple_file, :visible => true)
851
1065
  ole_workbook = book.ole_workbook
852
1066
  new_book = Workbook.new(ole_workbook)
@@ -858,7 +1072,7 @@ describe Workbook do
858
1072
  new_book.Windows(new_book.ole_workbook.Name).Visible.should == true
859
1073
  end
860
1074
 
861
- it "should type-lift an open known workbook and let it be visible and readonly" do
1075
+ it "should type-lift an open known win32ole workbook and let it be visible and readonly" do
862
1076
  book = Workbook.open(@simple_file, :visible => true, :read_only => true)
863
1077
  ole_workbook = book.ole_workbook
864
1078
  new_book = Workbook.new(ole_workbook)
@@ -871,7 +1085,7 @@ describe Workbook do
871
1085
  new_book.ReadOnly.should == true
872
1086
  end
873
1087
 
874
- it "should type-lift an open known workbook and make it visible" do
1088
+ it "should type-lift an open known win32ole workbook and make it visible" do
875
1089
  book = Workbook.open(@simple_file)
876
1090
  ole_workbook = book.ole_workbook
877
1091
  new_book = Workbook.new(ole_workbook, :visible => true)
@@ -883,7 +1097,7 @@ describe Workbook do
883
1097
  new_book.Windows(new_book.ole_workbook.Name).Visible.should == true
884
1098
  end
885
1099
 
886
- it "should type-lift an open unknown workbook" do
1100
+ it "should type-lift an open unknown win32ole workbook" do
887
1101
  ole_excel = WIN32OLE.new('Excel.Application')
888
1102
  ws = ole_excel.Workbooks
889
1103
  abs_filename = General.absolute_path(@simple_file1)
@@ -893,7 +1107,7 @@ describe Workbook do
893
1107
  new_book.excel.Hwnd.should == ole_excel.Hwnd
894
1108
  end
895
1109
 
896
- it "should type-lift an open unknown workbook and make it visible" do
1110
+ it "should type-lift an open unknown win32ole workbook and make it visible" do
897
1111
  ole_excel = WIN32OLE.new('Excel.Application')
898
1112
  ws = ole_excel.Workbooks
899
1113
  abs_filename = General.absolute_path(@simple_file1)
@@ -905,7 +1119,7 @@ describe Workbook do
905
1119
  new_book.Windows(new_book.ole_workbook.Name).Visible.should == true
906
1120
  end
907
1121
 
908
- it "should type-lift an open unknown workbook and make it visible and readonly" do
1122
+ it "should type-lift an open unknown win32ole workbook and make it visible and readonly" do
909
1123
  ole_excel = WIN32OLE.new('Excel.Application')
910
1124
  ws = ole_excel.Workbooks
911
1125
  abs_filename = General.absolute_path(@simple_file1)
@@ -1366,7 +1580,7 @@ describe Workbook do
1366
1580
  it "should raise an error if no Excel or Workbook is given" do
1367
1581
  expect{
1368
1582
  Workbook.open(@simple_file1, :force => {:excel => :b})
1369
- }.to raise_error(TypeREOError, "given object is neither an Excel, a Workbook, nor a Win32ole")
1583
+ }.to raise_error(TypeREOError, @error_message_excel)
1370
1584
  end
1371
1585
 
1372
1586
  it "should do force_excel even if both force_ and default_excel is given" do
@@ -1522,7 +1736,7 @@ describe Workbook do
1522
1736
  it "should raise an error if no Excel or Workbook is given" do
1523
1737
  expect{
1524
1738
  Workbook.open(@simple_file1, :excel => :b)
1525
- }.to raise_error(TypeREOError, "given object is neither an Excel, a Workbook, nor a Win32ole")
1739
+ }.to raise_error(TypeREOError, @error_message_excel)
1526
1740
  end
1527
1741
 
1528
1742
  it "should do force_excel even if both force_ and default_excel is given" do
@@ -1680,7 +1894,7 @@ describe Workbook do
1680
1894
  it "should raise an error if no Excel or Workbook is given" do
1681
1895
  expect{
1682
1896
  Workbook.open(@simple_file1, :force_excel => :b)
1683
- }.to raise_error(TypeREOError, "given object is neither an Excel, a Workbook, nor a Win32ole")
1897
+ }.to raise_error(TypeREOError, @error_message_excel)
1684
1898
  end
1685
1899
 
1686
1900
  it "should do force_excel even if both force_ and default_excel is given" do
@@ -1921,7 +2135,7 @@ describe Workbook do
1921
2135
  it "should raise an error if no Excel or Workbook is given" do
1922
2136
  expect{
1923
2137
  Workbook.open(@different_file, :default => {:excel => :a})
1924
- }.to raise_error(TypeREOError, "given object is neither an Excel, a Workbook, nor a Win32ole")
2138
+ }.to raise_error(TypeREOError, @error_message_excel)
1925
2139
  end
1926
2140
 
1927
2141
  end
@@ -2103,7 +2317,7 @@ describe Workbook do
2103
2317
  it "should raise an error if no Excel or Workbook is given" do
2104
2318
  expect{
2105
2319
  Workbook.open(@different_file, :default_excel => :a)
2106
- }.to raise_error(TypeREOError, "given object is neither an Excel, a Workbook, nor a Win32ole")
2320
+ }.to raise_error(TypeREOError, @error_message_excel)
2107
2321
  end
2108
2322
 
2109
2323
  end