jruby-poi 0.5.2 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/jruby-poi.gemspec +2 -1
- data/lib/poi/workbook/cell.rb +37 -15
- data/lib/poi/workbook/named_range.rb +45 -0
- data/lib/poi/workbook/row.rb +4 -2
- data/lib/poi/workbook/workbook.rb +37 -2
- data/lib/poi/workbook/worksheet.rb +10 -1
- data/lib/poi/workbook.rb +1 -0
- data/specs/data/various_samples.xlsx +0 -0
- data/specs/workbook_spec.rb +88 -20
- metadata +4 -3
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.6.0
|
data/jruby-poi.gemspec
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{jruby-poi}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.6.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Scott Deming", "Jason Rogers"]
|
@@ -36,6 +36,7 @@ Gem::Specification.new do |s|
|
|
36
36
|
"lib/poi.rb",
|
37
37
|
"lib/poi/workbook.rb",
|
38
38
|
"lib/poi/workbook/cell.rb",
|
39
|
+
"lib/poi/workbook/named_range.rb",
|
39
40
|
"lib/poi/workbook/row.rb",
|
40
41
|
"lib/poi/workbook/workbook.rb",
|
41
42
|
"lib/poi/workbook/worksheet.rb",
|
data/lib/poi/workbook/cell.rb
CHANGED
@@ -35,31 +35,53 @@ module POI
|
|
35
35
|
@cell = cell
|
36
36
|
end
|
37
37
|
|
38
|
+
# This is NOT an inexpensive operation. The purpose of this method is merely to get more information
|
39
|
+
# out of cell when one thinks the value returned is incorrect. It may have more value in development
|
40
|
+
# than in production.
|
38
41
|
def error_value
|
39
|
-
|
42
|
+
if poi_cell.getCellType == CELL_TYPE_ERROR
|
43
|
+
Java::org.apache.poi.hssf.record.formula.eval.ErrorEval.getText(poi_cell.getErrorCellValue)
|
44
|
+
elsif poi_cell.getCellType == CELL_TYPE_FORMULA && poi_cell.getCachedFormulaResultType == CELL_TYPE_ERROR
|
45
|
+
formula_evaluator = Java::org.apache.poi.xssf.usermodel.XSSFFormulaEvaluator.new poi_cell.sheet.workbook
|
46
|
+
value_of(formula_evaluator.evaluate(poi_cell))
|
47
|
+
else
|
48
|
+
nil
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# returns the formula for this Cell if it has one, otherwise nil
|
53
|
+
def formula_value
|
54
|
+
poi_cell.getCellType == CELL_TYPE_FORMULA ? poi_cell.getCellFormula : nil
|
40
55
|
end
|
41
56
|
|
42
57
|
def value
|
43
|
-
return nil if
|
44
|
-
value_of(cell_value_for_type(
|
58
|
+
return nil if poi_cell.nil?
|
59
|
+
value_of(cell_value_for_type(poi_cell.getCellType))
|
45
60
|
end
|
46
61
|
|
47
62
|
def comment
|
48
|
-
|
63
|
+
poi_cell.getCellComment
|
49
64
|
end
|
50
65
|
|
51
66
|
def index
|
52
|
-
|
67
|
+
poi_cell.getColumnIndex
|
53
68
|
end
|
54
69
|
|
70
|
+
# Get the String representation of this Cell's value.
|
71
|
+
#
|
72
|
+
# If this Cell is a formula you can pass a false to this method and
|
73
|
+
# get the formula instead of the String representation.
|
55
74
|
def to_s(evaluate_formulas=true)
|
56
|
-
if
|
57
|
-
|
75
|
+
return '' if poi_cell.nil?
|
76
|
+
|
77
|
+
if poi_cell.getCellType == CELL_TYPE_FORMULA && evaluate_formulas == false
|
78
|
+
formula_value
|
58
79
|
else
|
59
80
|
value.to_s
|
60
81
|
end
|
61
82
|
end
|
62
83
|
|
84
|
+
# returns the underlying org.apache.poi.ss.usermodel.Cell
|
63
85
|
def poi_cell
|
64
86
|
@cell
|
65
87
|
end
|
@@ -73,30 +95,30 @@ module POI
|
|
73
95
|
when CELL_TYPE_BOOLEAN: cell_value.getBooleanValue
|
74
96
|
when CELL_TYPE_ERROR: Java::org.apache.poi.hssf.record.formula.eval.ErrorEval.getText(cell_value.getErrorValue)
|
75
97
|
when CELL_TYPE_NUMERIC
|
76
|
-
if Java::org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted
|
98
|
+
if Java::org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted poi_cell
|
77
99
|
Date.parse(Java::org.apache.poi.ss.usermodel.DateUtil.getJavaDate(cell_value.getNumberValue).to_s)
|
78
100
|
else
|
79
101
|
cell_value.getNumberValue
|
80
102
|
end
|
81
103
|
when CELL_TYPE_STRING: cell_value.getStringValue
|
82
104
|
else
|
83
|
-
raise "unhandled cell type[#{
|
105
|
+
raise "unhandled cell type[#{cell_value.getCellType}]"
|
84
106
|
end
|
85
107
|
end
|
86
108
|
|
87
109
|
def cell_value_for_type(cell_type)
|
110
|
+
return nil if cell_type.nil?
|
88
111
|
begin
|
89
112
|
case cell_type
|
90
113
|
when CELL_TYPE_BLANK: nil
|
91
|
-
when CELL_TYPE_BOOLEAN: CELL_VALUE.valueOf(
|
92
|
-
when CELL_TYPE_FORMULA: cell_value_for_type(
|
93
|
-
when CELL_TYPE_STRING: CELL_VALUE.new(
|
94
|
-
when CELL_TYPE_ERROR, CELL_TYPE_NUMERIC: CELL_VALUE.new(
|
114
|
+
when CELL_TYPE_BOOLEAN: CELL_VALUE.valueOf(poi_cell.getBooleanCellValue)
|
115
|
+
when CELL_TYPE_FORMULA: cell_value_for_type(poi_cell.getCachedFormulaResultType)
|
116
|
+
when CELL_TYPE_STRING: CELL_VALUE.new(poi_cell.getStringCellValue)
|
117
|
+
when CELL_TYPE_ERROR, CELL_TYPE_NUMERIC: CELL_VALUE.new(poi_cell.getNumericCellValue)
|
95
118
|
else
|
96
|
-
raise "unhandled cell type[#{
|
119
|
+
raise "unhandled cell type[#{poi_cell.getCellType}]"
|
97
120
|
end
|
98
121
|
rescue
|
99
|
-
@error_value = $!
|
100
122
|
nil
|
101
123
|
end
|
102
124
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
class NamedRange
|
2
|
+
|
3
|
+
# takes an instance of org.apache.poi.ss.usermodel.Name, and a POI::Workbook
|
4
|
+
def initialize name, workbook
|
5
|
+
@name = name
|
6
|
+
@workbook = workbook
|
7
|
+
end
|
8
|
+
|
9
|
+
def name
|
10
|
+
@name.getNameName
|
11
|
+
end
|
12
|
+
|
13
|
+
def sheet
|
14
|
+
@workbook[@name.getSheetName]
|
15
|
+
end
|
16
|
+
|
17
|
+
def formula
|
18
|
+
@name.getRefersToFormula
|
19
|
+
end
|
20
|
+
|
21
|
+
def cells
|
22
|
+
area_range? ? all_cells_from_area : @workbook.cell(formula)
|
23
|
+
end
|
24
|
+
|
25
|
+
def values
|
26
|
+
cells.collect{|c| c.value}
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
def area_range?
|
31
|
+
area.nil? == false
|
32
|
+
end
|
33
|
+
|
34
|
+
def area
|
35
|
+
@area ||= begin
|
36
|
+
org.apache.poi.ss.util.AreaReference.new formula
|
37
|
+
rescue
|
38
|
+
nil
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def all_cells_from_area
|
43
|
+
area.getAllReferencedCells.collect{|c| @workbook.cell c.formatAsString}
|
44
|
+
end
|
45
|
+
end
|
data/lib/poi/workbook/row.rb
CHANGED
@@ -27,7 +27,8 @@ module POI
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def [](index)
|
30
|
-
|
30
|
+
return nil if poi_row.nil?
|
31
|
+
Cell.new(poi_row.getCell(index))
|
31
32
|
end
|
32
33
|
|
33
34
|
def cells
|
@@ -35,7 +36,8 @@ module POI
|
|
35
36
|
end
|
36
37
|
|
37
38
|
def index
|
38
|
-
|
39
|
+
return nil if poi_row.nil?
|
40
|
+
poi_row.getRowNum
|
39
41
|
end
|
40
42
|
|
41
43
|
def poi_row
|
@@ -50,11 +50,46 @@ module POI
|
|
50
50
|
end
|
51
51
|
|
52
52
|
def worksheets
|
53
|
-
Worksheets.new(self)
|
53
|
+
@worksheets ||= Worksheets.new(self)
|
54
|
+
end
|
55
|
+
|
56
|
+
def named_ranges
|
57
|
+
@named_ranges ||= (0...@workbook.getNumberOfNames).collect do | idx |
|
58
|
+
NamedRange.new @workbook.getNameAt(idx), self
|
59
|
+
end
|
54
60
|
end
|
55
61
|
|
62
|
+
# sheet_index can be a Fixnum, referring to the 0-based sheet or
|
63
|
+
# a String which is the sheet name or a cell reference.
|
64
|
+
#
|
65
|
+
# If a cell reference is passed the value of that cell is returned.
|
56
66
|
def [](sheet_index)
|
57
|
-
|
67
|
+
begin
|
68
|
+
cell = cell(sheet_index)
|
69
|
+
Array === cell ? cell.collect{|e| e.value} : cell.value
|
70
|
+
rescue
|
71
|
+
answer = worksheets[sheet_index]
|
72
|
+
answer.poi_worksheet.nil? ? nil : answer
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# takes a String in the form of a 3D cell reference and returns the Cell (eg. "Sheet 1!A1")
|
77
|
+
def cell reference
|
78
|
+
if named_range = named_ranges.detect{|e| e.name == reference}
|
79
|
+
cells = named_range.cells.compact
|
80
|
+
if cells.empty?
|
81
|
+
return nil
|
82
|
+
else
|
83
|
+
return cells.length == 1 ? cells.first : cells
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
ref = org.apache.poi.ss.util.CellReference.new(reference)
|
88
|
+
if ref.getSheetName.nil?
|
89
|
+
raise 'cell references at the workbook level must include a sheet reference (eg. Sheet1!A1)'
|
90
|
+
else
|
91
|
+
worksheets[ref.getSheetName][ref.getRow][ref.getCol]
|
92
|
+
end
|
58
93
|
end
|
59
94
|
|
60
95
|
def poi_workbook
|
@@ -39,8 +39,17 @@ module POI
|
|
39
39
|
Rows.new(self)
|
40
40
|
end
|
41
41
|
|
42
|
+
# Accepts a Fixnum or a String as the row_index
|
43
|
+
#
|
44
|
+
# row_index as Fixnum - returns the 0-based row
|
45
|
+
# row_index as String - assumes a cell reference within this sheet and returns the cell value for that reference
|
42
46
|
def [](row_index)
|
43
|
-
|
47
|
+
if Fixnum === row_index
|
48
|
+
rows[row_index]
|
49
|
+
else
|
50
|
+
ref = org.apache.poi.ss.util.CellReference.new(row_index)
|
51
|
+
rows[ref.getRow][ref.getCol].value
|
52
|
+
end
|
44
53
|
end
|
45
54
|
|
46
55
|
def poi_worksheet
|
data/lib/poi/workbook.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require File.join(JRUBY_POI_LIB_PATH, 'poi', 'workbook', 'named_range')
|
1
2
|
require File.join(JRUBY_POI_LIB_PATH, 'poi', 'workbook', 'workbook')
|
2
3
|
require File.join(JRUBY_POI_LIB_PATH, 'poi', 'workbook', 'worksheet')
|
3
4
|
require File.join(JRUBY_POI_LIB_PATH, 'poi', 'workbook', 'row')
|
Binary file
|
data/specs/workbook_spec.rb
CHANGED
@@ -6,23 +6,81 @@ describe POI::Workbook do
|
|
6
6
|
it "should open a workbook and allow access to its worksheets" do
|
7
7
|
name = TestDataFile.expand_path("various_samples.xlsx")
|
8
8
|
book = POI::Workbook.open(name)
|
9
|
-
book.worksheets.size.should ==
|
9
|
+
book.worksheets.size.should == 5
|
10
10
|
book.filename.should == name
|
11
11
|
end
|
12
12
|
|
13
13
|
it "should be able to create a Workbook from an IO object" do
|
14
14
|
content = StringIO.new(open(TestDataFile.expand_path("various_samples.xlsx"), 'rb'){|f| f.read})
|
15
15
|
book = POI::Workbook.open(content)
|
16
|
-
book.worksheets.size.should ==
|
16
|
+
book.worksheets.size.should == 5
|
17
17
|
book.filename.should =~ /spreadsheet.xlsx$/
|
18
18
|
end
|
19
19
|
|
20
20
|
it "should be able to create a Workbook from a Java input stream" do
|
21
21
|
content = java.io.FileInputStream.new(TestDataFile.expand_path("various_samples.xlsx"))
|
22
22
|
book = POI::Workbook.open(content)
|
23
|
-
book.worksheets.size.should ==
|
23
|
+
book.worksheets.size.should == 5
|
24
24
|
book.filename.should =~ /spreadsheet.xlsx$/
|
25
25
|
end
|
26
|
+
|
27
|
+
it "should return cells by reference" do
|
28
|
+
name = TestDataFile.expand_path("various_samples.xlsx")
|
29
|
+
book = POI::Workbook.open(name)
|
30
|
+
|
31
|
+
book.cell("numbers!A1").value.should == 'NUM'
|
32
|
+
book.cell("numbers!A2").to_s.should == '1.0'
|
33
|
+
book.cell("numbers!A3").to_s.should == '2.0'
|
34
|
+
book.cell("numbers!A4").to_s.should == '3.0'
|
35
|
+
|
36
|
+
book.cell("numbers!A10").to_s.should == '9.0'
|
37
|
+
book.cell("numbers!B10").to_s.should == '81.0'
|
38
|
+
book.cell("numbers!C10").to_s.should == '729.0'
|
39
|
+
book.cell("numbers!D10").to_s.should == '3.0'
|
40
|
+
|
41
|
+
book.cell("text & pic!A10").value.should == 'This is an Excel XLSX workbook.'
|
42
|
+
book.cell("bools & errors!B3").value.should == true
|
43
|
+
book.cell("high refs!AM619").value.should == 'This is some text'
|
44
|
+
book.cell("high refs!AO624").value.should == 24.0
|
45
|
+
book.cell("high refs!AP631").value.should == 13.0
|
46
|
+
|
47
|
+
book.cell(%Q{'text & pic'!A10}).value.should == 'This is an Excel XLSX workbook.'
|
48
|
+
book.cell(%Q{'bools & errors'!B3}).value.should == true
|
49
|
+
book.cell(%Q{'high refs'!AM619}).value.should == 'This is some text'
|
50
|
+
book.cell(%Q{'high refs'!AO624}).value.should == 24.0
|
51
|
+
book.cell(%Q{'high refs'!AP631}).value.should == 13.0
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should handle named cell ranges" do
|
55
|
+
name = TestDataFile.expand_path("various_samples.xlsx")
|
56
|
+
book = POI::Workbook.open(name)
|
57
|
+
|
58
|
+
book.named_ranges.length.should == 3
|
59
|
+
book.named_ranges.collect{|e| e.name}.should == %w{four_times_six NAMES nums}
|
60
|
+
book.named_ranges.collect{|e| e.sheet.name}.should == ['high refs', 'bools & errors', 'high refs']
|
61
|
+
book.named_ranges.collect{|e| e.formula}.should == ["'high refs'!$AO$624", "'bools & errors'!$D$2:$D$11", "'high refs'!$AP$619:$AP$631"]
|
62
|
+
book['four_times_six'].should == 24.0
|
63
|
+
book['nums'].should == (1..13).collect{|e| e * 1.0}
|
64
|
+
|
65
|
+
# NAMES is a range of empty cells
|
66
|
+
book['NAMES'].should == [nil, nil, nil, nil, nil, nil, nil]
|
67
|
+
book.cell('NAMES').each do | cell |
|
68
|
+
cell.value.should be_nil
|
69
|
+
cell.poi_cell.should be_nil
|
70
|
+
cell.to_s.should be_empty
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should return cell values by reference" do
|
75
|
+
name = TestDataFile.expand_path("various_samples.xlsx")
|
76
|
+
book = POI::Workbook.open(name)
|
77
|
+
|
78
|
+
book['text & pic!A10'].should == 'This is an Excel XLSX workbook.'
|
79
|
+
book['bools & errors!B3'].should == true
|
80
|
+
book['high refs!AM619'].should == 'This is some text'
|
81
|
+
book['high refs!AO624'].should == 24.0
|
82
|
+
book['high refs!AP631'].should == 13.0
|
83
|
+
end
|
26
84
|
end
|
27
85
|
|
28
86
|
describe POI::Worksheets do
|
@@ -54,8 +112,19 @@ describe POI::Worksheets do
|
|
54
112
|
sheet.should be_kind_of POI::Worksheet
|
55
113
|
end
|
56
114
|
|
57
|
-
book.worksheets.size.should ==
|
58
|
-
book.worksheets.collect.size.should ==
|
115
|
+
book.worksheets.size.should == 5
|
116
|
+
book.worksheets.collect.size.should == 5
|
117
|
+
end
|
118
|
+
|
119
|
+
it "returns cells when passing a cell reference" do
|
120
|
+
name = TestDataFile.expand_path("various_samples.xlsx")
|
121
|
+
book = POI::Workbook.open(name)
|
122
|
+
book['dates']['A2'].should == Date.parse('2010-02-28')
|
123
|
+
book['dates']['a2'].should == Date.parse('2010-02-28')
|
124
|
+
book['dates']['B2'].should == Date.parse('2010-03-14')
|
125
|
+
book['dates']['b2'].should == Date.parse('2010-03-14')
|
126
|
+
book['dates']['C2'].should == Date.parse('2010-03-28')
|
127
|
+
book['dates']['c2'].should == Date.parse('2010-03-28')
|
59
128
|
end
|
60
129
|
end
|
61
130
|
|
@@ -133,7 +202,6 @@ describe POI::Cells do
|
|
133
202
|
rows[9][3].to_s.should == '3.0'
|
134
203
|
end
|
135
204
|
|
136
|
-
|
137
205
|
it "should handle array access from the workbook down to cells" do
|
138
206
|
book[1][9][0].to_s.should == '9.0'
|
139
207
|
book[1][9][1].to_s.should == '81.0'
|
@@ -153,26 +221,26 @@ describe POI::Cells do
|
|
153
221
|
rows[6][0].value.should == 0.0 #'~CIRCULAR~REF~'
|
154
222
|
rows[6][0].error_value.should be_nil
|
155
223
|
|
156
|
-
rows[7][0].value.should be_nil
|
157
|
-
rows[7][0].error_value.should == '
|
224
|
+
rows[7][0].value.should be_nil
|
225
|
+
rows[7][0].error_value.should == '#DIV/0!'
|
158
226
|
|
159
|
-
rows[8][0].value.should be_nil
|
160
|
-
rows[8][0].error_value.should == '
|
227
|
+
rows[8][0].value.should be_nil
|
228
|
+
rows[8][0].error_value.should == '#N/A'
|
161
229
|
|
162
|
-
rows[9][0].value.should be_nil
|
163
|
-
rows[9][0].error_value.should == '
|
230
|
+
rows[9][0].value.should be_nil
|
231
|
+
rows[9][0].error_value.should == '#NAME?'
|
164
232
|
|
165
|
-
rows[10][0].value.should be_nil
|
166
|
-
rows[10][0].error_value.should == '
|
233
|
+
rows[10][0].value.should be_nil
|
234
|
+
rows[10][0].error_value.should == '#NULL!'
|
167
235
|
|
168
|
-
rows[11][0].value.should be_nil
|
169
|
-
rows[11][0].error_value.should == '
|
236
|
+
rows[11][0].value.should be_nil
|
237
|
+
rows[11][0].error_value.should == '#NUM!'
|
170
238
|
|
171
|
-
rows[12][0].value.should be_nil
|
172
|
-
rows[12][0].error_value.should == '
|
239
|
+
rows[12][0].value.should be_nil
|
240
|
+
rows[12][0].error_value.should == '#REF!'
|
173
241
|
|
174
|
-
rows[13][0].value.should be_nil
|
175
|
-
rows[13][0].error_value.should == '
|
242
|
+
rows[13][0].value.should be_nil
|
243
|
+
rows[13][0].error_value.should == '#VALUE!'
|
176
244
|
|
177
245
|
lambda{ rows[14][0].value }.should_not raise_error(Java::java.lang.RuntimeException)
|
178
246
|
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 6
|
8
|
+
- 0
|
9
|
+
version: 0.6.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Scott Deming
|
@@ -50,6 +50,7 @@ files:
|
|
50
50
|
- lib/poi.rb
|
51
51
|
- lib/poi/workbook.rb
|
52
52
|
- lib/poi/workbook/cell.rb
|
53
|
+
- lib/poi/workbook/named_range.rb
|
53
54
|
- lib/poi/workbook/row.rb
|
54
55
|
- lib/poi/workbook/workbook.rb
|
55
56
|
- lib/poi/workbook/worksheet.rb
|