jruby-poi 0.9.0 → 1.0.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.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.travis.yml +18 -4
- data/Gemfile +3 -6
- data/Gemfile.lock +20 -27
- data/README.markdown +49 -47
- data/Rakefile +20 -27
- data/jruby-poi.gemspec +7 -70
- data/lib/poi-jars/lib/commons-codec-1.10.jar +0 -0
- data/lib/poi-jars/lib/commons-collections4-4.1.jar +0 -0
- data/lib/poi-jars/lib/commons-logging-1.2.jar +0 -0
- data/lib/poi-jars/lib/junit-4.12.jar +0 -0
- data/lib/poi-jars/lib/log4j-1.2.17.jar +0 -0
- data/lib/poi-jars/ooxml-lib/curvesapi-1.04.jar +0 -0
- data/lib/{ooxml-lib/xmlbeans-2.3.0.jar → poi-jars/ooxml-lib/xmlbeans-2.6.0.jar} +0 -0
- data/lib/poi-jars/poi-3.15.jar +0 -0
- data/lib/poi-jars/poi-examples-3.15.jar +0 -0
- data/lib/poi-jars/poi-excelant-3.15.jar +0 -0
- data/lib/poi-jars/poi-ooxml-3.15.jar +0 -0
- data/lib/poi-jars/poi-ooxml-schemas-3.15.jar +0 -0
- data/lib/poi-jars/poi-scratchpad-3.15.jar +0 -0
- data/lib/poi.rb +13 -7
- data/lib/poi/version.rb +11 -0
- data/lib/poi/workbook/area.rb +20 -17
- data/lib/poi/workbook/cell.rb +28 -42
- data/lib/poi/workbook/row.rb +1 -1
- data/lib/poi/workbook/workbook.rb +3 -7
- data/lib/poi/workbook/worksheet.rb +2 -2
- data/spec/data/1904_window_dates.xls +0 -0
- data/spec/data/various_samples.xlsx +0 -0
- data/spec/facade_spec.rb +35 -35
- data/spec/spec_helper.rb +10 -0
- data/spec/support/matchers/cell_matcher.rb +3 -3
- data/spec/workbook_spec.rb +368 -385
- data/spec/writing_spec.rb +144 -144
- metadata +111 -121
- data/VERSION +0 -1
- data/lib/ooxml-lib/dom4j-1.6.1.jar +0 -0
- data/lib/ooxml-lib/stax-api-1.0.1.jar +0 -0
- data/lib/poi-3.8-20120326.jar +0 -0
- data/lib/poi-examples-3.8-20120326.jar +0 -0
- data/lib/poi-excelant-3.8-20120326.jar +0 -0
- data/lib/poi-ooxml-3.8-20120326.jar +0 -0
- data/lib/poi-ooxml-schemas-3.8-20120326.jar +0 -0
- data/lib/poi-scratchpad-3.8-20120326.jar +0 -0
data/lib/poi/workbook/cell.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'date'
|
1
3
|
module POI
|
2
4
|
class Cells
|
3
5
|
include Enumerable
|
@@ -9,7 +11,7 @@ module POI
|
|
9
11
|
end
|
10
12
|
|
11
13
|
def [](index)
|
12
|
-
@cells[index] ||= Cell.new(@poi_row.
|
14
|
+
@cells[index] ||= Cell.new(@poi_row.get_cell(index) || @poi_row.create_cell(index), @row)
|
13
15
|
end
|
14
16
|
|
15
17
|
def size
|
@@ -52,8 +54,8 @@ module POI
|
|
52
54
|
elsif poi_cell.cell_type == CELL_TYPE_FORMULA &&
|
53
55
|
poi_cell.cached_formula_result_type == CELL_TYPE_ERROR
|
54
56
|
|
55
|
-
|
56
|
-
|
57
|
+
cell_value = formula_evaluator.evaluate(poi_cell)
|
58
|
+
cell_value && error_value_from(cell_value.error_value)
|
57
59
|
else
|
58
60
|
nil
|
59
61
|
end
|
@@ -66,7 +68,7 @@ module POI
|
|
66
68
|
|
67
69
|
def value
|
68
70
|
return nil if poi_cell.nil?
|
69
|
-
|
71
|
+
cast_value
|
70
72
|
end
|
71
73
|
|
72
74
|
def formula= new_value
|
@@ -124,51 +126,35 @@ module POI
|
|
124
126
|
end
|
125
127
|
|
126
128
|
private
|
127
|
-
def
|
128
|
-
|
129
|
-
|
130
|
-
case cell_value.cell_type
|
129
|
+
def cast_value(type = cell_type)
|
130
|
+
case type
|
131
131
|
when CELL_TYPE_BLANK then nil
|
132
|
-
when CELL_TYPE_BOOLEAN then
|
133
|
-
when CELL_TYPE_ERROR then
|
134
|
-
when
|
135
|
-
when CELL_TYPE_STRING then
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
end
|
140
|
-
|
141
|
-
def cell_value_for_type(cell_type)
|
142
|
-
return nil if cell_type.nil?
|
143
|
-
begin
|
144
|
-
case cell_type
|
145
|
-
when CELL_TYPE_BLANK then nil
|
146
|
-
when CELL_TYPE_BOOLEAN then CELL_VALUE.value_of(poi_cell.boolean_cell_value)
|
147
|
-
when CELL_TYPE_FORMULA then cell_value_for_type(poi_cell.cached_formula_result_type)
|
148
|
-
when CELL_TYPE_STRING then CELL_VALUE.new(poi_cell.string_cell_value)
|
149
|
-
when CELL_TYPE_ERROR, CELL_TYPE_NUMERIC then CELL_VALUE.new(poi_cell.numeric_cell_value)
|
132
|
+
when CELL_TYPE_BOOLEAN then get_boolean_cell_value
|
133
|
+
when CELL_TYPE_ERROR then nil
|
134
|
+
when CELL_TYPE_FORMULA then cast_value(poi_cell.cached_formula_result_type)
|
135
|
+
when CELL_TYPE_STRING then get_string_cell_value
|
136
|
+
when CELL_TYPE_NUMERIC
|
137
|
+
if DATE_UTIL.cell_date_formatted(poi_cell)
|
138
|
+
DateTime.parse(get_date_cell_value.to_s)
|
150
139
|
else
|
151
|
-
|
140
|
+
get_numeric_cell_value
|
152
141
|
end
|
153
|
-
|
154
|
-
|
142
|
+
else
|
143
|
+
raise "unhandled cell type[#{type}]"
|
155
144
|
end
|
156
145
|
end
|
157
|
-
|
158
|
-
def
|
159
|
-
|
146
|
+
|
147
|
+
def workbook
|
148
|
+
@row.worksheet.workbook
|
160
149
|
end
|
161
|
-
|
162
|
-
def
|
163
|
-
workbook.
|
150
|
+
|
151
|
+
def formula_evaluator
|
152
|
+
workbook.formula_evaluator
|
164
153
|
end
|
165
|
-
|
166
|
-
def
|
167
|
-
|
168
|
-
|
169
|
-
else
|
170
|
-
cell_value.number_value
|
171
|
-
end
|
154
|
+
|
155
|
+
def error_value_from(cell_value)
|
156
|
+
#org.apache.poi.ss.usermodel.ErrorConstants.get_text(cell_value)
|
157
|
+
org.apache.poi.ss.usermodel.FormulaError.forInt(cell_value).getString
|
172
158
|
end
|
173
159
|
end
|
174
160
|
end
|
data/lib/poi/workbook/row.rb
CHANGED
@@ -9,7 +9,7 @@ module POI
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def [](index)
|
12
|
-
@rows[index] ||= Row.new(@poi_worksheet.
|
12
|
+
@rows[index] ||= Row.new(@poi_worksheet.get_row(index) || @poi_worksheet.create_row(index), @worksheet)
|
13
13
|
end
|
14
14
|
|
15
15
|
def size
|
@@ -132,7 +132,7 @@ module POI
|
|
132
132
|
|
133
133
|
def named_ranges
|
134
134
|
@named_ranges ||= (0...@workbook.number_of_names).collect do | idx |
|
135
|
-
NamedRange.new @workbook.
|
135
|
+
NamedRange.new @workbook.get_name_at(idx), self
|
136
136
|
end
|
137
137
|
end
|
138
138
|
|
@@ -208,7 +208,7 @@ module POI
|
|
208
208
|
end
|
209
209
|
|
210
210
|
def cells_in_area reference
|
211
|
-
area = Area.new(reference)
|
211
|
+
area = Area.new(reference, self.get_spreadsheet_version)
|
212
212
|
area.in(self)
|
213
213
|
end
|
214
214
|
|
@@ -242,13 +242,9 @@ module POI
|
|
242
242
|
area_start = "#{sheet_parts.first}!#{area_parts.first}"
|
243
243
|
area_end = area_parts.last
|
244
244
|
|
245
|
-
area =
|
245
|
+
area = AREA_REF.getWholeColumn(get_worksheet_version, area_start, area_end)
|
246
246
|
full_ref = "#{area.first_cell.format_as_string}:#{area.last_cell.format_as_string}"
|
247
247
|
Area.new(full_ref).in(self)
|
248
|
-
# cell_reference = org.apache.poi.ss.util.CellReference.new( reference + "1" )
|
249
|
-
# column = cell_reference.get_col
|
250
|
-
# sheet = cell_reference.get_sheet_name
|
251
|
-
# worksheets[sheet].rows.collect{|row| row[column]}
|
252
248
|
end
|
253
249
|
|
254
250
|
private
|
@@ -10,7 +10,7 @@ module POI
|
|
10
10
|
def [](index_or_name)
|
11
11
|
worksheet = case
|
12
12
|
when index_or_name.kind_of?(Numeric)
|
13
|
-
@poi_workbook.
|
13
|
+
@poi_workbook.get_sheet_at(index_or_name) || @poi_workbook.create_sheet
|
14
14
|
else
|
15
15
|
@poi_workbook.get_sheet(index_or_name) || @poi_workbook.create_sheet(index_or_name)
|
16
16
|
end
|
@@ -22,7 +22,7 @@ module POI
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def each
|
25
|
-
(0...size).each { |i| yield Worksheet.new(@poi_workbook.
|
25
|
+
(0...size).each { |i| yield Worksheet.new(@poi_workbook.get_sheet_at(i), @workbook) }
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
Binary file
|
Binary file
|
data/spec/facade_spec.rb
CHANGED
@@ -4,45 +4,45 @@ describe "POI.Facade" do
|
|
4
4
|
it "should create specialized methods for boolean methods, getters, and setters" do
|
5
5
|
book = POI::Workbook.create('foo.xlsx')
|
6
6
|
sheet = book.create_sheet
|
7
|
-
sheet.respond_to?(:column_broken?).should
|
8
|
-
sheet.respond_to?(:column_hidden?).should
|
9
|
-
sheet.respond_to?(:display_formulas?).should
|
10
|
-
sheet.respond_to?(:display_gridlines?).should
|
11
|
-
sheet.respond_to?(:selected?).should
|
12
|
-
sheet.respond_to?(:column_breaks).should
|
13
|
-
sheet.respond_to?(:column_break=).should
|
14
|
-
sheet.respond_to?(:autobreaks?).should
|
15
|
-
sheet.respond_to?(:autobreaks=).should
|
16
|
-
sheet.respond_to?(:autobreaks!).should
|
17
|
-
sheet.respond_to?(:column_broken?).should
|
18
|
-
sheet.respond_to?(:fit_to_page).should
|
19
|
-
sheet.respond_to?(:fit_to_page?).should
|
20
|
-
sheet.respond_to?(:fit_to_page=).should
|
21
|
-
sheet.respond_to?(:fit_to_page!).should
|
7
|
+
sheet.respond_to?(:column_broken?).should be true
|
8
|
+
sheet.respond_to?(:column_hidden?).should be true
|
9
|
+
sheet.respond_to?(:display_formulas?).should be true
|
10
|
+
sheet.respond_to?(:display_gridlines?).should be true
|
11
|
+
sheet.respond_to?(:selected?).should be true
|
12
|
+
sheet.respond_to?(:column_breaks).should be true
|
13
|
+
sheet.respond_to?(:column_break=).should be true
|
14
|
+
sheet.respond_to?(:autobreaks?).should be true
|
15
|
+
sheet.respond_to?(:autobreaks=).should be true
|
16
|
+
sheet.respond_to?(:autobreaks!).should be true
|
17
|
+
sheet.respond_to?(:column_broken?).should be true
|
18
|
+
sheet.respond_to?(:fit_to_page).should be true
|
19
|
+
sheet.respond_to?(:fit_to_page?).should be true
|
20
|
+
sheet.respond_to?(:fit_to_page=).should be true
|
21
|
+
sheet.respond_to?(:fit_to_page!).should be true
|
22
22
|
|
23
|
-
sheet.respond_to?(:array_formula).should_not
|
24
|
-
sheet.respond_to?(:array_formula=).should_not
|
23
|
+
sheet.respond_to?(:array_formula).should_not be true
|
24
|
+
sheet.respond_to?(:array_formula=).should_not be true
|
25
25
|
|
26
26
|
row = sheet[0]
|
27
|
-
row.respond_to?(:first_cell_num).should
|
28
|
-
row.respond_to?(:height).should
|
29
|
-
row.respond_to?(:height=).should
|
30
|
-
row.respond_to?(:height_in_points).should
|
31
|
-
row.respond_to?(:height_in_points=).should
|
32
|
-
row.respond_to?(:zero_height?).should
|
33
|
-
row.respond_to?(:zero_height!).should
|
34
|
-
row.respond_to?(:zero_height=).should
|
27
|
+
row.respond_to?(:first_cell_num).should be true
|
28
|
+
row.respond_to?(:height).should be true
|
29
|
+
row.respond_to?(:height=).should be true
|
30
|
+
row.respond_to?(:height_in_points).should be true
|
31
|
+
row.respond_to?(:height_in_points=).should be true
|
32
|
+
row.respond_to?(:zero_height?).should be true
|
33
|
+
row.respond_to?(:zero_height!).should be true
|
34
|
+
row.respond_to?(:zero_height=).should be true
|
35
35
|
|
36
36
|
cell = row[0]
|
37
|
-
cell.respond_to?(:boolean_cell_value).should
|
38
|
-
cell.respond_to?(:boolean_cell_value?).should
|
39
|
-
cell.respond_to?(:cached_formula_result_type).should
|
40
|
-
cell.respond_to?(:cell_error_value=).should
|
41
|
-
cell.respond_to?(:cell_value=).should
|
42
|
-
cell.respond_to?(:hyperlink=).should
|
43
|
-
cell.respond_to?(:cell_value!).should
|
44
|
-
cell.respond_to?(:remove_cell_comment!).should
|
45
|
-
cell.respond_to?(:cell_style).should
|
46
|
-
cell.respond_to?(:cell_style=).should
|
37
|
+
cell.respond_to?(:boolean_cell_value).should be true
|
38
|
+
cell.respond_to?(:boolean_cell_value?).should be true
|
39
|
+
cell.respond_to?(:cached_formula_result_type).should be true
|
40
|
+
cell.respond_to?(:cell_error_value=).should be true
|
41
|
+
cell.respond_to?(:cell_value=).should be true
|
42
|
+
cell.respond_to?(:hyperlink=).should be true
|
43
|
+
cell.respond_to?(:cell_value!).should be true
|
44
|
+
cell.respond_to?(:remove_cell_comment!).should be true
|
45
|
+
cell.respond_to?(:cell_style).should be true
|
46
|
+
cell.respond_to?(:cell_style=).should be true
|
47
47
|
end
|
48
48
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -2,6 +2,7 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
RSpec.configure do |c|
|
4
4
|
c.filter_run_excluding :unimplemented => true
|
5
|
+
c.expect_with(:rspec) { |expect_config| expect_config.syntax = :should }
|
5
6
|
end
|
6
7
|
|
7
8
|
require File.expand_path('../lib/poi', File.dirname(__FILE__))
|
@@ -14,3 +15,12 @@ class TestDataFile
|
|
14
15
|
File.expand_path(File.join(File.dirname(__FILE__), 'data', name))
|
15
16
|
end
|
16
17
|
end
|
18
|
+
|
19
|
+
if RUBY_VERSION < '1.9'
|
20
|
+
class DateTime
|
21
|
+
def to_date
|
22
|
+
Date.parse(self.strftime('%Y-%m-%d'))
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
@@ -3,15 +3,15 @@ RSpec::Matchers.define :equal_at_cell do |expected, row, col|
|
|
3
3
|
actual == expected
|
4
4
|
end
|
5
5
|
|
6
|
-
|
6
|
+
failure_message do |actual|
|
7
7
|
"expected #{actual} to equal #{expected} (row:#{row}, cell:#{col})"
|
8
8
|
end
|
9
9
|
|
10
|
-
|
10
|
+
failure_message_when_negated do |actual|
|
11
11
|
"expected #{actual} not to equal #{expected} (row:#{row}, cell:#{col})"
|
12
12
|
end
|
13
13
|
|
14
14
|
description do
|
15
15
|
"to equal #{expected}"
|
16
16
|
end
|
17
|
-
end
|
17
|
+
end
|
data/spec/workbook_spec.rb
CHANGED
@@ -1,385 +1,368 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
require 'date'
|
4
|
-
require 'stringio'
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
book
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
book
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
book
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
book
|
47
|
-
|
48
|
-
book["numbers
|
49
|
-
book["numbers
|
50
|
-
book["numbers
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
book.
|
57
|
-
book.cell("numbers!
|
58
|
-
book.cell("numbers!
|
59
|
-
book.cell("numbers!
|
60
|
-
|
61
|
-
|
62
|
-
book.cell("numbers!
|
63
|
-
book.cell("numbers!
|
64
|
-
book.cell("numbers!
|
65
|
-
|
66
|
-
|
67
|
-
book.cell(
|
68
|
-
book.cell(
|
69
|
-
book.cell(
|
70
|
-
book.cell(
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
book.
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
book
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
book.
|
86
|
-
book.
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
book
|
102
|
-
book['
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
book[
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
book
|
121
|
-
|
122
|
-
book.worksheets[
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
book.worksheets
|
133
|
-
book.worksheets
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
book
|
140
|
-
book.
|
141
|
-
|
142
|
-
book.
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
describe POI::
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
sheet = book.worksheets["text & pic"]
|
167
|
-
sheet.rows
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
rows[
|
247
|
-
rows[
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
rows
|
266
|
-
|
267
|
-
rows[
|
268
|
-
rows[
|
269
|
-
|
270
|
-
rows[
|
271
|
-
|
272
|
-
|
273
|
-
rows[
|
274
|
-
rows[8][0].
|
275
|
-
|
276
|
-
rows[
|
277
|
-
rows[
|
278
|
-
|
279
|
-
rows[
|
280
|
-
rows[
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
rows
|
286
|
-
rows[
|
287
|
-
|
288
|
-
|
289
|
-
rows[
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
rows[
|
294
|
-
|
295
|
-
rows[
|
296
|
-
rows[
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
rows
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
rows
|
307
|
-
rows[
|
308
|
-
rows[
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
rows[
|
314
|
-
rows[2][0].to_s.should ==
|
315
|
-
|
316
|
-
rows[
|
317
|
-
rows[
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
rows
|
335
|
-
rows[
|
336
|
-
rows[
|
337
|
-
rows[
|
338
|
-
rows[
|
339
|
-
rows[
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
end
|
370
|
-
|
371
|
-
it "should notify the workbook that I have been updated" do
|
372
|
-
book['dates!A10'].to_s.should == '2010-03-08'
|
373
|
-
book['dates!A16'].to_s.should == '2010-03-14'
|
374
|
-
book['dates!B2'].to_s.should == '2010-03-14'
|
375
|
-
|
376
|
-
cell = book.cell('dates!B2')
|
377
|
-
cell.formula.should == 'A16'
|
378
|
-
|
379
|
-
cell.formula = 'A10 + 1'
|
380
|
-
book.cell('dates!B2').poi_cell.should === cell.poi_cell
|
381
|
-
book.cell('dates!B2').formula.should == 'A10 + 1'
|
382
|
-
|
383
|
-
book['dates!B2'].to_s.should == '2010-03-09'
|
384
|
-
end
|
385
|
-
end
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'date'
|
4
|
+
require 'stringio'
|
5
|
+
|
6
|
+
VARIOUS_SAMPLES_PATH = TestDataFile.expand_path("various_samples.xlsx")
|
7
|
+
DATES_1904_WINDOW_XLS_PATH = TestDataFile.expand_path("1904_window_dates.xls")
|
8
|
+
|
9
|
+
describe POI::Workbook do
|
10
|
+
it "should open a workbook and allow access to its worksheets" do
|
11
|
+
book = POI::Workbook.open(VARIOUS_SAMPLES_PATH)
|
12
|
+
book.worksheets.size.should == 6
|
13
|
+
book.filename.should == VARIOUS_SAMPLES_PATH
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should be able to create a Workbook from an IO object" do
|
17
|
+
content = StringIO.new(open(VARIOUS_SAMPLES_PATH, 'rb'){|f| f.read})
|
18
|
+
book = POI::Workbook.open(content)
|
19
|
+
book.worksheets.size.should == 6
|
20
|
+
book.filename.should =~ /spreadsheet.xlsx$/
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should be able to create a Workbook from a Java input stream" do
|
24
|
+
content = java.io.FileInputStream.new(VARIOUS_SAMPLES_PATH)
|
25
|
+
book = POI::Workbook.open(content)
|
26
|
+
book.worksheets.size.should == 6
|
27
|
+
book.filename.should =~ /spreadsheet.xlsx$/
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should create an HSSFWorkbook when passed a :format => :hssf option" do
|
31
|
+
book = POI::Workbook.create('test.xls', :format => :hssf)
|
32
|
+
book.poi_workbook.should be_kind_of(org.apache.poi.hssf.usermodel.HSSFWorkbook)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should create an XSSFWorkbook when passed a :format => :xssf option" do
|
36
|
+
book = POI::Workbook.create('test.xlsx', :format => :xssf)
|
37
|
+
book.poi_workbook.should be_kind_of(org.apache.poi.xssf.usermodel.XSSFWorkbook)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should create an XSSFWorkbook by default" do
|
41
|
+
book = POI::Workbook.create('test.xlsx')
|
42
|
+
book.poi_workbook.should be_kind_of(org.apache.poi.xssf.usermodel.XSSFWorkbook)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should return a column of cells by reference" do
|
46
|
+
book = POI::Workbook.open(VARIOUS_SAMPLES_PATH)
|
47
|
+
|
48
|
+
book["numbers!$A"].should == book['numbers'].rows.collect{|e| e[0].value}
|
49
|
+
book["numbers!A"].should == book['numbers'].rows.collect{|e| e[0].value}
|
50
|
+
book["numbers!C"].should == book['numbers'].rows.collect{|e| e[2].value}
|
51
|
+
book["numbers!$D:$D"].should == book['numbers'].rows.collect{|e| e[3].value}
|
52
|
+
book["numbers!$c:$D"].should == {"C" => book['numbers'].rows.collect{|e| e[2].value}, "D" => book['numbers'].rows.collect{|e| e[3].value}}
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should return cells by reference" do
|
56
|
+
book = POI::Workbook.open(VARIOUS_SAMPLES_PATH)
|
57
|
+
book.cell("numbers!A1").value.should == 'NUM'
|
58
|
+
book.cell("numbers!A2").to_s.should == '1.0'
|
59
|
+
book.cell("numbers!A3").to_s.should == '2.0'
|
60
|
+
book.cell("numbers!A4").to_s.should == '3.0'
|
61
|
+
|
62
|
+
book.cell("numbers!A10").to_s.should == '9.0'
|
63
|
+
book.cell("numbers!B10").to_s.should == '81.0'
|
64
|
+
book.cell("numbers!C10").to_s.should == '729.0'
|
65
|
+
book.cell("numbers!D10").to_s.should == '3.0'
|
66
|
+
|
67
|
+
book.cell(%Q{'text & pic'!A10}).value.should == 'This is an Excel XLSX workbook.'
|
68
|
+
book.cell(%Q{'bools & errors'!B3}).value.should == true
|
69
|
+
book.cell(%Q{'high refs'!AM619}).value.should == 'This is some text'
|
70
|
+
book.cell(%Q{'high refs'!AO624}).value.should == 24.0
|
71
|
+
book.cell(%Q{'high refs'!AP631}).value.should == 13.0
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should handle named cell ranges" do
|
75
|
+
book = POI::Workbook.open(VARIOUS_SAMPLES_PATH)
|
76
|
+
|
77
|
+
book.named_ranges.length.should == 3
|
78
|
+
book.named_ranges.collect{|e| e.name}.should == %w{four_times_six NAMES nums}
|
79
|
+
book.named_ranges.collect{|e| e.sheet.name}.should == ['high refs', 'bools & errors', 'high refs']
|
80
|
+
book.named_ranges.collect{|e| e.formula}.should == ["'high refs'!$AO$624", "'bools & errors'!$D$2:$D$11", "'high refs'!$AP$619:$AP$631"]
|
81
|
+
book['four_times_six'].should == 24.0
|
82
|
+
book['nums'].should == (1..13).collect{|e| e * 1.0}
|
83
|
+
|
84
|
+
# NAMES is a range of empty cells
|
85
|
+
book['NAMES'].should == [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil]
|
86
|
+
book.cell('NAMES').each do | cell |
|
87
|
+
cell.value.should be_nil
|
88
|
+
cell.poi_cell.should_not be_nil
|
89
|
+
cell.to_s.should be_empty
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should return an array of cell values by reference" do
|
94
|
+
book = POI::Workbook.open(VARIOUS_SAMPLES_PATH)
|
95
|
+
book['dates!A2:A16'].map(&:to_date).should == (Date.parse('2010-02-28')..Date.parse('2010-03-14')).to_a
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should return cell values by reference" do
|
99
|
+
book = POI::Workbook.open(VARIOUS_SAMPLES_PATH)
|
100
|
+
|
101
|
+
book[%Q{'text & pic'!A10}].should == 'This is an Excel XLSX workbook.'
|
102
|
+
book[%Q{'bools & errors'!B3}].should == true
|
103
|
+
book[%Q{'high refs'!AM619}].should == 'This is some text'
|
104
|
+
book[%Q{'high refs'!AO624}].should == 24.0
|
105
|
+
book[%Q{'high refs'!AP631}].should == 13.0
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe POI::Worksheets do
|
110
|
+
let(:book) { POI::Workbook.open(VARIOUS_SAMPLES_PATH) }
|
111
|
+
|
112
|
+
it "should allow indexing worksheets by ordinal" do
|
113
|
+
book.worksheets[0].name.should == "text & pic"
|
114
|
+
book.worksheets[1].name.should == "numbers"
|
115
|
+
book.worksheets[2].name.should == "dates"
|
116
|
+
book.worksheets[3].name.should == "bools & errors"
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should allow indexing worksheets by name" do
|
120
|
+
book.worksheets["text & pic"].name.should == "text & pic"
|
121
|
+
book.worksheets["numbers"].name.should == "numbers"
|
122
|
+
book.worksheets["dates"].name.should == "dates"
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should be enumerable" do
|
126
|
+
book.worksheets.should be_kind_of Enumerable
|
127
|
+
|
128
|
+
book.worksheets.each do |sheet|
|
129
|
+
sheet.should be_kind_of POI::Worksheet
|
130
|
+
end
|
131
|
+
|
132
|
+
book.worksheets.count.should == 6
|
133
|
+
book.worksheets.collect.count.should == 6
|
134
|
+
end
|
135
|
+
|
136
|
+
it "returns cells when passing a cell reference" do
|
137
|
+
book['dates']['A2'].class.should == DateTime
|
138
|
+
book['dates']['A2'].to_date.should == Date.parse('2010-02-28')
|
139
|
+
book['dates']['a2'].to_date.should == Date.parse('2010-02-28')
|
140
|
+
book['dates']['B2'].to_date.should == Date.parse('2010-03-14')
|
141
|
+
book['dates']['b2'].to_date.should == Date.parse('2010-03-14')
|
142
|
+
book['dates']['C2'].to_date.should == Date.parse('2010-03-28')
|
143
|
+
book['dates']['c2'].to_date.should == Date.parse('2010-03-28')
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
describe POI::Rows do
|
148
|
+
it "should be enumerable" do
|
149
|
+
book = POI::Workbook.open(VARIOUS_SAMPLES_PATH)
|
150
|
+
sheet = book.worksheets["text & pic"]
|
151
|
+
sheet.rows.should be_kind_of Enumerable
|
152
|
+
|
153
|
+
sheet.rows.each do |row|
|
154
|
+
row.should be_kind_of POI::Row
|
155
|
+
end
|
156
|
+
|
157
|
+
sheet.rows.count.should == 7
|
158
|
+
sheet.rows.collect.count.should == 7
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
describe POI::Cells do
|
163
|
+
let(:book) { POI::Workbook.open(VARIOUS_SAMPLES_PATH) }
|
164
|
+
|
165
|
+
it "should be enumerable" do
|
166
|
+
sheet = book.worksheets["text & pic"]
|
167
|
+
rows = sheet.rows
|
168
|
+
cells = rows[0].cells
|
169
|
+
|
170
|
+
cells.should be_kind_of Enumerable
|
171
|
+
cells.count.should == 1
|
172
|
+
cells.collect.count.should == 1
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
describe POI::Cell do
|
177
|
+
let(:book) { POI::Workbook.open(VARIOUS_SAMPLES_PATH) }
|
178
|
+
|
179
|
+
context "1900 windowed dates" do
|
180
|
+
it "should provide dates for date cells" do
|
181
|
+
sheet = book.worksheets["dates"]
|
182
|
+
rows = sheet.rows
|
183
|
+
|
184
|
+
dates_by_column = [
|
185
|
+
(DateTime.parse('2010-02-28')..DateTime.parse('2010-03-14')),
|
186
|
+
(DateTime.parse('2010-03-14')..DateTime.parse('2010-03-28')),
|
187
|
+
(DateTime.parse('2010-03-28')..DateTime.parse('2010-04-11'))
|
188
|
+
]
|
189
|
+
(0..2).each do |col|
|
190
|
+
dates_by_column[col].each_with_index do |date, index|
|
191
|
+
row = index + 1
|
192
|
+
c = sheet.rows[row].cells[col]
|
193
|
+
c.value.to_date.should == date.to_date
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
context "1904 windowed dates" do
|
200
|
+
let(:book) { POI::Workbook.open(DATES_1904_WINDOW_XLS_PATH) }
|
201
|
+
it "returns entered dates correctly" do
|
202
|
+
c = book.worksheets[0].rows[1].cells[0]
|
203
|
+
c.value.to_date.should == Date.parse("2012-01-01")
|
204
|
+
end
|
205
|
+
|
206
|
+
it "returns dates computed by a formula correctly" do
|
207
|
+
c = book.worksheets[0].rows[1].cells[3]
|
208
|
+
c.value.to_date.should == Date.parse("2012-01-02")
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
it "should provide numbers for numeric cells" do
|
213
|
+
sheet = book.worksheets["numbers"]
|
214
|
+
rows = sheet.rows
|
215
|
+
|
216
|
+
(1..15).each do |number|
|
217
|
+
row = number
|
218
|
+
rows[row][0].value.should equal_at_cell(number, row, 0)
|
219
|
+
rows[row][1].value.should equal_at_cell(number ** 2, row, 1)
|
220
|
+
rows[row][2].value.should equal_at_cell(number ** 3, row, 2)
|
221
|
+
rows[row][3].value.should equal_at_cell(Math.sqrt(number), row, 3)
|
222
|
+
end
|
223
|
+
|
224
|
+
rows[9][0].to_s.should == '9.0'
|
225
|
+
rows[9][1].to_s.should == '81.0'
|
226
|
+
rows[9][2].to_s.should == '729.0'
|
227
|
+
rows[9][3].to_s.should == '3.0'
|
228
|
+
end
|
229
|
+
|
230
|
+
it "should handle array access from the workbook down to cells" do
|
231
|
+
book[1][9][0].to_s.should == '9.0'
|
232
|
+
book[1][9][1].to_s.should == '81.0'
|
233
|
+
book[1][9][2].to_s.should == '729.0'
|
234
|
+
book[1][9][3].to_s.should == '3.0'
|
235
|
+
|
236
|
+
book["numbers"][9][0].to_s.should == '9.0'
|
237
|
+
book["numbers"][9][1].to_s.should == '81.0'
|
238
|
+
book["numbers"][9][2].to_s.should == '729.0'
|
239
|
+
book["numbers"][9][3].to_s.should == '3.0'
|
240
|
+
end
|
241
|
+
|
242
|
+
it "should provide error text for error cells" do
|
243
|
+
sheet = book.worksheets["bools & errors"]
|
244
|
+
rows = sheet.rows
|
245
|
+
|
246
|
+
rows[6][0].value.should == 0.0 #'~CIRCULAR~REF~'
|
247
|
+
rows[6][0].error_value.should be_nil
|
248
|
+
|
249
|
+
rows[7][0].value.should be_nil
|
250
|
+
rows[7][0].error_value.should == '#DIV/0!'
|
251
|
+
|
252
|
+
rows[8][0].value.should be_nil
|
253
|
+
rows[8][0].error_value.should == '#N/A'
|
254
|
+
|
255
|
+
rows[9][0].value.should be_nil
|
256
|
+
rows[9][0].error_value.should == '#NAME?'
|
257
|
+
|
258
|
+
rows[10][0].value.should be_nil
|
259
|
+
rows[10][0].error_value.should == '#NULL!'
|
260
|
+
|
261
|
+
rows[11][0].value.should be_nil
|
262
|
+
rows[11][0].error_value.should == '#NUM!'
|
263
|
+
|
264
|
+
rows[12][0].value.should be_nil
|
265
|
+
rows[12][0].error_value.should == '#REF!'
|
266
|
+
|
267
|
+
rows[13][0].value.should be_nil
|
268
|
+
rows[13][0].error_value.should == '#VALUE!'
|
269
|
+
|
270
|
+
lambda{ rows[14][0].value }.should_not raise_error
|
271
|
+
|
272
|
+
rows[6][0].to_s.should == '0.0' #'~CIRCULAR~REF~'
|
273
|
+
rows[7][0].to_s.should == '' #'#DIV/0!'
|
274
|
+
rows[8][0].to_s.should == '' #'#N/A'
|
275
|
+
rows[9][0].to_s.should == '' #'#NAME?'
|
276
|
+
rows[10][0].to_s.should == '' #'#NULL!'
|
277
|
+
rows[11][0].to_s.should == '' #'#NUM!'
|
278
|
+
rows[12][0].to_s.should == '' #'#REF!'
|
279
|
+
rows[13][0].to_s.should == '' #'#VALUE!'
|
280
|
+
rows[14][0].to_s.should == ''
|
281
|
+
end
|
282
|
+
|
283
|
+
it "should provide booleans for boolean cells" do
|
284
|
+
sheet = book.worksheets["bools & errors"]
|
285
|
+
rows = sheet.rows
|
286
|
+
rows[1][0].value.should == false
|
287
|
+
rows[1][0].to_s.should == 'false'
|
288
|
+
|
289
|
+
rows[1][1].value.should == false
|
290
|
+
rows[1][1].to_s.should == 'false'
|
291
|
+
|
292
|
+
rows[2][0].value.should == true
|
293
|
+
rows[2][0].to_s.should == 'true'
|
294
|
+
|
295
|
+
rows[2][1].value.should == true
|
296
|
+
rows[2][1].to_s.should == 'true'
|
297
|
+
end
|
298
|
+
|
299
|
+
it "should provide the cell value as a string" do
|
300
|
+
sheet = book.worksheets["text & pic"]
|
301
|
+
rows = sheet.rows
|
302
|
+
|
303
|
+
rows[0][0].value.should == "This"
|
304
|
+
rows[1][0].value.should == "is"
|
305
|
+
rows[2][0].value.should == "an"
|
306
|
+
rows[3][0].value.should == "Excel"
|
307
|
+
rows[4][0].value.should == "XLSX"
|
308
|
+
rows[5][0].value.should == "workbook"
|
309
|
+
rows[9][0].value.should == 'This is an Excel XLSX workbook.'
|
310
|
+
|
311
|
+
|
312
|
+
rows[0][0].to_s.should == "This"
|
313
|
+
rows[1][0].to_s.should == "is"
|
314
|
+
rows[2][0].to_s.should == "an"
|
315
|
+
rows[3][0].to_s.should == "Excel"
|
316
|
+
rows[4][0].to_s.should == "XLSX"
|
317
|
+
rows[5][0].to_s.should == "workbook"
|
318
|
+
rows[9][0].to_s.should == 'This is an Excel XLSX workbook.'
|
319
|
+
end
|
320
|
+
|
321
|
+
it "should provide formulas instead of string-ified values" do
|
322
|
+
sheet = book.worksheets["numbers"]
|
323
|
+
rows = sheet.rows
|
324
|
+
|
325
|
+
(1..15).each do |number|
|
326
|
+
row = number
|
327
|
+
rows[row][0].to_s(false).should == "#{number}.0"
|
328
|
+
rows[row][1].to_s(false).should == "A#{row + 1}*A#{row + 1}"
|
329
|
+
rows[row][2].to_s(false).should == "B#{row + 1}*A#{row + 1}"
|
330
|
+
rows[row][3].to_s(false).should == "SQRT(A#{row + 1})"
|
331
|
+
end
|
332
|
+
|
333
|
+
sheet = book.worksheets["bools & errors"]
|
334
|
+
rows = sheet.rows
|
335
|
+
rows[1][0].to_s(false).should == '1=2'
|
336
|
+
rows[1][1].to_s(false).should == 'FALSE'
|
337
|
+
rows[2][0].to_s(false).should == '1=1'
|
338
|
+
rows[2][1].to_s(false).should == 'TRUE'
|
339
|
+
rows[14][0].to_s(false).should == 'foobar(1)'
|
340
|
+
|
341
|
+
sheet = book.worksheets["text & pic"]
|
342
|
+
sheet.rows[9][0].to_s(false).should == 'CONCATENATE(A1," ", A2," ", A3," ", A4," ", A5," ", A6,".")'
|
343
|
+
end
|
344
|
+
|
345
|
+
it "should handle getting values out of 'non-existent' cells" do
|
346
|
+
sheet = book.worksheets["bools & errors"]
|
347
|
+
sheet.rows[14][2].value.should be_nil
|
348
|
+
end
|
349
|
+
|
350
|
+
it "should notify the workbook that I have been updated" do
|
351
|
+
book['dates!A10'].to_date.should == Date.parse('2010-03-08')
|
352
|
+
book['dates!A16'].to_date.should == Date.parse('2010-03-14')
|
353
|
+
book['dates!B2'].to_date.should == Date.parse('2010-03-14')
|
354
|
+
|
355
|
+
cell = book.cell('dates!B2')
|
356
|
+
cell.formula.should == 'A16'
|
357
|
+
|
358
|
+
cell.formula = 'A10 + 1'
|
359
|
+
book.cell('dates!B2').poi_cell.should === cell.poi_cell
|
360
|
+
book.cell('dates!B2').formula.should == 'A10 + 1'
|
361
|
+
|
362
|
+
book['dates!B2'].to_date.should == Date.parse('2010-03-09')
|
363
|
+
end
|
364
|
+
|
365
|
+
it "should work with IFERROR" do
|
366
|
+
book['newfeatures!F6'].should == 'NOT FOUND'
|
367
|
+
end
|
368
|
+
end
|