Create a simple Google Docs File in a Subfolder - google-drive-api

I am a beginner in Scripting and for my training I try to create a simple Google File in a subfolder:
function createFilesInSubFolder() {
//This creates the Workingfolder
var folder = DriveApp.createFolder('MyWorkingFolder');
//This creates a file in the folder
var file = folder.createFile('FileName','Text in the File',MimeType.GOOGLE_DOCS);
//Mime.Typen: https://developers.google.com/apps-script/reference/base/mime-type
}
The script gives me this error:
Ungültiges Argument: file.contentType (Zeile 6, Datei "Code")
The script works when I create a minetype JPEG or PLAIN_TEXT. Where is the trick to create a Google document direct in a subfolder? To create a file in the rootfolder works with the command DocumentApp.create('GoogleStandardFileType').

In the case of creating Google Docs, it uses DocumentApp or Drive API. And when Google Docs are created, there are 2 methods for creating it in a subfolder.
Method 1
In this method, a document is created by DocumentApp.create() and changed the parents (folder) from initial folder (root folder) to MyWorkingFolder.
Script :
var doc = DocumentApp.create('FileName');
doc.getBody().editAsText().insertText(0, 'Text in the File');
var file = DriveApp.getFileById(doc.getId());
var destfolder = DriveApp.createFolder('MyWorkingFolder');
var sourcefolder = file.getParents().next();
destfolder.addFile(file);
sourcefolder.removeFile(file);
Method 2
In this method, a document is created by Drive API. In this case, when the document is created, the document is directly created to the subfolder MyWorkingFolder.
Script :
DocumentApp.openById(Drive.Files.insert({
"title": "FileName",
"mimeType": "application/vnd.google-apps.document",
"parents": [{"id": DriveApp.createFolder('MyWorkingFolder').getId()}]
}).id).getBody().editAsText().insertText(0, 'Text in the File');
Note :
When you use Drive API, please enable Drive API on Google API Console as follows.
In the script editor, select Resources > Cloud Platform Project
At the bottom of the dialog, click the link for the Google API Console.
In the console, click into the filter box and type part of the name of the API "Drive API", then click the name once you see it.
On the next screen, click Enable API.
Close the Developers Console and return to the script editor. Click OK in the dialog.
If I misunderstand your question, I'm sorry.

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.

File movement between Google Shared Drive (team drive) folders using Apps Script

I am creating a workflow for Shared Drive (Team Drive) where I have 3 folders under team drive:
TO BE APPROVED
APPROVED
REJECTED
I am sending a document from TO BE APPROVED folder for approval, if user approves it then this document should move to APPROVED folder. Same logic for REJECTED.
Now my question is how can I move a document between Shared Drive folders. DriveApp.getFolderById(folderId).addFile() is not working as I can not have more than one parent in Team Drive. DriveApp.getFolderById(folderId).createFile() is working but it is creating a whole new file with new ID which is not fulfilling my purpose of approval workflow as this is a whole new file.
Is there any way to move file or copy/replace any operations which will not change my file's ID? I tried for REST APIs as well but couldn't found any.
Okay looks like I found an answer, via REST API I can update file's parents. I've made that call and it's working.
Here's the sample.
var apiUrl = "https://www.googleapis.com/drive/v3/files/fileId?addParents=newFolderId&removeParents=oldFolderId&supportsTeamDrives=true";
var token = ScriptApp.getOAuthToken();
var header = {"Authorization":"Bearer " + token};
var options = {
"method":"PATCH",
"headers": header
};
var res = UrlFetchApp.fetch(apiUrl, options);
UPDATE
Using Advance Services API we can achieve the same, here's the answer I've received from Aliaksei Ivaneichyk
function moveFileToFolder(fileId, newFolderId) {
var file = Drive.Files.get(fileId, {supportsTeamDrives: true});
Drive.Files.patch(file, fileId, {
removeParents: file.parents.map(function(f) { return f.id; }),
addParents: [newFolderId],
supportsTeamDrives: true
});
}
Here you need to Enable Drive SDK advance services if you are using Appscript. In case of Appmaker Add Drive SDK as Service in Settings Option.

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.

Update (Overwrite) one Apps Script file with another Apps Script file using Apps Script Code

Overwrite file. Overwrite Apps Script file.
This is not a question to create a new Apps Script file. That won't help me. I need to update an existing Apps Script file. This question is similar to creating a new file, but it's not the same issue. The syntax for an update, and the requirements for an update may be different enough from creating a new file, that I can't get a solution from the answer about creating a new file. I've looked at an answer for creating a new file, and that has not answered my question.
I have tried using the Advanced Drive Service to update an existing Apps Script file with another Apps Script file.
function updateMyScript() {
var targetFileID = 'File ID';
var dataSource = {
"files": [
{
"id":"739a57da-f77c-4e1a-96df-7d86ef227d62",
"name":"Code",
"type":"server_js",
"source":"function doGet() {\n return HtmlService.createHtmlOutputFromFile(\u0027index\u0027);\n}\n"
},
{
"id":"2c7e8b5a-dbc5-4cd2-80e9-77b6291b3167",
"name":"index",
"type":"html",
"source":"\u003chtml\u003e\n \u003cbody\u003e\n New message!!\n \u003c/body\u003e\n\u003c/html\u003e"
}
]
};
var filesResource = Drive.Files.get(targetFileID);
var blob = Utilities.newBlob(JSON.stringify(dataSource), "application/vnd.google-apps.script+json");
var whatRezult = Drive.Files.update(filesResource, targetFileID, blob, {"convert":"true"});
Logger.log('whatRezult: ' + whatRezult);
};
The id properties in the dataSource object are id's of each specific .gs or html file inside of the project. I got those id's by downloading the "target" Apps Script file to JSON, then opening up the JSON file and copying out the file id's. So, I know that those are correct. I'd like a way to retrieve those individual file ID's from the project with code. The post about creating a new apps script file, does not explain how to get the "sub" ID's from the project file. The project file ID is not the same as each file ID inside of the project. The name and type properties are obvious. And there are only two types of files which, from the example, have types of server_js and "html". It looks like the source for the internal files to the Apps Script project file can be a string literal. So, you can just type in whatever you want the replacement content to be.
The target ID is self explanatory.
If there is a way to do this with either the Advanced Drive Service or UrlFetchApp.fetch() that will answer my question. I only want to use Apps Script. So, I'm not looking for a solution written in some other language, or that is run from outside of Apps Script.
With the above code, I'm getting an error from the next to last line:
Drive.Files.update(filesResource, targetFileID, blob, {"convert":"true"});
The error is:
The app does not have the required scope to update Apps Scripts.
So, obviously, it's looking for a scope setting to be indicated somewhere. I'm guessing that it would go into the the fourth parameter for the options.
You need to ask for the special Drive-AppsScript scope:
https://www.googleapis.com/auth/drive.scripts
Since you cannot tell Apps Script to ask this scope for you (it determines its own scopes automatically by analyzing your code). You need to do the oAuth dance yourself (by using Eric's lib for example). But then since you also cannot set this token you retrieved yourself for the script to use in its built-in or advanced service calls (not that I know of anyway), you'll have to do the UrlFetch call manually too, and pass your "custom" token in the header (like shown in the "create new script" question.
The UrlFetch call to update is very similar to the insert one. Just change the method to PUT and add the apps script project id in the path.
var url = "https://www.googleapis.com/upload/drive/v2/files/" + scriptID;
var requestBody = ...; //the same
var options = {
"headers": {
'Authorization': 'Bearer ' + yourManuallyFetchedToken,
},
"contentType": "application/vnd.google-apps.script+json",
"method" : "PUT", //changed here from POST to PUT
"payload": JSON.stringify(requestBody)
}
I've created a GitHub repository of a project that will update one Apps Script file (the target) from a source Apps Script file. It's totally free to copy and use.
GitHub Repository - apps-script-update
See the Read Me file in the GitHub repository for instructions
The code at GitHub is using the newer Apps Script API, which is different from the original answer.
The new Apps Script API now allows for an Apps Script project to be updated. The project that is updated can be bound to a document. (Sheet, Form, Doc) This code uses the REST API, and makes a PUT request from Apps Script code using UrlFetchApp.fetch(url,options) This code is being run from an Apps Script file to update another Apps Script file.
The Apps Script API must be enabled for the Apps Script file running the code. The Apps Script API is enabled in the Google Cloud console. From the code editor, choose "Resources" and "Cloud Platform project" Search for Apps Script API and enable it.
function updateContent(scriptId,content,theAccessTkn) {
//try{
var options,payload,response,url;
if (!content) {
//Error handling function
return;
}
if (!theAccessTkn) {
theAccessTkn = ScriptApp.getOAuthToken();
}
//https://developers.google.com/apps-script/api/reference/rest/v1/projects/updateContent
url = "https://script.googleapis.com/v1/projects/" + scriptId + "/content";
options = {
"method" : "PUT",
"muteHttpExceptions": true,
"headers": {
'Authorization': 'Bearer ' + theAccessTkn
},
"contentType": "application/json",//If the content type is set then you can stringify the payload
"payload": JSON.stringify(content)
};
response = UrlFetchApp.fetch(url,options);
response = JSON.parse(response);//Must be parsed even though it shows as coming back as an object
//Logger.log('typeof response: ' + typeof response)
//Logger.log('response 29 in file GS_Update: ' + JSON.stringify(response).slice(0,45))
return response;
//} catch(e) {
//Logger.log(response)
//}
};
You must use the correct scopes in order for the code to run without an authorization error.
The scopes can be set in the appsscript.json file. To view the appsscript.json file, you must first click the View menu, and choose the "Show manifest" menu item.
{
"timeZone": "America/New_York",
"oauthScopes": [
"https://www.googleapis.com/auth/script.projects",
"https://www.googleapis.com/auth/script.external_request"
],
"dependencies": {
},
"exceptionLogging": "STACKDRIVER"
}
The first time that the Apps Script API is used, the PUT request may not work, and will return an error with a link to the Google Cloud console. That's why it's important to view the return response Logger.log('typeof response: ' + typeof response) from the response = UrlFetchApp.fetch(url,options); statement.

Create new file in a folder with Apps Script using Google Advanced Drive service

There are four ways to create a new file:
DocsList - Shown as DocsList in the Main List. Built in to Apps Script.
DriveApp - Shown as Drive in the Main List. Built in to Apps Script.
Drive API - Also shown as Drive in the Main List. Must be added to Apps Script.
DocumentApp - Shown as Document in the Main List. Built in, but only creates a document file.
They are all called services. Drive API is called an advanced service. So, which one should you use? I don't know, it depends. This question is about the Drive API Advanced Service.
I don't want to use 2 or 3 of the services to get the job done. I'd like to just use one of them. But to decide which one to use, I need to know the capabilities and options of all of them. If the simplest and easiest one to use will do everything I want, then I'll use that.
If I can create a new file with Drive API, but then I need to use the DriveApp service to move the file I created with Drive API, to the folder I want it in, then using Drive API in that particular situation is pointless.
I can create a new file in my Google Drive from a Google Apps Script .gs code, but the file gets written to the main 'My Drive'. I want to write the file directly to a sub-folder. My current code is:
var fileNameSetA = 'someFile.jpg';
var uploadedBlobA = an image uploaded with a file picker;
var fileTestDrive = {
title: fileNameSetA,
mimeType: 'image/jpeg'
};
fileTestDrive = Drive.Files.insert(fileTestDrive, uploadedBlobA);
Even though the code works, I have no idea why the syntax is the way it is, and I can't find documentation that tells me why. I can find a list of properties:
The title: and mimeType: are Optional Properties as part of the Request Body. From the example, the Optional Properties are obviously put in a key:value paired object. So, is the syntax:
Drive.Files.insert(optional properties, content);
There are also Required query parameters of:
uploadType --> media, multipart, resumable
But I don't see any required uploadType parameter designated anywhere in the example code. So, I don't understand Google's documentation.
Google Documentation Insert
Is it possible to write directly to a specific drive with Google Advanced Drive service in a Apps Script .gs code file? How do I do it?
The easiest way to create a new file is to use DriveApp which comes with pure Google Apps Script:
var dir = DriveApp.getFolderById("{dir_id}");
var file = dir.createFile(name, content);
If you do not know exact directory's id you can get the folder by its name:
var dir = DriveApp.getFoldersByName(name).next();
The next() is there because getFoldersByName() returns collection of all directories whose names match given value.
Also check DriveApp docs: https://developers.google.com/apps-script/reference/drive/drive-app
Maybe this is a bit late, but by looking at the REST API docs, it shows that you can use Drive.Files.insert to insert into any folder. You simply have to add the folder's ID in the properties of the file you are inserting as such:
var file = {
title: 'myFile',
"parents": [{'id':folder.getId()}], //<--By setting this parent ID to the folder's ID, it creates this file in the correct folder.
mimeType: 'image/png'
};
Folder ID can be obtained from the shareable link using the Google Drive GUI or as shown here. (e.g. Use the Execute function on the right.)
Alternatively, you can access the folder by name by replacing the folder.getID() with Drive.getFoldersByName('name of folder').
This is helpful because Drive.Files.insert() accepts arguments while Drive.createFile() and Drive.createFolder() do not.
The documentation for INSERT for the Drive API is found at this link:
Drive API for INSERT
There is a section for Request body. One of the Optional Properties for Insert is parents[]. The brackets [] indicate that a list of parents can be designated. The documentation for parents[] states this:
Collection of parent folders which contain this file. Setting this
field will put the file in all of the provided folders. On insert, if
no folders are provided, the file will be placed in the default root
folder.
So, . . . using Insert in Drive API, . . . . CAN write a new file directly to a subfolder. It's possible.
Now, the nomenclature and syntax for the Google Drive SDK, HTTP request is different than what is inside of Apps Script.
The syntax for invoking the Drive API HTTP Request inside of a .gs file is one of the following three:
Drive.Files.insert(FILE resource)
Drive.Files.insert(FILE resource, BLOB mediaData)
Drive.Files.insert(FILE resource, BLOB mediaData, OBJECT optionalArgs)
The syntax shown in the list above is from the auto-complete drop down list inside the Apps Script code editor. If you type Drive.Files. a list of possible methods will appear. I can't find information about the syntax anywhere in the online documentation.
So, where does the parents[] optional property go? Well, it's not a Blob, so we can rule that out. It's either FILE resource, or OBJECT optionalArgs. optionalArgs indicates that it's an object, but FILE resource is actually also an object.
In the examples, the FILE resource is constructed as key:value pair object.
Uploading Files - Advanced Drive Service - Google Documentation
Direct Answer to Question
This summary from https://developers.google.com/apps-script/advanced/drive sums things up pretty well:
The advanced Drive service allows you to use the Google Drive web API
in Apps Script. Much like Apps Script's built-in Drive service, this
API allows scripts to create, find, and modify files and folders in
Google Drive. In most cases, the built-in service is easier to
use, but this advanced service provides a few extra features,
including access to custom file properties as well as revisions for
files and folders.
Like all advanced services in Apps Script, the advanced Drive
service uses the same objects, methods, and parameters as the public
API.
Essentially DriveApp is easier to use than Drive, but Drive gives you more functionality since it shares the same functionality of the public API. I was not able to see how to save a file to a Shared/Team drive using DriveApp, so I ended up using Drive. The pain came around lack of documentation for the Google Apps Script implementation of Drive.
Explanation of My Solution and Code Sample:
A specific implementation of saving a file to Google drive, but this will likely be useful for others. It took me a whole day to figure this out since the documentation and code examples for Google Apps scripts is severely lacking. My use case was for saving a JSON file to a shared Google Drive (Team Drive).
There are three parameters that I did not have at first and my files were not uploading. I am not sure if all are necessary. One was the "kind": "drive#parentReference" part of the parents metadata. The next was "teamDriveId": teamDriveId which is also in the metadata. The last parameter was "supportsAllDrives": true which I passed in the optional parameter location of Drive.Files.insert().
I found the API explorer on https://developers.google.com/drive/api/v2/reference/files/insert to be very useful in figuring out which parameters were needed and how they needed to be formatted. I basically edited values in the explorer till I got a network request that worked. I then pulled the parameters I used into my Google Apps script.
/**
* Creates a JSON file in the designated Google Drive location
* #param {String} jsonString - A JS string from the result of a JSON.stringify(jsObject)
* #param {String} filename - The filename. Be sure to include the .json extension
* #param {String} folderId - The ID of the Google Drive folder where the file will be created
* #param {String} teamDriveId - The ID of the team drive
* #return {void}
*/
function createJSONFileInDriveFolder(jsonString, filename, folderId, teamDriveId) {
var metadata = {
"title": filename,
"mimeType": "application/json",
"parents": [
{
"id": folderId,
"kind": "drive#parentReference"
}
],
"teamDriveId": teamDriveId
};
var optionalParams = {
"supportsAllDrives": true
};
try {
var jsonBlob = Utilities.newBlob(jsonString, 'application/vnd.google-apps.script+json');
Drive.Files.insert(metadata, jsonBlob, optionalParams);
} catch (error) {
Logger.log(error);
}
}
var searchthreads = GmailApp.search('in:inbox AND after:2020/11/30 AND has:attachment');//"in:all -in:trash category:social older_than:15d
Logger.log("GMAIL thread 0:"+ searchthreads[0].getId());
Logger.log("GMAIL thread 1:"+ searchthreads[1].getId());
Logger.log("GMAIL thread 2:"+ searchthreads[2].getId());
Logger.log("Active User: " + me);
Logger.log("Search Thread: " + searchthreads.length);
Logger.log("Gmail lenght" + gmailthread.length);
//Logger.log("Gmail lenght" + gmailMessages.length);
for (var i in searchthreads){
var messageCOunt = searchthreads[i].getMessageCount();
Logger.log("messageCOunt :" + messageCOunt);
var messages = searchthreads[i].getMessages();
for (var m in messages){
var messagesender = messages[m].getFrom();
var messageDate = messages[m].getDate();
var messageReplyTo = messages[m].getReplyTo();
var messagesubject = messages[m].getSubject();
var messagebody = messages[m].getSubject();
var messagephoneNo = messages[m].getSubject();
//messages[m].isInInbox();
var messageid = messages[m].getId();
var messageplainbody = messages[m].getSubject();//messages[0].getPlainBody();
var EmailStatus ='N';
var ApptStatus = "CVReceived";// Tracking till candidate offer and payout
var messageattachement = messages[m].getAttachments();
//var png=UrlFetchApp.fetch(messageattachement).getBlob();
//https://drive.google.com/drive/folders/1RY4i6FwUvfy5OxrJ1pZTxJAOxjFFXbhz?usp=sharing
var folder = DriveApp.getFolderById("1RY4i6FwUvfy5OxrJ1pZTxJAOxjFFXbhz");
// DriveApp.getFolderById("1RY4i6FwUvfy5OxrJ1pZTxJAOxjFFXbhz").createFile(png);
//DriveApp.createFile();
for (var k in messageattachement){
var filename = messageattachement[k].getName();
var filesize = messageattachement[k].getSize();
var filecontent = messageattachement[k].getContentType();
var fileBlob = messageattachement[k].getAs(filecontent);
var filecpblob = messageattachement[k].copyBlob();
//folder.createFile(filename, messageattachement);
var file = {
title: filename,
"parents": [{'id':folder.getId()}],
mimeType: filecontent
};
file = Drive.Files.insert(file, filecpblob);
//DataStudioApp
Logger.log('ID: %s, File size (bytes): %s', file.id, file.fileSize);
//folder.createFile(filecpblob);
}
var processeddate = new Date();
I know it's been a while since this question was posted. But here is the solution to help other readers. When using Drive.Files.insert() method, in order to specify a location for the inserted file, you must specify the parents[] property within the FILE resource. So expanding on #Alan Wells response here is the syntax for writing a blob as Goggle Spreadsheet format in a specific folder.
let newFile = {title: 'Title goes here', parents: [{id: targetFolderId}]};
let savedFile = Drive.Files.insert(
newFile,
blobGoesHere,
{mimeType: MimeType.GOOGLE_SHEETS, convert: true});
Please note that parents: takes an array of objects. You can specify multiple locations for a single file (it will be created in all the specified folders). Even if you want to use a single location you still have to provide this object in a list.
I was able to use the DriveApp to create a file in a specified folder this way.
var driveFolder = DriveApp.getFolderByName("MyDriveFolder");
var file = driveFolder.createFile(formObject.txtReceipt);
file.setName("MyFile");
PS: formObject.txtReceipt is coming from a file upload control on a form in the html and this returns a blob