Spreadsheet uploadTicket:FinishedWithEntry:error not being called

38 views
Skip to first unread message

JustinXXVII

unread,
Dec 29, 2009, 11:45:30 PM12/29/09
to Google Data APIs Objective-C Client Library Discussion
After experimenting quite a bit tonight, I've come to now attempting
to upload dummy .xls file to Google. The tutorial in the
ObjCIntroduction Wiki seems out of date. It refers to a class called
GDataEntrySpreadsheetDoc, but that doesn't exist. The closest I can
find is GDataEntrySpreadsheet.

I've included blankSpreadsheet.xls in my mainBundle. Here is my
source verbatim. Can you tell what the problem is?

-(void)uploadBlankSpreadsheet {
NSLog(@"Creating spreadsheet data");
SEL progressSel = @selector
(ticket:hasDeliveredByteCount:ofTotalByteCount:);
[spreadsheetService setServiceUploadProgressSelector:progressSel];
GDataEntrySpreadsheet *newEntry = [GDataEntrySpreadsheet
spreadsheetEntry];
NSString *path = [[NSBundle mainBundle]
pathForResource:@"blankSpreadsheet" ofType:@"xls"];
NSLog(path);
NSData *data = [NSData dataWithContentsOfFile:path];
if(!data) {
NSLog(@"File error occurred, no data ready.");
} else {
NSString *filename = [path lastPathComponent];
[newEntry setUploadSlug:filename];
[newEntry setUploadData:data];
[newEntry setUploadMIMEType:@"application/vnd.ms-excel"];
NSString *title = [[NSFileManager defaultManager]
displayNameAtPath:path];
[newEntry setTitleWithString:title];
NSURL *postURL = [[spreadsheetFeed postLink]URL];
GDataServiceTicket *ticket;
ticket = [spreadsheetService fetchEntryByInsertingEntry:newEntry
forFeedURL:postURL delegate:self didFinishSelector:@selector
(uploadTicket:finishedWithEntry:error:)];
NSLog(@"Now uploading blank spreadsheet...");
}
}

-(void)uploadTicket:(GDataServiceTicket *)ticket finishedWithEntry:
(GDataEntrySpreadsheet *)entry error:(NSError *)error {
if (error) {
NSLog(@"There was an error uploading the spreadsheet");
NSLog(@"%@",[error description]);
UIAlertView *errorAlert = [[UIAlertView alloc]
initWithTitle:@"Error" message:[NSString stringWithFormat:@"%@",[error
description]] delegate:self cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[errorAlert show];
[errorAlert release];
} else {
NSLog(@"No Errors uploading spreadsheet");
}
}


The last line I get in my console is always "Now uploading blank
spreadsheet..."

Greg, I noticed any spreadsheet questions always get referred to the
Spreadsheet API forum. I figured this question was more of an
objective-c one, so I asked here first. Thanks for all of your help
so far!

Greg Robbins

unread,
Dec 30, 2009, 1:46:02 AM12/30/09
to gdata-objec...@googlegroups.com
Uploading a new spreadsheet is done with the Google Docs (DocList) API rather than with the Spreadsheet API, and requires an instance of GDataServiceGoogleDocs as the service object, along with the user's DocList feed. The DocsSample app in the library shows how to fetch the DocList feed.

You don't need an actual spreadsheet file to create a new spreadsheet; just call some data a csv file in the MIME type, and the DocList server will create a spreadsheet for it.

Here's a working example.

- (void)uploadBlankSpreadsheetToDocListFeed:(GDataFeedDocList *)docListFeed {
  NSString *colNames = @"col1,col2,col3";
  NSData *data = [colNames dataUsingEncoding:NSUTF8StringEncoding];
                        
  GDataEntrySpreadsheetDoc *newEntry = [GDataEntrySpreadsheetDoc documentEntry];
  [newEntry setTitleWithString:@"New Empty Spreadsheet"];
  [newEntry setUploadData:data];
  [newEntry setUploadMIMEType:@"text/csv"];
  [newEntry setUploadSlug:@"New Empty Spreadsheet.csv"];
  
  NSURL *postURL = [[docListFeed postLink] URL];

  GDataServiceGoogleDocs *service = [self docsService];
  [service fetchEntryByInsertingEntry:newEntry
                           forFeedURL:postURL
                             delegate:self
                    didFinishSelector:@selector(createSpreadsheetTicket:finishedWithEntry:error:)];
}

- (void)createSpreadsheetTicket:(GDataServiceTicket *)ticket
              finishedWithEntry:(GDataEntrySpreadsheetDoc *)entry
                          error:(NSError *)error {
  NSLog(@"new spreadsheet entry: %@ \nerror:%@", entry, error);
}



Greg Robbins

unread,
Dec 30, 2009, 2:05:59 AM12/30/09
to gdata-objec...@googlegroups.com
If your callbacks are not being invoked, it's typically either because an exception is firing when the fetch is attempted (exceptions should show up in Xcode's console window) or because the app does not have an executing run loop to call the callbacks (such as when writing plain C console tools.)


It's fine to ask questions first in this discussion group, as most of the developers who respond to questions in the API-specific groups won't be familiar with Objective-C or the Obj-C library. But the Objective-C library is just a thin layer on top of the actual http and XML protocol. The developers in the other groups have more experience with their API's protocols.

By comparing the protocol sections of the developer guide for the APIs with the Objective-C sample apps, the translation between them should (hopefully) be apparent. The relationship between the Objective-C library and the protocol is not difficult, but it is not intuitive, either. 

Turning on the library's http logging facility also makes debugging your code much easier, as you can see just what http and XML is (or is not) being generated by your code, and what responses are being received from the server. Looking at the logs usually clears up any mystery.

Unfortunately, the Spreadsheet API is currently one of the more difficult-to-use and incomplete protocols. It is actively being developed at Google.

JustinXXVII

unread,
Dec 30, 2009, 8:13:47 AM12/30/09
to Google Data APIs Objective-C Client Library Discussion
Greg, thanks for your response. I'll include the Documents source in
my project and give this a shot. As far as turning on the HTTP
logging, can I still do that if I don't compile with the framework? I
went with the option of just referencing the GData Sources folder
inside the GData project file, and removing the unneeded clients.

Greg Robbins

unread,
Dec 30, 2009, 11:25:41 AM12/30/09
to gdata-objec...@googlegroups.com
Logging just requires having GDataHTTPFetcherLogging.h/m included with the rest of the library (it's part of the Networking group), and then calling  [GDataHTTPFetcher setIsLoggingEnabled:YES]

JustinXXVII

unread,
Dec 30, 2009, 1:14:19 PM12/30/09
to Google Data APIs Objective-C Client Library Discussion
Greg, you hit the nail right on the head. The HTTP Logging is a great
tool, thanks for that suggestion. Your provided functions work. I
tried looking at the GDocs Example file, but it wouldn't compile in
10.5. It's ok though, since you explained how to get it to work.

My app works by checking the documents list, searching for a specific
spreadsheet. If it doesn't exist, it uploads it with the filename
specified. Then, the data I need can be inserted on the second line,
pushing everything else down a row. I haven't started on the code to
insert a record. I figured out the code to insert a table, but once
one table gets put in, I can no longer use the API to update the
spreadsheet, I get an error that says using the API will somehow break
my existing table. I guess it's now down to learning the records
entry portion to just insert an entry on row 2. I will be back, I'm
sure! Right now it's time for some chicken nuggets from McDonalds

JustinXXVII

unread,
Dec 30, 2009, 2:02:47 PM12/30/09
to Google Data APIs Objective-C Client Library Discussion

I've peered at the randomize function in the spreadsheet table
example. Can you point out the difference between a record field and
a record entry?

Is this the gist?
GDataEntrySpreadsheetRecord *oneRecordEntry = [[recordFeed entries]
objectAtIndex:0];
NSString *oneField = [[oneRecordField fields] objectAtIndex:0];

Should I be doing

//one for each: Year, Month, Week, Date, Score
NSArray *fields = [NSArray
arrayWithObjects:@"2009",@"December",@"1",@"12/1/2009",@"5000",nil];
[recordEntry setFields:fields];

GDataServiceGoogleSpreadsheet *service = [self spreadsheetService];
GDataServiceTicket *ticket;

ticket = [service fetchEntryByUpdatingEntry:recordEntry
delegate:self
didFinishSelector:@selector
(editRecordTicket:finishedWithEntry:error:)];

Where do I set it so it inserts on Row 2?

Greg Robbins

unread,
Dec 30, 2009, 2:19:09 PM12/30/09
to gdata-objec...@googlegroups.com
A record entry, GDataEntrySpreadsheetRecord, contains a list of fields, each of which is an instance of GDataSpreadsheetField.

Read through the records API documentation to see how entries and fields are related,
http://code.google.com/apis/spreadsheets/data/3.0/developers_guide_protocol.html#TableRecordFeeds

You can append a record (a row) by inserting to the record feed's post link. The API supports modifying records by updating using the record's edit link, but I do not know if it supports inserting new records between existing records.

Reply all
Reply to author
Forward
0 new messages