English 中文(简体)
Programatically updating a Google spreadsheet
原标题:

I ve got a pre-existing Google spreadsheet. Each month I update this document. I ve got a template workseet in the spreadseet that I d like to clone and then update.

I d prefer to clone the worksheet rather than create it from scratch as it has some pretty complex formulas.

I m using the Python api for the Google spreadsheets here:

http://code.google.com/apis/spreadsheets/data/1.0/developers_guide_python.html

Does anyone know how to clone and copy a worksheet in a pre-existing document?

Edit

I seemed to have confused one reader. I don t have an excel spreadsheet. I only have a Google spreadsheet that has a template worksheet.

I d like to clone this worksheet, rename it and then edit it programatically.

最佳回答
  1. Clone your template worksheet using the instructions on Copying Documents
  2. Access the list of worksheets within the cloned document and iterate through to the required spreadsheet.
  3. Use the cell feed to get the appropriate cell in your spreadsheet, then update the values.
问题回答

Whoa!!! Back the truck up. There s a much simpler approach

I have been researching this a bit over the past few weeks because I m planning to do the same thing for my monthly reports. I don t have the actual code fleshed out yet but I ll add it as I make progress.

In Google Docs there are so many API s and similar terms related to working with docs that things can get a little confusing. If you don t already know, establish in your head the fact that GAS (Google Apps Scripting) and GAE (Google App Engine) are two completely different things. Even though they sound the same thing they re about as similar as Java is to JavaScript.

GAS are the scrips embedded in Google Docs (which will hopefully be importable as stand alone modules in the future) that drive things like validation and dynamic documents but they re a lot more powerful than most suspect (they can do things like modify/update external documents and auto-email responses). Keep in mind that these need to be lightweight because they re run on google s servers. If your script takes to long to finish up it s execution will get cut off prematurely (google around to find the limits). That means you should use vanilla JS only (no frameworks like jQuery) and performance tweaks wherever possible.

GAE, on the other hand, is like a web server (with an available database layer) that lives somewhere in the cloud. It exists as a convenient (and already deployed) middleware layer for businesses/interests to create custom apps to do more heavy lifting. Unfortunately, the external Spreadsheet s API is too limited to accomplish what we re working on by itself so it s a non-option.

Automation using Google Apps Scripting and time-based triggers

This approach should work but requires a slightly hackish approach.

Open up the workbook containing your report sheets. Click on [Tools] -> [Script editor...]. Once there goto [Triggers] -> [Current script s triggers...].

If you don t have any triggers present, add one. Then, under the Events dropdown menu select Time-driven .

Welcome to the world of server-side event handlers. One of the neat features that you get with cloud-based documents is the ability to trigger cron jobs directly within your document. No external middleware necessary.

If you haven t noticed by now there s no trigger for Month timer . This is where it gets hacky. To work around the lack of this feature it s going to require that we fire the trigger on a daily basis and use some JavaScript to match the current date with the previous day s date.

[code will go here]

First, comes the function that gets attached to the time trigger event handler. This block of code just simply parses the date, compares it to the previous date, and stores the value in a hidden sheet (that we use as out persistence layer) for the next day s comparison. If the new-month condition is met then the next block of code runs.

[code will go here]

Yours will obviously differ from mine a bit but the basic concept is:

  • Load the SpreadSheet object (not to be confused with a Sheet object)
  • Locate the template Sheet object
  • Clone the template Sheet giving it an appropriate date-range-based name

In mine, my next step will be to extract data from the month to generate a stacked line graph to report the current status to my higher-ups.

Note: Because of the multi-user collaboration nature of docs, events have to be fired server-side. This creates a big problem for us. Because the event code runs elsewhere if the code errors, we don t get any feedback from our browser. The only solution to this is to setup a notification on the trigger to immediately email you when the script faults.

Update: While researching this, I found another cool technique. If I can manage to get this working without any bugs I might try to invoke the trigger using a date marked on Google Calendar.

First of all, I ve never worked with Python before - but I ll tell you how I did this in C++.

I ve used cURL to make a GET request to the google documents API. The binary data of the file was returned and I wrote that to a file. Now I had the XLS file and then I used a C/C++ library that could read XLS files to manipulate the downloaded file. The API that I used supported a variety of options; you could do anything that you could do in Excel. After modification I uploaded it again to Google Docs.

This is really complicated. I understand that you can edit your spreadsheets with Python using their API, Google tends to offer that ability on many of their web services and it s all done by sending HTTP post requests made of XML somehow, I hope you know that part, I don t.

According to this you can at least add worksheets, read rows from other worksheets and write rows to worksheets. if you must, you could copy it one row at a time, however sending an additional POST request for each row seems like a horrible idea.

Edit:

I m learning more and more about this, but still a long way off from solving your original problem. This overview of REST principles goes over the basic style of interaction that goes on between programs on the web. Google seems to be following it religiously.

It all takes place within the HTTP protocol, something I knew nothing about before today. In this HTTP specification the basic game is spelled out. Its not as dry as it looks, and maybe I m just a huge geek, but I find it an inspiring read. Not unlike The Constitution of The United States.

So since you want to "clone" a document, your going to be using a GET request for a particular worksheet, and then sending that worksheet back as the payload of POST.

Getting closer :)

Couldn t you could export your spreadsheet as a xls and then upload it as a new doc with a (slightly) different name, specifying the new name in the XML metadata?

The Download and Create/upload Document sections at http://code.google.com/apis/documents/overview.html should be beneficial.

I can t immediately see any import/export functionality in the Python API docs, but sending a few http requests isn t so bad.

(Feb 2017) Rephrasing question with current terminology: How do you copy a Google Sheet template, then modify it (the copy) programmatically? Short answer: it s much easier with current Google APIs, specifically the Google Drive v3 API and the Google Sheets v4 API, and you can do it with any language supported by the Google APIs Client Libraries.

The latest Sheets API provides features not available in older releases, namely giving developers programmatic access to a Sheet as if you were using the user interface (UI), i.e., create frozen rows, cell formatting, resize rows/columns, add pivot tables, cell validation, create charts, etc.

As you can guess, the Sheets API is primarily for programmatically accessing spreadsheet operations & functionality as described above, but to perform file-level access such as copying a template Sheet, use the Google Drive API instead.

Pseudocode (Python) to copy a file (Sheet) using the Drive API (assuming we first search for the most recently modified file with the template name, hence the orderBy and selection of the first result [0] below):

TMPLFILE =  my Sheets template 
tmpl = DRIVE.files().list(q="name= %s " % TMPLFILE).execute().get( files )[0]
NEW_SHEET = { name :  Sheets data, Feb 2017 }
SHEET_ID = DRIVE.files().copy(body=NEW_SHEET, fileId=tmpl[ id ]).execute().get( id )

Pseudocode to read values from a SQL database (SQLite) and write them to the new Sheet created above (starting from cell A1 as "upper-left") as if a user entered the values from the UI (so formulae can be applied, etc.):

cxn = sqlite3.connect( db.sqlite )
cur = cxn.cursor()
rows = cur.execute( SELECT * FROM data ).fetchall()
cxn.close()
DATA = { values : rows}
SHEETS.spreadsheets().values().update(spreadsheetId=SHEET_ID,
    range= A1 , body=DATA, valueInputOption= USER_ENTERED ).execute()

If you re relatively new to modern Google APIs, I have a (somewhat dated but) user-friendly intro video for you. There are 2 videos after that maybe useful too, including one that demonstrates using the Drive API. Those are videos 2, 3, and 4 in this playlist. Videos 23 & 25 are another pair featuring the Drive and Sheets APIs.

All newer videos can be found in this playlist where you ll find another pair of videos featuring the Sheets API plus a reprise of the "template copying" code above but copying a Slides template which is then modified with the Slides API) instead (video 2).

As mentioned in another answer, you can also use Google Apps Script to do something similar if you prefer that environment vs. using REST APIs, although Apps Script currently uses older APIs. Also there are few outstanding bugs that may make it a bit more challenging (specifically this one and this one).





相关问题
Can Django models use MySQL functions?

Is there a way to force Django models to pass a field to a MySQL function every time the model data is read or loaded? To clarify what I mean in SQL, I want the Django model to produce something like ...

An enterprise scheduler for python (like quartz)

I am looking for an enterprise tasks scheduler for python, like quartz is for Java. Requirements: Persistent: if the process restarts or the machine restarts, then all the jobs must stay there and ...

How to remove unique, then duplicate dictionaries in a list?

Given the following list that contains some duplicate and some unique dictionaries, what is the best method to remove unique dictionaries first, then reduce the duplicate dictionaries to single ...

What is suggested seed value to use with random.seed()?

Simple enough question: I m using python random module to generate random integers. I want to know what is the suggested value to use with the random.seed() function? Currently I am letting this ...

How can I make the PyDev editor selectively ignore errors?

I m using PyDev under Eclipse to write some Jython code. I ve got numerous instances where I need to do something like this: import com.work.project.component.client.Interface.ISubInterface as ...

How do I profile `paster serve` s startup time?

Python s paster serve app.ini is taking longer than I would like to be ready for the first request. I know how to profile requests with middleware, but how do I profile the initialization time? I ...

Pragmatically adding give-aways/freebies to an online store

Our business currently has an online store and recently we ve been offering free specials to our customers. Right now, we simply display the special and give the buyer a notice stating we will add the ...

Converting Dictionary to List? [duplicate]

I m trying to convert a Python dictionary into a Python list, in order to perform some calculations. #My dictionary dict = {} dict[ Capital ]="London" dict[ Food ]="Fish&Chips" dict[ 2012 ]="...

热门标签