roo 1.13.2 → 2.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (236) hide show
  1. checksums.yaml +5 -5
  2. data/.codeclimate.yml +17 -0
  3. data/.github/issue_template.md +16 -0
  4. data/.github/pull_request_template.md +14 -0
  5. data/.github/workflows/pull-request.yml +15 -0
  6. data/.github/workflows/ruby.yml +34 -0
  7. data/.gitignore +11 -0
  8. data/.rubocop.yml +186 -0
  9. data/.simplecov +4 -0
  10. data/CHANGELOG.md +702 -0
  11. data/Gemfile +18 -12
  12. data/Guardfile +23 -0
  13. data/LICENSE +5 -1
  14. data/README.md +328 -0
  15. data/Rakefile +23 -23
  16. data/examples/roo_soap_client.rb +28 -31
  17. data/examples/roo_soap_server.rb +4 -6
  18. data/examples/write_me.rb +9 -10
  19. data/lib/roo/base.rb +317 -504
  20. data/lib/roo/constants.rb +7 -0
  21. data/lib/roo/csv.rb +141 -113
  22. data/lib/roo/errors.rb +11 -0
  23. data/lib/roo/excelx/cell/base.rb +108 -0
  24. data/lib/roo/excelx/cell/boolean.rb +30 -0
  25. data/lib/roo/excelx/cell/date.rb +28 -0
  26. data/lib/roo/excelx/cell/datetime.rb +107 -0
  27. data/lib/roo/excelx/cell/empty.rb +20 -0
  28. data/lib/roo/excelx/cell/number.rb +99 -0
  29. data/lib/roo/excelx/cell/string.rb +19 -0
  30. data/lib/roo/excelx/cell/time.rb +44 -0
  31. data/lib/roo/excelx/cell.rb +110 -0
  32. data/lib/roo/excelx/comments.rb +55 -0
  33. data/lib/roo/excelx/coordinate.rb +19 -0
  34. data/lib/roo/excelx/extractor.rb +39 -0
  35. data/lib/roo/excelx/format.rb +71 -0
  36. data/lib/roo/excelx/images.rb +26 -0
  37. data/lib/roo/excelx/relationships.rb +33 -0
  38. data/lib/roo/excelx/shared.rb +39 -0
  39. data/lib/roo/excelx/shared_strings.rb +151 -0
  40. data/lib/roo/excelx/sheet.rb +151 -0
  41. data/lib/roo/excelx/sheet_doc.rb +257 -0
  42. data/lib/roo/excelx/styles.rb +64 -0
  43. data/lib/roo/excelx/workbook.rb +64 -0
  44. data/lib/roo/excelx.rb +407 -601
  45. data/lib/roo/font.rb +17 -0
  46. data/lib/roo/formatters/base.rb +15 -0
  47. data/lib/roo/formatters/csv.rb +84 -0
  48. data/lib/roo/formatters/matrix.rb +23 -0
  49. data/lib/roo/formatters/xml.rb +31 -0
  50. data/lib/roo/formatters/yaml.rb +40 -0
  51. data/lib/roo/helpers/default_attr_reader.rb +20 -0
  52. data/lib/roo/helpers/weak_instance_cache.rb +41 -0
  53. data/lib/roo/libre_office.rb +4 -0
  54. data/lib/roo/link.rb +34 -0
  55. data/lib/roo/open_office.rb +631 -0
  56. data/lib/roo/spreadsheet.rb +28 -23
  57. data/lib/roo/tempdir.rb +24 -0
  58. data/lib/roo/utils.rb +128 -0
  59. data/lib/roo/version.rb +3 -0
  60. data/lib/roo.rb +26 -24
  61. data/roo.gemspec +29 -203
  62. data/spec/helpers.rb +5 -0
  63. data/spec/lib/roo/base_spec.rb +291 -3
  64. data/spec/lib/roo/csv_spec.rb +38 -11
  65. data/spec/lib/roo/excelx/cell/time_spec.rb +15 -0
  66. data/spec/lib/roo/excelx/format_spec.rb +7 -6
  67. data/spec/lib/roo/excelx/relationships_spec.rb +43 -0
  68. data/spec/lib/roo/excelx/sheet_doc_spec.rb +11 -0
  69. data/spec/lib/roo/excelx_spec.rb +672 -11
  70. data/spec/lib/roo/libreoffice_spec.rb +16 -6
  71. data/spec/lib/roo/openoffice_spec.rb +30 -8
  72. data/spec/lib/roo/spreadsheet_spec.rb +60 -12
  73. data/spec/lib/roo/strict_spec.rb +43 -0
  74. data/spec/lib/roo/utils_spec.rb +119 -0
  75. data/spec/lib/roo/weak_instance_cache_spec.rb +92 -0
  76. data/spec/lib/roo_spec.rb +0 -0
  77. data/spec/spec_helper.rb +7 -6
  78. data/test/all_ss.rb +12 -11
  79. data/test/excelx/cell/test_attr_reader_default.rb +72 -0
  80. data/test/excelx/cell/test_base.rb +68 -0
  81. data/test/excelx/cell/test_boolean.rb +36 -0
  82. data/test/excelx/cell/test_date.rb +38 -0
  83. data/test/excelx/cell/test_datetime.rb +45 -0
  84. data/test/excelx/cell/test_empty.rb +18 -0
  85. data/test/excelx/cell/test_number.rb +90 -0
  86. data/test/excelx/cell/test_string.rb +48 -0
  87. data/test/excelx/cell/test_time.rb +30 -0
  88. data/test/excelx/test_coordinate.rb +51 -0
  89. data/test/formatters/test_csv.rb +136 -0
  90. data/test/formatters/test_matrix.rb +76 -0
  91. data/test/formatters/test_xml.rb +78 -0
  92. data/test/formatters/test_yaml.rb +20 -0
  93. data/test/helpers/test_accessing_files.rb +81 -0
  94. data/test/helpers/test_comments.rb +43 -0
  95. data/test/helpers/test_formulas.rb +9 -0
  96. data/test/helpers/test_labels.rb +103 -0
  97. data/test/helpers/test_sheets.rb +55 -0
  98. data/test/helpers/test_styles.rb +62 -0
  99. data/test/roo/test_base.rb +182 -0
  100. data/test/roo/test_csv.rb +88 -0
  101. data/test/roo/test_excelx.rb +360 -0
  102. data/test/roo/test_libre_office.rb +9 -0
  103. data/test/roo/test_open_office.rb +289 -0
  104. data/test/test_helper.rb +123 -59
  105. data/test/test_roo.rb +392 -2292
  106. metadata +153 -298
  107. data/CHANGELOG +0 -417
  108. data/Gemfile.lock +0 -78
  109. data/README.markdown +0 -126
  110. data/VERSION +0 -1
  111. data/lib/roo/excel.rb +0 -355
  112. data/lib/roo/excel2003xml.rb +0 -300
  113. data/lib/roo/google.rb +0 -292
  114. data/lib/roo/openoffice.rb +0 -496
  115. data/lib/roo/roo_rails_helper.rb +0 -83
  116. data/lib/roo/worksheet.rb +0 -18
  117. data/scripts/txt2html +0 -67
  118. data/spec/lib/roo/excel2003xml_spec.rb +0 -15
  119. data/spec/lib/roo/excel_spec.rb +0 -17
  120. data/spec/lib/roo/google_spec.rb +0 -64
  121. data/test/files/1900_base.xls +0 -0
  122. data/test/files/1900_base.xlsx +0 -0
  123. data/test/files/1904_base.xls +0 -0
  124. data/test/files/1904_base.xlsx +0 -0
  125. data/test/files/Bibelbund.csv +0 -3741
  126. data/test/files/Bibelbund.ods +0 -0
  127. data/test/files/Bibelbund.xls +0 -0
  128. data/test/files/Bibelbund.xlsx +0 -0
  129. data/test/files/Bibelbund.xml +0 -62518
  130. data/test/files/Bibelbund1.ods +0 -0
  131. data/test/files/Pfand_from_windows_phone.xlsx +0 -0
  132. data/test/files/bad_excel_date.xls +0 -0
  133. data/test/files/bbu.ods +0 -0
  134. data/test/files/bbu.xls +0 -0
  135. data/test/files/bbu.xlsx +0 -0
  136. data/test/files/bbu.xml +0 -152
  137. data/test/files/bode-v1.ods.zip +0 -0
  138. data/test/files/bode-v1.xls.zip +0 -0
  139. data/test/files/boolean.csv +0 -2
  140. data/test/files/boolean.ods +0 -0
  141. data/test/files/boolean.xls +0 -0
  142. data/test/files/boolean.xlsx +0 -0
  143. data/test/files/boolean.xml +0 -112
  144. data/test/files/borders.ods +0 -0
  145. data/test/files/borders.xls +0 -0
  146. data/test/files/borders.xlsx +0 -0
  147. data/test/files/borders.xml +0 -144
  148. data/test/files/bug-numbered-sheet-names.xlsx +0 -0
  149. data/test/files/bug-row-column-fixnum-float.xls +0 -0
  150. data/test/files/bug-row-column-fixnum-float.xml +0 -127
  151. data/test/files/comments.ods +0 -0
  152. data/test/files/comments.xls +0 -0
  153. data/test/files/comments.xlsx +0 -0
  154. data/test/files/csvtypes.csv +0 -1
  155. data/test/files/datetime.ods +0 -0
  156. data/test/files/datetime.xls +0 -0
  157. data/test/files/datetime.xlsx +0 -0
  158. data/test/files/datetime.xml +0 -142
  159. data/test/files/datetime_floatconv.xls +0 -0
  160. data/test/files/datetime_floatconv.xml +0 -148
  161. data/test/files/dreimalvier.ods +0 -0
  162. data/test/files/emptysheets.ods +0 -0
  163. data/test/files/emptysheets.xls +0 -0
  164. data/test/files/emptysheets.xlsx +0 -0
  165. data/test/files/emptysheets.xml +0 -105
  166. data/test/files/excel2003.xml +0 -21140
  167. data/test/files/false_encoding.xls +0 -0
  168. data/test/files/false_encoding.xml +0 -132
  169. data/test/files/file_item_error.xlsx +0 -0
  170. data/test/files/formula.ods +0 -0
  171. data/test/files/formula.xls +0 -0
  172. data/test/files/formula.xlsx +0 -0
  173. data/test/files/formula.xml +0 -134
  174. data/test/files/formula_parse_error.xls +0 -0
  175. data/test/files/formula_parse_error.xml +0 -1833
  176. data/test/files/formula_string_error.xlsx +0 -0
  177. data/test/files/html-escape.ods +0 -0
  178. data/test/files/link.xls +0 -0
  179. data/test/files/link.xlsx +0 -0
  180. data/test/files/matrix.ods +0 -0
  181. data/test/files/matrix.xls +0 -0
  182. data/test/files/named_cells.ods +0 -0
  183. data/test/files/named_cells.xls +0 -0
  184. data/test/files/named_cells.xlsx +0 -0
  185. data/test/files/no_spreadsheet_file.txt +0 -1
  186. data/test/files/numbers1.csv +0 -18
  187. data/test/files/numbers1.ods +0 -0
  188. data/test/files/numbers1.xls +0 -0
  189. data/test/files/numbers1.xlsx +0 -0
  190. data/test/files/numbers1.xml +0 -312
  191. data/test/files/numeric-link.xlsx +0 -0
  192. data/test/files/only_one_sheet.ods +0 -0
  193. data/test/files/only_one_sheet.xls +0 -0
  194. data/test/files/only_one_sheet.xlsx +0 -0
  195. data/test/files/only_one_sheet.xml +0 -67
  196. data/test/files/paragraph.ods +0 -0
  197. data/test/files/paragraph.xls +0 -0
  198. data/test/files/paragraph.xlsx +0 -0
  199. data/test/files/paragraph.xml +0 -127
  200. data/test/files/prova.xls +0 -0
  201. data/test/files/ric.ods +0 -0
  202. data/test/files/simple_spreadsheet.ods +0 -0
  203. data/test/files/simple_spreadsheet.xls +0 -0
  204. data/test/files/simple_spreadsheet.xlsx +0 -0
  205. data/test/files/simple_spreadsheet.xml +0 -225
  206. data/test/files/simple_spreadsheet_from_italo.ods +0 -0
  207. data/test/files/simple_spreadsheet_from_italo.xls +0 -0
  208. data/test/files/simple_spreadsheet_from_italo.xml +0 -242
  209. data/test/files/so_datetime.csv +0 -7
  210. data/test/files/style.ods +0 -0
  211. data/test/files/style.xls +0 -0
  212. data/test/files/style.xlsx +0 -0
  213. data/test/files/style.xml +0 -154
  214. data/test/files/time-test.csv +0 -2
  215. data/test/files/time-test.ods +0 -0
  216. data/test/files/time-test.xls +0 -0
  217. data/test/files/time-test.xlsx +0 -0
  218. data/test/files/time-test.xml +0 -131
  219. data/test/files/type_excel.ods +0 -0
  220. data/test/files/type_excel.xlsx +0 -0
  221. data/test/files/type_excelx.ods +0 -0
  222. data/test/files/type_excelx.xls +0 -0
  223. data/test/files/type_openoffice.xls +0 -0
  224. data/test/files/type_openoffice.xlsx +0 -0
  225. data/test/files/whitespace.ods +0 -0
  226. data/test/files/whitespace.xls +0 -0
  227. data/test/files/whitespace.xlsx +0 -0
  228. data/test/files/whitespace.xml +0 -184
  229. data/test/rm_sub_test.rb +0 -12
  230. data/test/rm_test.rb +0 -7
  231. data/test/test_generic_spreadsheet.rb +0 -259
  232. data/website/index.html +0 -385
  233. data/website/index.txt +0 -423
  234. data/website/javascripts/rounded_corners_lite.inc.js +0 -285
  235. data/website/stylesheets/screen.css +0 -130
  236. data/website/template.rhtml +0 -48
@@ -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 Roo::Libreoffice do
16
- it 'is an alias of LibreOffice' do
17
- expect(Roo::Libreoffice).to eq(Roo::LibreOffice)
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
- # OpenOffice is an alias of LibreOffice. See libreoffice_spec.
15
- end
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.XLS' }
15
+ let(:filename) { 'file.XLSX' }
7
16
 
8
17
  it 'loads the proper type' do
9
- expect(Roo::Excel).to receive(:new).with(filename, {})
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 options' do
30
- it 'passes the options through' do
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 'when the file extension' do
76
+ context 'with a file extension option' do
38
77
  let(:filename) { 'file.xls' }
39
78
 
40
- context "is xls" do
41
- let(:options) { { extension: "xls" } }
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::Excel).to receive(:new).with(filename, options)
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 "is .xls" do
50
- let(:options) { { extension: ".xls" } }
97
+ context '.xlsx' do
98
+ let(:options) { { extension: '.xlsx' } }
51
99
 
52
100
  it 'loads with .xls extension options' do
53
- expect(Roo::Excel).to receive(:new).with(filename, options)
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 File.expand_path("../../lib/roo", __FILE__)
1
+ require 'simplecov'
2
+ require 'roo'
3
+ require 'helpers'
2
4
 
3
- require 'vcr'
4
-
5
- VCR.configure do |c|
6
- c.cassette_library_dir = 'spec/fixtures/vcr_cassettes'
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
- Dir.glob("test/files/*.ods").each do |fn|
3
- begin
4
- oo = Roo::OpenOffice.new fn
5
- print File.basename(fn) + " "
6
- puts oo.officeversion
7
- rescue Zip::ZipError, Errno::ENOENT => e
8
- # file is not a real .ods spreadsheet file
9
- puts e.message
10
- end
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