I have the name for event and end date (without start date) in Google Sheets.
Column B is the name of the event and column C is end date.
The script says execution successful but events are not getting added in Google Calendar.
I am the owner and have full rights/permission.
Here's the script:
function onOpen() {
var ui = SpreadsheetApp.getUi();
var menu = ui.createMenu('Sync to Calendar');
var item = menu.addItem('Commit', 'syncCalendar');
item.addToUi();
}
function calendar() {
var spreadsheet = SpreadsheetApp.getActiveSheet();
var eventCal = CalendarApp.getCalendarById("calendarid**");
var name = spreadsheet.getRange('B3:B250').getValue();
var start = new Date(spreadsheet.getRange('C3:C250').getValue()).getTime();
var end = new Date(spreadsheet.getRange('C3:C250').getValue()).getTime();
eventCal.createEvent(name,new Date(start),new Date(end));
Logger.log('Reminder is added to your calendar');
}
You have to make a loop as follows
const cal = '#################gmail.com'
function calendar() {
var spreadsheet = SpreadsheetApp.getActiveSheet();
var eventCal = CalendarApp.getCalendarById(cal);
var lastRow = spreadsheet.getLastRow()
var name = spreadsheet.getRange('B3:B' + lastRow).getValues().flat();
var start = spreadsheet.getRange('C3:C' + lastRow).getValues().flat();
var end = spreadsheet.getRange('C3:C' + lastRow).getValues().flat();
name.forEach((n, i) => {
try {
var id = eventCal.createEvent(n, new Date(start[i].getTime()), new Date(end[i].getTime())).getId();
console.log(id)
} catch (e) {
console.log(i + ' ' + e)
}
})
Logger.log('Reminder is added to your calendar');
}
flat()
forEach()
With the help of #Mike Steelson this script is working.
However, when you run the code again, it creates duplicates in the calendar.
Is there any way to avoid this?
const cal = 'yourcalendarid#group.calendar.google.com'
function calendar() {
var spreadsheet = SpreadsheetApp.getActiveSheet();
var eventCal = CalendarApp.getCalendarById(cal);
var lastRow = spreadsheet.getLastRow()
var name = spreadsheet.getRange('B3:B' + lastRow).getValues().flat();
var start = spreadsheet.getRange('C3:C' + lastRow).getValues().flat();
var end = spreadsheet.getRange('C3:C' + lastRow).getValues().flat();
name.forEach((n, i) => {
try {
var id = eventCal.createEvent(n, new Date(start[i].getTime()), new Date(end[i].getTime())).getId();
console.log(id)
} catch (e) {
console.log(i + ' ' + e)
}
})
Logger.log('Reminder is added to your calendar');
}
Related
I tried to fill it with my sheet data, but that
var dataRange = sheet.getDataRange();
get an error. What should I do?
function RefreshImports() {
var lock = LockService.getScriptLock();
if (!lock.tryLock(5000)) return; // Wait up to 5s for previous refresh to end.
var id = "1r7TgCWXfjmcjufT0yz9qcFDlr482SdHDHlZYblXyAt0"; // [YOUR SPREADSHEET ID]
var ss = SpreadsheetApp.openById(id);
var sheet = ss.getSheetByName("crypto"); // sheet name
var dataRange = sheet.getDataRange();
var formulas = dataRange.getFormulas();
var content = "";
var now = new Date();
var time = now.getTime();
var re = /.*[^a-z0-9]import(?:xml|data|feed|html|range)\(.*/gi;
var re2 = /((\?|&)(update=[0-9]*))/gi;
var re3 = /(",)/gi;
for (var row=0; row<formulas.length; row++) {
for (var col=0; col<formulas[0].length; col++) {
content = formulas[row][col];
if (content != "") {
var match = content.search(re);
if (match !== -1 ) {
// import function is used in this cell
var updatedContent = content.toString().replace(re2,"$2update=" + time);
if (updatedContent == content) {
// No querystring exists yet in url
updatedContent = content.toString().replace(re3,"?update=" + time + "$1");
}
// Update url in formula with querystring param
sheet.getRange(row+1, col+1).setFormula(updatedContent);
}
}
}
}
// Done refresh; release the lock.
lock.releaseLock();
// Show last updated time on sheet somewhere
sheet.getRange(7,2).setValue("Rates were last updated at " + now.toLocaleTimeString())
}
I set up the trigger.
Not sure what you trying to do and you explanation leaves a lot to be desired.
So this is a simple way to put your formulas into a sheet named "Destination".
function RefreshImports() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName("crypto");
const rg = sh.getDataRange();
const formulas = rg.getFormulas();
sh.getRange(1,1,formulas.length,formulas[0].length).setFormulas(formulas);
}
I'm working on a Google Sheets script to perform the following:
iterate through a specified sheet, finding rows that do not contain a specified value within a specified column
store these rows as a range in a variable
remove all other rows
replace the sheet content with the stored rows
The script runs without error, but does not affect sheet content. I'm not sure what the issue is - any feedback is appreciated.
Here's the script:
function onOpen() {
const ui = SpreadsheetApp.getUi();
ui.createMenu('Clear OI')
.addItem('Clear OI', 'removeZeroOI')
.addToUi();
}
function removeZeroOI() {
// Deleting Rows Based on Cell Values
//GLOBALS
var SS = SpreadsheetApp.openById("mySheetID");
var SHEET = SS.getSheetByName("mySheetName");
var RANGE = SHEET.getDataRange();
var DELETE_VAL = 0;
var COL_TO_SEARCH = 13; //column N
function main() {
var startTime = new Date().getTime();
var deleteSelectedRows = removeFilterSetVals();
var runTime = (new Date().getTime() - startTime)/1000;
Logger.log("Runtime is: "+runTime + " seconds");
};
function removeFilterSetVals(){
var rangeVals = RANGE.getValues();
var filteredRange = rangeVals.filter(function(val){
return val[COL_TO_SEARCH] != DELETE_VAL ;
});
RANGE.clearContent();
var newRange = SHEET.getRange(1,1,filteredRange.length, filteredRange[0].length);
newRange.setValues(filteredRange);
};
}
If you are actually using your showing script, I think that in your script, when the function of removeZeroOI() is run, main() and removeFilterSetVals() are not run. By this, the script doesn't work while no error occurs.
When you want to run main() and removeFilterSetVals(), how about the following modifications?
Modified script:
function removeZeroOI() {
var SS = SpreadsheetApp.openById("mySheetID");
var SHEET = SS.getSheetByName("mySheetName");
var RANGE = SHEET.getDataRange();
var DELETE_VAL = 0;
var COL_TO_SEARCH = 13; //column N
main(); // Added
function main() {
var startTime = new Date().getTime();
var deleteSelectedRows = removeFilterSetVals();
var runTime = (new Date().getTime() - startTime) / 1000;
Logger.log("Runtime is: " + runTime + " seconds");
};
function removeFilterSetVals() {
var rangeVals = RANGE.getValues();
var filteredRange = rangeVals.filter(function(val) {
return val[COL_TO_SEARCH] != DELETE_VAL;
});
RANGE.clearContent();
var newRange = SHEET.getRange(1, 1, filteredRange.length, filteredRange[0]
.length);
newRange.setValues(filteredRange);
};
}
And,
function removeZeroOI() {
var SS = SpreadsheetApp.openById("mySheetID");
var SHEET = SS.getSheetByName("mySheetName");
var RANGE = SHEET.getDataRange();
var DELETE_VAL = 0;
var COL_TO_SEARCH = 13; //column N
var startTime = new Date().getTime();
// Script of "removeFilterSetVals()" is put here.
var rangeVals = RANGE.getValues();
var filteredRange = rangeVals.filter(function(val) {
return val[COL_TO_SEARCH] != DELETE_VAL;
});
RANGE.clearContent();
var newRange = SHEET.getRange(1, 1, filteredRange.length, filteredRange[0]
.length);
newRange.setValues(filteredRange);
var runTime = (new Date().getTime() - startTime) / 1000;
Logger.log("Runtime is: " + runTime + " seconds");
}
Well we have this google form and the details are being added to google sheet with custom g apps scripts. When the details have been appended to the google sheet log, it should send email. If I run the sendmail() manually, it works but when I call it inside onFormSubmit(), it's not working. What could have gone wrong?
function onFormSubmit(e) {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var templateLink = sheet.getSheetByName("Template Link").getRange(1, 1).getValue();
var logSheet = sheet.getSheetByName("Log");
var formResponsesSheet = sheet.getSheetByName("Form Responses 1");
var formResponsesHeader = formResponsesSheet.getRange(1, 2, 1, formResponsesSheet.getLastColumn() -1).getValues();
var newFileName = e.namedValues['Name'][0] + "-" + e.namedValues['Date'][0];
var populatedDocsFolder = DriveApp.getFolderById("1yTSd7W0U4Gcsm6CIw8NtD022F-MA7CPx");
var templateDocID = DocumentApp.openByUrl(templateLink).getId();
var newDocID = DriveApp.getFileById(templateDocID).makeCopy(newFileName, populatedDocsFolder).getId();
var newDocLink = DriveApp.getFileById(newDocID).getUrl();
var newDoc = DocumentApp.openById(newDocID);
var newDocBody = newDoc.getBody();
for (i = 0; i < formResponsesHeader[0].length; i++) {
var thisHeader = formResponsesHeader[0][i];
var thisValue = e.namedValues[thisHeader][0];
newDocBody.replaceText("<<" + thisHeader + ">>", thisValue);
}
//Log
var name = e.namedValues['Name'][0];
var email = e.namedValues['Email'][0];
var date = e.namedValues['Date'][0];
logSheet.appendRow([name,email,date,newDocID]);
//Trigger
ScriptApp.newTrigger("sendEmail").timeBased().after(15000).create();
//sendEmail();
}
function sendEmail() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var logSheet = sheet.getSheetByName("Log");
var logSheetData = logSheet.getDataRange().getDisplayValues();
var templateName = sheet.getSheetByName("Template Name").getRange(1, 1).getValue();
for (i = 1; i < logSheetData.length; i++) {
if (logSheetData[i][4] == "") {
//SEND EMAIL
var name = logSheetData[i][0];
var email = logSheetData[i][1];
var date = logSheetData[i][2];
var id = logSheetData[i][3];
var pdfName = templateName + "-" + name + "-" + date;
//PDF EMAIL
try{
var doc = DriveApp.getFileById(id);
var blob = doc.getBlob().getAs('application/pdf').setName(pdfName + ".pdf");
var subject = 'Document Created';
//GmailApp.sendEmail(email, subject, "This is just a test", {attachments: [blob]});
MailApp.sendEmail(email, subject, "", {attachments: [blob], name: pdfName});
}catch(err){
continue;
}
//Log Sheet Update
logSheet.getRange(i + 1, 5).setValue("Sent");
}
}
}
function onOpen() {
SpreadsheetApp.getUi().createMenu("Custom Menu")
.addItem("Build Form Submit Trigger", "formSubmitTrigger")
.addSeparator()
.addItem("Send Email", "sendEmail")
.addSeparator()
.addItem("Mismatch Check", "mismatchCheck")
.addToUi();
}
function formSubmitTrigger() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
ScriptApp.newTrigger("onFormSubmit").forSpreadsheet(sheet).onFormSubmit().create();
}
function mismatchCheck() {
var result = "";
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var templateLink = sheet.getSheetByName("Template Link").getRange(1, 1).getValue();
var formResponsesSheet = sheet.getSheetByName("Form Responses 1");
var formResponsesHeader = formResponsesSheet.getRange(1, 2, 1, formResponsesSheet.getLastColumn() -1).getValues();
var docBody = DocumentApp.openByUrl(templateLink).getBody().getText();
var matches = docBody.match(/<</g); var noOfLessThanMatches = matches.length;
var matches = docBody.match(/>>/g); var noOfMoreThanMatches = matches.length;
var lessThan = docBody.search(/<</g);
var moreThan = docBody.search(/>>/g);
Logger.log([noOfLessThanMatches,noOfMoreThanMatches]);
result += "<b>Less Than Signs:</b> " + noOfLessThanMatches + "<br>";
result += "<b>More Than Signs:</b> " + noOfMoreThanMatches + "<br>";
result += "<br><b>Doc to Form Check</b><br>";
var newDocBody = docBody;
var reverseArray = [];
for (i = 0; i < noOfLessThanMatches; i++) {
var lessThan = newDocBody.search(/<</g);
var moreThan = newDocBody.search(/>>/g);
var subString = newDocBody.substring(lessThan + 2,moreThan);
Logger.log(subString);
var indexOf = formResponsesHeader[0].indexOf(subString);
if (indexOf > -1) {
result += subString + " - FOUND<br>";
} else {
result += subString + " - NOT FOUND<br>";
}
reverseArray.push(subString);
newDocBody = newDocBody.replace("<<" + subString + ">>","XX")
}
result += "<br><b>Form to Doc Check</b><br>";
for (z = 0; z < formResponsesHeader[0].length; z++) {
var thisString = formResponsesHeader[0][z];
var indexOf = reverseArray.indexOf(thisString);
if (indexOf > -1) {
result += thisString + " - FOUND<br>";
} else {
result += thisString + " - NOT FOUND<br>";
}
}
Logger.log(result);
var htmlOutput = HtmlService
.createHtmlOutput('<p>' + result + '</p>')
.setWidth(400)
.setHeight(500);
SpreadsheetApp.getUi().showModalDialog(htmlOutput, 'RESULT');
}
UPDATE: I have pasted the whole code instead above so you guys can see
You have to register onFormSubmit as the function that handles the form submit trigger. Have you registered the function "onFormSubmit" like this:
ScriptApp.newTrigger('onFormSubmit').forForm(form).onFormSubmit().create();
You might also want to check the registered triggers by clicking on Edit > Current project's trigger from your Apps Script project.
[Edit] Since the trigger is created properly, change the first the line of the trigger code from:
function onFormSubmit(e) {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
to this:
function onFormSubmit(e) {
var sheet = SpreadsheetApp.openById(e.source.getDestinationId());
I am getting error in line 29. But the same code works when pasted in another sheet. Separate trigger is used. Edit-> Current project's trigger.
var Team_email='abc#gmail.com';
function TriggerOnEdit(e)
{
Logger.log("stg1");
sendEmailOnassigned(e);
}
function showMessageOnApproval(e)
{
var edited_row = checkStatusIsAssigned(e);
if(edited_row > 0)
{
SpreadsheetApp.getUi().alert("Row # "+edited_row+" approved!");
}
}
function showMessageOnUpdate(e)
{
var range = e.range;
SpreadsheetApp.getUi().alert("range updated " + range.getA1Notation());
}
function checkStatusIsAssigned(e)
{
Logger.log("stg3");
var range = e.range;
if(range.getColumn() <= 12 &&
range.getLastColumn() >=12 )
{
var edited_row = range.getRow();
var status = SpreadsheetApp.getActiveSheet().getRange(edited_row,11).getValue();
if(status == 'Assigned')
{
return edited_row;
}
}
return 0;
}
function sendEmailOnassigned(e)
{
Logger.log("stg2");
var approved_row = checkStatusIsAssigned(e);
if(approved_row <= 0)
{
return;
}
Logger.log("stg4");
sendEmailByRow(approved_row);
}
function sendEmailByRow(row)
{
Logger.log("stg5");
var values = SpreadsheetApp.getActiveSheet().getRange(row,1,row,13).getValues();
var row_values = values[0];
var mail = composeAssignedEmail(row_values);
MailApp.sendEmail(Team_email,mail.subject,mail.message);
var Requester_email = composeRequesterEmail(row_values);
MailApp.sendEmail(Requester_email.email,Requester_email.subject,Requester_email.message);
}
function composeAssignedEmail(row_values)
{
Logger.log("stg6");
var Request_Number = row_values[1];
var email = row_values[2];
var Project_Name = row_values[4];
var Nature_Of_Work = row_values[5];
var Quantity = row_values[6];
var Estimated_Hours = row_values[7];
var Name = row_values[12];
var message = "Hello Requester, \n "+" \n The following Resource "+ Name ;
var subject = "Request_Number - " + Request_Number ;
return({message:message,subject:subject});
}
function composeRequesterEmail(row_values)
{
Logger.log("stg7");
var Request_Number = row_values[1];
var email = row_values[2] ;
var Project_Name = row_values[4];
var Nature_Of_Work = row_values[5];
var Quantity = row_values[6];
var Estimated_Hours = row_values[7];
var Name = row_values[12];
var message = "Hello Requester, \n "+" \n The following Resource "+ Name;
var subject = "Request_Number - " + Request_Number;
return({message:message,subject:subject, email:email });
}
Please tell me the error where is the mistake.
We can not use debug function to understand the mistake. because trigger is on edit.
Also when we use 'e' what are the information do we feed the function?
How to correct this?
I am hitting the Google Scripts 6-minute timeout. The script is running through quite a few folders and subfolders. I am hoping that there is either (or both):
A way to optimize the script to more efficiently/intelligently run through the dataset/iterators?
A way to use a getContinuationToken()
Any help would be much appreciated!
I have tried to limit the number of folders/subfolders the script runs through. Even on a 'minimal' run, it times out. And FYI, my goal is to:
make a copy of files that are NOT owned by 'me'...
change the name of the original file (that was not owned by me) to be 'delete'
Here is the code:
FOLDERS = ["0B4FiuEqe8ftGb2lSbjJzakJDNWs"]; /*, "0B4FiuEqe8ftGN2YxZFU5RlhMSDQ", "0B4FiuEqe8ftGN2YxZFU5RlhMSDQ", "1D_1u_KwcLOsBuKyQ7NCsKDd8DB5JwOn6"];*/
function copyNonOwnedFiles() {
var arr = FOLDERS
for (var j = 0; j < arr.length; j++) {
var folderTOP = DriveApp.getFolderById(arr[j]);
var folders = folderTOP.getFolders();
var me = Session.getActiveUser().getEmail();
//RUN #1 = this runs through all of the subfolders
//iterator 1
while (folders.hasNext()) {
var folder = folders.next();
//get all files within these folders
var files = folder.getFiles();
//iterator 2
while (files.hasNext()) {
var file = files.next();
var Owner = file.getOwner().getEmail();
if( Owner !== me ){
var name = file.getName();
file.makeCopy(name);
file.setName('delete');
}
}
}
//RUN #2 = this runs through the parent folder
var files2 = folderTOP.getFiles();
//iterator 2
while (files2.hasNext()) {
var file2 = files2.next();
var Owner = file2.getOwner().getEmail();
if( Owner !== me ){
var name2 = file2.getName();
file2.makeCopy(name2);
file2.setName('delete');
}
}
}
}
Try this:
This script will find the files owned by the active user, in the folders with the listed ids and display them on a modeless dialog. This script will probably need to utilize lock service for multiple simultaneous users.
var myFiles=[];
var ids=["0B4FiuEqe8ftGb2lSbjJzakJDNWs", "0B4FiuEqe8ftGN2YxZFU5RlhMSDQ", "0B4FiuEqe8ftGN2YxZFU5RlhMSDQ", "1D_1u_KwcLOsBuKyQ7NCsKDd8DB5JwOn6"];
var me='';
function getMyFiles() {
myFiles=[];
me=Session.getActiveUser().getEmail();
for(var i=0;i<ids.length;i++) {
getFnF(DriveApp.getFolderById(ids[i]));
}
var html="<style>th,td{border:1px solid black;}</style><table><tr><th>Item</th><th>Name</th><th>Url</th></tr>";
for(var i=0;i<myFiles.length;i++) {
html+=Utilities.formatString('<tr><td>%s</td><td>%s</td><td>Link</td></tr>',i+1,myFiles[i].name,myFiles[i].url);
}
html+='</table><input type="button" value="Close" onClick="google.script.host.close();" />';
var userInterface=HtmlService.createHtmlOutput(html);
var title=Utilities.formatString('Files Owned by: %s',me);
SpreadsheetApp.getUi().showModelessDialog(userInterface, title)
}
function getFnF(folder) {
var folder= folder || DriveApp.getRootFolder();
var files=folder.getFiles();
while(files.hasNext()) {
var file=files.next();
if(file.getOwner().getEmail()==me) {
myFiles.push({name:file.getName(),url:file.getUrl()});
}
}
var subfolders=folder.getFolders()
while(subfolders.hasNext()) {
var subfolder=subfolders.next();
getFnF(subfolder);
}
}
for anyone who has this same question or a similar one... I found that it was much faster/easier/less resource intensive to use a search than a file iterator
dataSheetName = "List";
function onOpen(){
var ui = SpreadsheetApp.getUi();
ui.createMenu('Custom Menu')
.addItem('List Files', 'ListFiles')
.addSeparator()
.addToUi();
}
function ListFiles() {
var sheet = SpreadsheetApp.getActive();
var dataSheet = sheet.getSheetByName(dataSheetName);
// Clear Sheet
var lastRow = dataSheet.getLastRow();
if (lastRow > 0) {
dataSheet.getRange(2, 1, lastRow, dataSheet.getLastColumn()).clearContent();
}
dataSheet.getRange("E2").setValue("Process Started at: " + new Date());
Logger.log("Start: " + new Date());
// var row = ['File Name', 'File Id'];
var row = ['File Name', 'File Id'];
var data = [];
data.push(row);
// Find files modified in the last 24 hours
var totalDays = 30;
var today = new Date();
var oneDayAgo = new Date(today.getTime() - totalDays * 24 * 60 * 60 * 1000);
var startTime = oneDayAgo.toISOString();
// The magic search expression
var search = '(trashed = false) and (modifiedDate > "' + startTime + '") and not (title contains \'DELETE\') and not (\'me\' in owners) ';
// var search = "(mimeType='image/jpeg') and not (title contains 'DELETE') ";
// var search = " not ('me' in owners) and not (title contains 'DELETE') ";
// var search = " not ('me' in owners) ";
//var search = 'sharedWithMe';
// 'me' in owners
var i = 1;
var files = DriveApp.searchFiles(search);
Logger.log("2: " + new Date());
dataSheet.getRange("E3").setValue("Search Completed at: " + new Date());
// while (files.hasNext() && (i < 10000) {
while (files.hasNext() ) {
var file = files.next();
try {
// data.push([file.getName(),file.getId()]);
data.push([file.getName(), file.getId()]);
}
catch (e) {
Logger.log(file.getName());
}
// i += i;
}
// Write data
var dataRange = dataSheet.getRange(1, 1, data.length, row.length);
dataRange.setValues(data);
Logger.log("3: " + new Date());
dataSheet.getRange("E4").setValue("List Completed at: " + new Date());
}