datashift 0.2.1 → 0.2.2
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.
- data/.document +5 -5
- data/LICENSE.txt +26 -26
- data/README.markdown +326 -305
- data/README.rdoc +19 -19
- data/Rakefile +86 -93
- data/VERSION +1 -1
- data/datashift.gemspec +163 -152
- data/lib/applications/jruby/jexcel_file.rb +410 -408
- data/lib/applications/jruby/word.rb +79 -79
- data/lib/datashift.rb +183 -152
- data/lib/datashift/exceptions.rb +11 -11
- data/lib/datashift/file_definitions.rb +353 -353
- data/lib/datashift/mapping_file_definitions.rb +87 -87
- data/lib/datashift/method_detail.rb +293 -275
- data/lib/datashift/method_dictionary.rb +208 -209
- data/lib/datashift/method_mapper.rb +90 -90
- data/lib/datashift/model_mapper.rb +27 -0
- data/lib/exporters/csv_exporter.rb +36 -0
- data/lib/exporters/excel_exporter.rb +116 -0
- data/lib/exporters/exporter_base.rb +15 -0
- data/lib/generators/csv_generator.rb +36 -36
- data/lib/generators/excel_generator.rb +106 -122
- data/lib/generators/generator_base.rb +13 -13
- data/lib/helpers/core_ext/to_b.rb +24 -24
- data/lib/helpers/rake_utils.rb +42 -0
- data/lib/helpers/spree_helper.rb +194 -153
- data/lib/java/poi-3.7/LICENSE +507 -507
- data/lib/java/poi-3.7/NOTICE +21 -21
- data/lib/java/poi-3.7/RELEASE_NOTES.txt +115 -115
- data/lib/loaders/csv_loader.rb +98 -98
- data/lib/loaders/excel_loader.rb +155 -155
- data/lib/loaders/loader_base.rb +420 -420
- data/lib/loaders/spreadsheet_loader.rb +136 -136
- data/lib/loaders/spree/image_loader.rb +67 -63
- data/lib/loaders/spree/product_loader.rb +289 -248
- data/lib/thor/generate_excel.thor +54 -0
- data/sandbox/app/controllers/application_controller.rb +3 -0
- data/sandbox/config/application.rb +43 -0
- data/sandbox/config/database.yml +34 -0
- data/sandbox/config/environment.rb +7 -0
- data/sandbox/config/environments/development.rb +30 -0
- data/spec/csv_loader_spec.rb +30 -30
- data/spec/datashift_spec.rb +26 -26
- data/spec/db/migrate/20110803201325_create_test_bed.rb +85 -85
- data/spec/excel_exporter_spec.rb +78 -78
- data/spec/excel_generator_spec.rb +78 -78
- data/spec/excel_loader_spec.rb +223 -223
- data/spec/file_definitions.rb +141 -141
- data/spec/fixtures/ProjectsDefaults.yml +29 -29
- data/spec/fixtures/config/database.yml +27 -27
- data/spec/fixtures/datashift_Spree_db.sqlite +0 -0
- data/spec/fixtures/datashift_test_models_db.sqlite +0 -0
- data/spec/fixtures/negative/SpreeProdMiss1Mandatory.csv +4 -4
- data/spec/fixtures/negative/SpreeProdMissManyMandatory.csv +4 -4
- data/spec/fixtures/spree/SpreeProducts.csv +4 -4
- data/spec/fixtures/spree/SpreeProducts.xls +0 -0
- data/spec/fixtures/spree/SpreeProductsMultiColumn.csv +4 -4
- data/spec/fixtures/spree/SpreeProductsMultiColumn.xls +0 -0
- data/spec/fixtures/spree/SpreeProductsSimple.csv +4 -4
- data/spec/fixtures/spree/SpreeProductsWithImages.csv +4 -4
- data/spec/fixtures/spree/SpreeZoneExample.csv +5 -5
- data/spec/fixtures/test_model_defs.rb +57 -57
- data/spec/loader_spec.rb +120 -120
- data/spec/method_dictionary_spec.rb +242 -242
- data/spec/method_mapper_spec.rb +41 -41
- data/spec/spec_helper.rb +154 -116
- data/spec/spree_exporter_spec.rb +67 -0
- data/spec/spree_generator_spec.rb +77 -64
- data/spec/spree_loader_spec.rb +363 -324
- data/spec/spree_method_mapping_spec.rb +218 -214
- data/tasks/config/seed_fu_product_template.erb +15 -15
- data/tasks/config/tidy_config.txt +12 -12
- data/tasks/{excel_generator.rake → export/excel_generator.rake} +101 -78
- data/tasks/file_tasks.rake +36 -36
- data/tasks/import/csv.rake +50 -49
- data/tasks/import/excel.rake +74 -71
- data/tasks/spree/image_load.rake +108 -108
- data/tasks/spree/product_loader.rake +43 -43
- data/tasks/word_to_seedfu.rake +166 -166
- data/test/helper.rb +18 -18
- data/test/test_interact.rb +7 -7
- metadata +16 -8
- data/datashift-0.1.0.gem +0 -0
- data/tasks/db_tasks.rake +0 -66
@@ -1,409 +1,411 @@
|
|
1
|
-
# Copyright:: (c) Autotelik Media Ltd 2011
|
2
|
-
# Author :: Tom Statter
|
3
|
-
# Date :: Aug 2010
|
4
|
-
# License:: MIT
|
5
|
-
#
|
6
|
-
# An Excel file helper. Create and populate XSL files
|
7
|
-
#
|
8
|
-
# The maximum number of columns and rows in an Excel file is fixed at 256 Columns and 65536 Rows
|
9
|
-
#
|
10
|
-
# POI jar location needs to be added to class path.
|
11
|
-
#
|
12
|
-
# TODO - Check out http://poi.apache.org/poi-ruby.html
|
13
|
-
#
|
14
|
-
if(DataShift::Guards::jruby?)
|
15
|
-
|
16
|
-
require "poi-3.7-20101029.jar"
|
17
|
-
|
18
|
-
class JExcelFile
|
19
|
-
|
20
|
-
java_import org.apache.poi.poifs.filesystem.POIFSFileSystem
|
21
|
-
|
22
|
-
include_class 'org.apache.poi.hssf.usermodel.HSSFCell'
|
23
|
-
include_class 'org.apache.poi.hssf.usermodel.HSSFWorkbook'
|
24
|
-
include_class 'org.apache.poi.hssf.usermodel.HSSFCellStyle'
|
25
|
-
include_class 'org.apache.poi.hssf.usermodel.HSSFDataFormat'
|
26
|
-
include_class 'org.apache.poi.hssf.usermodel.HSSFClientAnchor'
|
27
|
-
include_class 'org.apache.poi.hssf.usermodel.HSSFRichTextString'
|
28
|
-
|
29
|
-
include_class 'java.io.ByteArrayOutputStream'
|
30
|
-
include_class 'java.util.Date'
|
31
|
-
include_class 'java.io.FileInputStream'
|
32
|
-
include_class 'java.io.FileOutputStream'
|
33
|
-
|
34
|
-
attr_accessor :book, :row, :date_style
|
35
|
-
attr_reader :sheet
|
36
|
-
|
37
|
-
MAX_COLUMNS = 256.freeze
|
38
|
-
|
39
|
-
def self.date_format
|
40
|
-
HSSFDataFormat.getBuiltinFormat("m/d/yy h:mm")
|
41
|
-
end
|
42
|
-
|
43
|
-
# NOTE: this is the POI 3.7 HSSF maximum rows
|
44
|
-
def self.maxrows
|
45
|
-
return 65535
|
46
|
-
end
|
47
|
-
|
48
|
-
# The HSSFWorkbook uses 0 based indexes, whilst our companion jexcel_win32 class
|
49
|
-
# uses 1 based indexes. So they can be used interchangeably we bring indexes
|
50
|
-
# inline with JExcel usage in this class, as 1 based maps more intuitively for the user
|
51
|
-
#
|
52
|
-
# i.e Row 1 passed to this class, internally means Row 0
|
53
|
-
|
54
|
-
def initialize()
|
55
|
-
@book = nil
|
56
|
-
# The @patriarchs hash is a workaround because HSSFSheet.getDrawingPatriarch()
|
57
|
-
# causes a lot of issues (if it doesn't throw an exception!)
|
58
|
-
@patriarchs = Hash.new
|
59
|
-
|
60
|
-
@date_style = nil
|
61
|
-
end
|
62
|
-
|
63
|
-
def open(filename)
|
64
|
-
inp = FileInputStream.new(filename)
|
65
|
-
|
66
|
-
@book = HSSFWorkbook.new(inp)
|
67
|
-
|
68
|
-
@date_style = @book.createCellStyle
|
69
|
-
@date_style.setDataFormat( JExcelFile::date_format )
|
70
|
-
|
71
|
-
@current_sheet = 0
|
72
|
-
sheet(@current_sheet)
|
73
|
-
end
|
74
|
-
|
75
|
-
# EXCEL ITEMS
|
76
|
-
|
77
|
-
def create(sheet_name)
|
78
|
-
@book = HSSFWorkbook.new() if @book.nil?
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
@
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
@
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
#############################
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
#
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
HSSFCell::
|
177
|
-
elsif(data.
|
178
|
-
HSSFCell::
|
179
|
-
|
180
|
-
HSSFCell::
|
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
|
-
@row.createCell(column - 1, HSSFCell::
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
##############################
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
when HSSFCell::
|
267
|
-
when HSSFCell::
|
268
|
-
when HSSFCell::
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
out.
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
#
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
@sheet.
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
outs.
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
#
|
338
|
-
#
|
339
|
-
#
|
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
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
cell_index
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
1
|
+
# Copyright:: (c) Autotelik Media Ltd 2011
|
2
|
+
# Author :: Tom Statter
|
3
|
+
# Date :: Aug 2010
|
4
|
+
# License:: MIT
|
5
|
+
#
|
6
|
+
# An Excel file helper. Create and populate XSL files
|
7
|
+
#
|
8
|
+
# The maximum number of columns and rows in an Excel file is fixed at 256 Columns and 65536 Rows
|
9
|
+
#
|
10
|
+
# POI jar location needs to be added to class path.
|
11
|
+
#
|
12
|
+
# TODO - Check out http://poi.apache.org/poi-ruby.html
|
13
|
+
#
|
14
|
+
if(DataShift::Guards::jruby?)
|
15
|
+
|
16
|
+
require "poi-3.7-20101029.jar"
|
17
|
+
|
18
|
+
class JExcelFile
|
19
|
+
|
20
|
+
java_import org.apache.poi.poifs.filesystem.POIFSFileSystem
|
21
|
+
|
22
|
+
include_class 'org.apache.poi.hssf.usermodel.HSSFCell'
|
23
|
+
include_class 'org.apache.poi.hssf.usermodel.HSSFWorkbook'
|
24
|
+
include_class 'org.apache.poi.hssf.usermodel.HSSFCellStyle'
|
25
|
+
include_class 'org.apache.poi.hssf.usermodel.HSSFDataFormat'
|
26
|
+
include_class 'org.apache.poi.hssf.usermodel.HSSFClientAnchor'
|
27
|
+
include_class 'org.apache.poi.hssf.usermodel.HSSFRichTextString'
|
28
|
+
|
29
|
+
include_class 'java.io.ByteArrayOutputStream'
|
30
|
+
include_class 'java.util.Date'
|
31
|
+
include_class 'java.io.FileInputStream'
|
32
|
+
include_class 'java.io.FileOutputStream'
|
33
|
+
|
34
|
+
attr_accessor :book, :row, :date_style
|
35
|
+
attr_reader :sheet
|
36
|
+
|
37
|
+
MAX_COLUMNS = 256.freeze unless defined?(MAX_COLUMNS)
|
38
|
+
|
39
|
+
def self.date_format
|
40
|
+
HSSFDataFormat.getBuiltinFormat("m/d/yy h:mm")
|
41
|
+
end
|
42
|
+
|
43
|
+
# NOTE: this is the POI 3.7 HSSF maximum rows
|
44
|
+
def self.maxrows
|
45
|
+
return 65535
|
46
|
+
end
|
47
|
+
|
48
|
+
# The HSSFWorkbook uses 0 based indexes, whilst our companion jexcel_win32 class
|
49
|
+
# uses 1 based indexes. So they can be used interchangeably we bring indexes
|
50
|
+
# inline with JExcel usage in this class, as 1 based maps more intuitively for the user
|
51
|
+
#
|
52
|
+
# i.e Row 1 passed to this class, internally means Row 0
|
53
|
+
|
54
|
+
def initialize()
|
55
|
+
@book = nil
|
56
|
+
# The @patriarchs hash is a workaround because HSSFSheet.getDrawingPatriarch()
|
57
|
+
# causes a lot of issues (if it doesn't throw an exception!)
|
58
|
+
@patriarchs = Hash.new
|
59
|
+
|
60
|
+
@date_style = nil
|
61
|
+
end
|
62
|
+
|
63
|
+
def open(filename)
|
64
|
+
inp = FileInputStream.new(filename)
|
65
|
+
|
66
|
+
@book = HSSFWorkbook.new(inp)
|
67
|
+
|
68
|
+
@date_style = @book.createCellStyle
|
69
|
+
@date_style.setDataFormat( JExcelFile::date_format )
|
70
|
+
|
71
|
+
@current_sheet = 0
|
72
|
+
sheet(@current_sheet)
|
73
|
+
end
|
74
|
+
|
75
|
+
# EXCEL ITEMS
|
76
|
+
|
77
|
+
def create(sheet_name)
|
78
|
+
@book = HSSFWorkbook.new() if @book.nil?
|
79
|
+
|
80
|
+
acceptable_name = sheet_name.gsub(':', '').gsub(" ", '')
|
81
|
+
|
82
|
+
# Double check sheet doesn't already exist
|
83
|
+
if(@book.getSheetIndex(acceptable_name) < 0)
|
84
|
+
sheet = @book.createSheet(acceptable_name.gsub(" ", ''))
|
85
|
+
|
86
|
+
@patriarchs.store(acceptable_name, sheet.createDrawingPatriarch())
|
87
|
+
end
|
88
|
+
@current_sheet = @book.getSheetIndex(acceptable_name)
|
89
|
+
|
90
|
+
@date_style = @book.createCellStyle
|
91
|
+
@date_style.setDataFormat( JExcelFile::date_format )
|
92
|
+
|
93
|
+
self.sheet()
|
94
|
+
end
|
95
|
+
|
96
|
+
alias_method(:create_sheet, :create)
|
97
|
+
|
98
|
+
# Return the current or specified HSSFSheet
|
99
|
+
def sheet(i = nil)
|
100
|
+
@current_sheet = i if i
|
101
|
+
@sheet = @book.getSheetAt(@current_sheet)
|
102
|
+
end
|
103
|
+
|
104
|
+
def activate_sheet(sheet)
|
105
|
+
active_sheet = @current_sheet
|
106
|
+
if(@book)
|
107
|
+
i = sheet if sheet.kind_of?(Integer)
|
108
|
+
i = @book.getSheetIndex(sheet) if sheet.kind_of?(String)
|
109
|
+
|
110
|
+
if( i >= 0 )
|
111
|
+
@book.setActiveSheet(i) unless @book.nil?
|
112
|
+
active_sheet = @book.getSheetAt(i)
|
113
|
+
active_sheet.setActive(true)
|
114
|
+
end unless i.nil?
|
115
|
+
end
|
116
|
+
return active_sheet
|
117
|
+
end
|
118
|
+
|
119
|
+
def num_rows
|
120
|
+
@sheet.getPhysicalNumberOfRows
|
121
|
+
end
|
122
|
+
|
123
|
+
# Process each row. (type is org.apache.poi.hssf.usermodel.HSSFRow)
|
124
|
+
|
125
|
+
def each_row
|
126
|
+
@sheet.rowIterator.each { |row| yield row }
|
127
|
+
end
|
128
|
+
|
129
|
+
# Create new row, bring index in line with POI usage (our 1 is their 0)
|
130
|
+
def create_row(index)
|
131
|
+
return if @sheet.nil?
|
132
|
+
raise "BAD INDEX: Row indexing starts at 1" if(index == 0)
|
133
|
+
@row = @sheet.createRow(index - 1)
|
134
|
+
@row
|
135
|
+
end
|
136
|
+
|
137
|
+
#############################
|
138
|
+
# INSERTING DATA INTO EXCEL #
|
139
|
+
#############################
|
140
|
+
|
141
|
+
# Populate a single cell with data
|
142
|
+
#
|
143
|
+
def set_cell(row, column, datum)
|
144
|
+
@row = @sheet.getRow(row - 1) || create_row(row)
|
145
|
+
@row.createCell(column - 1, excel_cell_type(datum)).setCellValue(datum)
|
146
|
+
end
|
147
|
+
|
148
|
+
# Convert array into a header row
|
149
|
+
def set_headers(headers)
|
150
|
+
create_row(1)
|
151
|
+
return if headers.empty?
|
152
|
+
|
153
|
+
set_row(1, 1, headers)
|
154
|
+
end
|
155
|
+
|
156
|
+
# Populate a row of cells with data in an array
|
157
|
+
# where the co-ordinates relate to row/column start position
|
158
|
+
#
|
159
|
+
def set_row( row, col, data, sheet_num = nil)
|
160
|
+
|
161
|
+
sheet(sheet_num)
|
162
|
+
|
163
|
+
create_row(row)
|
164
|
+
|
165
|
+
column = col
|
166
|
+
data.each do |datum|
|
167
|
+
set_cell(row, column, datum)
|
168
|
+
column += 1
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
# Return a mapping from Ruby type to type for HSSFCell
|
173
|
+
def excel_cell_type(data)
|
174
|
+
|
175
|
+
if(data.kind_of?(Numeric))
|
176
|
+
HSSFCell::CELL_TYPE_NUMERIC
|
177
|
+
elsif(data.nil?)
|
178
|
+
HSSFCell::CELL_TYPE_BLANK
|
179
|
+
elsif(data.is_a?(TrueClass) || data.is_a?(FalseClass))
|
180
|
+
HSSFCell::CELL_TYPE_BOOLEAN
|
181
|
+
else
|
182
|
+
HSSFCell::CELL_TYPE_STRING
|
183
|
+
end
|
184
|
+
# HSSFCell::CELL_TYPE_FORMULA
|
185
|
+
end
|
186
|
+
|
187
|
+
# TODO - Move into an ActiveRecord helper module of it's own
|
188
|
+
def ar_to_headers( records )
|
189
|
+
return if( !records.first.is_a?(ActiveRecord::Base) || records.empty?)
|
190
|
+
|
191
|
+
headers = records.first.class.columns.collect( &:name )
|
192
|
+
set_headers( headers )
|
193
|
+
end
|
194
|
+
|
195
|
+
# Pass a set of AR records
|
196
|
+
def ar_to_xls(records, options = {})
|
197
|
+
return if( ! records.first.is_a?(ActiveRecord::Base) || records.empty?)
|
198
|
+
|
199
|
+
row_index =
|
200
|
+
if(options[:no_headers])
|
201
|
+
1
|
202
|
+
else
|
203
|
+
ar_to_headers( records )
|
204
|
+
2
|
205
|
+
end
|
206
|
+
|
207
|
+
records.each do |record|
|
208
|
+
create_row(row_index)
|
209
|
+
|
210
|
+
ar_to_xls_row(1, record)
|
211
|
+
|
212
|
+
row_index += 1
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
# Save data from an AR record to the current row, based on the record's columns [c1,c2,c3]
|
217
|
+
# Returns the number of the final column written to
|
218
|
+
def ar_to_xls_row(start_column, record)
|
219
|
+
return unless( record.is_a?(ActiveRecord::Base))
|
220
|
+
|
221
|
+
column = start_column
|
222
|
+
record.class.columns.each do |connection_column|
|
223
|
+
ar_to_xls_cell(column, record, connection_column)
|
224
|
+
column += 1
|
225
|
+
end
|
226
|
+
column
|
227
|
+
end
|
228
|
+
|
229
|
+
def ar_to_xls_cell(column, record, connection_column)
|
230
|
+
begin
|
231
|
+
datum = record.send(connection_column.name)
|
232
|
+
|
233
|
+
if(connection_column.sql_type =~ /date/)
|
234
|
+
@row.createCell(column - 1, HSSFCell::CELL_TYPE_STRING).setCellValue(datum.to_s)
|
235
|
+
|
236
|
+
elsif(connection_column.type == :boolean || connection_column.sql_type =~ /tinyint/)
|
237
|
+
@row.createCell(column - 1, HSSFCell::CELL_TYPE_BOOLEAN).setCellValue(datum)
|
238
|
+
|
239
|
+
elsif(connection_column.sql_type =~ /int/)
|
240
|
+
@row.createCell(column - 1, HSSFCell::CELL_TYPE_NUMERIC).setCellValue(datum.to_i)
|
241
|
+
else
|
242
|
+
@row.createCell(column - 1, HSSFCell::CELL_TYPE_STRING).setCellValue( datum.to_s )
|
243
|
+
end
|
244
|
+
|
245
|
+
rescue => e
|
246
|
+
puts "Failed to export #{datum} from #{connection_column.inspect} to column #{column}"
|
247
|
+
puts e
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
##############################
|
252
|
+
# RETRIEVING DATA FROM EXCEL #
|
253
|
+
##############################
|
254
|
+
|
255
|
+
# Return the raw data of the requested cell by row/column
|
256
|
+
def get_cell_value(row, column)
|
257
|
+
raise TypeError, "Expect row argument of type HSSFRow" unless row.is_a?(Java::OrgApachePoiHssfUsermodel::HSSFRow)
|
258
|
+
cell_value( row.getCell(column) )
|
259
|
+
end
|
260
|
+
|
261
|
+
# Return the raw data of an HSSFCell
|
262
|
+
def cell_value(cell)
|
263
|
+
return unless cell
|
264
|
+
#puts "DEBUG CELL TYPE : #{cell} => #{cell.getCellType().inspect}"
|
265
|
+
case (cell.getCellType())
|
266
|
+
when HSSFCell::CELL_TYPE_FORMULA then return cell.getCellFormula()
|
267
|
+
when HSSFCell::CELL_TYPE_NUMERIC then return cell.getNumericCellValue()
|
268
|
+
when HSSFCell::CELL_TYPE_STRING then return cell.getStringCellValue()
|
269
|
+
when HSSFCell::CELL_TYPE_BOOLEAN then return cell.getBooleanCellValue()
|
270
|
+
when HSSFCell::CELL_TYPE_BLANK then return ""
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
def save( filename = nil )
|
275
|
+
filename.nil? ? file = @filepath : file = filename
|
276
|
+
out = FileOutputStream.new(file)
|
277
|
+
@book.write(out) unless @book.nil?
|
278
|
+
out.close
|
279
|
+
end
|
280
|
+
|
281
|
+
def save_to_text( filename )
|
282
|
+
File.open( filename, 'w') {|f| f.write(to_s) }
|
283
|
+
end
|
284
|
+
|
285
|
+
|
286
|
+
def add_comment( cell, text )
|
287
|
+
raise "Please supply valid HSSFCell" unless cell.respond_to?('setCellComment')
|
288
|
+
return if @sheet.nil?
|
289
|
+
|
290
|
+
patriarch = @patriarchs[@sheet.getSheetName()]
|
291
|
+
|
292
|
+
anchor = HSSFClientAnchor.new(100, 50, 100, 50, cell.getColumnIndex(), cell.getRowIndex(), cell.getColumnIndex()+3, cell.getRowIndex()+4)
|
293
|
+
comment = patriarch.createCellComment(anchor)
|
294
|
+
|
295
|
+
comment_text = HSSFRichTextString.new(text)
|
296
|
+
comment.setString(comment_text)
|
297
|
+
comment.setAuthor("Mapping")
|
298
|
+
|
299
|
+
cell.setCellComment(comment)
|
300
|
+
end
|
301
|
+
|
302
|
+
# The internal representation of a Excel File
|
303
|
+
|
304
|
+
# Get a percentage style
|
305
|
+
def getPercentStyle()
|
306
|
+
if (@percentCellStyle.nil? && @book)
|
307
|
+
@percentCellStyle = @book.createCellStyle();
|
308
|
+
@percentCellStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat("0.00%"));
|
309
|
+
end
|
310
|
+
return @percentCellStyle
|
311
|
+
end
|
312
|
+
|
313
|
+
# Auto size either the given column index or all columns
|
314
|
+
def autosize(column = nil)
|
315
|
+
return if @sheet.nil?
|
316
|
+
if (column.kind_of? Integer)
|
317
|
+
@sheet.autoSizeColumn(column)
|
318
|
+
else
|
319
|
+
@sheet.getRow(0).cellIterator.each{|c| @sheet.autoSizeColumn(c.getColumnIndex)}
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
def to_s
|
324
|
+
return "" unless @book
|
325
|
+
|
326
|
+
outs = ByteArrayOutputStream.new
|
327
|
+
@book.write(outs);
|
328
|
+
outs.close();
|
329
|
+
String.from_java_bytes(outs.toByteArray)
|
330
|
+
end
|
331
|
+
|
332
|
+
def createFreezePane(row=1, column=0)
|
333
|
+
return if @sheet.nil?
|
334
|
+
@sheet.createFreezePane(row, column)
|
335
|
+
end
|
336
|
+
|
337
|
+
# Use execute to run sql query provided
|
338
|
+
# and write to a csv file (path required)
|
339
|
+
# header row is optional but default is on
|
340
|
+
# Auto mapping of specified columns is optional
|
341
|
+
# @mappings is a hash{column => map} of columns to a map{old_value => new_value}
|
342
|
+
def results_to_sheet( results, sheet, mappings=nil, header=true)
|
343
|
+
numrows = results.length
|
344
|
+
sheet_name = sheet
|
345
|
+
|
346
|
+
if (numrows == 0)
|
347
|
+
log :info, "WARNING - results are empty nothing written to sheet: #{sheet}"
|
348
|
+
return
|
349
|
+
end
|
350
|
+
|
351
|
+
#Check if we need to split the results into seperate sheets
|
352
|
+
if (numrows > @@maxrows )
|
353
|
+
startrow = 0
|
354
|
+
while (numrows > 0)
|
355
|
+
# Split the results and write to a new sheet
|
356
|
+
next_results = results.slice(startrow, @@maxrows > numrows ? numrows : @@maxrows)
|
357
|
+
self.results_to_sheet(next_results, "#{sheet_name}", mappings, header) if next_results
|
358
|
+
|
359
|
+
# Increase counters
|
360
|
+
numrows -= next_results.length
|
361
|
+
startrow += next_results.length
|
362
|
+
sheet_name += 'I'
|
363
|
+
end
|
364
|
+
else
|
365
|
+
# Create required sheet
|
366
|
+
self.create(sheet)
|
367
|
+
|
368
|
+
row_index = self.num_rows
|
369
|
+
# write header line
|
370
|
+
if (header && row_index==0 )
|
371
|
+
header_row = @sheet.createRow(row_index)
|
372
|
+
cell_index = 0
|
373
|
+
results[0].keys.each{ |h|
|
374
|
+
header_row.createCell(cell_index).setCellValue("#{h}")
|
375
|
+
@sheet.setDefaultColumnStyle(cell_index, self.getPercentStyle) if "#{h}".include? '%'
|
376
|
+
cell_index += 1
|
377
|
+
}
|
378
|
+
# Freeze the header row
|
379
|
+
@sheet.createFreezePane( 0, 1, 0, 1 )
|
380
|
+
row_index += 1
|
381
|
+
end
|
382
|
+
|
383
|
+
# write_results
|
384
|
+
results.each{ |row|
|
385
|
+
sheet_row = @sheet.createRow(row_index)
|
386
|
+
cell_index = 0
|
387
|
+
row.each{|k,v|
|
388
|
+
celltype = v.kind_of?(Numeric) ? HSSFCell::CELL_TYPE_NUMERIC : HSSFCell::CELL_TYPE_STRING
|
389
|
+
cell = sheet_row.createCell(cell_index, celltype)
|
390
|
+
|
391
|
+
v.nil? ? value = "<NIL>" : value = v
|
392
|
+
|
393
|
+
cell.setCellValue(value)
|
394
|
+
|
395
|
+
cell_index +=1
|
396
|
+
}
|
397
|
+
#puts "#{sheet}: written row #{row_index}"
|
398
|
+
row_index +=1
|
399
|
+
}
|
400
|
+
end
|
401
|
+
|
402
|
+
end
|
403
|
+
|
404
|
+
end # END JExcelFile
|
405
|
+
else
|
406
|
+
class JExcelFile
|
407
|
+
def initialize
|
408
|
+
raise DataShift::BadRuby, "Please install and use JRuby for working with .xls files"
|
409
|
+
end
|
410
|
+
end
|
409
411
|
end
|