roo 2.0.1 → 2.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.
- checksums.yaml +4 -4
- data/.codeclimate.yml +17 -0
- data/.github/ISSUE_TEMPLATE +10 -0
- data/.gitignore +4 -0
- data/.travis.yml +10 -6
- data/CHANGELOG.md +116 -1
- data/Gemfile +3 -4
- data/Gemfile_ruby2 +30 -0
- data/Guardfile +1 -2
- data/README.md +56 -22
- data/Rakefile +1 -1
- data/lib/roo/base.rb +108 -245
- data/lib/roo/constants.rb +5 -0
- data/lib/roo/csv.rb +94 -87
- data/lib/roo/errors.rb +11 -0
- data/lib/roo/excelx/cell/base.rb +94 -0
- data/lib/roo/excelx/cell/boolean.rb +27 -0
- data/lib/roo/excelx/cell/date.rb +28 -0
- data/lib/roo/excelx/cell/datetime.rb +111 -0
- data/lib/roo/excelx/cell/empty.rb +19 -0
- data/lib/roo/excelx/cell/number.rb +87 -0
- data/lib/roo/excelx/cell/string.rb +19 -0
- data/lib/roo/excelx/cell/time.rb +43 -0
- data/lib/roo/excelx/cell.rb +33 -4
- data/lib/roo/excelx/comments.rb +33 -0
- data/lib/roo/excelx/coordinate.rb +12 -0
- data/lib/roo/excelx/extractor.rb +3 -4
- data/lib/roo/excelx/format.rb +64 -0
- data/lib/roo/excelx/shared.rb +32 -0
- data/lib/roo/excelx/shared_strings.rb +124 -4
- data/lib/roo/excelx/sheet.rb +12 -7
- data/lib/roo/excelx/sheet_doc.rb +108 -97
- data/lib/roo/excelx/styles.rb +1 -1
- data/lib/roo/excelx.rb +61 -103
- data/lib/roo/formatters/base.rb +15 -0
- data/lib/roo/formatters/csv.rb +84 -0
- data/lib/roo/formatters/matrix.rb +23 -0
- data/lib/roo/formatters/xml.rb +31 -0
- data/lib/roo/formatters/yaml.rb +40 -0
- data/lib/roo/libre_office.rb +1 -2
- data/lib/roo/link.rb +21 -2
- data/lib/roo/open_office.rb +468 -523
- data/lib/roo/spreadsheet.rb +3 -1
- data/lib/roo/tempdir.rb +21 -0
- data/lib/roo/utils.rb +7 -7
- data/lib/roo/version.rb +1 -1
- data/lib/roo.rb +8 -3
- data/roo.gemspec +2 -1
- data/spec/helpers.rb +5 -0
- data/spec/lib/roo/base_spec.rb +229 -0
- data/spec/lib/roo/csv_spec.rb +19 -0
- data/spec/lib/roo/excelx_spec.rb +97 -11
- data/spec/lib/roo/openoffice_spec.rb +18 -1
- data/spec/lib/roo/spreadsheet_spec.rb +20 -0
- data/spec/lib/roo/utils_spec.rb +1 -1
- data/spec/spec_helper.rb +5 -5
- data/test/all_ss.rb +12 -11
- data/test/excelx/cell/test_base.rb +63 -0
- data/test/excelx/cell/test_boolean.rb +36 -0
- data/test/excelx/cell/test_date.rb +38 -0
- data/test/excelx/cell/test_datetime.rb +45 -0
- data/test/excelx/cell/test_empty.rb +7 -0
- data/test/excelx/cell/test_number.rb +74 -0
- data/test/excelx/cell/test_string.rb +28 -0
- data/test/excelx/cell/test_time.rb +30 -0
- data/test/formatters/test_csv.rb +119 -0
- data/test/formatters/test_matrix.rb +76 -0
- data/test/formatters/test_xml.rb +78 -0
- data/test/formatters/test_yaml.rb +20 -0
- data/test/helpers/test_accessing_files.rb +60 -0
- data/test/helpers/test_comments.rb +43 -0
- data/test/helpers/test_formulas.rb +9 -0
- data/test/helpers/test_labels.rb +103 -0
- data/test/helpers/test_sheets.rb +55 -0
- data/test/helpers/test_styles.rb +62 -0
- data/test/roo/test_base.rb +182 -0
- data/test/roo/test_csv.rb +60 -0
- data/test/roo/test_excelx.rb +325 -0
- data/test/roo/test_libre_office.rb +9 -0
- data/test/roo/test_open_office.rb +289 -0
- data/test/test_helper.rb +116 -18
- data/test/test_roo.rb +362 -2088
- metadata +70 -4
- data/test/test_generic_spreadsheet.rb +0 -237
data/lib/roo/base.rb
CHANGED
@@ -4,12 +4,21 @@ require 'tmpdir'
|
|
4
4
|
require 'stringio'
|
5
5
|
require 'nokogiri'
|
6
6
|
require 'roo/utils'
|
7
|
+
require "roo/formatters/base"
|
8
|
+
require "roo/formatters/csv"
|
9
|
+
require "roo/formatters/matrix"
|
10
|
+
require "roo/formatters/xml"
|
11
|
+
require "roo/formatters/yaml"
|
7
12
|
|
8
13
|
# Base class for all other types of spreadsheets
|
9
14
|
class Roo::Base
|
10
15
|
include Enumerable
|
16
|
+
include Roo::Formatters::Base
|
17
|
+
include Roo::Formatters::CSV
|
18
|
+
include Roo::Formatters::Matrix
|
19
|
+
include Roo::Formatters::XML
|
20
|
+
include Roo::Formatters::YAML
|
11
21
|
|
12
|
-
TEMP_PREFIX = 'roo_'.freeze
|
13
22
|
MAX_ROW_COL = 999_999.freeze
|
14
23
|
MIN_ROW_COL = 0.freeze
|
15
24
|
|
@@ -18,6 +27,15 @@ class Roo::Base
|
|
18
27
|
# sets the line with attribute names (default: 1)
|
19
28
|
attr_accessor :header_line
|
20
29
|
|
30
|
+
def self.TEMP_PREFIX
|
31
|
+
warn '[DEPRECATION] please access TEMP_PREFIX via Roo::TEMP_PREFIX'
|
32
|
+
Roo::TEMP_PREFIX
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.finalize(object_id)
|
36
|
+
proc { finalize_tempdirs(object_id) }
|
37
|
+
end
|
38
|
+
|
21
39
|
def initialize(filename, options = {}, _file_warning = :error, _tmpdir = nil)
|
22
40
|
@filename = filename
|
23
41
|
@options = options
|
@@ -32,14 +50,12 @@ class Roo::Base
|
|
32
50
|
@last_column = {}
|
33
51
|
|
34
52
|
@header_line = 1
|
35
|
-
rescue => e # clean up any temp files, but only if an error was raised
|
36
|
-
close
|
37
|
-
raise e
|
38
53
|
end
|
39
54
|
|
40
55
|
def close
|
41
|
-
|
42
|
-
|
56
|
+
if self.class.respond_to?(:finalize_tempdirs)
|
57
|
+
self.class.finalize_tempdirs(object_id)
|
58
|
+
end
|
43
59
|
nil
|
44
60
|
end
|
45
61
|
|
@@ -91,7 +107,7 @@ class Roo::Base
|
|
91
107
|
first_column = [first_column, key.last.to_i].min
|
92
108
|
last_column = [last_column, key.last.to_i].max
|
93
109
|
end if @cell[sheet]
|
94
|
-
{first_row: first_row, first_column: first_column, last_row: last_row, last_column: last_column}
|
110
|
+
{ first_row: first_row, first_column: first_column, last_row: last_row, last_column: last_column }
|
95
111
|
end
|
96
112
|
|
97
113
|
%w(first_row last_row first_column last_column).each do |key|
|
@@ -103,74 +119,8 @@ class Roo::Base
|
|
103
119
|
EOS
|
104
120
|
end
|
105
121
|
|
106
|
-
# returns a rectangular area (default: all cells) as yaml-output
|
107
|
-
# you can add additional attributes with the prefix parameter like:
|
108
|
-
# oo.to_yaml({"file"=>"flightdata_2007-06-26", "sheet" => "1"})
|
109
|
-
def to_yaml(prefix = {}, from_row = nil, from_column = nil, to_row = nil, to_column = nil, sheet = default_sheet)
|
110
|
-
return '' unless first_row # empty result if there is no first_row in a sheet
|
111
|
-
|
112
|
-
from_row ||= first_row(sheet)
|
113
|
-
to_row ||= last_row(sheet)
|
114
|
-
from_column ||= first_column(sheet)
|
115
|
-
to_column ||= last_column(sheet)
|
116
|
-
|
117
|
-
result = "--- \n"
|
118
|
-
from_row.upto(to_row) do |row|
|
119
|
-
from_column.upto(to_column) do |col|
|
120
|
-
unless empty?(row, col, sheet)
|
121
|
-
result << "cell_#{row}_#{col}: \n"
|
122
|
-
prefix.each do|k, v|
|
123
|
-
result << " #{k}: #{v} \n"
|
124
|
-
end
|
125
|
-
result << " row: #{row} \n"
|
126
|
-
result << " col: #{col} \n"
|
127
|
-
result << " celltype: #{celltype(row, col, sheet)} \n"
|
128
|
-
value = cell(row, col, sheet)
|
129
|
-
if celltype(row, col, sheet) == :time
|
130
|
-
value = integer_to_timestring(value)
|
131
|
-
end
|
132
|
-
result << " value: #{value} \n"
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
result
|
137
|
-
end
|
138
|
-
|
139
|
-
# write the current spreadsheet to stdout or into a file
|
140
|
-
def to_csv(filename = nil, separator = ',', sheet = default_sheet)
|
141
|
-
if filename
|
142
|
-
File.open(filename, 'w') do |file|
|
143
|
-
write_csv_content(file, sheet, separator)
|
144
|
-
end
|
145
|
-
true
|
146
|
-
else
|
147
|
-
sio = ::StringIO.new
|
148
|
-
write_csv_content(sio, sheet, separator)
|
149
|
-
sio.rewind
|
150
|
-
sio.read
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
# returns a matrix object from the whole sheet or a rectangular area of a sheet
|
155
|
-
def to_matrix(from_row = nil, from_column = nil, to_row = nil, to_column = nil, sheet = default_sheet)
|
156
|
-
require 'matrix'
|
157
|
-
|
158
|
-
return Matrix.empty unless first_row
|
159
|
-
|
160
|
-
from_row ||= first_row(sheet)
|
161
|
-
to_row ||= last_row(sheet)
|
162
|
-
from_column ||= first_column(sheet)
|
163
|
-
to_column ||= last_column(sheet)
|
164
|
-
|
165
|
-
Matrix.rows(from_row.upto(to_row).map do |row|
|
166
|
-
from_column.upto(to_column).map do |col|
|
167
|
-
cell(row, col, sheet)
|
168
|
-
end
|
169
|
-
end)
|
170
|
-
end
|
171
|
-
|
172
122
|
def inspect
|
173
|
-
"<##{
|
123
|
+
"<##{self.class}:#{object_id.to_s(8)} #{instance_variables.join(' ')}>"
|
174
124
|
end
|
175
125
|
|
176
126
|
# find a row either by row number or a condition
|
@@ -180,7 +130,7 @@ class Roo::Base
|
|
180
130
|
options = (args.last.is_a?(Hash) ? args.pop : {})
|
181
131
|
|
182
132
|
case args[0]
|
183
|
-
when
|
133
|
+
when Integer
|
184
134
|
find_by_row(args[0])
|
185
135
|
when :all
|
186
136
|
find_by_conditions(options)
|
@@ -217,15 +167,15 @@ class Roo::Base
|
|
217
167
|
row, col = normalize(row, col)
|
218
168
|
cell_type = cell_type_by_value(value)
|
219
169
|
set_value(row, col, value, sheet)
|
220
|
-
set_type(row, col, cell_type
|
170
|
+
set_type(row, col, cell_type, sheet)
|
221
171
|
end
|
222
172
|
|
223
173
|
def cell_type_by_value(value)
|
224
174
|
case value
|
225
|
-
when
|
175
|
+
when Integer then :float
|
226
176
|
when String, Float then :string
|
227
177
|
else
|
228
|
-
|
178
|
+
fail ArgumentError, "Type for #{value} not set"
|
229
179
|
end
|
230
180
|
end
|
231
181
|
|
@@ -256,13 +206,13 @@ class Roo::Base
|
|
256
206
|
sheets.each do|sheet|
|
257
207
|
self.default_sheet = sheet
|
258
208
|
result << 'Sheet ' + n.to_s + ":\n"
|
259
|
-
|
260
|
-
result << ' - empty -'
|
261
|
-
else
|
209
|
+
if first_row
|
262
210
|
result << " First row: #{first_row}\n"
|
263
211
|
result << " Last row: #{last_row}\n"
|
264
212
|
result << " First column: #{::Roo::Utils.number_to_letter(first_column)}\n"
|
265
213
|
result << " Last column: #{::Roo::Utils.number_to_letter(last_column)}"
|
214
|
+
else
|
215
|
+
result << ' - empty -'
|
266
216
|
end
|
267
217
|
result << "\n" if sheet != sheets.last
|
268
218
|
n += 1
|
@@ -271,38 +221,12 @@ class Roo::Base
|
|
271
221
|
end
|
272
222
|
end
|
273
223
|
|
274
|
-
# returns an XML representation of all sheets of a spreadsheet file
|
275
|
-
def to_xml
|
276
|
-
Nokogiri::XML::Builder.new do |xml|
|
277
|
-
xml.spreadsheet do
|
278
|
-
sheets.each do |sheet|
|
279
|
-
self.default_sheet = sheet
|
280
|
-
xml.sheet(name: sheet) do |x|
|
281
|
-
if first_row && last_row && first_column && last_column
|
282
|
-
# sonst gibt es Fehler bei leeren Blaettern
|
283
|
-
first_row.upto(last_row) do |row|
|
284
|
-
first_column.upto(last_column) do |col|
|
285
|
-
unless empty?(row, col)
|
286
|
-
x.cell(cell(row, col),
|
287
|
-
row: row,
|
288
|
-
column: col,
|
289
|
-
type: celltype(row, col))
|
290
|
-
end
|
291
|
-
end
|
292
|
-
end
|
293
|
-
end
|
294
|
-
end
|
295
|
-
end
|
296
|
-
end
|
297
|
-
end.to_xml
|
298
|
-
end
|
299
|
-
|
300
224
|
# when a method like spreadsheet.a42 is called
|
301
225
|
# convert it to a call of spreadsheet.cell('a',42)
|
302
226
|
def method_missing(m, *args)
|
303
227
|
# #aa42 => #cell('aa',42)
|
304
228
|
# #aa42('Sheet1') => #cell('aa',42,'Sheet1')
|
305
|
-
if m =~ /^([a-z]+)(\d)$/
|
229
|
+
if m =~ /^([a-z]+)(\d+)$/
|
306
230
|
col = ::Roo::Utils.letter_to_number(Regexp.last_match[1])
|
307
231
|
row = Regexp.last_match[2].to_i
|
308
232
|
if args.empty?
|
@@ -318,7 +242,7 @@ class Roo::Base
|
|
318
242
|
# access different worksheets by calling spreadsheet.sheet(1)
|
319
243
|
# or spreadsheet.sheet('SHEETNAME')
|
320
244
|
def sheet(index, name = false)
|
321
|
-
self.default_sheet = String
|
245
|
+
self.default_sheet = index.is_a?(::String) ? index : sheets[index]
|
322
246
|
name ? [default_sheet, self] : self
|
323
247
|
end
|
324
248
|
|
@@ -352,35 +276,32 @@ class Roo::Base
|
|
352
276
|
# control characters and white spaces around columns
|
353
277
|
|
354
278
|
def each(options = {})
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
else
|
361
|
-
clean_sheet_if_need(options)
|
362
|
-
search_or_set_header(options)
|
363
|
-
headers = @headers ||
|
364
|
-
Hash[(first_column..last_column).map do |col|
|
365
|
-
[cell(@header_line, col), col]
|
366
|
-
end]
|
367
|
-
|
368
|
-
@header_line.upto(last_row) do |line|
|
369
|
-
yield(Hash[headers.map { |k, v| [k, cell(line, v)] }])
|
370
|
-
end
|
279
|
+
return to_enum(:each, options) unless block_given?
|
280
|
+
|
281
|
+
if options.empty?
|
282
|
+
1.upto(last_row) do |line|
|
283
|
+
yield row(line)
|
371
284
|
end
|
372
285
|
else
|
373
|
-
|
286
|
+
clean_sheet_if_need(options)
|
287
|
+
search_or_set_header(options)
|
288
|
+
headers = @headers ||
|
289
|
+
Hash[(first_column..last_column).map do |col|
|
290
|
+
[cell(@header_line, col), col]
|
291
|
+
end]
|
292
|
+
|
293
|
+
@header_line.upto(last_row) do |line|
|
294
|
+
yield(Hash[headers.map { |k, v| [k, cell(line, v)] }])
|
295
|
+
end
|
374
296
|
end
|
375
297
|
end
|
376
298
|
|
377
299
|
def parse(options = {})
|
378
|
-
|
379
|
-
|
380
|
-
yield(row) if block_given?
|
381
|
-
ary << row
|
300
|
+
results = each(options).map do |row|
|
301
|
+
block_given? ? yield(row) : row
|
382
302
|
end
|
383
|
-
|
303
|
+
|
304
|
+
options[:headers] == true ? results : results.drop(1)
|
384
305
|
end
|
385
306
|
|
386
307
|
def row_with(query, return_headers = false)
|
@@ -393,38 +314,40 @@ class Roo::Base
|
|
393
314
|
@header_line = line_no
|
394
315
|
return return_headers ? headers : line_no
|
395
316
|
elsif line_no > 100
|
396
|
-
|
317
|
+
raise Roo::HeaderRowNotFoundError
|
397
318
|
end
|
398
319
|
end
|
399
|
-
|
320
|
+
raise Roo::HeaderRowNotFoundError
|
400
321
|
end
|
401
322
|
|
402
323
|
protected
|
403
324
|
|
404
|
-
def file_type_check(filename,
|
325
|
+
def file_type_check(filename, exts, name, warning_level, packed = nil)
|
405
326
|
if packed == :zip
|
406
|
-
#
|
407
|
-
#
|
408
|
-
#
|
327
|
+
# spreadsheet.ods.zip => spreadsheet.ods
|
328
|
+
# Decompression is not performed here, only the 'zip' extension
|
329
|
+
# is removed from the file.
|
409
330
|
filename = File.basename(filename, File.extname(filename))
|
410
331
|
end
|
411
332
|
|
412
|
-
if uri?(filename) && qs_begin = filename.rindex('?')
|
333
|
+
if uri?(filename) && (qs_begin = filename.rindex('?'))
|
413
334
|
filename = filename[0..qs_begin - 1]
|
414
335
|
end
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
336
|
+
exts = Array(exts)
|
337
|
+
|
338
|
+
return if exts.include?(File.extname(filename).downcase)
|
339
|
+
|
340
|
+
case warning_level
|
341
|
+
when :error
|
342
|
+
warn file_type_warning_message(filename, exts)
|
343
|
+
fail TypeError, "#{filename} is not #{name} file"
|
344
|
+
when :warning
|
345
|
+
warn "are you sure, this is #{name} spreadsheet file?"
|
346
|
+
warn file_type_warning_message(filename, exts)
|
347
|
+
when :ignore
|
348
|
+
# ignore
|
349
|
+
else
|
350
|
+
fail "#{warning_level} illegal state of file_warning"
|
428
351
|
end
|
429
352
|
end
|
430
353
|
|
@@ -448,10 +371,6 @@ class Roo::Base
|
|
448
371
|
|
449
372
|
private
|
450
373
|
|
451
|
-
def track_tmpdir!(tmpdir)
|
452
|
-
(@tmpdirs ||= []) << tmpdir
|
453
|
-
end
|
454
|
-
|
455
374
|
def clean_sheet_if_need(options)
|
456
375
|
return unless options[:clean]
|
457
376
|
options.delete(:clean)
|
@@ -475,16 +394,18 @@ class Roo::Base
|
|
475
394
|
return if is_stream?(filename)
|
476
395
|
filename = download_uri(filename, tmpdir) if uri?(filename)
|
477
396
|
filename = unzip(filename, tmpdir) if packed == :zip
|
478
|
-
|
479
|
-
|
480
|
-
|
397
|
+
|
398
|
+
fail IOError, "file #{filename} does not exist" unless File.file?(filename)
|
399
|
+
|
481
400
|
filename
|
482
401
|
end
|
483
402
|
|
484
|
-
def file_type_warning_message(filename,
|
485
|
-
|
403
|
+
def file_type_warning_message(filename, exts)
|
404
|
+
*rest, last_ext = exts
|
405
|
+
ext_list = rest.any? ? "#{rest.join(', ')} or #{last_ext}" : last_ext
|
406
|
+
"use #{Roo::CLASS_FOR_EXTENSION.fetch(last_ext.sub('.', '').to_sym)}.new to handle #{ext_list} spreadsheet files. This has #{File.extname(filename).downcase}"
|
486
407
|
rescue KeyError
|
487
|
-
raise "unknown file
|
408
|
+
raise "unknown file types: #{ext_list}"
|
488
409
|
end
|
489
410
|
|
490
411
|
def find_by_row(row_index)
|
@@ -532,14 +453,26 @@ class Roo::Base
|
|
532
453
|
initialize(@filename)
|
533
454
|
end
|
534
455
|
|
456
|
+
def find_basename(filename)
|
457
|
+
if uri?(filename)
|
458
|
+
require 'uri'
|
459
|
+
uri = URI.parse filename
|
460
|
+
File.basename(uri.path)
|
461
|
+
elsif !is_stream?(filename)
|
462
|
+
File.basename(filename)
|
463
|
+
end
|
464
|
+
end
|
465
|
+
|
535
466
|
def make_tmpdir(prefix = nil, root = nil, &block)
|
536
|
-
|
537
|
-
|
467
|
+
warn '[DEPRECATION] extend Roo::Tempdir and use its .make_tempdir instead'
|
468
|
+
prefix = "#{Roo::TEMP_PREFIX}#{prefix}"
|
469
|
+
root ||= ENV['ROO_TMP']
|
470
|
+
|
471
|
+
if block_given?
|
472
|
+
# folder is deleted at end of block
|
473
|
+
::Dir.mktmpdir(prefix, root, &block)
|
538
474
|
else
|
539
|
-
|
540
|
-
end
|
541
|
-
::Dir.mktmpdir(prefix, root || ENV['ROO_TMP'], &block).tap do |result|
|
542
|
-
block_given? || track_tmpdir!(result)
|
475
|
+
self.class.make_tempdir(self, prefix, root)
|
543
476
|
end
|
544
477
|
end
|
545
478
|
|
@@ -577,7 +510,7 @@ class Roo::Base
|
|
577
510
|
# converts cell coordinate to numeric values of row,col
|
578
511
|
def normalize(row, col)
|
579
512
|
if row.is_a?(::String)
|
580
|
-
if col.is_a?(::
|
513
|
+
if col.is_a?(::Integer)
|
581
514
|
# ('A',1):
|
582
515
|
# ('B', 5) -> (5, 2)
|
583
516
|
row, col = col, row
|
@@ -585,21 +518,21 @@ class Roo::Base
|
|
585
518
|
fail ArgumentError
|
586
519
|
end
|
587
520
|
end
|
588
|
-
|
589
|
-
|
590
|
-
|
521
|
+
|
522
|
+
col = ::Roo::Utils.letter_to_number(col) if col.is_a?(::String)
|
523
|
+
|
591
524
|
[row, col]
|
592
525
|
end
|
593
526
|
|
594
527
|
def uri?(filename)
|
595
|
-
filename.start_with?('http://', 'https://')
|
528
|
+
filename.start_with?('http://', 'https://', 'ftp://')
|
596
529
|
rescue
|
597
530
|
false
|
598
531
|
end
|
599
532
|
|
600
533
|
def download_uri(uri, tmpdir)
|
601
534
|
require 'open-uri'
|
602
|
-
tempfilename = File.join(tmpdir,
|
535
|
+
tempfilename = File.join(tmpdir, find_basename(uri))
|
603
536
|
begin
|
604
537
|
File.open(tempfilename, 'wb') do |file|
|
605
538
|
open(uri, 'User-Agent' => "Ruby/#{RUBY_VERSION}") do |net|
|
@@ -633,12 +566,12 @@ class Roo::Base
|
|
633
566
|
case sheet
|
634
567
|
when nil
|
635
568
|
fail ArgumentError, "Error: sheet 'nil' not valid"
|
636
|
-
when
|
569
|
+
when Integer
|
637
570
|
sheets.fetch(sheet - 1) do
|
638
571
|
fail RangeError, "sheet index #{sheet} not found"
|
639
572
|
end
|
640
573
|
when String
|
641
|
-
unless sheets.include?
|
574
|
+
unless sheets.include?(sheet)
|
642
575
|
fail RangeError, "sheet '#{sheet}' not found"
|
643
576
|
end
|
644
577
|
else
|
@@ -662,74 +595,4 @@ class Roo::Base
|
|
662
595
|
ret
|
663
596
|
end
|
664
597
|
end
|
665
|
-
|
666
|
-
# Write all cells to the csv file. File can be a filename or nil. If the this
|
667
|
-
# parameter is nil the output goes to STDOUT
|
668
|
-
def write_csv_content(file = nil, sheet = nil, separator = ',')
|
669
|
-
file ||= STDOUT
|
670
|
-
if first_row(sheet) # sheet is not empty
|
671
|
-
1.upto(last_row(sheet)) do |row|
|
672
|
-
1.upto(last_column(sheet)) do |col|
|
673
|
-
file.print(separator) if col > 1
|
674
|
-
file.print cell_to_csv(row, col, sheet)
|
675
|
-
end
|
676
|
-
file.print("\n")
|
677
|
-
end # sheet not empty
|
678
|
-
end
|
679
|
-
end
|
680
|
-
|
681
|
-
# The content of a cell in the csv output
|
682
|
-
def cell_to_csv(row, col, sheet)
|
683
|
-
if empty?(row, col, sheet)
|
684
|
-
''
|
685
|
-
else
|
686
|
-
onecell = cell(row, col, sheet)
|
687
|
-
|
688
|
-
case celltype(row, col, sheet)
|
689
|
-
when :string
|
690
|
-
%("#{onecell.gsub('"', '""')}") unless onecell.empty?
|
691
|
-
when :boolean
|
692
|
-
%("#{onecell.gsub('"', '""').downcase}")
|
693
|
-
when :float, :percentage
|
694
|
-
if onecell == onecell.to_i
|
695
|
-
onecell.to_i.to_s
|
696
|
-
else
|
697
|
-
onecell.to_s
|
698
|
-
end
|
699
|
-
when :formula
|
700
|
-
case onecell
|
701
|
-
when String
|
702
|
-
%("#{onecell.gsub('"', '""')}") unless onecell.empty?
|
703
|
-
when Float
|
704
|
-
if onecell == onecell.to_i
|
705
|
-
onecell.to_i.to_s
|
706
|
-
else
|
707
|
-
onecell.to_s
|
708
|
-
end
|
709
|
-
when DateTime
|
710
|
-
onecell.to_s
|
711
|
-
else
|
712
|
-
fail "unhandled onecell-class #{onecell.class}"
|
713
|
-
end
|
714
|
-
when :date, :datetime
|
715
|
-
onecell.to_s
|
716
|
-
when :time
|
717
|
-
integer_to_timestring(onecell)
|
718
|
-
when :link
|
719
|
-
%("#{onecell.url.gsub('"', '""')}")
|
720
|
-
else
|
721
|
-
fail "unhandled celltype #{celltype(row, col, sheet)}"
|
722
|
-
end || ''
|
723
|
-
end
|
724
|
-
end
|
725
|
-
|
726
|
-
# converts an integer value to a time string like '02:05:06'
|
727
|
-
def integer_to_timestring(content)
|
728
|
-
h = (content / 3600.0).floor
|
729
|
-
content = content - h * 3600
|
730
|
-
m = (content / 60.0).floor
|
731
|
-
content = content - m * 60
|
732
|
-
s = content
|
733
|
-
sprintf('%02d:%02d:%02d', h, m, s)
|
734
|
-
end
|
735
598
|
end
|
@@ -0,0 +1,5 @@
|
|
1
|
+
module Roo
|
2
|
+
ROO_EXCEL_NOTICE = "Excel support has been extracted to roo-xls due to its dependency on the GPL'd spreadsheet gem. Install roo-xls to use Roo::Excel.".freeze
|
3
|
+
ROO_EXCELML_NOTICE = "Excel SpreadsheetML support has been extracted to roo-xls. Install roo-xls to use Roo::Excel2003XML.".freeze
|
4
|
+
ROO_GOOGLE_NOTICE = "Google support has been extracted to roo-google. Install roo-google to use Roo::Google.".freeze
|
5
|
+
end
|