roo 2.7.0 → 2.8.3

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 (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