roo 1.13.1 → 2.10.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (235) hide show
  1. checksums.yaml +5 -5
  2. data/.codeclimate.yml +17 -0
  3. data/.github/issue_template.md +16 -0
  4. data/.github/pull_request_template.md +14 -0
  5. data/.github/workflows/pull-request.yml +15 -0
  6. data/.github/workflows/ruby.yml +34 -0
  7. data/.gitignore +11 -0
  8. data/.rubocop.yml +186 -0
  9. data/.simplecov +4 -0
  10. data/CHANGELOG.md +702 -0
  11. data/Gemfile +18 -12
  12. data/Guardfile +23 -0
  13. data/LICENSE +5 -1
  14. data/README.md +328 -0
  15. data/Rakefile +23 -23
  16. data/examples/roo_soap_client.rb +28 -31
  17. data/examples/roo_soap_server.rb +4 -6
  18. data/examples/write_me.rb +9 -10
  19. data/lib/roo/base.rb +317 -504
  20. data/lib/roo/constants.rb +7 -0
  21. data/lib/roo/csv.rb +141 -113
  22. data/lib/roo/errors.rb +11 -0
  23. data/lib/roo/excelx/cell/base.rb +108 -0
  24. data/lib/roo/excelx/cell/boolean.rb +30 -0
  25. data/lib/roo/excelx/cell/date.rb +28 -0
  26. data/lib/roo/excelx/cell/datetime.rb +107 -0
  27. data/lib/roo/excelx/cell/empty.rb +20 -0
  28. data/lib/roo/excelx/cell/number.rb +99 -0
  29. data/lib/roo/excelx/cell/string.rb +19 -0
  30. data/lib/roo/excelx/cell/time.rb +44 -0
  31. data/lib/roo/excelx/cell.rb +110 -0
  32. data/lib/roo/excelx/comments.rb +55 -0
  33. data/lib/roo/excelx/coordinate.rb +19 -0
  34. data/lib/roo/excelx/extractor.rb +39 -0
  35. data/lib/roo/excelx/format.rb +71 -0
  36. data/lib/roo/excelx/images.rb +26 -0
  37. data/lib/roo/excelx/relationships.rb +33 -0
  38. data/lib/roo/excelx/shared.rb +39 -0
  39. data/lib/roo/excelx/shared_strings.rb +151 -0
  40. data/lib/roo/excelx/sheet.rb +151 -0
  41. data/lib/roo/excelx/sheet_doc.rb +257 -0
  42. data/lib/roo/excelx/styles.rb +64 -0
  43. data/lib/roo/excelx/workbook.rb +64 -0
  44. data/lib/roo/excelx.rb +407 -601
  45. data/lib/roo/font.rb +17 -0
  46. data/lib/roo/formatters/base.rb +15 -0
  47. data/lib/roo/formatters/csv.rb +84 -0
  48. data/lib/roo/formatters/matrix.rb +23 -0
  49. data/lib/roo/formatters/xml.rb +31 -0
  50. data/lib/roo/formatters/yaml.rb +40 -0
  51. data/lib/roo/helpers/default_attr_reader.rb +20 -0
  52. data/lib/roo/helpers/weak_instance_cache.rb +41 -0
  53. data/lib/roo/libre_office.rb +4 -0
  54. data/lib/roo/link.rb +34 -0
  55. data/lib/roo/open_office.rb +631 -0
  56. data/lib/roo/spreadsheet.rb +28 -23
  57. data/lib/roo/tempdir.rb +24 -0
  58. data/lib/roo/utils.rb +128 -0
  59. data/lib/roo/version.rb +3 -0
  60. data/lib/roo.rb +26 -24
  61. data/roo.gemspec +29 -202
  62. data/spec/helpers.rb +5 -0
  63. data/spec/lib/roo/base_spec.rb +291 -3
  64. data/spec/lib/roo/csv_spec.rb +38 -11
  65. data/spec/lib/roo/excelx/cell/time_spec.rb +15 -0
  66. data/spec/lib/roo/excelx/format_spec.rb +7 -6
  67. data/spec/lib/roo/excelx/relationships_spec.rb +43 -0
  68. data/spec/lib/roo/excelx/sheet_doc_spec.rb +11 -0
  69. data/spec/lib/roo/excelx_spec.rb +682 -6
  70. data/spec/lib/roo/libreoffice_spec.rb +16 -6
  71. data/spec/lib/roo/openoffice_spec.rb +30 -8
  72. data/spec/lib/roo/spreadsheet_spec.rb +60 -12
  73. data/spec/lib/roo/strict_spec.rb +43 -0
  74. data/spec/lib/roo/utils_spec.rb +119 -0
  75. data/spec/lib/roo/weak_instance_cache_spec.rb +92 -0
  76. data/spec/lib/roo_spec.rb +0 -0
  77. data/spec/spec_helper.rb +7 -6
  78. data/test/all_ss.rb +12 -11
  79. data/test/excelx/cell/test_attr_reader_default.rb +72 -0
  80. data/test/excelx/cell/test_base.rb +68 -0
  81. data/test/excelx/cell/test_boolean.rb +36 -0
  82. data/test/excelx/cell/test_date.rb +38 -0
  83. data/test/excelx/cell/test_datetime.rb +45 -0
  84. data/test/excelx/cell/test_empty.rb +18 -0
  85. data/test/excelx/cell/test_number.rb +90 -0
  86. data/test/excelx/cell/test_string.rb +48 -0
  87. data/test/excelx/cell/test_time.rb +30 -0
  88. data/test/excelx/test_coordinate.rb +51 -0
  89. data/test/formatters/test_csv.rb +136 -0
  90. data/test/formatters/test_matrix.rb +76 -0
  91. data/test/formatters/test_xml.rb +78 -0
  92. data/test/formatters/test_yaml.rb +20 -0
  93. data/test/helpers/test_accessing_files.rb +81 -0
  94. data/test/helpers/test_comments.rb +43 -0
  95. data/test/helpers/test_formulas.rb +9 -0
  96. data/test/helpers/test_labels.rb +103 -0
  97. data/test/helpers/test_sheets.rb +55 -0
  98. data/test/helpers/test_styles.rb +62 -0
  99. data/test/roo/test_base.rb +182 -0
  100. data/test/roo/test_csv.rb +88 -0
  101. data/test/roo/test_excelx.rb +360 -0
  102. data/test/roo/test_libre_office.rb +9 -0
  103. data/test/roo/test_open_office.rb +289 -0
  104. data/test/test_helper.rb +123 -59
  105. data/test/test_roo.rb +392 -2292
  106. metadata +153 -296
  107. data/CHANGELOG +0 -412
  108. data/Gemfile.lock +0 -78
  109. data/README.markdown +0 -126
  110. data/VERSION +0 -1
  111. data/lib/roo/excel.rb +0 -355
  112. data/lib/roo/excel2003xml.rb +0 -300
  113. data/lib/roo/google.rb +0 -292
  114. data/lib/roo/openoffice.rb +0 -496
  115. data/lib/roo/roo_rails_helper.rb +0 -83
  116. data/lib/roo/worksheet.rb +0 -18
  117. data/scripts/txt2html +0 -67
  118. data/spec/lib/roo/excel2003xml_spec.rb +0 -15
  119. data/spec/lib/roo/excel_spec.rb +0 -17
  120. data/spec/lib/roo/google_spec.rb +0 -64
  121. data/test/files/1900_base.xls +0 -0
  122. data/test/files/1900_base.xlsx +0 -0
  123. data/test/files/1904_base.xls +0 -0
  124. data/test/files/1904_base.xlsx +0 -0
  125. data/test/files/Bibelbund.csv +0 -3741
  126. data/test/files/Bibelbund.ods +0 -0
  127. data/test/files/Bibelbund.xls +0 -0
  128. data/test/files/Bibelbund.xlsx +0 -0
  129. data/test/files/Bibelbund.xml +0 -62518
  130. data/test/files/Bibelbund1.ods +0 -0
  131. data/test/files/Pfand_from_windows_phone.xlsx +0 -0
  132. data/test/files/bad_excel_date.xls +0 -0
  133. data/test/files/bbu.ods +0 -0
  134. data/test/files/bbu.xls +0 -0
  135. data/test/files/bbu.xlsx +0 -0
  136. data/test/files/bbu.xml +0 -152
  137. data/test/files/bode-v1.ods.zip +0 -0
  138. data/test/files/bode-v1.xls.zip +0 -0
  139. data/test/files/boolean.csv +0 -2
  140. data/test/files/boolean.ods +0 -0
  141. data/test/files/boolean.xls +0 -0
  142. data/test/files/boolean.xlsx +0 -0
  143. data/test/files/boolean.xml +0 -112
  144. data/test/files/borders.ods +0 -0
  145. data/test/files/borders.xls +0 -0
  146. data/test/files/borders.xlsx +0 -0
  147. data/test/files/borders.xml +0 -144
  148. data/test/files/bug-numbered-sheet-names.xlsx +0 -0
  149. data/test/files/bug-row-column-fixnum-float.xls +0 -0
  150. data/test/files/bug-row-column-fixnum-float.xml +0 -127
  151. data/test/files/comments.ods +0 -0
  152. data/test/files/comments.xls +0 -0
  153. data/test/files/comments.xlsx +0 -0
  154. data/test/files/csvtypes.csv +0 -1
  155. data/test/files/datetime.ods +0 -0
  156. data/test/files/datetime.xls +0 -0
  157. data/test/files/datetime.xlsx +0 -0
  158. data/test/files/datetime.xml +0 -142
  159. data/test/files/datetime_floatconv.xls +0 -0
  160. data/test/files/datetime_floatconv.xml +0 -148
  161. data/test/files/dreimalvier.ods +0 -0
  162. data/test/files/emptysheets.ods +0 -0
  163. data/test/files/emptysheets.xls +0 -0
  164. data/test/files/emptysheets.xlsx +0 -0
  165. data/test/files/emptysheets.xml +0 -105
  166. data/test/files/excel2003.xml +0 -21140
  167. data/test/files/false_encoding.xls +0 -0
  168. data/test/files/false_encoding.xml +0 -132
  169. data/test/files/file_item_error.xlsx +0 -0
  170. data/test/files/formula.ods +0 -0
  171. data/test/files/formula.xls +0 -0
  172. data/test/files/formula.xlsx +0 -0
  173. data/test/files/formula.xml +0 -134
  174. data/test/files/formula_parse_error.xls +0 -0
  175. data/test/files/formula_parse_error.xml +0 -1833
  176. data/test/files/formula_string_error.xlsx +0 -0
  177. data/test/files/html-escape.ods +0 -0
  178. data/test/files/link.xls +0 -0
  179. data/test/files/link.xlsx +0 -0
  180. data/test/files/matrix.ods +0 -0
  181. data/test/files/matrix.xls +0 -0
  182. data/test/files/named_cells.ods +0 -0
  183. data/test/files/named_cells.xls +0 -0
  184. data/test/files/named_cells.xlsx +0 -0
  185. data/test/files/no_spreadsheet_file.txt +0 -1
  186. data/test/files/numbers1.csv +0 -18
  187. data/test/files/numbers1.ods +0 -0
  188. data/test/files/numbers1.xls +0 -0
  189. data/test/files/numbers1.xlsx +0 -0
  190. data/test/files/numbers1.xml +0 -312
  191. data/test/files/only_one_sheet.ods +0 -0
  192. data/test/files/only_one_sheet.xls +0 -0
  193. data/test/files/only_one_sheet.xlsx +0 -0
  194. data/test/files/only_one_sheet.xml +0 -67
  195. data/test/files/paragraph.ods +0 -0
  196. data/test/files/paragraph.xls +0 -0
  197. data/test/files/paragraph.xlsx +0 -0
  198. data/test/files/paragraph.xml +0 -127
  199. data/test/files/prova.xls +0 -0
  200. data/test/files/ric.ods +0 -0
  201. data/test/files/simple_spreadsheet.ods +0 -0
  202. data/test/files/simple_spreadsheet.xls +0 -0
  203. data/test/files/simple_spreadsheet.xlsx +0 -0
  204. data/test/files/simple_spreadsheet.xml +0 -225
  205. data/test/files/simple_spreadsheet_from_italo.ods +0 -0
  206. data/test/files/simple_spreadsheet_from_italo.xls +0 -0
  207. data/test/files/simple_spreadsheet_from_italo.xml +0 -242
  208. data/test/files/so_datetime.csv +0 -7
  209. data/test/files/style.ods +0 -0
  210. data/test/files/style.xls +0 -0
  211. data/test/files/style.xlsx +0 -0
  212. data/test/files/style.xml +0 -154
  213. data/test/files/time-test.csv +0 -2
  214. data/test/files/time-test.ods +0 -0
  215. data/test/files/time-test.xls +0 -0
  216. data/test/files/time-test.xlsx +0 -0
  217. data/test/files/time-test.xml +0 -131
  218. data/test/files/type_excel.ods +0 -0
  219. data/test/files/type_excel.xlsx +0 -0
  220. data/test/files/type_excelx.ods +0 -0
  221. data/test/files/type_excelx.xls +0 -0
  222. data/test/files/type_openoffice.xls +0 -0
  223. data/test/files/type_openoffice.xlsx +0 -0
  224. data/test/files/whitespace.ods +0 -0
  225. data/test/files/whitespace.xls +0 -0
  226. data/test/files/whitespace.xlsx +0 -0
  227. data/test/files/whitespace.xml +0 -184
  228. data/test/rm_sub_test.rb +0 -12
  229. data/test/rm_test.rb +0 -7
  230. data/test/test_generic_spreadsheet.rb +0 -259
  231. data/website/index.html +0 -385
  232. data/website/index.txt +0 -423
  233. data/website/javascripts/rounded_corners_lite.inc.js +0 -285
  234. data/website/stylesheets/screen.css +0 -130
  235. data/website/template.rhtml +0 -48
@@ -1,23 +1,699 @@
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
+
9
+ describe 'Constants' do
10
+ describe 'ERROR_VALUES' do
11
+ it 'returns all possible errorr values' do
12
+ expect(described_class::ERROR_VALUES).to eq(%w(#N/A #REF! #NAME? #DIV/0! #NULL! #VALUE! #NUM!).to_set)
13
+ end
14
+
15
+ it 'is a set' do
16
+ expect(described_class::ERROR_VALUES).to be_an_instance_of(Set)
17
+ end
18
+ end
19
+ end
20
+
4
21
  describe '.new' do
5
- subject {
6
- Roo::Excelx.new('test/files/numbers1.xlsx')
7
- }
22
+ let(:path) { 'test/files/numeric-link.xlsx' }
8
23
 
9
24
  it 'creates an instance' do
10
25
  expect(subject).to be_a(Roo::Excelx)
11
26
  end
12
27
 
13
28
  context 'given a file with missing rels' do
14
- subject {
15
- Roo::Excelx.new('test/files/file_item_error.xlsx')
16
- }
29
+ let(:path) { 'test/files/file_item_error.xlsx' }
17
30
 
18
31
  it 'creates an instance' do
19
32
  expect(subject).to be_a(Roo::Excelx)
20
33
  end
21
34
  end
35
+
36
+ context 'with more cells than specified max' do
37
+ let(:path) { 'test/files/only_one_sheet.xlsx' }
38
+
39
+ it 'raises an appropriate error' do
40
+ expect { Roo::Excelx.new(path, cell_max: 1) }.to raise_error(Roo::Excelx::ExceedsMaxError)
41
+ end
42
+ end
43
+
44
+ context 'with fewer cells than specified max' do
45
+ let(:path) { 'test/files/only_one_sheet.xlsx' }
46
+
47
+ it 'creates an instance' do
48
+ expect(Roo::Excelx.new(path, cell_max: 100)).to be_a(Roo::Excelx)
49
+ end
50
+ end
51
+
52
+ context 'file path is a Pathname' do
53
+ let(:path) { Pathname.new('test/files/file_item_error.xlsx') }
54
+
55
+ it 'creates an instance' do
56
+ expect(subject).to be_a(Roo::Excelx)
57
+ end
58
+ end
59
+ end
60
+
61
+ describe '#cell' do
62
+ context 'for a link cell' do
63
+ context 'with numeric contents' do
64
+ let(:path) { 'test/files/numeric-link.xlsx' }
65
+
66
+ subject do
67
+ xlsx.cell('A', 1)
68
+ end
69
+
70
+ it 'returns a link with the number as a string value' do
71
+ expect(subject).to be_a(Roo::Link)
72
+ # FIXME: Because Link inherits from String, it is a String,
73
+ # But in theory, it shouldn't have to be a String.
74
+ # NOTE: This test is broken becase Cell::Numeric formats numbers
75
+ # more intelligently.
76
+ # expect(subject).to eq('8675309.0')
77
+ end
78
+ end
79
+ end
80
+
81
+ context 'for a non-existent cell' do
82
+ let(:path) { 'test/files/numeric-link.xlsx' }
83
+ it 'return nil' do
84
+ expect(xlsx.cell('AAA', 999)).to eq nil
85
+ end
86
+ end
87
+ end
88
+
89
+ describe 'for a workbook with hidden sheets' do
90
+ let(:path) { 'test/files/hidden_sheets.xlsx' }
91
+
92
+ it 'returns the cell contents from the visible sheet' do
93
+ expect(Roo::Excelx.new(path, only_visible_sheets: true).cell('A', 1)).to eq "visible sheet 1"
94
+ end
95
+ end
96
+
97
+ describe '#parse' do
98
+ let(:path) { 'test/files/numeric-link.xlsx' }
99
+
100
+ context 'with a columns hash' do
101
+ context 'when not present in the sheet' do
102
+ it 'does not raise' do
103
+ expect do
104
+ xlsx.sheet(0).parse(
105
+ this: 'This',
106
+ that: 'That'
107
+ )
108
+ end.to raise_error(Roo::HeaderRowNotFoundError)
109
+ end
110
+ end
111
+ end
112
+ end
113
+
114
+ describe '#parse_with_clean_option' do
115
+ let(:path) { 'test/files/parse_with_clean_option.xlsx' }
116
+ let(:options) { {clean: true} }
117
+
118
+ context 'with clean: true' do
119
+
120
+ it 'does not raise' do
121
+ expect do
122
+ xlsx.parse(options)
123
+ end.not_to raise_error
124
+ end
125
+ end
126
+ end
127
+
128
+ describe '#parse_unicode_with_clean_option' do
129
+ let(:path) { 'test/files/parse_clean_with_unicode.xlsx' }
130
+ let(:options) { {clean: true, name: 'Name'} }
131
+
132
+ context 'with clean: true' do
133
+ it 'returns a non empty string' do
134
+ expect(xlsx.parse(options).last[:name]).to eql('凯')
135
+ end
136
+ end
137
+ end
138
+
139
+ describe '#sheets' do
140
+ let(:path) { 'test/files/numbers1.xlsx' }
141
+
142
+ it 'returns the expected result' do
143
+ expect(subject.sheets).to eq ["Tabelle1", "Name of Sheet 2", "Sheet3", "Sheet4", "Sheet5"]
144
+ end
145
+
146
+ describe 'only showing visible sheets' do
147
+ let(:path) { 'test/files/hidden_sheets.xlsx' }
148
+
149
+ it 'returns the expected result' do
150
+ expect(Roo::Excelx.new(path, only_visible_sheets: true).sheets).to eq ["VisibleSheet1"]
151
+ end
152
+ end
153
+ end
154
+
155
+ describe '#sheet_for' do
156
+ let(:path) { 'test/files/numbers1.xlsx' }
157
+
158
+ # This is kinda gross
159
+ it 'returns the expected result' do
160
+ expect(subject.sheet_for("Tabelle1").instance_variable_get("@name")).to eq "Tabelle1"
161
+ end
162
+
163
+ it 'returns the expected result when passed a number' do
164
+ expect(subject.sheet_for(0).instance_variable_get("@name")).to eq "Tabelle1"
165
+ end
166
+
167
+ it 'returns the expected result when passed a number that is not the first sheet' do
168
+ expect(subject.sheet_for(1).instance_variable_get("@name")).to eq "Name of Sheet 2"
169
+ end
170
+
171
+ it "should raise an error if passed a sheet that does not exist as an integer" do
172
+ expect { subject.sheet_for(10) }.to raise_error RangeError
173
+ end
174
+
175
+ it "should raise an error if passed a sheet that does not exist as a string" do
176
+ expect { subject.sheet_for("does_not_exist") }.to raise_error RangeError
177
+ end
178
+ end
179
+
180
+ describe '#row' do
181
+ let(:path) { 'test/files/numbers1.xlsx' }
182
+
183
+ it 'returns the expected result' do
184
+ expect(subject.row(1, "Sheet5")).to eq [1.0, 5.0, 5.0, nil, nil]
185
+ end
186
+ end
187
+
188
+ describe '#column' do
189
+ let(:path) { 'test/files/numbers1.xlsx' }
190
+
191
+ it 'returns the expected result' do
192
+ expect(subject.column(1, "Sheet5")).to eq [1.0, 2.0, 3.0, Date.new(2007,11,21), 42.0, "ABC"]
193
+ end
194
+ end
195
+
196
+ describe '#first_row' do
197
+ let(:path) { 'test/files/numbers1.xlsx' }
198
+
199
+ it 'returns the expected result' do
200
+ expect(subject.first_row("Sheet5")).to eq 1
201
+ end
202
+ end
203
+
204
+ describe '#last_row' do
205
+ let(:path) { 'test/files/numbers1.xlsx' }
206
+
207
+ it 'returns the expected result' do
208
+ expect(subject.last_row("Sheet5")).to eq 6
209
+ end
210
+ end
211
+
212
+ describe '#first_column' do
213
+ let(:path) { 'test/files/numbers1.xlsx' }
214
+
215
+ it 'returns the expected result' do
216
+ expect(subject.first_column("Sheet5")).to eq 1
217
+ end
218
+ end
219
+
220
+ describe '#last_column' do
221
+ let(:path) { 'test/files/numbers1.xlsx' }
222
+
223
+ it 'returns the expected result' do
224
+ expect(subject.last_column("Sheet5")).to eq 5
225
+ end
226
+ end
227
+
228
+ describe '#set' do
229
+ before do
230
+ subject.set(1, 2, "Foo", "Sheet5")
231
+ end
232
+
233
+ let(:path) { 'test/files/numbers1.xlsx' }
234
+ let(:cell) { subject.cell(1, 2, "Sheet5") }
235
+
236
+ it 'returns the expected result' do
237
+ expect(cell).to eq "Foo"
238
+ end
239
+ end
240
+
241
+ describe '#formula' do
242
+ let(:path) { 'test/files/formula.xlsx' }
243
+
244
+ it 'returns the expected result' do
245
+ expect(subject.formula(1, 1, "Sheet1")).to eq nil
246
+ expect(subject.formula(7, 2, "Sheet1")).to eq "SUM($A$1:B6)"
247
+ expect(subject.formula(1000, 2000, "Sheet1")).to eq nil
248
+ end
249
+ end
250
+
251
+ describe '#formula?' do
252
+ let(:path) { 'test/files/formula.xlsx' }
253
+
254
+ it 'returns the expected result' do
255
+ expect(subject.formula?(1, 1, "Sheet1")).to eq false
256
+ expect(subject.formula?(7, 2, "Sheet1")).to eq true
257
+ expect(subject.formula?(1000, 2000, "Sheet1")).to eq false
258
+ end
259
+ end
260
+
261
+ describe '#formulas' do
262
+ let(:path) { 'test/files/formula.xlsx' }
263
+
264
+ it 'returns the expected result' do
265
+ expect(subject.formulas("Sheet1")).to eq [[7, 1, "SUM(A1:A6)"], [7, 2, "SUM($A$1:B6)"]]
266
+ end
267
+ end
268
+
269
+ describe '#font' do
270
+ let(:path) { 'test/files/style.xlsx' }
271
+
272
+ it 'returns the expected result' do
273
+ expect(subject.font(1, 1).bold?).to eq true
274
+ expect(subject.font(1, 1).italic?).to eq false
275
+ expect(subject.font(1, 1).underline?).to eq false
276
+
277
+ expect(subject.font(7, 1).bold?).to eq false
278
+ expect(subject.font(7, 1).italic?).to eq true
279
+ expect(subject.font(7, 1).underline?).to eq true
280
+ expect(subject.font(1000, 2000)).to eq nil
281
+ end
282
+ end
283
+
284
+ describe '#celltype' do
285
+ let(:path) { 'test/files/numbers1.xlsx' }
286
+
287
+ it 'returns the expected result' do
288
+ expect(subject.celltype(1, 1, "Sheet4")).to eq :date
289
+ expect(subject.celltype(1, 2, "Sheet4")).to eq :float
290
+ expect(subject.celltype(6, 2, "Sheet5")).to eq :string
291
+ expect(subject.celltype(1000, 2000, "Sheet5")).to eq nil
292
+ end
293
+ end
294
+
295
+ describe '#excelx_type' do
296
+ let(:path) { 'test/files/numbers1.xlsx' }
297
+
298
+ it 'returns the expected result' do
299
+ expect(subject.excelx_type(1, 1, "Sheet5")).to eq [:numeric_or_formula, "General"]
300
+ expect(subject.excelx_type(6, 2, "Sheet5")).to eq :string
301
+ expect(subject.excelx_type(1000, 2000, "Sheet5")).to eq nil
302
+ end
303
+ end
304
+
305
+ # FIXME: IMO, these tests don't provide much value. Under what circumstances
306
+ # will a user require the "index" value for the shared strings table?
307
+ # Excel value should be the raw unformatted value for the cell.
308
+ describe '#excelx_value' do
309
+ let(:path) { 'test/files/numbers1.xlsx' }
310
+
311
+ it 'returns the expected result' do
312
+ # These values are the index in the shared strings table, might be a better
313
+ # way to get these rather than hardcoding.
314
+
315
+ # expect(subject.excelx_value(1, 1, "Sheet5")).to eq "1" # passes by accident
316
+ # expect(subject.excelx_value(6, 2, "Sheet5")).to eq "16"
317
+ # expect(subject.excelx_value(6000, 2000, "Sheet5")).to eq nil
318
+ end
319
+ end
320
+
321
+ describe '#formatted_value' do
322
+ context 'contains zero-padded numbers' do
323
+ let(:path) { 'test/files/zero-padded-number.xlsx' }
324
+
325
+ it 'returns a zero-padded number' do
326
+ expect(subject.formatted_value(4, 1)).to eq '05010'
327
+ end
328
+ end
329
+
330
+ context 'contains US currency' do
331
+ let(:path) { 'test/files/currency-us.xlsx' }
332
+
333
+ it 'returns a zero-padded number' do
334
+ expect(subject.formatted_value(4, 1)).to eq '$20.51'
335
+ end
336
+ end
337
+
338
+ context 'contains euro currency' do
339
+ let(:path) { 'test/files/currency-euro.xlsx' }
340
+
341
+ it 'returns a zero-padded number' do
342
+ expect(subject.formatted_value(4, 1)).to eq '€20.51'
343
+ end
344
+ end
345
+
346
+ context 'contains uk currency' do
347
+ let(:path) { 'test/files/currency-uk.xlsx' }
348
+
349
+ it 'returns a zero-padded number' do
350
+ expect(subject.formatted_value(4, 1)).to eq '£20.51'
351
+ end
352
+ end
353
+ end
354
+
355
+ describe '#row' do
356
+ context 'integers with leading zero'
357
+ let(:path) { 'test/files/number_with_zero_prefix.xlsx' }
358
+
359
+ it 'returns base 10 integer' do
360
+ (1..50).each do |row_index|
361
+ range_start = (row_index - 1) * 20 + 1
362
+ expect(subject.row(row_index)).to eq (range_start..(range_start+19)).to_a
363
+ end
364
+ end
365
+ end
366
+
367
+ describe '#excelx_format' do
368
+ let(:path) { 'test/files/style.xlsx' }
369
+
370
+ it 'returns the expected result' do
371
+ # These are the index of the style for a given document
372
+ # might be more reliable way to get this info.
373
+ expect(subject.excelx_format(1, 1)).to eq "General"
374
+ expect(subject.excelx_format(2, 2)).to eq "0.00"
375
+ expect(subject.excelx_format(5000, 1000)).to eq nil
376
+ end
377
+ end
378
+
379
+ describe '#empty?' do
380
+ let(:path) { 'test/files/style.xlsx' }
381
+
382
+ it 'returns the expected result' do
383
+ # These are the index of the style for a given document
384
+ # might be more reliable way to get this info.
385
+ expect(subject.empty?(1, 1)).to eq false
386
+ expect(subject.empty?(13, 1)).to eq true
387
+ end
388
+ end
389
+
390
+ describe '#label' do
391
+ let(:path) { 'test/files/named_cells.xlsx' }
392
+
393
+ it 'returns the expected result' do
394
+ expect(subject.label("berta")).to eq [4, 2, "Sheet1"]
395
+ expect(subject.label("dave")).to eq [nil, nil, nil]
396
+ end
397
+ end
398
+
399
+ describe '#labels' do
400
+ let(:path) { 'test/files/named_cells.xlsx' }
401
+
402
+ it 'returns the expected result' do
403
+ expect(subject.labels).to eq [["anton", [5, 3, "Sheet1"]], ["berta", [4, 2, "Sheet1"]], ["caesar", [7, 2, "Sheet1"]]]
404
+ end
405
+ end
406
+
407
+ describe '#hyperlink?' do
408
+ let(:path) { 'test/files/link.xlsx' }
409
+
410
+ it 'returns the expected result' do
411
+ expect(subject.hyperlink?(1, 1)).to eq true
412
+ expect(subject.hyperlink?(1, 2)).to eq false
413
+ end
414
+
415
+ context 'defined on cell range' do
416
+ let(:path) { 'test/files/cell-range-link.xlsx' }
417
+
418
+ it 'returns the expected result' do
419
+ [[false]*3, *[[true, true, false]]*4, [false]*3].each.with_index(1) do |row, row_index|
420
+ row.each.with_index(1) do |value, col_index|
421
+ expect(subject.hyperlink?(row_index, col_index)).to eq(value)
422
+ end
423
+ end
424
+ end
425
+ end
426
+ end
427
+
428
+ describe '#hyperlink' do
429
+ context 'defined on cell range' do
430
+ let(:path) { 'test/files/cell-range-link.xlsx' }
431
+
432
+ it 'returns the expected result' do
433
+ link = "http://www.google.com"
434
+ [[nil]*3, *[[link, link, nil]]*4, [nil]*3].each.with_index(1) do |row, row_index|
435
+ row.each.with_index(1) do |value, col_index|
436
+ expect(subject.hyperlink(row_index, col_index)).to eq(value)
437
+ end
438
+ end
439
+ end
440
+ end
441
+
442
+ context 'without location' do
443
+ let(:path) { 'test/files/link.xlsx' }
444
+
445
+ it 'returns the expected result' do
446
+ expect(subject.hyperlink(1, 1)).to eq "http://www.google.com"
447
+ expect(subject.hyperlink(1, 2)).to eq nil
448
+ end
449
+ end
450
+
451
+ context 'with location' do
452
+ let(:path) { 'test/files/link_with_location.xlsx' }
453
+
454
+ it 'returns the expected result' do
455
+ expect(subject.hyperlink(1, 1)).to eq "http://www.google.com/#hey"
456
+ expect(subject.hyperlink(1, 2)).to eq nil
457
+ end
458
+ end
459
+ end
460
+
461
+ describe '#comment' do
462
+ let(:path) { 'test/files/comments.xlsx' }
463
+
464
+ it 'returns the expected result' do
465
+ expect(subject.comment(4, 2)).to eq "Kommentar fuer B4"
466
+ expect(subject.comment(1, 2)).to eq nil
467
+ end
468
+ end
469
+
470
+ describe '#comment?' do
471
+ let(:path) { 'test/files/comments.xlsx' }
472
+
473
+ it 'returns the expected result' do
474
+ expect(subject.comment?(4, 2)).to eq true
475
+ expect(subject.comment?(1, 2)).to eq false
476
+ end
477
+ end
478
+
479
+ describe '#comments' do
480
+ let(:path) { 'test/files/comments.xlsx' }
481
+
482
+ it 'returns the expected result' do
483
+ expect(subject.comments).to eq [[4, 2, "Kommentar fuer B4"], [5, 2, "Kommentar fuer B5"]]
484
+ end
485
+ end
486
+
487
+ # nil, nil, nil, nil, nil
488
+ # nil, nil, nil, nil, nil
489
+ # Date Start time End time Pause Sum Comment
490
+ # 2007-05-07 9.25 10.25 0 1 Task 1
491
+ # 2007-05-07 10.75 12.50 0 1.75 Task 1
492
+ # 2007-05-07 18.00 19.00 0 1 Task 2
493
+ # 2007-05-08 9.25 10.25 0 1 Task 2
494
+ # 2007-05-08 14.50 15.50 0 1 Task 3
495
+ # 2007-05-08 8.75 9.25 0 0.5 Task 3
496
+ # 2007-05-14 21.75 22.25 0 0.5 Task 3
497
+ # 2007-05-14 22.50 23.00 0 0.5 Task 3
498
+ # 2007-05-15 11.75 12.75 0 1 Task 3
499
+ # 2007-05-07 10.75 10.75 0 0 Task 1
500
+ # nil
501
+ describe '#each_row_streaming' do
502
+ let(:path) { 'test/files/simple_spreadsheet.xlsx' }
503
+
504
+ let(:expected_rows) do
505
+ [
506
+ [nil, nil, nil, nil, nil],
507
+ [nil, nil, nil, nil, nil],
508
+ ["Date", "Start time", "End time", "Pause", "Sum", "Comment", nil, nil],
509
+ [Date.new(2007, 5, 7), 9.25, 10.25, 0.0, 1.0, "Task 1"],
510
+ [Date.new(2007, 5, 7), 10.75, 12.50, 0.0, 1.75, "Task 1"],
511
+ [Date.new(2007, 5, 7), 18.0, 19.0, 0.0, 1.0, "Task 2"],
512
+ [Date.new(2007, 5, 8), 9.25, 10.25, 0.0, 1.0, "Task 2"],
513
+ [Date.new(2007, 5, 8), 14.5, 15.5, 0.0, 1.0, "Task 3"],
514
+ [Date.new(2007, 5, 8), 8.75, 9.25, 0.0, 0.5, "Task 3"],
515
+ [Date.new(2007, 5, 14), 21.75, 22.25, 0.0, 0.5, "Task 3"],
516
+ [Date.new(2007, 5, 14), 22.5, 23.0, 0.0, 0.5, "Task 3"],
517
+ [Date.new(2007, 5, 15), 11.75, 12.75, 0.0, 1.0, "Task 3"],
518
+ [Date.new(2007, 5, 7), 10.75, 10.75, 0.0, 0.0, "Task 1"],
519
+ [nil]
520
+ ]
521
+ end
522
+
523
+ it 'returns the expected result' do
524
+ index = 0
525
+ subject.each_row_streaming do |row|
526
+ expect(row.map(&:value)).to eq expected_rows[index]
527
+ index += 1
528
+ end
529
+ end
530
+
531
+ context 'with max_rows options' do
532
+ it 'returns the expected result' do
533
+ index = 0
534
+ subject.each_row_streaming(max_rows: 3) do |row|
535
+ expect(row.map(&:value)).to eq expected_rows[index]
536
+ index += 1
537
+ end
538
+ # Expect this to get incremented one time more than max (because of the increment at the end of the block)
539
+ # but it should not be near expected_rows.size
540
+ expect(index).to eq 4
541
+ end
542
+ end
543
+
544
+ context 'with offset option' do
545
+ let(:offset) { 3 }
546
+
547
+ it 'returns the expected result' do
548
+ index = 0
549
+ subject.each_row_streaming(offset: offset) do |row|
550
+ expect(row.map(&:value)).to eq expected_rows[index + offset]
551
+ index += 1
552
+ end
553
+ expect(index).to eq 11
554
+ end
555
+ end
556
+
557
+ context 'with offset and max_rows options' do
558
+ let(:offset) { 3 }
559
+ let(:max_rows) { 3 }
560
+
561
+ it 'returns the expected result' do
562
+ index = 0
563
+ subject.each_row_streaming(offset: offset, max_rows: max_rows) do |row|
564
+ expect(row.map(&:value)).to eq expected_rows[index + offset]
565
+ index += 1
566
+ end
567
+ expect(index).to eq 4
568
+ end
569
+ end
570
+
571
+ context 'without block passed' do
572
+ it 'returns an enumerator' do
573
+ expect(subject.each_row_streaming).to be_a(Enumerator)
574
+ end
575
+ end
576
+ end
577
+
578
+ describe '#html_strings' do
579
+ describe "HTML Parsing Enabling" do
580
+ let(:path) { 'test/files/html_strings_formatting.xlsx' }
581
+
582
+ it 'returns the expected result' do
583
+ expect(subject.excelx_value(1, 1, "Sheet1")).to eq("This has no formatting.")
584
+ expect(subject.excelx_value(2, 1, "Sheet1")).to eq("<html>This has<b> bold </b>formatting.</html>")
585
+ expect(subject.excelx_value(2, 2, "Sheet1")).to eq("<html>This has <i>italics</i> formatting.</html>")
586
+ expect(subject.excelx_value(2, 3, "Sheet1")).to eq("<html>This has <u>underline</u> format.</html>")
587
+ expect(subject.excelx_value(2, 4, "Sheet1")).to eq("<html>Superscript. x<sup>123</sup></html>")
588
+ expect(subject.excelx_value(2, 5, "Sheet1")).to eq("<html>SubScript. T<sub>j</sub></html>")
589
+
590
+ expect(subject.excelx_value(3, 1, "Sheet1")).to eq("<html>Bold, italics <b><i>together</i></b>.</html>")
591
+ expect(subject.excelx_value(3, 2, "Sheet1")).to eq("<html>Bold, Underline <b><u>together</u></b>.</html>")
592
+ expect(subject.excelx_value(3, 3, "Sheet1")).to eq("<html>Bold, Superscript. <b>x</b><sup><b>N</b></sup></html>")
593
+ expect(subject.excelx_value(3, 4, "Sheet1")).to eq("<html>Bold, Subscript. <b>T</b><sub><b>abc</b></sub></html>")
594
+ expect(subject.excelx_value(3, 5, "Sheet1")).to eq("<html>Italics, Underline <i><u>together</u></i>.</html>")
595
+ expect(subject.excelx_value(3, 6, "Sheet1")).to eq("<html>Italics, Superscript. <i>X</i><sup><i>abc</i></sup></html>")
596
+ expect(subject.excelx_value(3, 7, "Sheet1")).to eq("<html>Italics, Subscript. <i>B</i><sub><i>efg</i></sub></html>")
597
+ expect(subject.excelx_value(4, 1, "Sheet1")).to eq("<html>Bold, italics underline,<b><i><u> together</u></i></b>.</html>")
598
+ expect(subject.excelx_value(4, 2, "Sheet1")).to eq("<html>Bold, italics, superscript. <b>X</b><sup><b><i>abc</i></b></sup><b><i>123</i></b></html>")
599
+ expect(subject.excelx_value(4, 3, "Sheet1")).to eq("<html>Bold, Italics, subscript. <b><i>Mg</i></b><sub><b><i>ha</i></b></sub><b><i>2</i></b></html>")
600
+ expect(subject.excelx_value(4, 4, "Sheet1")).to eq("<html>Bold, Underline, superscript. <b><u>AB</u></b><sup><b><u>C12</u></b></sup><b><u>3</u></b></html>")
601
+ expect(subject.excelx_value(4, 5, "Sheet1")).to eq("<html>Bold, Underline, subscript. <b><u>Good</u></b><sub><b><u>XYZ</u></b></sub></html>")
602
+ expect(subject.excelx_value(4, 6, "Sheet1")).to eq("<html>Italics, Underline, superscript. <i><u>Up</u></i><sup><i><u>swing</u></i></sup></html>")
603
+ expect(subject.excelx_value(4, 7, "Sheet1")).to eq("<html>Italics, Underline, subscript. <i><u>T</u></i><sub><i><u>swing</u></i></sub></html>")
604
+ expect(subject.excelx_value(5, 1, "Sheet1")).to eq("<html>Bold, italics, underline, superscript. <b><i><u>GHJK</u></i></b><sup><b><i><u>190</u></i></b></sup><b><i><u>4</u></i></b></html>")
605
+ expect(subject.excelx_value(5, 2, "Sheet1")).to eq("<html>Bold, italics, underline, subscript. <b><i><u>Mike</u></i></b><sub><b><i><u>drop</u></i></b></sub></html>")
606
+ expect(subject.excelx_value(6, 1, "Sheet1")).to eq("See that regular html tags do not create html tags.\n<ol>\n <li> Denver Broncos </li>\n <li> Carolina Panthers </li>\n <li> New England Patriots</li>\n <li>Arizona Panthers</li>\n</ol>")
607
+ expect(subject.excelx_value(7, 1, "Sheet1")).to eq("<html>Does create html tags when formatting is used..\n<ol>\n <li> <b>Denver Broncos</b> </li>\n <li> <i>Carolina Panthers </i></li>\n <li> <u>New England Patriots</u></li>\n <li>Arizona Panthers</li>\n</ol></html>")
608
+ end
609
+ end
610
+ end
611
+
612
+ describe '_x000D_' do
613
+ let(:path) { 'test/files/x000D.xlsx' }
614
+ it 'does not contain _x000D_' do
615
+ expect(subject.cell(2, 9)).not_to include('_x000D_')
616
+ end
617
+ end
618
+
619
+ describe 'opening a file with a chart sheet' do
620
+ let(:path) { 'test/files/chart_sheet.xlsx' }
621
+ it 'should not raise' do
622
+ expect{ subject }.to_not raise_error
623
+ end
624
+ end
625
+
626
+ describe 'opening a file with white space in the styles.xml' do
627
+ let(:path) { 'test/files/style_nodes_with_white_spaces.xlsx' }
628
+ subject(:xlsx) do
629
+ Roo::Spreadsheet.open(path, expand_merged_ranges: true, extension: :xlsx)
630
+ end
631
+ it 'should properly recognize formats' do
632
+ expect(subject.sheet(0).excelx_format(2,1)).to eq 'm/d/yyyy" "h:mm:ss" "AM/PM'
633
+ end
634
+ end
635
+
636
+ describe 'opening a file with filters' do
637
+ let(:path) { 'test/files/wrong_coordinates.xlsx' }
638
+ subject(:xlsx) do
639
+ Roo::Spreadsheet.open(path)
640
+ end
641
+
642
+ it 'should properly extract defined_names' do
643
+ expect(subject.sheet(0).workbook.defined_names.length).to eq(1)
644
+ end
645
+ end
646
+
647
+ describe 'images' do
648
+ let(:path) { 'test/files/images.xlsx' }
649
+
650
+ it 'returns array of images from default sheet' do
651
+ expect(subject.images).to be_kind_of(Array)
652
+ expect(subject.images.size).to eql(19)
653
+ end
654
+
655
+ it 'returns empty array if there is no images on the sheet' do
656
+ expect(subject.images("Sheet2")).to eql([])
657
+ end
658
+ end
659
+ end
660
+
661
+ describe 'Roo::Excelx with options set' do
662
+ subject(:xlsx) do
663
+ Roo::Excelx.new(path, disable_html_wrapper: true)
664
+ end
665
+
666
+ describe '#html_strings' do
667
+ describe "HTML Parsing Disabled" do
668
+ let(:path) { 'test/files/html_strings_formatting.xlsx' }
669
+
670
+ it 'returns the expected result' do
671
+ expect(subject.excelx_value(1, 1, "Sheet1")).to eq("This has no formatting.")
672
+ expect(subject.excelx_value(2, 1, "Sheet1")).to eq("This has bold formatting.")
673
+ expect(subject.excelx_value(2, 2, "Sheet1")).to eq("This has italics formatting.")
674
+ expect(subject.excelx_value(2, 3, "Sheet1")).to eq("This has underline format.")
675
+ expect(subject.excelx_value(2, 4, "Sheet1")).to eq("Superscript. x123")
676
+ expect(subject.excelx_value(2, 5, "Sheet1")).to eq("SubScript. Tj")
677
+
678
+ expect(subject.excelx_value(3, 1, "Sheet1")).to eq("Bold, italics together.")
679
+ expect(subject.excelx_value(3, 2, "Sheet1")).to eq("Bold, Underline together.")
680
+ expect(subject.excelx_value(3, 3, "Sheet1")).to eq("Bold, Superscript. xN")
681
+ expect(subject.excelx_value(3, 4, "Sheet1")).to eq("Bold, Subscript. Tabc")
682
+ expect(subject.excelx_value(3, 5, "Sheet1")).to eq("Italics, Underline together.")
683
+ expect(subject.excelx_value(3, 6, "Sheet1")).to eq("Italics, Superscript. Xabc")
684
+ expect(subject.excelx_value(3, 7, "Sheet1")).to eq("Italics, Subscript. Befg")
685
+ expect(subject.excelx_value(4, 1, "Sheet1")).to eq("Bold, italics underline, together.")
686
+ expect(subject.excelx_value(4, 2, "Sheet1")).to eq("Bold, italics, superscript. Xabc123")
687
+ expect(subject.excelx_value(4, 3, "Sheet1")).to eq("Bold, Italics, subscript. Mgha2")
688
+ expect(subject.excelx_value(4, 4, "Sheet1")).to eq("Bold, Underline, superscript. ABC123")
689
+ expect(subject.excelx_value(4, 5, "Sheet1")).to eq("Bold, Underline, subscript. GoodXYZ")
690
+ expect(subject.excelx_value(4, 6, "Sheet1")).to eq("Italics, Underline, superscript. Upswing")
691
+ expect(subject.excelx_value(4, 7, "Sheet1")).to eq("Italics, Underline, subscript. Tswing")
692
+ expect(subject.excelx_value(5, 1, "Sheet1")).to eq("Bold, italics, underline, superscript. GHJK1904")
693
+ expect(subject.excelx_value(5, 2, "Sheet1")).to eq("Bold, italics, underline, subscript. Mikedrop")
694
+ expect(subject.excelx_value(6, 1, "Sheet1")).to eq("See that regular html tags do not create html tags.\n<ol>\n <li> Denver Broncos </li>\n <li> Carolina Panthers </li>\n <li> New England Patriots</li>\n <li>Arizona Panthers</li>\n</ol>")
695
+ expect(subject.excelx_value(7, 1, "Sheet1")).to eq("Does create html tags when formatting is used..\n<ol>\n <li> Denver Broncos </li>\n <li> Carolina Panthers </li>\n <li> New England Patriots</li>\n <li>Arizona Panthers</li>\n</ol>")
696
+ end
697
+ end
22
698
  end
23
699
  end