roo 1.13.2 → 2.7.0

Sign up to get free protection for your applications and to get access to all the features.
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