roo 1.10.1 → 1.10.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/.gitignore +2 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +38 -0
- data/History.txt +4 -4
- data/License.txt +20 -0
- data/Manifest.txt +68 -0
- data/README.markdown +109 -0
- data/Rakefile +5 -4
- data/bin/roo +0 -0
- data/examples/roo_soap_client.rb +53 -0
- data/examples/roo_soap_server.rb +29 -0
- data/examples/write_me.rb +33 -0
- data/lib/roo.rb +20 -61
- data/lib/roo/csv.rb +13 -11
- data/lib/roo/excel.rb +108 -219
- data/lib/roo/excel2003xml.rb +312 -0
- data/lib/roo/excelx.rb +205 -341
- data/lib/roo/generic_spreadsheet.rb +371 -268
- data/lib/roo/google.rb +64 -54
- data/lib/roo/openoffice.rb +101 -156
- data/lib/roo/roo_rails_helper.rb +5 -5
- data/lib/roo/worksheet.rb +18 -0
- data/roo.gemspec +43 -0
- data/scripts/txt2html +67 -0
- data/test/all_ss.rb +8 -10
- data/test/{1900_base.xls → files/1900_base.xls} +0 -0
- data/test/{1904_base.xls → files/1904_base.xls} +0 -0
- data/test/{Bibelbund.csv → files/Bibelbund.csv} +0 -0
- data/test/{Bibelbund.ods → files/Bibelbund.ods} +0 -0
- data/test/{Bibelbund.xls → files/Bibelbund.xls} +0 -0
- data/test/{Bibelbund.xlsx → files/Bibelbund.xlsx} +0 -0
- data/test/files/Bibelbund.xml +62518 -0
- data/test/{Bibelbund1.ods → files/Bibelbund1.ods} +0 -0
- data/test/{Pfand_from_windows_phone.xlsx → files/Pfand_from_windows_phone.xlsx} +0 -0
- data/test/files/bad_excel_date.xls +0 -0
- data/test/{bbu.ods → files/bbu.ods} +0 -0
- data/test/{bbu.xls → files/bbu.xls} +0 -0
- data/test/{bbu.xlsx → files/bbu.xlsx} +0 -0
- data/test/files/bbu.xml +152 -0
- data/test/{bode-v1.ods.zip → files/bode-v1.ods.zip} +0 -0
- data/test/{bode-v1.xls.zip → files/bode-v1.xls.zip} +0 -0
- data/test/{boolean.ods → files/boolean.ods} +0 -0
- data/test/{boolean.xls → files/boolean.xls} +0 -0
- data/test/{boolean.xlsx → files/boolean.xlsx} +0 -0
- data/test/files/boolean.xml +112 -0
- data/test/{borders.ods → files/borders.ods} +0 -0
- data/test/{borders.xls → files/borders.xls} +0 -0
- data/test/{borders.xlsx → files/borders.xlsx} +0 -0
- data/test/files/borders.xml +144 -0
- data/test/{bug-row-column-fixnum-float.xls → files/bug-row-column-fixnum-float.xls} +0 -0
- data/test/files/bug-row-column-fixnum-float.xml +127 -0
- data/test/{comments.ods → files/comments.ods} +0 -0
- data/test/{comments.xls → files/comments.xls} +0 -0
- data/test/{comments.xlsx → files/comments.xlsx} +0 -0
- data/test/{csvtypes.csv → files/csvtypes.csv} +0 -0
- data/test/{datetime.ods → files/datetime.ods} +0 -0
- data/test/{datetime.xls → files/datetime.xls} +0 -0
- data/test/{datetime.xlsx → files/datetime.xlsx} +0 -0
- data/test/files/datetime.xml +142 -0
- data/test/{datetime_floatconv.xls → files/datetime_floatconv.xls} +0 -0
- data/test/files/datetime_floatconv.xml +148 -0
- data/test/{dreimalvier.ods → files/dreimalvier.ods} +0 -0
- data/test/{emptysheets.ods → files/emptysheets.ods} +0 -0
- data/test/{emptysheets.xls → files/emptysheets.xls} +0 -0
- data/test/{emptysheets.xlsx → files/emptysheets.xlsx} +0 -0
- data/test/files/emptysheets.xml +105 -0
- data/test/files/excel2003.xml +21140 -0
- data/test/{false_encoding.xls → files/false_encoding.xls} +0 -0
- data/test/files/false_encoding.xml +132 -0
- data/test/{formula.ods → files/formula.ods} +0 -0
- data/test/{formula.xls → files/formula.xls} +0 -0
- data/test/{formula.xlsx → files/formula.xlsx} +0 -0
- data/test/files/formula.xml +134 -0
- data/test/files/formula_parse_error.xls +0 -0
- data/test/files/formula_parse_error.xml +1833 -0
- data/test/{formula_string_error.xlsx → files/formula_string_error.xlsx} +0 -0
- data/test/{html-escape.ods → files/html-escape.ods} +0 -0
- data/test/{matrix.ods → files/matrix.ods} +0 -0
- data/test/{matrix.xls → files/matrix.xls} +0 -0
- data/test/{named_cells.ods → files/named_cells.ods} +0 -0
- data/test/{named_cells.xls → files/named_cells.xls} +0 -0
- data/test/{named_cells.xlsx → files/named_cells.xlsx} +0 -0
- data/test/{no_spreadsheet_file.txt → files/no_spreadsheet_file.txt} +0 -0
- data/test/{numbers1.csv → files/numbers1.csv} +0 -0
- data/test/{numbers1.ods → files/numbers1.ods} +0 -0
- data/test/{numbers1.xls → files/numbers1.xls} +0 -0
- data/test/{numbers1.xlsx → files/numbers1.xlsx} +0 -0
- data/test/files/numbers1.xml +312 -0
- data/test/{only_one_sheet.ods → files/only_one_sheet.ods} +0 -0
- data/test/{only_one_sheet.xls → files/only_one_sheet.xls} +0 -0
- data/test/{only_one_sheet.xlsx → files/only_one_sheet.xlsx} +0 -0
- data/test/files/only_one_sheet.xml +67 -0
- data/test/{paragraph.ods → files/paragraph.ods} +0 -0
- data/test/{paragraph.xls → files/paragraph.xls} +0 -0
- data/test/{paragraph.xlsx → files/paragraph.xlsx} +0 -0
- data/test/files/paragraph.xml +127 -0
- data/test/{prova.xls → files/prova.xls} +0 -0
- data/test/{ric.ods → files/ric.ods} +0 -0
- data/test/{simple_spreadsheet.ods → files/simple_spreadsheet.ods} +0 -0
- data/test/{simple_spreadsheet.xls → files/simple_spreadsheet.xls} +0 -0
- data/test/{simple_spreadsheet.xlsx → files/simple_spreadsheet.xlsx} +0 -0
- data/test/files/simple_spreadsheet.xml +225 -0
- data/test/{simple_spreadsheet_from_italo.ods → files/simple_spreadsheet_from_italo.ods} +0 -0
- data/test/{simple_spreadsheet_from_italo.xls → files/simple_spreadsheet_from_italo.xls} +0 -0
- data/test/files/simple_spreadsheet_from_italo.xml +242 -0
- data/test/{so_datetime.csv → files/so_datetime.csv} +0 -0
- data/test/{style.ods → files/style.ods} +0 -0
- data/test/{style.xls → files/style.xls} +0 -0
- data/test/{style.xlsx → files/style.xlsx} +0 -0
- data/test/files/style.xml +154 -0
- data/test/{time-test.csv → files/time-test.csv} +0 -0
- data/test/{time-test.ods → files/time-test.ods} +0 -0
- data/test/{time-test.xls → files/time-test.xls} +0 -0
- data/test/{time-test.xlsx → files/time-test.xlsx} +0 -0
- data/test/files/time-test.xml +131 -0
- data/test/{type_excel.ods → files/type_excel.ods} +0 -0
- data/test/{type_excel.xlsx → files/type_excel.xlsx} +0 -0
- data/test/{type_excelx.ods → files/type_excelx.ods} +0 -0
- data/test/{type_excelx.xls → files/type_excelx.xls} +0 -0
- data/test/{type_openoffice.xls → files/type_openoffice.xls} +0 -0
- data/test/{type_openoffice.xlsx → files/type_openoffice.xlsx} +0 -0
- data/test/{whitespace.ods → files/whitespace.ods} +0 -0
- data/test/{whitespace.xls → files/whitespace.xls} +0 -0
- data/test/{whitespace.xlsx → files/whitespace.xlsx} +0 -0
- data/test/files/whitespace.xml +184 -0
- data/test/test_generic_spreadsheet.rb +257 -0
- data/test/test_helper.rb +167 -27
- data/test/test_roo.rb +1178 -930
- data/website/index.html +385 -0
- data/website/index.txt +423 -0
- data/website/javascripts/rounded_corners_lite.inc.js +285 -0
- data/website/stylesheets/screen.css +130 -0
- data/website/template.rhtml +48 -0
- metadata +151 -121
- data/README.txt +0 -110
- data/lib/roo/.csv.rb.swp +0 -0
data/lib/roo/csv.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'csv'
|
3
|
+
require 'time'
|
3
4
|
|
4
5
|
# The Csv class can read csv files (must be separated with commas) which then
|
5
6
|
# can be handled like spreadsheets. This means you can access cells like A5
|
@@ -7,10 +8,9 @@ require 'csv'
|
|
7
8
|
# The Csv class provides only string objects. If you want conversions to other
|
8
9
|
# types you have to do it yourself.
|
9
10
|
|
10
|
-
class Csv < GenericSpreadsheet
|
11
|
+
class Roo::Csv < Roo::GenericSpreadsheet
|
11
12
|
def initialize(filename, packed=nil, file_warning=:error, tmpdir=nil)
|
12
13
|
@filename = filename
|
13
|
-
super()
|
14
14
|
@cell = Hash.new
|
15
15
|
@cell_type = Hash.new
|
16
16
|
@cells_read = Hash.new
|
@@ -27,14 +27,14 @@ class Csv < GenericSpreadsheet
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def cell(row, col, sheet=nil)
|
30
|
-
sheet
|
30
|
+
sheet ||= @default_sheet
|
31
31
|
read_cells(sheet) unless @cells_read[sheet]
|
32
32
|
row,col = normalize(row,col)
|
33
33
|
@cell[[row,col]]
|
34
34
|
end
|
35
35
|
|
36
36
|
def celltype(row, col, sheet=nil)
|
37
|
-
sheet
|
37
|
+
sheet ||= @default_sheet
|
38
38
|
read_cells(sheet) unless @cells_read[sheet]
|
39
39
|
row,col = normalize(row,col)
|
40
40
|
@cell_type[[row,col]]
|
@@ -46,17 +46,19 @@ class Csv < GenericSpreadsheet
|
|
46
46
|
|
47
47
|
private
|
48
48
|
|
49
|
+
TYPE_MAP = {
|
50
|
+
String => :string,
|
51
|
+
Float => :float,
|
52
|
+
Date => :date,
|
53
|
+
DateTime => :datetime,
|
54
|
+
}
|
55
|
+
|
49
56
|
def celltype_class(value)
|
50
|
-
|
51
|
-
Float => :float,
|
52
|
-
Date => :date,
|
53
|
-
DateTime => :datetime,
|
54
|
-
}[value.class]
|
55
|
-
raise "unknown type for #{value.inspect}"
|
57
|
+
TYPE_MAP[value.class]
|
56
58
|
end
|
57
59
|
|
58
60
|
def read_cells(sheet=nil)
|
59
|
-
sheet
|
61
|
+
sheet ||= @default_sheet
|
60
62
|
@cell_type = {} unless @cell_type
|
61
63
|
@cell = {} unless @cell
|
62
64
|
@first_row[sheet] = 1
|
data/lib/roo/excel.rb
CHANGED
@@ -1,127 +1,35 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'spreadsheet'
|
3
|
+
require 'iconv'
|
3
4
|
#require 'lib/roo/generic_spreadsheet'
|
4
5
|
#require 'parseexcel'
|
5
|
-
CHARGUESS =
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
# The Spreadsheet library has a bug in handling Excel
|
13
|
-
# base dates so if the file is a 1904 base date then
|
14
|
-
# dates are off by a day. 1900 base dates work fine
|
15
|
-
module Spreadsheet
|
16
|
-
module Excel
|
17
|
-
class Row < Spreadsheet::Row
|
18
|
-
def _date data # :nodoc:
|
19
|
-
return data if data.is_a?(Date)
|
20
|
-
date = @worksheet.date_base + data.to_i
|
21
|
-
if LEAP_ERROR > @worksheet.date_base
|
22
|
-
date -= 1
|
23
|
-
end
|
24
|
-
date
|
25
|
-
end
|
26
|
-
public :_datetime
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
#=====================================================================
|
32
|
-
# TODO:
|
33
|
-
# redefinition of this method, the method in the spreadsheet gem has a bug
|
34
|
-
# redefinition can be removed, if spreadsheet does it in the correct way
|
35
|
-
module Spreadsheet
|
36
|
-
module Excel
|
37
|
-
class Row < Spreadsheet::Row
|
38
|
-
def _datetime data # :nodoc:
|
39
|
-
return data if data.is_a?(DateTime)
|
40
|
-
base = @worksheet.date_base
|
41
|
-
date = base + data.to_f
|
42
|
-
hour = (data % 1) * 24
|
43
|
-
min = (hour % 1) * 60
|
44
|
-
sec = ((min % 1) * 60).round
|
45
|
-
min = min.floor
|
46
|
-
hour = hour.floor
|
47
|
-
if sec > 59
|
48
|
-
sec = 0
|
49
|
-
min += 1
|
50
|
-
end
|
51
|
-
if min > 59
|
52
|
-
min = 0
|
53
|
-
hour += 1
|
54
|
-
end
|
55
|
-
if hour > 23
|
56
|
-
hour = 0
|
57
|
-
date += 1
|
58
|
-
end
|
59
|
-
if LEAP_ERROR > base
|
60
|
-
date -= 1
|
61
|
-
end
|
62
|
-
DateTime.new(date.year, date.month, date.day, hour, min, sec)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
#=====================================================================
|
68
|
-
|
69
|
-
# ruby-spreadsheet has a font object so we're extending it
|
70
|
-
# with our own functionality but still providing full access
|
71
|
-
# to the user for other font information
|
72
|
-
module ExcelFontExtensions
|
73
|
-
def bold?(*args)
|
74
|
-
#From ruby-spreadsheet doc: 100 <= weight <= 1000, bold => 700, normal => 400
|
75
|
-
case weight
|
76
|
-
when 700
|
77
|
-
true
|
78
|
-
else
|
79
|
-
false
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
def italic?
|
84
|
-
italic
|
85
|
-
end
|
86
|
-
|
87
|
-
def underline?
|
88
|
-
underline != :none
|
6
|
+
CHARGUESS =
|
7
|
+
begin
|
8
|
+
require 'charguess'
|
9
|
+
true
|
10
|
+
rescue LoadError
|
11
|
+
false
|
89
12
|
end
|
90
13
|
|
91
|
-
end
|
92
|
-
|
93
14
|
# Class for handling Excel-Spreadsheets
|
94
|
-
class Excel < GenericSpreadsheet
|
95
|
-
|
96
|
-
EXCEL_NO_FORMULAS = 'Formulas are not supported for excel spreadsheets.'
|
15
|
+
class Roo::Excel < Roo::GenericSpreadsheet
|
97
16
|
|
98
17
|
# Creates a new Excel spreadsheet object.
|
99
18
|
# Parameter packed: :zip - File is a zip-file
|
100
19
|
def initialize(filename, packed = nil, file_warning = :error)
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
filename = unzip(filename) if packed and packed == :zip
|
112
|
-
@filename = filename
|
113
|
-
unless File.file?(@filename)
|
114
|
-
FileUtils::rm_r(@tmpdir)
|
115
|
-
raise IOError, "file #{@filename} does not exist"
|
116
|
-
end
|
117
|
-
begin
|
20
|
+
file_type_check(filename,'.xls','an Excel', file_warning, packed)
|
21
|
+
make_tmpdir do |tmpdir|
|
22
|
+
filename = open_from_uri(filename, tmpdir) if uri?(filename)
|
23
|
+
filename = open_from_stream(filename[7..-1], tmpdir) if filename[0,7] == "stream:"
|
24
|
+
filename = unzip(filename, tmpdir) if packed == :zip
|
25
|
+
|
26
|
+
@filename = filename
|
27
|
+
unless File.file?(@filename)
|
28
|
+
raise IOError, "file #{@filename} does not exist"
|
29
|
+
end
|
118
30
|
@workbook = Spreadsheet.open(filename)
|
119
|
-
rescue Ole::Storage::FormatError
|
120
|
-
FileUtils::rm_r(@tmpdir)
|
121
|
-
raise # nach aussen weiterhin sichtbar
|
122
31
|
end
|
123
32
|
@default_sheet = self.sheets.first
|
124
|
-
FileUtils::rm_r(@tmpdir)
|
125
33
|
@cell = Hash.new
|
126
34
|
@cell_type = Hash.new
|
127
35
|
@formula = Hash.new
|
@@ -134,6 +42,10 @@ class Excel < GenericSpreadsheet
|
|
134
42
|
@fonts = Hash.new
|
135
43
|
end
|
136
44
|
|
45
|
+
def encoding=(codepage)
|
46
|
+
@workbook.encoding = codepage
|
47
|
+
end
|
48
|
+
|
137
49
|
# returns an array of sheet names in the spreadsheet
|
138
50
|
def sheets
|
139
51
|
@workbook.worksheets.collect {|worksheet| normalize_string(worksheet.name)}
|
@@ -141,8 +53,9 @@ class Excel < GenericSpreadsheet
|
|
141
53
|
|
142
54
|
# returns the content of a cell. The upper left corner is (1,1) or ('A',1)
|
143
55
|
def cell(row,col,sheet=nil)
|
144
|
-
sheet
|
145
|
-
|
56
|
+
sheet ||= @default_sheet
|
57
|
+
validate_sheet!(sheet)
|
58
|
+
|
146
59
|
read_cells(sheet) unless @cells_read[sheet]
|
147
60
|
raise "should be read" unless @cells_read[sheet]
|
148
61
|
row,col = normalize(row,col)
|
@@ -170,18 +83,14 @@ class Excel < GenericSpreadsheet
|
|
170
83
|
# * :time
|
171
84
|
# * :datetime
|
172
85
|
def celltype(row,col,sheet=nil)
|
173
|
-
sheet
|
86
|
+
sheet ||= @default_sheet
|
174
87
|
read_cells(sheet) unless @cells_read[sheet]
|
175
88
|
row,col = normalize(row,col)
|
176
89
|
begin
|
177
90
|
if @formula[sheet] and @formula[sheet][[row,col]]
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
return @cell_type[sheet][[row,col]]
|
182
|
-
else
|
183
|
-
return nil
|
184
|
-
end
|
91
|
+
:formula
|
92
|
+
elsif @cell_type[sheet]
|
93
|
+
@cell_type[sheet][[row,col]]
|
185
94
|
end
|
186
95
|
rescue
|
187
96
|
puts "Error in sheet #{sheet}, row #{row}, col #{col}"
|
@@ -206,36 +115,20 @@ class Excel < GenericSpreadsheet
|
|
206
115
|
|
207
116
|
# Given a cell, return the cell's font
|
208
117
|
def font(row, col, sheet=nil)
|
209
|
-
sheet
|
118
|
+
sheet ||= @default_sheet
|
210
119
|
read_cells(sheet) unless @cells_read[sheet]
|
211
120
|
row,col = normalize(row,col)
|
212
121
|
@fonts[sheet][[row,col]]
|
213
|
-
end
|
214
|
-
|
122
|
+
end
|
123
|
+
|
215
124
|
# shows the internal representation of all cells
|
216
125
|
# mainly for debugging purposes
|
217
126
|
def to_s(sheet=nil)
|
218
|
-
sheet
|
127
|
+
sheet ||= @default_sheet
|
219
128
|
read_cells(sheet) unless @cells_read[sheet]
|
220
129
|
@cell[sheet].inspect
|
221
130
|
end
|
222
131
|
|
223
|
-
# returns the row,col values of the labelled cell
|
224
|
-
# (nil,nil) if label is not defined
|
225
|
-
# sheet parameter is not really needed because label names are global
|
226
|
-
# to the whole spreadsheet
|
227
|
-
def label(labelname,sheet=nil)
|
228
|
-
sheet = @default_sheet unless sheet
|
229
|
-
read_cells(sheet) unless @cells_read[sheet]
|
230
|
-
if @labels.has_key? labelname
|
231
|
-
return @labels[labelname][1].to_i,
|
232
|
-
GenericSpreadsheet.letter_to_number(@labels[labelname][2]),
|
233
|
-
@labels[labelname][0]
|
234
|
-
else
|
235
|
-
return nil,nil,nil
|
236
|
-
end
|
237
|
-
end
|
238
|
-
|
239
132
|
private
|
240
133
|
|
241
134
|
# converts name of a sheet to index (0,1,2,..)
|
@@ -249,26 +142,6 @@ class Excel < GenericSpreadsheet
|
|
249
142
|
raise StandardError, "sheet '#{name}' not found"
|
250
143
|
end
|
251
144
|
|
252
|
-
def empty_row?(row)
|
253
|
-
content = false
|
254
|
-
row.compact.each {|elem|
|
255
|
-
if elem != ''
|
256
|
-
content = true
|
257
|
-
end
|
258
|
-
}
|
259
|
-
! content
|
260
|
-
end
|
261
|
-
|
262
|
-
def empty_column?(col)
|
263
|
-
content = false
|
264
|
-
col.compact.each {|elem|
|
265
|
-
if elem != ''
|
266
|
-
content = true
|
267
|
-
end
|
268
|
-
}
|
269
|
-
! content
|
270
|
-
end
|
271
|
-
|
272
145
|
def normalize_string(value)
|
273
146
|
value = every_second_null?(value) ? remove_every_second_null(value) : value
|
274
147
|
if CHARGUESS && encoding = CharGuess::guess(value)
|
@@ -277,18 +150,17 @@ class Excel < GenericSpreadsheet
|
|
277
150
|
platform_specific_iconv(value)
|
278
151
|
end
|
279
152
|
end
|
280
|
-
|
153
|
+
|
281
154
|
def platform_specific_iconv(value)
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
end # case
|
155
|
+
result =
|
156
|
+
case RUBY_PLATFORM.downcase
|
157
|
+
when /darwin|solaris/
|
158
|
+
Iconv.new('utf-8','utf-8').iconv(value)
|
159
|
+
when /mswin32/
|
160
|
+
Iconv.new('utf-8','iso-8859-1').iconv(value)
|
161
|
+
else
|
162
|
+
value
|
163
|
+
end
|
292
164
|
if every_second_null?(result)
|
293
165
|
result = remove_every_second_null(result)
|
294
166
|
end
|
@@ -299,10 +171,8 @@ class Excel < GenericSpreadsheet
|
|
299
171
|
result = true
|
300
172
|
return false if str.length < 2
|
301
173
|
0.upto(str.length/2-1) do |i|
|
302
|
-
|
303
|
-
|
304
|
-
if n != "\000"
|
305
|
-
result = false
|
174
|
+
if str[i*2+1,1] != "\000"
|
175
|
+
result = false
|
306
176
|
break
|
307
177
|
end
|
308
178
|
end
|
@@ -319,62 +189,81 @@ class Excel < GenericSpreadsheet
|
|
319
189
|
end
|
320
190
|
|
321
191
|
# helper function to set the internal representation of cells
|
322
|
-
def set_cell_values(sheet,row,col,i,v,
|
192
|
+
def set_cell_values(sheet,row,col,i,v,value_type,formula,tr,font)
|
323
193
|
#key = "#{y},#{x+i}"
|
324
194
|
key = [row,col+i]
|
325
195
|
@cell_type[sheet] = {} unless @cell_type[sheet]
|
326
|
-
@cell_type[sheet][key] =
|
196
|
+
@cell_type[sheet][key] = value_type
|
327
197
|
@formula[sheet] = {} unless @formula[sheet]
|
328
198
|
@formula[sheet][key] = formula if formula
|
329
199
|
@cell[sheet] = {} unless @cell[sheet]
|
330
200
|
@fonts[sheet] = {} unless @fonts[sheet]
|
331
201
|
@fonts[sheet][key] = font
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
202
|
+
|
203
|
+
@cell[sheet][key] =
|
204
|
+
case value_type
|
205
|
+
when :float
|
206
|
+
v.to_f
|
207
|
+
when :string
|
208
|
+
v
|
209
|
+
when :date
|
210
|
+
v
|
211
|
+
when :datetime
|
212
|
+
@cell[sheet][key] = DateTime.new(v.year,v.month,v.day,v.hour,v.min,v.sec)
|
213
|
+
when :percentage
|
214
|
+
v.to_f
|
215
|
+
when :time
|
216
|
+
v
|
217
|
+
else
|
218
|
+
v
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
# ruby-spreadsheet has a font object so we're extending it
|
223
|
+
# with our own functionality but still providing full access
|
224
|
+
# to the user for other font information
|
225
|
+
module ExcelFontExtensions
|
226
|
+
def bold?(*args)
|
227
|
+
#From ruby-spreadsheet doc: 100 <= weight <= 1000, bold => 700, normal => 400
|
228
|
+
weight == 700
|
229
|
+
end
|
230
|
+
|
231
|
+
def italic?
|
232
|
+
italic
|
233
|
+
end
|
234
|
+
|
235
|
+
def underline?
|
236
|
+
underline != :none
|
348
237
|
end
|
349
238
|
end
|
350
239
|
|
351
240
|
# read all cells in the selected sheet
|
352
241
|
def read_cells(sheet=nil)
|
353
|
-
sheet
|
354
|
-
|
355
|
-
|
356
|
-
|
242
|
+
sheet ||= @default_sheet
|
243
|
+
validate_sheet!(sheet)
|
244
|
+
|
357
245
|
if @cells_read[sheet]
|
358
246
|
raise "sheet #{sheet} already read"
|
359
247
|
end
|
360
|
-
|
248
|
+
|
361
249
|
worksheet = @workbook.worksheet(sheet_no(sheet))
|
362
250
|
row_index=1
|
363
|
-
worksheet.each(0) do |row|
|
251
|
+
worksheet.each(0) do |row|
|
364
252
|
(0..row.size).each do |cell_index|
|
365
253
|
cell = row.at(cell_index)
|
366
254
|
next if cell.nil? #skip empty cells
|
367
255
|
next if cell.class == Spreadsheet::Formula && cell.value.nil? # skip empty formula cells
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
256
|
+
value_type, v =
|
257
|
+
if date_or_time?(row, cell_index)
|
258
|
+
read_cell_date_or_time(row, cell_index)
|
259
|
+
else
|
260
|
+
read_cell(row, cell_index)
|
261
|
+
end
|
373
262
|
formula = tr = nil #TODO:???
|
374
263
|
col_index = cell_index + 1
|
375
264
|
font = row.format(cell_index).font
|
376
265
|
font.extend(ExcelFontExtensions)
|
377
|
-
set_cell_values(sheet,row_index,col_index,0,v,
|
266
|
+
set_cell_values(sheet,row_index,col_index,0,v,value_type,formula,tr,font)
|
378
267
|
end #row
|
379
268
|
row_index += 1
|
380
269
|
end # worksheet
|
@@ -388,8 +277,8 @@ class Excel < GenericSpreadsheet
|
|
388
277
|
cell = cell.value if cell.class == Spreadsheet::Formula
|
389
278
|
cell
|
390
279
|
end
|
391
|
-
|
392
|
-
# Test the cell to see if it's a valid date/time.
|
280
|
+
|
281
|
+
# Test the cell to see if it's a valid date/time.
|
393
282
|
def date_or_time?(row, idx)
|
394
283
|
format = row.format(idx)
|
395
284
|
if format.date_or_time?
|
@@ -397,11 +286,11 @@ class Excel < GenericSpreadsheet
|
|
397
286
|
true if Float(cell) > 0 rescue false
|
398
287
|
else
|
399
288
|
false
|
400
|
-
end
|
289
|
+
end
|
401
290
|
end
|
402
291
|
private :date_or_time?
|
403
|
-
|
404
|
-
# Read the date-time cell and convert to,
|
292
|
+
|
293
|
+
# Read the date-time cell and convert to,
|
405
294
|
# the date-time values for Roo
|
406
295
|
def read_cell_date_or_time(row, idx)
|
407
296
|
cell = read_cell_content(row, idx)
|
@@ -418,10 +307,10 @@ class Excel < GenericSpreadsheet
|
|
418
307
|
value = h*3600+m*60+s
|
419
308
|
else
|
420
309
|
if row.at(idx).class == Spreadsheet::Formula
|
421
|
-
datetime = row._datetime
|
310
|
+
datetime = row.send(:_datetime, cell)
|
422
311
|
else
|
423
312
|
datetime = row.datetime(idx)
|
424
|
-
end
|
313
|
+
end
|
425
314
|
if datetime.hour != 0 or
|
426
315
|
datetime.min != 0 or
|
427
316
|
datetime.sec != 0
|
@@ -430,23 +319,23 @@ class Excel < GenericSpreadsheet
|
|
430
319
|
else
|
431
320
|
value_type = :date
|
432
321
|
if row.at(idx).class == Spreadsheet::Formula
|
433
|
-
value = row._date
|
322
|
+
value = row.send(:_date, cell)
|
434
323
|
else
|
435
324
|
value = row.date(idx)
|
436
|
-
end
|
325
|
+
end
|
437
326
|
value = sprintf("%04d-%02d-%02d",value.year,value.month,value.day)
|
438
327
|
end
|
439
|
-
end
|
328
|
+
end
|
440
329
|
return value_type, value
|
441
330
|
end
|
442
331
|
private :read_cell_date_or_time
|
443
|
-
|
444
|
-
# Read the cell and based on the class,
|
332
|
+
|
333
|
+
# Read the cell and based on the class,
|
445
334
|
# return the values for Roo
|
446
335
|
def read_cell(row, idx)
|
447
336
|
cell = read_cell_content(row, idx)
|
448
337
|
case cell
|
449
|
-
when Float, Integer, Fixnum, Bignum
|
338
|
+
when Float, Integer, Fixnum, Bignum
|
450
339
|
value_type = :float
|
451
340
|
value = cell.to_f
|
452
341
|
when String, TrueClass, FalseClass
|
@@ -462,7 +351,7 @@ class Excel < GenericSpreadsheet
|
|
462
351
|
|
463
352
|
def wait_for_version_080
|
464
353
|
if Spreadsheet::VERSION<='0.8.0'
|
465
|
-
raise
|
354
|
+
raise 'Formulas are not supported for excel spreadsheets.' +
|
466
355
|
" We have to wait for the 0.8.0 version of the Spreadsheet gem (currently used version is #{Spreadsheet::VERSION})"
|
467
356
|
else
|
468
357
|
raise 'Thomas should implement formulas from Spreadsheet gem'
|