Google Slides API / Apps Script - find URLs and make them into hyperlinks - javascript

My script pulls rows from a form-populated spreadsheet and applies the values to a slide template.
They submit a Title, Description, and a Link to the resource they are submitting.
I need the "Link", which should be submitted as an URL, to automatically become a hyperlink when the slide is created. Everything I've tried has returned an error. I want to run .setLinkUrl(link) on the previously inserted link text. I just cant get it to stick. Any help would be appreciated.
--below is the function I'm trying to run--
function dataInjectionNN() {
var dataSpreadsheetUrl = "...spreadsheeturl.urlytypestuff..."
var ss = SpreadsheetApp.openByUrl(dataSpreadsheetUrl);
var deck = SlidesApp.getActivePresentation();
var mathCluster = deck.getName();
// Logger.log(mathCluster)
var sheet = ss.getSheetByName(mathCluster);
var lastR = sheet.getLastRow();
var range =sheet.getDataRange();
// Logger.log(range.getLastRow() + " Is the last Column.");
var values = range.getValues();
// Logger.log(values);
var slides = deck.getSlides();
var presLength = slides.length;
var templateSlide = slides[1];
values.forEach(function(page){
// run if the presentation has less slides that the number of form entries
if((presLength-2) < lastR){
if(page[3] = mathCluster){
var title = page[9];
var link = page[10];
var desc = page[11];
templateSlide.duplicate();//Duplicate the template page
slides = deck.getSlides();//update the slides array for indexes and length
newSlide = slides[2]; //declare the new page to update
var shapes = (newSlide.getShapes());
shapes.forEach(function(shape){
shape.getText().replaceAllText('<<Title>>',title);
shape.getText().replaceAllText('<<Link>>',link);
shape.getText().replaceAllText('<<Description>>',desc);
presLength = slides.length;
newSlide.move(presLength);
})
}
}
});
}

Related

Copy values to next column(if blank) in the same row. If not blank, copy to the second column(if blank) in same row. Repeat

Disclaimer: Im very new to google scripts. I jumbled together this code with mixed success.
When I run the script, it works fine with the first two attempts. Then it doesnt work after that because column Q now has values in other cells within the column and the script is technically correct but not running at intended. I need to ignore column Q cells that are not blank and still run the script to copy P values to the other cells in column Q.
Also, when column Q with in the same row is not blank, I need to copy the value from column P to column R (if blank). Rinse and Repeat script...
function copyVals () {
var ss = SpreadsheetApp.getActiveSpreadsheet ();
var source = ss.getRange ("Sheet1!P2:P");
var destSheet = ss.getSheetByName("Sheet1");
var destRange = destSheet.getRange('Q2:Q')
var destRange2 = destSheet.getRange('R2:R')
if (destRange.isBlank()) {
source.copyTo (destRange, {contentsOnly: true});
source.clear ();
}
if (destRange2.isBlank()) {
source.copyTo (destRange2, {contentsOnly: true});
source.clear ();
}
}
You need to do the blank check for each cell separately
However, if you do it wiht the Apps Script method isBlank() - this will make your code a bit slow.
I suggest you to
retreive the existing values both in the source and destination ranges with getValues
check for each of the destinations values either those are empty and replace the empty values through source values
assign the modified values back to the sheet with setValues
Sample code:
function copyVals () {
var ss = SpreadsheetApp.getActiveSpreadsheet ()
var sheet = ss.getSheetByName("Sheet1")
var lastRow = sheet.getLastRow()
var source = sheet.getRange ("P2:P" + lastRow)
var destSheet = sheet
var destRange = destSheet.getRange('Q2:Q' + lastRow)
var destRange2 = destSheet.getRange('R2:R' + lastRow)
var sourceValues = source.getValues().flat()
var destValues = destRange.getValues()
var dest2Values = destRange2.getValues()
sourceValues.forEach(function(value, i){
console.log("i" + i)
if (destValues[i][0] == "") {
destValues[i][0] = value
}
if (dest2Values[i][0] == "") {
dest2Values[i][0] = value
}
})
destRange.setValues(destValues)
destRange2.setValues(dest2Values)
source.clear ();
}
UPDATE
If you want to copy to column Q and R alternately, you can use script properties to save the run count of the script and execute different code blocks for odd and even number.
Sample:
function copyVals () {
var ss = SpreadsheetApp.getActiveSpreadsheet ()
var sheet = ss.getSheetByName("Sheet1")
var lastRow = sheet.getLastRow()
var source = sheet.getRange ("P2:P" + lastRow)
var destSheet = sheet
var destRange = destSheet.getRange('Q2:Q' + lastRow)
var destRange2 = destSheet.getRange('R2:R' + lastRow)
var sourceValues = source.getValues().flat()
var destValues = destRange.getValues()
var dest2Values = destRange2.getValues()
var scriptProperties = PropertiesService.getScriptProperties()
var myProperty = scriptProperties.getProperty('timesCalled')
if (!myProperty){
myProperty = "1"
}
myProperty = JSON.parse(myProperty)
var isOdd = myProperty % 2
if(isOdd){
sourceValues.forEach(function(value, i){
console.log("i" + i)
if (destValues[i][0] == "") {
destValues[i][0] = value
}
})
destRange.setValues(destValues)
} else{
sourceValues.forEach(function(value, i){
if (dest2Values[i][0] == "") {
dest2Values[i][0] = value
}
})
destRange2.setValues(dest2Values)
}
source.clear ()
myProperty++
scriptProperties.setProperty('timesCalled', JSON.stringify(myProperty))
}

Google Form creates Google Slides from template Script

I have a script that on Form submit takes the data from the spreadsheet and creates a copy of a template and populates the google docs. I am trying to accomplish the same thing from google form to google slides.
First script I use for the google forms to google docs. The second script is my attempt of using the same principles and applying to google slides. My issue is I'm getting an error saying TypeError: values.forEach is not a function (line 109, file "Code") in relation to values.forEach(function(page). Any suggestions on how I could go about solving this?
Google Form to Google Sheets
function autoFillGoogleDocFromForm(e) {
var timestamp = e.values[0];
var address = e.values[1];
var image = e.values[2];
var price = e.values[3];
var summary = e.values[4];
var type = e.values[5];
var year_built = e.values[6];
var bed = e.values[7];
var bath = e.values[8];
var home_size = e.values[9];
var lot_size = e.values[10];
var occupancy = e.values[11];
var templateFile = DriveApp.getFileById("xxxxxxxx");
var templateResponseFolder = DriveApp.getFolderById("yyyyyyyyyy")
var copy = templateFile.makeCopy( address , templateResponseFolder);
var doc = DocumentApp.openById(copy.getId())
var body = doc.getBody();
body.replaceText("{{address}}", address);
body.replaceText("{{price}}", price);
body.replaceText("{{summary}}", summary);
body.replaceText("{{type}}", type);
body.replaceText("{{year_built}}", year_built);
body.replaceText("{{beds}}", bed);
body.replaceText("{{baths}}", bath);
body.replaceText("{{home_size}}", home_size);
body.replaceText("{{lot_size}}", lot_size);
body.replaceText("{{occupancy}}", occupancy);
doc.saveAndClose;
}
Google Form to Google Slides
function generateLandingPagesReport(){
var dataSpreadsheetUrl = "https://docs.google.com/spreadsheets/xxxxxxxxx/edit"
var Presentation_ID = "xxxxxxxxxxxxxx";
var ss = SpreadsheetApp.openByUrl(dataSpreadsheetUrl);
var deck = SlidesApp.openById(Presentation_ID);
var sheet = ss.getSheetByName('Sheet1');
var values = sheet.getRange('A1:J17').getValues;
var slides = deck.getSlides();
var templateSlide = slides[1];
var presLength = slides.length;
values.forEach(function(page){
values.forEach(function(page){
if(page[0]){
var landingPage = page[0];
var sessions = page[1];
var newSessions = page[2];
}
templateSlide.duplicate(); // duplicate the template page
/*slides = deck.getSlides(); // update the slides array for indexes and length*/
newSlide = slides[2]; // declare the new page to update
var shapes = (newSlide.getShapes());
shapes.forEach(function(shape){
shape.getText().replaceAllText('{{landing page}}', landingPage);
shape.getText().replaceAllText('{{sessions}}', sessions);
shape.getText().replaceAllText('{{new sessions}}',newSessions);
});
presLength = slides.length;
newSlide.move(presLength);
//end our condition statement
}); //close our loop of values
//remove template slide
templateSlide.remove();
});
}
You're missing the parenthesis when calling the getValue() method.
Change this:
var values = sheet.getRange('A1:J17').getValues;
To this:
var values = sheet.getRange('A1:J17').getValues();
Not exactly what I was looking for but this uses the first Row to identify the tag inside the Google slides template like {{title}} and replaces that with the value in the second row of the sheet
function createPresentation() {
var templateFile = DriveApp.getFileById("1YVEA4WtU1Kf6nZRgHpwnKBIR-V6rRN6s9zCdOQDkWNI");
var templateResponseFolder = DriveApp.getFolderById("1k7rcfXODij4o4arSULuKZUHbit1m_X64");
var copy = templateFile.makeCopy("New" , templateResponseFolder);
var Presentation = SlidesApp.openById(copy.getId());
var values = SpreadsheetApp.getActive().getDataRange().getValues();
values.forEach(function(row) {
var templateVariable = row[0];
var templateValue = row[1];
Presentation.replaceAllText(templateVariable, templateValue);
});
}
After you have copy the template page, you work on it and try to do replace.
However, change may be pending such that newSlide = slides[2]; give undefined.
You may need to try saveAndClose() before performing any actions.
templateSlide.duplicate(); // duplicate the template page
/*slides = deck.getSlides(); // update the slides array for indexes and length*/
/* flush the presentation */
deck.saveAndClose();
deck = SlidesApp.openById(Presentation_ID);
slides = deck.getSlides();
newSlide = slides[2]; // declare the new page to update
var shapes = (newSlide.getShapes());
shapes.forEach(function(shape){
shape.getText().replaceAllText('{{landing page}}', landingPage);
shape.getText().replaceAllText('{{sessions}}', sessions);
shape.getText().replaceAllText('{{new sessions}}',newSessions);
});

Trouble creating events in Google Agenda from Google Sheets with a script

I created a script in a Google Sheet to create events in Google Agenda, in order to study.
My goal is to create many events like this : if i study on D0, the first event must be at D+3, then D+10 , D+30, D+60.
I get many problems :
the script write "AJOUTE" in each box of the column (which means in french that the events are added to Agenda) , even if they are not completed with dates (I want to update for each chapter when it's done, and I do not do a whole chapter the same day!)
the script doesn't care if the events are already created, so i get multiple events for the same thing...
My script is the following :
var EVENT_IMPORTED = "AJOUTE";
var ss = SpreadsheetApp.getActiveSpreadsheet();
function onOpen() {
var menuEntries = [{name: "Ajouter les événements à l'agenda", functionName: "importCalendar"}];
ss.addMenu("Agenda", menuEntries);
}
function importCalendar() {
var sheet = SpreadsheetApp.getActiveSheet();
var startcolumn = 1
var numcolumns = 30
var dataRange = sheet.getRange(startcolumn, 1, numcolumns, 6)
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var column = data[i];
var titre = column[1];
var DateJ3 = column[2];
var DateJ10 = column[3];
var DateJ30 = column[4];
var DateJ60 = column[5];
var eventImported = column[6];
var setupInfo = ss.getSheetByName("agenda");
var calendarName = setupInfo.getRange("A1").getValue();
if (eventImported != EVENT_IMPORTED && titre != "") {
var cal = CalendarApp.openByName(calendarName);
cal.createAllDayEvent(titre, new Date(DateJ3));
cal.createAllDayEvent(titre, new Date(DateJ10));
cal.createAllDayEvent(titre, new Date(DateJ30));
cal.createAllDayEvent(titre, new Date(DateJ60));
sheet.getRange(startcolumn + i, 7).setValue(EVENT_IMPORTED);
SpreadsheetApp.flush();
}
}
}
Thank you in advance, i'm despair, i searched for hours but found nothing to help...

Return String variable delayed

I have a web page with a table identified by "table-rank" class.
This table has 3 pages : to go on next page, i use the .click function on the net button.
I tried to build a finalHtml string by capturing specific element in each lines of the table.
Problem : The finalHtml contains 3 times the datas of the first page of the table. No data of the second page and third page is captured..
It's because, when i click on the button, it's asynchronous, and the first loop continue to parse the table which have not been already refreshed. How can i do, to be sure that the data have been loaded when i click on the next button ?
function getClassement() {
var finalHtml = '' ;
for (var k=0; k<2; k++) {
for (var i=0; i<$(".table-rank tbody tr").length; i++) {
var currentLine = $(".table-rank tbody tr")[i];
// Get position
var positionEl = $(currentLine).find(".ng-binding")[0];
var position = $(positionEl).text();
// Get id
var idEl = $(currentLine).find(".ng-binding")[1];
var id = $(idEl).text();
// Get prenom/nom
var nomPrenom = "test";
// Nombre de paris
var nbrParisEl = $(currentLine).find(".ng-binding")[2];
var nbParis = $(nbrParisEl).text();
// Nombre de bons paris
var nbrBonsParisEl = $(currentLine).find(".ng-binding")[3];
var nbBonsParis = $(nbrBonsParisEl).text();
// Score exacts
var scoresExactsEl = $(currentLine).find(".ng-binding")[4];
var scoresExacts = $(scoresExactsEl).text();
// Points totals
var pointsTotalEl = $(currentLine).find(".ng-binding")[7];
var pointsTotals = $(pointsTotalEl).text();
finalHtml = finalHtml + "<tr><td><span class='position'>"+position+"</span></td><td>"+id+"</td><td>"+nomPrenom+"</td><td>"+nbParis+"</td><td>"+nbBonsParis+"</td><td>"+scoresExacts+"</td><td><span class='total'>"+pointsTotals+"</span></td></tr>";
}
// Go next page
$(".pager a")[1].click();
}
return finalHtml;
}

sending data from a google spreadsheet program to google calender

Here is my case.
A user fills a form for event booking, the submitted form is stored in a google spreadsheet which I have synced to a google calender so that it automatically sends the data to it.
Everything is working fine apart from the fact that event times could clash.
When customers book an event centre for let's say on 13/3/2015 T 10:00AM, if another user enters the same date and time, the entry should not be accepted.
To summarise it, I want to avoid a clash of events booking. Thank you all.
here is my script.
var calendarId = "mycalenderid";
//below are the column ids of that represents the values used in the spreadsheet (these are non zero indexed)
var startDtId = 9;
var endDtId = 10;
var titleId = 6;
var descId = 11;
var formTimeStampId = 1;
function getLatestAndSubmitToCalendar() {
var sheet = SpreadsheetApp.getActiveSheet();
var rows = sheet.getDataRange();
var numRows = rows.getNumRows();
var values = rows.getValues();
var lr = rows.getLastRow();
var startDt = sheet.getRange(lr,startDtId,1,1).getValue();
//set to first hour and minute of the day.
//startDt.setHours(0);
//startDt.setMinutes(00);
var endDt = sheet.getRange(lr,endDtId,1,1).getValue();
//set endDt to last hour and minute of the day
//endDt.setHours(23);
//endDt.setMinutes(59);
var subOn = "Submitted on:"+sheet.getRange(lr,formTimeStampId,1,1).getValue();
var desc = "Added by :"+sheet.getRange(lr,descId,1,1).getValue()+"\n"+subOn;
var title = sheet.getRange(lr,titleId,1,1).getValue()+"DIA";
createEvent(calendarId,title,startDt,endDt,desc);
}
function createEvent(calendarId,title,startDt,endDt,desc) {
var cal = CalendarApp.getCalendarById(calendarId);
var start = new Date(startDt);
var end = new Date(endDt);
var loc = 'Script Center';
var event = cal.createEvent(title, start, end, {
description : desc,
location : loc
});
};
Here's a pseudocode of what you're trying to do:
function findEvent(desiredDateTime)
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Sheet1");
var range = sheet.getDataRange();
var data = range.getValues();
var lRow = range.getLastRow();
var flag = true;
var count = 0;
while (flag == true || count < lRow)
{
if (desiredDateTime >= data[count][startDtId] && desiredDateTime <= data[count][endDtId])
{
flag = false;
}
else
{
count++;
}
}
if (flag == true)
{
//Call function to add event
}else{
//Tell user desired date-time is not available.
//If you're asking for user's email address,
//simplest approach would be to send an email.
}
}
You might have to modify other bits and pieces of your code as well to accommodate this but it shouldn't be too hard. Hope this provides you with a certain direction to follow through.

Categories

Resources