roo 1.3.11 → 1.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +15 -6
- data/Manifest.txt +53 -0
- data/README.txt +97 -0
- data/Rakefile +45 -0
- data/bin/roo +8 -0
- data/lib/roo.rb +55 -9
- data/lib/roo/excel.rb +44 -40
- data/lib/roo/excelx.rb +99 -60
- data/lib/roo/generic_spreadsheet.rb +29 -1
- data/lib/roo/google.rb +71 -117
- data/lib/roo/openoffice.rb +79 -27
- data/lib/roo/version.rb +9 -9
- data/tasks/ann.rake +80 -0
- data/tasks/bones.rake +20 -0
- data/tasks/gem.rake +201 -0
- data/tasks/git.rake +40 -0
- data/tasks/notes.rake +27 -0
- data/tasks/post_load.rake +34 -0
- data/tasks/rdoc.rake +51 -0
- data/tasks/rubyforge.rake +55 -0
- data/tasks/setup.rb +292 -0
- data/tasks/spec.rake +54 -0
- data/tasks/svn.rake +47 -0
- data/tasks/test.rake +40 -0
- data/tasks/zentest.rake +36 -0
- data/test/1900_base.xls +0 -0
- data/test/1904_base.xls +0 -0
- data/test/Bibelbund.csv +0 -0
- data/test/bode-v1.ods.zip +0 -0
- data/test/bode-v1.xls.zip +0 -0
- data/test/boolean.xls +0 -0
- data/test/datetime.xls +0 -0
- data/test/named_cells.ods +0 -0
- data/test/numbers1.csv +0 -0
- data/test/{bad_excel_date.xls → prova.xls} +0 -0
- data/test/test_helper.rb +1 -1
- data/test/test_roo.rb +365 -256
- data/test/whitespace.xls +0 -0
- metadata +48 -30
- data/README.markdown +0 -55
- data/examples/roo_soap_client.rb +0 -53
- data/examples/roo_soap_server.rb +0 -29
- data/examples/write_me.rb +0 -33
- data/test/formula_parse_error.xls +0 -0
- data/test/skipped_tests.rb +0 -789
data/lib/roo/excelx.rb
CHANGED
@@ -1,11 +1,15 @@
|
|
1
|
-
require 'xml'
|
1
|
+
#TODO: require 'xml'
|
2
2
|
require 'fileutils'
|
3
3
|
require 'zip/zipfilesystem'
|
4
4
|
require 'date'
|
5
|
+
require 'rubygems'
|
6
|
+
require 'nokogiri'
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
-
|
8
|
+
if RUBY_VERSION < '1.9.0'
|
9
|
+
class String
|
10
|
+
def end_with?(str)
|
11
|
+
self[-str.length,str.length] == str
|
12
|
+
end
|
9
13
|
end
|
10
14
|
end
|
11
15
|
|
@@ -100,27 +104,33 @@ class Excelx < GenericSpreadsheet
|
|
100
104
|
@file_nr = @@nr
|
101
105
|
extract_content(@filename)
|
102
106
|
file = File.new(File.join(@tmpdir, @file_nr.to_s+"_roo_workbook.xml"))
|
103
|
-
@workbook_doc = XML::Parser.io(file).parse
|
107
|
+
# TODO: @workbook_doc = XML::Parser.io(file).parse
|
108
|
+
@workbook_doc = Nokogiri::XML(file)
|
109
|
+
|
110
|
+
|
104
111
|
file.close
|
105
112
|
@shared_table = []
|
106
113
|
if File.exist?(File.join(@tmpdir, @file_nr.to_s+'_roo_sharedStrings.xml'))
|
107
114
|
file = File.new(File.join(@tmpdir, @file_nr.to_s+'_roo_sharedStrings.xml'))
|
108
|
-
@sharedstring_doc = XML::Parser.io(file).parse
|
115
|
+
#TODO: @sharedstring_doc = XML::Parser.io(file).parse
|
116
|
+
@sharedstring_doc = Nokogiri::XML(file)
|
109
117
|
file.close
|
110
118
|
read_shared_strings(@sharedstring_doc)
|
111
119
|
end
|
112
120
|
@styles_table = []
|
113
|
-
@style_definitions = Array.new { |h,k| h[k] = {} }
|
121
|
+
@style_definitions = Array.new # TODO: ??? { |h,k| h[k] = {} }
|
114
122
|
if File.exist?(File.join(@tmpdir, @file_nr.to_s+'_roo_styles.xml'))
|
115
123
|
file = File.new(File.join(@tmpdir, @file_nr.to_s+'_roo_styles.xml'))
|
116
|
-
@styles_doc = XML::Parser.io(file).parse
|
124
|
+
#TODO: @styles_doc = XML::Parser.io(file).parse
|
125
|
+
@styles_doc = Nokogiri::XML(file)
|
117
126
|
file.close
|
118
127
|
read_styles(@styles_doc)
|
119
128
|
end
|
120
129
|
@sheet_doc = []
|
121
130
|
@sheet_files.each_with_index do |item, i|
|
122
131
|
file = File.new(item)
|
123
|
-
@sheet_doc[i] = XML::Parser.io(file).parse
|
132
|
+
#TODO: @sheet_doc[i] = XML::Parser.io(file).parse
|
133
|
+
@sheet_doc[i] = Nokogiri::XML(file)
|
124
134
|
file.close
|
125
135
|
end
|
126
136
|
ensure
|
@@ -192,7 +202,7 @@ class Excelx < GenericSpreadsheet
|
|
192
202
|
end
|
193
203
|
|
194
204
|
def italic?
|
195
|
-
|
205
|
+
@italic == true
|
196
206
|
end
|
197
207
|
|
198
208
|
def underline?
|
@@ -202,13 +212,13 @@ class Excelx < GenericSpreadsheet
|
|
202
212
|
|
203
213
|
# Given a cell, return the cell's style
|
204
214
|
def font(row, col, sheet=nil)
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
215
|
+
sheet = @default_sheet unless sheet
|
216
|
+
read_cells(sheet) unless @cells_read[sheet]
|
217
|
+
row,col = normalize(row,col)
|
218
|
+
s_attribute = @s_attribute[sheet][[row,col]]
|
219
|
+
s_attribute ||= 0
|
220
|
+
s_attribute = s_attribute.to_i
|
221
|
+
@style_definitions[s_attribute]
|
212
222
|
end
|
213
223
|
|
214
224
|
# set a cell to a certain value
|
@@ -281,8 +291,10 @@ class Excelx < GenericSpreadsheet
|
|
281
291
|
# returns an array of sheet names in the spreadsheet
|
282
292
|
def sheets
|
283
293
|
return_sheets = []
|
284
|
-
@workbook_doc.find("//*[local-name()='sheet']").each do |sheet|
|
285
|
-
|
294
|
+
#TODO: @workbook_doc.find("//*[local-name()='sheet']").each do |sheet|
|
295
|
+
@workbook_doc.xpath("//*[local-name()='sheet']").each do |sheet|
|
296
|
+
#TODO: return_sheets << sheet.attributes.to_h['name']
|
297
|
+
return_sheets << sheet['name']
|
286
298
|
end
|
287
299
|
return_sheets
|
288
300
|
end
|
@@ -374,8 +386,8 @@ class Excelx < GenericSpreadsheet
|
|
374
386
|
return x,y
|
375
387
|
end
|
376
388
|
|
377
|
-
# read all cells in the selected sheet
|
378
389
|
def format2type(format)
|
390
|
+
format = format.to_s # weil von Typ Nokogiri::XML::Attr
|
379
391
|
if FORMATS.has_key? format
|
380
392
|
FORMATS[format]
|
381
393
|
else
|
@@ -390,22 +402,34 @@ class Excelx < GenericSpreadsheet
|
|
390
402
|
raise ArgumentError, "Error: sheet '#{sheet||'nil'}' not valid" if @default_sheet == nil and sheet==nil
|
391
403
|
raise RangeError unless self.sheets.include? sheet
|
392
404
|
n = self.sheets.index(sheet)
|
393
|
-
@sheet_doc[n].find("//*[local-name()='c']").each do |c|
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
405
|
+
#TODO: @sheet_doc[n].find("//*[local-name()='c']").each do |c|
|
406
|
+
@sheet_doc[n].xpath("//*[local-name()='c']").each do |c|
|
407
|
+
#TODO: s_attribute = c.attributes.to_h['s'].to_i # should be here
|
408
|
+
s_attribute = c['s'].to_i # should be here
|
409
|
+
#TODO: if (c.attributes.to_h['t'] == 's')
|
410
|
+
# c: <c r="A5" s="2">
|
411
|
+
# <v>22606</v>
|
412
|
+
# </c>, format: , tmp_type: float
|
413
|
+
|
414
|
+
if c['t'] == 's'
|
415
|
+
tmp_type = :shared
|
416
|
+
#TODO: elsif (c.attributes.to_h['t'] == 'b')
|
417
|
+
elsif c['t'] == 'b'
|
418
|
+
tmp_type = :boolean
|
419
|
+
else
|
420
|
+
#s_attribute = c.attributes.to_h['s'].to_i # was here
|
421
|
+
s_attribute = c['s'].to_i # was here
|
422
|
+
format = attribute2format(s_attribute)
|
423
|
+
tmp_type = format2type(format)
|
424
|
+
end
|
404
425
|
formula = nil
|
405
|
-
c.each_element do |cell|
|
426
|
+
#TODO: c.each_element do |cell|
|
427
|
+
c.children.each do |cell|
|
428
|
+
#TODO: if cell.name == 'f'
|
406
429
|
if cell.name == 'f'
|
407
430
|
formula = cell.content
|
408
431
|
end
|
432
|
+
#TODO: if cell.name == 'v'
|
409
433
|
if cell.name == 'v'
|
410
434
|
if tmp_type == :time or tmp_type == :datetime
|
411
435
|
if cell.content.to_f >= 1.0
|
@@ -417,7 +441,7 @@ class Excelx < GenericSpreadsheet
|
|
417
441
|
else
|
418
442
|
end
|
419
443
|
end
|
420
|
-
excelx_type = [:numeric_or_formula,format]
|
444
|
+
excelx_type = [:numeric_or_formula,format.to_s]
|
421
445
|
excelx_value = cell.content
|
422
446
|
if tmp_type == :shared
|
423
447
|
vt = :string
|
@@ -443,7 +467,8 @@ class Excelx < GenericSpreadsheet
|
|
443
467
|
v = cell.content
|
444
468
|
end
|
445
469
|
#puts "vt: #{vt}" if cell.text.include? "22606.5120"
|
446
|
-
x,y = split_coordinate(c.attributes.to_h['r'])
|
470
|
+
#TODO: x,y = split_coordinate(c.attributes.to_h['r'])
|
471
|
+
x,y = split_coordinate(c['r'])
|
447
472
|
tr=nil #TODO: ???s
|
448
473
|
set_cell_values(sheet,x,y,0,v,vt,formula,tr,str_v,excelx_type,excelx_value,s_attribute)
|
449
474
|
end
|
@@ -523,17 +548,19 @@ class Excelx < GenericSpreadsheet
|
|
523
548
|
|
524
549
|
# read the shared strings xml document
|
525
550
|
def read_shared_strings(doc)
|
526
|
-
doc.find("//*[local-name()='si']").each do |si|
|
551
|
+
#TODO: doc.find("//*[local-name()='si']").each do |si|
|
552
|
+
doc.xpath("//*[local-name()='si']").each do |si|
|
527
553
|
shared_table_entry = ''
|
528
|
-
si.each_element do |elem|
|
529
|
-
|
554
|
+
#TODO: si.each_element do |elem|
|
555
|
+
si.children.each do |elem|
|
556
|
+
if elem.name == 'r'
|
530
557
|
elem.each_element do |r_elem|
|
531
|
-
if
|
558
|
+
if r_elem.name == 't'
|
532
559
|
shared_table_entry << r_elem.content
|
533
560
|
end
|
534
561
|
end
|
535
562
|
end
|
536
|
-
if
|
563
|
+
if elem.name == 't'
|
537
564
|
shared_table_entry = elem.content
|
538
565
|
end
|
539
566
|
end
|
@@ -547,37 +574,46 @@ class Excelx < GenericSpreadsheet
|
|
547
574
|
@cellXfs = []
|
548
575
|
fonts = []
|
549
576
|
|
550
|
-
doc.find("//*[local-name()='numFmt']").each do |numFmt|
|
551
|
-
|
552
|
-
|
577
|
+
#TODO: doc.find("//*[local-name()='numFmt']").each do |numFmt|
|
578
|
+
doc.xpath("//*[local-name()='numFmt']").each do |numFmt|
|
579
|
+
# TODO: numFmtId = numFmt.attributes.to_h['numFmtId']
|
580
|
+
numFmtId = numFmt.attributes['numFmtId']
|
581
|
+
#TODO: formatCode = numFmt.attributes.to_h['formatCode']
|
582
|
+
formatCode = numFmt.attributes['formatCode']
|
553
583
|
@numFmts << [numFmtId, formatCode]
|
554
584
|
end
|
555
|
-
doc.find("//*[local-name()='fonts']").each do |fonts_el|
|
556
|
-
|
557
|
-
|
585
|
+
#TODO: doc.find("//*[local-name()='fonts']").each do |fonts_el|
|
586
|
+
doc.xpath("//*[local-name()='fonts']").each do |fonts_el|
|
587
|
+
#TODO: fonts_el.each_element do |font_el|
|
588
|
+
fonts_el.children.each do |font_el|
|
589
|
+
#TODO: if font_el.name == 'font'
|
590
|
+
if font_el == 'font'
|
558
591
|
font = Excelx::Font.new
|
559
592
|
font_el.each_element do |font_sub_el|
|
560
593
|
case font_sub_el.name
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
594
|
+
when 'b'
|
595
|
+
font.bold = true
|
596
|
+
when 'i'
|
597
|
+
font.italic = true
|
598
|
+
when 'u'
|
599
|
+
font.underline = true
|
600
|
+
end
|
568
601
|
end
|
569
602
|
fonts << font
|
570
603
|
end
|
571
604
|
end
|
572
605
|
end
|
573
606
|
|
574
|
-
doc.find("//*[local-name()='cellXfs']").each do |xfs|
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
607
|
+
#TODO: doc.find("//*[local-name()='cellXfs']").each do |xfs|
|
608
|
+
doc.xpath("//*[local-name()='cellXfs']").each do |xfs|
|
609
|
+
xfs.children.each do |xf|
|
610
|
+
#TODO: numFmtId = xf.attributes.to_h['numFmtId']
|
611
|
+
numFmtId = xf['numFmtId']
|
612
|
+
@cellXfs << [numFmtId]
|
613
|
+
#TODO: fontId = xf.attributes.to_h['fontId'].to_i
|
614
|
+
fontId = xf['fontId'].to_i
|
615
|
+
@style_definitions << fonts[fontId]
|
616
|
+
end
|
581
617
|
end
|
582
618
|
end
|
583
619
|
|
@@ -585,7 +621,10 @@ class Excelx < GenericSpreadsheet
|
|
585
621
|
def attribute2format(s)
|
586
622
|
result = nil
|
587
623
|
@numFmts.each {|nf|
|
588
|
-
if nf.first == @cellXfs[s.to_i].first
|
624
|
+
#TODO: if nf.first == @cellXfs[s.to_i].first
|
625
|
+
# to_s weil das eine Nokogiri::XML::Attr und das
|
626
|
+
# andere ein String ist
|
627
|
+
if nf.first.to_s == @cellXfs[s.to_i].first
|
589
628
|
result = nf[1]
|
590
629
|
break
|
591
630
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# encoding: utf-8
|
1
2
|
require 'rubygems'
|
2
3
|
require 'builder'
|
3
4
|
|
@@ -313,7 +314,7 @@ class GenericSpreadsheet
|
|
313
314
|
def info
|
314
315
|
result = "File: #{File.basename(@filename)}\n"+
|
315
316
|
"Number of sheets: #{sheets.size}\n"+
|
316
|
-
"Sheets: #{sheets.
|
317
|
+
"Sheets: #{sheets.join(', ')}\n"
|
317
318
|
n = 1
|
318
319
|
sheets.each {|sheet|
|
319
320
|
self.default_sheet = sheet
|
@@ -359,6 +360,33 @@ class GenericSpreadsheet
|
|
359
360
|
xml_document
|
360
361
|
end
|
361
362
|
|
363
|
+
# when a method like spreadsheet.a42 is called
|
364
|
+
# convert it to a call of spreadsheet.cell('a',42)
|
365
|
+
def method_missing(m, *args)
|
366
|
+
# #aa42 => #cell('aa',42)
|
367
|
+
# #aa42('Sheet1') => #cell('aa',42,'Sheet1')
|
368
|
+
if m =~ /^([a-z]+)(\d)$/
|
369
|
+
col = GenericSpreadsheet.letter_to_number($1)
|
370
|
+
row = $2.to_i
|
371
|
+
if args.size > 0
|
372
|
+
return cell(row,col,args[0])
|
373
|
+
else
|
374
|
+
return cell(row,col)
|
375
|
+
end
|
376
|
+
# else
|
377
|
+
# geht noch nicht, weil label unterhalb (in Openoffice) dieser Klasse
|
378
|
+
# es definiert ist
|
379
|
+
# p "Label #{m} angesprochen?"
|
380
|
+
# row,col,sheet = label('anton')
|
381
|
+
# # row,col,sheet = label(m)
|
382
|
+
# p "row: #{row}"
|
383
|
+
# p "col: #{col}"
|
384
|
+
# p "sheet: #{sheet}"
|
385
|
+
# return cell(row,col)
|
386
|
+
end
|
387
|
+
raise ArgumentError, "Method #{m} missing. Args: #{args}"
|
388
|
+
end
|
389
|
+
|
362
390
|
protected
|
363
391
|
|
364
392
|
def file_type_check(filename, ext, name)
|
data/lib/roo/google.rb
CHANGED
@@ -1,100 +1,10 @@
|
|
1
|
-
require '
|
2
|
-
require
|
1
|
+
#require 'xml'
|
2
|
+
require "google_spreadsheet"
|
3
3
|
|
4
4
|
class GoogleHTTPError < RuntimeError; end
|
5
5
|
class GoogleReadError < RuntimeError; end
|
6
6
|
class GoogleWriteError < RuntimeError; end
|
7
7
|
|
8
|
-
# overwrite some methods from the gdata-gem:
|
9
|
-
module GData
|
10
|
-
class Spreadsheet < GData::Base
|
11
|
-
|
12
|
-
def visibility
|
13
|
-
@headers ? "private" : "public"
|
14
|
-
end
|
15
|
-
|
16
|
-
def projection
|
17
|
-
@headers ? "full" : "values"
|
18
|
-
end
|
19
|
-
|
20
|
-
#-- modified
|
21
|
-
def evaluate_cell(cell, sheet_no=1)
|
22
|
-
raise ArgumentError, "invalid cell: #{cell}" unless cell
|
23
|
-
raise ArgumentError, "invalid sheet_no: #{sheet_no}" unless sheet_no >0 and sheet_no.class == Fixnum
|
24
|
-
path = "/feeds/cells/#{@spreadsheet_id}/#{sheet_no}/#{visibility}/#{projection}/#{cell}"
|
25
|
-
doc = Hpricot(request(path))
|
26
|
-
result = (doc/"content").inner_html
|
27
|
-
end
|
28
|
-
|
29
|
-
#-- new
|
30
|
-
def sheetlist
|
31
|
-
path = "/feeds/worksheets/#{@spreadsheet_id}/#{visibility}/#{projection}"
|
32
|
-
doc = Hpricot(request(path))
|
33
|
-
result = []
|
34
|
-
(doc/"content").each { |elem|
|
35
|
-
result << elem.inner_html
|
36
|
-
}
|
37
|
-
if result.size == 0
|
38
|
-
if (doc/"h2").inner_html =~ /Error/
|
39
|
-
raise GoogleHTTPError, "#{(doc/'h2').inner_html}: #{(doc/'title').inner_html} [key '#{@spreadsheet_id}']"
|
40
|
-
else
|
41
|
-
raise GoogleReadError, "#{doc} [key '#{@spreadsheet_id}']"
|
42
|
-
end
|
43
|
-
end
|
44
|
-
result
|
45
|
-
end
|
46
|
-
|
47
|
-
#-- new
|
48
|
-
#@@ added sheet_no to definition
|
49
|
-
def save_entry_roo(entry, sheet_no)
|
50
|
-
raise GoogleWriteError, "unable to write to public spreadsheets" if visibility == 'public'
|
51
|
-
path = "/feeds/cells/#{@spreadsheet_id}/#{sheet_no}/#{visibility}/#{projection}"
|
52
|
-
post(path, entry)
|
53
|
-
end
|
54
|
-
|
55
|
-
#-- new
|
56
|
-
def entry_roo(formula, row=1, col=1)
|
57
|
-
<<-XML
|
58
|
-
<entry xmlns='http://www.w3.org/2005/Atom' xmlns:gs='http://schemas.google.com/spreadsheets/2006'>
|
59
|
-
<gs:cell row='#{row}' col='#{col}' inputValue='#{formula}' />
|
60
|
-
</entry>
|
61
|
-
XML
|
62
|
-
end
|
63
|
-
|
64
|
-
#-- new
|
65
|
-
#@@ added sheet_no to definition
|
66
|
-
def add_to_cell_roo(row,col,value, sheet_no=1)
|
67
|
-
save_entry_roo(entry_roo(value,row,col), sheet_no)
|
68
|
-
end
|
69
|
-
|
70
|
-
#-- new
|
71
|
-
def get_one_sheet
|
72
|
-
path = "/feeds/cells/#{@spreadsheet_id}/1/#{visibility}/#{projection}"
|
73
|
-
doc = Hpricot(request(path))
|
74
|
-
end
|
75
|
-
|
76
|
-
#new
|
77
|
-
def oben_unten_links_rechts(sheet_no)
|
78
|
-
path = "/feeds/cells/#{@spreadsheet_id}/#{sheet_no}/#{visibility}/#{projection}"
|
79
|
-
doc = Hpricot(request(path))
|
80
|
-
rows = []
|
81
|
-
cols = []
|
82
|
-
(doc/"gs:cell").each {|item|
|
83
|
-
rows.push item['row'].to_i
|
84
|
-
cols.push item['col'].to_i
|
85
|
-
}
|
86
|
-
return rows.min, rows.max, cols.min, cols.max
|
87
|
-
end
|
88
|
-
|
89
|
-
def fulldoc(sheet_no)
|
90
|
-
path = "/feeds/cells/#{@spreadsheet_id}/#{sheet_no}/#{visibility}/#{projection}"
|
91
|
-
doc = Hpricot(request(path))
|
92
|
-
return doc
|
93
|
-
end
|
94
|
-
|
95
|
-
end # class
|
96
|
-
end # module
|
97
|
-
|
98
8
|
class Google < GenericSpreadsheet
|
99
9
|
attr_accessor :date_format, :datetime_format
|
100
10
|
|
@@ -122,10 +32,13 @@ class Google < GenericSpreadsheet
|
|
122
32
|
@date_format = '%d/%m/%Y'
|
123
33
|
@datetime_format = '%d/%m/%Y %H:%M:%S'
|
124
34
|
@time_format = '%H:%M:%S'
|
125
|
-
|
126
|
-
@
|
127
|
-
@
|
35
|
+
session = GoogleSpreadsheet.login(user, password)
|
36
|
+
@sheetlist = []
|
37
|
+
session.spreadsheet_by_key(@spreadsheetkey).worksheets.each { |sheet|
|
38
|
+
@sheetlist << sheet.title
|
39
|
+
}
|
128
40
|
@default_sheet = self.sheets.first
|
41
|
+
@worksheets = session.spreadsheet_by_key(@spreadsheetkey).worksheets
|
129
42
|
end
|
130
43
|
|
131
44
|
# returns an array of sheet names in the spreadsheet
|
@@ -182,6 +95,8 @@ class Google < GenericSpreadsheet
|
|
182
95
|
value = @cell[sheet]["#{row},#{col}"]
|
183
96
|
if celltype(row,col,sheet) == :date
|
184
97
|
begin
|
98
|
+
$log.debug "cell() value: #{value} @date_format: #{@date_format}"
|
99
|
+
$log.debug "returns #{Date.strptime(value, @date_format).inspect}"
|
185
100
|
return Date.strptime(value, @date_format)
|
186
101
|
rescue ArgumentError
|
187
102
|
raise "Invalid Date #{sheet}[#{row},#{col}] #{value} using format '{@date_format}'"
|
@@ -276,7 +191,7 @@ class Google < GenericSpreadsheet
|
|
276
191
|
raise RangeError, "invalid sheet '"+sheet.to_s+"'"
|
277
192
|
end
|
278
193
|
row,col = normalize(row,col)
|
279
|
-
|
194
|
+
add_to_cell_roo(row,col,value,sheet_no)
|
280
195
|
# re-read the portion of the document that has changed
|
281
196
|
if @cells_read[sheet]
|
282
197
|
key = "#{row},#{col}"
|
@@ -291,7 +206,8 @@ class Google < GenericSpreadsheet
|
|
291
206
|
sheet = @default_sheet unless sheet
|
292
207
|
unless @first_row[sheet]
|
293
208
|
sheet_no = sheets.index(sheet) + 1
|
294
|
-
@first_row[sheet], @last_row[sheet], @first_column[sheet], @last_column[sheet] =
|
209
|
+
@first_row[sheet], @last_row[sheet], @first_column[sheet], @last_column[sheet] =
|
210
|
+
oben_unten_links_rechts(sheet_no)
|
295
211
|
end
|
296
212
|
return @first_row[sheet]
|
297
213
|
end
|
@@ -301,7 +217,8 @@ class Google < GenericSpreadsheet
|
|
301
217
|
sheet = @default_sheet unless sheet
|
302
218
|
unless @last_row[sheet]
|
303
219
|
sheet_no = sheets.index(sheet) + 1
|
304
|
-
@first_row[sheet], @last_row[sheet], @first_column[sheet], @last_column[sheet] =
|
220
|
+
@first_row[sheet], @last_row[sheet], @first_column[sheet], @last_column[sheet] =
|
221
|
+
oben_unten_links_rechts(sheet_no)
|
305
222
|
end
|
306
223
|
return @last_row[sheet]
|
307
224
|
end
|
@@ -311,7 +228,8 @@ class Google < GenericSpreadsheet
|
|
311
228
|
sheet = @default_sheet unless sheet
|
312
229
|
unless @first_column[sheet]
|
313
230
|
sheet_no = sheets.index(sheet) + 1
|
314
|
-
@first_row[sheet], @last_row[sheet], @first_column[sheet], @last_column[sheet] =
|
231
|
+
@first_row[sheet], @last_row[sheet], @first_column[sheet], @last_column[sheet] =
|
232
|
+
oben_unten_links_rechts(sheet_no)
|
315
233
|
end
|
316
234
|
return @first_column[sheet]
|
317
235
|
end
|
@@ -321,7 +239,8 @@ class Google < GenericSpreadsheet
|
|
321
239
|
sheet = @default_sheet unless sheet
|
322
240
|
unless @last_column[sheet]
|
323
241
|
sheet_no = sheets.index(sheet) + 1
|
324
|
-
@first_row[sheet], @last_row[sheet], @first_column[sheet], @last_column[sheet] =
|
242
|
+
@first_row[sheet], @last_row[sheet], @first_column[sheet], @last_column[sheet] =
|
243
|
+
oben_unten_links_rechts(sheet_no)
|
325
244
|
end
|
326
245
|
return @last_column[sheet]
|
327
246
|
end
|
@@ -332,25 +251,37 @@ class Google < GenericSpreadsheet
|
|
332
251
|
def read_cells(sheet=nil)
|
333
252
|
sheet = @default_sheet unless sheet
|
334
253
|
raise RangeError, "illegal sheet <#{sheet}>" unless sheets.index(sheet)
|
335
|
-
sheet_no = sheets.index(sheet)
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
254
|
+
sheet_no = sheets.index(sheet)
|
255
|
+
$log.debug "sheet: #{sheet}"
|
256
|
+
$log.debug "sheet_no: #{sheet_no}"
|
257
|
+
ws = @worksheets[sheet_no]
|
258
|
+
$log.debug "#{ws.inspect}"
|
259
|
+
for row in 1..ws.num_rows
|
260
|
+
for col in 1..ws.num_cols
|
261
|
+
key = "#{row},#{col}"
|
262
|
+
string_value = ws.input_value(row,col) # item['inputvalue'] || item['inputValue']
|
263
|
+
numeric_value = ws[row,col] #item['numericvalue'] || item['numericValue']
|
264
|
+
(value, value_type) = determine_datatype(string_value, numeric_value)
|
265
|
+
@cell[sheet][key] = value unless value == "" or value == nil
|
266
|
+
if value_type == :date
|
267
|
+
$log.debug "date erkannt. value: #{value}"
|
268
|
+
end
|
269
|
+
@cell_type[sheet][key] = value_type
|
270
|
+
@formula[sheet] = {} unless @formula[sheet]
|
271
|
+
@formula[sheet][key] = string_value if value_type == :formula
|
272
|
+
############
|
273
|
+
#$log.debug("key: #{key}")
|
274
|
+
#$log.debug "#{ws[row,col].inspect}"
|
275
|
+
#@cell[sheet][key] = ws[row,col]
|
276
|
+
#$log.debug "@cell[sheet][key]: #{@cell[sheet][key]}"
|
277
|
+
############
|
278
|
+
end
|
349
279
|
end
|
350
280
|
@cells_read[sheet] = true
|
351
281
|
end
|
352
282
|
|
353
283
|
def determine_datatype(val, numval=nil)
|
284
|
+
# $log.debug "val: #{val} numval: #{numval}"
|
354
285
|
if val.nil? || val[0,1] == '='
|
355
286
|
ty = :formula
|
356
287
|
if numeric?(numval)
|
@@ -372,8 +303,31 @@ class Google < GenericSpreadsheet
|
|
372
303
|
else
|
373
304
|
ty = :string
|
374
305
|
end
|
375
|
-
end
|
306
|
+
end
|
307
|
+
$log.debug "val: #{val} ty: #{ty}" if ty == :date
|
376
308
|
return val, ty
|
377
309
|
end
|
378
|
-
|
379
|
-
|
310
|
+
|
311
|
+
def add_to_cell_roo(row,col,value, sheet_no=1)
|
312
|
+
sheet_no -= 1
|
313
|
+
@worksheets[sheet_no][row,col] = value
|
314
|
+
@worksheets[sheet_no].save
|
315
|
+
end
|
316
|
+
def entry_roo(value,row,col)
|
317
|
+
return value,row,col
|
318
|
+
end
|
319
|
+
|
320
|
+
def oben_unten_links_rechts(sheet_no)
|
321
|
+
ws = @worksheets[sheet_no-1]
|
322
|
+
rows = []
|
323
|
+
cols = []
|
324
|
+
for row in 1..ws.num_rows
|
325
|
+
for col in 1..ws.num_cols
|
326
|
+
rows << row if ws[row,col] and ws[row,col] != '' #TODO: besser?
|
327
|
+
cols << col if ws[row,col] and ws[row,col] != '' #TODO: besser?
|
328
|
+
end
|
329
|
+
end
|
330
|
+
return rows.min, rows.max, cols.min, cols.max
|
331
|
+
end
|
332
|
+
|
333
|
+
end # class
|