jruby-poi 0.6.1 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -8,19 +8,19 @@ module POI
8
8
  end
9
9
 
10
10
  def name
11
- @name.getNameName
11
+ @name.name_name
12
12
  end
13
13
 
14
14
  def sheet
15
- @workbook[@name.getSheetName]
15
+ @workbook.worksheets[@name.sheet_name]
16
16
  end
17
17
 
18
18
  def formula
19
- @name.getRefersToFormula
19
+ @name.refers_to_formula
20
20
  end
21
21
 
22
22
  def cells
23
- [@workbook.cell(formula)].flatten
23
+ @name.is_deleted ? [] : [@workbook.cell(formula)].flatten
24
24
  end
25
25
 
26
26
  def values
@@ -5,44 +5,54 @@ module POI
5
5
  def initialize(worksheet)
6
6
  @worksheet = worksheet
7
7
  @poi_worksheet = worksheet.poi_worksheet
8
+ @rows = {}
8
9
  end
9
10
 
10
11
  def [](index)
11
- Row.new(@poi_worksheet.getRow(index))
12
+ @rows[index] ||= Row.new(@poi_worksheet.row(index) || @poi_worksheet.create_row(index), @worksheet)
12
13
  end
13
14
 
14
15
  def size
15
- @poi_worksheet.getPhysicalNumberOfRows
16
+ @poi_worksheet.physical_number_of_rows
16
17
  end
17
18
 
18
19
  def each
19
- it = @poi_worksheet.rowIterator
20
- yield Row.new(it.next) while it.hasNext
20
+ it = @poi_worksheet.row_iterator
21
+ yield Row.new(it.next, @worksheet) while it.has_next
21
22
  end
22
23
  end
23
24
 
24
- class Row
25
- def initialize(row)
26
- @row = row
25
+ class Row < Facade(:poi_row, org.apache.poi.ss.usermodel.Row)
26
+ def initialize(row, worksheet)
27
+ @row = row
28
+ @worksheet = worksheet
27
29
  end
28
30
 
29
31
  def [](index)
30
32
  return nil if poi_row.nil?
31
- Cell.new(poi_row.getCell(index))
33
+ cells[index]
32
34
  end
33
35
 
34
36
  def cells
35
- Cells.new(self)
37
+ @cells ||= Cells.new(self)
36
38
  end
37
39
 
38
40
  def index
39
41
  return nil if poi_row.nil?
40
- poi_row.getRowNum
42
+ poi_row.row_num
41
43
  end
42
44
 
45
+ def height_in_points= num
46
+ set_height_in_points num.to_f
47
+ end
48
+
43
49
  def poi_row
44
50
  @row
45
51
  end
52
+
53
+ def worksheet
54
+ @worksheet
55
+ end
46
56
  end
47
57
  end
48
58
 
@@ -1,8 +1,18 @@
1
1
  require 'tmpdir'
2
2
  require 'stringio'
3
+ require 'java'
3
4
 
4
5
  module POI
5
- class Workbook
6
+ class Workbook < Facade(:poi_workbook, org.apache.poi.ss.usermodel.Workbook)
7
+ FONT = org.apache.poi.ss.usermodel.Font
8
+ FONT_CONSTANTS = Hash[*FONT.constants.map{|e| [e.downcase.to_sym, FONT.const_get(e)]}.flatten]
9
+
10
+ CELL_STYLE = org.apache.poi.ss.usermodel.CellStyle
11
+ CELL_STYLE_CONSTANTS = Hash[*CELL_STYLE.constants.map{|e| [e.downcase.to_sym, CELL_STYLE.const_get(e)]}.flatten]
12
+
13
+ INDEXED_COLORS = org.apache.poi.ss.usermodel.IndexedColors
14
+ INDEXED_COLORS_CONSTANTS = Hash[*INDEXED_COLORS.constants.map{|e| [e.downcase.to_sym, INDEXED_COLORS.const_get(e)]}.flatten]
15
+
6
16
  def self.open(filename_or_stream)
7
17
  name, stream = if filename_or_stream.kind_of?(java.io.InputStream)
8
18
  [File.join(Dir.tmpdir, "spreadsheet.xlsx"), filename_or_stream]
@@ -21,11 +31,19 @@ module POI
21
31
  instance
22
32
  end
23
33
 
34
+ def self.create(filename)
35
+ self.new(filename, nil)
36
+ end
37
+
24
38
  attr_reader :filename
25
39
 
26
40
  def initialize(filename, io_stream)
27
41
  @filename = filename
28
- @workbook = org.apache.poi.ss.usermodel.WorkbookFactory.create(io_stream)
42
+ @workbook = io_stream ? org.apache.poi.ss.usermodel.WorkbookFactory.create(io_stream) : org.apache.poi.xssf.usermodel.XSSFWorkbook.new
43
+ end
44
+
45
+ def formula_evaluator
46
+ @formula_evaluator ||= @workbook.creation_helper.create_formula_evaluator
29
47
  end
30
48
 
31
49
  def save
@@ -48,32 +66,102 @@ module POI
48
66
  def close
49
67
  #noop
50
68
  end
69
+
70
+ def create_sheet name='New Sheet'
71
+ # @workbook.createSheet name
72
+ worksheets[name]
73
+ end
74
+
75
+ def create_style options={}
76
+ font = @workbook.createFont
77
+ set_value( font, :font_height_in_points, options ) do | value |
78
+ value.to_i
79
+ end
80
+ set_value font, :bold_weight, options, FONT_CONSTANTS
81
+ set_value font, :color, options, INDEXED_COLORS_CONSTANTS do | value |
82
+ value.index
83
+ end
84
+
85
+ style = @workbook.createCellStyle
86
+ [:alignment, :vertical_alignment, :fill_pattern, :border_right, :border_left, :border_top, :border_bottom].each do | sym |
87
+ set_value style, sym, options, CELL_STYLE_CONSTANTS do | value |
88
+ value.to_i
89
+ end
90
+ end
91
+ [:right_border_color, :left_border_color, :top_border_color, :bottom_border_color, :fill_foreground_color, :fill_background_color].each do | sym |
92
+ set_value( style, sym, options, INDEXED_COLORS_CONSTANTS ) do | value |
93
+ value.index
94
+ end
95
+ end
96
+ [:hidden, :locked, :wrap_text].each do | sym |
97
+ set_value style, sym, options
98
+ end
99
+ [:rotation, :indentation].each do | sym |
100
+ set_value( style, sym, options ) do | value |
101
+ value.to_i
102
+ end
103
+ end
104
+ set_value( style, :data_format, options ) do |value|
105
+ @workbook.create_data_format.getFormat(value)
106
+ end
107
+ style.font = font
108
+ style
109
+ end
110
+
111
+ def set_value on, value_sym, from, using=nil
112
+ return on unless from.has_key?(value_sym)
113
+ value = if using
114
+ using[from[value_sym]]
115
+ else
116
+ from[value_sym]
117
+ end
118
+ value = yield value if block_given?
119
+ on.send("set_#{value_sym}", value)
120
+ on
121
+ end
51
122
 
52
123
  def worksheets
53
124
  @worksheets ||= Worksheets.new(self)
54
125
  end
55
126
 
56
127
  def named_ranges
57
- @named_ranges ||= (0...@workbook.getNumberOfNames).collect do | idx |
58
- NamedRange.new @workbook.getNameAt(idx), self
128
+ @named_ranges ||= (0...@workbook.number_of_names).collect do | idx |
129
+ NamedRange.new @workbook.name_at(idx), self
59
130
  end
60
131
  end
61
132
 
62
- # sheet_index can be a Fixnum, referring to the 0-based sheet or
133
+ # reference can be a Fixnum, referring to the 0-based sheet or
63
134
  # a String which is the sheet name or a cell reference.
64
135
  #
65
136
  # If a cell reference is passed the value of that cell is returned.
137
+ #
138
+ # If the reference refers to a contiguous range of cells an Array of values will be returned.
139
+ #
140
+ # If the reference refers to a multiple columns a Hash of values will be returned by column name.
66
141
  def [](reference)
67
- begin
68
- cell = cell(reference)
69
- Array === cell ? cell.collect{|e| e.value} : cell.value
70
- rescue
71
- answer = worksheets[reference]
72
- answer.poi_worksheet.nil? ? nil : answer
142
+ if Fixnum === reference
143
+ return worksheets[reference]
144
+ end
145
+
146
+ if sheet = worksheets.detect{|e| e.name == reference}
147
+ return sheet.poi_worksheet.nil? ? nil : sheet
148
+ end
149
+
150
+ cell = cell(reference)
151
+ if Array === cell
152
+ cell.collect{|e| e.value}
153
+ elsif Hash === cell
154
+ values = {}
155
+ cell.each_pair{|column_name, cells| values[column_name] = cells.collect{|e| e.value}}
156
+ values
157
+ else
158
+ cell.value
73
159
  end
74
160
  end
75
161
 
76
162
  # takes a String in the form of a 3D cell reference and returns the Cell (eg. "Sheet 1!A1")
163
+ #
164
+ # If the reference refers to a contiguous range of cells an array of Cells will be returned
77
165
  def cell reference
78
166
  # if the reference is to a named range of cells, get that range and return it
79
167
  if named_range = named_ranges.detect{|e| e.name == reference}
@@ -85,32 +173,90 @@ module POI
85
173
  end
86
174
  end
87
175
 
176
+ # check if the named_range is a full column reference
177
+ if column_reference?(named_range)
178
+ return all_cells_in_column named_range.formula
179
+ end
180
+
88
181
  # if the reference is to an area of cells, get all the cells in that area and return them
89
182
  cells = cells_in_area(reference)
90
183
  unless cells.empty?
91
184
  return cells.length == 1 ? cells.first : cells
92
185
  end
93
186
 
94
- ref = org.apache.poi.ss.util.CellReference.new(reference)
95
- if ref.getSheetName.nil?
187
+ if column_reference?(reference)
188
+ return all_cells_in_column reference
189
+ end
190
+
191
+ ref = POI::CELL_REF.new(reference)
192
+ single_cell ref
193
+ end
194
+
195
+ # ref is a POI::CELL_REF instance
196
+ def single_cell ref
197
+ if ref.sheet_name.nil?
96
198
  raise 'cell references at the workbook level must include a sheet reference (eg. Sheet1!A1)'
97
199
  else
98
- worksheets[ref.getSheetName][ref.getRow][ref.getCol]
200
+ worksheets[ref.sheet_name][ref.row][ref.col]
99
201
  end
100
202
  end
101
203
 
102
204
  def cells_in_area reference
103
205
  area = Area.new(reference)
104
- if area.single_cell_reference?
105
- []
106
- else
107
- area.in(self).compact
108
- end
206
+ area.in(self)
109
207
  end
110
208
 
111
209
  def poi_workbook
112
210
  @workbook
113
211
  end
212
+
213
+ def on_update cell
214
+ #clear_all_formula_results
215
+ #formula_evaluator.notify_update_cell cell.poi_cell
216
+ end
217
+
218
+ def on_formula_update cell
219
+ #clear_all_formula_results
220
+ formula_evaluator.notify_set_formula cell.poi_cell
221
+ formula_evaluator.evaluate_formula_cell(cell.poi_cell)
222
+ end
223
+
224
+ def on_delete cell
225
+ #clear_all_formula_results
226
+ formula_evaluator.notify_delete_cell cell.poi_cell
227
+ end
228
+
229
+ def clear_all_formula_results
230
+ formula_evaluator.clear_all_cached_result_values
231
+ end
232
+
233
+ def all_cells_in_column reference
234
+ sheet_parts = reference.split('!')
235
+ area_parts = sheet_parts.last.split(':')
236
+ area_start = "#{sheet_parts.first}!#{area_parts.first}"
237
+ area_end = area_parts.last
238
+
239
+ area = org.apache.poi.ss.util.AreaReference.getWholeColumn(area_start, area_end)
240
+ full_ref = "#{area.first_cell.format_as_string}:#{area.last_cell.format_as_string}"
241
+ Area.new(full_ref).in(self)
242
+ # cell_reference = org.apache.poi.ss.util.CellReference.new( reference + "1" )
243
+ # column = cell_reference.get_col
244
+ # sheet = cell_reference.get_sheet_name
245
+ # worksheets[sheet].rows.collect{|row| row[column]}
246
+ end
247
+
248
+ private
249
+ def column_reference? named_range_or_reference
250
+ return false if named_range_or_reference.nil?
251
+
252
+ reference = named_range_or_reference
253
+ if NamedRange === named_range_or_reference
254
+ reference = named_range_or_reference.formula
255
+ end
256
+ cell_reference = reference.split('!', 2).last
257
+ beginning, ending = cell_reference.split(':')
258
+ !(beginning =~ /\d/ || (ending.nil? ? false : ending =~ /\d/))
259
+ end
114
260
  end
115
261
  end
116
262
 
@@ -7,54 +7,72 @@ module POI
7
7
  @poi_workbook = workbook.poi_workbook
8
8
  end
9
9
 
10
- def [](index)
10
+ def [](index_or_name)
11
11
  worksheet = case
12
- when index.kind_of?(Numeric)
13
- @poi_workbook.getSheetAt(index)
12
+ when index_or_name.kind_of?(Numeric)
13
+ @poi_workbook.sheet_at(index_or_name) || @poi_workbook.create_sheet
14
14
  else
15
- @poi_workbook.getSheet(index)
15
+ @poi_workbook.get_sheet(index_or_name) || @poi_workbook.create_sheet(index_or_name)
16
16
  end
17
- Worksheet.new(worksheet)
17
+ Worksheet.new(worksheet, @workbook)
18
18
  end
19
19
 
20
20
  def size
21
- @poi_workbook.getNumberOfSheets
21
+ @poi_workbook.number_of_sheets
22
22
  end
23
23
 
24
24
  def each
25
- (0...size).each { |i| yield Worksheet.new(@poi_workbook.getSheetAt(i)) }
25
+ (0...size).each { |i| yield Worksheet.new(@poi_workbook.sheet_at(i), @workbook) }
26
26
  end
27
27
  end
28
28
 
29
- class Worksheet
30
- def initialize(worksheet = nil)
29
+ class Worksheet < Facade(:poi_worksheet, org.apache.poi.ss.usermodel.Sheet)
30
+
31
+ def initialize(worksheet, workbook)
31
32
  @worksheet = worksheet
33
+ @workbook = workbook
32
34
  end
33
-
35
+
34
36
  def name
35
- @worksheet.getSheetName
37
+ @worksheet.sheet_name
38
+ end
39
+
40
+ def first_row
41
+ @worksheet.first_row_num
42
+ end
43
+
44
+ def last_row
45
+ @worksheet.last_row_num
36
46
  end
37
47
 
38
48
  def rows
39
- Rows.new(self)
49
+ @rows ||= Rows.new(self)
40
50
  end
41
51
 
42
52
  # Accepts a Fixnum or a String as the row_index
43
53
  #
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
54
+ # row_index as Fixnum: returns the 0-based row
55
+ #
56
+ # row_index as String: assumes a cell reference within this sheet
57
+ # if the value of the reference is non-nil the value is returned,
58
+ # otherwise the referenced cell is returned
46
59
  def [](row_index)
47
60
  if Fixnum === row_index
48
61
  rows[row_index]
49
62
  else
50
63
  ref = org.apache.poi.ss.util.CellReference.new(row_index)
51
- rows[ref.getRow][ref.getCol].value
64
+ cell = rows[ref.row][ref.col]
65
+ cell && cell.value ? cell.value : cell
52
66
  end
53
67
  end
54
68
 
55
69
  def poi_worksheet
56
70
  @worksheet
57
71
  end
72
+
73
+ def workbook
74
+ @workbook
75
+ end
58
76
  end
59
77
  end
60
78
 
data/spec_debug.sh CHANGED
@@ -1,13 +1,24 @@
1
1
  #!/bin/sh
2
2
  #set -x
3
3
  RUBY_DIR=$(dirname $(which ruby))/..
4
- RUBYGEMS_DIR=${RUBY_DIR}/lib/ruby/gems/1.8/gems
4
+ if [[ ${RUBY_DIR} == *1.6.* ]]
5
+ then
6
+ RUBYGEMS_DIR=${RUBY_DIR}/lib/ruby/gems/jruby/gems
7
+ else
8
+ RUBYGEMS_DIR=${RUBY_DIR}/lib/ruby/gems/1.8/gems
9
+ fi
5
10
 
6
11
  GEM_COLUMNIZE=$(ls -1d $RUBYGEMS_DIR/columnize*/lib | head -1 | /usr/bin/ruby -e 'print File.expand_path($stdin.read)')
7
12
  GEM_RUBY_DEBUG_BASE=$(ls -1d $RUBYGEMS_DIR/ruby-debug-base-*/lib | head -1 | /usr/bin/ruby -e 'print File.expand_path($stdin.read)')
8
13
  GEM_RUBY_DEBUG_CLI=$(ls -1d $RUBYGEMS_DIR/ruby-debug-*/cli | head -1 | /usr/bin/ruby -e 'print File.expand_path($stdin.read)')
9
14
  GEM_SOURCES=$(ls -1d $RUBYGEMS_DIR/sources-*/lib | head -1 | /usr/bin/ruby -e 'print File.expand_path($stdin.read)')
10
15
 
16
+ echo "RUBYGEMS_DIR: ${RUBYGEMS_DIR}"
17
+ echo "GEM_SOURCES: ${GEM_SOURCES}"
18
+ echo "GEM_COLUMNIZE: ${GEM_COLUMNIZE}"
19
+ echo "GEM_RUBY_DEBUG_CLI: ${GEM_RUBY_DEBUG_CLI}"
20
+ echo "GEM_RUBY_DEBUG_BASE: ${GEM_RUBY_DEBUG_BASE}"
21
+
11
22
  runner="ruby --client \
12
23
  -I${GEM_COLUMNIZE} \
13
24
  -I${GEM_RUBY_DEBUG_BASE} \
@@ -15,7 +26,7 @@ runner="ruby --client \
15
26
  -I${GEM_SOURCES} \
16
27
  -rubygems -S"
17
28
 
18
- cmd="spec -c --debugger $*"
29
+ cmd="bundle exec rdebug rspec -c $*"
19
30
  #cmd="irb"
20
31
 
21
32
  $runner $cmd