Google Sites "addListItem" fails with Google Form Prefilled URL - html

I am working up a solution which returns a link to a prefilled Google Form, to be located on a classic Google Sites List Page. I have all the code in place, everything works, aside from the last vital part: programmatically, via Google Apps Script, adding the Google Form prefilled url as a new listitem on a Google Sites List Page. I am doing the prefilling using variables from a spreadsheet (the Responses from the google form). The url/anchor code looks perfectly formed in the Log. Here is the code:
//fetch all spreadsheet row entries to variables
var keyname = candname;
var keytimestamp = ActiveSheet.getRange("A"+ActiveRow).getValue();
var keytimestamp = Utilities.formatDate(new Date(), "GMT", "yyyy-MM-dd");
var keyinc01 = ActiveSheet.getRange("B"+ActiveRow).getValue();
var keyinc02 = ActiveSheet.getRange("C"+ActiveRow).getValue();
var keyinc03 = ActiveSheet.getRange("D"+ActiveRow).getValue();
var keybrok01 = ActiveSheet.getRange("E"+ActiveRow).getValue();
var keybrok02 = ActiveSheet.getRange("F"+ActiveRow).getValue();
var keybrok03 = ActiveSheet.getRange("G"+ActiveRow).getValue();
var keyacc01 = ActiveSheet.getRange("H"+ActiveRow).getValue();
var keyacc02 = ActiveSheet.getRange("I"+ActiveRow).getValue();
var keyacc03 = ActiveSheet.getRange("J"+ActiveRow).getValue();
//var prefillurl = "https://www.google.co.uk"; //test other url
var prefillurl = 'https://docs.google.com/a/xxxxxxxx.org/forms/d/e/1FAIpQLSfOT0CVpSyGrlZmKKIRVCqbg11rAa9ANyYL8u9QwIWjqWfITg/viewform?entry.1894338678='+keyinc01+'&entry.1429410229='+keyinc02+'&entry.868549131='+keyinc03+'&entry.1083479546='+keybrok01+'&entry.1385475363='+keybrok02+'&entry.137722395='+keybrok03+'&entry.1074722805='+keyacc01+'&entry.1093081320='+keyacc02+'&entry.409101030='+keyacc03;
var listpageurl = "Google Form Link";
Logger.log(listpageurl);
var site = SitesApp.getSiteByUrl("https://sites.google.com/a/xxxxxxxx.org/xxxxxxxx");
var page = site.getChildByName("/home/candidates/"+candwebname);
page.addListItem([ keytimestamp, ssname, listpageurl ]);
As you can see I have tested the anchor tag syntax with the commented "https://www.google.co.uk", which works, and the prefilled url pasted into a browser also works correctly (grabbed from the Log). Also the listpage will accept the url via manual direct entry.However I always get the error about the anchor tag not being properly formed when I run the code. I have also tested with and without the https:// in the url, just in case. I have either missed something fundemental, have left out some additional quotes or double quotes, or have found a bug?
I have found a workaround, which was to enable UrlShortener, but would prefer to be able to use the prefilled url directly ( I will have a lot of these to do!) to speed things up, and make the code more transferrable.
Can anyone spot the issue here?

Related

How to make Google Slide update value WITHOUT having to manually open it? [duplicate]

This question already has answers here:
pdf is created from google slide, but with the markers populated (via GAS)
(1 answer)
Created PDF does not reflect changes made to the original document
(2 answers)
Converting a google doc to a pdf results in blank pdf, google scripts
(1 answer)
Closed 3 months ago.
I have a Google Sheet with a Google Apps Script that basically intends to do the following when triggered:
Open a specific Google Slides file (it's a template)
Duplicate it into a specific subfolder
Change some placeholder values of this copy
Send this new Google Slide via Email as a PDF.
Everything works great EXCEPT for step 3, which for some reason ONLY updates when I manually open this new file. So the PDF that I receive via email actually still contains the placeholder values, as does the "preview" I see on my Drive before opening the Slides presentation. However, if I open it, it automatically shows the new updated values. I can't figure out why this might be happening.
Things I tried:
Add Utilities.sleep() to allow for the values to update, but it doesn't seem to work. Only opening it does it.
Add a line to .openById() again in case this "forces it to open", but doesn't work.
Adding a loop to refresh each slide.
This is a minimal reproducible code that I have, but would require a Google Slide with two placeholders as "[var_0]" and "[var_1]":
const idTemplate = "1BugZRdW8aOzgPOZun-j_U60lC-yXQFXug3R2-MR7AFs";
function generatePresentationData() {
var s = SpreadsheetApp.getActive();
//Data is in A2:B2 of "Records" sheet.
var ss = s.getSheetByName("Records");
var data = ss.getRange("A2:B2").getValues();
//Get the Google Slides template
var file = DriveApp.getFileById(idTemplate);
//Create a copy of the template into a specific folder, and get the ID of this copy
var newParte = file.makeCopy("New Parte", DriveApp.getFolderById("1rCEYVilGiOlxh03aFANzD4qgKXKBmODh"));
var newParteId = newParte.getId();
//Get the slides of this file.
var slides = getSlides_(newParteId);
//Replace the placeholders with the value in A2:B2. This is the part that doesn't actually "shows up" on this new file until I manually open it from my Drive. It does work correctly, so I don't think the issue lies here
writeDataToPlayersSlide_(slides, data);
//I have tried adding a wait period but didn't work
Utilities.sleep(60000);
//I also tried defining the file again before proceeding to send it via email, but again didn't work
var newParte = DriveApp.getFileById(newParteId);
//I also tried refreshing each slide
refreshSlides(SlidesApp.openById(newParteId));
//Get this new file as a Blob
var theBlob = newParte.getBlob().getAs('application/pdf');
var nameFile = 'Test.pdf';
var email = "mail#gmail.com";
var subject = 'Test Subject';
var body = 'Hi!, <br/>Here is your file.';
GmailApp.sendEmail(email, subject, body, {
htmlBody: body,
attachments: [{
fileName: nameFile,
content: theBlob.getBytes(),
mimeType: "application/pdf"
}]
});
}
function getSlides_(newParteId){
let presentation = SlidesApp.openById(newParteId);
let slides = presentation.getSlides();
return slides;
}
function writeDataToPlayersSlide_(slides, data){
let parte = slides[0];
for (let index=0;index<data[0].length;index++){
parte.replaceAllText(`[var_${index}]`,data[0][index]);
}
}
function refreshSlides(presentation){
// loop through all slides and refresh them
numSlides = presentation.getSlides().length;
for (i = 0; i < numSlides; i++) {
presentation.getSlides()[i].refreshSlide();
}
}
Instead of
//I have tried adding a wait period but didn't work
Utilities.sleep(60000);
//I also tried defining the file again before proceeding to send it via email, but again didn't work
var newParte = DriveApp.getFileById(newParteId);
//I also tried refreshing each slide
refreshSlides(SlidesApp.openById(newParteId));
use
newParte.saveAndClose();
newParte = DriveApp.getFileById(newParteId);
Apparently the problem is that you have missed that Google Apps Script applies changes to Docs Editors files after the script ends.
If order to force Google Apps Script applies the changes at some point, i.e before sendding an email, when making changes to
spreadsheets use SpreadsheetApp.flush()
documents use DocumentsApp.Document.saveAndClose()
presentations use SlidesApp.Presentation.saveAndClose()

Insert hyperlink with variable into google docs using google scripts

I have a google Form, and the responses populate a response google Sheet, which has a google Script function to generate a google Document using a template.
I am trying to get the address entered in the Form (stored in the response Sheet) to become a hyperlink in the generated Doc.
I have been using the body.replaceText() to replace all the fields I need in the Doc:
body.replaceText("{{Date}}", date);
and its working well, but the address field I would like to become a hyperlink.
I have been trying to do it this way:
body.replaceText("{{Location}}", =HYPERLINK("http://www.google.com/maps/place/'+location+'"));
But that does not become a usable hyperlink, resulting with this in the Doc (please note while it becomes a hyperlink on this page it does not become a hyperlink in Docs):
=HYPERLINK("http://www.google.com/maps/place/myplacenotyours")
I have also tried:
body.replaceText("{{Location}}", location = HYPERLINK("http://www.google.com/maps/place/"+location+));
But this throws up syntax errors.
I have this var:
var location = e.values[2];
So perhaps it better to use that to create another var as a hypertext?
I am now trying:
var loclink = 'Hyperlink("http://www.google.com/maps/place/'+location+'","'+location+'")';
but that doesnt do it either... I'm now starting to think that one can't insert a hyperlink using replace method?
Sorry for the noob question, but I can't figure this out. Can you help me find a solution and put a var into a hypertext link and put that into the Doc as a link?!
Cheers.
Something like this:
function insertLink() {
var pattern = '{{Location}}';
var url = 'https://stackoverflow.com/a/69143679/14265469';
var text = 'how to paste a link';
var doc = DocumentApp.getActiveDocument();
var body = doc.getBody();
var next = body.findText(pattern);
if (!next) return;
var start = next.getStartOffset();
body.replaceText(pattern, text);
body.editAsText().setLinkUrl(start, start+text.length-1, url);
}

Google Apps Script to automatically open copied document after creating it?

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()

getting Exception: Invalid ID error, when using getFileById

I am trying to use a script from a tutorial online that will put URLs in a google forms response sheet so I can go back and edit responses after they have been submitted.
The script comes from this guy https://www.youtube.com/watch?v=nqOE_FIMd_w
and his instructions are here: https://docs.google.com/document/d/1m9V_AHZdA24pUAR1xGxQNt_y3k7J9RKoSG5v_9oFvcU/edit
here is the script from the tutorial:
function assignEditUrls() {
var form = FormApp.openById('Your form ke goes here');
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Your responses Google Sheet name goes here - The tab name, not the file name');
var data = sheet.getDataRange().getValues();
var urlCol = Column number where URLs get entered goes here;
var responses = form.getResponses();
var timestamps = [], urls = [], resultUrls = [];
for (var i = 0; i < responses.length; i++) {
timestamps.push(responses[i].getTimestamp().setMilliseconds(0));
urls.push(responses[i].getEditResponseUrl());
}
for (var j = 1; j < data.length; j++) {
resultUrls.push([data[j][0]?urls[timestamps.indexOf(data[j][0].setMilliseconds(0))]:'']);
}
sheet.getRange(2, urlCol, resultUrls.length).setValues(resultUrls);
}
It seems all simple enough, but the script keeps giving me an error:
Invalid ID (line 2, file "getEditLinks")
Seems to be a problem with the document key.
I have already given the script permission and I have concentrated my attemtps to resolve this by grabbing different parts of this URL for the file. (I remember that Google used to need the whole URL at some point in the past)
Mine is
*https://docs.google.com/spreadsheets/d/1pKmad.....VtT3GaM/edit#gid=1905774080*
(where ..... is more of the doc key. I am not putting the whole lot for security reasons)
According to the tutorial, and all other research into this, it seems this part is the correct part from the URL to use.
1pKmad.....VtT3GaM
But this is what bring the error.
I tried the whole URL, the URL just up to the doc key part, and a few other subsets of this, but none work.
Can anyone see what I am doing wrong here?
Issue:
Based on your description you are trying to access a spreadsheet file by its id but you are using FormApp.
Instead you should be using SpreadsheetApp instead:
var form = SpreadsheetApp.openById('1pKmad.....VtT3GaM'); // form is now a spreadsheet object
but the new issue now is that the variable is not form anymore but a spreadsheet object and as a result you will get other errors down the road when calling form.getResponses().
Solution:
You need to use your existing script and put the id of the form instead of the spreadsheet, which can be found on the form url:
var form = FormApp.openById('Form ID here not Spreadsheet ID');
Note:
The form url looks like this:
https://docs.google.com/forms/d/formID/edit
and you can find the form that is attached to the spreadsheet file by the spreadsheet file menu:

Doesn't work - Cross-domain Redirect in google form in an iframe in google sheets app script

I have a function launchForm within a Google Sheet which calls another function createForm with a single question. I get the URL of the newly created form and pass it into a sandbox Iframe using UrlFetchApp, as shown below:
function launchForm() {
var form = createForm(); // separate function that works fine
formUrl = form.getPublishedUrl()
var response = UrlFetchApp.fetch(formUrl,{"followRedirects" : true}); // true if automatic redirecting works
var formHtml = response.getContentText();
var htmlApp = HtmlService
.createHtmlOutput(formHtml)
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL) // did this to prevent error but didn't help
var ss = SpreadsheetApp.getActiveSpreadsheet();
ss.show(htmlApp);
}
I have created a custom menu in sheets to run the launchForm function.
The trouble is, that the new form URL is at docs.google.com/a/, while the sheet is at docs.google.com/spreadsheets/d/...
This means that the iframe, instead of loading the form, opens up to a sign-in screen in when I (the creator of the form) tries to run it. When someone else with edit permissions runs the script, he sees the form as expected, but is then unable to make any inputs into the form.
I have read about CORS, X-frame-options, OAuth2, and nothing seems to provide the precise answer about what I must do. Any help will be much appreciated.