Google Apps Script to automatically open copied document after creating it? - google-apps-script

We are using sheets for our mom & pop store as our invoice. However, my mother-in-law keeps saving over our invoice and we're always having to go back and delete the filled in sections. She cannot seem to remember the steps of making a copy and then opening that. I am using a script (button) to create a copy of the original and it is renamed as the customer name & date into a specific folder. However, once we do that, we still have to navigate to the folder and open the new document. Is there there a way to do this after I click the button on our original document to open of the copy that was made? Here is the script that I am using.
function saveAsSpreadsheet()
{
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var range = sheet.getRange('Carolina Fireworks Order Form!C8');
sheet.setNamedRange('TestRange', range);
var TestRange = sheet.getRangeByName('Carolina Fireworks Order Form!C8').getValues();
Logger.log(TestRange);
var destFolder = DriveApp.getFolderById("1UdK90fEs3gkP4KZuUbmZbvvyVAW5ZMGw");
let name = SpreadsheetApp.getActiveSheet().getRange('C8').getValue();
const ds = Utilities.formatDate(new Date(),SpreadsheetApp.getActive().getSpreadsheetTimeZone(),"MM.dd.yy");
DriveApp.getFileById(sheet.getId()).makeCopy('TestRange', destFolder).setName(`${name}.${ds}`);
}

In your situation, how about the following modification?
From:
DriveApp.getFileById(sheet.getId()).makeCopy('TestRange', destFolder).setName(`${name}.${ds}`);
To:
const file = DriveApp.getFileById(sheet.getId()).makeCopy('TestRange', destFolder).setName(`${name}.${ds}`);
var js = `<script>window.open('${file.getUrl()}');google.script.host.close();</script>`;
var html = HtmlService.createHtmlOutput(js);
SpreadsheetApp.getUi().showModalDialog(html, 'Now loading.');
In this script, the URL is opened using Javascript on the dialog.
This is from this post
Note:
From MetaMan's comment
If you want this to work you will have to disable popup blocking
References:
showModalDialog(userInterface, title)
Window.open()

Related

sheet.getFormUrl() not found

When creating a copy of a spreadsheet that is linked to a form, a newSheets.getFormUrl() not found error occurs. The new spreadsheet is created since I'm able to add a new editor to it and it appears in the appropriate drive folder. Likewise, the expected new form is created and it is indeed linked to the the new spreadsheet. However, when trying to get a handle on the new form via getFormUrl(), the error occurs. I want to rename the new form and move it to a new folder but can't.
Also, although Spreadsheet.getFormURL() exists in the API, it doesn't appear in the typeahead when keying in the function. My Apps Script runtime is V8.
// generate the response sheet into the folder and add editor
var newSheet = DriveApp.getFileById(templateResponseSheetID).makeCopy('Contact Tracing RESPONSES - ' + name, childDocsFolder);
newSheet.addEditor(email);
var newform = newSheet.getFormUrl();
The problem is that newSheet is a File object but getFormUrl() is a method of Class Spreadsheet
instead of
var newform = newSheet.getFormUrl();
use
var spreadsheet = SpreadsheetApp.open(newSheet);
var url = spreadsheet.getFormUrl()

Google script create new spreadsheet and set as active

I can create a new spreadsheet using:
var newWorksheet = SpreadsheetApp.create("newWorksheetName");
However, how do I immediately set it as active so I can edit it?
As far as I know, I need to get the spreadsheet ID, to open it, but I don't know how to find this out automatically.
Try this:
var crNew = SpreadsheetApp.create("newWorksheetName");
var ssNew = SpreadsheetApp.openByUrl(crNew.getUrl());
where ssNew is the new Spreadsheet file.
Then you can use ssNew to directly access the new Spreadsheet file.
For example, the following will give you the name of the first sheet of the newly generated newWorksheetName:
Logger.log(ssNew.getSheets()[0].getName());
Output: Sheet1
Another example would be to change the name of the sheet:
ssNew.getSheets()[0].setName("newname");

Efficient Way of sending Spreadsheet over email using GAS function?

I am creating an addon for Google Sheets that my local High School's volunteer clubs can use to keep track of their member's volunteer hours. Most of the code is done and works very nicely, and I am currently working on a system that will send a member a spreadsheet listing all of the volunteer events that they have logged. I have GAS create a separate spreadsheet, and then send an email with that separate spreadsheet attached in PDF. When the email is received, the PDF is empty except for a singular empty cell at the top left of the page.
I am pretty new to GAS but have been able to grasp the content pretty easily. I have only tried one method of sending the Spreadsheet and that is by using the .getAs(MimeType.PDF). When I changed the "PDF" to "GOOGLE_SHEETS," GAS returned the error: "Blob object must have non-null data for this operation." I am not entirely sure what a Blob object is, and have not found any website or video that has fully explained it, so I am not sure how to go about troubleshooting that error.
I think I'm having a problem grabbing the file because it either sends an empty PDF or it returns an error claiming it needs "non-null data."
function TigerMail()
{
var Drive = DriveApp;
var app = SpreadsheetApp;
var LOOKUP = app.getActiveSpreadsheet().getSheetByName("Student
Lookup");
var Name = LOOKUP.getRange("E1").getValue();
Name = Name + "'s Hours";
//app.openById(Name+"'s Hours");
var HOURS = app.create(Name);
var ESheet = HOURS.getSheets()[0];
var ROW = LOOKUP.getLastRow();
var arr = LOOKUP.getRange("D1:J"+ROW).getValues();
var cell = ESheet.getRange("A1:G"+ROW);
cell.setValues(arr);
////////////////////////////////////////////////////
var LOOKUP = app.getActiveSpreadsheet().getSheetByName("Student
Lookup");
var cell = LOOKUP.getRange("D1");
var Addr = cell.getValue();
var ROW = LOOKUP.getLastRow();
var file = Drive.getFilesByName(Name);
var file = file.next();
var FORMAT = file.getAs(MimeType.GOOGLE_SHEETS);
TigerMail.sendEmail(Addr, "Hours", "Attached is a list of all of the
events you have volunteered at:", {attachments: [FORMAT]} );
}
the final four lines are where the errors are occurring at. I believe I am misunderstanding how the .next() and .getFilesByName() work.
(above the comment line: creating a spreadsheet of hours)
(below the comment line: grabbing the spreadsheet and attaching it to an email)
Here is the link to the Google Sheet:
https://docs.google.com/spreadsheets/d/1qlUfTWaj-VyBD2M45F63BtHaqF0UOVkwi04XwZFJ4vg/edit?usp=sharing
In your script, new Spreadsheet is created and put values.
You want to sent an email by attaching the file which was converted from the created Spreadsheet to PDF format.
If my understanding is correct, how about this modification? Please think of this as just one of several answers.
Modification points:
About Drive.getFilesByName(Name), unfortunately, there is no method of getFilesByName() in Drive.
I think that when you want to use the created Spreadsheet, HOURS of var HOURS = app.create(Name) can be used.
About var FORMAT = file.getAs(MimeType.GOOGLE_SHEETS), in the case of Google Docs, when the blob is retrieved, the blob is automatically converted to PDF format. This can be also used for your situation.
In order to save the values put to the created Spreadsheet, it uses SpreadsheetApp.flush().
When above points are reflected to your script, it becomes as follows.
Modified script:
Please modify as follows.
From:
var file = Drive.getFilesByName(Name);
var file = file.next();
var FORMAT = file.getAs(MimeType.GOOGLE_SHEETS);
To:
SpreadsheetApp.flush();
var FORMAT = HOURS.getBlob();
Note:
In your script, it seems that var ROW = LOOKUP.getLastRow() is not used.
References:
flush()
getBlob()
If I misunderstood your question and this was not the result you want, I apologize.

Programmatically delete a script

I was wondering if someone could offer me some advice.
I have a master spreadsheet, acting as a template. I have written a script which can be run from the menu (using addToUi command), which makes a copy of template spreadsheet.
The problem is that the script gets copied into the new spreadsheet also which I don't want.
Could anyone suggest a possible way around this please?
I did think a possible way was to get the script to open the copied template and delete the script but not sure if this is possible.
Here is the function which does the copying....
function createCopy() {
var myValue = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange("B8").getValue();
var destinationFolder = DriveApp.getFolderById("xxxxxxxxxxxxxxxx");
DriveApp.getFileById(SpreadsheetApp.getActiveSpreadsheet().getId()).makeCopy(myValue,destinationFolder);
}
(Cell reference B8 holds the value of what I called the copied spreadsheet).
Rayden, I use a function like that to just copy one sheet to a new spreadsheet and it doesn't drag the script with it. gDrive is the id for the Spreadsheet, tabName the individual sheet you want copied, Filename the name of the copy and destination the destination directory.
//******************************************************************************
//- This function takes a tab and makes it its own file
function tabToSheet(gDrive,tabName,fileName,destination){
var sh = SpreadsheetApp.openById(gDrive);
var ss = sh.getSheetByName(tabName);
//create a new document in the location given
var newSheet = SpreadsheetApp.create("TEMPDELETEME");
//copy the tab from current document to new document
ss.copyTo(newSheet);
var id = newSheet.getId();
newSheet.deleteSheet(newSheet.getSheetByName("Sheet1"));
os = newSheet.getSheets()[0];
os.setName(tabName);
var file = DriveApp.getFileById(id);
var folder = DriveApp.getFolderById(destination);
var finalId = file.makeCopy(fileName, folder).getId();
file.setTrashed(true);
return finalId;
}//*****************************************************************************
The difference is that i'm making a new sheet, then copying the tab rather than copying the entire file. You could add another tab and remove the variables if you want to copy multiple tabs.
I was having trouble implementing J.G.'s approach of moving individual sheets, so the approach I took was to add a conditional in front of the script to only run if the spreadsheet id was equal to the id of the original spreadsheet. My use case was trying to suppress a custom menu on the original workbook from reappearing on the copy, so it worked for that.
var bookId = spreadsheet.getId();
if (bookId === 'original spreadsheet id') {
*Function*
}

PDF Template Archiving

I have Created a form that generates a response sheet. I also have created a Doc which is a Template that my responses fill into. From here it was being turned into a PDF and e-mailed to specific recipients. I now need to archive these into specific folders based on a columns answer. I simply first would like to just be able to move or copy them into a specific folder. How is this possible. I have used multiple scripts but just cant see where the disconnect is. Any help would be greatly appreciated. Thank you enter link description here
You could try using some code like this:
function moveFileToFolder() {
var theFolder = DriveApp.getFolderById('your Folder ID');
var theFile = DriveApp.getFileById('Your File ID').makeCopy(theFolder);
var oldFileName = theFile.getName();
var archivedName = oldFileName.slice(5);
Logger.log('archivedName: ' + archivedName);
archivedName = "archive" + archivedName;
theFile.setName(archivedName);
}
To delete the old file without having to send it to the trash:
//This requires the Drive API To be turned on in the Advanced Google Services.
//RESOURCES menu, ADVANCED GOOGLE SERVICES
function deleteFile(idToDLET) {
//idToDLET = 'the File ID';
//This deletes a file without needing to move it to the trash
var rtrnFromDLET = Drive.Files.remove(idToDLET);
}