Again, I'm looking into just giving back header information with each list
entry, which should resolve everyone's issues.  With a valid workaround of
using the cells feed to look up the first row positionally though, this
isn't a huge deal, in my honest opinion.

-Vic



On Thu, Mar 17, 2011 at 8:22 AM, David Bullock <[email protected]> wrote:

> Hey Jason, that's a great write-up, and a great illustration of the
> pain of (as you nicely put it) content-dependent keys.
>
> Just dreaming here, but follows might be the definition of a list.
> (Borrowing heavily from the deprecated Table API).
>
>  <gs:data>
>      <gs:header height="1" nativenames="1" />
>      <gs:column idx="1" key="id" name="Item" />
>      <gs:column idx="2" key="descr" name="Description" />
>      <gs:column idx="3" key="qty" name="Quantity" />
>      <gs:column idx="4" key="ea" name="Each" />
>      <gs:column idx="5" key="total" name="Total" c1="=qty * ea" />
>  </gs:data>
>
>
> The 'name' attribute would be the content-dependent key, while the
> 'key' would be the content-independent key, conforming to existing
> list-feed naming constraints.  User changes to the sheet would modify
> 'idx' and 'name', but 'key' would stay put (and the E-Tag and Last-
> Modified of the resource containing this metatdata would change).
> When updating this metadata via the ATOM/REST API, 'key' would be
> required always, and either 'name' or 'idx' would suffice to establish
> the binding (so long as 'name' could be distinctly found in the header
> row when the metadata is POSTed or PUT or else a 4xx error).  If
> *both* 'name' and 'idx' are supplied, the index establishes the
> binding, and the content of the header cell is rewritten.
>
> Where to put this metadata?  How to integrate it with the existing
> list feed?  OK, here's my proposal in baby-steps:
>
> Put this metadata into entries in a separate feed.  Call it the 'List
> Definition' feed to avoid confusion with Tables.  Now, for each
> worksheet in the spreadsheet, there is an automatic List Definition,
> which have the property that their 'key' is always a function of
> 'name' according to the present name-munging rules in the List API.
> These automatic List Definitions can't have their column 'key' values
> set via the API (except as a side-effect of setting 'name') or else
> they give a 4xx HTTP status.
>
> Existing clients of the API access the lists defined by these
> 'automatic list definitions' in the same way they do now.
>
> I guess by now we have to fill in a few details:
>
> <entry>
>     <title>tableA</title>
>     <gs:listtype>auto</gs:listtype>
>     <gs:worksheet name="Invoices" />
>     <gs:data>
>      <gs:header height="1" nativenames="1" />
>      <gs:column idx="1" key="id" name="Item" />
>      <gs:column idx="2" key="descr" name="Description" />
>      <gs:column idx="3" key="qty" name="Quantity" />
>      <gs:column idx="4" key="ea" name="Each" />
>      <gs:column idx="5" key="total" name="Total" c1="=qty * ea" />
>  </gs:data>
>  <content src="https://foo/bar"; type=http://schemas.google.com/
> spreadsheets/2006#listfeed" />
> </entry>
>
> Now, if we want, we can add more list definitions (unique by <title/>
> within the feed), defining whatever we liked.  Additional list feeds
> are created for each definition we POST/PUT, using the key names for
> the <gsx:*/> elements in the list entry.  (The <gs:field name=""
> idx=""/> was probably a bit of overkill in the defunct Records feed).
>
> Any cool things that might have come with the now-defunct Record feed
> in terms of queries can be added to the list feed's querying abillity.
>
> I slipped in the 'c1' attribute to <gs:column/> ... that's all about
> declaring the formula for a given column, but only in terms of other
> fields in the row.  Thought would need to be given to naming and
> synatx, but think of it more as a template for a legal spreadsheet
> expresion rather than a legal spreadsheet expression itself.  It might
> only be valid in the 'automatic' list feed definitions. Such columns
> would exhibit the property that, when you inserted a row via the API
> or via the GUI, it auto-filled the formula into the cell.
>
> That API would certainly solve my use-cases.  What about you Jason?
>
> What about you, Google?
>
> cheers,
> David.
>
> On Mar 17, 3:20 am, Jason Cipriani <[email protected]> wrote:
> > I agree with David's sentiments. Personally, however, my use cases are
> very
> > different.
> >
> > I've been doing mostly web application development with PHP (and some
> > desktop application development with Java). The Zend client library does
> not
> > support tables, only list and cell feeds.
> >
> > I map Google spreadsheet column names to application-specific column
> names
> > myself, all of my applications have a central configuration that defines
> > this mapping, and I have the spreadsheet access hidden behind a layer of
> > abstraction in my software. I abstract it away like this for two reasons:
> 1)
> > because, as David mentions, list feed keys are content-dependent and
> > unreliable, and 2) so I can move away from Google spreadsheets some day
> (the
> > only reason I am using them is because I've been building applications on
> > top of existing systems powered by Google Forms).
> >
> > What I do to combat unreliable column headers is each time I access the
> list
> > feed, I compare the key names (and order) with the last time I accessed
> the
> > list feed. This is a virtually free operation compared to the list feed
> > access itself. If they change I have the application alert me via email
> so I
> > can go adjust the configuration. If the keys change to the point where
> they
> > might break the mapping in my application, the applications will report
> an
> > error to the user until I fix it -- for the applications I've been
> writing
> > it is more important to make sure the data is not corrupt rather than
> making
> > sure the apps have 100% uptime. Column changes happen infrequently enough
> > that this works well for me, the only reason they change is because some
> > users access the spreadsheets directly and change things they shouldn't
> be
> > changing (something I can't control).
> >
> > Because the spreadsheets I work with are generated by Google Forms, and
> > because Google Forms puts the wording of the question in the column
> headers,
> > and because sometimes the questions are very, very long, sometimes I map
> by
> > column index rather than list key because I simply don't feel comfortable
> > using 500 character key names that can change any time somebody, say,
> fixes
> > a grammatical error in a Google Forms question.
> >
> > Here is the algorithm I've been using to map column header values to
> indexes
> > and list feed keys. So far it has been working but it makes a lot of
> > undocumented assumptions, and only works if there is at least one
> non-header
> > row in the spreadsheet (list feed must return a result). Weird pseudocode
> > follows:
> >
> > === BEGIN ===
> >
> > struct COLUMN {
> >    string header;
> >    int index;
> >    string listkey;
> >
> > };
> >
> > headers = retrieve first row via cell feed, no empty cell return;
> > columns = a list of COLUMN structures, initially empty;
> >
> > for each cell in headers {
> >   COLUMN column;
> >   column.header = cell.text;
> >   column.index = cell.columnnumber;
> >   // column.listkey not determined yet
> >   columns.add(column);
> >
> > }
> >
> > sort columns by .index; // no guarantees that cells returned in order.
> >
> > // now 'columns' is a list of nonempty column headers and column
> > // indices, from left to right in the spreadsheet.
> >
> > listitem = retrieve a single row via list feed;
> > int curindex = 0;
> >
> > // assumptions:
> > //   - keys for columns with empty headers will start with an underscore.
> > //   - list entry fields are in order left to right, and correspond with
> > //     column headers.
> > for each field in listitem {
> >   if (field.key starts with '_')
> >     continue; // skip
> >   columns[curindex].listkey = field.key;
> >
> > }
> >
> > // columns now contains column header, index, and list key name for each
> > // column. this data can be cached, and this cache invalidated if the
> > // application detects a change in the list entry keys, which it can do
> > // as it retrieves items.
> >
> > === END ===
> >
> > *So for me, it would solve a ton of problems if the list feed simply had
> a
> > new column metadata element that contained column header names, column
> > indices, and key names.*
> >
> > It's all very messy and hard to work with right now.
> >
> > Jason
> >
> >
> >
> > On Wed, Mar 16, 2011 at 9:01 AM, David Bullock <[email protected]>
> wrote:
> > > In the lately deprecated tables API, if it had ever worked the way I
> > > read that it was intended to work (which it once did), one wouldn't
> > > ever need to discover the column names by reading the header row.
> > > Instead, one would say something like the following when defining a
> > > table:
> >
> > >  *in future, for my own convenience, I will refer to column B as
> > > 'Description'"
> >
> > > The next day, when some sensible spreadsheet user inserts a column to
> > > the left of B and renames the new C1 to "Item Name", your app doesn't
> > > break.  Just like a named range, the sheet adjusts the reference so
> > > that the name your code relies on - 'Description' - now refers to
> > > column C ... and further, while the name your code chose and the value
> > > of the header cell C1 are now different, it's no big deal - the column
> > > has the same *semantic* meaning.  You're just isolated from changes in
> > > its position and its user-facing description.
> >
> > > How nice would it have been?  Very nice.  We could even have defined
> > > table P to include columns A-F, and table Q to include just columns A
> > > and E (useful since the Spreadsheet API doesn't support partial
> > > response/update).
> >
> > > Instead, Google screwed it up by introducing a two-way binding between
> > > the name the application chose to refer to the colum, and the value of
> > > the header cell.  Oomph.  Quick - back to the cells feed to see if we
> > > can work out (somehow) what to call these columns when addressing them
> > > via the list feed!
> >
> > > All kinds of wierd behaviour ensued (I could point you to a few bugs I
> > > personally filed), among the worst of which was the stupid, stupid
> > > message "This operation is not permitted because it would alter the
> > > structure of this table" when the spreadsheet user tried to do such
> > > nefarious things as oh, fill-down a formula cell, or cut and paste a
> > > range.
> >
> > > Having thus reduced the grand concept of tables to an annoying
> > > repetition of the List API, some grown up in the playground obviously
> > > canned it.
> >
> > > And now we are stuck with this rigmarole of *looking  up* the column
> > > names ... and Google are 'considering a feature that would allow you
> > > to fetch the header row'.  Just let us bind our application-specific
> > > names to column indexes already, and adjust them the way you do named
> > > ranges.
> >
> > > But it's like talking to a brick wall ...
> >
> > > David.
> >
> > > On Mar 16, 6:38 am, Vic Fryzel <[email protected]> wrote:
> > > > Unfortunately, at the moment, you must use the cells feed to
> accomplish
> > > > this.  I'm considering a feature that would allow you to fetch the
> header
> > > > row with the lists feed, but I don't have an ETA yet.
> >
> > > > -Vic
> >
> > > > On Fri, Mar 4, 2011 at 9:56 PM, Jason Cipriani <
> [email protected]
> > > >wrote:
> >
> > > > >  Using PHP Zend bindings for spreadsheet API.
> >
> > > > > If I have a WorksheetEntry; I can use getContentsAsRows() to get
> all of
> > > the
> > > > > entries in that worksheet's list feed.
> >
> > > > > The keys in each list entry are the column headers converted to
> > > lowercase
> > > > > with all non alpha-numeric characters stripped out.
> >
> > > > > How do I get the real column names for this worksheet entry, and
> the
> > > > > corresponding list entry keys for each column? Alternatively, a way
> to
> > > get
> > > > > the real column name given the list entry key would work too.
> >
> > > > > My goal is to be able to both display the real column header text
> > > > > (spreadsheet column headers are Google Forms questions) to the user
> of
> > > my
> > > > > application, and also to know what the list entry key is for each
> > > column so
> > > > > I can display the values of the columns as well.
> > > > >  One way I've been toying with is to use a cell feed to get the
> first
> > > row
> > > > > and read the headers that way.
> >
> > > > > But then, how do I build a correspondence between the column
> headers
> > > and
> > > > > the list entry values?
> >
> > > > > Am I guaranteed that the values in a list entry will be returned in
> > > > > left-to-right GUI order, and empty values will be present (value
> count
> > > will
> > > > > be equal to column count)?
> >
> > > > > Being able to display the column headers and the corresponding
> values
> > > in an
> > > > > application seems like a very reasonable goal, I feel like I'm
> missing
> > > > > something because this is surprisingly clunky...
> >
> > > > > Thanks!
> > > > > Jason- Hide quoted text -
> >
> > > > - Show quoted text -- Hide quoted text -
> >
> > - Show quoted text -
>

Reply via email to