The following will send email notification if F6 is edited on a google sheet. I need help making it send a notification if any cell in column F is edited, not just one cell. I tried ('F6,F7, etc) and I tried F:F, those don't work.
function emailNotification(e) {
var sheet = e.source.getActiveSheet();
if (sheet.getName() !== 'Sheet1' || e.range.getA1Notation() !== ('F6')) return;
return;
var recipient = "mail#google.com";
var subject = 'SUBJECT';
var body = ' BODY OF MAIL ';
MailApp.sendEmail(recipient, subject, body);
};
Please help, I don't know where I'm going wrong. Otherwise the script works like a charm for a single cell. Just not the whole column
This will run code if any cell in column F of Sheet1 is edited.
function onEdit(e)
{
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var sheetName= sheet.getSheetName();
if(sheetName=="Sheet1"){
var editRange = sheet.getActiveRange();
var editRow = editRange.getRow();
var editCol = editRange.getColumn();
var lr = sheet.getLastRow()
var range = sheet.getRange("F1:F"+lr);
var rangeRowStart = range.getRow();
var rangeRowEnd = rangeRowStart + range.getHeight()-1;
var rangeColStart = range.getColumn();
var rangeColEnd = rangeColStart + range.getWidth()-1;
if (editRow >= rangeRowStart && editRow <= rangeRowEnd
&& editCol >= rangeColStart && editCol <= rangeColEnd)
{
Logger.log("Run Code")
//YOUR CODE HERE
}}}
Related
Exporting events from Google calendar to Google Sheets without the formatting found in the text as in the image. How do I download it?\
function getEvents2022() {//חודש 0122var ss = SpreadsheetApp.getActiveSpreadsheet();var sheet = ss.getSheetByName("0122");
var start_time = sheet.getRange("A2").getValue();var end_time = sheet.getRange("B2").getValue();var id_cal = sheet.getRange("C2").getValue();
var cal = CalendarApp.getCalendarById("AAA#gmail.com");
var events = cal.getEvents(new Date("01/01/2022 12:00 AM"), new Date("01/31/2022 11:59 PM"));
for (var i = 0;i\<events.length;i++){
var title = events[i].getTitle();
var start_time = events[i].getStartTime();
var end_time = events[i].getEndTime();
var loc = events[i].getLocation();
var des = events[i].getDescription();
var vis = events[i].getVisibility();
sheet.getRange(i+2,1).setValue(title);
sheet.getRange(i+2,2).setValue(start_time);
sheet.getRange(i+2,3).setValue(end_time);
sheet.getRange(i+2,4).setValue(loc);
sheet.getRange(i+2,5).setValue(des);
sheet.getRange(i+2,6).setValue(vis);
}
I'm not sure if this is exactly what you want but try it.
let events = calendar.getEvents(start,end);
let desc = [];
events.forEach( event => {
let text = event.getDescription();
text = text.replace(/<.+?>/gm,"");
console.log(text);
}
);
Reference
RegExr
I need a little help with a google spreadsheet script. Currently I'm using a script to copy entire row if contition is met(checkbox TRUE/FALSE). If different condition is met(different checkbox), i need to copy that entire row to "Completed" AND the tricky part for me, I need to ONLY copy cells in A,B,P columns in that specific row to sheet "Flash" to position A,B,C.. Could someone help me? Thanks!
function onEdit(event) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "Orders" && r.getColumn() == 9 && r.getValue() == true) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Completed");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
} else if(s.getName() == "Orders" && r.getColumn() == 15 && r.getValue() == true) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Completed");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).copyTo(target);
var targetSheet = ss.getSheetByName("Flash");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).copyTo(target);
s.deleteRow(row);
}
}
I'm trying to save all of the sheets on my spreadsheet to google drive as one PDF (ultimately I would like to have them email as well). I'm having trouble saving more than just one of the sheets. I've tried multiple way of doing it. The code below is the best way I've found so far. Again the problem is that it only saves the first page as a PDF, I cant figure out how to get around the delete redundant sheets. All the posts I have seen only want to save 1 page, I have over 24 pages that need to be saved as one PDF. Thanks in advance for your help!
function PDF() {
var sheetName = SpreadsheetApp.getActiveSpreadsheet();
var folderID = "*** Google Drive ID***"; // Folder id to save in a Drive folder.
var ss = SpreadsheetApp.openByUrl(
'https://docs.google.com/spreadsheets/d/***Spreadsheet ID***');
var pdfName = "MAR - " + ss.getRange("A1:A1").getValue(); //Need to set the values to another sheet
var sourceSpreadsheet = SpreadsheetApp.getActive();
var sourceSheet = sourceSpreadsheet.getSheetByName(sheetName);
var folder = DriveApp.getFolderById(folderID);
//Copy whole spreadsheet
var destSpreadsheet = SpreadsheetApp.open(DriveApp.getFileById(sourceSpreadsheet.getId()).makeCopy("tmp_convert_to_pdf", folder))
//delete redundant sheets
var sheets = destSpreadsheet.getSheets();
for (i = 0; i < sheets.length; i++) {
if (sheets[i].getSheetName() != sheetName){
destSpreadsheet.deleteSheet(sheets[i]);
}
}
var destSheet = destSpreadsheet.getSheets()[0];
//repace cell values with text (to avoid broken references)
var sourceRange = sourceSheet.getRange(1,1,sourceSheet.getMaxRows(),sourceSheet.getMaxColumns());
var sourcevalues = sourceRange.getValues();
var destRange = destSheet.getRange(1, 1, destSheet.getMaxRows(), destSheet.getMaxColumns());
destRange.setValues(sourcevalues);
//save to pdf
var theBlob = destSpreadsheet.getBlob().getAs('application/pdf').setName(pdfName);
var newFile = folder.createFile(theBlob);
//Delete the temporary sheet
DriveApp.getFileById(destSpreadsheet.getId()).setTrashed(true);
}
By using Drive API, you can convert from a spreadsheet to a PDF which has all sheets in the spreadsheet. In order to use this, so please enable Drive API on Google API Console as follows.
In the script editor, select Resources > Cloud Platform Project
At the bottom of the dialog, click the link for the Google API Console.
In the console, click into the filter box and type part of the name of the API "Drive API", then click the name once you see it.
On the next screen, click Enable API.
Close the Developers Console and return to the script editor. Click OK in the dialog.
I prepared a sample script for creating PDF file from spreadsheet. Please use this to your script.
Script :
var spreadsheetId = "#####";
var folderId = "#####";
var outputFilename = "#####";
var url = "https://www.googleapis.com/drive/v3/files/" + spreadsheetId + "/export?mimeType=application/pdf";
var options = {
method: "GET",
headers: {Authorization: "Bearer " + ScriptApp.getOAuthToken()},
muteHttpExceptions: true
};
var response = UrlFetchApp.fetch(url, options).getBlob();
DriveApp.getFolderById(folderId).createFile(response).setName(outputFilename);
About this script, although I confirmed this works fine, if it doesn't work at your environment, please tell me. And if I misunderstand your question, I'm sorry.
Added 1 :
function PDF() {
var sheetName = SpreadsheetApp.getActiveSpreadsheet();
var folderID = "*** Google Drive ID***"; // Folder id to save in a Drive folder.
var ss = SpreadsheetApp.openByUrl(
'https://docs.google.com/spreadsheets/d/***Spreadsheet ID***');
var pdfName = "MAR - " + ss.getRange("A1:A1").getValue(); //Need to set the values to another sheet
var sourceSpreadsheet = SpreadsheetApp.getActive();
var sourceSheet = sourceSpreadsheet.getSheetByName(sheetName);
var folder = DriveApp.getFolderById(folderID);
//Copy whole spreadsheet
var destSpreadsheet = SpreadsheetApp.open(DriveApp.getFileById(sourceSpreadsheet.getId()).makeCopy("tmp_convert_to_pdf", folder))
//delete redundant sheets
var sheets = destSpreadsheet.getSheets();
for (i = 0; i < sheets.length; i++) {
if (sheets[i].getSheetName() != sheetName){
destSpreadsheet.deleteSheet(sheets[i]);
}
}
var destSheet = destSpreadsheet.getSheets()[0];
//repace cell values with text (to avoid broken references)
var sourceRange = sourceSheet.getRange(1,1,sourceSheet.getMaxRows(),sourceSheet.getMaxColumns());
var sourcevalues = sourceRange.getValues();
var destRange = destSheet.getRange(1, 1, destSheet.getMaxRows(), destSheet.getMaxColumns());
destRange.setValues(sourcevalues);
//save to pdf
// var theBlob = destSpreadsheet.getBlob().getAs('application/pdf').setName(pdfName);
// var newFile = folder.createFile(theBlob);
// A sample script was added here.
var url = "https://www.googleapis.com/drive/v3/files/" + destSpreadsheet.getId() + "/export?mimeType=application/pdf";
var options = {
method: "GET",
headers: {Authorization: "Bearer " + ScriptApp.getOAuthToken()},
muteHttpExceptions: true
};
var response = UrlFetchApp.fetch(url, options).getBlob();
DriveApp.getFolderById(folderID).createFile(response).setName(pdfName);
//Delete the temporary sheet
DriveApp.getFileById(destSpreadsheet.getId()).setTrashed(true);
}
Added 2 :
function PDF() {
var folderID = "*** Google Drive ID***"; // Folder id to save in a Drive folder.
var ss = SpreadsheetApp.openByUrl(
'https://docs.google.com/spreadsheets/d/***Spreadsheet ID***');
var pdfName = "MAR - " + ss.getRange("A1:A1").getValue(); //Need to set the values to another sheet
var sourceSpreadsheet = SpreadsheetApp.getActive();
var folder = DriveApp.getFolderById(folderID);
// A sample script was added here.
var url = "https://www.googleapis.com/drive/v3/files/" + sourceSpreadsheet.getId() + "/export?mimeType=application/pdf";
var options = {
method: "GET",
headers: {Authorization: "Bearer " + ScriptApp.getOAuthToken()},
muteHttpExceptions: true
};
var response = UrlFetchApp.fetch(url, options).getBlob();
DriveApp.getFolderById(folderID).createFile(response).setName(pdfName);
}
Here is the function that creates PDF file from google sheet and function that moves new created file into the folder that id you give to the parameter of the function.
function downloadPDF(fileId, folderId) {
var file = Drive.Files.get(fileId);
var url = file.exportLinks[MimeType.PDF];
var options = {
headers: {
Authorization:"Bearer " + ScriptApp.getOAuthToken()
},
muteHttpExceptions : true
}
var response = UrlFetchApp.fetch(url, options);
var status = response.getResponseCode();
var result = response.getContentText();
if (status != 200) {
// Get additional error message info, depending on format
if (result.toUpperCase().indexOf("<HTML") !== -1) {
var message = strip_tags(result);
}
else if (result.indexOf('errors') != -1) {
message = JSON.parse(result).error.message;
}
throw new Error('Error (' + status + ") " + message );
}
var doc = response.getBlob();
var newFileid = DriveApp.createFile(doc).setName(file.title + '.pdf').getId();
let id = moveFileTo(newFileid, folderId);
return id;
}
function moveFileTo(sourceId, folderId){
let file = DriveApp.getFileById(sourceId)
let blob = file.getBlob();
let id = DriveApp.getFolderById(folderId).createFile(blob).getId();
file.setTrashed(true)
return id;
}
I am trying to make it so if any cells between I4:AI503 on the spreadsheet listed below gets edited, it will update the timestamp in column AK.
The following code is used in this spreadsheet:
function onEdit() {
var ss = SpreadsheetApp.getActiveSheet();
if (ss.getName() == "RS3 Points") {
var range = ss.getActiveCell();
var col = range.getColumn();
var row = range.getRow();
if ((col >= 9) && (col <= 35) && (row > 3)) {
var ActiveCell = ss.getRange().getRow()
var TimestampCol = ss.getLastColumn()
var formattedDate = Utilities.formatDate(new Date(), "GMT", "dd-MM-yyyy");
var GetRange = ss.getRangeByName(ActiveCell, TimestampCol)
GetRange.setValue(formattedDate)
}
}
}
Make sure column AK is formatted as Date. Then, try this code:
function onEdit(e) {
if (e.source.getActiveSheet().getName() !== "RS3 Points" ||
e.range.columnStart < 9 || e.range.columnStart > 35 ||
e.range.rowStart < 4 || e.range
.columnStart < e.range.columnEnd) return;
e.range.offset(0, 37 - e.range.columnStart).setValue(new Date());
}
These two scripts are incredibly slow. I work with a data set of about 32 columns by 1000 rows ( growing pretty rapidly ).
I've read and even used code for treating data like an array so that you can make only one call to google-services, but I'm not sure how that can help me with this case.
I need to hide certain columns depending on which person is using the google sheet
Here is the actual code:
function HideColumns(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var range = sheet.getRange("A1");
sheet.hideColumn(range);
range = sheet.getRange("C1:E1");
sheet.hideColumn(range);
range = sheet.getRange("G1");
sheet.hideColumn(range);
range = sheet.getRange("I1");
sheet.hideColumn(range);
range = sheet.getRange("K1");
sheet.hideColumn(range);
range = sheet.getRange("Q1:Z1");
sheet.hideColumn(range);
range = sheet.getRange("AC1:AG1");
sheet.hideColumn(range);
}
function ShowColumns(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var range = sheet.getRange("A1");
sheet.unhideColumn(range);
range = sheet.getRange("C1:E1");
sheet.unhideColumn(range);
range = sheet.getRange("G1");
sheet.unhideColumn(range);
range = sheet.getRange("I1");
sheet.unhideColumn(range);
range = sheet.getRange("K1");
sheet.unhideColumn(range);
range = sheet.getRange("Q1:Z1");
sheet.unhideColumn(range);
range = sheet.getRange("AC1:AG1");
sheet.unhideColumn(range);
}
unfortunately hiding columns is a "spreadsheet only" function, no way to make it faster or in batch...
maybe you could imagine a custom UI (built with UiApp or HTMLService) to show only the user relevant data ? but that might not be possible, depending on how much you need spreadsheet specific features..., not speaking of the work it might represent.
For the ShowColumns() script, are you just needing to unhide all columns in the sheet? If so, you could at least simplify that one a bit:
function ShowColumns() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var range = sheet.getRange("1:1");
sheet.unhideColumn(range);
}
You can use batch request to Sheets API (enable advanced service first) to hide/unhide multiple columns in one API call:
function changeHideForColumnsOptimized(ssId, sheetId, columns, hide)
{
let requests = [];
columns.map(col => {
// get column index/indexes
let colArray = col.split(':');
let startIndex = letterToColumn(colArray[0]) - 1;
let endIndex = letterToColumn(colArray[colArray[1] ? 1 : 0]) - 1;
let hiddenByUser = hide ? true: false;
requests.push({
updateDimensionProperties: {
range: {
sheetId: sheetId,
dimension: 'COLUMNS',
startIndex: startIndex, // start index is inclusive
endIndex: endIndex + 1 // end index is exclusive
},
properties: {
hiddenByUser: hiddenByUser
},
fields: 'hiddenByUser'
}
})
});
Sheets.Spreadsheets.batchUpdate({requests: requests}, ssId);
}
// via https://stackoverflow.com/a/21231012/555121
function letterToColumn(letter)
{
var column = 0, length = letter.length;
for (var i = 0; i < length; i++)
{
column += (letter.charCodeAt(i) - 64) * Math.pow(26, length - i - 1);
}
return column;
}
An then use it like this:
function HideColumns(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
let columnsToHide = ['A', 'C:E', 'G', 'I', 'K', 'Q:Z', 'AC:AG'];
changeHideForColumnsOptimized(ss.getId(), sheet.getSheetId(), columnsToHide, true);
}
function ShowColumns(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
let columnsToUnHide = ['A', 'C:E', 'G', 'I', 'K', 'Q:Z', 'AC:AG'];
changeHideForColumnsOptimized(ss.getId(), sheet.getSheetId(), columnsToUnHide, false);
}
This answer is based on these two questions:
Hide column with Sheets API call
Convert column index into corresponding column letter