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.
- checksums.yaml +5 -5
- data/.codeclimate.yml +17 -0
- data/.github/issue_template.md +16 -0
- data/.github/pull_request_template.md +14 -0
- data/.github/workflows/pull-request.yml +15 -0
- data/.github/workflows/ruby.yml +34 -0
- data/.gitignore +11 -0
- data/.rubocop.yml +186 -0
- data/.simplecov +4 -0
- data/CHANGELOG.md +702 -0
- data/Gemfile +18 -12
- data/Guardfile +23 -0
- data/LICENSE +5 -1
- data/README.md +328 -0
- data/Rakefile +23 -23
- data/examples/roo_soap_client.rb +28 -31
- data/examples/roo_soap_server.rb +4 -6
- data/examples/write_me.rb +9 -10
- data/lib/roo/base.rb +317 -504
- data/lib/roo/constants.rb +7 -0
- data/lib/roo/csv.rb +141 -113
- data/lib/roo/errors.rb +11 -0
- data/lib/roo/excelx/cell/base.rb +108 -0
- data/lib/roo/excelx/cell/boolean.rb +30 -0
- data/lib/roo/excelx/cell/date.rb +28 -0
- data/lib/roo/excelx/cell/datetime.rb +107 -0
- data/lib/roo/excelx/cell/empty.rb +20 -0
- data/lib/roo/excelx/cell/number.rb +99 -0
- data/lib/roo/excelx/cell/string.rb +19 -0
- data/lib/roo/excelx/cell/time.rb +44 -0
- data/lib/roo/excelx/cell.rb +110 -0
- data/lib/roo/excelx/comments.rb +55 -0
- data/lib/roo/excelx/coordinate.rb +19 -0
- data/lib/roo/excelx/extractor.rb +39 -0
- data/lib/roo/excelx/format.rb +71 -0
- data/lib/roo/excelx/images.rb +26 -0
- data/lib/roo/excelx/relationships.rb +33 -0
- data/lib/roo/excelx/shared.rb +39 -0
- data/lib/roo/excelx/shared_strings.rb +151 -0
- data/lib/roo/excelx/sheet.rb +151 -0
- data/lib/roo/excelx/sheet_doc.rb +257 -0
- data/lib/roo/excelx/styles.rb +64 -0
- data/lib/roo/excelx/workbook.rb +64 -0
- data/lib/roo/excelx.rb +407 -601
- data/lib/roo/font.rb +17 -0
- data/lib/roo/formatters/base.rb +15 -0
- data/lib/roo/formatters/csv.rb +84 -0
- data/lib/roo/formatters/matrix.rb +23 -0
- data/lib/roo/formatters/xml.rb +31 -0
- data/lib/roo/formatters/yaml.rb +40 -0
- data/lib/roo/helpers/default_attr_reader.rb +20 -0
- data/lib/roo/helpers/weak_instance_cache.rb +41 -0
- data/lib/roo/libre_office.rb +4 -0
- data/lib/roo/link.rb +34 -0
- data/lib/roo/open_office.rb +631 -0
- data/lib/roo/spreadsheet.rb +28 -23
- data/lib/roo/tempdir.rb +24 -0
- data/lib/roo/utils.rb +128 -0
- data/lib/roo/version.rb +3 -0
- data/lib/roo.rb +26 -24
- data/roo.gemspec +29 -203
- data/spec/helpers.rb +5 -0
- data/spec/lib/roo/base_spec.rb +291 -3
- data/spec/lib/roo/csv_spec.rb +38 -11
- data/spec/lib/roo/excelx/cell/time_spec.rb +15 -0
- data/spec/lib/roo/excelx/format_spec.rb +7 -6
- data/spec/lib/roo/excelx/relationships_spec.rb +43 -0
- data/spec/lib/roo/excelx/sheet_doc_spec.rb +11 -0
- data/spec/lib/roo/excelx_spec.rb +672 -11
- data/spec/lib/roo/libreoffice_spec.rb +16 -6
- data/spec/lib/roo/openoffice_spec.rb +30 -8
- data/spec/lib/roo/spreadsheet_spec.rb +60 -12
- data/spec/lib/roo/strict_spec.rb +43 -0
- data/spec/lib/roo/utils_spec.rb +119 -0
- data/spec/lib/roo/weak_instance_cache_spec.rb +92 -0
- data/spec/lib/roo_spec.rb +0 -0
- data/spec/spec_helper.rb +7 -6
- data/test/all_ss.rb +12 -11
- data/test/excelx/cell/test_attr_reader_default.rb +72 -0
- data/test/excelx/cell/test_base.rb +68 -0
- data/test/excelx/cell/test_boolean.rb +36 -0
- data/test/excelx/cell/test_date.rb +38 -0
- data/test/excelx/cell/test_datetime.rb +45 -0
- data/test/excelx/cell/test_empty.rb +18 -0
- data/test/excelx/cell/test_number.rb +90 -0
- data/test/excelx/cell/test_string.rb +48 -0
- data/test/excelx/cell/test_time.rb +30 -0
- data/test/excelx/test_coordinate.rb +51 -0
- data/test/formatters/test_csv.rb +136 -0
- data/test/formatters/test_matrix.rb +76 -0
- data/test/formatters/test_xml.rb +78 -0
- data/test/formatters/test_yaml.rb +20 -0
- data/test/helpers/test_accessing_files.rb +81 -0
- data/test/helpers/test_comments.rb +43 -0
- data/test/helpers/test_formulas.rb +9 -0
- data/test/helpers/test_labels.rb +103 -0
- data/test/helpers/test_sheets.rb +55 -0
- data/test/helpers/test_styles.rb +62 -0
- data/test/roo/test_base.rb +182 -0
- data/test/roo/test_csv.rb +88 -0
- data/test/roo/test_excelx.rb +360 -0
- data/test/roo/test_libre_office.rb +9 -0
- data/test/roo/test_open_office.rb +289 -0
- data/test/test_helper.rb +123 -59
- data/test/test_roo.rb +392 -2292
- metadata +153 -298
- data/CHANGELOG +0 -417
- data/Gemfile.lock +0 -78
- data/README.markdown +0 -126
- data/VERSION +0 -1
- data/lib/roo/excel.rb +0 -355
- data/lib/roo/excel2003xml.rb +0 -300
- data/lib/roo/google.rb +0 -292
- data/lib/roo/openoffice.rb +0 -496
- data/lib/roo/roo_rails_helper.rb +0 -83
- data/lib/roo/worksheet.rb +0 -18
- data/scripts/txt2html +0 -67
- data/spec/lib/roo/excel2003xml_spec.rb +0 -15
- data/spec/lib/roo/excel_spec.rb +0 -17
- data/spec/lib/roo/google_spec.rb +0 -64
- data/test/files/1900_base.xls +0 -0
- data/test/files/1900_base.xlsx +0 -0
- data/test/files/1904_base.xls +0 -0
- data/test/files/1904_base.xlsx +0 -0
- data/test/files/Bibelbund.csv +0 -3741
- data/test/files/Bibelbund.ods +0 -0
- data/test/files/Bibelbund.xls +0 -0
- data/test/files/Bibelbund.xlsx +0 -0
- data/test/files/Bibelbund.xml +0 -62518
- data/test/files/Bibelbund1.ods +0 -0
- data/test/files/Pfand_from_windows_phone.xlsx +0 -0
- data/test/files/bad_excel_date.xls +0 -0
- data/test/files/bbu.ods +0 -0
- data/test/files/bbu.xls +0 -0
- data/test/files/bbu.xlsx +0 -0
- data/test/files/bbu.xml +0 -152
- data/test/files/bode-v1.ods.zip +0 -0
- data/test/files/bode-v1.xls.zip +0 -0
- data/test/files/boolean.csv +0 -2
- data/test/files/boolean.ods +0 -0
- data/test/files/boolean.xls +0 -0
- data/test/files/boolean.xlsx +0 -0
- data/test/files/boolean.xml +0 -112
- data/test/files/borders.ods +0 -0
- data/test/files/borders.xls +0 -0
- data/test/files/borders.xlsx +0 -0
- data/test/files/borders.xml +0 -144
- data/test/files/bug-numbered-sheet-names.xlsx +0 -0
- data/test/files/bug-row-column-fixnum-float.xls +0 -0
- data/test/files/bug-row-column-fixnum-float.xml +0 -127
- data/test/files/comments.ods +0 -0
- data/test/files/comments.xls +0 -0
- data/test/files/comments.xlsx +0 -0
- data/test/files/csvtypes.csv +0 -1
- data/test/files/datetime.ods +0 -0
- data/test/files/datetime.xls +0 -0
- data/test/files/datetime.xlsx +0 -0
- data/test/files/datetime.xml +0 -142
- data/test/files/datetime_floatconv.xls +0 -0
- data/test/files/datetime_floatconv.xml +0 -148
- data/test/files/dreimalvier.ods +0 -0
- data/test/files/emptysheets.ods +0 -0
- data/test/files/emptysheets.xls +0 -0
- data/test/files/emptysheets.xlsx +0 -0
- data/test/files/emptysheets.xml +0 -105
- data/test/files/excel2003.xml +0 -21140
- data/test/files/false_encoding.xls +0 -0
- data/test/files/false_encoding.xml +0 -132
- data/test/files/file_item_error.xlsx +0 -0
- data/test/files/formula.ods +0 -0
- data/test/files/formula.xls +0 -0
- data/test/files/formula.xlsx +0 -0
- data/test/files/formula.xml +0 -134
- data/test/files/formula_parse_error.xls +0 -0
- data/test/files/formula_parse_error.xml +0 -1833
- data/test/files/formula_string_error.xlsx +0 -0
- data/test/files/html-escape.ods +0 -0
- data/test/files/link.xls +0 -0
- data/test/files/link.xlsx +0 -0
- data/test/files/matrix.ods +0 -0
- data/test/files/matrix.xls +0 -0
- data/test/files/named_cells.ods +0 -0
- data/test/files/named_cells.xls +0 -0
- data/test/files/named_cells.xlsx +0 -0
- data/test/files/no_spreadsheet_file.txt +0 -1
- data/test/files/numbers1.csv +0 -18
- data/test/files/numbers1.ods +0 -0
- data/test/files/numbers1.xls +0 -0
- data/test/files/numbers1.xlsx +0 -0
- data/test/files/numbers1.xml +0 -312
- data/test/files/numeric-link.xlsx +0 -0
- data/test/files/only_one_sheet.ods +0 -0
- data/test/files/only_one_sheet.xls +0 -0
- data/test/files/only_one_sheet.xlsx +0 -0
- data/test/files/only_one_sheet.xml +0 -67
- data/test/files/paragraph.ods +0 -0
- data/test/files/paragraph.xls +0 -0
- data/test/files/paragraph.xlsx +0 -0
- data/test/files/paragraph.xml +0 -127
- data/test/files/prova.xls +0 -0
- data/test/files/ric.ods +0 -0
- data/test/files/simple_spreadsheet.ods +0 -0
- data/test/files/simple_spreadsheet.xls +0 -0
- data/test/files/simple_spreadsheet.xlsx +0 -0
- data/test/files/simple_spreadsheet.xml +0 -225
- data/test/files/simple_spreadsheet_from_italo.ods +0 -0
- data/test/files/simple_spreadsheet_from_italo.xls +0 -0
- data/test/files/simple_spreadsheet_from_italo.xml +0 -242
- data/test/files/so_datetime.csv +0 -7
- data/test/files/style.ods +0 -0
- data/test/files/style.xls +0 -0
- data/test/files/style.xlsx +0 -0
- data/test/files/style.xml +0 -154
- data/test/files/time-test.csv +0 -2
- data/test/files/time-test.ods +0 -0
- data/test/files/time-test.xls +0 -0
- data/test/files/time-test.xlsx +0 -0
- data/test/files/time-test.xml +0 -131
- data/test/files/type_excel.ods +0 -0
- data/test/files/type_excel.xlsx +0 -0
- data/test/files/type_excelx.ods +0 -0
- data/test/files/type_excelx.xls +0 -0
- data/test/files/type_openoffice.xls +0 -0
- data/test/files/type_openoffice.xlsx +0 -0
- data/test/files/whitespace.ods +0 -0
- data/test/files/whitespace.xls +0 -0
- data/test/files/whitespace.xlsx +0 -0
- data/test/files/whitespace.xml +0 -184
- data/test/rm_sub_test.rb +0 -12
- data/test/rm_test.rb +0 -7
- data/test/test_generic_spreadsheet.rb +0 -259
- data/website/index.html +0 -385
- data/website/index.txt +0 -423
- data/website/javascripts/rounded_corners_lite.inc.js +0 -285
- data/website/stylesheets/screen.css +0 -130
- data/website/template.rhtml +0 -48
|
@@ -2,18 +2,28 @@ require 'spec_helper'
|
|
|
2
2
|
|
|
3
3
|
describe Roo::LibreOffice do
|
|
4
4
|
describe '.new' do
|
|
5
|
-
subject
|
|
5
|
+
subject do
|
|
6
6
|
Roo::LibreOffice.new('test/files/numbers1.ods')
|
|
7
|
-
|
|
7
|
+
end
|
|
8
8
|
|
|
9
9
|
it 'creates an instance' do
|
|
10
10
|
expect(subject).to be_a(Roo::LibreOffice)
|
|
11
11
|
end
|
|
12
12
|
end
|
|
13
|
-
end
|
|
14
13
|
|
|
15
|
-
describe
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
describe '#sheets' do
|
|
15
|
+
let(:path) { 'test/files/hidden_sheets.ods' }
|
|
16
|
+
|
|
17
|
+
describe 'showing all sheets' do
|
|
18
|
+
it 'returns the expected result' do
|
|
19
|
+
expect(Roo::LibreOffice.new(path).sheets).to eq ["HiddenSheet1", "VisibleSheet1", "HiddenSheet2"]
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
describe 'only showing visible sheets' do
|
|
24
|
+
it 'returns the expected result' do
|
|
25
|
+
expect(Roo::LibreOffice.new(path, only_visible_sheets: true).sheets).to eq ["VisibleSheet1"]
|
|
26
|
+
end
|
|
27
|
+
end
|
|
18
28
|
end
|
|
19
29
|
end
|
|
@@ -2,20 +2,42 @@ require 'spec_helper'
|
|
|
2
2
|
|
|
3
3
|
describe Roo::OpenOffice do
|
|
4
4
|
describe '.new' do
|
|
5
|
-
subject
|
|
5
|
+
subject do
|
|
6
6
|
Roo::OpenOffice.new('test/files/numbers1.ods')
|
|
7
|
-
|
|
7
|
+
end
|
|
8
8
|
|
|
9
9
|
it 'creates an instance' do
|
|
10
10
|
expect(subject).to be_a(Roo::OpenOffice)
|
|
11
11
|
end
|
|
12
|
-
end
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
context 'for float/integer values' do
|
|
14
|
+
context 'integer without point' do
|
|
15
|
+
it { expect(subject.cell(3,"A","Sheet4")).to eq(1234) }
|
|
16
|
+
it { expect(subject.cell(3,"A","Sheet4")).to be_a(Integer) }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
context 'float with point' do
|
|
20
|
+
it { expect(subject.cell(3,"B","Sheet4")).to eq(1234.00) }
|
|
21
|
+
it { expect(subject.cell(3,"B","Sheet4")).to be_a(Float) }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
context 'float with point' do
|
|
25
|
+
it { expect(subject.cell(3,"C","Sheet4")).to eq(1234.12) }
|
|
26
|
+
it { expect(subject.cell(3,"C","Sheet4")).to be_a(Float) }
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
context 'file path is a Pathname' do
|
|
31
|
+
subject do
|
|
32
|
+
Roo::OpenOffice.new(Pathname.new('test/files/numbers1.ods'))
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it 'creates an instance' do
|
|
36
|
+
expect(subject).to be_a(Roo::OpenOffice)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
16
39
|
|
|
17
|
-
describe Roo::Openoffice do
|
|
18
|
-
it 'is an alias of LibreOffice' do
|
|
19
|
-
expect(Roo::Openoffice).to eq(Roo::OpenOffice)
|
|
20
40
|
end
|
|
41
|
+
|
|
42
|
+
# OpenOffice is an alias of LibreOffice. See libreoffice_spec.
|
|
21
43
|
end
|
|
@@ -2,15 +2,34 @@ require 'spec_helper'
|
|
|
2
2
|
|
|
3
3
|
describe Roo::Spreadsheet do
|
|
4
4
|
describe '.open' do
|
|
5
|
+
context 'when the file name includes a space' do
|
|
6
|
+
let(:filename) { 'great scott.xlsx' }
|
|
7
|
+
|
|
8
|
+
it 'loads the proper type' do
|
|
9
|
+
expect(Roo::Excelx).to receive(:new).with(filename, {})
|
|
10
|
+
Roo::Spreadsheet.open(filename)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
5
14
|
context 'when the file extension is uppercase' do
|
|
6
|
-
let(:filename) { 'file.
|
|
15
|
+
let(:filename) { 'file.XLSX' }
|
|
7
16
|
|
|
8
17
|
it 'loads the proper type' do
|
|
9
|
-
expect(Roo::
|
|
18
|
+
expect(Roo::Excelx).to receive(:new).with(filename, {})
|
|
10
19
|
Roo::Spreadsheet.open(filename)
|
|
11
20
|
end
|
|
12
21
|
end
|
|
13
22
|
|
|
23
|
+
context 'for a tempfile' do
|
|
24
|
+
let(:tempfile) { Tempfile.new('foo.csv') }
|
|
25
|
+
let(:filename) { tempfile.path }
|
|
26
|
+
|
|
27
|
+
it 'loads the proper type' do
|
|
28
|
+
expect(Roo::CSV).to receive(:new).with(filename, {file_warning: :ignore}).and_call_original
|
|
29
|
+
expect(Roo::Spreadsheet.open(tempfile, extension: :csv)).to be_a(Roo::CSV)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
14
33
|
context 'for a url' do
|
|
15
34
|
context 'that is csv' do
|
|
16
35
|
let(:filename) { 'http://example.com/file.csv?with=params#and=anchor' }
|
|
@@ -22,35 +41,64 @@ describe Roo::Spreadsheet do
|
|
|
22
41
|
end
|
|
23
42
|
end
|
|
24
43
|
|
|
44
|
+
context 'for a windows path' do
|
|
45
|
+
context 'that is xlsx' do
|
|
46
|
+
let(:filename) { 'c:\Users\Joe\Desktop\myfile.xlsx' }
|
|
47
|
+
|
|
48
|
+
it 'loads the proper type' do
|
|
49
|
+
expect(Roo::Excelx).to receive(:new).with(filename, {})
|
|
50
|
+
Roo::Spreadsheet.open(filename)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
context 'for a xlsm file' do
|
|
56
|
+
let(:filename) { 'macros spreadsheet.xlsm' }
|
|
57
|
+
|
|
58
|
+
it 'loads the proper type' do
|
|
59
|
+
expect(Roo::Excelx).to receive(:new).with(filename, {})
|
|
60
|
+
Roo::Spreadsheet.open(filename)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
25
64
|
context 'for a csv file' do
|
|
26
65
|
let(:filename) { 'file.csv' }
|
|
27
|
-
let(:options) { {csv_options: {col_sep: '"'}} }
|
|
66
|
+
let(:options) { { csv_options: { col_sep: '"' } } }
|
|
28
67
|
|
|
29
|
-
context 'with
|
|
30
|
-
it 'passes the
|
|
68
|
+
context 'with csv_options' do
|
|
69
|
+
it 'passes the csv_options through' do
|
|
31
70
|
expect(Roo::CSV).to receive(:new).with(filename, options)
|
|
32
71
|
Roo::Spreadsheet.open(filename, options)
|
|
33
72
|
end
|
|
34
73
|
end
|
|
35
74
|
end
|
|
36
75
|
|
|
37
|
-
context '
|
|
76
|
+
context 'with a file extension option' do
|
|
38
77
|
let(:filename) { 'file.xls' }
|
|
39
78
|
|
|
40
|
-
context
|
|
41
|
-
let(:options) { { extension:
|
|
79
|
+
context ':xlsx' do
|
|
80
|
+
let(:options) { { extension: :xlsx } }
|
|
81
|
+
|
|
82
|
+
it 'loads with xls extension options' do
|
|
83
|
+
expect(Roo::Excelx).to receive(:new).with(filename, options)
|
|
84
|
+
Roo::Spreadsheet.open(filename, options)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
context 'xlsx' do
|
|
89
|
+
let(:options) { { extension: 'xlsx' } }
|
|
42
90
|
|
|
43
91
|
it 'loads with xls extension options' do
|
|
44
|
-
expect(Roo::
|
|
92
|
+
expect(Roo::Excelx).to receive(:new).with(filename, options)
|
|
45
93
|
Roo::Spreadsheet.open(filename, options)
|
|
46
94
|
end
|
|
47
95
|
end
|
|
48
96
|
|
|
49
|
-
context
|
|
50
|
-
let(:options) { { extension:
|
|
97
|
+
context '.xlsx' do
|
|
98
|
+
let(:options) { { extension: '.xlsx' } }
|
|
51
99
|
|
|
52
100
|
it 'loads with .xls extension options' do
|
|
53
|
-
expect(Roo::
|
|
101
|
+
expect(Roo::Excelx).to receive(:new).with(filename, options)
|
|
54
102
|
Roo::Spreadsheet.open(filename, options)
|
|
55
103
|
end
|
|
56
104
|
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
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
RSpec.describe ::Roo::Utils do
|
|
4
|
+
subject { described_class }
|
|
5
|
+
|
|
6
|
+
context '#number_to_letter' do
|
|
7
|
+
described_class::LETTERS.each_with_index do |letter, index|
|
|
8
|
+
it "should return '#{ letter }' when passed #{ index + 1 }" do
|
|
9
|
+
expect(described_class.number_to_letter(index + 1)).to eq(letter)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
{
|
|
14
|
+
27 => 'AA', 26*2 => 'AZ', 26*3 => 'BZ', 26**2 + 26 => 'ZZ', 26**2 + 27 => 'AAA',
|
|
15
|
+
26**3 + 26**2 + 26 => 'ZZZ', 1.0 => 'A', 676 => 'YZ', 677 => 'ZA'
|
|
16
|
+
}.each do |key, value|
|
|
17
|
+
it "should return '#{value}' when passed #{key}" do
|
|
18
|
+
expect(described_class.number_to_letter(key)).to eq(value)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
context '#letter_to_number' do
|
|
24
|
+
it "should give 1 for 'A' and 'a'" do
|
|
25
|
+
expect(described_class.letter_to_number('A')).to eq(1)
|
|
26
|
+
expect(described_class.letter_to_number('a')).to eq(1)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "should give the correct value for 'Z'" do
|
|
30
|
+
expect(described_class.letter_to_number('Z')).to eq(26)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "should give the correct value for 'AA' regardless of case mixing" do
|
|
34
|
+
%w(AA aA Aa aa).each do |key|
|
|
35
|
+
expect(described_class.letter_to_number(key)).to eq(27)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
{ 'AB' => 28, 'AZ' => 26*2, 'BZ' => 26*3, 'ZZ' => 26**2 + 26 }.each do |key, value|
|
|
40
|
+
it "should give the correct value for '#{key}'" do
|
|
41
|
+
expect(described_class.letter_to_number(key)).to eq(value)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
context '.extract_coordinate' do
|
|
47
|
+
it "returns the expected result" do
|
|
48
|
+
expect(described_class.extract_coordinate('A1')).to eq [1, 1]
|
|
49
|
+
expect(described_class.extract_coordinate('B2')).to eq [2, 2]
|
|
50
|
+
expect(described_class.extract_coordinate('R2')).to eq [2, 18]
|
|
51
|
+
expect(described_class.extract_coordinate('AR31')).to eq [31, 18 + 26]
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
context '.split_coord' do
|
|
56
|
+
it "returns the expected result" do
|
|
57
|
+
expect(described_class.split_coord('A1')).to eq ["A", 1]
|
|
58
|
+
expect(described_class.split_coord('B2')).to eq ["B", 2]
|
|
59
|
+
expect(described_class.split_coord('R2')).to eq ["R", 2]
|
|
60
|
+
expect(described_class.split_coord('AR31')).to eq ["AR", 31]
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "raises an error when appropriate" do
|
|
64
|
+
expect { described_class.split_coord('A') }.to raise_error(ArgumentError)
|
|
65
|
+
expect { described_class.split_coord('2') }.to raise_error(ArgumentError)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
context '.num_cells_in_range' do
|
|
71
|
+
it "returns the expected result" do
|
|
72
|
+
expect(described_class.num_cells_in_range('A1:B2')).to eq 4
|
|
73
|
+
expect(described_class.num_cells_in_range('B2:E3')).to eq 8
|
|
74
|
+
expect(described_class.num_cells_in_range('R2:Z10')).to eq 81
|
|
75
|
+
expect(described_class.num_cells_in_range('AR31:AR32')).to eq 2
|
|
76
|
+
expect(described_class.num_cells_in_range('A1')).to eq 1
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it "raises an error when appropriate" do
|
|
80
|
+
expect { described_class.num_cells_in_range('A1:B1:B2') }.to raise_error(ArgumentError)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
context '.coordinates_in_range' do
|
|
85
|
+
it "returns the expected result" do
|
|
86
|
+
expect(described_class.coordinates_in_range('').to_a).to eq []
|
|
87
|
+
expect(described_class.coordinates_in_range('B2').to_a).to eq [[2, 2]]
|
|
88
|
+
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]]
|
|
89
|
+
expect(described_class.coordinates_in_range('G3:D2').to_a).to eq []
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it "raises an error when appropriate" do
|
|
93
|
+
expect { described_class.coordinates_in_range('D2:G3:I5').to_a }.to raise_error(ArgumentError)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
context '.load_xml' do
|
|
98
|
+
it 'returns the expected result' do
|
|
99
|
+
expect(described_class.load_xml('test/files/sheet1.xml')).to be_a(Nokogiri::XML::Document)
|
|
100
|
+
expect(described_class.load_xml('test/files/sheet1.xml').
|
|
101
|
+
remove_namespaces!.xpath("/worksheet/dimension").map do |dim|
|
|
102
|
+
dim["ref"] end.first).to eq "A1:B11"
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
context '.each_element' do
|
|
107
|
+
it 'returns the expected result' do
|
|
108
|
+
described_class.each_element('test/files/sheet1.xml', 'dimension') do |dim|
|
|
109
|
+
expect(dim["ref"]).to eq "A1:B11"
|
|
110
|
+
end
|
|
111
|
+
rows = []
|
|
112
|
+
described_class.each_element('test/files/sheet1.xml', 'row') do |row|
|
|
113
|
+
rows << row
|
|
114
|
+
end
|
|
115
|
+
expect(rows.size).to eq 11
|
|
116
|
+
expect(rows[2]["r"]).to eq "3"
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
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
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
require
|
|
1
|
+
require 'simplecov'
|
|
2
|
+
require 'roo'
|
|
3
|
+
require 'helpers'
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
c.
|
|
7
|
-
c.hook_into :webmock # or :fakeweb
|
|
5
|
+
RSpec.configure do |c|
|
|
6
|
+
c.include Helpers
|
|
7
|
+
c.color = true
|
|
8
|
+
c.formatter = :documentation if ENV["USE_REPORTERS"]
|
|
8
9
|
end
|
data/test/all_ss.rb
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
require 'roo'
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
end
|
|
1
|
+
require 'roo'
|
|
2
|
+
|
|
3
|
+
Dir.glob('test/files/*.ods').each do |fn|
|
|
4
|
+
begin
|
|
5
|
+
oo = Roo::OpenOffice.new fn
|
|
6
|
+
print "#{File.basename(fn)} "
|
|
7
|
+
puts oo.officeversion
|
|
8
|
+
rescue Zip::ZipError, Errno::ENOENT => e
|
|
9
|
+
# file is not a real .ods spreadsheet file
|
|
10
|
+
puts e.message
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
require "test_helper"
|
|
2
|
+
|
|
3
|
+
class TestAttrReaderDefault < Minitest::Test
|
|
4
|
+
def base
|
|
5
|
+
Roo::Excelx::Cell::Base
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def boolean
|
|
9
|
+
Roo::Excelx::Cell::Boolean
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def class_date
|
|
13
|
+
Roo::Excelx::Cell::Date
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def datetime
|
|
17
|
+
Roo::Excelx::Cell::DateTime
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def empty
|
|
21
|
+
Roo::Excelx::Cell::Empty
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def number
|
|
25
|
+
Roo::Excelx::Cell::Number
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def string
|
|
29
|
+
Roo::Excelx::Cell::String
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def base_date
|
|
33
|
+
::Date.new(1899, 12, 30)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def base_timestamp
|
|
37
|
+
::Date.new(1899, 12, 30).to_datetime.to_time.to_i
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def class_time
|
|
41
|
+
Roo::Excelx::Cell::Time
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def test_cell_default_values
|
|
45
|
+
assert_values base.new(nil, nil, [], 1, nil, nil), default_type: :base, :@default_type => nil, style: 1, :@style => nil
|
|
46
|
+
assert_values boolean.new("1", nil, nil, nil, nil), default_type: :boolean, :@default_type => nil, cell_type: :boolean, :@cell_type => nil
|
|
47
|
+
assert_values class_date.new("41791", nil, [:numeric_or_formula, "mm-dd-yy"], 6, nil, base_date, nil), default_type: :date, :@default_type => nil
|
|
48
|
+
assert_values class_time.new("0.521", nil, [:numeric_or_formula, "hh:mm"], 6, nil, base_timestamp, nil), default_type: :time, :@default_type => nil
|
|
49
|
+
assert_values datetime.new("41791.521", nil, [:numeric_or_formula, "mm-dd-yy hh:mm"], 6, nil, base_timestamp, nil), default_type: :datetime, :@default_type => nil
|
|
50
|
+
assert_values empty.new(nil), default_type: nil, :@default_type => nil, style: nil, :@style => nil
|
|
51
|
+
assert_values number.new("42", nil, ["0"], nil, nil, nil), default_type: :float, :@default_type => nil
|
|
52
|
+
assert_values string.new("1", nil, nil, nil, nil), default_type: :string, :@default_type => nil, cell_type: :string, :@cell_type => nil
|
|
53
|
+
|
|
54
|
+
assert_values base.new(nil, nil, [], 2, nil, nil), style: 2, :@style => 2
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def assert_values(object, value_hash)
|
|
58
|
+
value_hash.each do |attr_name, expected_value|
|
|
59
|
+
value = if attr_name.to_s.include?("@")
|
|
60
|
+
object.instance_variable_defined?(attr_name) ? object.instance_variable_get(attr_name) : nil
|
|
61
|
+
else
|
|
62
|
+
object.public_send(attr_name)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
if expected_value
|
|
66
|
+
assert_equal expected_value, value
|
|
67
|
+
else
|
|
68
|
+
assert_nil value
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class TestRooExcelxCellBase < Minitest::Test
|
|
4
|
+
def base
|
|
5
|
+
Roo::Excelx::Cell::Base
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def value
|
|
9
|
+
'Hello World'
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def test_cell_type_is_base
|
|
13
|
+
cell = base.new(value, nil, [], nil, nil, nil)
|
|
14
|
+
assert_equal :base, cell.type
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def test_cell_value
|
|
18
|
+
cell_value = value
|
|
19
|
+
cell = base.new(cell_value, nil, [], nil, nil, nil)
|
|
20
|
+
assert_equal cell_value, cell.cell_value
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def test_not_empty?
|
|
24
|
+
cell = base.new(value, nil, [], nil, nil, nil)
|
|
25
|
+
refute cell.empty?
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def test_presence
|
|
29
|
+
cell = base.new(value, nil, [], nil, nil, nil)
|
|
30
|
+
assert_equal cell, cell.presence
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def test_cell_type_is_formula
|
|
34
|
+
formula = true
|
|
35
|
+
cell = base.new(value, formula, [], nil, nil, nil)
|
|
36
|
+
assert_equal :formula, cell.type
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def test_formula?
|
|
40
|
+
formula = true
|
|
41
|
+
cell = base.new(value, formula, [], nil, nil, nil)
|
|
42
|
+
assert cell.formula?
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def test_cell_type_is_link
|
|
46
|
+
link = 'http://example.com'
|
|
47
|
+
cell = base.new(value, nil, [], nil, link, nil)
|
|
48
|
+
assert_equal :link, cell.type
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def test_link?
|
|
52
|
+
link = 'http://example.com'
|
|
53
|
+
cell = base.new(value, nil, [], nil, link, nil)
|
|
54
|
+
assert cell.link?
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def test_link_value
|
|
58
|
+
link = 'http://example.com'
|
|
59
|
+
cell = base.new(value, nil, [], nil, link, nil)
|
|
60
|
+
assert_equal value, cell.value
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def test_link_value_href
|
|
64
|
+
link = 'http://example.com'
|
|
65
|
+
cell = base.new(value, nil, [], nil, link, nil)
|
|
66
|
+
assert_equal link, cell.value.href
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class TestRooExcelxCellNumber < Minitest::Test
|
|
4
|
+
def boolean
|
|
5
|
+
Roo::Excelx::Cell::Boolean
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def test_formatted_value
|
|
9
|
+
cell = boolean.new '1', nil, nil, nil, nil
|
|
10
|
+
assert_equal 'TRUE', cell.formatted_value
|
|
11
|
+
|
|
12
|
+
cell = boolean.new '0', nil, nil, nil, nil
|
|
13
|
+
assert_equal 'FALSE', cell.formatted_value
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def test_to_s
|
|
17
|
+
cell = boolean.new '1', nil, nil, nil, nil
|
|
18
|
+
assert_equal 'TRUE', cell.to_s
|
|
19
|
+
|
|
20
|
+
cell = boolean.new '0', nil, nil, nil, nil
|
|
21
|
+
assert_equal 'FALSE', cell.to_s
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def test_cell_value
|
|
25
|
+
cell = boolean.new '1', nil, nil, nil, nil
|
|
26
|
+
assert_equal '1', cell.cell_value
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def test_value
|
|
30
|
+
cell = boolean.new '1', nil, nil, nil, nil
|
|
31
|
+
assert_equal true, cell.value
|
|
32
|
+
|
|
33
|
+
cell = boolean.new '0', nil, nil, nil, nil
|
|
34
|
+
assert_equal false, cell.value
|
|
35
|
+
end
|
|
36
|
+
end
|