jruby-poi 0.6.1 → 0.7.1

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.
@@ -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