Skip to content

Commit

Permalink
add support for public google spreadsheets
Browse files Browse the repository at this point in the history
  • Loading branch information
Hugh McGowan committed Aug 29, 2009
1 parent 1ef2850 commit a274170
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 18 deletions.
48 changes: 32 additions & 16 deletions lib/roo/google.rb
@@ -1,44 +1,64 @@
require 'gdata/spreadsheet'
require 'xml'

class GoogleHTTPError < RuntimeError; end
class GoogleReadError < RuntimeError; end
class GoogleWriteError < RuntimeError; end

# overwrite some methods from the gdata-gem:
module GData
class Spreadsheet < GData::Base

def visibility
@headers ? "private" : "public"
end

def projection
@headers ? "full" : "values"
end

#-- modified
def evaluate_cell(cell, sheet_no=1)
raise ArgumentError, "invalid cell: #{cell}" unless cell
raise ArgumentError, "invalid sheet_no: #{sheet_no}" unless sheet_no >0 and sheet_no.class == Fixnum
path = "/feeds/cells/#{@spreadsheet_id}/#{sheet_no}/#{@headers ? "private" : "public"}/basic/#{cell}"

path = "/feeds/cells/#{@spreadsheet_id}/#{sheet_no}/#{visibility}/#{projection}/#{cell}"
doc = Hpricot(request(path))
result = (doc/"content").inner_html
end

#-- new
def sheetlist
path = "/feeds/worksheets/#{@spreadsheet_id}/private/basic"
path = "/feeds/worksheets/#{@spreadsheet_id}/#{visibility}/#{projection}"
doc = Hpricot(request(path))
result = []
(doc/"content").each { |elem|
result << elem.inner_html
}
if result.size == 0
if (doc/"h2").inner_html =~ /Error/
raise GoogleHTTPError, "#{(doc/'h2').inner_html}: #{(doc/'title').inner_html} [key '#{@spreadsheet_id}']"
else
raise GoogleReadError, "#{doc} [key '#{@spreadsheet_id}']"
end
end
result
end

#-- new
#@@ added sheet_no to definition
def save_entry_roo(entry, sheet_no)
path = "/feeds/cells/#{@spreadsheet_id}/#{sheet_no}/#{@headers ? 'private' : 'public'}/full"
raise GoogleWriteError, "unable to write to public spreadsheets" if visibility == 'public'
path = "/feeds/cells/#{@spreadsheet_id}/#{sheet_no}/#{visibility}/#{projection}"
post(path, entry)
end

#-- new
def entry_roo(formula, row=1, col=1)
<<XML
<<-XML
<entry xmlns='http://www.w3.org/2005/Atom' xmlns:gs='http://schemas.google.com/spreadsheets/2006'>
<gs:cell row='#{row}' col='#{col}' inputValue='#{formula}' />
</entry>
XML
XML
end

#-- new
Expand All @@ -49,13 +69,13 @@ def add_to_cell_roo(row,col,value, sheet_no=1)

#-- new
def get_one_sheet
path = "/feeds/cells/#{@spreadsheet_id}/1/private/full"
path = "/feeds/cells/#{@spreadsheet_id}/1/#{visibility}/#{projection}"
doc = Hpricot(request(path))
end

#new
def oben_unten_links_rechts(sheet_no)
path = "/feeds/cells/#{@spreadsheet_id}/#{sheet_no}/private/full"
path = "/feeds/cells/#{@spreadsheet_id}/#{sheet_no}/#{visibility}/#{projection}"
doc = Hpricot(request(path))
rows = []
cols = []
Expand All @@ -67,7 +87,7 @@ def oben_unten_links_rechts(sheet_no)
end

def fulldoc(sheet_no)
path = "/feeds/cells/#{@spreadsheet_id}/#{sheet_no}/private/full"
path = "/feeds/cells/#{@spreadsheet_id}/#{sheet_no}/#{visibility}/#{projection}"
doc = Hpricot(request(path))
return doc
end
Expand All @@ -90,7 +110,6 @@ def initialize(spreadsheetkey,user=nil,password=nil)
unless password
password = ENV['GOOGLE_PASSWORD']
end
@default_sheet = nil
@cell = Hash.new {|h,k| h[k]=Hash.new}
@cell_type = Hash.new {|h,k| h[k]=Hash.new}
@formula = Hash.new
Expand All @@ -104,11 +123,8 @@ def initialize(spreadsheetkey,user=nil,password=nil)
@datetime_format = '%d/%m/%Y %H:%M:%S'
@time_format = '%H:%M:%S'
@gs = GData::Spreadsheet.new(spreadsheetkey)
@gs.authenticate(user, password)
@gs.authenticate(user, password) unless user.empty? || password.empty?
@sheetlist = @gs.sheetlist
#-- ----------------------------------------------------------------------
#-- TODO: Behandlung von Berechtigungen hier noch einbauen ???
#-- ----------------------------------------------------------------------
@default_sheet = self.sheets.first
end

Expand Down Expand Up @@ -192,7 +208,7 @@ def celltype(row, col, sheet=nil)
sheet = @default_sheet unless sheet
read_cells(sheet) unless @cells_read[sheet]
row,col = normalize(row,col)
if @formula[sheet]["#{row},#{col}"]
if @formula.size > 0 && @formula[sheet]["#{row},#{col}"]
return :formula
else
@cell_type[sheet]["#{row},#{col}"]
Expand Down Expand Up @@ -335,7 +351,7 @@ def read_cells(sheet=nil)
end

def determine_datatype(val, numval=nil)
if val[0,1] == '='
if val.nil? || val[0,1] == '='
ty = :formula
if numeric?(numval)
val = numval.to_f
Expand Down
32 changes: 30 additions & 2 deletions test/test_roo.rb
Expand Up @@ -158,6 +158,16 @@ def with_each_spreadsheet(options)
yield Roo::Spreadsheet.open(key_of(options[:name]) || options[:name]) if GOOGLE && options[:format].include?(:google)
end

def with_public_google_spreadsheet(&block)
user = ENV['GOOGLE_MAIL']
pass = ENV['GOOGLE_PASSWORD']
ENV['GOOGLE_MAIL'] = ''
ENV['GOOGLE_PASSWORD'] = ''
block.call
ENV['GOOGLE_MAIL'] = user
ENV['GOOGLE_PASSWORD'] = pass
end

# Using Date.strptime so check that it's using the method
# with the value set in date_format
def test_date
Expand Down Expand Up @@ -385,7 +395,7 @@ def test_argument_error
def test_empty_eh
with_each_spreadsheet(:name=>'numbers1') do |oo|
assert oo.empty?('a',14)
assert ! oo.empty?('a',15)
assert !oo.empty?('a',15)
assert oo.empty?('a',20)
end
end
Expand Down Expand Up @@ -1199,6 +1209,7 @@ def test_should_raise_file_not_found_error

def test_write_google
# write.me: http://spreadsheets.google.com/ccc?key=ptu6bbahNZpY0N0RrxQbWdw&hl=en_GB

with_each_spreadsheet(:name=>'write.me', :format=>:google) do |oo|
oo.set_value(1,1,"hello from the tests")
assert_equal "hello from the tests", oo.cell(1,1)
Expand Down Expand Up @@ -1345,7 +1356,7 @@ def test_no_remaining_tmp_files_excelx

def test_no_remaining_tmp_files_google
if GOOGLE
assert_nothing_raised() {
assert_raise(GoogleReadError) {
oo = Google.new(key_of("no_spreadsheet_file.txt"))
}
a=Dir.glob("oo_*")
Expand Down Expand Up @@ -1790,5 +1801,22 @@ def test_bad_excel_date
end
end

def test_public_google_doc
with_public_google_spreadsheet do
assert_raise(GoogleHTTPError) { Google.new("foo") }
assert_raise(GoogleReadError) { Google.new(key_of('numbers1'))}
assert_nothing_raised { Google.new("0AncOJVyN5MMMcjZtN0hGbFVPd3N0MFJUVVR1aFEwT3c") } # use spreadsheet key (private)
assert_nothing_raised { Google.new(key_of('write.me')) } # use spreadsheet key (public)
end
end

def test_public_google_doc_write
with_public_google_spreadsheet do
assert_raise(GoogleWriteError) {
oo = Google.new(key_of('write.me'))
oo.set_value(1,1,'test')
}
end
end

end # class

0 comments on commit a274170

Please sign in to comment.