Google docs api - get all the document - google-drive-api

Is it possible to get all the documents from google docs using google-docs API?
On the API reference page, I am not able to find API for get all the list of documents
the below api used for get single document using documentId.
GET https://docs.googleapis.com/v1/documents/{documentId}
Reference: https://developers.google.com/docs/api/reference/rest/v1/documents/get
If I forget the document Id, how can get the document? this information not available on the reference api page.

I believe your goal as follows.
You want to retrieve all Google Document files using the method of "documents.get" in Google Docs API.
You have no Document IDs of all Google Document files. You are required to retrieve the Document ID.
In order to achieve your goal, I would like to propose to use the following 2 processes.
Retrieve Document IDs of Google Document files.
In this case, the method of "Files: list" in Drive API is used. Ref
In order to retrieve Google Document files, the search query of mimeType='application/vnd.google-apps.document' and trashed=false is used.
The sample curl command is as follows.
curl \
'https://www.googleapis.com/drive/v3/files?pageSize=1000&q=mimeType%3D%27application%2Fvnd.google-apps.document%27%20and%20trashed%3Dfalse' \
--header 'Authorization: Bearer [YOUR_ACCESS_TOKEN]' \
--header 'Accept: application/json' \
--compressed
When you want to retrieve the Google Document files in the specific folder, please use mimeType='application/vnd.google-apps.document' and trashed=false and '###' in parents as the search query.
When above curl command is run, the file list including the file IDs is returned.
In this sample, the page size is 1000. When you have more document files, please use pageToken.
Retrieve the data from Google Document files.
In this case, the method of "documents.get" in Google Docs API is used.
Using the file IDs retrieved by above method, you can retrieve all Google Document files. In the current stage, I think that in this case, it is required to request to the endpoint for each Document ID in a loop.
In this case, the endpoint in your question can be used.
References:
Files: list
Search for files and folders
Method: documents.get

Related

Google Script - Convert Sheet to XLSX and download it via HTTP

I am trying to convert Google Sheet to XLSX and download it via HTTP (all done by script, exported again on every request).
First, I tried the code solution provided here and it did indeed work and sent the file by email.
Then, I tried to do the request and download the file on my own via code/curl. As I know URL and Authorization Bearer token it should have been easy.
var url = "https://docs.google.com/spreadsheets/d/" + file.getId() + "/export?format=xlsx";
var token = ScriptApp.getOAuthToken();
The cUrl example for this looked like this:
curl --location --request GET 'https://docs.google.com/spreadsheets/d/SPREADSHEET_ID/export?format=xlsx' --header 'Authorization: Bearer TOKEN_ID'
It did work properly for some time but recently it stopped working, even though it does work within Google Script returning proper response code (200) and the result. Currently it returns Error code 400: Bad Request instead if done from curl/external code.
Did I miss some update from Google that made such requests not possible from outside of Google Script itself?
It looks like it was a bug that Google has finally fixed!
Now it does work properly.
For those who want to get the URL in another way, here's alternative approach (but a bit slower). It saves the file to Google Drive and creates accessible public link to it. Please note that it will create a new file in directory on each request, so you might want to delete them by code first.
var dir = DriveApp.getFolderById("drive_folder_id");
var file = dir.createFile(blob).setName('file.xlsx');
file.setSharing(DriveApp.Access.ANYONE_WITH_LINK,DriveApp.Permission.VIEW);
var url = file.getDownloadUrl();

Google Drive API: Create Folder: Allow conflict error if folder by name exists

DISCUSSION
Google Drive API v3: Create Folder
CLOUD DRIVE APIs COMPARISON
Other cloud drive APIs when creating a folder, including Box API and Dropbox API, both return a conflict error if a folder of the same name already exists in parent folder.
However, Google Drive API by default allows creating folders of the same name.
QUESTION
Is there a way to return conflict error if trying to create a folder of the same name within Google Drive parent folder?
If I take the approach using API to search for folder by name first, then create folder if not exists, then this could result in a possible race condition by a parallel process doing the same task in creating a unique folder by name.
EXAMPLE
Google Drive API create folder call in curl
curl "https://www.googleapis.com/drive/v3/files" \
--request POST \
--verbose \
--write-out 'HTTPSTATUS:%{http_code}' \
--silent \
--header "authorization: Bearer [** ACCESS TOKEN **]" \
--header "cache-control: no-cache" \
--header "content-type: application/json; charset=utf-8" \
--header "Accept: application/json" \
--data '{ \
"mimeType":"application\/vnd.google-apps.folder", \
"name": "[** FOLDER NAME **]", \
"parents": ["root"] \
}'
Each call creates a new folder in Google Drive parent folder with unique folder id, however, same folder name. I wish to avoid this:
Success [HTTP status: 200]
{
"kind": "drive#file",
"id": "1mpy2-TVeZDTL8vZ6fKHTyoGoFHX-18EN",
"name": "TEST",
"mimeType": "application/vnd.google-apps.folder"
}
...
Success [HTTP status: 200]
{
"kind": "drive#file",
"id": "1iqYnEWOVFcWO3jWX1IgIv2wxtGVYruQX",
"name": "TEST",
"mimeType": "application/vnd.google-apps.folder"
}
I appreciate any assistance in getting a single call approach to either return conflict error or auto-renaming.
You want to return the conflict error, if the same folder name is existing when new folder is created in the specific folder.
You want to use this with the asynchronous process.
In this case, you don't want to create the duplicated folder name.
You want to achieve this by one API call with Drive API.
If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.
Issue and workaround:
At Google Drive, all files and folders are managed by the unique ID. By this, the files and folders with the same name can be created in a folder. When Drive API is used, this uses the ID which is not the filename and folder name. So in order to achieve your goal with Drive API, it is required to search the folder name. And also, the exclusive processing is required to for prevent to be created the same folder name with the asynchronous process. By this, unfortunately, your goal cannot be achieved with only the simple curl command.
From above situation, in order to achieve your goal with only the simple curl command, I would like to use Web Apps as an API as a workaround. Web Apps is created by Google Apps Script and this can be used like an API. By this, I thought that your goal can be achieved by this workaround.
Usage:
In order to use this workaround, please do the following flow.
Create new Google Apps Script project.
Access to script.google.com.
In this case, the login screen is shown. So so please login to Google. By this, the script editor is opened.
When you access to script.google.com for the first time, you'll be redirected to a page that introduces Apps Script. At that time, please click Start Scripting to proceed to the script editor.
Input the filename of GAS project at the top left.
Copy and paste the following sample script. This is used as the script of server side.
function doGet(e) {
var lock = LockService.getScriptLock();
if (lock.tryLock(10000)) {
var parent, folder;
if (e.parameter.parentId) {
parent = DriveApp.getFolderById(e.parameter.parentId);
folder = parent.getFoldersByName(e.parameter.folderName);
} else {
parent = DriveApp.getRootFolder();
folder = DriveApp.getFoldersByName(e.parameter.folderName);
}
if (folder.hasNext()) {
lock.releaseLock();
var err = {error: "Same folder name is existing."};
return ContentService.createTextOutput(JSON.stringify(err)).setMimeType(ContentService.MimeType.JSON);
}
var folderId = parent.createFolder(e.parameter.folderName).getId();
lock.releaseLock();
var msg = {message: "Done.", folderId: folderId};
return ContentService.createTextOutput(JSON.stringify(msg)).setMimeType(ContentService.MimeType.JSON);
}
}
Unfortunately, Web Apps cannot manage the response code. In this case, the status code of 200 is returned even when an error occurs in the script. So I returned the response value as JSON object.
In this script, the process is run with the exclusive processing. By this, even when you run the request with the asynchronous process, the same folder name is not created.
Deploy Web Apps.
On the script editor, Open a dialog box by "Publish" -> "Deploy as web app".
Select "Me" for "Execute the app as:".
Select "Only myself" for "Who has access to the app:".
In this case, in order to access to Web Apps, it is required to use the access token.
If "Anyone, even anonymous" is used instead of "Only myself", the access token is not required to be used.
Click "Deploy" button as new "Project version".
Automatically open a dialog box of "Authorization required".
Click "Review Permissions".
Select own account.
Click "Advanced" at "This app isn't verified".
Click "Go to ### project name ###(unsafe)"
Click "Allow" button.
Click "OK".
Copy the URL of Web Apps. It's like https://script.google.com/macros/s/###/exec.
When you modified the Google Apps Script, please redeploy as new version. By this, the modified script is reflected to Web Apps. Please be careful this.
I think that the developer mode can be also used because the access token is used. But in your case, I thought that the script of server side might be suitable that it is managed as the version. So I didn't propose to use the developer mode.
Use the deoloyed Web Apps with the following curl command.
curl -L \
-H "Authorization: Bearer ###" \
"https://script.google.com/macros/s/###/exec?parentId=###&folderName=###"
parentId and folderName are used as the query parameter.
When the same folder name of folderName is existing in the folder of parentId, {"error":"Same folder name is existing."} is returned.
When the same folder name of folderName is NOT existing in the folder of parentId, new folder is created and {"message":"Done.","folderId":"### folder ID of created folder ###"} is returned.
References:
Overview of Google Apps Script
Web Apps
Taking advantage of Web Apps with Google Apps Script
Class DriveApp
Lock Service
If I misunderstood your question and this was not the direction you want, I apologize.

How to get the url to Google doc image

I have a Google Docs document which contains one image. I found images's objectId as stated here https://developers.google.com/docs/api/reference/rest/v1/InlineObject but I can't understand how to get an url to that image.
I tried searching for this objectId in Drive but it returns File not found.
Any ideas ?
Update
As noted by #Tanaike the image info is contained in the result.inlineObjects and
not directly in the paragraph.
You want to retrieve the URL of the inserted image in Google Document using Google Docs API.
If my understanding is correct, how about this answer?
I think that the property of inlineObjectElement that you are checking is in the paragraph. The information of the inserted images can be seen at the property of inlineObjects. And the URL can be seen at the property of ImageProperties.
The endpoint is as follows.
Endpoint:
GET https://docs.googleapis.com/v1/documents/{documentId}?fields=inlineObjects
Here, as a sample, inlineObjects is used as fields. You can also use * as fields.
Result:
The URL can be retrieved as follows. It supposes that response is the returned value from above endpoint.
url = response.inlineObjects["kix.###"].inlineObjectProperties.embeddedObject.imageProperties.sourceUri
kix.### is inlineObjectId in your question.
If the image is inserted from the URL of outside, the URL is the same with the URL which was used when the image was inserted.
If the image is inserted from Google Drive, the URL is like below.
https://lh3.google.com/u/0/d/{fileId}=w###-h###
In this case, {fileId} is the file ID of the image. You can retrieve the original file using this file ID.
References:
Method: documents.get
InlineObject
ImageProperties
If I misunderstood your question and this was not the result you want, I apologize.
Step #1: Right-click and Copy the image from the Google Doc.
Step #2: Paste into dynalist.io.
(Note: Dynalist doesn't allow you to paste images, but you can paste images from Google Docs because it just adds the link.)
I understand that this may not help if you are trying to do something with the API, but for finding the link to a single image, it is the simplest method I've found.
use the drive and doc api
use the gdoc api retrieve the ContentUri:
(Document.InlineObjects[imageid].InlineObjectProperties.EmbeddedObject.ImageProperties.ContentUri)
imageid has the form "kix.###..."
The imageid can be retrieved frm the InlineObjects map, the key is the imageid
After obtaining the ContentUri you must strip the ending "=wxx-hyy" to obtain the the image file id for the drive api
use the drive api to obtain the file pointer:
*fil, err = service.Files.Get(fileid).Do()
After obtaining the file pointer, you can retrieve the image file characteristics (see File)
Alternatively the image file can be downloaded via:
httpResp, err =service.Files.Export(fileid, mime).Download()
mime types are listed here

How to get the id for a published to the web spreadsheet in google apps scripts

I have a script that takes rows from a spreadsheet, and creates individual spreadsheet files for each row. Then the script publishes them to the web.
What I'm not able to get is the id that will allow me to get an url for a web version of it.
A regular spreadsheet id looks like this:
1N8h00iN2L7aaUbI9TYRWioaZHjHNSc_vNucCbVADj1o
And a published to the web id looks like this:
2PACX-1vTPSkv4Rz7CqwabTTfxa3xcVF-Gzxu7IboLyLkfoShP2d3qdX8o0qdvk5d_nWZD2rq43E2LXmVAm5HI
(longer, and it starts with 2PACX-)
Anybody know how to?
Thanks in advance.
You want to retrieve URL from the web published spreadsheet using file ID. If my understanding is correct, how about this answer? Unfortunately, "publishedLink" cannot be retrieved by Drive API v3. "publishedLink" got to not be able to be used from Drive API v3. Furthermore now, Drive API v2 also cannot be used anymore. So it is required to create the link manually.
When the spreadsheet is published to Web, you retrieve URL like as follows.
https://docs.google.com/spreadsheets/d/e/2PACX-1vTPSkv4Rz7CqwabTTfxa3xcVF-Gzxu7IboLyLkfoShP2d3qdX8o0qdvk5d_nWZD2rq43E2LXmVAm5HI/pubhtml
When you want to use the URL using file ID, please use the following URL. You can use both URLs.
Pattern 1:
https://docs.google.com/spreadsheet/pub?key=### fileId ###
Pattern 2:
https://docs.google.com/spreadsheets/d/### fileId ###/pubhtml
If I misunderstand your question, I'm sorry.

Accessing a (new-style, public) Google sheet as JSON

How can I access the contents of a (new-style) Google sheet a JSON? My aim is to access the values from JavaScript, so I need to be able to download the JSON via HTTP.
Example: how can I download the data from this sheet as JSON?
I tried to find the answer via a web search, but ultimately failed:
Many tutorials on the web start with the instruction to find the key=... value in the url. The URL I got when I exported the sheet is https://docs.google.com/spreadsheets/d/1mhv1lpzufTruZhzrY-ms0ciDVKYiFJLWCMpi4OOuqvI/pubhtml?gid=1822753188&single=true and has no key=... in it.
The answer to "Accessing A Public Google Sheet" seems to indicate that I should try https://docs.google.com/spreadsheets/d/1mhv1lpzufTruZhzrY-ms0ciDVKYiFJLWCMpi4OOuqvI/export?format=csv&id=1mhv1lpzufTruZhzrY-ms0ciDVKYiFJLWCMpi4OOuqvI&gid=1822753188 to get a CSV version, but this does not work for me: I get a sign-in page instead of the data.
I found approaches using Google Apps Scripts, but these seem to require some user action in the browser instead of giving a download link.
If you want to use the latest API (v4), you'll need to do the following:
Generate a spreadsheets API key (see instructions below).
Make your sheet publicly accessible.
Use a request of the form:
https://sheets.googleapis.com/v4/spreadsheets/SPREADSHEET_ID/values/RANGE?key=API_KEY
You'll then get a clean JSON response back:
{
"range": "Sheet1!A1:D5",
"majorDimension": "ROWS",
"values": [
["Item", "Cost", "Stocked", "Ship Date"],
["Wheel", "$20.50", "4", "3/1/2016"],
["Door", "$15", "2", "3/15/2016"],
["Engine", "$100", "1", "30/20/2016"],
["Totals", "$135.5", "7", "3/20/2016"]
],
}
Note that if you want to specify the entire contents of a page, an identifier such as Sheet1 is perfectly valid.
See Basic Reading for more information.
As of v4 API, all requests must be accompanied by an identifier (e.g. API key):
Requests to the Google Sheets API for public data must be accompanied by an identifier, which can be an API key or an access token.
Follow the steps in the linked document to create an API key on the credentials page.
Make sure to:
Create a new app on Google Cloud Platform.
Create a new API key.
Add the Google Sheets API. (API Manager > Dashboard > Enable API)
Note that you can still access public data without forcing the user to log in:
In the new Sheets API v4, there is no explicit declaration of visibility. API calls are made using spreadsheet IDs. If the application does not have permission to access specified spreadsheet, an error is returned. Otherwise the call proceeds.
Note that you do not need to publish the sheet to the web. All you need to do is make sure anyone with the link can access the sheet.
(I.e. when you click Create credentials on the Google Sheets API, choose Other non-UI, User data, and it says "User data cannot be accessed from a platform without a UI because it requires user interaction for sign-in." you can safely ignore that message. The API Key is all you really need, since this is public data.)
Common error messages:
The request is missing a valid API key.
You didn't include the key= param in your call.
API key not valid. Please pass a valid API key.
Google developers console
You supplied an incorrect API key. Make sure that you typed in your key correctly. If you don't have a key yet, go to the Google developers console and create one.
API Key not found. Please pass a valid API key.
Google developer console API key
Your API Key is probably correct, but you most likely didn't add the Google Sheets permission. Go to the Google developer console API key page and add the sheets permission.
The caller does not have permission
Your sheet isn't set to be publicly accessible.
I have finally (kind of) solved my problem. Just for future reference, and in case somebody else runs into the same troubles, here the solution I came up with:
To make the worksheet publicly accessible, one needs to make the worksheet publicly accessible. This is done in the Google Sheets web interface, using the menu entries File > Publish to the web ... > link > publish. It is possible to either publish the whole spreadsheet or individual worksheets.
An API to access data from Google Sheets programmatically is described on the Google Sheets API web pages. This API uses URLS of the form https://spreadsheets.google.com/feeds/.../key/worksheetId/.... Slightly oddly, the meaning of key and worksheetId seems not to be explained in the API documentation.
My experiments show that the key value can be found by taking part of the URLs used to access the sheet via the web interface (see also here). The key is everything after the /d/, until the next slash. For the spreadsheet in the question, the key is thus 1mhv1lpzufTruZhzrY-ms0ciDVKYiFJLWCMpi4OOuqvI. The worksheetId seems to be an integer, giving the position of the worksheet in the spreadsheet. For the example in the question one has to know that the sheet shown is the second worksheet, the worksheetId in this case is 2.
The API defined public and private requests. To access an exported resource without authentication, public requests must be used.
The API calls to get data from the spreadsheet are explained in the section "Retrieving a list-based feed" (click on the "Protocol" tab in the examples). The URL required extract the data from the spreadsheet in the question is
https://spreadsheets.google.com/feeds/list/1mhv1lpzufTruZhzrY-ms0ciDVKYiFJLWCMpi4OOuqvI/2/public/full
A HTTP GET request to this URL returns that data as XML. (I have not found a way to get the data as JSON.)
The usual protections agains cross-site requests make it difficult to access the data via JavaScript XML RPC calls in a web app. One way around this problem is to proxy the API calls through the web server (e.g. using nginx's proxy_pass directive).
The above steps are at least a partial solution to the problem in the question. The only difficulty is that the data is returned as XML rather than as JSON. Since the API documentation does not mention JSON, maybe it is not possible any more to extract the data in this format?
Edit: (Aug 17, 2021) With the rollout of Sheets v4, the endpoint in the original answer has been deprecated. The updated endpoint and sample script included below:
Updated solution
Credits to the original answer here.
"https://docs.google.com/spreadsheets/d/" + spreadsheetId + "/gviz/tq?tqx=out:json&gid=0";
You don't technically have to include the gid if you just want the first sheet, but you can specify another sheet if you'd like using that parameter.
Here's a sample script to retrieve values of Spreadsheet as JSON, and then parsed as header row and values.
var sf = "https://docs.google.com/spreadsheets/d/1l7VfPOI3TYtPuBZlZ-JMMiZW1OK6rzIBt8RFd6KmwbA/gviz/tq?tqx=out:json";
$.ajax({url: sf, type: 'GET', dataType: 'text'})
.done(function(data) {
const r = data.match(/google\.visualization\.Query\.setResponse\(([\s\S\w]+)\)/);
if (r && r.length == 2) {
const obj = JSON.parse(r[1]);
const table = obj.table;
const header = table.cols.map(({label}) => label);
const rows = table.rows.map(({c}) => c.map(({v}) => v));
console.log(header);
console.log(rows);
}
})
.fail((e) => console.log(e.status));
Original solution
Note: This no longer works as Sheets v3 was deprecated in August 2021.
Here's how to get the JSON using those same URL parameters:
"https://spreadsheets.google.com/feeds/list/" + spreadsheetID + "/od6/public/values?alt=json";
Creds to #jochen on the answer with the path all the way up to XML "https://spreadsheets.google.com/feeds/list/" + spreadsheetID + "/od6/public/" + sheetID;
As #jochen's answer explains, this sheetID is based on the order of the sheets in the spreadsheet.
A faster solution here is to use this https://gist.github.com/ronaldsmartin/47f5239ab1834c47088e to wrap around your existing spreadsheet.
You first need to change your sheet access to Anyone with link can View
Add the id and sheet html param to the URL below.
https://script.google.com/macros/s/AKfycbzGvKKUIaqsMuCj7-A2YRhR-f7GZjl4kSxSN1YyLkS01_CfiyE/exec
Eg: your id is your sheet id which is
1mhv1lpzufTruZhzrY-ms0ciDVKYiFJLWCMpi4OOuqvI
and your sheet which is
Sheet2
In your case you can actually see your data here as json at
https://script.google.com/macros/s/AKfycbzGvKKUIaqsMuCj7-A2YRhR-f7GZjl4kSxSN1YyLkS01_CfiyE/exec?id=1mhv1lpzufTruZhzrY-ms0ciDVKYiFJLWCMpi4OOuqvI&sheet=Sheet2
To be safe, you should deploy the code sheetAsJson.gs in the github gist above as your own in your Google Drive.
Here is the solution
Note your sheet id in the document url (don't use the published url to find the id!)
Publish your sheet, just as html page
Use the id from step 1,
and put it in this url https://spreadsheets.google.com/feeds/cells/{id}/1/public/full?alt=json
The /1 indicates the first sheet in your document