roo 1.13.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (172) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +7 -0
  3. data/.simplecov +4 -0
  4. data/.travis.yml +13 -0
  5. data/CHANGELOG.md +500 -0
  6. data/Gemfile +16 -10
  7. data/Guardfile +24 -0
  8. data/LICENSE +3 -1
  9. data/README.md +254 -0
  10. data/Rakefile +23 -23
  11. data/examples/roo_soap_client.rb +28 -31
  12. data/examples/roo_soap_server.rb +4 -6
  13. data/examples/write_me.rb +9 -10
  14. data/lib/roo/base.rb +303 -388
  15. data/lib/roo/csv.rb +120 -113
  16. data/lib/roo/excelx/comments.rb +24 -0
  17. data/lib/roo/excelx/extractor.rb +20 -0
  18. data/lib/roo/excelx/relationships.rb +26 -0
  19. data/lib/roo/excelx/shared_strings.rb +40 -0
  20. data/lib/roo/excelx/sheet_doc.rb +202 -0
  21. data/lib/roo/excelx/styles.rb +62 -0
  22. data/lib/roo/excelx/workbook.rb +59 -0
  23. data/lib/roo/excelx.rb +452 -484
  24. data/lib/roo/font.rb +17 -0
  25. data/lib/roo/libre_office.rb +5 -0
  26. data/lib/roo/link.rb +15 -0
  27. data/lib/roo/{openoffice.rb → open_office.rb} +678 -496
  28. data/lib/roo/spreadsheet.rb +20 -23
  29. data/lib/roo/utils.rb +78 -0
  30. data/lib/roo/version.rb +3 -0
  31. data/lib/roo.rb +18 -24
  32. data/roo.gemspec +20 -204
  33. data/spec/lib/roo/base_spec.rb +1 -4
  34. data/spec/lib/roo/csv_spec.rb +21 -13
  35. data/spec/lib/roo/excelx/format_spec.rb +7 -6
  36. data/spec/lib/roo/excelx_spec.rb +388 -11
  37. data/spec/lib/roo/libreoffice_spec.rb +16 -6
  38. data/spec/lib/roo/openoffice_spec.rb +2 -8
  39. data/spec/lib/roo/spreadsheet_spec.rb +40 -12
  40. data/spec/lib/roo/utils_spec.rb +106 -0
  41. data/spec/spec_helper.rb +2 -1
  42. data/test/test_generic_spreadsheet.rb +19 -67
  43. data/test/test_helper.rb +9 -56
  44. data/test/test_roo.rb +252 -477
  45. metadata +63 -302
  46. data/CHANGELOG +0 -417
  47. data/Gemfile.lock +0 -78
  48. data/README.markdown +0 -126
  49. data/VERSION +0 -1
  50. data/lib/roo/excel.rb +0 -355
  51. data/lib/roo/excel2003xml.rb +0 -300
  52. data/lib/roo/google.rb +0 -292
  53. data/lib/roo/roo_rails_helper.rb +0 -83
  54. data/lib/roo/worksheet.rb +0 -18
  55. data/spec/lib/roo/excel2003xml_spec.rb +0 -15
  56. data/spec/lib/roo/excel_spec.rb +0 -17
  57. data/spec/lib/roo/google_spec.rb +0 -64
  58. data/test/files/1900_base.xls +0 -0
  59. data/test/files/1900_base.xlsx +0 -0
  60. data/test/files/1904_base.xls +0 -0
  61. data/test/files/1904_base.xlsx +0 -0
  62. data/test/files/Bibelbund.csv +0 -3741
  63. data/test/files/Bibelbund.ods +0 -0
  64. data/test/files/Bibelbund.xls +0 -0
  65. data/test/files/Bibelbund.xlsx +0 -0
  66. data/test/files/Bibelbund.xml +0 -62518
  67. data/test/files/Bibelbund1.ods +0 -0
  68. data/test/files/Pfand_from_windows_phone.xlsx +0 -0
  69. data/test/files/bad_excel_date.xls +0 -0
  70. data/test/files/bbu.ods +0 -0
  71. data/test/files/bbu.xls +0 -0
  72. data/test/files/bbu.xlsx +0 -0
  73. data/test/files/bbu.xml +0 -152
  74. data/test/files/bode-v1.ods.zip +0 -0
  75. data/test/files/bode-v1.xls.zip +0 -0
  76. data/test/files/boolean.csv +0 -2
  77. data/test/files/boolean.ods +0 -0
  78. data/test/files/boolean.xls +0 -0
  79. data/test/files/boolean.xlsx +0 -0
  80. data/test/files/boolean.xml +0 -112
  81. data/test/files/borders.ods +0 -0
  82. data/test/files/borders.xls +0 -0
  83. data/test/files/borders.xlsx +0 -0
  84. data/test/files/borders.xml +0 -144
  85. data/test/files/bug-numbered-sheet-names.xlsx +0 -0
  86. data/test/files/bug-row-column-fixnum-float.xls +0 -0
  87. data/test/files/bug-row-column-fixnum-float.xml +0 -127
  88. data/test/files/comments.ods +0 -0
  89. data/test/files/comments.xls +0 -0
  90. data/test/files/comments.xlsx +0 -0
  91. data/test/files/csvtypes.csv +0 -1
  92. data/test/files/datetime.ods +0 -0
  93. data/test/files/datetime.xls +0 -0
  94. data/test/files/datetime.xlsx +0 -0
  95. data/test/files/datetime.xml +0 -142
  96. data/test/files/datetime_floatconv.xls +0 -0
  97. data/test/files/datetime_floatconv.xml +0 -148
  98. data/test/files/dreimalvier.ods +0 -0
  99. data/test/files/emptysheets.ods +0 -0
  100. data/test/files/emptysheets.xls +0 -0
  101. data/test/files/emptysheets.xlsx +0 -0
  102. data/test/files/emptysheets.xml +0 -105
  103. data/test/files/excel2003.xml +0 -21140
  104. data/test/files/false_encoding.xls +0 -0
  105. data/test/files/false_encoding.xml +0 -132
  106. data/test/files/file_item_error.xlsx +0 -0
  107. data/test/files/formula.ods +0 -0
  108. data/test/files/formula.xls +0 -0
  109. data/test/files/formula.xlsx +0 -0
  110. data/test/files/formula.xml +0 -134
  111. data/test/files/formula_parse_error.xls +0 -0
  112. data/test/files/formula_parse_error.xml +0 -1833
  113. data/test/files/formula_string_error.xlsx +0 -0
  114. data/test/files/html-escape.ods +0 -0
  115. data/test/files/link.xls +0 -0
  116. data/test/files/link.xlsx +0 -0
  117. data/test/files/matrix.ods +0 -0
  118. data/test/files/matrix.xls +0 -0
  119. data/test/files/named_cells.ods +0 -0
  120. data/test/files/named_cells.xls +0 -0
  121. data/test/files/named_cells.xlsx +0 -0
  122. data/test/files/no_spreadsheet_file.txt +0 -1
  123. data/test/files/numbers1.csv +0 -18
  124. data/test/files/numbers1.ods +0 -0
  125. data/test/files/numbers1.xls +0 -0
  126. data/test/files/numbers1.xlsx +0 -0
  127. data/test/files/numbers1.xml +0 -312
  128. data/test/files/numeric-link.xlsx +0 -0
  129. data/test/files/only_one_sheet.ods +0 -0
  130. data/test/files/only_one_sheet.xls +0 -0
  131. data/test/files/only_one_sheet.xlsx +0 -0
  132. data/test/files/only_one_sheet.xml +0 -67
  133. data/test/files/paragraph.ods +0 -0
  134. data/test/files/paragraph.xls +0 -0
  135. data/test/files/paragraph.xlsx +0 -0
  136. data/test/files/paragraph.xml +0 -127
  137. data/test/files/prova.xls +0 -0
  138. data/test/files/ric.ods +0 -0
  139. data/test/files/simple_spreadsheet.ods +0 -0
  140. data/test/files/simple_spreadsheet.xls +0 -0
  141. data/test/files/simple_spreadsheet.xlsx +0 -0
  142. data/test/files/simple_spreadsheet.xml +0 -225
  143. data/test/files/simple_spreadsheet_from_italo.ods +0 -0
  144. data/test/files/simple_spreadsheet_from_italo.xls +0 -0
  145. data/test/files/simple_spreadsheet_from_italo.xml +0 -242
  146. data/test/files/so_datetime.csv +0 -7
  147. data/test/files/style.ods +0 -0
  148. data/test/files/style.xls +0 -0
  149. data/test/files/style.xlsx +0 -0
  150. data/test/files/style.xml +0 -154
  151. data/test/files/time-test.csv +0 -2
  152. data/test/files/time-test.ods +0 -0
  153. data/test/files/time-test.xls +0 -0
  154. data/test/files/time-test.xlsx +0 -0
  155. data/test/files/time-test.xml +0 -131
  156. data/test/files/type_excel.ods +0 -0
  157. data/test/files/type_excel.xlsx +0 -0
  158. data/test/files/type_excelx.ods +0 -0
  159. data/test/files/type_excelx.xls +0 -0
  160. data/test/files/type_openoffice.xls +0 -0
  161. data/test/files/type_openoffice.xlsx +0 -0
  162. data/test/files/whitespace.ods +0 -0
  163. data/test/files/whitespace.xls +0 -0
  164. data/test/files/whitespace.xlsx +0 -0
  165. data/test/files/whitespace.xml +0 -184
  166. data/test/rm_sub_test.rb +0 -12
  167. data/test/rm_test.rb +0 -7
  168. data/website/index.html +0 -385
  169. data/website/index.txt +0 -423
  170. data/website/javascripts/rounded_corners_lite.inc.js +0 -285
  171. data/website/stylesheets/screen.css +0 -130
  172. data/website/template.rhtml +0 -48
@@ -1,37 +1,414 @@
1
+ # encoding: utf-8
1
2
  require 'spec_helper'
2
3
 
3
4
  describe Roo::Excelx do
5
+ subject(:xlsx) do
6
+ Roo::Excelx.new(path)
7
+ end
8
+
4
9
  describe '.new' do
5
- subject {
6
- Roo::Excelx.new('test/files/numbers1.xlsx')
7
- }
10
+ let(:path) { 'test/files/numeric-link.xlsx' }
8
11
 
9
12
  it 'creates an instance' do
10
13
  expect(subject).to be_a(Roo::Excelx)
11
14
  end
12
15
 
13
16
  context 'given a file with missing rels' do
14
- subject {
15
- Roo::Excelx.new('test/files/file_item_error.xlsx')
16
- }
17
+ let(:path) { 'test/files/file_item_error.xlsx' }
17
18
 
18
19
  it 'creates an instance' do
19
20
  expect(subject).to be_a(Roo::Excelx)
20
21
  end
21
22
  end
23
+
24
+ context 'with more cells than specified max' do
25
+ let(:path) { 'test/files/only_one_sheet.xlsx' }
26
+
27
+ it 'raises an appropriate error' do
28
+ expect { Roo::Excelx.new(path, cell_max: 1) }.to raise_error(Roo::Excelx::ExceedsMaxError)
29
+ end
30
+ end
31
+
32
+ context 'with fewer cells than specified max' do
33
+ let(:path) { 'test/files/only_one_sheet.xlsx' }
34
+
35
+ it 'creates an instance' do
36
+ expect(Roo::Excelx.new(path, cell_max: 100)).to be_a(Roo::Excelx)
37
+ end
38
+ end
22
39
  end
23
40
 
24
41
  describe '#cell' do
25
42
  context 'for a link cell' do
26
43
  context 'with numeric contents' do
27
- subject {
28
- Roo::Excelx.new('test/files/numeric-link.xlsx').cell('A', 1)
29
- }
44
+ let(:path) { 'test/files/numeric-link.xlsx' }
45
+
46
+ subject do
47
+ xlsx.cell('A', 1)
48
+ end
30
49
 
31
50
  it 'returns a link with the number as a string value' do
32
- expect(subject).to be_a(Spreadsheet::Link)
33
- expect(subject).to eq("8675309.0")
51
+ expect(subject).to be_a(Roo::Link)
52
+ expect(subject).to eq('8675309.0')
53
+ end
54
+ end
55
+ end
56
+
57
+ context 'for a non-existent cell' do
58
+ let(:path) { 'test/files/numeric-link.xlsx' }
59
+ it 'return nil' do
60
+ expect(xlsx.cell('AAA', 999)).to eq nil
61
+ end
62
+ end
63
+ end
64
+
65
+ describe '#parse' do
66
+ let(:path) { 'test/files/numeric-link.xlsx' }
67
+
68
+ context 'with a columns hash' do
69
+ context 'when not present in the sheet' do
70
+ it 'does not raise' do
71
+ expect do
72
+ xlsx.sheet(0).parse(
73
+ this: 'This',
74
+ that: 'That'
75
+ )
76
+ end.to raise_error("Couldn't find header row.")
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+ describe '#parse_with_clean_option' do
83
+ let(:path) { 'test/files/parse_with_clean_option.xlsx' }
84
+ let(:options) { {clean: true} }
85
+
86
+ context 'with clean: true' do
87
+
88
+ it 'does not raise' do
89
+ expect do
90
+ xlsx.parse(options)
91
+ end.not_to raise_error
92
+ end
93
+ end
94
+ end
95
+
96
+ describe '#parse_unicode_with_clean_option' do
97
+ let(:path) { 'test/files/parse_clean_with_unicode.xlsx' }
98
+ let(:options) { {clean: true, name: 'Name'} }
99
+
100
+ context 'with clean: true' do
101
+
102
+ it 'returns a non empty string' do
103
+ expect(xlsx.parse(options).last[:name]).to eql('凯')
104
+ end
105
+ end
106
+ end
107
+
108
+
109
+
110
+
111
+ describe '#sheets' do
112
+ let(:path) { 'test/files/numbers1.xlsx' }
113
+
114
+ it 'returns the expected result' do
115
+ expect(subject.sheets).to eq ["Tabelle1", "Name of Sheet 2", "Sheet3", "Sheet4", "Sheet5"]
116
+ end
117
+
118
+ describe 'only showing visible sheets' do
119
+ let(:path) { 'test/files/hidden_sheets.xlsx' }
120
+
121
+ it 'returns the expected result' do
122
+ expect(Roo::Excelx.new(path, only_visible_sheets: true).sheets).to eq ["VisibleSheet1"]
123
+ end
124
+ end
125
+ end
126
+
127
+ describe '#sheet_for' do
128
+ let(:path) { 'test/files/numbers1.xlsx' }
129
+
130
+ # This is kinda gross
131
+ it 'returns the expected result' do
132
+ expect(subject.sheet_for("Tabelle1").instance_variable_get("@name")).to eq "Tabelle1"
133
+ end
134
+ end
135
+
136
+ describe '#row' do
137
+ let(:path) { 'test/files/numbers1.xlsx' }
138
+
139
+ it 'returns the expected result' do
140
+ expect(subject.row(1, "Sheet5")).to eq [1.0, 5.0, 5.0, nil, nil]
141
+ end
142
+ end
143
+
144
+ describe '#column' do
145
+ let(:path) { 'test/files/numbers1.xlsx' }
146
+
147
+ it 'returns the expected result' do
148
+ expect(subject.column(1, "Sheet5")).to eq [1.0, 2.0, 3.0, Date.new(2007,11,21), 42.0, "ABC"]
149
+ end
150
+ end
151
+
152
+ describe '#first_row' do
153
+ let(:path) { 'test/files/numbers1.xlsx' }
154
+
155
+ it 'returns the expected result' do
156
+ expect(subject.first_row("Sheet5")).to eq 1
157
+ end
158
+ end
159
+
160
+ describe '#last_row' do
161
+ let(:path) { 'test/files/numbers1.xlsx' }
162
+
163
+ it 'returns the expected result' do
164
+ expect(subject.last_row("Sheet5")).to eq 6
165
+ end
166
+ end
167
+
168
+ describe '#first_column' do
169
+ let(:path) { 'test/files/numbers1.xlsx' }
170
+
171
+ it 'returns the expected result' do
172
+ expect(subject.first_column("Sheet5")).to eq 1
173
+ end
174
+ end
175
+
176
+ describe '#last_column' do
177
+ let(:path) { 'test/files/numbers1.xlsx' }
178
+
179
+ it 'returns the expected result' do
180
+ expect(subject.last_column("Sheet5")).to eq 5
181
+ end
182
+ end
183
+
184
+ describe '#set' do
185
+
186
+ before do
187
+ subject.set(1, 2, "Foo", "Sheet5")
188
+ end
189
+
190
+ let(:path) { 'test/files/numbers1.xlsx' }
191
+ let(:cell) { subject.cell(1, 2, "Sheet5") }
192
+
193
+ it 'returns the expected result' do
194
+ expect(cell).to eq "Foo"
195
+ end
196
+ end
197
+
198
+ describe '#formula' do
199
+ let(:path) { 'test/files/formula.xlsx' }
200
+
201
+ it 'returns the expected result' do
202
+ expect(subject.formula(1, 1, "Sheet1")).to eq nil
203
+ expect(subject.formula(7, 2, "Sheet1")).to eq "SUM($A$1:B6)"
204
+ expect(subject.formula(1000, 2000, "Sheet1")).to eq nil
205
+ end
206
+ end
207
+
208
+ describe '#formula?' do
209
+ let(:path) { 'test/files/formula.xlsx' }
210
+
211
+ it 'returns the expected result' do
212
+ expect(subject.formula?(1, 1, "Sheet1")).to eq false
213
+ expect(subject.formula?(7, 2, "Sheet1")).to eq true
214
+ expect(subject.formula?(1000, 2000, "Sheet1")).to eq false
215
+ end
216
+ end
217
+
218
+ describe '#formulas' do
219
+ let(:path) { 'test/files/formula.xlsx' }
220
+
221
+ it 'returns the expected result' do
222
+ expect(subject.formulas("Sheet1")).to eq [[7, 1, "SUM(A1:A6)"], [7, 2, "SUM($A$1:B6)"]]
223
+ end
224
+ end
225
+
226
+ describe '#font' do
227
+ let(:path) { 'test/files/style.xlsx' }
228
+
229
+ it 'returns the expected result' do
230
+ expect(subject.font(1, 1).bold?).to eq true
231
+ expect(subject.font(1, 1).italic?).to eq false
232
+ expect(subject.font(1, 1).underline?).to eq false
233
+
234
+ expect(subject.font(7, 1).bold?).to eq false
235
+ expect(subject.font(7, 1).italic?).to eq true
236
+ expect(subject.font(7, 1).underline?).to eq true
237
+ expect(subject.font(1000, 2000)).to eq nil
238
+ end
239
+ end
240
+
241
+ describe '#celltype' do
242
+ let(:path) { 'test/files/numbers1.xlsx' }
243
+
244
+ it 'returns the expected result' do
245
+ expect(subject.celltype(1, 1, "Sheet4")).to eq :date
246
+ expect(subject.celltype(1, 2, "Sheet4")).to eq :float
247
+ expect(subject.celltype(6, 2, "Sheet5")).to eq :string
248
+ expect(subject.celltype(1000, 2000, "Sheet5")).to eq nil
249
+ end
250
+ end
251
+
252
+ describe '#excelx_type' do
253
+ let(:path) { 'test/files/numbers1.xlsx' }
254
+
255
+ it 'returns the expected result' do
256
+ expect(subject.excelx_type(1, 1, "Sheet5")).to eq [:numeric_or_formula, "General"]
257
+ expect(subject.excelx_type(6, 2, "Sheet5")).to eq :string
258
+ expect(subject.excelx_type(1000, 2000, "Sheet5")).to eq nil
259
+ end
260
+ end
261
+
262
+ describe '#excelx_value' do
263
+ let(:path) { 'test/files/numbers1.xlsx' }
264
+
265
+ it 'returns the expected result' do
266
+ # These values are the index in the shared strings table, might be a better
267
+ # way to get these rather than hardcoding.
268
+ expect(subject.excelx_value(1, 1, "Sheet5")).to eq "1"
269
+ expect(subject.excelx_value(6, 2, "Sheet5")).to eq "16"
270
+ expect(subject.excelx_value(6000, 2000, "Sheet5")).to eq nil
271
+ end
272
+ end
273
+
274
+ describe '#excelx_format' do
275
+ let(:path) { 'test/files/style.xlsx' }
276
+
277
+ it 'returns the expected result' do
278
+ # These are the index of the style for a given document
279
+ # might be more reliable way to get this info.
280
+ expect(subject.excelx_format(1, 1)).to eq "General"
281
+ expect(subject.excelx_format(2, 2)).to eq "0.00"
282
+ expect(subject.excelx_format(5000, 1000)).to eq nil
283
+ end
284
+ end
285
+
286
+ describe '#empty?' do
287
+ let(:path) { 'test/files/style.xlsx' }
288
+
289
+ it 'returns the expected result' do
290
+ # These are the index of the style for a given document
291
+ # might be more reliable way to get this info.
292
+ expect(subject.empty?(1, 1)).to eq false
293
+ expect(subject.empty?(13, 1)).to eq true
294
+ end
295
+ end
296
+
297
+ describe '#label' do
298
+ let(:path) { 'test/files/named_cells.xlsx' }
299
+
300
+ it 'returns the expected result' do
301
+ expect(subject.label("berta")).to eq [4, 2, "Sheet1"]
302
+ expect(subject.label("dave")).to eq [nil, nil, nil]
303
+ end
304
+ end
305
+
306
+ describe '#labels' do
307
+ let(:path) { 'test/files/named_cells.xlsx' }
308
+
309
+ it 'returns the expected result' do
310
+ expect(subject.labels).to eq [["anton", [5, 3, "Sheet1"]], ["berta", [4, 2, "Sheet1"]], ["caesar", [7, 2, "Sheet1"]]]
311
+ end
312
+ end
313
+
314
+ describe '#hyperlink?' do
315
+ let(:path) { 'test/files/link.xlsx' }
316
+
317
+ it 'returns the expected result' do
318
+ expect(subject.hyperlink?(1, 1)).to eq true
319
+ expect(subject.hyperlink?(1, 2)).to eq false
320
+ end
321
+ end
322
+
323
+ describe '#hyperlink' do
324
+ let(:path) { 'test/files/link.xlsx' }
325
+
326
+ it 'returns the expected result' do
327
+ expect(subject.hyperlink(1, 1)).to eq "http://www.google.com"
328
+ expect(subject.hyperlink(1, 2)).to eq nil
329
+ end
330
+ end
331
+
332
+ describe '#comment' do
333
+ let(:path) { 'test/files/comments.xlsx' }
334
+
335
+ it 'returns the expected result' do
336
+ expect(subject.comment(4, 2)).to eq "Kommentar fuer B4"
337
+ expect(subject.comment(1, 2)).to eq nil
338
+ end
339
+ end
340
+
341
+ describe '#comment?' do
342
+ let(:path) { 'test/files/comments.xlsx' }
343
+
344
+ it 'returns the expected result' do
345
+ expect(subject.comment?(4, 2)).to eq true
346
+ expect(subject.comment?(1, 2)).to eq false
347
+ end
348
+ end
349
+
350
+ describe '#comments' do
351
+ let(:path) { 'test/files/comments.xlsx' }
352
+
353
+ it 'returns the expected result' do
354
+ expect(subject.comments).to eq [[4, 2, "Kommentar fuer B4"], [5, 2, "Kommentar fuer B5"]]
355
+ end
356
+ end
357
+
358
+ # nil, nil, nil, nil, nil
359
+ # nil, nil, nil, nil, nil
360
+ # Date Start time End time Pause Sum Comment
361
+ # 2007-05-07 9.25 10.25 0 1 Task 1
362
+ # 2007-05-07 10.75 12.50 0 1.75 Task 1
363
+ # 2007-05-07 18.00 19.00 0 1 Task 2
364
+ # 2007-05-08 9.25 10.25 0 1 Task 2
365
+ # 2007-05-08 14.50 15.50 0 1 Task 3
366
+ # 2007-05-08 8.75 9.25 0 0.5 Task 3
367
+ # 2007-05-14 21.75 22.25 0 0.5 Task 3
368
+ # 2007-05-14 22.50 23.00 0 0.5 Task 3
369
+ # 2007-05-15 11.75 12.75 0 1 Task 3
370
+ # 2007-05-07 10.75 10.75 0 0 Task 1
371
+ # nil
372
+ describe '#each_row_streaming' do
373
+ let(:path) { 'test/files/simple_spreadsheet.xlsx' }
374
+
375
+ let(:expected_rows) do
376
+ [
377
+ [nil, nil, nil, nil, nil],
378
+ [nil, nil, nil, nil, nil],
379
+ ["Date", "Start time", "End time", "Pause", "Sum", "Comment", nil, nil],
380
+ [Date.new(2007, 5, 7), 9.25, 10.25, 0.0, 1.0, "Task 1"],
381
+ [Date.new(2007, 5, 7), 10.75, 12.50, 0.0, 1.75, "Task 1"],
382
+ [Date.new(2007, 5, 7), 18.0, 19.0, 0.0, 1.0, "Task 2"],
383
+ [Date.new(2007, 5, 8), 9.25, 10.25, 0.0, 1.0, "Task 2"],
384
+ [Date.new(2007, 5, 8), 14.5, 15.5, 0.0, 1.0, "Task 3"],
385
+ [Date.new(2007, 5, 8), 8.75, 9.25, 0.0, 0.5, "Task 3"],
386
+ [Date.new(2007, 5, 14), 21.75, 22.25, 0.0, 0.5, "Task 3"],
387
+ [Date.new(2007, 5, 14), 22.5, 23.0, 0.0, 0.5, "Task 3"],
388
+ [Date.new(2007, 5, 15), 11.75, 12.75, 0.0, 1.0, "Task 3"],
389
+ [Date.new(2007, 5, 7), 10.75, 10.75, 0.0, 0.0, "Task 1"],
390
+ [nil]
391
+ ]
392
+ end
393
+
394
+ it 'returns the expected result' do
395
+ index = 0
396
+ subject.each_row_streaming do |row|
397
+ expect(row.map(&:value)).to eq expected_rows[index]
398
+ index += 1
399
+ end
400
+ end
401
+
402
+ context 'with max_rows options' do
403
+ it 'returns the expected result' do
404
+ index = 0
405
+ subject.each_row_streaming(max_rows: 3) do |row|
406
+ expect(row.map(&:value)).to eq expected_rows[index]
407
+ index += 1
34
408
  end
409
+ # Expect this to get incremented one time more than max (because of the increment at the end of the block)
410
+ # but it should not be near expected_rows.size
411
+ expect(index).to eq 4
35
412
  end
36
413
  end
37
414
  end
@@ -2,18 +2,28 @@ require 'spec_helper'
2
2
 
3
3
  describe Roo::LibreOffice do
4
4
  describe '.new' do
5
- subject {
5
+ subject do
6
6
  Roo::LibreOffice.new('test/files/numbers1.ods')
7
- }
7
+ end
8
8
 
9
9
  it 'creates an instance' do
10
10
  expect(subject).to be_a(Roo::LibreOffice)
11
11
  end
12
12
  end
13
- end
14
13
 
15
- describe Roo::Libreoffice do
16
- it 'is an alias of LibreOffice' do
17
- expect(Roo::Libreoffice).to eq(Roo::LibreOffice)
14
+ describe '#sheets' do
15
+ let(:path) { 'test/files/hidden_sheets.ods' }
16
+
17
+ describe 'showing all sheets' do
18
+ it 'returns the expected result' do
19
+ expect(Roo::LibreOffice.new(path).sheets).to eq ["HiddenSheet1", "VisibleSheet1", "HiddenSheet2"]
20
+ end
21
+ end
22
+
23
+ describe 'only showing visible sheets' do
24
+ it 'returns the expected result' do
25
+ expect(Roo::LibreOffice.new(path, only_visible_sheets: true).sheets).to eq ["VisibleSheet1"]
26
+ end
27
+ end
18
28
  end
19
29
  end
@@ -2,9 +2,9 @@ require 'spec_helper'
2
2
 
3
3
  describe Roo::OpenOffice do
4
4
  describe '.new' do
5
- subject {
5
+ subject do
6
6
  Roo::OpenOffice.new('test/files/numbers1.ods')
7
- }
7
+ end
8
8
 
9
9
  it 'creates an instance' do
10
10
  expect(subject).to be_a(Roo::OpenOffice)
@@ -13,9 +13,3 @@ describe Roo::OpenOffice do
13
13
 
14
14
  # OpenOffice is an alias of LibreOffice. See libreoffice_spec.
15
15
  end
16
-
17
- describe Roo::Openoffice do
18
- it 'is an alias of LibreOffice' do
19
- expect(Roo::Openoffice).to eq(Roo::OpenOffice)
20
- end
21
- end
@@ -2,15 +2,34 @@ require 'spec_helper'
2
2
 
3
3
  describe Roo::Spreadsheet do
4
4
  describe '.open' do
5
+ context 'when the file name includes a space' do
6
+ let(:filename) { 'great scott.xlsx' }
7
+
8
+ it 'loads the proper type' do
9
+ expect(Roo::Excelx).to receive(:new).with(filename, {})
10
+ Roo::Spreadsheet.open(filename)
11
+ end
12
+ end
13
+
5
14
  context 'when the file extension is uppercase' do
6
- let(:filename) { 'file.XLS' }
15
+ let(:filename) { 'file.XLSX' }
7
16
 
8
17
  it 'loads the proper type' do
9
- expect(Roo::Excel).to receive(:new).with(filename, {})
18
+ expect(Roo::Excelx).to receive(:new).with(filename, {})
10
19
  Roo::Spreadsheet.open(filename)
11
20
  end
12
21
  end
13
22
 
23
+ context 'for a tempfile' do
24
+ let(:tempfile) { Tempfile.new('foo.csv') }
25
+ let(:filename) { tempfile.path }
26
+
27
+ it 'loads the proper type' do
28
+ expect(Roo::CSV).to receive(:new).with(filename, file_warning: :ignore).and_call_original
29
+ expect(Roo::Spreadsheet.open(tempfile, extension: :csv)).to be_a(Roo::CSV)
30
+ end
31
+ end
32
+
14
33
  context 'for a url' do
15
34
  context 'that is csv' do
16
35
  let(:filename) { 'http://example.com/file.csv?with=params#and=anchor' }
@@ -24,33 +43,42 @@ describe Roo::Spreadsheet do
24
43
 
25
44
  context 'for a csv file' do
26
45
  let(:filename) { 'file.csv' }
27
- let(:options) { {csv_options: {col_sep: '"'}} }
46
+ let(:options) { { csv_options: { col_sep: '"' } } }
28
47
 
29
- context 'with options' do
30
- it 'passes the options through' do
48
+ context 'with csv_options' do
49
+ it 'passes the csv_options through' do
31
50
  expect(Roo::CSV).to receive(:new).with(filename, options)
32
51
  Roo::Spreadsheet.open(filename, options)
33
52
  end
34
53
  end
35
54
  end
36
55
 
37
- context 'when the file extension' do
56
+ context 'with a file extension option' do
38
57
  let(:filename) { 'file.xls' }
39
58
 
40
- context "is xls" do
41
- let(:options) { { extension: "xls" } }
59
+ context ':xlsx' do
60
+ let(:options) { { extension: :xlsx } }
61
+
62
+ it 'loads with xls extension options' do
63
+ expect(Roo::Excelx).to receive(:new).with(filename, options)
64
+ Roo::Spreadsheet.open(filename, options)
65
+ end
66
+ end
67
+
68
+ context 'xlsx' do
69
+ let(:options) { { extension: 'xlsx' } }
42
70
 
43
71
  it 'loads with xls extension options' do
44
- expect(Roo::Excel).to receive(:new).with(filename, options)
72
+ expect(Roo::Excelx).to receive(:new).with(filename, options)
45
73
  Roo::Spreadsheet.open(filename, options)
46
74
  end
47
75
  end
48
76
 
49
- context "is .xls" do
50
- let(:options) { { extension: ".xls" } }
77
+ context '.xlsx' do
78
+ let(:options) { { extension: '.xlsx' } }
51
79
 
52
80
  it 'loads with .xls extension options' do
53
- expect(Roo::Excel).to receive(:new).with(filename, options)
81
+ expect(Roo::Excelx).to receive(:new).with(filename, options)
54
82
  Roo::Spreadsheet.open(filename, options)
55
83
  end
56
84
  end
@@ -0,0 +1,106 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe ::Roo::Utils do
4
+ subject { described_class }
5
+
6
+ context '#number_to_letter' do
7
+ ('A'..'Z').to_a.each_with_index do |letter, index|
8
+ it "should return '#{ letter }' when passed #{ index + 1 }" do
9
+ expect(described_class.number_to_letter(index + 1)).to eq(letter)
10
+ end
11
+ end
12
+
13
+ {
14
+ 27 => 'AA', 26*2 => 'AZ', 26*3 => 'BZ', 26**2 + 26 => 'ZZ', 26**2 + 27 => 'AAA',
15
+ 26**3 + 26**2 + 26 => 'ZZZ', 1.0 => 'A', 676 => 'YZ', 677 => 'ZA'
16
+ }.each do |key, value|
17
+ it "should return '#{value}' when passed #{key}" do
18
+ expect(described_class.number_to_letter(key)).to eq(value)
19
+ end
20
+ end
21
+ end
22
+
23
+ context '#letter_to_number' do
24
+ it "should give 1 for 'A' and 'a'" do
25
+ expect(described_class.letter_to_number('A')).to eq(1)
26
+ expect(described_class.letter_to_number('a')).to eq(1)
27
+ end
28
+
29
+ it "should give the correct value for 'Z'" do
30
+ expect(described_class.letter_to_number('Z')).to eq(26)
31
+ end
32
+
33
+ it "should give the correct value for 'AA' regardless of case mixing" do
34
+ %w(AA aA Aa aa).each do |key|
35
+ expect(described_class.letter_to_number(key)).to eq(27)
36
+ end
37
+ end
38
+
39
+ { 'AB' => 28, 'AZ' => 26*2, 'BZ' => 26*3, 'ZZ' => 26**2 + 26 }.each do |key, value|
40
+ it "should give the correct value for '#{key}'" do
41
+ expect(described_class.letter_to_number(key)).to eq(value)
42
+ end
43
+ end
44
+ end
45
+
46
+ context '.split_coordinate' do
47
+ it "returns the expected result" do
48
+ expect(described_class.split_coordinate('A1')).to eq [1, 1]
49
+ expect(described_class.split_coordinate('B2')).to eq [2, 2]
50
+ expect(described_class.split_coordinate('R2')).to eq [2, 18]
51
+ expect(described_class.split_coordinate('AR31')).to eq [31, 18 + 26]
52
+ end
53
+ end
54
+
55
+ context '.split_coord' do
56
+ it "returns the expected result" do
57
+ expect(described_class.split_coord('A1')).to eq ["A", 1]
58
+ expect(described_class.split_coord('B2')).to eq ["B", 2]
59
+ expect(described_class.split_coord('R2')).to eq ["R", 2]
60
+ expect(described_class.split_coord('AR31')).to eq ["AR", 31]
61
+ end
62
+
63
+ it "raises an error when appropriate" do
64
+ expect { described_class.split_coord('A') }.to raise_error(ArgumentError)
65
+ expect { described_class.split_coord('2') }.to raise_error(ArgumentError)
66
+ end
67
+ end
68
+
69
+
70
+ context '.num_cells_in_range' do
71
+ it "returns the expected result" do
72
+ expect(described_class.num_cells_in_range('A1:B2')).to eq 4
73
+ expect(described_class.num_cells_in_range('B2:E3')).to eq 8
74
+ expect(described_class.num_cells_in_range('R2:Z10')).to eq 81
75
+ expect(described_class.num_cells_in_range('AR31:AR32')).to eq 2
76
+ expect(described_class.num_cells_in_range('A1')).to eq 1
77
+ end
78
+
79
+ it "raises an error when appropriate" do
80
+ expect { described_class.num_cells_in_range('A1:B1:B2') }.to raise_error(ArgumentError)
81
+ end
82
+ end
83
+
84
+ context '.load_xml' do
85
+ it 'returns the expected result' do
86
+ expect(described_class.load_xml('test/files/sheet1.xml')).to be_a(Nokogiri::XML::Document)
87
+ expect(described_class.load_xml('test/files/sheet1.xml').
88
+ remove_namespaces!.xpath("/worksheet/dimension").map do |dim|
89
+ dim.attributes["ref"].value end.first).to eq "A1:B11"
90
+ end
91
+ end
92
+
93
+ context '.each_element' do
94
+ it 'returns the expected result' do
95
+ described_class.each_element('test/files/sheet1.xml', 'dimension') do |dim|
96
+ expect(dim.attributes["ref"].value).to eq "A1:B11"
97
+ end
98
+ rows = []
99
+ described_class.each_element('test/files/sheet1.xml', 'row') do |row|
100
+ rows << row
101
+ end
102
+ expect(rows.size).to eq 11
103
+ expect(rows[2].attributes["r"].value).to eq "3"
104
+ end
105
+ end
106
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,4 +1,5 @@
1
- require File.expand_path("../../lib/roo", __FILE__)
1
+ require 'simplecov'
2
+ require 'roo'
2
3
 
3
4
  require 'vcr'
4
5