roo 0.6.1 → 0.7.0
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/History.txt +9 -0
- data/lib/roo/excel.rb +230 -58
- data/lib/roo/openoffice.rb +334 -158
- data/lib/roo/version.rb +2 -2
- data/test/numbers1.xls +0 -0
- data/test/test_roo.rb +822 -224
- data/website/index.html +8 -11
- data/website/index.txt +5 -4
- metadata +82 -75
data/History.txt
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
== 0.7.0 2007-11-23
|
2
|
+
* 6 enhancements:
|
3
|
+
* Openoffice/Excel: the most methods can be called with an option 'sheet'
|
4
|
+
parameter which will be used instead of the default sheet
|
5
|
+
* Excel: improved the speed of CVS output
|
6
|
+
* Openoffice/Excel: new method #column
|
7
|
+
* Openoffice/Excel: new method #find
|
8
|
+
* Openoffice/Excel: new method #info
|
9
|
+
* better exception if a spreadsheet file does not exist
|
1
10
|
== 0.6.1 2007-10-06
|
2
11
|
* 2 enhancements:
|
3
12
|
* Openoffice: percentage-values are now treated as numbers (not strings)
|
data/lib/roo/excel.rb
CHANGED
@@ -2,8 +2,23 @@ require 'rubygems'
|
|
2
2
|
gem 'parseexcel', '>= 0.5.2'
|
3
3
|
require 'parseexcel'
|
4
4
|
|
5
|
+
module Spreadsheet
|
6
|
+
module ParseExcel
|
7
|
+
class Worksheet
|
8
|
+
include Enumerable
|
9
|
+
attr_reader :min_row, :max_row, :min_col, :max_col
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
# Class Excel is derived from class Openoffice. It implements almost all methods
|
16
|
+
# from the Openoffice class in the same way.
|
17
|
+
# Parameter packed: :zip - File is a zip-file
|
5
18
|
class Excel < Openoffice
|
6
19
|
|
20
|
+
EXCEL_NO_FORMULAS = 'formulas are not supported for excel spreadsheets'
|
21
|
+
|
7
22
|
def initialize(filename, packed = nil)
|
8
23
|
@tmpdir = "oo_"+$$.to_s
|
9
24
|
unless File.exists?(@tmpdir)
|
@@ -15,28 +30,35 @@ class Excel < Openoffice
|
|
15
30
|
warn "are you sure, this is an excel file?"
|
16
31
|
end
|
17
32
|
@filename = filename
|
33
|
+
unless File.file?(@filename)
|
34
|
+
raise IOError, "file #{@filename} does not exist"
|
35
|
+
end
|
18
36
|
@workbook = Spreadsheet::ParseExcel.parse(filename)
|
19
37
|
@default_sheet = nil
|
20
38
|
# no need to set default_sheet if there is only one sheet in the document
|
21
39
|
if self.sheets.size == 1
|
22
40
|
@default_sheet = self.sheets.first
|
23
41
|
end
|
24
|
-
@first_row = @last_row = @first_column = @last_column = nil
|
42
|
+
# @first_row = @last_row = @first_column = @last_column = nil
|
43
|
+
#if ENV["roo_local"] != "thomas-p"
|
44
|
+
FileUtils::rm_r(@tmpdir)
|
45
|
+
#end
|
46
|
+
@first_row = Hash.new
|
47
|
+
@last_row = Hash.new
|
48
|
+
@first_column = Hash.new
|
49
|
+
@last_column = Hash.new
|
50
|
+
@cells_read = Hash.new
|
25
51
|
end
|
26
52
|
|
27
53
|
def sheets
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
result
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
)
|
37
|
-
end
|
38
|
-
return result
|
39
|
-
#end
|
54
|
+
result = []
|
55
|
+
0.upto(@workbook.sheet_count - 1) do |i|
|
56
|
+
# TODO: is there a better way to do conversion?
|
57
|
+
result << Iconv.new('utf-8','unicode').iconv(
|
58
|
+
@workbook.worksheet(i).name
|
59
|
+
)
|
60
|
+
end
|
61
|
+
return result
|
40
62
|
end
|
41
63
|
|
42
64
|
# sets the working sheet (1,2,3,..)
|
@@ -50,14 +72,15 @@ class Excel < Openoffice
|
|
50
72
|
else
|
51
73
|
raise TypeError, "what are you trying to set as default sheet?"
|
52
74
|
end
|
53
|
-
@first_row = @last_row = @first_column = @last_column = nil
|
54
|
-
@cells_read = false
|
75
|
+
@first_row[n] = @last_row[n] = @first_column[n] = @last_column[n] = nil
|
76
|
+
@cells_read[n] = false
|
55
77
|
end
|
56
78
|
|
57
79
|
# returns the content of a cell. The upper left corner is (1,1) or ('A',1)
|
58
|
-
def cell(row,col)
|
80
|
+
def cell(row,col,sheet=nil)
|
81
|
+
sheet = @default_sheet unless sheet
|
59
82
|
row,col = normalize(row,col)
|
60
|
-
worksheet = @workbook.worksheet(sheet_no(
|
83
|
+
worksheet = @workbook.worksheet(sheet_no(sheet))
|
61
84
|
skip = 0
|
62
85
|
line = 1
|
63
86
|
worksheet.each(skip) { |row_par|
|
@@ -72,90 +95,163 @@ class Excel < Openoffice
|
|
72
95
|
when :text then return cell.to_s('utf-8')
|
73
96
|
when :date then return cell.date
|
74
97
|
else
|
75
|
-
return cell.to_s('utf-8')
|
98
|
+
return nil # cell.to_s('utf-8')
|
76
99
|
end
|
77
100
|
end
|
78
101
|
line += 1
|
79
102
|
}
|
80
103
|
end
|
81
104
|
|
82
|
-
# returns the type of a cell:
|
83
|
-
def celltype(row,col)
|
105
|
+
# returns the type of a cell: :float, :string, :date
|
106
|
+
def celltype(row,col,sheet=nil)
|
107
|
+
default_sheet_check if sheet == nil
|
108
|
+
sheet = @default_sheet unless sheet
|
84
109
|
row,col = normalize(row,col)
|
85
|
-
|
86
|
-
worksheet = @workbook.worksheet(sheet_no(
|
110
|
+
|
111
|
+
worksheet = @workbook.worksheet(sheet_no(sheet))
|
87
112
|
skip = 0
|
88
113
|
line = 1
|
89
114
|
worksheet.each(skip) { |row_par|
|
90
115
|
if line == row
|
116
|
+
return nil unless row_par
|
91
117
|
cell = row_par.at(col-1)
|
92
118
|
return nil unless cell
|
93
119
|
case cell.type
|
94
|
-
when :numeric
|
95
|
-
|
96
|
-
when :
|
97
|
-
|
120
|
+
when :numeric
|
121
|
+
return :float
|
122
|
+
when :text
|
123
|
+
return :string
|
124
|
+
when :date
|
125
|
+
return :date
|
126
|
+
else
|
127
|
+
return cell.type.to_sym
|
98
128
|
end
|
99
129
|
end
|
100
130
|
line += 1
|
101
131
|
}
|
102
132
|
end
|
103
133
|
|
104
|
-
#
|
105
|
-
|
134
|
+
# returns all values in this row as an array
|
135
|
+
# row numbers are 1,2,3,... like in the spreadsheet
|
136
|
+
def row(rownumber,sheet=nil)
|
137
|
+
sheet = @default_sheet unless sheet
|
106
138
|
default_sheet_check
|
107
|
-
worksheet = @workbook.worksheet(sheet_no(
|
108
|
-
therow = worksheet.row(rownumber-1)
|
139
|
+
worksheet = @workbook.worksheet(sheet_no(sheet))
|
140
|
+
#therow = worksheet.row(rownumber-1)
|
109
141
|
result = []
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
142
|
+
worksheet.row(rownumber-1).each {|cell|
|
143
|
+
if cell
|
144
|
+
case cell.type
|
145
|
+
when :numeric then result << cell.to_i
|
146
|
+
when :text then result << cell.to_s('utf-8')
|
147
|
+
when :date then result << cell.date
|
148
|
+
else
|
149
|
+
result << cell.to_s('utf-8')
|
150
|
+
end
|
115
151
|
else
|
116
|
-
|
152
|
+
result << nil
|
117
153
|
end
|
118
154
|
}
|
119
155
|
return result
|
120
156
|
end
|
121
157
|
|
158
|
+
# returns all values in this column as an array
|
159
|
+
# column numbers are 1,2,3,... like in the spreadsheet
|
160
|
+
def column(columnnumber,sheet=nil)
|
161
|
+
if columnnumber.class == String
|
162
|
+
columnnumber = Openoffice.letter_to_number(columnnumber)
|
163
|
+
end
|
164
|
+
sheet = @default_sheet unless sheet
|
165
|
+
default_sheet_check
|
166
|
+
worksheet = @workbook.worksheet(sheet_no(sheet))
|
167
|
+
skip = 0
|
168
|
+
result = []
|
169
|
+
worksheet.each(skip) { |row_par|
|
170
|
+
if defined? row_par.at(columnnumber-1)
|
171
|
+
cell = row_par.at(columnnumber-1)
|
172
|
+
#if defined? cell = row_par.at(columnnumber-1)
|
173
|
+
if cell
|
174
|
+
case cell.type
|
175
|
+
when :numeric then result << cell.to_i
|
176
|
+
when :text then result << cell.to_s('utf-8')
|
177
|
+
when :date then result << cell.date
|
178
|
+
else
|
179
|
+
result << cell.to_s('utf-8')
|
180
|
+
end
|
181
|
+
else
|
182
|
+
result << nil
|
183
|
+
end
|
184
|
+
else
|
185
|
+
result << nil
|
186
|
+
end
|
187
|
+
}
|
188
|
+
result
|
189
|
+
end
|
190
|
+
|
122
191
|
# returns the first non empty column
|
123
|
-
def first_column
|
124
|
-
|
125
|
-
|
192
|
+
def first_column(sheet=nil)
|
193
|
+
sheet = @default_sheet unless sheet
|
194
|
+
return @first_column[sheet] if @first_column[sheet]
|
195
|
+
fr, lr, fc, lc = get_firsts_lasts(sheet)
|
126
196
|
fc
|
127
197
|
end
|
128
198
|
|
129
199
|
# returns the last non empty column
|
130
|
-
def last_column
|
131
|
-
|
132
|
-
|
200
|
+
def last_column(sheet=nil)
|
201
|
+
sheet = @default_sheet unless sheet
|
202
|
+
return @last_column[sheet] if @last_column[sheet]
|
203
|
+
fr, lr, fc, lc = get_firsts_lasts(sheet)
|
133
204
|
lc
|
134
205
|
end
|
135
206
|
|
136
207
|
# returns the first non empty row
|
137
|
-
def first_row
|
138
|
-
|
139
|
-
|
208
|
+
def first_row(sheet=nil)
|
209
|
+
sheet = @default_sheet unless sheet
|
210
|
+
return @first_row[sheet] if @first_row[sheet]
|
211
|
+
fr, lr, fc, lc = get_firsts_lasts(sheet)
|
140
212
|
fr
|
141
213
|
end
|
142
214
|
|
143
215
|
# returns the last non empty row
|
144
|
-
def last_row
|
145
|
-
|
146
|
-
|
216
|
+
def last_row(sheet=nil)
|
217
|
+
sheet = @default_sheet unless sheet
|
218
|
+
return @last_row[sheet] if @last_row[sheet]
|
219
|
+
fr, lr, fc, lc = get_firsts_lasts(sheet)
|
147
220
|
lr
|
148
221
|
end
|
149
222
|
|
150
223
|
# true if a cell is empty
|
151
|
-
def empty?(row, col)
|
224
|
+
def empty?(row, col, sheet=nil)
|
225
|
+
sheet = @default_sheet unless sheet
|
152
226
|
row,col = normalize(row,col)
|
153
|
-
return true if row < first_row || row > last_row || col < first_column || col > last_column
|
154
|
-
return true unless cell(row, col)
|
155
|
-
return true if celltype(row, col) == "string" && cell(row, col) == ""
|
227
|
+
return true if row < first_row(sheet) || row > last_row(sheet) || col < first_column(sheet) || col > last_column(sheet)
|
228
|
+
return true unless cell(row, col, sheet)
|
229
|
+
return true if celltype(row, col, sheet) == "string" && cell(row, col, sheet) == ""
|
156
230
|
false
|
157
231
|
end
|
158
232
|
|
233
|
+
# first non-empty column as a letter
|
234
|
+
def first_column_as_letter(sheet=nil)
|
235
|
+
sheet = @default_sheet unless sheet
|
236
|
+
Openoffice.number_to_letter(first_column(sheet))
|
237
|
+
end
|
238
|
+
|
239
|
+
# last non-empty column as a letter
|
240
|
+
def last_column_as_letter(sheet=nil)
|
241
|
+
sheet = @default_sheet unless sheet
|
242
|
+
Openoffice.number_to_letter(last_column(sheet))
|
243
|
+
end
|
244
|
+
|
245
|
+
def formula(row,col,sheet=nil)
|
246
|
+
raise EXCEL_NO_FORMULAS
|
247
|
+
end
|
248
|
+
def formula?(row,col,sheet=nil)
|
249
|
+
raise EXCEL_NO_FORMULAS
|
250
|
+
end
|
251
|
+
def formulas(sheet=nil)
|
252
|
+
raise EXCEL_NO_FORMULAS
|
253
|
+
end
|
254
|
+
|
159
255
|
private
|
160
256
|
|
161
257
|
# check if default_sheet was set
|
@@ -164,14 +260,33 @@ private
|
|
164
260
|
end
|
165
261
|
|
166
262
|
# determine the first and last boundaries
|
167
|
-
def get_firsts_lasts
|
263
|
+
def get_firsts_lasts(sheet=nil)
|
264
|
+
sheet = @default_sheet unless sheet
|
168
265
|
fr = fc = 999_999
|
169
266
|
lr = lc = -999_999
|
170
|
-
worksheet = @workbook.worksheet(sheet_no(@default_sheet))
|
267
|
+
#TODO: worksheet = @workbook.worksheet(sheet_no(@default_sheet))
|
268
|
+
worksheet = @workbook.worksheet(sheet_no(sheet))
|
269
|
+
if false #=============================================================
|
270
|
+
if @filename == "test/false_encoding.xls"
|
271
|
+
#assert_instance_of(Spreadsheet::ParseExcel::Worksheet, worksheet)
|
272
|
+
p worksheet.class
|
273
|
+
|
274
|
+
p worksheet.methods
|
275
|
+
p '### min_row: '+worksheet.min_row.to_s
|
276
|
+
p '### max_row: '+worksheet.max_row.to_s
|
277
|
+
p '### min_col: '+worksheet.min_col.to_s
|
278
|
+
p '### max_col: '+worksheet.max_col.to_s
|
279
|
+
end
|
280
|
+
if @filename == "test/false_encoding.xls"
|
281
|
+
p worksheet
|
282
|
+
end
|
171
283
|
skip = 0
|
172
284
|
line = 1
|
173
285
|
worksheet.each(skip) { |row_par|
|
174
286
|
if row_par
|
287
|
+
if @filename == "test/false_encoding.xls"
|
288
|
+
p row_par
|
289
|
+
end
|
175
290
|
row_par.each_with_index {|cell,i|
|
176
291
|
# nicht beruecksichtigen, wenn nil und vorher noch nichts war
|
177
292
|
if cell
|
@@ -184,10 +299,23 @@ private
|
|
184
299
|
end
|
185
300
|
line += 1
|
186
301
|
}
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
302
|
+
end #=============================================================
|
303
|
+
fr = worksheet.min_row + 1
|
304
|
+
lr = worksheet.max_row + 1
|
305
|
+
fc = worksheet.min_col + 1
|
306
|
+
lc = worksheet.max_col + 1
|
307
|
+
# 2007-11-05 BEGIN
|
308
|
+
# parsexcel liefert (mir unverstaendlich) eine Zeile als letzte Zeile
|
309
|
+
# zurueck, die aber leer ist. Deshalb Korrekturfunktion, die wirklich
|
310
|
+
# die letzte nicht leere Zeile liefert.
|
311
|
+
while empty_row? row(lr,sheet)
|
312
|
+
lr -= 1
|
313
|
+
end
|
314
|
+
# 2007-11-05 END
|
315
|
+
@first_row[sheet] = fr
|
316
|
+
@last_row[sheet] = lr
|
317
|
+
@first_column[sheet] = fc
|
318
|
+
@last_column[sheet] = lc
|
191
319
|
return fr, lr, fc, lc
|
192
320
|
end
|
193
321
|
|
@@ -204,4 +332,48 @@ private
|
|
204
332
|
raise StandardError, "sheet '#{name}' not found"
|
205
333
|
end
|
206
334
|
|
335
|
+
def write_csv_content(file=nil,sheet=nil)
|
336
|
+
file = STDOUT unless file
|
337
|
+
sheet = @default_sheet unless sheet
|
338
|
+
worksheet = @workbook.worksheet(sheet_no(sheet))
|
339
|
+
skip = 0
|
340
|
+
worksheet.each(skip) { |row_par|
|
341
|
+
1.upto(row_par.length) {|col|
|
342
|
+
file.print(",") if col > 1
|
343
|
+
cell = row_par.at(col-1)
|
344
|
+
unless cell
|
345
|
+
empty = true
|
346
|
+
else
|
347
|
+
case cell.type
|
348
|
+
when :numeric
|
349
|
+
onecelltype = :float
|
350
|
+
onecell = cell.to_f
|
351
|
+
when :text
|
352
|
+
onecelltype = :string
|
353
|
+
onecell = cell.to_s('utf-8')
|
354
|
+
when :date
|
355
|
+
onecelltype = :date
|
356
|
+
onecell = cell.date
|
357
|
+
else
|
358
|
+
onecelltype = nil
|
359
|
+
onecell = nil
|
360
|
+
end
|
361
|
+
end
|
362
|
+
file.print one_cell_output(onecelltype,onecell,empty)
|
363
|
+
}
|
364
|
+
file.print("\n")
|
365
|
+
}
|
366
|
+
end
|
367
|
+
|
368
|
+
def empty_row?(row)
|
369
|
+
content = false
|
370
|
+
row.each {|elem|
|
371
|
+
if elem != ''
|
372
|
+
#if elem.class == String and elem.size > 0
|
373
|
+
content = true
|
374
|
+
end
|
375
|
+
}
|
376
|
+
! content
|
377
|
+
end
|
378
|
+
|
207
379
|
end
|
data/lib/roo/openoffice.rb
CHANGED
@@ -4,16 +4,19 @@ require 'rexml/document'
|
|
4
4
|
require 'fileutils'
|
5
5
|
require 'zip/zipfilesystem'
|
6
6
|
require 'date'
|
7
|
-
#require 'llip'
|
8
7
|
require 'base64'
|
9
|
-
require 'logger'
|
10
8
|
|
11
|
-
#
|
9
|
+
# The class Openoffice defines the basic functionality for the access to
|
10
|
+
# spreadsheet documents. Other classes like _Excel_ are defined as subclasses
|
11
|
+
# of this class.
|
12
12
|
|
13
13
|
class Openoffice
|
14
14
|
|
15
15
|
@@nr = 0
|
16
16
|
|
17
|
+
# sets the line with attribute names (default: 1)
|
18
|
+
attr_accessor :header_line
|
19
|
+
|
17
20
|
# initialization and opening of a spreadsheet file
|
18
21
|
# values for packed: :zip
|
19
22
|
def initialize(filename, packed=nil) #, create = false)
|
@@ -29,17 +32,18 @@ class Openoffice
|
|
29
32
|
#if create and ! File.exists?(filename)
|
30
33
|
# self.create_openoffice(filename)
|
31
34
|
#end
|
32
|
-
@cells_read =
|
35
|
+
@cells_read = Hash.new
|
36
|
+
#TODO: @cells_read[:default] = false
|
33
37
|
@filename = filename
|
38
|
+
unless File.file?(@filename)
|
39
|
+
raise IOError, "file #{@filename} does not exist"
|
40
|
+
end
|
34
41
|
@@nr += 1
|
35
42
|
@file_nr = @@nr
|
36
43
|
extract_content
|
37
44
|
file = File.new(File.join(@tmpdir, @file_nr.to_s+"_roo_content.xml"))
|
38
45
|
@doc = REXML::Document.new file
|
39
46
|
file.close
|
40
|
-
@cell = Hash.new
|
41
|
-
@cell_type = Hash.new
|
42
|
-
@formula = Hash.new
|
43
47
|
#if ENV["roo_local"] != "thomas-p"
|
44
48
|
FileUtils::rm_r(@tmpdir)
|
45
49
|
#end
|
@@ -48,15 +52,18 @@ class Openoffice
|
|
48
52
|
if self.sheets.size == 1
|
49
53
|
@default_sheet = self.sheets.first
|
50
54
|
end
|
51
|
-
@
|
52
|
-
@
|
53
|
-
|
54
|
-
|
55
|
-
|
55
|
+
@cell = Hash.new
|
56
|
+
@cell_type = Hash.new
|
57
|
+
@formula = Hash.new
|
58
|
+
@first_row = Hash.new
|
59
|
+
@last_row = Hash.new
|
60
|
+
@first_column = Hash.new
|
61
|
+
@last_column = Hash.new
|
62
|
+
@header_line = 1
|
56
63
|
end
|
57
64
|
|
58
65
|
# creates a new empty openoffice-spreadsheet file
|
59
|
-
def create_openoffice(filename)
|
66
|
+
def create_openoffice(filename) #:nodoc:
|
60
67
|
#TODO: a better way for creating the file contents
|
61
68
|
# now you have to call mkbase64...rb to create an include file with all
|
62
69
|
# the empty files in an openoffice zip-file
|
@@ -69,70 +76,80 @@ class Openoffice
|
|
69
76
|
|
70
77
|
# reopens and read a spreadsheet document
|
71
78
|
def reload
|
72
|
-
|
79
|
+
ds = @default_sheet
|
73
80
|
initialize(@filename)
|
74
|
-
self.default_sheet =
|
75
|
-
|
81
|
+
self.default_sheet = ds
|
82
|
+
#@first_row = @last_row = @first_column = @last_column = nil
|
76
83
|
end
|
77
84
|
|
78
|
-
#
|
79
|
-
# (1,1) is the upper left corner
|
85
|
+
# Returns the content of a spreadsheet-cell.
|
86
|
+
# (1,1) is the upper left corner.
|
80
87
|
# (1,1), (1,'A'), ('A',1), ('a',1) all refers to the
|
81
|
-
# cell at first line
|
82
|
-
def cell(row,col)
|
83
|
-
|
88
|
+
# cell at the first line and first row.
|
89
|
+
def cell(row, col, sheet=nil)
|
90
|
+
sheet = @default_sheet unless sheet
|
91
|
+
read_cells(sheet) unless @cells_read[sheet]
|
84
92
|
row,col = normalize(row,col)
|
85
|
-
if celltype(row,col) == :date
|
86
|
-
yyyy,mm,dd = @cell["#{row},#{col}"].split('-')
|
93
|
+
if celltype(row,col,sheet) == :date
|
94
|
+
yyyy,mm,dd = @cell[sheet]["#{row},#{col}"].split('-')
|
87
95
|
return Date.new(yyyy.to_i,mm.to_i,dd.to_i)
|
88
96
|
end
|
89
|
-
@cell["#{row},#{col}"]
|
97
|
+
@cell[sheet]["#{row},#{col}"]
|
90
98
|
end
|
91
99
|
|
92
|
-
#
|
93
|
-
# nil if there is no formula
|
94
|
-
|
95
|
-
|
100
|
+
# Returns the formula at (row,col).
|
101
|
+
# Returns nil if there is no formula.
|
102
|
+
# The method Openoffice#formula? checks if there is a formula.
|
103
|
+
def formula(row,col,sheet=nil)
|
104
|
+
sheet = @default_sheet unless sheet
|
105
|
+
read_cells(sheet) unless @cells_read[sheet]
|
96
106
|
row,col = normalize(row,col)
|
97
|
-
if @formula["#{row},#{col}"] == nil
|
107
|
+
if @formula[sheet]["#{row},#{col}"] == nil
|
98
108
|
return nil
|
99
109
|
else
|
100
|
-
return @formula["#{row},#{col}"]["oooc:".length..-1]
|
110
|
+
return @formula[sheet]["#{row},#{col}"]["oooc:".length..-1]
|
101
111
|
end
|
102
112
|
end
|
103
113
|
|
104
114
|
# true, if there is a formula
|
105
|
-
def formula?(row,col)
|
106
|
-
|
115
|
+
def formula?(row,col,sheet=nil)
|
116
|
+
sheet = @default_sheet unless sheet
|
117
|
+
read_cells unless @cells_read[sheet]
|
107
118
|
row,col = normalize(row,col)
|
108
119
|
formula(row,col) != nil
|
109
120
|
end
|
110
121
|
|
111
122
|
# set a cell to a certain value
|
112
123
|
# (this will not be saved back to the spreadsheet file!)
|
113
|
-
def set(row,col,value)
|
114
|
-
|
124
|
+
def set(row,col,value,sheet=nil) #:nodoc:
|
125
|
+
sheet = @default_sheet unless sheet
|
126
|
+
read_cells(sheet) unless @cells_read[sheet]
|
115
127
|
row,col = normalize(row,col)
|
116
|
-
set_value(row,col,value)
|
128
|
+
set_value(row,col,value,sheet)
|
117
129
|
if value.class == Fixnum
|
118
|
-
set_type(row,col,:float)
|
130
|
+
set_type(row,col,:float,sheet)
|
119
131
|
elsif value.class == String
|
120
|
-
set_type(row,col,:string)
|
132
|
+
set_type(row,col,:string,sheet)
|
121
133
|
elsif value.class == Float
|
122
|
-
set_type(row,col,:string)
|
134
|
+
set_type(row,col,:string,sheet)
|
123
135
|
else
|
124
|
-
raise ArgumentError, "
|
136
|
+
raise ArgumentError, "Type for "+value.to_s+" not set"
|
125
137
|
end
|
126
138
|
end
|
127
139
|
|
128
|
-
# returns the
|
129
|
-
|
130
|
-
|
140
|
+
# returns the type of a cell:
|
141
|
+
# * :float
|
142
|
+
# * :string,
|
143
|
+
# * :date
|
144
|
+
# * :percentage
|
145
|
+
def celltype(row,col,sheet=nil)
|
146
|
+
sheet = @default_sheet unless sheet
|
147
|
+
read_cells(sheet) unless @cells_read[sheet]
|
131
148
|
row,col = normalize(row,col)
|
132
|
-
if @formula["#{row},#{col}"]
|
149
|
+
if @formula[sheet]["#{row},#{col}"]
|
133
150
|
return :formula
|
134
151
|
else
|
135
|
-
@cell_type["#{row},#{col}"]
|
152
|
+
@cell_type[sheet]["#{row},#{col}"]
|
136
153
|
end
|
137
154
|
end
|
138
155
|
|
@@ -175,12 +192,9 @@ class Openoffice
|
|
175
192
|
raise TypeError, "what are you trying to set as default sheet?"
|
176
193
|
end
|
177
194
|
@default_sheet = sheet
|
178
|
-
@first_row = @last_row = @first_column = @last_column = nil
|
179
|
-
@cells_read = false
|
180
|
-
@cell = Hash.new
|
181
|
-
@cell_type = Hash.new
|
182
|
-
@formula = Hash.new
|
183
195
|
check_default_sheet
|
196
|
+
@first_row[sheet] = @last_row[sheet] = @first_column[sheet] = @last_column[sheet] = nil
|
197
|
+
@cells_read[sheet] = false
|
184
198
|
end
|
185
199
|
|
186
200
|
alias set_default_sheet default_sheet=
|
@@ -195,18 +209,20 @@ class Openoffice
|
|
195
209
|
|
196
210
|
# shows the internal representation of all cells
|
197
211
|
# mainly for debugging purposes
|
198
|
-
def to_s
|
199
|
-
|
200
|
-
@
|
212
|
+
def to_s(sheet=nil)
|
213
|
+
sheet = @default_sheet unless sheet
|
214
|
+
read_cells(sheet) unless @cells_read[sheet]
|
215
|
+
@cell[sheet].inspect
|
201
216
|
end
|
202
217
|
|
203
218
|
# returns all values in this row as an array
|
204
219
|
# row numbers are 1,2,3,... like in the spreadsheet
|
205
|
-
def row(rownumber)
|
206
|
-
|
220
|
+
def row(rownumber,sheet=nil)
|
221
|
+
sheet = @default_sheet unless sheet
|
222
|
+
read_cells(sheet) unless @cells_read[sheet]
|
207
223
|
result = []
|
208
224
|
tmp_arr = []
|
209
|
-
@cell.each_pair {|key,value|
|
225
|
+
@cell[sheet].each_pair {|key,value|
|
210
226
|
y,x = key.split(',')
|
211
227
|
x = x.to_i
|
212
228
|
y = y.to_i
|
@@ -220,105 +236,129 @@ class Openoffice
|
|
220
236
|
end
|
221
237
|
result
|
222
238
|
end
|
223
|
-
|
239
|
+
|
240
|
+
# returns all values in this column as an array
|
241
|
+
# column numbers are 1,2,3,... like in the spreadsheet
|
242
|
+
def column(columnnumber,sheet=nil)
|
243
|
+
if columnnumber.class == String
|
244
|
+
columnnumber = Openoffice.letter_to_number(columnnumber)
|
245
|
+
end
|
246
|
+
sheet = @default_sheet unless sheet
|
247
|
+
read_cells(sheet) unless @cells_read[sheet]
|
248
|
+
result = []
|
249
|
+
first_row(sheet).upto(last_row(sheet)) do |row|
|
250
|
+
result << cell(row,columnnumber,sheet)
|
251
|
+
end
|
252
|
+
result
|
253
|
+
end
|
254
|
+
|
224
255
|
# returns the number of the last non-empty row
|
225
|
-
def last_row
|
226
|
-
|
227
|
-
|
228
|
-
|
256
|
+
def last_row(sheet=nil)
|
257
|
+
sheet = @default_sheet unless sheet
|
258
|
+
read_cells(sheet) unless @cells_read[sheet]
|
259
|
+
if @last_row[sheet]
|
260
|
+
return @last_row[sheet]
|
229
261
|
end
|
230
262
|
impossible_value = 0
|
231
263
|
result = impossible_value
|
232
|
-
@cell.each_pair {|key,value|
|
264
|
+
@cell[sheet].each_pair {|key,value|
|
233
265
|
y,x = key.split(',')
|
234
266
|
y = y.to_i
|
235
267
|
result = [result, y].max if value
|
236
268
|
}
|
237
269
|
result = nil if result == impossible_value
|
238
|
-
@last_row = result
|
270
|
+
@last_row[sheet] = result
|
239
271
|
result
|
240
272
|
end
|
241
273
|
|
242
274
|
# returns the number of the last non-empty column
|
243
|
-
def last_column
|
244
|
-
|
245
|
-
|
246
|
-
|
275
|
+
def last_column(sheet=nil)
|
276
|
+
sheet = @default_sheet unless sheet
|
277
|
+
read_cells(sheet) unless @cells_read[sheet]
|
278
|
+
if @last_column[sheet]
|
279
|
+
return @last_column[sheet]
|
247
280
|
end
|
248
281
|
impossible_value = 0
|
249
282
|
result = impossible_value
|
250
|
-
@cell.each_pair {|key,value|
|
283
|
+
@cell[sheet].each_pair {|key,value|
|
251
284
|
y,x = key.split(',')
|
252
285
|
x = x.to_i
|
253
286
|
result = [result, x].max if value
|
254
287
|
}
|
255
288
|
result = nil if result == impossible_value
|
256
|
-
@last_column = result
|
289
|
+
@last_column[sheet] = result
|
257
290
|
result
|
258
291
|
end
|
259
292
|
|
260
293
|
# returns the number of the first non-empty row
|
261
|
-
def first_row
|
262
|
-
|
263
|
-
|
264
|
-
|
294
|
+
def first_row(sheet=nil)
|
295
|
+
if sheet == nil
|
296
|
+
sheet = @default_sheet
|
297
|
+
end
|
298
|
+
read_cells(sheet) unless @cells_read[sheet]
|
299
|
+
if @first_row[sheet]
|
300
|
+
return @first_row[sheet]
|
265
301
|
end
|
266
302
|
impossible_value = 999_999 # more than a spreadsheet can hold
|
267
303
|
result = impossible_value
|
268
|
-
@cell.each_pair {|key,value|
|
304
|
+
@cell[sheet].each_pair {|key,value|
|
269
305
|
y,x = key.split(',')
|
270
306
|
y = y.to_i
|
271
307
|
result = [result, y].min if value
|
272
308
|
}
|
273
309
|
result = nil if result == impossible_value
|
274
|
-
@first_row = result
|
310
|
+
@first_row[sheet] = result
|
275
311
|
result
|
276
312
|
end
|
277
313
|
|
278
314
|
# returns the number of the first non-empty column
|
279
|
-
def first_column
|
280
|
-
|
281
|
-
|
282
|
-
|
315
|
+
def first_column(sheet=nil)
|
316
|
+
if sheet == nil
|
317
|
+
sheet = @default_sheet
|
318
|
+
end
|
319
|
+
read_cells(sheet) unless @cells_read[sheet]
|
320
|
+
if @first_column[sheet]
|
321
|
+
return @first_column[sheet]
|
283
322
|
end
|
284
323
|
impossible_value = 999_999 # more than a spreadsheet can hold
|
285
324
|
result = impossible_value
|
286
|
-
@cell.each_pair {|key,value|
|
325
|
+
@cell[sheet].each_pair {|key,value|
|
287
326
|
y,x = key.split(',')
|
288
327
|
x = x.to_i
|
289
328
|
result = [result, x].min if value
|
290
329
|
}
|
291
330
|
result = nil if result == impossible_value
|
292
|
-
@first_column = result
|
331
|
+
@first_column[sheet] = result
|
293
332
|
result
|
294
333
|
end
|
295
334
|
|
296
335
|
# first non-empty column as a letter
|
297
|
-
def first_column_as_letter
|
298
|
-
Openoffice.number_to_letter(first_column)
|
336
|
+
def first_column_as_letter(sheet=nil)
|
337
|
+
Openoffice.number_to_letter(first_column(sheet))
|
299
338
|
end
|
300
339
|
|
301
340
|
# last non-empty column as a letter
|
302
|
-
def last_column_as_letter
|
303
|
-
Openoffice.number_to_letter(last_column)
|
341
|
+
def last_column_as_letter(sheet=nil)
|
342
|
+
Openoffice.number_to_letter(last_column(sheet))
|
304
343
|
end
|
305
344
|
|
306
345
|
# true if cell is empty
|
307
|
-
def empty?(row, col)
|
308
|
-
|
309
|
-
|
310
|
-
return true
|
346
|
+
def empty?(row, col, sheet=nil)
|
347
|
+
sheet = @default_sheet unless sheet
|
348
|
+
read_cells(sheet) unless @cells_read[sheet]
|
349
|
+
return true unless cell(row, col, sheet)
|
350
|
+
return true if celltype(row, col, sheet) == :string && cell(row, col, sheet).empty?
|
311
351
|
false
|
312
352
|
end
|
313
353
|
|
314
354
|
# save spreadsheet
|
315
|
-
def save
|
355
|
+
def save #:nodoc:
|
316
356
|
42
|
317
357
|
end
|
318
358
|
|
319
359
|
# evaluate the formula at this cell
|
320
360
|
# experimental: DO NOT USE THIS!
|
321
|
-
def solve(row,col)
|
361
|
+
def solve(row,col) #:nodoc:
|
322
362
|
parser = SpreadsheetParser.new
|
323
363
|
visitor = Visitor.new
|
324
364
|
#puts cell(row,col)
|
@@ -332,13 +372,14 @@ class Openoffice
|
|
332
372
|
|
333
373
|
# returns each formula in the selected sheet as an array of elements
|
334
374
|
# [row, col, formula]
|
335
|
-
def formulas
|
375
|
+
def formulas(sheet=nil)
|
336
376
|
theformulas = Array.new
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
377
|
+
sheet = @default_sheet unless sheet
|
378
|
+
read_cells(sheet) unless @cells_read[sheet]
|
379
|
+
first_row(sheet).upto(last_row(sheet)) {|row|
|
380
|
+
first_column(sheet).upto(last_column(sheet)) {|col|
|
381
|
+
if formula?(row,col,sheet)
|
382
|
+
f = [row, col, formula(row,col,sheet)]
|
342
383
|
theformulas << f
|
343
384
|
end
|
344
385
|
}
|
@@ -349,19 +390,20 @@ class Openoffice
|
|
349
390
|
# returns a rectangular area (default: all cells) as yaml-output
|
350
391
|
# you can add additional attributes with the prefix parameter like:
|
351
392
|
# oo.to_yaml({"file"=>"flightdata_2007-06-26", "sheet" => "1"})
|
352
|
-
def to_yaml(prefix={}, from_row=nil, from_column=nil, to_row=nil, to_column=nil)
|
393
|
+
def to_yaml(prefix={}, from_row=nil, from_column=nil, to_row=nil, to_column=nil,sheet=nil)
|
394
|
+
sheet = @default_sheet unless sheet
|
353
395
|
result = "--- \n"
|
354
|
-
(from_row||first_row).upto(to_row||last_row) do |row|
|
355
|
-
(from_column||first_column).upto(to_column||last_column) do |col|
|
356
|
-
unless
|
396
|
+
(from_row||first_row(sheet)).upto(to_row||last_row(sheet)) do |row|
|
397
|
+
(from_column||first_column(sheet)).upto(to_column||last_column(sheet)) do |col|
|
398
|
+
unless empty?(row,col,sheet)
|
357
399
|
result << "cell_#{row}_#{col}: \n"
|
358
400
|
prefix.each {|k,v|
|
359
401
|
result << " #{k}: #{v} \n"
|
360
402
|
}
|
361
403
|
result << " row: #{row} \n"
|
362
404
|
result << " col: #{col} \n"
|
363
|
-
result << " celltype: #{self.celltype(row,col)} \n"
|
364
|
-
result << " value: #{self.cell(row,col)} \n"
|
405
|
+
result << " celltype: #{self.celltype(row,col,sheet)} \n"
|
406
|
+
result << " value: #{self.cell(row,col,sheet)} \n"
|
365
407
|
end
|
366
408
|
end
|
367
409
|
end
|
@@ -369,20 +411,120 @@ class Openoffice
|
|
369
411
|
end
|
370
412
|
|
371
413
|
# write the current spreadsheet to stdout or into a file
|
372
|
-
def to_csv(filename=nil)
|
414
|
+
def to_csv(filename=nil,sheet=nil)
|
415
|
+
sheet = @default_sheet unless sheet
|
373
416
|
if filename
|
374
417
|
file = File.open(filename,"w") # do |file|
|
375
|
-
write_csv_content(file)
|
418
|
+
write_csv_content(file,sheet)
|
376
419
|
file.close
|
377
420
|
else
|
378
|
-
write_csv_content
|
421
|
+
write_csv_content(STDOUT,sheet)
|
379
422
|
end
|
380
423
|
true
|
381
424
|
end
|
382
425
|
|
383
|
-
|
426
|
+
# find a row either by row number or a condition
|
427
|
+
# Caution: this works only within the default sheet -> set default_sheet before you call this method
|
428
|
+
# (experimental. see examples in the test_roo.rb file)
|
429
|
+
def find(*args)
|
430
|
+
result_array = false
|
431
|
+
args.each {|arg,val|
|
432
|
+
if arg.class == Hash
|
433
|
+
arg.each { |hkey,hval|
|
434
|
+
if hkey == :array and hval == true
|
435
|
+
result_array = true
|
436
|
+
end
|
437
|
+
}
|
438
|
+
end
|
439
|
+
}
|
440
|
+
column_with = {}
|
441
|
+
1.upto(last_column) do |col|
|
442
|
+
column_with[cell(@header_line,col)] = col
|
443
|
+
end
|
444
|
+
result = Array.new
|
445
|
+
#-- id
|
446
|
+
if args[0].class == Fixnum
|
447
|
+
rownum = args[0]
|
448
|
+
tmp = {}
|
449
|
+
1.upto(self.row(rownum).size) {|j|
|
450
|
+
x = ''
|
451
|
+
column_with.each { |key,val|
|
452
|
+
if val == j
|
453
|
+
x = key
|
454
|
+
end
|
455
|
+
}
|
456
|
+
tmp[x] = cell(rownum,j)
|
457
|
+
}
|
458
|
+
result = [ tmp ] # row(rownum)
|
459
|
+
#-- :all
|
460
|
+
elsif args[0] == :all
|
461
|
+
if args[1].class == Hash
|
462
|
+
args[1].each {|key,val|
|
463
|
+
if key == :conditions
|
464
|
+
column_with = {}
|
465
|
+
1.upto(last_column) do |col|
|
466
|
+
column_with[cell(@header_line,col)] = col
|
467
|
+
end
|
468
|
+
conditions = val
|
469
|
+
first_row.upto(last_row) do |i|
|
470
|
+
# are all conditions met?
|
471
|
+
found = 1
|
472
|
+
conditions.each { |key,val|
|
473
|
+
if cell(i,column_with[key]) == val
|
474
|
+
found *= 1
|
475
|
+
else
|
476
|
+
found *= 0
|
477
|
+
end
|
478
|
+
}
|
479
|
+
# p self.row(i) if found > 0
|
480
|
+
if found > 0
|
481
|
+
tmp = {}
|
482
|
+
1.upto(self.row(i).size) {|j|
|
483
|
+
x = ''
|
484
|
+
column_with.each { |key,val|
|
485
|
+
if val == j
|
486
|
+
x = key
|
487
|
+
end
|
488
|
+
}
|
489
|
+
tmp[x] = cell(i,j)
|
490
|
+
}
|
491
|
+
if result_array
|
492
|
+
result << self.row(i)
|
493
|
+
else
|
494
|
+
result << tmp
|
495
|
+
end
|
496
|
+
end
|
497
|
+
end
|
498
|
+
end # :conditions
|
499
|
+
}
|
500
|
+
end
|
501
|
+
end
|
502
|
+
result
|
503
|
+
end
|
504
|
+
|
505
|
+
# Returns information of the spreadsheet document and all sheets within
|
506
|
+
# this document.
|
507
|
+
def info
|
508
|
+
result = "File: #{@filename}\n"+
|
509
|
+
"Number of sheets: #{sheets.size}\n"+
|
510
|
+
"Sheets: #{sheets.map{|sheet| sheet+", "}.to_s[0..-3]}\n"
|
511
|
+
n = 1
|
512
|
+
sheets.each {|sheet|
|
513
|
+
self.default_sheet = sheet
|
514
|
+
result << "Sheet " + n.to_s + ":\n"
|
515
|
+
result << " First row: #{first_row}\n"
|
516
|
+
result << " Last row: #{last_row}\n"
|
517
|
+
result << " First column: #{Openoffice.number_to_letter(first_column)}\n"
|
518
|
+
result << " Last column: #{Openoffice.number_to_letter(last_column)}"
|
519
|
+
result << "\n" if sheet != sheets.last
|
520
|
+
n += 1
|
521
|
+
}
|
522
|
+
result
|
523
|
+
end
|
384
524
|
|
385
|
-
|
525
|
+
private
|
526
|
+
|
527
|
+
def process_zipfile_packed(zip, path='')
|
386
528
|
ret=nil
|
387
529
|
if zip.file.file? path
|
388
530
|
# extract and return filename
|
@@ -405,7 +547,6 @@ protected
|
|
405
547
|
ret
|
406
548
|
end
|
407
549
|
|
408
|
-
private
|
409
550
|
def unzip(filename)
|
410
551
|
ret = nil
|
411
552
|
Zip::ZipFile.open(filename) do |zip|
|
@@ -416,27 +557,31 @@ private
|
|
416
557
|
|
417
558
|
# read the version of the OO-Version
|
418
559
|
def oo_version
|
419
|
-
sheet_found = false
|
560
|
+
#sheet_found = false
|
420
561
|
@doc.each_element do |oo_document|
|
421
562
|
@officeversion = oo_document.attributes['version']
|
422
563
|
end
|
423
564
|
end
|
424
565
|
|
425
|
-
def
|
426
|
-
|
427
|
-
@
|
428
|
-
|
566
|
+
def set_cell_values(sheet,x,y,i,v,vt,formula,tr,str_v)
|
567
|
+
key = "#{y},#{x+i}"
|
568
|
+
@cell_type[sheet] = {} unless @cell_type[sheet]
|
569
|
+
@cell_type[sheet][key] = Openoffice.oo_type_2_roo_type(vt)
|
570
|
+
@formula[sheet] = {} unless @formula[sheet]
|
571
|
+
@formula[sheet][key] = formula if formula
|
572
|
+
@cell[sheet] = {} unless @cell[sheet]
|
573
|
+
case @cell_type[sheet][key]
|
429
574
|
when :float
|
430
|
-
@cell[
|
575
|
+
@cell[sheet][key] = v.to_f
|
431
576
|
when :string
|
432
|
-
@cell[
|
577
|
+
@cell[sheet][key] = str_v
|
433
578
|
when :date
|
434
|
-
@cell[
|
579
|
+
@cell[sheet][key] = tr.attributes['date-value']
|
435
580
|
when :percentage
|
436
|
-
@cell[
|
581
|
+
@cell[sheet][key] = v.to_f
|
437
582
|
else
|
438
|
-
@cell[
|
439
|
-
end
|
583
|
+
@cell[sheet][key] = v
|
584
|
+
end
|
440
585
|
end
|
441
586
|
|
442
587
|
# read all cells in the selected sheet
|
@@ -444,9 +589,10 @@ private
|
|
444
589
|
# the following construct means '4 blanks'
|
445
590
|
# some content <text:s text:c="3"/>
|
446
591
|
#++
|
447
|
-
def read_cells
|
592
|
+
def read_cells(sheet=nil)
|
593
|
+
sheet = @default_sheet unless sheet
|
448
594
|
sheet_found = false
|
449
|
-
raise ArgumentError, "Error:
|
595
|
+
raise ArgumentError, "Error: sheet '#{sheet||'nil'}' not valid" if @default_sheet == nil and sheet==nil
|
450
596
|
oo_document_count = 0
|
451
597
|
@doc.each_element do |oo_document|
|
452
598
|
# @officeversion = oo_document.attributes['version']
|
@@ -459,7 +605,7 @@ private
|
|
459
605
|
if be.name == "spreadsheet"
|
460
606
|
be.each_element do |se|
|
461
607
|
if se.name == "table"
|
462
|
-
if se.attributes['name']
|
608
|
+
if se.attributes['name']==sheet #@default_sheet
|
463
609
|
sheet_found = true
|
464
610
|
x=1
|
465
611
|
y=1
|
@@ -502,12 +648,12 @@ private
|
|
502
648
|
if skip
|
503
649
|
if v != nil or tr.attributes['date-value']
|
504
650
|
0.upto(skip.to_i-1) do |i|
|
505
|
-
|
651
|
+
set_cell_values(sheet,x,y,i,v,vt,formula,tr,str_v)
|
506
652
|
end
|
507
653
|
end
|
508
654
|
x += (skip.to_i - 1)
|
509
655
|
end # if skip
|
510
|
-
|
656
|
+
set_cell_values(sheet,x,y,0,v,vt,formula,tr,str_v)
|
511
657
|
x += 1
|
512
658
|
end
|
513
659
|
end
|
@@ -523,10 +669,10 @@ private
|
|
523
669
|
end
|
524
670
|
end
|
525
671
|
end
|
526
|
-
if sheet_found
|
672
|
+
if !sheet_found
|
527
673
|
raise RangeError
|
528
674
|
end
|
529
|
-
@cells_read = true
|
675
|
+
@cells_read[sheet] = true
|
530
676
|
end
|
531
677
|
|
532
678
|
# Checks if the default_sheet exists. If not an RangeError exception is
|
@@ -615,7 +761,9 @@ private
|
|
615
761
|
result = 0
|
616
762
|
while letters && letters.length > 0
|
617
763
|
character = letters[0,1].upcase
|
618
|
-
num = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".index(character)
|
764
|
+
num = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".index(character)
|
765
|
+
raise ArgumentError, "invalid column character '#{letters[0,1]}'" if num == nil
|
766
|
+
num += 1
|
619
767
|
result = result * 26 + num
|
620
768
|
letters = letters[1..-1]
|
621
769
|
end
|
@@ -623,12 +771,14 @@ private
|
|
623
771
|
end
|
624
772
|
|
625
773
|
|
626
|
-
def set_value(row,col,value)
|
627
|
-
|
774
|
+
def set_value(row,col,value,sheet=nil)
|
775
|
+
sheet = @default_value unless sheet
|
776
|
+
@cell[sheet]["#{row},#{col}"] = value
|
628
777
|
end
|
629
778
|
|
630
|
-
def set_type(row,col,type)
|
631
|
-
|
779
|
+
def set_type(row,col,type,sheet=nil)
|
780
|
+
sheet = @default_value unless sheet
|
781
|
+
@cell_type[sheet]["#{row},#{col}"] = type
|
632
782
|
end
|
633
783
|
|
634
784
|
A_ROO_TYPE = {
|
@@ -658,39 +808,65 @@ private
|
|
658
808
|
File.join(@tmpdir, File.basename(uri))
|
659
809
|
end
|
660
810
|
|
661
|
-
def write_csv_content(file=nil)
|
811
|
+
def write_csv_content(file=nil,sheet=nil)
|
662
812
|
file = STDOUT unless file
|
663
|
-
|
664
|
-
|
665
|
-
1.upto(last_column) do |col|
|
813
|
+
if first_row # sheet is not empty
|
814
|
+
first_row(sheet).upto(last_row(sheet)) do |row|
|
815
|
+
1.upto(last_column(sheet)) do |col|
|
666
816
|
file.print(",") if col > 1
|
667
|
-
onecell = cell(row,col)
|
668
|
-
onecelltype = celltype(row,col)
|
669
|
-
|
670
|
-
|
817
|
+
onecell = cell(row,col,sheet)
|
818
|
+
onecelltype = celltype(row,col,sheet)
|
819
|
+
file.print one_cell_output(onecelltype,onecell,empty?(row,col,sheet))
|
820
|
+
end
|
821
|
+
file.print("\n")
|
822
|
+
end # sheet not empty
|
823
|
+
end
|
824
|
+
end
|
825
|
+
|
826
|
+
def one_cell_output(onecelltype,onecell,empty)
|
827
|
+
str = ""
|
828
|
+
if empty
|
829
|
+
str += ''
|
830
|
+
else
|
831
|
+
case onecelltype
|
832
|
+
when :string
|
833
|
+
if onecell == ""
|
834
|
+
str << ''
|
835
|
+
else
|
836
|
+
onecell.gsub!(/"/,'""')
|
837
|
+
str << ('"'+onecell+'"')
|
838
|
+
end
|
839
|
+
when :float,:percentage
|
840
|
+
if onecell == onecell.to_i
|
841
|
+
str << onecell.to_i.to_s
|
842
|
+
else
|
843
|
+
str << onecell.to_s
|
844
|
+
end
|
845
|
+
when :formula
|
846
|
+
if onecell.class == String
|
847
|
+
if onecell == ""
|
848
|
+
str << ''
|
671
849
|
else
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
when :float
|
681
|
-
if onecell == onecell.to_i
|
682
|
-
file.print onecell.to_i
|
683
|
-
else
|
684
|
-
file.print onecell
|
685
|
-
end
|
686
|
-
else
|
687
|
-
raise "unhandled celltype "+celltype.to_s
|
688
|
-
end
|
850
|
+
onecell.gsub!(/"/,'""')
|
851
|
+
str << '"'+onecell+'"'
|
852
|
+
end
|
853
|
+
elsif onecell.class == Float
|
854
|
+
if onecell == onecell.to_i
|
855
|
+
str << onecell.to_i.to_s
|
856
|
+
else
|
857
|
+
str << onecell.to_s
|
689
858
|
end
|
690
|
-
|
859
|
+
else
|
860
|
+
raise "unhandled onecell-class "+onecell.class.to_s
|
691
861
|
end
|
692
|
-
|
862
|
+
when :date
|
863
|
+
str << '"'+onecell.to_s+'"'
|
864
|
+
else
|
865
|
+
raise "unhandled celltype "+onecelltype.to_s
|
693
866
|
end
|
867
|
+
end
|
868
|
+
#cells << onecell
|
869
|
+
str
|
694
870
|
end
|
695
871
|
|
696
872
|
# helper method to convert compressed spaces and other elements within
|