roo 1.10.1 → 1.10.2
Sign up to get free protection for your applications and to get access to all the features.
- 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/google.rb
CHANGED
@@ -1,12 +1,16 @@
|
|
1
|
-
|
1
|
+
begin
|
2
|
+
require "google_spreadsheet"
|
3
|
+
rescue LoadError => e
|
4
|
+
raise e, "Using Roo::Google requires the google-spreadsheet-ruby gem"
|
5
|
+
end
|
2
6
|
|
3
7
|
class GoogleHTTPError < RuntimeError; end
|
4
8
|
class GoogleReadError < RuntimeError; end
|
5
9
|
class GoogleWriteError < RuntimeError; end
|
6
10
|
|
7
|
-
class Google < GenericSpreadsheet
|
11
|
+
class Roo::Google < Roo::GenericSpreadsheet
|
8
12
|
attr_accessor :date_format, :datetime_format
|
9
|
-
|
13
|
+
|
10
14
|
# Creates a new Google spreadsheet object.
|
11
15
|
def initialize(spreadsheetkey,user=nil,password=nil)
|
12
16
|
@filename = spreadsheetkey
|
@@ -35,7 +39,7 @@ class Google < GenericSpreadsheet
|
|
35
39
|
@cells_read = Hash.new
|
36
40
|
@header_line = 1
|
37
41
|
@date_format = '%d/%m/%Y'
|
38
|
-
@datetime_format = '%d/%m/%Y %H:%M:%S'
|
42
|
+
@datetime_format = '%d/%m/%Y %H:%M:%S'
|
39
43
|
@time_format = '%H:%M:%S'
|
40
44
|
session = GoogleSpreadsheet.login(user, password)
|
41
45
|
@sheetlist = []
|
@@ -52,31 +56,25 @@ class Google < GenericSpreadsheet
|
|
52
56
|
end
|
53
57
|
|
54
58
|
def date?(string)
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
false
|
60
|
-
end
|
59
|
+
Date.strptime(string, @date_format)
|
60
|
+
true
|
61
|
+
rescue
|
62
|
+
false
|
61
63
|
end
|
62
64
|
|
63
65
|
# is String a time with format HH:MM:SS?
|
64
66
|
def time?(string)
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
false
|
70
|
-
end
|
67
|
+
DateTime.strptime(string, @time_format)
|
68
|
+
true
|
69
|
+
rescue
|
70
|
+
false
|
71
71
|
end
|
72
72
|
|
73
73
|
def datetime?(string)
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
false
|
79
|
-
end
|
74
|
+
DateTime.strptime(string, @datetime_format)
|
75
|
+
true
|
76
|
+
rescue
|
77
|
+
false
|
80
78
|
end
|
81
79
|
|
82
80
|
def numeric?(string)
|
@@ -93,8 +91,8 @@ class Google < GenericSpreadsheet
|
|
93
91
|
# (1,1), (1,'A'), ('A',1), ('a',1) all refers to the
|
94
92
|
# cell at the first line and first row.
|
95
93
|
def cell(row, col, sheet=nil)
|
96
|
-
sheet
|
97
|
-
|
94
|
+
sheet ||= @default_sheet
|
95
|
+
validate_sheet!(sheet) #TODO: 2007-12-16
|
98
96
|
read_cells(sheet) unless @cells_read[sheet]
|
99
97
|
row,col = normalize(row,col)
|
100
98
|
value = @cell[sheet]["#{row},#{col}"]
|
@@ -110,7 +108,7 @@ class Google < GenericSpreadsheet
|
|
110
108
|
rescue ArgumentError
|
111
109
|
raise "Invalid DateTime #{sheet}[#{row},#{col}] #{value} using format '{@datetime_format}'"
|
112
110
|
end
|
113
|
-
end
|
111
|
+
end
|
114
112
|
return value
|
115
113
|
end
|
116
114
|
|
@@ -123,7 +121,7 @@ class Google < GenericSpreadsheet
|
|
123
121
|
# * :time
|
124
122
|
# * :datetime
|
125
123
|
def celltype(row, col, sheet=nil)
|
126
|
-
sheet
|
124
|
+
sheet ||= @default_sheet
|
127
125
|
read_cells(sheet) unless @cells_read[sheet]
|
128
126
|
row,col = normalize(row,col)
|
129
127
|
if @formula.size > 0 && @formula[sheet]["#{row},#{col}"]
|
@@ -137,19 +135,19 @@ class Google < GenericSpreadsheet
|
|
137
135
|
# Returns nil if there is no formula.
|
138
136
|
# The method #formula? checks if there is a formula.
|
139
137
|
def formula(row,col,sheet=nil)
|
140
|
-
sheet
|
138
|
+
sheet ||= @default_sheet
|
141
139
|
read_cells(sheet) unless @cells_read[sheet]
|
142
140
|
row,col = normalize(row,col)
|
143
141
|
if @formula[sheet]["#{row},#{col}"] == nil
|
144
142
|
return nil
|
145
143
|
else
|
146
|
-
return @formula[sheet]["#{row},#{col}"]
|
144
|
+
return @formula[sheet]["#{row},#{col}"]
|
147
145
|
end
|
148
146
|
end
|
149
147
|
|
150
148
|
# true, if there is a formula
|
151
149
|
def formula?(row,col,sheet=nil)
|
152
|
-
sheet
|
150
|
+
sheet ||= @default_sheet
|
153
151
|
read_cells(sheet) unless @cells_read[sheet]
|
154
152
|
row,col = normalize(row,col)
|
155
153
|
formula(row,col) != nil
|
@@ -167,40 +165,42 @@ class Google < GenericSpreadsheet
|
|
167
165
|
|
168
166
|
# sets the cell to the content of 'value'
|
169
167
|
# a formula can be set in the form of '=SUM(...)'
|
170
|
-
def
|
171
|
-
sheet
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
sheet_no = sheets.index(sheet)+1
|
176
|
-
rescue
|
177
|
-
raise RangeError, "invalid sheet '"+sheet.to_s+"'"
|
178
|
-
end
|
168
|
+
def set(row,col,value,sheet=nil)
|
169
|
+
sheet ||= @default_sheet
|
170
|
+
validate_sheet!(sheet)
|
171
|
+
|
172
|
+
sheet_no = sheets.index(sheet)+1
|
179
173
|
row,col = normalize(row,col)
|
180
174
|
add_to_cell_roo(row,col,value,sheet_no)
|
181
175
|
# re-read the portion of the document that has changed
|
182
176
|
if @cells_read[sheet]
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
177
|
+
value, value_type = determine_datatype(value.to_s)
|
178
|
+
|
179
|
+
_set_value(col,row,value,sheet)
|
180
|
+
set_type(col,row,value_type,sheet)
|
187
181
|
end
|
188
182
|
end
|
189
|
-
|
183
|
+
|
184
|
+
# *DEPRECATED*: Use Roo::Google#set instead
|
185
|
+
def set_value(row,col,value,sheet=nil)
|
186
|
+
warn "[DEPRECATION] `set_value` is deprecated. Please use `set` instead."
|
187
|
+
set(row,col,value,sheet)
|
188
|
+
end
|
189
|
+
|
190
190
|
# returns the first non-empty row in a sheet
|
191
191
|
def first_row(sheet=nil)
|
192
|
-
sheet
|
192
|
+
sheet ||= @default_sheet
|
193
193
|
unless @first_row[sheet]
|
194
194
|
sheet_no = sheets.index(sheet) + 1
|
195
195
|
@first_row[sheet], @last_row[sheet], @first_column[sheet], @last_column[sheet] =
|
196
196
|
oben_unten_links_rechts(sheet_no)
|
197
|
-
end
|
197
|
+
end
|
198
198
|
return @first_row[sheet]
|
199
199
|
end
|
200
200
|
|
201
201
|
# returns the last non-empty row in a sheet
|
202
202
|
def last_row(sheet=nil)
|
203
|
-
sheet
|
203
|
+
sheet ||= @default_sheet
|
204
204
|
unless @last_row[sheet]
|
205
205
|
sheet_no = sheets.index(sheet) + 1
|
206
206
|
@first_row[sheet], @last_row[sheet], @first_column[sheet], @last_column[sheet] =
|
@@ -211,7 +211,7 @@ class Google < GenericSpreadsheet
|
|
211
211
|
|
212
212
|
# returns the first non-empty column in a sheet
|
213
213
|
def first_column(sheet=nil)
|
214
|
-
sheet
|
214
|
+
sheet ||= @default_sheet
|
215
215
|
unless @first_column[sheet]
|
216
216
|
sheet_no = sheets.index(sheet) + 1
|
217
217
|
@first_row[sheet], @last_row[sheet], @first_column[sheet], @last_column[sheet] =
|
@@ -222,7 +222,7 @@ class Google < GenericSpreadsheet
|
|
222
222
|
|
223
223
|
# returns the last non-empty column in a sheet
|
224
224
|
def last_column(sheet=nil)
|
225
|
-
sheet
|
225
|
+
sheet ||= @default_sheet
|
226
226
|
unless @last_column[sheet]
|
227
227
|
sheet_no = sheets.index(sheet) + 1
|
228
228
|
@first_row[sheet], @last_row[sheet], @first_column[sheet], @last_column[sheet] =
|
@@ -233,10 +233,20 @@ class Google < GenericSpreadsheet
|
|
233
233
|
|
234
234
|
private
|
235
235
|
|
236
|
-
|
236
|
+
def _set_value(row,col,value,sheet=nil)
|
237
|
+
sheet ||= @default_sheet
|
238
|
+
@cell[sheet][ "#{row},#{col}"] = value
|
239
|
+
end
|
240
|
+
|
241
|
+
def set_type(row,col,type,sheet=nil)
|
242
|
+
sheet ||= @default_sheet
|
243
|
+
@cell_type[sheet]["#{row},#{col}"] = type
|
244
|
+
end
|
245
|
+
|
246
|
+
# read all cells in a sheet.
|
237
247
|
def read_cells(sheet=nil)
|
238
|
-
sheet
|
239
|
-
|
248
|
+
sheet ||= @default_sheet
|
249
|
+
validate_sheet!(sheet)
|
240
250
|
sheet_no = sheets.index(sheet)
|
241
251
|
ws = @worksheets[sheet_no]
|
242
252
|
for row in 1..ws.num_rows
|
@@ -253,7 +263,7 @@ class Google < GenericSpreadsheet
|
|
253
263
|
end
|
254
264
|
@cells_read[sheet] = true
|
255
265
|
end
|
256
|
-
|
266
|
+
|
257
267
|
def determine_datatype(val, numval=nil)
|
258
268
|
if val.nil? || val[0,1] == '='
|
259
269
|
ty = :formula
|
@@ -267,7 +277,7 @@ class Google < GenericSpreadsheet
|
|
267
277
|
ty = :datetime
|
268
278
|
elsif date?(val)
|
269
279
|
ty = :date
|
270
|
-
elsif numeric?(val)
|
280
|
+
elsif numeric?(val)
|
271
281
|
ty = :float
|
272
282
|
val = val.to_f
|
273
283
|
elsif time?(val)
|
@@ -277,7 +287,7 @@ class Google < GenericSpreadsheet
|
|
277
287
|
ty = :string
|
278
288
|
end
|
279
289
|
end
|
280
|
-
return val, ty
|
290
|
+
return val, ty
|
281
291
|
end
|
282
292
|
|
283
293
|
def add_to_cell_roo(row,col,value, sheet_no=1)
|
data/lib/roo/openoffice.rb
CHANGED
@@ -5,38 +5,51 @@ require 'date'
|
|
5
5
|
require 'nokogiri'
|
6
6
|
require 'cgi'
|
7
7
|
require 'pp' #TODO
|
8
|
-
class Openoffice < GenericSpreadsheet
|
8
|
+
class Roo::Openoffice < Roo::GenericSpreadsheet
|
9
9
|
|
10
|
-
|
10
|
+
class << self
|
11
|
+
def extract_content(tmpdir, filename)
|
12
|
+
Zip::ZipFile.open(filename) do |zip|
|
13
|
+
process_zipfile(tmpdir, zip)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def process_zipfile(tmpdir, zip, path='')
|
18
|
+
if zip.file.file? path
|
19
|
+
if path == "content.xml"
|
20
|
+
open(File.join(tmpdir, 'roo_content.xml'),'wb') {|f|
|
21
|
+
f << zip.read(path)
|
22
|
+
}
|
23
|
+
end
|
24
|
+
else
|
25
|
+
unless path.empty?
|
26
|
+
path += '/'
|
27
|
+
end
|
28
|
+
zip.dir.foreach(path) do |filename|
|
29
|
+
process_zipfile(tmpdir, zip, path+filename)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
11
34
|
|
12
35
|
# initialization and opening of a spreadsheet file
|
13
36
|
# values for packed: :zip
|
14
|
-
def initialize(filename, packed=nil, file_warning=:error,
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
unless File.file?(@filename)
|
30
|
-
FileUtils::rm_r(@tmpdir)
|
31
|
-
raise IOError, "file #{@filename} does not exist"
|
37
|
+
def initialize(filename, packed=nil, file_warning=:error, tmpdir_root=nil)
|
38
|
+
file_type_check(filename,'.ods','an Roo::Openoffice', file_warning, packed)
|
39
|
+
make_tmpdir(tmpdir_root) do |tmpdir|
|
40
|
+
filename = open_from_uri(filename, tmpdir) if uri?(filename)
|
41
|
+
filename = unzip(filename, tmpdir) if packed == :zip
|
42
|
+
@cells_read = Hash.new
|
43
|
+
#TODO: @cells_read[:default] = false
|
44
|
+
@filename = filename
|
45
|
+
unless File.file?(@filename)
|
46
|
+
raise IOError, "file #{@filename} does not exist"
|
47
|
+
end
|
48
|
+
self.class.extract_content(tmpdir, @filename)
|
49
|
+
@doc = File.open(File.join(tmpdir, "roo_content.xml")) do |file|
|
50
|
+
Nokogiri::XML(file)
|
51
|
+
end
|
32
52
|
end
|
33
|
-
@@nr += 1
|
34
|
-
@file_nr = @@nr
|
35
|
-
extract_content
|
36
|
-
file = File.new(File.join(@tmpdir, @file_nr.to_s+"_roo_content.xml"))
|
37
|
-
@doc = Nokogiri::XML(file)
|
38
|
-
file.close
|
39
|
-
FileUtils::rm_r(@tmpdir)
|
40
53
|
@default_sheet = self.sheets.first
|
41
54
|
@cell = Hash.new
|
42
55
|
@cell_type = Hash.new
|
@@ -47,22 +60,20 @@ class Openoffice < GenericSpreadsheet
|
|
47
60
|
@last_column = Hash.new
|
48
61
|
@style = Hash.new
|
49
62
|
@style_defaults = Hash.new { |h,k| h[k] = [] }
|
50
|
-
@style_definitions = Hash.new
|
63
|
+
@style_definitions = Hash.new
|
51
64
|
@header_line = 1
|
52
|
-
@label = Hash.new
|
53
|
-
@labels_read = false
|
54
65
|
@comment = Hash.new
|
55
66
|
@comments_read = Hash.new
|
56
67
|
end
|
57
68
|
|
58
69
|
def method_missing(m,*args)
|
59
|
-
read_labels
|
70
|
+
read_labels
|
60
71
|
# is method name a label name
|
61
72
|
if @label.has_key?(m.to_s)
|
62
73
|
row,col = label(m.to_s)
|
63
74
|
cell(row,col)
|
64
75
|
else
|
65
|
-
# call super for methods like #a1
|
76
|
+
# call super for methods like #a1
|
66
77
|
super
|
67
78
|
end
|
68
79
|
end
|
@@ -72,7 +83,7 @@ class Openoffice < GenericSpreadsheet
|
|
72
83
|
# (1,1), (1,'A'), ('A',1), ('a',1) all refers to the
|
73
84
|
# cell at the first line and first row.
|
74
85
|
def cell(row, col, sheet=nil)
|
75
|
-
sheet
|
86
|
+
sheet ||= @default_sheet
|
76
87
|
read_cells(sheet) unless @cells_read[sheet]
|
77
88
|
row,col = normalize(row,col)
|
78
89
|
if celltype(row,col,sheet) == :date
|
@@ -86,7 +97,7 @@ class Openoffice < GenericSpreadsheet
|
|
86
97
|
# Returns nil if there is no formula.
|
87
98
|
# The method #formula? checks if there is a formula.
|
88
99
|
def formula(row,col,sheet=nil)
|
89
|
-
sheet
|
100
|
+
sheet ||= @default_sheet
|
90
101
|
read_cells(sheet) unless @cells_read[sheet]
|
91
102
|
row,col = normalize(row,col)
|
92
103
|
if @formula[sheet][[row,col]] == nil
|
@@ -106,7 +117,7 @@ class Openoffice < GenericSpreadsheet
|
|
106
117
|
|
107
118
|
# true, if there is a formula
|
108
119
|
def formula?(row,col,sheet=nil)
|
109
|
-
sheet
|
120
|
+
sheet ||= @default_sheet
|
110
121
|
read_cells(sheet) unless @cells_read[sheet]
|
111
122
|
row,col = normalize(row,col)
|
112
123
|
formula(row,col) != nil
|
@@ -115,7 +126,7 @@ class Openoffice < GenericSpreadsheet
|
|
115
126
|
# returns each formula in the selected sheet as an array of elements
|
116
127
|
# [row, col, formula]
|
117
128
|
def formulas(sheet=nil)
|
118
|
-
sheet
|
129
|
+
sheet ||= @default_sheet
|
119
130
|
read_cells(sheet) unless @cells_read[sheet]
|
120
131
|
if @formula[sheet]
|
121
132
|
@formula[sheet].each.collect do |elem|
|
@@ -128,45 +139,27 @@ class Openoffice < GenericSpreadsheet
|
|
128
139
|
|
129
140
|
class Font
|
130
141
|
attr_accessor :bold, :italic, :underline
|
131
|
-
|
132
|
-
def bold?
|
142
|
+
|
143
|
+
def bold?
|
133
144
|
@bold == 'bold'
|
134
145
|
end
|
135
146
|
|
136
|
-
def italic?
|
147
|
+
def italic?
|
137
148
|
@italic == 'italic'
|
138
149
|
end
|
139
|
-
|
140
|
-
def underline?
|
150
|
+
|
151
|
+
def underline?
|
141
152
|
@underline != nil
|
142
153
|
end
|
143
154
|
end
|
144
155
|
|
145
|
-
# Given a cell, return the cell's style
|
156
|
+
# Given a cell, return the cell's style
|
146
157
|
def font(row, col, sheet=nil)
|
147
|
-
sheet
|
158
|
+
sheet ||= @default_sheet
|
148
159
|
read_cells(sheet) unless @cells_read[sheet]
|
149
160
|
row,col = normalize(row,col)
|
150
161
|
style_name = @style[sheet][[row,col]] || @style_defaults[sheet][col - 1] || 'Default'
|
151
162
|
@style_definitions[style_name]
|
152
|
-
end
|
153
|
-
|
154
|
-
# set a cell to a certain value
|
155
|
-
# (this will not be saved back to the spreadsheet file!)
|
156
|
-
def set(row,col,value,sheet=nil) #:nodoc:
|
157
|
-
sheet = @default_sheet unless sheet
|
158
|
-
read_cells(sheet) unless @cells_read[sheet]
|
159
|
-
row,col = normalize(row,col)
|
160
|
-
set_value(row,col,value,sheet)
|
161
|
-
if value.class == Fixnum
|
162
|
-
set_type(row,col,:float,sheet)
|
163
|
-
elsif value.class == String
|
164
|
-
set_type(row,col,:string,sheet)
|
165
|
-
elsif value.class == Float
|
166
|
-
set_type(row,col,:string,sheet)
|
167
|
-
else
|
168
|
-
raise ArgumentError, "Type for "+value.to_s+" not set"
|
169
|
-
end
|
170
163
|
end
|
171
164
|
|
172
165
|
# returns the type of a cell:
|
@@ -178,7 +171,7 @@ class Openoffice < GenericSpreadsheet
|
|
178
171
|
# * :time
|
179
172
|
# * :datetime
|
180
173
|
def celltype(row,col,sheet=nil)
|
181
|
-
sheet
|
174
|
+
sheet ||= @default_sheet
|
182
175
|
read_cells(sheet) unless @cells_read[sheet]
|
183
176
|
row,col = normalize(row,col)
|
184
177
|
if @formula[sheet][[row,col]]
|
@@ -195,8 +188,8 @@ class Openoffice < GenericSpreadsheet
|
|
195
188
|
end
|
196
189
|
return_sheets
|
197
190
|
end
|
198
|
-
|
199
|
-
# version of the
|
191
|
+
|
192
|
+
# version of the Roo::Openoffice document
|
200
193
|
# at 2007 this is always "1.0"
|
201
194
|
def officeversion
|
202
195
|
oo_version
|
@@ -206,7 +199,7 @@ class Openoffice < GenericSpreadsheet
|
|
206
199
|
# shows the internal representation of all cells
|
207
200
|
# mainly for debugging purposes
|
208
201
|
def to_s(sheet=nil)
|
209
|
-
sheet
|
202
|
+
sheet ||= @default_sheet
|
210
203
|
read_cells(sheet) unless @cells_read[sheet]
|
211
204
|
@cell[sheet].inspect
|
212
205
|
end
|
@@ -214,13 +207,13 @@ class Openoffice < GenericSpreadsheet
|
|
214
207
|
# returns the row,col values of the labelled cell
|
215
208
|
# (nil,nil) if label is not defined
|
216
209
|
def label(labelname)
|
217
|
-
read_labels
|
210
|
+
read_labels
|
218
211
|
unless @label.size > 0
|
219
212
|
return nil,nil,nil
|
220
213
|
end
|
221
214
|
if @label.has_key? labelname
|
222
215
|
return @label[labelname][1].to_i,
|
223
|
-
GenericSpreadsheet.letter_to_number(@label[labelname][2]),
|
216
|
+
Roo::GenericSpreadsheet.letter_to_number(@label[labelname][2]),
|
224
217
|
@label[labelname][0]
|
225
218
|
else
|
226
219
|
return nil,nil,nil
|
@@ -228,24 +221,22 @@ class Openoffice < GenericSpreadsheet
|
|
228
221
|
end
|
229
222
|
|
230
223
|
# Returns an array which all labels. Each element is an array with
|
231
|
-
# [labelname, [
|
224
|
+
# [labelname, [row,col,sheetname]]
|
232
225
|
def labels(sheet=nil)
|
233
|
-
read_labels
|
234
|
-
|
235
|
-
|
236
|
-
result << [ label[0], # name
|
226
|
+
read_labels
|
227
|
+
@label.map do |label|
|
228
|
+
[ label[0], # name
|
237
229
|
[ label[1][1].to_i, # row
|
238
|
-
GenericSpreadsheet.letter_to_number(label[1][2]), # column
|
230
|
+
Roo::GenericSpreadsheet.letter_to_number(label[1][2]), # column
|
239
231
|
label[1][0], # sheet
|
240
232
|
] ]
|
241
233
|
end
|
242
|
-
result
|
243
234
|
end
|
244
235
|
|
245
236
|
# returns the comment at (row/col)
|
246
237
|
# nil if there is no comment
|
247
238
|
def comment(row,col,sheet=nil)
|
248
|
-
sheet
|
239
|
+
sheet ||= @default_sheet
|
249
240
|
read_cells(sheet) unless @cells_read[sheet]
|
250
241
|
row,col = normalize(row,col)
|
251
242
|
return nil unless @comment[sheet]
|
@@ -254,7 +245,7 @@ class Openoffice < GenericSpreadsheet
|
|
254
245
|
|
255
246
|
# true, if there is a comment
|
256
247
|
def comment?(row,col,sheet=nil)
|
257
|
-
sheet
|
248
|
+
sheet ||= @default_sheet
|
258
249
|
read_cells(sheet) unless @cells_read[sheet]
|
259
250
|
row,col = normalize(row,col)
|
260
251
|
comment(row,col) != nil
|
@@ -264,7 +255,7 @@ class Openoffice < GenericSpreadsheet
|
|
264
255
|
# returns each comment in the selected sheet as an array of elements
|
265
256
|
# [row, col, comment]
|
266
257
|
def comments(sheet=nil)
|
267
|
-
sheet
|
258
|
+
sheet ||= @default_sheet
|
268
259
|
read_comments(sheet) unless @comments_read[sheet]
|
269
260
|
if @comment[sheet]
|
270
261
|
@comment[sheet].each.collect do |elem|
|
@@ -285,10 +276,10 @@ class Openoffice < GenericSpreadsheet
|
|
285
276
|
end
|
286
277
|
|
287
278
|
# helper function to set the internal representation of cells
|
288
|
-
def set_cell_values(sheet,x,y,i,v,
|
289
|
-
key = [y,x+i]
|
279
|
+
def set_cell_values(sheet,x,y,i,v,value_type,formula,table_cell,str_v,style_name)
|
280
|
+
key = [y,x+i]
|
290
281
|
@cell_type[sheet] = {} unless @cell_type[sheet]
|
291
|
-
@cell_type[sheet][key] = Openoffice.oo_type_2_roo_type(
|
282
|
+
@cell_type[sheet][key] = Roo::Openoffice.oo_type_2_roo_type(value_type)
|
292
283
|
@formula[sheet] = {} unless @formula[sheet]
|
293
284
|
if formula
|
294
285
|
['of:', 'oooc:'].each do |prefix|
|
@@ -332,10 +323,9 @@ class Openoffice < GenericSpreadsheet
|
|
332
323
|
# some content <text:s text:c="3"/>
|
333
324
|
#++
|
334
325
|
def read_cells(sheet=nil)
|
335
|
-
sheet
|
326
|
+
sheet ||= @default_sheet
|
327
|
+
validate_sheet!(sheet)
|
336
328
|
sheet_found = false
|
337
|
-
raise ArgumentError, "Error: sheet '#{sheet||'nil'}' not valid" if @default_sheet == nil and sheet==nil
|
338
|
-
raise RangeError unless self.sheets.include? sheet
|
339
329
|
|
340
330
|
@doc.xpath("//*[local-name()='table']").each do |ws|
|
341
331
|
if sheet == ws['name']
|
@@ -345,7 +335,7 @@ class Openoffice < GenericSpreadsheet
|
|
345
335
|
ws.children.each do |table_element|
|
346
336
|
case table_element.name
|
347
337
|
when 'table-column'
|
348
|
-
@style_defaults[sheet] << table_element.attributes['default-cell-style-name']
|
338
|
+
@style_defaults[sheet] << table_element.attributes['default-cell-style-name']
|
349
339
|
when 'table-row'
|
350
340
|
if table_element.attributes['number-rows-repeated']
|
351
341
|
skip_row = table_element.attributes['number-rows-repeated'].to_s.to_i
|
@@ -354,10 +344,11 @@ class Openoffice < GenericSpreadsheet
|
|
354
344
|
table_element.children.each do |cell|
|
355
345
|
skip_col = cell['number-columns-repeated']
|
356
346
|
formula = cell['formula']
|
357
|
-
|
347
|
+
value_type = cell['value-type']
|
358
348
|
v = cell['value']
|
359
349
|
style_name = cell['style-name']
|
360
|
-
|
350
|
+
case value_type
|
351
|
+
when 'string'
|
361
352
|
str_v = ''
|
362
353
|
# insert \n if there is more than one paragraph
|
363
354
|
para_count = 0
|
@@ -401,34 +392,34 @@ class Openoffice < GenericSpreadsheet
|
|
401
392
|
str_v = CGI.unescapeHTML(str_v)
|
402
393
|
end # == 'p'
|
403
394
|
end
|
404
|
-
|
395
|
+
when 'time'
|
405
396
|
cell.children.each do |str|
|
406
397
|
if str.name == 'p'
|
407
398
|
v = str.content
|
408
399
|
end
|
409
400
|
end
|
410
|
-
|
401
|
+
when '', nil
|
411
402
|
#
|
412
|
-
|
403
|
+
when 'date'
|
413
404
|
#
|
414
|
-
|
405
|
+
when 'percentage'
|
415
406
|
#
|
416
|
-
|
407
|
+
when 'float'
|
417
408
|
#
|
418
|
-
|
409
|
+
when 'boolean'
|
419
410
|
v = cell.attributes['boolean-value'].to_s
|
420
411
|
else
|
421
|
-
# raise "unknown type #{
|
412
|
+
# raise "unknown type #{value_type}"
|
422
413
|
end
|
423
414
|
if skip_col
|
424
415
|
if v != nil or cell.attributes['date-value']
|
425
416
|
0.upto(skip_col.to_i-1) do |i|
|
426
|
-
set_cell_values(sheet,col,row,i,v,
|
417
|
+
set_cell_values(sheet,col,row,i,v,value_type,formula,cell,str_v,style_name)
|
427
418
|
end
|
428
419
|
end
|
429
420
|
col += (skip_col.to_i - 1)
|
430
421
|
end # if skip
|
431
|
-
set_cell_values(sheet,col,row,0,v,
|
422
|
+
set_cell_values(sheet,col,row,0,v,value_type,formula,cell,str_v,style_name)
|
432
423
|
col += 1
|
433
424
|
end
|
434
425
|
row += 1
|
@@ -447,34 +438,32 @@ class Openoffice < GenericSpreadsheet
|
|
447
438
|
@comments_read[sheet] = true
|
448
439
|
end
|
449
440
|
|
450
|
-
# Only calls read_cells because GenericSpreadsheet calls read_comments
|
451
|
-
# whereas the reading of comments is done in read_cells for Openoffice-objects
|
441
|
+
# Only calls read_cells because Roo::GenericSpreadsheet calls read_comments
|
442
|
+
# whereas the reading of comments is done in read_cells for Roo::Openoffice-objects
|
452
443
|
def read_comments(sheet=nil)
|
453
444
|
read_cells(sheet)
|
454
445
|
end
|
455
|
-
|
446
|
+
|
456
447
|
def read_labels
|
457
|
-
@doc.xpath("//table:named-range").
|
448
|
+
@label ||= Hash[@doc.xpath("//table:named-range").map do |ne|
|
458
449
|
#-
|
459
450
|
# $Sheet1.$C$5
|
460
451
|
#+
|
461
452
|
name = ne.attribute('name').to_s
|
462
|
-
sheetname,coords = ne.attribute('cell-range-address').to_s.split('
|
463
|
-
col = coords.split('$')
|
464
|
-
row = coords.split('$')[2]
|
453
|
+
sheetname,coords = ne.attribute('cell-range-address').to_s.split('.$')
|
454
|
+
col, row = coords.split('$')
|
465
455
|
sheetname = sheetname[1..-1] if sheetname[0,1] == '$'
|
466
|
-
|
467
|
-
end
|
468
|
-
@labels_read = true
|
456
|
+
[name, [sheetname,row,col]]
|
457
|
+
end]
|
469
458
|
end
|
470
|
-
|
459
|
+
|
471
460
|
def read_styles(style_elements)
|
472
|
-
@style_definitions['Default'] = Openoffice::Font.new
|
461
|
+
@style_definitions['Default'] = Roo::Openoffice::Font.new
|
473
462
|
style_elements.each do |style|
|
474
463
|
next unless style.name == 'style'
|
475
464
|
style_name = style.attributes['name']
|
476
465
|
style.each do |properties|
|
477
|
-
font = Openoffice::Font.new
|
466
|
+
font = Roo::Openoffice::Font.new
|
478
467
|
font.bold = properties.attributes['font-weight']
|
479
468
|
font.italic = properties.attributes['font-style']
|
480
469
|
font.underline = properties.attributes['text-underline-style']
|
@@ -482,50 +471,6 @@ class Openoffice < GenericSpreadsheet
|
|
482
471
|
end
|
483
472
|
end
|
484
473
|
end
|
485
|
-
|
486
|
-
# Checks if the default_sheet exists. If not an RangeError exception is
|
487
|
-
# raised
|
488
|
-
def check_default_sheet
|
489
|
-
sheet_found = false
|
490
|
-
raise ArgumentError, "Error: default_sheet not set" if @default_sheet == nil
|
491
|
-
sheet_found = true if sheets.include?(@default_sheet)
|
492
|
-
if ! sheet_found
|
493
|
-
raise RangeError, "sheet '#{@default_sheet}' not found"
|
494
|
-
end
|
495
|
-
end
|
496
|
-
|
497
|
-
def process_zipfile(zip, path='')
|
498
|
-
if zip.file.file? path
|
499
|
-
if path == "content.xml"
|
500
|
-
open(File.join(@tmpdir, @file_nr.to_s+'_roo_content.xml'),'wb') {|f|
|
501
|
-
f << zip.read(path)
|
502
|
-
}
|
503
|
-
end
|
504
|
-
else
|
505
|
-
unless path.empty?
|
506
|
-
path += '/'
|
507
|
-
end
|
508
|
-
zip.dir.foreach(path) do |filename|
|
509
|
-
process_zipfile(zip, path+filename)
|
510
|
-
end
|
511
|
-
end
|
512
|
-
end
|
513
|
-
|
514
|
-
def extract_content
|
515
|
-
Zip::ZipFile.open(@filename) do |zip|
|
516
|
-
process_zipfile(zip)
|
517
|
-
end
|
518
|
-
end
|
519
|
-
|
520
|
-
def set_value(row,col,value,sheet=nil)
|
521
|
-
sheet = @default_value unless sheet
|
522
|
-
@cell[sheet][[row,col]] = value
|
523
|
-
end
|
524
|
-
|
525
|
-
def set_type(row,col,type,sheet=nil)
|
526
|
-
sheet = @default_value unless sheet
|
527
|
-
@cell_type[sheet][[row,col]] = type
|
528
|
-
end
|
529
474
|
|
530
475
|
A_ROO_TYPE = {
|
531
476
|
"float" => :float,
|
@@ -535,10 +480,10 @@ class Openoffice < GenericSpreadsheet
|
|
535
480
|
"time" => :time,
|
536
481
|
}
|
537
482
|
|
538
|
-
def
|
483
|
+
def self.oo_type_2_roo_type(ootype)
|
539
484
|
return A_ROO_TYPE[ootype]
|
540
485
|
end
|
541
|
-
|
486
|
+
|
542
487
|
# helper method to convert compressed spaces and other elements within
|
543
488
|
# an text into a string
|
544
489
|
def children_to_string(children)
|
@@ -564,6 +509,6 @@ class Openoffice < GenericSpreadsheet
|
|
564
509
|
|
565
510
|
end # class
|
566
511
|
|
567
|
-
# Libreoffice is just an alias for Openoffice class
|
568
|
-
class Libreoffice < Openoffice
|
512
|
+
# Libreoffice is just an alias for Roo::Openoffice class
|
513
|
+
class Roo::Libreoffice < Roo::Openoffice
|
569
514
|
end
|