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/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
|