roo 1.13.2 → 2.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (236) 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 -203
  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 +672 -11
  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 -298
  107. data/CHANGELOG +0 -417
  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/numeric-link.xlsx +0 -0
  192. data/test/files/only_one_sheet.ods +0 -0
  193. data/test/files/only_one_sheet.xls +0 -0
  194. data/test/files/only_one_sheet.xlsx +0 -0
  195. data/test/files/only_one_sheet.xml +0 -67
  196. data/test/files/paragraph.ods +0 -0
  197. data/test/files/paragraph.xls +0 -0
  198. data/test/files/paragraph.xlsx +0 -0
  199. data/test/files/paragraph.xml +0 -127
  200. data/test/files/prova.xls +0 -0
  201. data/test/files/ric.ods +0 -0
  202. data/test/files/simple_spreadsheet.ods +0 -0
  203. data/test/files/simple_spreadsheet.xls +0 -0
  204. data/test/files/simple_spreadsheet.xlsx +0 -0
  205. data/test/files/simple_spreadsheet.xml +0 -225
  206. data/test/files/simple_spreadsheet_from_italo.ods +0 -0
  207. data/test/files/simple_spreadsheet_from_italo.xls +0 -0
  208. data/test/files/simple_spreadsheet_from_italo.xml +0 -242
  209. data/test/files/so_datetime.csv +0 -7
  210. data/test/files/style.ods +0 -0
  211. data/test/files/style.xls +0 -0
  212. data/test/files/style.xlsx +0 -0
  213. data/test/files/style.xml +0 -154
  214. data/test/files/time-test.csv +0 -2
  215. data/test/files/time-test.ods +0 -0
  216. data/test/files/time-test.xls +0 -0
  217. data/test/files/time-test.xlsx +0 -0
  218. data/test/files/time-test.xml +0 -131
  219. data/test/files/type_excel.ods +0 -0
  220. data/test/files/type_excel.xlsx +0 -0
  221. data/test/files/type_excelx.ods +0 -0
  222. data/test/files/type_excelx.xls +0 -0
  223. data/test/files/type_openoffice.xls +0 -0
  224. data/test/files/type_openoffice.xlsx +0 -0
  225. data/test/files/whitespace.ods +0 -0
  226. data/test/files/whitespace.xls +0 -0
  227. data/test/files/whitespace.xlsx +0 -0
  228. data/test/files/whitespace.xml +0 -184
  229. data/test/rm_sub_test.rb +0 -12
  230. data/test/rm_test.rb +0 -7
  231. data/test/test_generic_spreadsheet.rb +0 -259
  232. data/website/index.html +0 -385
  233. data/website/index.txt +0 -423
  234. data/website/javascripts/rounded_corners_lite.inc.js +0 -285
  235. data/website/stylesheets/screen.css +0 -130
  236. data/website/template.rhtml +0 -48
@@ -1,19 +1,56 @@
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' }
30
+
31
+ it 'creates an instance' do
32
+ expect(subject).to be_a(Roo::Excelx)
33
+ end
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') }
17
54
 
18
55
  it 'creates an instance' do
19
56
  expect(subject).to be_a(Roo::Excelx)
@@ -24,15 +61,639 @@ describe Roo::Excelx do
24
61
  describe '#cell' do
25
62
  context 'for a link cell' do
26
63
  context 'with numeric contents' do
27
- subject {
28
- Roo::Excelx.new('test/files/numeric-link.xlsx').cell('A', 1)
29
- }
64
+ let(:path) { 'test/files/numeric-link.xlsx' }
65
+
66
+ subject do
67
+ xlsx.cell('A', 1)
68
+ end
30
69
 
31
70
  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")
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
34
423
  end
35
424
  end
36
425
  end
37
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
698
+ end
38
699
  end