roo 2.7.0 → 2.8.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +5 -5
  2. data/.github/issue_template.md +16 -0
  3. data/.github/pull_request_template.md +14 -0
  4. data/.rubocop.yml +186 -0
  5. data/.travis.yml +12 -7
  6. data/CHANGELOG.md +53 -2
  7. data/LICENSE +2 -0
  8. data/README.md +29 -13
  9. data/lib/roo/base.rb +69 -61
  10. data/lib/roo/constants.rb +5 -3
  11. data/lib/roo/csv.rb +20 -12
  12. data/lib/roo/excelx/cell/base.rb +26 -12
  13. data/lib/roo/excelx/cell/boolean.rb +9 -6
  14. data/lib/roo/excelx/cell/date.rb +7 -7
  15. data/lib/roo/excelx/cell/datetime.rb +14 -18
  16. data/lib/roo/excelx/cell/empty.rb +3 -2
  17. data/lib/roo/excelx/cell/number.rb +35 -34
  18. data/lib/roo/excelx/cell/string.rb +3 -3
  19. data/lib/roo/excelx/cell/time.rb +4 -3
  20. data/lib/roo/excelx/cell.rb +10 -6
  21. data/lib/roo/excelx/comments.rb +3 -3
  22. data/lib/roo/excelx/coordinate.rb +11 -4
  23. data/lib/roo/excelx/extractor.rb +21 -3
  24. data/lib/roo/excelx/format.rb +38 -31
  25. data/lib/roo/excelx/images.rb +26 -0
  26. data/lib/roo/excelx/relationships.rb +12 -4
  27. data/lib/roo/excelx/shared.rb +10 -3
  28. data/lib/roo/excelx/shared_strings.rb +9 -15
  29. data/lib/roo/excelx/sheet.rb +49 -10
  30. data/lib/roo/excelx/sheet_doc.rb +89 -48
  31. data/lib/roo/excelx/styles.rb +3 -3
  32. data/lib/roo/excelx/workbook.rb +7 -3
  33. data/lib/roo/excelx.rb +42 -16
  34. data/lib/roo/helpers/default_attr_reader.rb +20 -0
  35. data/lib/roo/helpers/weak_instance_cache.rb +41 -0
  36. data/lib/roo/open_office.rb +8 -6
  37. data/lib/roo/spreadsheet.rb +1 -1
  38. data/lib/roo/utils.rb +70 -20
  39. data/lib/roo/version.rb +1 -1
  40. data/lib/roo.rb +4 -1
  41. data/roo.gemspec +13 -11
  42. data/spec/lib/roo/base_spec.rb +45 -3
  43. data/spec/lib/roo/excelx/relationships_spec.rb +43 -0
  44. data/spec/lib/roo/excelx/sheet_doc_spec.rb +11 -0
  45. data/spec/lib/roo/excelx_spec.rb +150 -31
  46. data/spec/lib/roo/strict_spec.rb +43 -0
  47. data/spec/lib/roo/utils_spec.rb +25 -3
  48. data/spec/lib/roo/weak_instance_cache_spec.rb +92 -0
  49. data/spec/lib/roo_spec.rb +0 -0
  50. data/spec/spec_helper.rb +1 -1
  51. data/test/excelx/cell/test_attr_reader_default.rb +72 -0
  52. data/test/excelx/cell/test_base.rb +5 -0
  53. data/test/excelx/cell/test_datetime.rb +6 -6
  54. data/test/excelx/cell/test_empty.rb +11 -0
  55. data/test/excelx/cell/test_number.rb +9 -0
  56. data/test/excelx/cell/test_string.rb +20 -0
  57. data/test/excelx/cell/test_time.rb +4 -4
  58. data/test/excelx/test_coordinate.rb +51 -0
  59. data/test/formatters/test_csv.rb +19 -2
  60. data/test/formatters/test_xml.rb +13 -9
  61. data/test/helpers/test_accessing_files.rb +60 -0
  62. data/test/helpers/test_comments.rb +43 -0
  63. data/test/helpers/test_formulas.rb +9 -0
  64. data/test/helpers/test_labels.rb +103 -0
  65. data/test/helpers/test_sheets.rb +55 -0
  66. data/test/helpers/test_styles.rb +62 -0
  67. data/test/roo/test_base.rb +182 -0
  68. data/test/roo/test_csv.rb +37 -1
  69. data/test/roo/test_excelx.rb +157 -13
  70. data/test/roo/test_open_office.rb +196 -33
  71. data/test/test_helper.rb +66 -22
  72. data/test/test_roo.rb +32 -881
  73. metadata +32 -14
  74. data/.github/ISSUE_TEMPLATE +0 -10
  75. data/Gemfile_ruby2 +0 -30
data/lib/roo.rb CHANGED
@@ -1,3 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'roo/version'
1
4
  require 'roo/constants'
2
5
  require 'roo/errors'
3
6
  require 'roo/spreadsheet'
@@ -9,7 +12,7 @@ module Roo
9
12
  autoload :Excelx, 'roo/excelx'
10
13
  autoload :CSV, 'roo/csv'
11
14
 
12
- TEMP_PREFIX = 'roo_'.freeze
15
+ TEMP_PREFIX = 'roo_'
13
16
 
14
17
  CLASS_FOR_EXTENSION = {
15
18
  ods: Roo::OpenOffice,
data/roo.gemspec CHANGED
@@ -4,21 +4,23 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'roo/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
- spec.name = 'roo'
8
- spec.version = Roo::VERSION
9
- spec.authors = ['Thomas Preymesser', 'Hugh McGowan', 'Ben Woosley', 'Oleksandr Simonov', 'Steven Daniels']
10
- spec.email = ['ruby.ruby.ruby.roo@gmail.com', 'oleksandr@simonov.me']
11
- spec.summary = 'Roo can access the contents of various spreadsheet files.'
12
- spec.description = "Roo can access the contents of various spreadsheet files. It can handle\n* OpenOffice\n* Excelx\n* LibreOffice\n* CSV"
13
- spec.homepage = 'http://github.com/roo-rb/roo'
14
- spec.license = 'MIT'
7
+ spec.name = 'roo'
8
+ spec.version = Roo::VERSION
9
+ spec.authors = ['Thomas Preymesser', 'Hugh McGowan', 'Ben Woosley', 'Oleksandr Simonov', 'Steven Daniels', 'Anmol Chopra']
10
+ spec.email = ['ruby.ruby.ruby.roo@gmail.com', 'oleksandr@simonov.me']
11
+ spec.summary = 'Roo can access the contents of various spreadsheet files.'
12
+ spec.description = "Roo can access the contents of various spreadsheet files. It can handle\n* OpenOffice\n* Excelx\n* LibreOffice\n* CSV"
13
+ spec.homepage = 'https://github.com/roo-rb/roo'
14
+ spec.license = 'MIT'
15
15
 
16
- spec.files = `git ls-files -z`.split("\x0")
16
+ spec.files = `git ls-files -z`.split("\x0")
17
17
  spec.files.reject! { |fn| fn.include?('test/files') }
18
- spec.require_paths = ['lib']
18
+ spec.require_paths = ['lib']
19
+
20
+ spec.required_ruby_version = ">= 2.3.0"
19
21
 
20
22
  spec.add_dependency 'nokogiri', '~> 1'
21
- spec.add_dependency 'rubyzip', '~> 1.1', '< 2.0.0'
23
+ spec.add_dependency 'rubyzip', '>= 1.3.0', '< 3.0.0'
22
24
 
23
25
  spec.add_development_dependency 'rake', '~> 10.1'
24
26
  spec.add_development_dependency 'minitest', '~> 5.4', '>= 5.4.3'
@@ -127,10 +127,22 @@ describe Roo::Base do
127
127
  end
128
128
  end
129
129
 
130
- describe '#row' do
131
- it 'should return the specified row' do
130
+ describe "#row" do
131
+ it "should return the specified row" do
132
132
  expect(spreadsheet.row(12)).to eq([41.0, 42.0, 43.0, 44.0, 45.0, nil, nil])
133
- expect(spreadsheet.row(16)).to eq([nil, '"Hello world!"', 'forty-three', 'forty-four', 'forty-five', nil, nil])
133
+ expect(spreadsheet.row(16)).to eq([nil, '"Hello world!"', "forty-three", "forty-four", "forty-five", nil, nil])
134
+ end
135
+
136
+ it "should return the specified row if default_sheet is set by a string" do
137
+ spreadsheet.default_sheet = "my_sheet"
138
+ expect(spreadsheet.row(12)).to eq([41.0, 42.0, 43.0, 44.0, 45.0, nil, nil])
139
+ expect(spreadsheet.row(16)).to eq([nil, '"Hello world!"', "forty-three", "forty-four", "forty-five", nil, nil])
140
+ end
141
+
142
+ it "should return the specified row if default_sheet is set by an integer" do
143
+ spreadsheet.default_sheet = 0
144
+ expect(spreadsheet.row(12)).to eq([41.0, 42.0, 43.0, 44.0, 45.0, nil, nil])
145
+ expect(spreadsheet.row(16)).to eq([nil, '"Hello world!"', "forty-three", "forty-four", "forty-five", nil, nil])
134
146
  end
135
147
  end
136
148
 
@@ -146,6 +158,11 @@ describe Roo::Base do
146
158
  expect { spreadsheet.row_with([/Missing Header/]) }.to \
147
159
  raise_error(Roo::HeaderRowNotFoundError)
148
160
  end
161
+
162
+ it 'returns missing headers' do
163
+ expect { spreadsheet.row_with([/Header/, /Missing Header 1/, /Missing Header 2/]) }.to \
164
+ raise_error(Roo::HeaderRowNotFoundError, '[/Missing Header 1/, /Missing Header 2/]')
165
+ end
149
166
  end
150
167
  end
151
168
 
@@ -173,6 +190,31 @@ describe Roo::Base do
173
190
  end
174
191
  end
175
192
 
193
+ describe "#default_sheet=" do
194
+ it "should correctly set the default sheet if passed a string" do
195
+ spreadsheet.default_sheet = "my_sheet"
196
+ expect(spreadsheet.default_sheet).to eq("my_sheet")
197
+ end
198
+
199
+ it "should correctly set the default sheet if passed an integer" do
200
+ spreadsheet.default_sheet = 0
201
+ expect(spreadsheet.default_sheet).to eq("my_sheet")
202
+ end
203
+
204
+ it "should correctly set the default sheet if passed an integer for the second sheet" do
205
+ spreadsheet.default_sheet = 1
206
+ expect(spreadsheet.default_sheet).to eq("blank sheet")
207
+ end
208
+
209
+ it "should raise an error if passed a sheet that does not exist as an integer" do
210
+ expect { spreadsheet.default_sheet = 10 }.to raise_error RangeError
211
+ end
212
+
213
+ it "should raise an error if passed a sheet that does not exist as a string" do
214
+ expect { spreadsheet.default_sheet = "does_not_exist" }.to raise_error RangeError
215
+ end
216
+ end
217
+
176
218
  describe '#to_yaml' do
177
219
  it 'should convert the spreadsheet to yaml' do
178
220
  expect(spreadsheet.to_yaml({}, 5, 1, 5, 1)).to eq("--- \n" + yaml_entry(5, 1, 'date', '1961-11-21'))
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ describe Roo::Excelx::Relationships do
6
+ subject(:relationships) { Roo::Excelx::Relationships.new Roo::Excelx.new(path).rels_files[0] }
7
+
8
+ describe "#include_type?" do
9
+ [
10
+ ["with hyperlink type", "test/files/link.xlsx", true, false],
11
+ ["with nil path", "test/files/Bibelbund.xlsx", false, false],
12
+ ["with comments type", "test/files/comments-google.xlsx", false, true],
13
+ ].each do |context_desc, file_path, hyperlink_value, comments_value|
14
+ context context_desc do
15
+ let(:path) { file_path }
16
+
17
+ it "should return #{hyperlink_value} for hyperlink" do
18
+ expect(subject.include_type?("hyperlink")).to be hyperlink_value
19
+ end
20
+
21
+ it "should return #{hyperlink_value} for link" do
22
+ expect(subject.include_type?("link")).to be hyperlink_value
23
+ end
24
+
25
+ it "should return false for hypelink" do
26
+ expect(subject.include_type?("hypelink")).to be false
27
+ end
28
+
29
+ it "should return false for coment" do
30
+ expect(subject.include_type?("coment")).to be false
31
+ end
32
+
33
+ it "should return #{comments_value} for comments" do
34
+ expect(subject.include_type?("comments")).to be comments_value
35
+ end
36
+
37
+ it "should return #{comments_value} for comment" do
38
+ expect(subject.include_type?("comment")).to be comments_value
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ describe Roo::Excelx::SheetDoc do
6
+ subject(:blank_children) { Roo::Excelx.new("test/files/blank_children.xlsx") }
7
+
8
+ example "#last_row" do
9
+ expect(subject.last_row).to eq 3
10
+ end
11
+ end
@@ -151,6 +151,22 @@ describe Roo::Excelx do
151
151
  it 'returns the expected result' do
152
152
  expect(subject.sheet_for("Tabelle1").instance_variable_get("@name")).to eq "Tabelle1"
153
153
  end
154
+
155
+ it 'returns the expected result when passed a number' do
156
+ expect(subject.sheet_for(0).instance_variable_get("@name")).to eq "Tabelle1"
157
+ end
158
+
159
+ it 'returns the expected result when passed a number that is not the first sheet' do
160
+ expect(subject.sheet_for(1).instance_variable_get("@name")).to eq "Name of Sheet 2"
161
+ end
162
+
163
+ it "should raise an error if passed a sheet that does not exist as an integer" do
164
+ expect { subject.sheet_for(10) }.to raise_error RangeError
165
+ end
166
+
167
+ it "should raise an error if passed a sheet that does not exist as a string" do
168
+ expect { subject.sheet_for("does_not_exist") }.to raise_error RangeError
169
+ end
154
170
  end
155
171
 
156
172
  describe '#row' do
@@ -304,6 +320,18 @@ describe Roo::Excelx do
304
320
  end
305
321
  end
306
322
 
323
+ describe '#row' do
324
+ context 'integers with leading zero'
325
+ let(:path) { 'test/files/number_with_zero_prefix.xlsx' }
326
+
327
+ it 'returns base 10 integer' do
328
+ (1..50).each do |row_index|
329
+ range_start = (row_index - 1) * 20 + 1
330
+ expect(subject.row(row_index)).to eq (range_start..(range_start+19)).to_a
331
+ end
332
+ end
333
+ end
334
+
307
335
  describe '#excelx_format' do
308
336
  let(:path) { 'test/files/style.xlsx' }
309
337
 
@@ -351,14 +379,50 @@ describe Roo::Excelx do
351
379
  expect(subject.hyperlink?(1, 1)).to eq true
352
380
  expect(subject.hyperlink?(1, 2)).to eq false
353
381
  end
382
+
383
+ context 'defined on cell range' do
384
+ let(:path) { 'test/files/cell-range-link.xlsx' }
385
+
386
+ it 'returns the expected result' do
387
+ [[false]*3, *[[true, true, false]]*4, [false]*3].each.with_index(1) do |row, row_index|
388
+ row.each.with_index(1) do |value, col_index|
389
+ expect(subject.hyperlink?(row_index, col_index)).to eq(value)
390
+ end
391
+ end
392
+ end
393
+ end
354
394
  end
355
395
 
356
396
  describe '#hyperlink' do
357
- let(:path) { 'test/files/link.xlsx' }
397
+ context 'defined on cell range' do
398
+ let(:path) { 'test/files/cell-range-link.xlsx' }
358
399
 
359
- it 'returns the expected result' do
360
- expect(subject.hyperlink(1, 1)).to eq "http://www.google.com"
361
- expect(subject.hyperlink(1, 2)).to eq nil
400
+ it 'returns the expected result' do
401
+ link = "http://www.google.com"
402
+ [[nil]*3, *[[link, link, nil]]*4, [nil]*3].each.with_index(1) do |row, row_index|
403
+ row.each.with_index(1) do |value, col_index|
404
+ expect(subject.hyperlink(row_index, col_index)).to eq(value)
405
+ end
406
+ end
407
+ end
408
+ end
409
+
410
+ context 'without location' do
411
+ let(:path) { 'test/files/link.xlsx' }
412
+
413
+ it 'returns the expected result' do
414
+ expect(subject.hyperlink(1, 1)).to eq "http://www.google.com"
415
+ expect(subject.hyperlink(1, 2)).to eq nil
416
+ end
417
+ end
418
+
419
+ context 'with location' do
420
+ let(:path) { 'test/files/link_with_location.xlsx' }
421
+
422
+ it 'returns the expected result' do
423
+ expect(subject.hyperlink(1, 1)).to eq "http://www.google.com/#hey"
424
+ expect(subject.hyperlink(1, 2)).to eq nil
425
+ end
362
426
  end
363
427
  end
364
428
 
@@ -480,34 +544,36 @@ describe Roo::Excelx do
480
544
  end
481
545
 
482
546
  describe '#html_strings' do
483
- let(:path) { 'test/files/html_strings_formatting.xlsx' }
547
+ describe "HTML Parsing Enabling" do
548
+ let(:path) { 'test/files/html_strings_formatting.xlsx' }
484
549
 
485
- it 'returns the expected result' do
486
- expect(subject.excelx_value(1, 1, "Sheet1")).to eq "This has no formatting."
487
- expect(subject.excelx_value(2, 1, "Sheet1")).to eq "<html>This has<b> bold </b>formatting.</html>"
488
- expect(subject.excelx_value(2, 2, "Sheet1")).to eq "<html>This has <i>italics</i> formatting.</html>"
489
- expect(subject.excelx_value(2, 3, "Sheet1")).to eq "<html>This has <u>underline</u> format.</html>"
490
- expect(subject.excelx_value(2, 4, "Sheet1")).to eq "<html>Superscript. x<sup>123</sup></html>"
491
- expect(subject.excelx_value(2, 5, "Sheet1")).to eq "<html>SubScript. T<sub>j</sub></html>"
492
-
493
- expect(subject.excelx_value(3, 1, "Sheet1")).to eq "<html>Bold, italics <b><i>together</i></b>.</html>"
494
- expect(subject.excelx_value(3, 2, "Sheet1")).to eq "<html>Bold, Underline <b><u>together</u></b>.</html>"
495
- expect(subject.excelx_value(3, 3, "Sheet1")).to eq "<html>Bold, Superscript. <b>x</b><sup><b>N</b></sup></html>"
496
- expect(subject.excelx_value(3, 4, "Sheet1")).to eq "<html>Bold, Subscript. <b>T</b><sub><b>abc</b></sub></html>"
497
- expect(subject.excelx_value(3, 5, "Sheet1")).to eq "<html>Italics, Underline <i><u>together</u></i>.</html>"
498
- expect(subject.excelx_value(3, 6, "Sheet1")).to eq "<html>Italics, Superscript. <i>X</i><sup><i>abc</i></sup></html>"
499
- expect(subject.excelx_value(3, 7, "Sheet1")).to eq "<html>Italics, Subscript. <i>B</i><sub><i>efg</i></sub></html>"
500
- expect(subject.excelx_value(4, 1, "Sheet1")).to eq "<html>Bold, italics underline,<b><i><u> together</u></i></b>.</html>"
501
- 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>"
502
- 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>"
503
- 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>"
504
- 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>"
505
- 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>"
506
- 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>"
507
- 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>"
508
- 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>"
509
- 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>"
510
- 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>"
550
+ it 'returns the expected result' do
551
+ expect(subject.excelx_value(1, 1, "Sheet1")).to eq("This has no formatting.")
552
+ expect(subject.excelx_value(2, 1, "Sheet1")).to eq("<html>This has<b> bold </b>formatting.</html>")
553
+ expect(subject.excelx_value(2, 2, "Sheet1")).to eq("<html>This has <i>italics</i> formatting.</html>")
554
+ expect(subject.excelx_value(2, 3, "Sheet1")).to eq("<html>This has <u>underline</u> format.</html>")
555
+ expect(subject.excelx_value(2, 4, "Sheet1")).to eq("<html>Superscript. x<sup>123</sup></html>")
556
+ expect(subject.excelx_value(2, 5, "Sheet1")).to eq("<html>SubScript. T<sub>j</sub></html>")
557
+
558
+ expect(subject.excelx_value(3, 1, "Sheet1")).to eq("<html>Bold, italics <b><i>together</i></b>.</html>")
559
+ expect(subject.excelx_value(3, 2, "Sheet1")).to eq("<html>Bold, Underline <b><u>together</u></b>.</html>")
560
+ expect(subject.excelx_value(3, 3, "Sheet1")).to eq("<html>Bold, Superscript. <b>x</b><sup><b>N</b></sup></html>")
561
+ expect(subject.excelx_value(3, 4, "Sheet1")).to eq("<html>Bold, Subscript. <b>T</b><sub><b>abc</b></sub></html>")
562
+ expect(subject.excelx_value(3, 5, "Sheet1")).to eq("<html>Italics, Underline <i><u>together</u></i>.</html>")
563
+ expect(subject.excelx_value(3, 6, "Sheet1")).to eq("<html>Italics, Superscript. <i>X</i><sup><i>abc</i></sup></html>")
564
+ expect(subject.excelx_value(3, 7, "Sheet1")).to eq("<html>Italics, Subscript. <i>B</i><sub><i>efg</i></sub></html>")
565
+ expect(subject.excelx_value(4, 1, "Sheet1")).to eq("<html>Bold, italics underline,<b><i><u> together</u></i></b>.</html>")
566
+ 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>")
567
+ 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>")
568
+ 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>")
569
+ 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>")
570
+ 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>")
571
+ 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>")
572
+ 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>")
573
+ 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>")
574
+ 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>")
575
+ 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>")
576
+ end
511
577
  end
512
578
  end
513
579
 
@@ -534,4 +600,57 @@ describe Roo::Excelx do
534
600
  expect(subject.sheet(0).excelx_format(2,1)).to eq 'm/d/yyyy" "h:mm:ss" "AM/PM'
535
601
  end
536
602
  end
603
+
604
+ describe 'images' do
605
+ let(:path) { 'test/files/images.xlsx' }
606
+
607
+ it 'returns array of images from default sheet' do
608
+ expect(subject.images).to be_kind_of(Array)
609
+ expect(subject.images.size).to eql(19)
610
+ end
611
+
612
+ it 'returns empty array if there is no images on the sheet' do
613
+ expect(subject.images("Sheet2")).to eql([])
614
+ end
615
+ end
537
616
  end
617
+
618
+ describe 'Roo::Excelx with options set' do
619
+ subject(:xlsx) do
620
+ Roo::Excelx.new(path, disable_html_wrapper: true)
621
+ end
622
+
623
+ describe '#html_strings' do
624
+ describe "HTML Parsing Disabled" do
625
+ let(:path) { 'test/files/html_strings_formatting.xlsx' }
626
+
627
+ it 'returns the expected result' do
628
+ expect(subject.excelx_value(1, 1, "Sheet1")).to eq("This has no formatting.")
629
+ expect(subject.excelx_value(2, 1, "Sheet1")).to eq("This has bold formatting.")
630
+ expect(subject.excelx_value(2, 2, "Sheet1")).to eq("This has italics formatting.")
631
+ expect(subject.excelx_value(2, 3, "Sheet1")).to eq("This has underline format.")
632
+ expect(subject.excelx_value(2, 4, "Sheet1")).to eq("Superscript. x123")
633
+ expect(subject.excelx_value(2, 5, "Sheet1")).to eq("SubScript. Tj")
634
+
635
+ expect(subject.excelx_value(3, 1, "Sheet1")).to eq("Bold, italics together.")
636
+ expect(subject.excelx_value(3, 2, "Sheet1")).to eq("Bold, Underline together.")
637
+ expect(subject.excelx_value(3, 3, "Sheet1")).to eq("Bold, Superscript. xN")
638
+ expect(subject.excelx_value(3, 4, "Sheet1")).to eq("Bold, Subscript. Tabc")
639
+ expect(subject.excelx_value(3, 5, "Sheet1")).to eq("Italics, Underline together.")
640
+ expect(subject.excelx_value(3, 6, "Sheet1")).to eq("Italics, Superscript. Xabc")
641
+ expect(subject.excelx_value(3, 7, "Sheet1")).to eq("Italics, Subscript. Befg")
642
+ expect(subject.excelx_value(4, 1, "Sheet1")).to eq("Bold, italics underline, together.")
643
+ expect(subject.excelx_value(4, 2, "Sheet1")).to eq("Bold, italics, superscript. Xabc123")
644
+ expect(subject.excelx_value(4, 3, "Sheet1")).to eq("Bold, Italics, subscript. Mgha2")
645
+ expect(subject.excelx_value(4, 4, "Sheet1")).to eq("Bold, Underline, superscript. ABC123")
646
+ expect(subject.excelx_value(4, 5, "Sheet1")).to eq("Bold, Underline, subscript. GoodXYZ")
647
+ expect(subject.excelx_value(4, 6, "Sheet1")).to eq("Italics, Underline, superscript. Upswing")
648
+ expect(subject.excelx_value(4, 7, "Sheet1")).to eq("Italics, Underline, subscript. Tswing")
649
+ expect(subject.excelx_value(5, 1, "Sheet1")).to eq("Bold, italics, underline, superscript. GHJK1904")
650
+ expect(subject.excelx_value(5, 2, "Sheet1")).to eq("Bold, italics, underline, subscript. Mikedrop")
651
+ 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>")
652
+ 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>")
653
+ end
654
+ end
655
+ end
656
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ describe Roo::Excelx do
4
+ subject { Roo::Excelx.new('test/files/strict.xlsx') }
5
+
6
+ example '#sheets' do
7
+ expect(subject.sheets).to eq %w(Sheet1 Sheet2)
8
+ end
9
+
10
+ example '#sheet' do
11
+ expect(subject.sheet('Sheet1')).to be_a(Roo::Excelx)
12
+ end
13
+
14
+ example '#cell' do
15
+ expect(subject.cell(1, 1)).to eq 'Sheet 1'
16
+ expect(subject.cell(1, 1, 'Sheet2')).to eq 'Sheet 2'
17
+ end
18
+
19
+ example '#row' do
20
+ expect(subject.row(1)).to eq ['Sheet 1']
21
+ expect(subject.row(1, 'Sheet2')).to eq ['Sheet 2']
22
+ end
23
+
24
+ example '#first_row' do
25
+ expect(subject.first_row).to eq 1
26
+ expect(subject.first_row('Sheet2')).to eq 1
27
+ end
28
+
29
+ example '#last_row' do
30
+ expect(subject.last_row).to eq 1
31
+ expect(subject.last_row('Sheet2')).to eq 1
32
+ end
33
+
34
+ example '#first_column' do
35
+ expect(subject.first_column).to eq 1
36
+ expect(subject.first_column('Sheet2')).to eq 1
37
+ end
38
+
39
+ example '#last_column' do
40
+ expect(subject.last_column).to eq 1
41
+ expect(subject.last_column('Sheet2')).to eq 1
42
+ end
43
+ end
@@ -52,6 +52,15 @@ RSpec.describe ::Roo::Utils do
52
52
  end
53
53
  end
54
54
 
55
+ context '.extract_coordinate' do
56
+ it "returns the expected result" do
57
+ expect(described_class.extract_coordinate('A1')).to eq [1, 1]
58
+ expect(described_class.extract_coordinate('B2')).to eq [2, 2]
59
+ expect(described_class.extract_coordinate('R2')).to eq [2, 18]
60
+ expect(described_class.extract_coordinate('AR31')).to eq [31, 18 + 26]
61
+ end
62
+ end
63
+
55
64
  context '.split_coord' do
56
65
  it "returns the expected result" do
57
66
  expect(described_class.split_coord('A1')).to eq ["A", 1]
@@ -81,26 +90,39 @@ RSpec.describe ::Roo::Utils do
81
90
  end
82
91
  end
83
92
 
93
+ context '.coordinates_in_range' do
94
+ it "returns the expected result" do
95
+ expect(described_class.coordinates_in_range('').to_a).to eq []
96
+ expect(described_class.coordinates_in_range('B2').to_a).to eq [[2, 2]]
97
+ expect(described_class.coordinates_in_range('D2:G3').to_a).to eq [[2, 4], [2, 5], [2, 6], [2, 7], [3, 4], [3, 5], [3, 6], [3, 7]]
98
+ expect(described_class.coordinates_in_range('G3:D2').to_a).to eq []
99
+ end
100
+
101
+ it "raises an error when appropriate" do
102
+ expect { described_class.coordinates_in_range('D2:G3:I5').to_a }.to raise_error(ArgumentError)
103
+ end
104
+ end
105
+
84
106
  context '.load_xml' do
85
107
  it 'returns the expected result' do
86
108
  expect(described_class.load_xml('test/files/sheet1.xml')).to be_a(Nokogiri::XML::Document)
87
109
  expect(described_class.load_xml('test/files/sheet1.xml').
88
110
  remove_namespaces!.xpath("/worksheet/dimension").map do |dim|
89
- dim.attributes["ref"].value end.first).to eq "A1:B11"
111
+ dim["ref"] end.first).to eq "A1:B11"
90
112
  end
91
113
  end
92
114
 
93
115
  context '.each_element' do
94
116
  it 'returns the expected result' do
95
117
  described_class.each_element('test/files/sheet1.xml', 'dimension') do |dim|
96
- expect(dim.attributes["ref"].value).to eq "A1:B11"
118
+ expect(dim["ref"]).to eq "A1:B11"
97
119
  end
98
120
  rows = []
99
121
  described_class.each_element('test/files/sheet1.xml', 'row') do |row|
100
122
  rows << row
101
123
  end
102
124
  expect(rows.size).to eq 11
103
- expect(rows[2].attributes["r"].value).to eq "3"
125
+ expect(rows[2]["r"]).to eq "3"
104
126
  end
105
127
  end
106
128
  end
@@ -0,0 +1,92 @@
1
+ require 'spec_helper'
2
+
3
+ if RUBY_PLATFORM == "java"
4
+ require 'java'
5
+ java_import 'java.lang.System'
6
+ end
7
+
8
+ describe Roo::Helpers::WeakInstanceCache do
9
+ let(:klass) do
10
+ Class.new do
11
+ include Roo::Helpers::WeakInstanceCache
12
+
13
+ def memoized_data
14
+ instance_cache(:@memoized_data) do
15
+ "Some Costly Operation #{rand(1000)}" * 1_000
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ subject do
22
+ klass.new
23
+ end
24
+
25
+ it 'should be lazy' do
26
+ expect(subject.instance_variables).to_not include(:@memoized_data)
27
+ data = subject.memoized_data
28
+ expect(subject.instance_variables).to include(:@memoized_data)
29
+ end
30
+
31
+
32
+ it 'should be memoized' do
33
+ data = subject.memoized_data
34
+ expect(subject.memoized_data).to equal(data)
35
+ end
36
+
37
+ it 'should recalculate after GC' do
38
+ expect(subject.instance_variables).to_not include(:@memoized_data)
39
+ GC.disable
40
+ subject.memoized_data && nil
41
+ expect(subject.instance_variables).to include(:@memoized_data)
42
+
43
+ force_gc
44
+ expect(subject.instance_variables).to_not include(:@memoized_data)
45
+ GC.disable
46
+ subject.memoized_data && nil
47
+ expect(subject.instance_variables).to include(:@memoized_data)
48
+ end
49
+
50
+ it 'must remove instance variable' do
51
+ expect(subject.instance_variables).to_not include(:@memoized_data)
52
+ GC.disable
53
+ subject.memoized_data && nil
54
+ expect(subject.instance_variables).to include(:@memoized_data)
55
+
56
+ force_gc
57
+ expect(subject.instance_variables).to_not include(:@memoized_data)
58
+ end
59
+
60
+ context '#inspect must not raise' do
61
+ it 'before calculation' do
62
+ expect{subject.inspect}.to_not raise_error
63
+ end
64
+ it 'after calculation' do
65
+ GC.disable
66
+ subject.memoized_data && nil
67
+ expect{subject.inspect}.to_not raise_error
68
+ expect(subject.inspect).to include("Some Costly Operation")
69
+ force_gc
70
+ end
71
+ it 'after GC' do
72
+ subject.memoized_data && nil
73
+ force_gc
74
+ expect(subject.instance_variables).to_not include(:@memoized_data)
75
+ expect{subject.inspect}.to_not raise_error
76
+ expect(subject.inspect).to_not include("Some Costly Operation")
77
+ end
78
+ end
79
+
80
+ if RUBY_PLATFORM == "java"
81
+ def force_gc
82
+ System.gc
83
+ sleep(0.1)
84
+ end
85
+ else
86
+ def force_gc
87
+ GC.start(full_mark: true, immediate_sweep: true)
88
+ sleep(0.1)
89
+ GC.start(full_mark: true, immediate_sweep: true)
90
+ end
91
+ end
92
+ end
File without changes
data/spec/spec_helper.rb CHANGED
@@ -5,5 +5,5 @@ require 'helpers'
5
5
  RSpec.configure do |c|
6
6
  c.include Helpers
7
7
  c.color = true
8
- c.formatter = :documentation
8
+ c.formatter = :documentation if ENV["USE_REPORTERS"]
9
9
  end