Upload CSV/Excel File as Sheet via Google App Script - google-apps-script

I see that the Drive Folder class has a createFile() which takes three arguments for name, content, and mimeType. Is it possible to use this as part of an upload call to have a user file uploaded and converted (to Google Docs) all in one go without having to call the REST API directly with convert=true?
For example, here's the HTML:
<html>
<head>
<base target="_top">
<script>
function handler(response) {
document.getElementById('uploader').innerHTML = "Uploaded file! " + response;
}
</script>
</head>
<body>
<div id="uploader">
<form>
<input type="file" name="theFile">
<input type="button" onclick="google.script.run.withSuccessHandler(handler).uploadFile(this.parentNode)" value="Upload!">
</form></div>
</body>
</html>
And here's the Google Script code:
function uploadFile(e) {
Logger.log("Uploading file!");
var dfolder = DriveApp.getFolderById('abcdefgh'); // replace w/ Drive FolderID
return dfolder.createFile(e.theFile).getName();
}
How would I go about changing that last line to something like:
return dfolder.createFile(newName, e.theFile, MimeType.GOOGLE_SHEETS);
Something I'm trying to figure out now is simply how to get the name of the file being uploaded (e.g. for newName). And then how to go about converting whatever form e.theFile is in to a string. If I try this as-is now I get the error:
Invalid argument: file.contentType at uploadFile(Code:31)

You want to upload CSV and Excel files using google.script.run.
When the file is uploaded, you want to convert to Google Spreadsheet.
You want to retrieve the filename of the uploaded file.
If my understanding is correct, how about this modification? Please think of this as just one of several answers.
I think that in your script, it is required to modify the Google Apps Script.
Modification points:
Value of e.theFile of uploadFile(e) is the blob. So you can retrieve the filename using getName().
You can convert the CSV and Excel format to Google Spreadsheet using Drive API. In this case, I used Drive API v2 at Advanced Google Services.
The reason of the error of Invalid argument: file.contentType at uploadFile is that the mimeType of MimeType.GOOGLE_SHEETS cannot be used with createFile().
Modified script:
Please modify uploadFile() as follows. Before you use this script, please enable Drive API at Advanced Google Services, and set the folder ID to folderId.
function uploadFile(e) {
Logger.log("Uploading file!");
// I modified below script.
var folderId = "###"; // Please set the folder ID here.
var blob = e.theFile;
var filename = blob.getName();
var mimeType = blob.getContentType();
if (mimeType == MimeType.CSV || mimeType == MimeType.MICROSOFT_EXCEL || mimeType == MimeType.MICROSOFT_EXCEL_LEGACY) {
return Drive.Files.insert({title: filename, mimeType: MimeType.GOOGLE_SHEETS, parents: [{id: folderId}]}, blob).title;
}
return "";
}
References:
Class Blob
Advanced Google Services
Files: insert of Drive API v2
If I misunderstood your question and this was not the result you want, I apologize.

Related

When trying to convert ppt to Google Slide receive converting error

In my google script program, I am trying to iterate over a folder and make all of the ppt files into google slide files.
function makeSlides(url) {
slideUrls = [];
var id = getId(url);
var powerPoints = DriveApp.getFolderById(id).getFilesByType(MimeType.MICROSOFT_POWERPOINT);
// turn ppt into slides
while(powerPoints.hasNext()) {
var powerPoint = powerPoints.next()
try{
var sheet = powerPoint.getBlob().getAs(MimeType.GOOGLE_SLIDES);
DriveApp.getFolderById(url).createFile(sheet)
Logger.log("OK " + powerPoint.getName());
}catch(e) {
Logger.log("ERROR: " + e)
}
}
After checking the logs I get an error
Exception: Converting from application/vnd.openxmlformats-officedocument.presentationml.presentation to application/vnd.google-apps.presentation is not supported.
I know within the UI of Google Drive, you can open a ppt as a Google Slide. Is there any work around to this? Or am I doing it wrong?
I did find this but this is the opposite of what I am trying to accomplish.
It cannot convert from Powerpoint format to Google Slides using getAs(). You can achieve this using Drive API. In this modification, I used Drive API using Advanced Google Services.
When you use this script, please enable Drive API at Advanced Google Services and API console. You can see about this at here.
Modified script:
Please modify as follows.
From:
var sheet = powerPoint.getBlob().getAs(MimeType.GOOGLE_SLIDES);
DriveApp.getFolderById(url).createFile(sheet)
To:
Drive.Files.insert({title: powerPoint.getName(), mimeType: MimeType.GOOGLE_SLIDES}, powerPoint.getBlob());
Note:
In this modified script, the converted file is created to the root folder. If you want to create in the specific folder, please modify from {title: powerPoint.getName(), mimeType: MimeType.GOOGLE_SLIDES} to {title: powerPoint.getName(), mimeType: MimeType.GOOGLE_SLIDES, parents: [{id: folderId}]}.
If you want to retrieve the file ID from the converted file, please use var id = Drive.Files.insert({title: powerPoint.getName(), mimeType: MimeType.GOOGLE_SLIDES}, powerPoint.getBlob()).id.
References:
Advanced Google Services
Drive API
Drive.Files.insert
If I misunderstand your question, please tell me. I would like to modify it.

Batch convert jpg to Google Docs

I have a folder of jpgs in Google Drive that I would like to convert to Google Docs. Now I can select each one manually and in the context menu "Open in Google Docs" This creates a new document with the image at the top of the page and OCR text below. I just want to do this with all my images.
There is a script here which converts gdoc to docx which I ought to be able to adapt for my case but I don't seem to be able to get it to work.
Here is my adapted script:
function convertJPGtoGoogleDocs() {
var srcfolderId = "~~~~~~~~~Sv4qZuPdJgvEq1A~~~~~~~~~"; // <--- Please input folder ID.
var dstfolderId = srcfolderId; // <--- If you want to change the destination folder, please modify this.
var files = DriveApp.getFolderById(srcfolderId).getFilesByType(MimeType.JPG);
while (files.hasNext()) {
var file = files.next();
DriveApp.getFolderById(dstfolderId).createFile(
UrlFetchApp.fetch(
"https://docs.google.com/document/d/" + file.getId() + "/export?format=gdoc",
{
"headers" : {Authorization: 'Bearer ' + ScriptApp.getOAuthToken()},
"muteHttpExceptions" : true
}
).getBlob().setName(file.getName() + ".docx")
);
}
}
Can anyone help?
Thanks.
You want to convert Jpeg files in a folder as Google Document.
When the Jpeg file is converted to Google Document, you want to use OCR.
If my understanding is correct, how about this modification?
Modification points:
In the script you modified, MimeType.JPG returns undefined. So the script in while is not run.
Please use MimeType.JPEG.
The script of this answer is used for exporting Google Document as Microsoft Word. Unfortunately, that script cannot be directly used for converting Jpeg file to Google Document.
If you want to modify the script of this answer, how about modifying as follows?
When you use this script, please enable Drive API at Advanced Google Services. By this, the API is automatically enabled at API console. The specification of Google Apps Script Project was Changed at April 8, 2019.
Modified script:
function convertJPGtoGoogleDocs() {
var srcfolderId = "~~~~~~~~~Sv4qZuPdJgvEq1A~~~~~~~~~"; // <--- Please input folder ID.
var dstfolderId = srcfolderId; // <--- If you want to change the destination folder, please modify this.
var files = DriveApp.getFolderById(srcfolderId).getFilesByType(MimeType.JPEG); // Modified
while (files.hasNext()) {
var file = files.next();
Drive.Files.insert({title: file.getName(), parents: [{id: dstfolderId}]}, file.getBlob(), {ocr: true}); // Modified
}
}
Note:
If there are a lot of files in the source folder, there is a possibility that the limitation of script runtime (6 min / execution) exceeds.
References:
Enum MimeType
Drive.Files.insert
If I misunderstand your question, please tell me. I would like to modify it.

Get the file ID of a Library

The basic case is 2 files:
Admin file. Library.
User file.
I use a library file as admin file, and store some settings on its sheet. In a User file, I have a code, that needs an access to Admin file.
The code in a library:
SpreadsheetApp.getActive();
won't work, it will return the User file when running from a library.
Is there a code to have an access to a library file (spreadsheet)?
I need this because do not want to hardcode the ID of a library, in order to make it work with different copies of a library file.
I think of a solution similar to Excel's:
Set book = ThisWorkbook
The code in Excel will always return file where the code is.
How about this sample script? Recently, Google Apps Script API was added. By this, users can easily manage GAS project files. This sample script uses this API.
In order to use this sample script, please do the following flow.
Installation
Enable Google Apps Script API at API console.
If you have already opened the script editor, you can access there by this link.
Retrieve current scopes.
On script editor, File -> Project properties -> Scopes
Copy scopes.
Add a scope of https://www.googleapis.com/auth/script.projects to the Manifests file (appsscript.json) of the script editor. https://www.googleapis.com/auth/script.projects.readonly may be able to be also used in this situation.
On script editor, View -> Show manifest file
Add "oauthScopes": ["https://www.googleapis.com/auth/script.projects", "https://www.googleapis.com/auth/script.external_request", "### other scopes ###"] to appsscript.json, and save.
In this sample, https://www.googleapis.com/auth/script.external_request is also required.
If your script needs other scopes, please add them here.
Copy and paste this sample script, and run. And please authorize.
Please input Identifier for the library and fileId of project file that the library was installed.
Sample script :
function fetch(id) {
var url = "https://script.googleapis.com/v1/projects/" + id + "/content";
var params = {
method: "get",
headers: {"Authorization": "Bearer " + ScriptApp.getOAuthToken()},
muteHttpExceptions: true
};
return JSON.parse(UrlFetchApp.fetch(url, params).getContentText()).files;
}
function main() {
var Identifier = "### Identifier ###"; // Identifier for the library.
var fileId = "### fileId ###"; // fileId of project file that the library was installed.
var files = fetch(fileId);
var library = files.filter(function(e){return (e.type == "JSON" && e.name == "appsscript")})[0];
var source = JSON.parse(library.source);
var libraryId = source.dependencies.libraries.filter(function(e){return e.userSymbol == Identifier})[0].libraryId;
var libraryCode = fetch(libraryId);
Logger.log(libraryCode)
}
Note :
The flow of this sample script is as follows.
Retrieve the library ID from fileId of project file that the library was installed.
Retrieve the library code from the library ID.
The result of libraryCode is json data. This data is raw data of project. You can retrieve the library code from it.
References :
Google Apps Script API
Manifests
If I misunderstand your question, I'm sorry.
Edit :
Unfortunately, in current stage, I think that it cannot achieve to retrieve Spreadsheet ID that the library was installed under the situation.

How to have a Google Form retrieve spreadsheet data and display it on a Google Site?

Desired Outcome: To be able to enter a search term in a Google Form (presumably but not necessarily; could be a form in a standard web page) and have the relevant data retrieved from a Google Sheet and displayed in Google Site web app.
I learnt how to retrieve data from a parameterized URL and display in a Google Site in this question: How to include data in a URL for a Google Apps Script web app to read?
So the "tech" for retrieving and displaying spreadsheet data is there but I don't know where to start when it comes to pulling the data from a online form rather than a URL. Perhaps on submit, read the form values somehow, create a parameterized URL and go to that page to display the data?
How about this sample? This is a very simple sample script. Please modify it to your environment. This sample retrieves data on Spreadsheet using the search text, and displays the matched row. In order to use this sample, please carry out as follows.
Copy and paste the following scripts to your script editor.
Input spreadsheet ID and sheet name which is used for searching data.
Deploy Web Apps and run script.
Input search text and push "ok" button.
Script :
Google Apps Script : code.gs
function doGet() {
return HtmlService.createTemplateFromFile('index').evaluate();
}
function getData(e) {
var id = "### Spreadsheet ID ###";
var sheetname = "### Sheet name ###";
var data = SpreadsheetApp.openById(id).getSheetByName(sheetname).getDataRange().getValues();
var ar = [];
data.forEach(function(f) {
if (~f.indexOf(e.searchtext)) {
ar.push(f);
}
});
return ar;
}
HTML : index.html
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<form>
<input type="text" name="searchtext">
<input type="button" value="ok" onClick="getData(this.parentNode)" />
</form>
<pre id="disp"></pre>
<script>
function dispData(e) {
$('#disp').text(JSON.stringify(e));
}
function getData(e) {
google.script.run.withSuccessHandler(dispData).getData(e);
}
</script>
Sample spreadsheet :
Result :
If I misunderstand your question, I'm sorry.

Google app scripts: email a spreadsheet as excel

How do you make an app script which attaches a spreadsheet as an excel file and emails it to a certain email address?
There are some older posts on Stackoverflow on how to do this however they seem to be outdated now and do not seem to work.
Thank you.
It looks like #Christiaan Westerbeek's answer is spot on but its been a year now since his post and I think there needs to be a bit of a modification in the script he has given above.
var url = file.exportLinks[MimeType.MICROSOFT_EXCEL];
There is something wrong with this line of code, maybe that exportLinks has now depreciated. When I executed his code it gave an error to the following effect:
TypeError: Cannot read property "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" from undefined.
The workaround is as follows:
The URL in the above line of code is basically the "download as xlsx" URL that can be used to directly download the spreadsheet as an xlsx file that you get from File> Download as > Microsoft Excel (.xlsx)
This is the format:
https://docs.google.com/spreadsheets/d/<<<ID>>>/export?format=xlsx&id=<<<ID>>>
where <<>> should be replaced by the ID of your file.
Check here to easily understand how to extract the ID from the URL of your google sheet.
Here's an up-to-date and working version. One prerequisite for this Google Apps script to work is that the Drive API v2 Advanced Google Service must be enabled. Enable it in your Google Apps script via Resources -> Advanced Google Services... -> Drive API v2 -> on. Then, that window will tell you that you must also enabled this service in the Google Developers Console. Follow the link and enable the service there too! When you're done, just use this script.
/**
* Thanks to a few answers that helped me build this script
* Explaining the Advanced Drive Service must be enabled: http://stackoverflow.com/a/27281729/1385429
* Explaining how to convert to a blob: http://ctrlq.org/code/20009-convert-google-documents
* Explaining how to convert to zip and to send the email: http://ctrlq.org/code/19869-email-google-spreadsheets-pdf
* New way to set the url to download from by #tera
*/
function emailAsExcel(config) {
if (!config || !config.to || !config.subject || !config.body) {
throw new Error('Configure "to", "subject" and "body" in an object as the first parameter');
}
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var spreadsheetId = spreadsheet.getId()
var file = Drive.Files.get(spreadsheetId);
var url = 'https://docs.google.com/spreadsheets/d/'+spreadsheetId+'/export?format=xlsx';
var token = ScriptApp.getOAuthToken();
var response = UrlFetchApp.fetch(url, {
headers: {
'Authorization': 'Bearer ' + token
}
});
var fileName = (config.fileName || spreadsheet.getName()) + '.xlsx';
var blobs = [response.getBlob().setName(fileName)];
if (config.zip) {
blobs = [Utilities.zip(blobs).setName(fileName + '.zip')];
}
GmailApp.sendEmail(
config.to,
config.subject,
config.body,
{
attachments: blobs
}
);
}
Update: I updated the way to set the url to download from. Doing it through the file.exportLinks collection is not working anymore. Thanks to #tera for pointing that out in his answer.