Google Spreadsheet show URL to a new File in pop up window - google-apps-script

I am currently trying to show some sort of pop up with a link to a new file that was created in the drive.
let me explain.
i have a database of employees
my spreadsheet as a button that copies information from a particular employee and then creates and fills another file with his info that then is saved/printed/or exported as pdf.
the script gets the URL of the file after this one is created, but i cant show it in the pop up window as a clickable link. here is my code.
(i am sorry if its a messy code, i learned 1 month ago)
function applicationcreator () {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var database = ss.getSheetByName("Database")
var rowname = database.getActiveCell().getRow()
var name = database.getRange(rowname, 4).getValues()
var ss2 = SpreadsheetApp.create("Resume")
var skill = ss2.getSheetByName("Sheet1")
var url =ss2.getUrl()
var form = ss.getSheetByName("Profilegenerator")
var copy = form.copyTo(ss2)
var form2 = ss2.getSheetByName("Copy of Profilegenerator").setName("Resume " + name)
var htmlOutput = HtmlService
.createHtmlOutput(url)
.setWidth(250) //optional
.setHeight(50); //optional
SpreadsheetApp.getUi().showModalDialog(htmlOutput, 'Employee Profile');
}
I greatly apreciate your help.

Related

App Script to insert an image from google drive to a google doc

Have collected info through a google form to a google sheet. Part of that info is the path to an image stored on drive. I have an app script that replaces key words on a document with the data collected in the sheet. I can get it to replace a piece of text, {{image}} for example with the url stored but I cannot get it to actually put a copy of the image into the document.
Any suggestions.
Code below
// #ts-nocheck
function autoFillGoogleDocFromForm(e) {
//e.values is an array of form values
var timestamp = e.values[0];
var email = e.values[1];
var who = e.values[2];
var employeeorcon = e.values[3];
var location = e.values[4];
var roomorarea = e.values[5];
var type = e.values[6];
var dateofworks = e.values[7];
var imageofcompletedcon = e.values[8];
var checkedoffintext = e.values[9];
var checkname = e.values[10];
var checkco = e.values[11];
var checkeddate = e.values[12];
//file is the template file, and you get it by ID
var file = DriveApp.getFileById("1WcYKvsRFbKK73J-ep66mR9drZyrkWap-x30rO-kVUcM");
//We can make a copy of the template, name it, and optionally tell it what folder to live in
//file.makeCopy will return a Google Drive file object
var folder = DriveApp.getFolderById("1MeU3-N3BMqOPvoaSGr2XassibR2XajdN")
var copy = file.makeCopy(roomorarea + '_' + timestamp, folder);
//Once we've got the new file created, we need to open it as a document by using its ID
var doc = DocumentApp.openById(copy.getId());
//Since everything we need to change is in the body, we need to get that
var body = doc.getBody();
//Then we call all of our replaceText methods
body.replaceText('{{location}}', location);
body.replaceText('{{room}}', roomorarea);
body.replaceText('{{completedby}}', who);
body.replaceText('{{checkedby}}', checkname);
body.replaceText('{{checkeddate}}', checkeddate);
body.replaceText('{{insdate}}', dateofworks);
body.replaceText('{{Empcon}}', employeeorcon);
body.replaceText('{{Type}}', type);
body.replaceText('{{image}}', imageofcompletedcon);
body.replaceText('{{methchk}}', checkedoffintext);
body.replaceText('{{checker}}', checkname);
body.replaceText('{{cocheck}}', checkco);
body.replaceText('{{datecheck}}', checkeddate);
//Lastly we save and close the document to persist our changes
doc.saveAndClose();
}
New to this, but tried insertimage etc, but really a bit beyond me.

How can I automate the adding of an image to a Google Doc from a url to a Drive file located in Google Sheets?

I have created a script to Auto Fill a Google Doc from a Google Form Submission (via Google Sheets) but I am struggling to auto fill an image into the Google Doc from a Drive url created in the Google Sheet (via an IF formula).
Essentially the Google doc is designed to simplify some admin work. The person submitting the Form chooses who the document is being written by and the digital signature of that person should be auto populated.
Here is what I have tried. Everything works well except the replaceTextToImage function - I am lost! Thanks in advance for your help.
function autoFillGoogleDocFromForm(e) {
//e.values is an array of form values
// #ts-ignore
var timestamp = e.values[0];
var COMPANYNAME = e.values[2];
var CONTACTNAME = e.values[7];
var DATE = e.values[9];
var STREET = e.values[3];
var TOWN = e.values[4];
var POSTCODE = e.values[5];
var COUNTRY = e.values[6];
var PURPOSE = e.values[10];
var JOBTITLE = e.values[8];
var DIRECTOR = e.values[11];
var ADDRESS_2 = e.values[12];
//file
var file = DriveApp.getFileById('1Dd78JKEHDr6JY3b3N9zxNHu6_7tK3-NSJPIdNVp_SNQ');
//We can make a copy of the template, name it, and optionally tell it what folder to live in
//file.makeCopy will return a Google Drive file object
var folder = DriveApp.getFolderById('1zyodJvnwabTRM7horzM0HRBw04b0IxbI')
var copy = file.makeCopy(COMPANYNAME + ',' + DATE, folder);
//Once we've got the new file created, we need to open it as a document by using its ID
var doc = DocumentApp.openById(copy.getId());
//Since everything we need to change is in the body, we need to get that
var body = doc.getBody();
//Then we call all of our replaceText methods
body.replaceText('{{COMPANYNAME}}', COMPANYNAME);
body.replaceText('{{CONTACTNAME}}', CONTACTNAME);
body.replaceText('{{DATE}}', DATE);
body.replaceText('{{STREET}}', STREET);
body.replaceText('{{ADDRESS_2}}', ADDRESS_2);
body.replaceText('{{TOWN}}', TOWN);
body.replaceText('{{POSTCODE}}', POSTCODE);
body.replaceText('{{COUNTRY}}', COUNTRY);
body.replaceText('{{PURPOSE}}', PURPOSE);
body.replaceText('{{JOBTITLE}}', JOBTITLE);
body.replaceText('{{DIRECTOR}}', DIRECTOR);
//function embedding image to document with a specified size
var replaceTextToImage = function(body, searchText, fileId) {
var width = 600; // Please set this.
var blob = DriveApp.getFileById('1Dd78JKEHDr6JY3b3N9zxNHu6_7tK3-NSJPIdNVp_SNQ').getBlob();
var r = body.findText(searchText).getElement();
r.asText().setText("");
var img = r.getParent().asParagraph().insertInlineImage(0, blob);
var w = img.getWidth();
var h = img.getHeight();
img.setWidth(width);
img.setHeight(width * h / w);
}
// Get the image fileID
var image = e.values[13]; // xx being the row number in which the link to the uploaded image is
var imageID = String(image).split("=")[1]; //gives you the fileID of the uploaded image
// Use the function replaceTextToImage
replaceTextToImage(body,'{{imageID}}', imageID); // replaces the {{image}} tag with the uploaded image
//Lastly we save and close the document to persist our changes
doc.saveAndClose();
}
So I think the problematic line in the code is this one:
var blob = DriveApp.getFileById('1Dd78JKEHDr6JY3b3N9zxNHu6_7tK3-NSJPIdNVp_SNQ').getBlob();
Please replace it with the following:
var blob = DriveApp.getFileById(fileId).getBlob();
What was happening is that since fileId is actually a defined parameter of the function replaceImageToText, removing it from inside the function and replacing it with an actual ID of a file resulted in the file with ID 1Dd78JKEHDr6JY3b3N9zxNHu6_7tK3-NSJPIdNVp_SNQ being considered as the image every single time the function was called instead of the image that was uploaded through your form.
I tried this out myself and it worked with a random image I uploaded to my drive. Please try this fix and see if it works for you too. Hope this helps!

Creating a view history log every time someone accesses a google doc and/or copies it using apps script

I wrote a script to log who and when opens a google doc. It works fine but the doc is a template for users to fill in so want to ensure whoever needs it will make a copy of the template through apps script.
I know users need edit access for the script to work but in terms of workarounds:
Is there a way for the script to still work if I give them a copy link or a template link?
Does it make more sense to use the google sheet as the base and pull from the google doc ID?
If that doesn't work than:
2) Is there a way to prompt them with a menu window to copy the file but delay it by x seconds on open?
//setups a count for the file
function setup() {
var propertyService = PropertiesService.getDocumentProperties();
propertyService.setProperty('viewCount', '0');
}
//logs the email and date of the user accessing the file
function onOpen(e) {
var count = parseInt(PropertiesService.getDocumentProperties().getProperty('viewCount'))+1;
PropertiesService.getDocumentProperties().setProperty('viewCount', count);
Logger.log(count);
var sheet = SpreadsheetApp.openById([spreadsheet ID]);
var user = Session.getActiveUser().getEmail();
var date = new Date();
sheet.getSheetByName('View Count').appendRow([user,date]);
}
You can add a menu item that creates a copy of the template for the user, logs the copy to the same sheet where you track who opens the file, and prompts the user to open their copy of the file to start working.
Steps
First: add these 3 functions.
The first, copyFile, creates a copy of the active document and names it the same plus the user's email. Then it logs the activity to the same change log, adding the new file's ID to the row. Finally, thanks to this nifty function it pops up a window with a link to the new file so the user can easily open it and start working.
The second, showAnchor, is the function that generates the HTML dialog box which presents the user a link to their new file.
The third, createMenu, adds a new menu item to the Google Docs nav bar, which prompts the user to copy the document. This, of course, triggers the copyFile function.
function copyFile() {
var thisDoc = DocumentApp.getActiveDocument()
var sheet = SpreadsheetApp.openById([spreadsheet ID]);
var user = Session.getActiveUser().getEmail();
var date = new Date();
var newCopy = DriveApp.getFileById(thisDoc.getId()).makeCopy(thisDoc.getName() + " " + user)
sheet.getSheetByName('View Count').appendRow([user,date,newCopy.getId()]);
var url = newCopy.getUrl()
showAnchor('Open Your File',url);
}
function showAnchor(name,url) {
var html = '<html><body>'+name+'</body></html>';
var ui = HtmlService.createHtmlOutput(html)
DocumentApp.getUi().showModelessDialog(ui," ");
}
function createMenu() {
const ui = DocumentApp.getUi();
const menu = ui.createMenu("Copy This Template");
menu.addItem("Copy", "copyFile");
menu.addToUi();
}
Then: add a call to createMenu() at the end of your onOpen script:
function onOpen(e) {
var count = parseInt(PropertiesService.getDocumentProperties().getProperty('viewCount'))+1;
PropertiesService.getDocumentProperties().setProperty('viewCount', count);
Logger.log(count);
var sheet = SpreadsheetApp.openById([spreadsheet ID]);
var user = Session.getActiveUser().getEmail();
var date = new Date();
sheet.getSheetByName('View Count').appendRow([user,date]);
createMenu();
}

Google App Script to copy and rename folder structure, including updating fields within a doc and sheet contained within the folders?

I must first apologise as I've never done any coding before. I've been doing a lot of googling and looking at other peoples codes to try and work out whats going on. I have the logic, but I don't know all the classes, triggers or even the right terminology! I can map out in my mind what needs to happen but need to learn the language first, so hoping you can point me in the right direction for learning materials, and help with this particular project.
I would like to automate something that we do a lot in our office, which is creating a new customer folder containing pre-defined sub-folders, and taking a template doc and sheet, filling out name and address fields, and saving them with the customer name appended with the doc or sheet name into relevant newly copied/created folders. I'm struggling to coherently explain this, so I've drawn something which will hopefully help:
sketch of folder structure with doc and sheet location
I've made a Google Form that posts results to a spreadsheet, and I've put a script in that sheet. I've worked out how to take a template sheet and doc, copy and rename them into a folder, but can't figure out what I need to do with the folders so they can be filed into unique places on drive.
Here is the code that I'm testing to copy the templates, add fields and rename and save:
function autoFillGoogleDocFromForm(e) {
var timestamp = e.values[0];
var title = e.values[1];
var firstName = e.values[2];
var lastName = e.values[3];
var emailAddress = e.values[4];
var premisesType = e.values[6];
//file is the template file, and you get it by ID
var file = DriveApp.getFileById('1QjYas1erxtQjLPduNMoY1EIEAjBOI5qbAMeX59qPib4');
//We can make a copy of the template, name it, and optionally tell it what folder to live in
//file.makeCopy will return a Google Drive file object
var folder = DriveApp.getFolderById('18GWERZFqgf9TbPfKDRX8gK02kbKpRLch')
var copy = file.makeCopy(lastName + ', ' + firstName, folder);
//Once we've got the new file created, we need to open it as a document by using its ID
var doc = DocumentApp.openById(copy.getId());
//Since everything we need to change is in the body, we need to get that
var body = doc.getBody();
var header = doc.getHeader();
//Then we call all of our replaceText methods
header.replaceText('{{Premises type}}', premisesType);
body.replaceText('{{First Name}}', firstName);
body.replaceText('{{Surname}}', lastName);
body.replaceText('{{Salutation}}', title);
body.replaceText('{{email}}', emailAddress);
body.replaceText('{{Premises type}}', premisesType);
//Lastly we save and close the document to persist our changes
doc.saveAndClose(); }
// REPLICATE ABOVE WITH SHEETS, fills out cell G2 with test info
function autoFillGoogleSheetFromForm(e) {
var timestamp = e.values[0];
var title = e.values[1];
var firstName = e.values[2];
var lastName = e.values[3];
var emailAddress = e.values[4];
var premisesType = e.values[6];
//file is the template file, and you get it by ID
var file = DriveApp.getFileById('1yvOtPcnGMQnE7Hc0d6vVMSG2Q5nY9u-MijaDZ51jlOU');
//We can make a copy of the template, name it, and optionally tell it what folder to live in
//file.makeCopy will return a Google Drive file object
var folder = DriveApp.getFolderById('18GWERZFqgf9TbPfKDRX8gK02kbKpRLch')
var copy = file.makeCopy(lastName + ', ' + firstName, folder);
//Once we've got the new file created, we need to open it as a document by using its ID
var ss = SpreadsheetApp.openById(copy.getId());
// ss is now the spreadsheet the script is associated with
var sheet = ss.getSheets()[0];
// sheets are counted starting from 0
// sheet is the first worksheet in the spreadsheet
var cell = sheet.getRange("G2");
cell.setValue(premisesType);
}
Hoping in anticipation someone can help without flaming me. I'm embarrassed enough posting this! I promise I am trying to learn and not going for the easy option!
Vince.
Edit: thanks to #iansedano I've almagamted some code which gets me whaere I need to be, except on some occasions I have the folder structer created multiple times, as though the smae form has been resubmitted several times. Here is the code I am now testing:
function autoCreateFoldersSheetDoc(e) {
var title = e.values[1];
var firstName = e.values[2];
var lastName = e.values[3];
var emailAddress = e.values[4];
var premisesType = e.values[6];
// This is the root directory where all the client folders would be stored
const customerRoot = DriveApp.getFolderById('1s4fD0wk8Mj_YiCkEOj7hUZedOv_AyPdl');
const mainFolder = customerRoot.createFolder(lastName + ', ' + firstName);
// Creating the sub folders
// Some are assigned to variables so that later children can be added
mainFolder.createFolder("1. Customer Correspondence")
const costsFolder = mainFolder.createFolder("2. Costs")
const proposalsFolder = mainFolder.createFolder("3. Proposals")
mainFolder.createFolder("4. Drawings")
mainFolder.createFolder("5. Testing & Commissioning")
// Creating children
costsFolder.createFolder("1. Suppliers")
const dcaFolder = costsFolder.createFolder("2. DCA")
// Take the template proposal doc and save a copy to the proposals folder
var fileA = DriveApp.getFileById('1QjYas1erxtQjLPduNMoY1EIEAjBOI5qbAMeX59qPib4');
var copyA = fileA.makeCopy(lastName + ', ' + firstName, proposalsFolder);
// Open new proposal doc and replace text
var doc = DocumentApp.openById(copyA.getId());
var body = doc.getBody();
var header = doc.getHeader();
header.replaceText('{{Premises type}}', premisesType);
body.replaceText('{{First Name}}', firstName);
body.replaceText('{{Surname}}', lastName);
body.replaceText('{{Salutation}}', title);
body.replaceText('{{email}}', emailAddress);
body.replaceText('{{Premises type}}', premisesType);
doc.saveAndClose();
// Take the template costs sheet and save a copy to the DCA folder
var fileB = DriveApp.getFileById('1yvOtPcnGMQnE7Hc0d6vVMSG2Q5nY9u-MijaDZ51jlOU');
var copyB = fileB.makeCopy(lastName + ', ' + firstName, dcaFolder);
// Open new costs sheet and replace text
var ss = SpreadsheetApp.openById(copyB.getId());
var sheet = ss.getSheets()[0];
var cellA = sheet.getRange("G2");
var cellB = sheet.getRange("H5");
var cellC = sheet.getRange("H6");
var cellD = sheet.getRange("H4");
var cellE = sheet.getRange("I2");
cellA.setValue(premisesType);
cellB.setValue(firstName);
cellC.setValue(lastName);
cellD.setValue(title);
cellE.setValue(emailAddress);
}
Any ideas how I can prevent the duplicates?
Sample function
/**
* This function takes three arguments, the client name,
* the costing sheet id, and the proposal doc id.
* It will then create the folders and place the documents in the
* right place, wherever they are in drive.
*/
function createClientAccountFolder(clientName, costingSheetId, ProposalDocId) {
// This is the root directory where all the client folders would be stored
const customerRoot = DriveApp.getFolderById('[YOUR_ROOT_FOLDER_ID]');
if (clientName) {
// This creates the main folder with the customer name
const mainFolder = customerRoot.createFolder(clientName);
// Creating the sub folders
// Some are assigned to variables so that later children can be added
mainFolder.createFolder("1. Customer Correspondence")
const costsFolder = mainFolder.createFolder("2. Costs")
const proposalsFolder = mainFolder.createFolder("3. Proposals")
mainFolder.createFolder("4. Drawings")
mainFolder.createFolder("4. Testing & Commissioning")
// Creating children
costsFolder.createFolder("1. Suppliers")
const dcaFolder = costsFolder.createFolder("2. DCA")
// Getting the documents
const costingSheet = DriveApp.getFileById(costingSheetId)
const proposalDoc = DriveApp.getFileById(ProposalDocId)
// Moving the documents to the respective folders
costingSheet.moveTo(dcaFolder)
proposalDoc.moveTo(proposalsFolder)
} else {
Logger.log('No Client Name Specified')
}
}
function test(){
createClientAccountFolder("John Smith", "[SHEET_ID]", "[DOC_ID]")
}
I was not sure how exactly to integrate it into your other script, since I don't have the data to be able to test it. Though, as a suggestion, you might add a line to the end of the functions autoFillGoogleDocFromForm and autoFillGoogleSheetFromForm.
return id
You would need to get the id of the documents first, and assign it to an id variable. Be sure to assign it as a string if you want to use the function above without any changes.
So all you would need to do is call all the functions from a main functions like this:
function main(){
const clientName = "John Smith"
const docId = autoFillGoogleDocFromForm()
const sheetId = autoFillGoogleSheetFromForm()
createClientAccountFolder(clientName, sheetId, docId)
}
You might also want a way to get the clientName in a different way, so this could all be automated easier. Though hopefully you get an idea of the kind of thing that would need to be done and you can modify it to your needs.
Let me know if anything is unclear!
References
createFolder(name)
getFolderById(id)
getFileById(id)
moveTo(destination)

I am unable to automate the population of footers in google docs

I am trying to automate the population of the footer of a google doc that I have with the values that a pop up dialogue gathers from the users when they open the document. The code that I am using can be seen below, however it only works with the footer of the first page, when and only when I activate the option "Different first page". If I de-activate it (because I want the footer to be consistent within the whole document) nothing changes (not even the first page of the document) when I run the script.
The footer looks like this:
Blablbla / ##value1##
Title: “##value2##” - blablabla
The script to substitute value1 and value2 looks like this:
function myFunction() {
// Display a dialog box for each field you need information for.
var ui = DocumentApp.getUi();
var value1Response = ui.prompt('Enter the value1');
var value2Response = ui.prompt('Enter the value2');
var date = new Date();
//Make a copy of the template file
var documentId = DriveApp.getFileById('google document Id').makeCopy().getId();
//Rename the copied file
DriveApp.getFileById(documentId).setName(value2Response.getResponseText() + date);
//Get the document footer as a variable
var footer = DocumentApp.openById(documentId).getFooter();
footer.replaceText('##value1##', value1Response.getResponseText());
footer.replaceText('##value2##', value2Response.getResponseText());
}
This works for me.
function myFunction() {
var doc=DocumentApp.getActiveDocument();
var ui = DocumentApp.getUi();
var value1Response = ui.prompt('Enter the value1');
var value2Response = ui.prompt('Enter the value2');
var value3Response = ui.prompt('Enter FileName');
var date = new Date();
var documentId = doc.getId();
var footer = doc.getFooter();
footer.replaceText('##value1##', value1Response.getResponseText());
footer.replaceText('##value2##', value2Response.getResponseText());
var doc=DocumentApp.openById("Doc Id");
var footer=doc.getFooter();
doc.setName(value3Response.getResponseText());
footer.replaceText('##value1##', value1Response.getResponseText());
footer.replaceText('##value2##', value2Response.getResponseText());
}