Yes! That would be perfect! =)

Jason


On Mon, Apr 4, 2011 at 1:20 PM, Vic Fryzel <[email protected]> wrote:

> I think ideally what I'd like to do is add indexed header information to
> the top of every lists feed, with both positional information, index names,
> and full names.  Does that sound like it'd work?
>
> -Vic
>
>
>
> On Mon, Apr 4, 2011 at 1:16 PM, Jason Cipriani 
> <[email protected]>wrote:
>
>> Hi Vic,
>>
>> I'm OK with the workaround except it's pretty kludgy. I would be more OK
>> with the workaround if you could guarantee that the following
>> assumptions will remain true in the future:
>>
>>   - List entry items are in left-to-right GUI order.
>>   - List entry always includes all items and never leaves out ones with
>> blank values.
>>   - List entry item names with blank column headers always start with an
>> underscore.
>>   - List entry item names with non-blank column headers never start with
>> an underscore.
>>
>> Can you make those guarantees?
>>
>> I think giving back header information with each list entry is almost less
>> ideal than the workaround just because the list feed already sends so much
>> data over the network (because it repeats the field names for every header).
>> In my Google Forms example, some of the questions are very long, and list
>> feed entry names account for over 80% of the amount of data in the list feed
>> - and I am already having usability issues with my web application because
>> of how long it takes to transfer spreadsheet data.
>>
>> What if you made an option to return column position indexes as keys in
>> the list feed entries *instead* of names? This would let you use the
>> workaround to associate fields with header values without having to rely on
>> any of the assumptions below, and would greatly reduce network usage for
>> list feeds as well. For me, the primary reason I use the list feed at all is
>> because the cell feed takes even more bandwidth (and has no guarantees on
>> the order of returned cells, so I had to piece together the returned data
>> using logic I posted about in another thread here), and list feed was the
>> most efficient way to transfer spreadsheet data that I could find.
>>
>> There currently does not seem to exist any way to efficiently retrieve
>> data from a spreadsheet without getting loads of redundant/irrelevant data
>> in the data stream.
>>
>> Jason
>>
>>
>> On Mon, Apr 4, 2011 at 12:16 PM, Vic Fryzel <[email protected]> wrote:
>>
>>> 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<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