roo 1.13.2 → 2.7.0

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 (216) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +17 -0
  3. data/.github/ISSUE_TEMPLATE +10 -0
  4. data/.gitignore +11 -0
  5. data/.simplecov +4 -0
  6. data/.travis.yml +17 -0
  7. data/CHANGELOG.md +626 -0
  8. data/Gemfile +17 -12
  9. data/Gemfile_ruby2 +30 -0
  10. data/Guardfile +23 -0
  11. data/LICENSE +3 -1
  12. data/README.md +285 -0
  13. data/Rakefile +23 -23
  14. data/examples/roo_soap_client.rb +28 -31
  15. data/examples/roo_soap_server.rb +4 -6
  16. data/examples/write_me.rb +9 -10
  17. data/lib/roo/base.rb +298 -495
  18. data/lib/roo/constants.rb +5 -0
  19. data/lib/roo/csv.rb +127 -113
  20. data/lib/roo/errors.rb +11 -0
  21. data/lib/roo/excelx/cell/base.rb +94 -0
  22. data/lib/roo/excelx/cell/boolean.rb +27 -0
  23. data/lib/roo/excelx/cell/date.rb +28 -0
  24. data/lib/roo/excelx/cell/datetime.rb +111 -0
  25. data/lib/roo/excelx/cell/empty.rb +19 -0
  26. data/lib/roo/excelx/cell/number.rb +87 -0
  27. data/lib/roo/excelx/cell/string.rb +19 -0
  28. data/lib/roo/excelx/cell/time.rb +43 -0
  29. data/lib/roo/excelx/cell.rb +106 -0
  30. data/lib/roo/excelx/comments.rb +55 -0
  31. data/lib/roo/excelx/coordinate.rb +12 -0
  32. data/lib/roo/excelx/extractor.rb +21 -0
  33. data/lib/roo/excelx/format.rb +64 -0
  34. data/lib/roo/excelx/relationships.rb +25 -0
  35. data/lib/roo/excelx/shared.rb +32 -0
  36. data/lib/roo/excelx/shared_strings.rb +157 -0
  37. data/lib/roo/excelx/sheet.rb +112 -0
  38. data/lib/roo/excelx/sheet_doc.rb +211 -0
  39. data/lib/roo/excelx/styles.rb +64 -0
  40. data/lib/roo/excelx/workbook.rb +59 -0
  41. data/lib/roo/excelx.rb +376 -602
  42. data/lib/roo/font.rb +17 -0
  43. data/lib/roo/formatters/base.rb +15 -0
  44. data/lib/roo/formatters/csv.rb +84 -0
  45. data/lib/roo/formatters/matrix.rb +23 -0
  46. data/lib/roo/formatters/xml.rb +31 -0
  47. data/lib/roo/formatters/yaml.rb +40 -0
  48. data/lib/roo/libre_office.rb +4 -0
  49. data/lib/roo/link.rb +34 -0
  50. data/lib/roo/open_office.rb +626 -0
  51. data/lib/roo/spreadsheet.rb +22 -23
  52. data/lib/roo/tempdir.rb +21 -0
  53. data/lib/roo/utils.rb +78 -0
  54. data/lib/roo/version.rb +3 -0
  55. data/lib/roo.rb +23 -24
  56. data/roo.gemspec +21 -204
  57. data/spec/helpers.rb +5 -0
  58. data/spec/lib/roo/base_spec.rb +229 -3
  59. data/spec/lib/roo/csv_spec.rb +38 -11
  60. data/spec/lib/roo/excelx/format_spec.rb +7 -6
  61. data/spec/lib/roo/excelx_spec.rb +510 -11
  62. data/spec/lib/roo/libreoffice_spec.rb +16 -6
  63. data/spec/lib/roo/openoffice_spec.rb +30 -8
  64. data/spec/lib/roo/spreadsheet_spec.rb +60 -12
  65. data/spec/lib/roo/utils_spec.rb +106 -0
  66. data/spec/spec_helper.rb +7 -6
  67. data/test/all_ss.rb +12 -11
  68. data/test/excelx/cell/test_base.rb +63 -0
  69. data/test/excelx/cell/test_boolean.rb +36 -0
  70. data/test/excelx/cell/test_date.rb +38 -0
  71. data/test/excelx/cell/test_datetime.rb +45 -0
  72. data/test/excelx/cell/test_empty.rb +7 -0
  73. data/test/excelx/cell/test_number.rb +74 -0
  74. data/test/excelx/cell/test_string.rb +28 -0
  75. data/test/excelx/cell/test_time.rb +30 -0
  76. data/test/formatters/test_csv.rb +119 -0
  77. data/test/formatters/test_matrix.rb +76 -0
  78. data/test/formatters/test_xml.rb +74 -0
  79. data/test/formatters/test_yaml.rb +20 -0
  80. data/test/roo/test_csv.rb +52 -0
  81. data/test/roo/test_excelx.rb +186 -0
  82. data/test/roo/test_libre_office.rb +9 -0
  83. data/test/roo/test_open_office.rb +126 -0
  84. data/test/test_helper.rb +73 -53
  85. data/test/test_roo.rb +1211 -2292
  86. metadata +119 -298
  87. data/CHANGELOG +0 -417
  88. data/Gemfile.lock +0 -78
  89. data/README.markdown +0 -126
  90. data/VERSION +0 -1
  91. data/lib/roo/excel.rb +0 -355
  92. data/lib/roo/excel2003xml.rb +0 -300
  93. data/lib/roo/google.rb +0 -292
  94. data/lib/roo/openoffice.rb +0 -496
  95. data/lib/roo/roo_rails_helper.rb +0 -83
  96. data/lib/roo/worksheet.rb +0 -18
  97. data/scripts/txt2html +0 -67
  98. data/spec/lib/roo/excel2003xml_spec.rb +0 -15
  99. data/spec/lib/roo/excel_spec.rb +0 -17
  100. data/spec/lib/roo/google_spec.rb +0 -64
  101. data/test/files/1900_base.xls +0 -0
  102. data/test/files/1900_base.xlsx +0 -0
  103. data/test/files/1904_base.xls +0 -0
  104. data/test/files/1904_base.xlsx +0 -0
  105. data/test/files/Bibelbund.csv +0 -3741
  106. data/test/files/Bibelbund.ods +0 -0
  107. data/test/files/Bibelbund.xls +0 -0
  108. data/test/files/Bibelbund.xlsx +0 -0
  109. data/test/files/Bibelbund.xml +0 -62518
  110. data/test/files/Bibelbund1.ods +0 -0
  111. data/test/files/Pfand_from_windows_phone.xlsx +0 -0
  112. data/test/files/bad_excel_date.xls +0 -0
  113. data/test/files/bbu.ods +0 -0
  114. data/test/files/bbu.xls +0 -0
  115. data/test/files/bbu.xlsx +0 -0
  116. data/test/files/bbu.xml +0 -152
  117. data/test/files/bode-v1.ods.zip +0 -0
  118. data/test/files/bode-v1.xls.zip +0 -0
  119. data/test/files/boolean.csv +0 -2
  120. data/test/files/boolean.ods +0 -0
  121. data/test/files/boolean.xls +0 -0
  122. data/test/files/boolean.xlsx +0 -0
  123. data/test/files/boolean.xml +0 -112
  124. data/test/files/borders.ods +0 -0
  125. data/test/files/borders.xls +0 -0
  126. data/test/files/borders.xlsx +0 -0
  127. data/test/files/borders.xml +0 -144
  128. data/test/files/bug-numbered-sheet-names.xlsx +0 -0
  129. data/test/files/bug-row-column-fixnum-float.xls +0 -0
  130. data/test/files/bug-row-column-fixnum-float.xml +0 -127
  131. data/test/files/comments.ods +0 -0
  132. data/test/files/comments.xls +0 -0
  133. data/test/files/comments.xlsx +0 -0
  134. data/test/files/csvtypes.csv +0 -1
  135. data/test/files/datetime.ods +0 -0
  136. data/test/files/datetime.xls +0 -0
  137. data/test/files/datetime.xlsx +0 -0
  138. data/test/files/datetime.xml +0 -142
  139. data/test/files/datetime_floatconv.xls +0 -0
  140. data/test/files/datetime_floatconv.xml +0 -148
  141. data/test/files/dreimalvier.ods +0 -0
  142. data/test/files/emptysheets.ods +0 -0
  143. data/test/files/emptysheets.xls +0 -0
  144. data/test/files/emptysheets.xlsx +0 -0
  145. data/test/files/emptysheets.xml +0 -105
  146. data/test/files/excel2003.xml +0 -21140
  147. data/test/files/false_encoding.xls +0 -0
  148. data/test/files/false_encoding.xml +0 -132
  149. data/test/files/file_item_error.xlsx +0 -0
  150. data/test/files/formula.ods +0 -0
  151. data/test/files/formula.xls +0 -0
  152. data/test/files/formula.xlsx +0 -0
  153. data/test/files/formula.xml +0 -134
  154. data/test/files/formula_parse_error.xls +0 -0
  155. data/test/files/formula_parse_error.xml +0 -1833
  156. data/test/files/formula_string_error.xlsx +0 -0
  157. data/test/files/html-escape.ods +0 -0
  158. data/test/files/link.xls +0 -0
  159. data/test/files/link.xlsx +0 -0
  160. data/test/files/matrix.ods +0 -0
  161. data/test/files/matrix.xls +0 -0
  162. data/test/files/named_cells.ods +0 -0
  163. data/test/files/named_cells.xls +0 -0
  164. data/test/files/named_cells.xlsx +0 -0
  165. data/test/files/no_spreadsheet_file.txt +0 -1
  166. data/test/files/numbers1.csv +0 -18
  167. data/test/files/numbers1.ods +0 -0
  168. data/test/files/numbers1.xls +0 -0
  169. data/test/files/numbers1.xlsx +0 -0
  170. data/test/files/numbers1.xml +0 -312
  171. data/test/files/numeric-link.xlsx +0 -0
  172. data/test/files/only_one_sheet.ods +0 -0
  173. data/test/files/only_one_sheet.xls +0 -0
  174. data/test/files/only_one_sheet.xlsx +0 -0
  175. data/test/files/only_one_sheet.xml +0 -67
  176. data/test/files/paragraph.ods +0 -0
  177. data/test/files/paragraph.xls +0 -0
  178. data/test/files/paragraph.xlsx +0 -0
  179. data/test/files/paragraph.xml +0 -127
  180. data/test/files/prova.xls +0 -0
  181. data/test/files/ric.ods +0 -0
  182. data/test/files/simple_spreadsheet.ods +0 -0
  183. data/test/files/simple_spreadsheet.xls +0 -0
  184. data/test/files/simple_spreadsheet.xlsx +0 -0
  185. data/test/files/simple_spreadsheet.xml +0 -225
  186. data/test/files/simple_spreadsheet_from_italo.ods +0 -0
  187. data/test/files/simple_spreadsheet_from_italo.xls +0 -0
  188. data/test/files/simple_spreadsheet_from_italo.xml +0 -242
  189. data/test/files/so_datetime.csv +0 -7
  190. data/test/files/style.ods +0 -0
  191. data/test/files/style.xls +0 -0
  192. data/test/files/style.xlsx +0 -0
  193. data/test/files/style.xml +0 -154
  194. data/test/files/time-test.csv +0 -2
  195. data/test/files/time-test.ods +0 -0
  196. data/test/files/time-test.xls +0 -0
  197. data/test/files/time-test.xlsx +0 -0
  198. data/test/files/time-test.xml +0 -131
  199. data/test/files/type_excel.ods +0 -0
  200. data/test/files/type_excel.xlsx +0 -0
  201. data/test/files/type_excelx.ods +0 -0
  202. data/test/files/type_excelx.xls +0 -0
  203. data/test/files/type_openoffice.xls +0 -0
  204. data/test/files/type_openoffice.xlsx +0 -0
  205. data/test/files/whitespace.ods +0 -0
  206. data/test/files/whitespace.xls +0 -0
  207. data/test/files/whitespace.xlsx +0 -0
  208. data/test/files/whitespace.xml +0 -184
  209. data/test/rm_sub_test.rb +0 -12
  210. data/test/rm_test.rb +0 -7
  211. data/test/test_generic_spreadsheet.rb +0 -259
  212. data/website/index.html +0 -385
  213. data/website/index.txt +0 -423
  214. data/website/javascripts/rounded_corners_lite.inc.js +0 -285
  215. data/website/stylesheets/screen.css +0 -130
  216. data/website/template.rhtml +0 -48
@@ -10,12 +10,33 @@ describe Roo::CSV do
10
10
  end
11
11
  end
12
12
 
13
+ describe '.new with stream' do
14
+ let(:csv) { Roo::CSV.new(File.read(path)) }
15
+ it 'creates an instance' do
16
+ expect(csv).to be_a(Roo::CSV)
17
+ end
18
+ end
19
+
13
20
  describe '#parse' do
14
- subject {
21
+ subject do
15
22
  csv.parse(options)
16
- }
23
+ end
17
24
  context 'with headers: true' do
18
- let(:options) { {headers: true} }
25
+ let(:options) { { headers: true } }
26
+
27
+ it "doesn't blow up" do
28
+ expect { subject }.to_not raise_error
29
+ end
30
+ end
31
+ end
32
+
33
+ describe '#parse_with_clean_option' do
34
+ subject do
35
+ csv.parse(options)
36
+ end
37
+ context 'with clean: true' do
38
+ let(:options) { {clean: true} }
39
+ let(:path) { 'test/files/parse_with_clean_option.csv' }
19
40
 
20
41
  it "doesn't blow up" do
21
42
  expect { subject }.to_not raise_error
@@ -25,30 +46,36 @@ describe Roo::CSV do
25
46
 
26
47
  describe '#csv_options' do
27
48
  context 'when created with the csv_options option' do
28
- let(:options) {
49
+ let(:options) do
29
50
  {
30
51
  col_sep: '\t',
31
52
  quote_char: "'"
32
53
  }
33
- }
54
+ end
34
55
 
35
56
  it 'returns the csv options' do
36
57
  csv = Roo::CSV.new(path, csv_options: options)
37
- csv.csv_options.should == options
58
+ expect(csv.csv_options).to eq(options)
38
59
  end
39
60
  end
40
61
 
41
62
  context 'when created without the csv_options option' do
42
63
  it 'returns a hash' do
43
64
  csv = Roo::CSV.new(path)
44
- csv.csv_options.should == {}
65
+ expect(csv.csv_options).to eq({})
45
66
  end
46
67
  end
47
68
  end
48
- end
49
69
 
50
- describe Roo::Csv do
51
- it 'is an alias of LibreOffice' do
52
- expect(Roo::Csv).to eq(Roo::CSV)
70
+ describe '#set_value' do
71
+ it 'returns the cell value' do
72
+ expect(csv.set_value('A', 1, 'some-value', nil)).to eq('some-value')
73
+ end
74
+ end
75
+
76
+ describe '#set_type' do
77
+ it 'returns the cell type' do
78
+ expect(csv.set_type('A', 1, 'some-type', nil)).to eq('some-type')
79
+ end
53
80
  end
54
81
  end
@@ -11,8 +11,8 @@ describe Roo::Excelx::Format do
11
11
  '0%' => :percentage,
12
12
  '0.00%' => :percentage,
13
13
  '0.00E+00' => :float,
14
- '# ?/?' => :float, #??? TODO:
15
- '# ??/??' => :float, #??? TODO:
14
+ '# ?/?' => :float, # ??? TODO:
15
+ '# ??/??' => :float, # ??? TODO:
16
16
  'mm-dd-yy' => :date,
17
17
  'd-mmm-yy' => :date,
18
18
  'd-mmm' => :date,
@@ -33,17 +33,18 @@ describe Roo::Excelx::Format do
33
33
  '##0.0E+0' => :float,
34
34
  '@' => :float,
35
35
  #-- zusaetzliche Formate, die nicht standardmaessig definiert sind:
36
- "yyyy\\-mm\\-dd" => :date,
36
+ 'yyyy\\-mm\\-dd' => :date,
37
37
  'dd/mm/yy' => :date,
38
38
  'hh:mm:ss' => :time,
39
- "dd/mm/yy\\ hh:mm" => :datetime,
39
+ 'dd/mm/yy\\ hh:mm' => :datetime,
40
40
  'dd/mmm/yy\\ hh:mm' => :datetime,
41
41
  'dd/mmm/yy' => :date, # 2011-05-21
42
42
  'yyyy-mm-dd' => :date, # 2011-09-16
43
- 'yyyy-mm-dd;@' => :date
43
+ 'yyyy-mm-dd;@' => :date,
44
+ '#0_);[Red]\(0\)' => :float
44
45
  }.each do |format, type|
45
46
  it "translates #{format} to #{type}" do
46
- Roo::Excelx::Format.to_type(format).should == type
47
+ expect(Roo::Excelx::Format.to_type(format)).to eq(type)
47
48
  end
48
49
  end
49
50
  end
@@ -1,19 +1,56 @@
1
+ # encoding: utf-8
1
2
  require 'spec_helper'
2
3
 
3
4
  describe Roo::Excelx do
5
+ subject(:xlsx) do
6
+ Roo::Excelx.new(path)
7
+ end
8
+
9
+ describe 'Constants' do
10
+ describe 'ERROR_VALUES' do
11
+ it 'returns all possible errorr values' do
12
+ expect(described_class::ERROR_VALUES).to eq(%w(#N/A #REF! #NAME? #DIV/0! #NULL! #VALUE! #NUM!).to_set)
13
+ end
14
+
15
+ it 'is a set' do
16
+ expect(described_class::ERROR_VALUES).to be_an_instance_of(Set)
17
+ end
18
+ end
19
+ end
20
+
4
21
  describe '.new' do
5
- subject {
6
- Roo::Excelx.new('test/files/numbers1.xlsx')
7
- }
22
+ let(:path) { 'test/files/numeric-link.xlsx' }
8
23
 
9
24
  it 'creates an instance' do
10
25
  expect(subject).to be_a(Roo::Excelx)
11
26
  end
12
27
 
13
28
  context 'given a file with missing rels' do
14
- subject {
15
- Roo::Excelx.new('test/files/file_item_error.xlsx')
16
- }
29
+ let(:path) { 'test/files/file_item_error.xlsx' }
30
+
31
+ it 'creates an instance' do
32
+ expect(subject).to be_a(Roo::Excelx)
33
+ end
34
+ end
35
+
36
+ context 'with more cells than specified max' do
37
+ let(:path) { 'test/files/only_one_sheet.xlsx' }
38
+
39
+ it 'raises an appropriate error' do
40
+ expect { Roo::Excelx.new(path, cell_max: 1) }.to raise_error(Roo::Excelx::ExceedsMaxError)
41
+ end
42
+ end
43
+
44
+ context 'with fewer cells than specified max' do
45
+ let(:path) { 'test/files/only_one_sheet.xlsx' }
46
+
47
+ it 'creates an instance' do
48
+ expect(Roo::Excelx.new(path, cell_max: 100)).to be_a(Roo::Excelx)
49
+ end
50
+ end
51
+
52
+ context 'file path is a Pathname' do
53
+ let(:path) { Pathname.new('test/files/file_item_error.xlsx') }
17
54
 
18
55
  it 'creates an instance' do
19
56
  expect(subject).to be_a(Roo::Excelx)
@@ -24,15 +61,477 @@ describe Roo::Excelx do
24
61
  describe '#cell' do
25
62
  context 'for a link cell' do
26
63
  context 'with numeric contents' do
27
- subject {
28
- Roo::Excelx.new('test/files/numeric-link.xlsx').cell('A', 1)
29
- }
64
+ let(:path) { 'test/files/numeric-link.xlsx' }
65
+
66
+ subject do
67
+ xlsx.cell('A', 1)
68
+ end
30
69
 
31
70
  it 'returns a link with the number as a string value' do
32
- expect(subject).to be_a(Spreadsheet::Link)
33
- expect(subject).to eq("8675309.0")
71
+ expect(subject).to be_a(Roo::Link)
72
+ # FIXME: Because Link inherits from String, it is a String,
73
+ # But in theory, it shouldn't have to be a String.
74
+ # NOTE: This test is broken becase Cell::Numeric formats numbers
75
+ # more intelligently.
76
+ # expect(subject).to eq('8675309.0')
34
77
  end
35
78
  end
36
79
  end
80
+
81
+ context 'for a non-existent cell' do
82
+ let(:path) { 'test/files/numeric-link.xlsx' }
83
+ it 'return nil' do
84
+ expect(xlsx.cell('AAA', 999)).to eq nil
85
+ end
86
+ end
87
+ end
88
+
89
+ describe '#parse' do
90
+ let(:path) { 'test/files/numeric-link.xlsx' }
91
+
92
+ context 'with a columns hash' do
93
+ context 'when not present in the sheet' do
94
+ it 'does not raise' do
95
+ expect do
96
+ xlsx.sheet(0).parse(
97
+ this: 'This',
98
+ that: 'That'
99
+ )
100
+ end.to raise_error(Roo::HeaderRowNotFoundError)
101
+ end
102
+ end
103
+ end
104
+ end
105
+
106
+ describe '#parse_with_clean_option' do
107
+ let(:path) { 'test/files/parse_with_clean_option.xlsx' }
108
+ let(:options) { {clean: true} }
109
+
110
+ context 'with clean: true' do
111
+
112
+ it 'does not raise' do
113
+ expect do
114
+ xlsx.parse(options)
115
+ end.not_to raise_error
116
+ end
117
+ end
118
+ end
119
+
120
+ describe '#parse_unicode_with_clean_option' do
121
+ let(:path) { 'test/files/parse_clean_with_unicode.xlsx' }
122
+ let(:options) { {clean: true, name: 'Name'} }
123
+
124
+ context 'with clean: true' do
125
+ it 'returns a non empty string' do
126
+ expect(xlsx.parse(options).last[:name]).to eql('凯')
127
+ end
128
+ end
129
+ end
130
+
131
+ describe '#sheets' do
132
+ let(:path) { 'test/files/numbers1.xlsx' }
133
+
134
+ it 'returns the expected result' do
135
+ expect(subject.sheets).to eq ["Tabelle1", "Name of Sheet 2", "Sheet3", "Sheet4", "Sheet5"]
136
+ end
137
+
138
+ describe 'only showing visible sheets' do
139
+ let(:path) { 'test/files/hidden_sheets.xlsx' }
140
+
141
+ it 'returns the expected result' do
142
+ expect(Roo::Excelx.new(path, only_visible_sheets: true).sheets).to eq ["VisibleSheet1"]
143
+ end
144
+ end
145
+ end
146
+
147
+ describe '#sheet_for' do
148
+ let(:path) { 'test/files/numbers1.xlsx' }
149
+
150
+ # This is kinda gross
151
+ it 'returns the expected result' do
152
+ expect(subject.sheet_for("Tabelle1").instance_variable_get("@name")).to eq "Tabelle1"
153
+ end
154
+ end
155
+
156
+ describe '#row' do
157
+ let(:path) { 'test/files/numbers1.xlsx' }
158
+
159
+ it 'returns the expected result' do
160
+ expect(subject.row(1, "Sheet5")).to eq [1.0, 5.0, 5.0, nil, nil]
161
+ end
162
+ end
163
+
164
+ describe '#column' do
165
+ let(:path) { 'test/files/numbers1.xlsx' }
166
+
167
+ it 'returns the expected result' do
168
+ expect(subject.column(1, "Sheet5")).to eq [1.0, 2.0, 3.0, Date.new(2007,11,21), 42.0, "ABC"]
169
+ end
170
+ end
171
+
172
+ describe '#first_row' do
173
+ let(:path) { 'test/files/numbers1.xlsx' }
174
+
175
+ it 'returns the expected result' do
176
+ expect(subject.first_row("Sheet5")).to eq 1
177
+ end
178
+ end
179
+
180
+ describe '#last_row' do
181
+ let(:path) { 'test/files/numbers1.xlsx' }
182
+
183
+ it 'returns the expected result' do
184
+ expect(subject.last_row("Sheet5")).to eq 6
185
+ end
186
+ end
187
+
188
+ describe '#first_column' do
189
+ let(:path) { 'test/files/numbers1.xlsx' }
190
+
191
+ it 'returns the expected result' do
192
+ expect(subject.first_column("Sheet5")).to eq 1
193
+ end
194
+ end
195
+
196
+ describe '#last_column' do
197
+ let(:path) { 'test/files/numbers1.xlsx' }
198
+
199
+ it 'returns the expected result' do
200
+ expect(subject.last_column("Sheet5")).to eq 5
201
+ end
202
+ end
203
+
204
+ describe '#set' do
205
+ before do
206
+ subject.set(1, 2, "Foo", "Sheet5")
207
+ end
208
+
209
+ let(:path) { 'test/files/numbers1.xlsx' }
210
+ let(:cell) { subject.cell(1, 2, "Sheet5") }
211
+
212
+ it 'returns the expected result' do
213
+ expect(cell).to eq "Foo"
214
+ end
215
+ end
216
+
217
+ describe '#formula' do
218
+ let(:path) { 'test/files/formula.xlsx' }
219
+
220
+ it 'returns the expected result' do
221
+ expect(subject.formula(1, 1, "Sheet1")).to eq nil
222
+ expect(subject.formula(7, 2, "Sheet1")).to eq "SUM($A$1:B6)"
223
+ expect(subject.formula(1000, 2000, "Sheet1")).to eq nil
224
+ end
225
+ end
226
+
227
+ describe '#formula?' do
228
+ let(:path) { 'test/files/formula.xlsx' }
229
+
230
+ it 'returns the expected result' do
231
+ expect(subject.formula?(1, 1, "Sheet1")).to eq false
232
+ expect(subject.formula?(7, 2, "Sheet1")).to eq true
233
+ expect(subject.formula?(1000, 2000, "Sheet1")).to eq false
234
+ end
235
+ end
236
+
237
+ describe '#formulas' do
238
+ let(:path) { 'test/files/formula.xlsx' }
239
+
240
+ it 'returns the expected result' do
241
+ expect(subject.formulas("Sheet1")).to eq [[7, 1, "SUM(A1:A6)"], [7, 2, "SUM($A$1:B6)"]]
242
+ end
243
+ end
244
+
245
+ describe '#font' do
246
+ let(:path) { 'test/files/style.xlsx' }
247
+
248
+ it 'returns the expected result' do
249
+ expect(subject.font(1, 1).bold?).to eq true
250
+ expect(subject.font(1, 1).italic?).to eq false
251
+ expect(subject.font(1, 1).underline?).to eq false
252
+
253
+ expect(subject.font(7, 1).bold?).to eq false
254
+ expect(subject.font(7, 1).italic?).to eq true
255
+ expect(subject.font(7, 1).underline?).to eq true
256
+ expect(subject.font(1000, 2000)).to eq nil
257
+ end
258
+ end
259
+
260
+ describe '#celltype' do
261
+ let(:path) { 'test/files/numbers1.xlsx' }
262
+
263
+ it 'returns the expected result' do
264
+ expect(subject.celltype(1, 1, "Sheet4")).to eq :date
265
+ expect(subject.celltype(1, 2, "Sheet4")).to eq :float
266
+ expect(subject.celltype(6, 2, "Sheet5")).to eq :string
267
+ expect(subject.celltype(1000, 2000, "Sheet5")).to eq nil
268
+ end
269
+ end
270
+
271
+ describe '#excelx_type' do
272
+ let(:path) { 'test/files/numbers1.xlsx' }
273
+
274
+ it 'returns the expected result' do
275
+ expect(subject.excelx_type(1, 1, "Sheet5")).to eq [:numeric_or_formula, "General"]
276
+ expect(subject.excelx_type(6, 2, "Sheet5")).to eq :string
277
+ expect(subject.excelx_type(1000, 2000, "Sheet5")).to eq nil
278
+ end
279
+ end
280
+
281
+ # FIXME: IMO, these tests don't provide much value. Under what circumstances
282
+ # will a user require the "index" value for the shared strings table?
283
+ # Excel value should be the raw unformatted value for the cell.
284
+ describe '#excelx_value' do
285
+ let(:path) { 'test/files/numbers1.xlsx' }
286
+
287
+ it 'returns the expected result' do
288
+ # These values are the index in the shared strings table, might be a better
289
+ # way to get these rather than hardcoding.
290
+
291
+ # expect(subject.excelx_value(1, 1, "Sheet5")).to eq "1" # passes by accident
292
+ # expect(subject.excelx_value(6, 2, "Sheet5")).to eq "16"
293
+ # expect(subject.excelx_value(6000, 2000, "Sheet5")).to eq nil
294
+ end
295
+ end
296
+
297
+ describe '#formatted_value' do
298
+ context 'contains zero-padded numbers' do
299
+ let(:path) { 'test/files/zero-padded-number.xlsx' }
300
+
301
+ it 'returns a zero-padded number' do
302
+ expect(subject.formatted_value(4, 1)).to eq '05010'
303
+ end
304
+ end
305
+ end
306
+
307
+ describe '#excelx_format' do
308
+ let(:path) { 'test/files/style.xlsx' }
309
+
310
+ it 'returns the expected result' do
311
+ # These are the index of the style for a given document
312
+ # might be more reliable way to get this info.
313
+ expect(subject.excelx_format(1, 1)).to eq "General"
314
+ expect(subject.excelx_format(2, 2)).to eq "0.00"
315
+ expect(subject.excelx_format(5000, 1000)).to eq nil
316
+ end
317
+ end
318
+
319
+ describe '#empty?' do
320
+ let(:path) { 'test/files/style.xlsx' }
321
+
322
+ it 'returns the expected result' do
323
+ # These are the index of the style for a given document
324
+ # might be more reliable way to get this info.
325
+ expect(subject.empty?(1, 1)).to eq false
326
+ expect(subject.empty?(13, 1)).to eq true
327
+ end
328
+ end
329
+
330
+ describe '#label' do
331
+ let(:path) { 'test/files/named_cells.xlsx' }
332
+
333
+ it 'returns the expected result' do
334
+ expect(subject.label("berta")).to eq [4, 2, "Sheet1"]
335
+ expect(subject.label("dave")).to eq [nil, nil, nil]
336
+ end
337
+ end
338
+
339
+ describe '#labels' do
340
+ let(:path) { 'test/files/named_cells.xlsx' }
341
+
342
+ it 'returns the expected result' do
343
+ expect(subject.labels).to eq [["anton", [5, 3, "Sheet1"]], ["berta", [4, 2, "Sheet1"]], ["caesar", [7, 2, "Sheet1"]]]
344
+ end
345
+ end
346
+
347
+ describe '#hyperlink?' do
348
+ let(:path) { 'test/files/link.xlsx' }
349
+
350
+ it 'returns the expected result' do
351
+ expect(subject.hyperlink?(1, 1)).to eq true
352
+ expect(subject.hyperlink?(1, 2)).to eq false
353
+ end
354
+ end
355
+
356
+ describe '#hyperlink' do
357
+ let(:path) { 'test/files/link.xlsx' }
358
+
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
362
+ end
363
+ end
364
+
365
+ describe '#comment' do
366
+ let(:path) { 'test/files/comments.xlsx' }
367
+
368
+ it 'returns the expected result' do
369
+ expect(subject.comment(4, 2)).to eq "Kommentar fuer B4"
370
+ expect(subject.comment(1, 2)).to eq nil
371
+ end
372
+ end
373
+
374
+ describe '#comment?' do
375
+ let(:path) { 'test/files/comments.xlsx' }
376
+
377
+ it 'returns the expected result' do
378
+ expect(subject.comment?(4, 2)).to eq true
379
+ expect(subject.comment?(1, 2)).to eq false
380
+ end
381
+ end
382
+
383
+ describe '#comments' do
384
+ let(:path) { 'test/files/comments.xlsx' }
385
+
386
+ it 'returns the expected result' do
387
+ expect(subject.comments).to eq [[4, 2, "Kommentar fuer B4"], [5, 2, "Kommentar fuer B5"]]
388
+ end
389
+ end
390
+
391
+ # nil, nil, nil, nil, nil
392
+ # nil, nil, nil, nil, nil
393
+ # Date Start time End time Pause Sum Comment
394
+ # 2007-05-07 9.25 10.25 0 1 Task 1
395
+ # 2007-05-07 10.75 12.50 0 1.75 Task 1
396
+ # 2007-05-07 18.00 19.00 0 1 Task 2
397
+ # 2007-05-08 9.25 10.25 0 1 Task 2
398
+ # 2007-05-08 14.50 15.50 0 1 Task 3
399
+ # 2007-05-08 8.75 9.25 0 0.5 Task 3
400
+ # 2007-05-14 21.75 22.25 0 0.5 Task 3
401
+ # 2007-05-14 22.50 23.00 0 0.5 Task 3
402
+ # 2007-05-15 11.75 12.75 0 1 Task 3
403
+ # 2007-05-07 10.75 10.75 0 0 Task 1
404
+ # nil
405
+ describe '#each_row_streaming' do
406
+ let(:path) { 'test/files/simple_spreadsheet.xlsx' }
407
+
408
+ let(:expected_rows) do
409
+ [
410
+ [nil, nil, nil, nil, nil],
411
+ [nil, nil, nil, nil, nil],
412
+ ["Date", "Start time", "End time", "Pause", "Sum", "Comment", nil, nil],
413
+ [Date.new(2007, 5, 7), 9.25, 10.25, 0.0, 1.0, "Task 1"],
414
+ [Date.new(2007, 5, 7), 10.75, 12.50, 0.0, 1.75, "Task 1"],
415
+ [Date.new(2007, 5, 7), 18.0, 19.0, 0.0, 1.0, "Task 2"],
416
+ [Date.new(2007, 5, 8), 9.25, 10.25, 0.0, 1.0, "Task 2"],
417
+ [Date.new(2007, 5, 8), 14.5, 15.5, 0.0, 1.0, "Task 3"],
418
+ [Date.new(2007, 5, 8), 8.75, 9.25, 0.0, 0.5, "Task 3"],
419
+ [Date.new(2007, 5, 14), 21.75, 22.25, 0.0, 0.5, "Task 3"],
420
+ [Date.new(2007, 5, 14), 22.5, 23.0, 0.0, 0.5, "Task 3"],
421
+ [Date.new(2007, 5, 15), 11.75, 12.75, 0.0, 1.0, "Task 3"],
422
+ [Date.new(2007, 5, 7), 10.75, 10.75, 0.0, 0.0, "Task 1"],
423
+ [nil]
424
+ ]
425
+ end
426
+
427
+ it 'returns the expected result' do
428
+ index = 0
429
+ subject.each_row_streaming do |row|
430
+ expect(row.map(&:value)).to eq expected_rows[index]
431
+ index += 1
432
+ end
433
+ end
434
+
435
+ context 'with max_rows options' do
436
+ it 'returns the expected result' do
437
+ index = 0
438
+ subject.each_row_streaming(max_rows: 3) do |row|
439
+ expect(row.map(&:value)).to eq expected_rows[index]
440
+ index += 1
441
+ end
442
+ # Expect this to get incremented one time more than max (because of the increment at the end of the block)
443
+ # but it should not be near expected_rows.size
444
+ expect(index).to eq 4
445
+ end
446
+ end
447
+
448
+ context 'with offset option' do
449
+ let(:offset) { 3 }
450
+
451
+ it 'returns the expected result' do
452
+ index = 0
453
+ subject.each_row_streaming(offset: offset) do |row|
454
+ expect(row.map(&:value)).to eq expected_rows[index + offset]
455
+ index += 1
456
+ end
457
+ expect(index).to eq 11
458
+ end
459
+ end
460
+
461
+ context 'with offset and max_rows options' do
462
+ let(:offset) { 3 }
463
+ let(:max_rows) { 3 }
464
+
465
+ it 'returns the expected result' do
466
+ index = 0
467
+ subject.each_row_streaming(offset: offset, max_rows: max_rows) do |row|
468
+ expect(row.map(&:value)).to eq expected_rows[index + offset]
469
+ index += 1
470
+ end
471
+ expect(index).to eq 4
472
+ end
473
+ end
474
+
475
+ context 'without block passed' do
476
+ it 'returns an enumerator' do
477
+ expect(subject.each_row_streaming).to be_a(Enumerator)
478
+ end
479
+ end
480
+ end
481
+
482
+ describe '#html_strings' do
483
+ let(:path) { 'test/files/html_strings_formatting.xlsx' }
484
+
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>"
511
+ end
512
+ end
513
+
514
+ describe '_x000D_' do
515
+ let(:path) { 'test/files/x000D.xlsx' }
516
+ it 'does not contain _x000D_' do
517
+ expect(subject.cell(2, 9)).not_to include('_x000D_')
518
+ end
519
+ end
520
+
521
+ describe 'opening a file with a chart sheet' do
522
+ let(:path) { 'test/files/chart_sheet.xlsx' }
523
+ it 'should not raise' do
524
+ expect{ subject }.to_not raise_error
525
+ end
526
+ end
527
+
528
+ describe 'opening a file with white space in the styles.xml' do
529
+ let(:path) { 'test/files/style_nodes_with_white_spaces.xlsx' }
530
+ subject(:xlsx) do
531
+ Roo::Spreadsheet.open(path, expand_merged_ranges: true, extension: :xlsx)
532
+ end
533
+ it 'should properly recognize formats' do
534
+ expect(subject.sheet(0).excelx_format(2,1)).to eq 'm/d/yyyy" "h:mm:ss" "AM/PM'
535
+ end
37
536
  end
38
537
  end