I'm trying to put on some Google Function to make that in the title. I'm very beginner but I'm up for the challenge. I managed to make a button that clears the whole range (C5:G102).
But I want now a code that clears that range only for the dates that are older than today.
I have columns with subject, a deadline, description, etc. The whole date goes from column C to G. So when I click the button I want all subjects in that row that already has an older deadline than today, to be cleared out. The dates are in the column D.
Can that be done?
I have only this:
function clearRange() {
//replace 'Sheet1' with your actual sheet name
var sheet = SpreadsheetApp.getActive().getSheetByName('ADD');
sheet.getRange('C5:G102').clearContent();
}
So, after some trying I came up with this: but it doesn't work...
function ClearOlder() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('ADD');
var lastRow = sheet.getLastRow();
var columnD = sheet.getRange(2, 4, sheet.getLastRow(), 1).getValues();
var day = 24*3600*1000
var today = parseInt((new Date().setHours(0,0,0,0))/day);
for (var i=1; i < columnD.length; i++) {
var dataday = parseInt(new Date(columnD[i][4]).getTime()/day);
if (dataday < today) {sheet.getRange(i+1, 4, lastRow, 1).clearContent();}
}
}
You can actually compare date directly in javascript. You do not need the parseInt() function.
var TEN_DAYS = 10 * 24 * 60 * 60 * 1000;
// days hrs min sec ms
var expiry = new Date() - TEN_DAYS;
var date1 = new Date('2019-02-5');
var date2 = new Date('2019-02-1');
var date3 = new Date('2019-01-25');
console.log(expiry > date1); //Less than 10 days ago
console.log(expiry > date2); //Less than 10 days ago
console.log(expiry > date3); //More than 10 days ago
Updated: Your columnD selector was off.
function clearOlder() {
//consider camelCase --> clearOlder()
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var lastRow = sheet.getLastRow();
var columnD = sheet.getRange(2, 4, sheet.getLastRow(), 1).getValues(); //OP updated this to better fit their specific spreadsheet.
var one_day = 24*3600*1000;
var expiry = new Date() - one_day;
for (var i=1; i < columnD.length; i++) {
var dataday = new Date(columnD[i][0]);
if (expiry > dataday) {
sheet.getRange(i+1, 1, 1, 4).clearContent(); //OP updated this to better fit their specific spreadsheet.
}
}
}
Yes! I got it!!!
function clearOlder() {
//consider camelCase --> clearOlder()
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var lastRow = sheet.getLastRow();
var columnD = sheet.getRange(1, 4, sheet.getLastRow(), 5).getValues();
var one_day = 24*3600*1000;
var expiry = new Date() - one_day;
for (var i=1; i < columnD.length; i++) {
var dataday = new Date(columnD[i][0]);
if (expiry > dataday) {
sheet.getRange(i+1, 1, 1, 5).clearContent();
}
}
}
Related
I am intending to send an email after 5 days comparing the timestamp in my google sheet. But it is not working.
Below is my code:
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2;
var numRows = sheet.getLastRow();
var dataRange = sheet.getRange(startRow, 2, numRows, 15)
var data = dataRange.getValues();
for (var i = 0; i < data.length; i++) {
var row = data[i];
var Timestamp = row[0];
var todaydate = new Date();
var secondDate = new Date();
secondDate.setDate(todaydate.getDate()+5);
if (Timestamp <= secondDate){
var messageHtml = "Hi " +
"<br><br>Test " +
"<br><br>test" +
"<br>Thank You<br><br>";
var message = messageHtml.replace(/\<br\/\>/gi, '\n').replace(/(<([^>]+)>)/ig, "");
// clear html tags and convert br to new lines for plain mail
var subject = "Uniform Order Form Pending Process";
MailApp.sendEmail("test#gmail.com", subject,message);
}
}
};
Sorry that maybe it might be something very simple but hope you guys can advise me.
Thanks
Try
secondDate.setDate(todaydate.getDate()+5 * 86400000);
one day is: 1000 * 60 * 60 * 24, which is 86400000 milliseconds.
I have a spreadsheet with multiple tabs all with a date in column A.
I need a script that I can run using a trigger each night to move all rows with a historic date in Column A to a single tab for historic rows.
I have been successful in getting historic rows in my first sheet to move to the historic tab however I cannot seem to make the script work for multiple tabs.
function HistoricDates() {
SHEET_NAME = "Area1" || "Area2" || "Area3"||"Area4";
// Initialising
var ss = SpreadsheetApp.getActiveSpreadsheet();
var Sheet = ss.getSheetByName(SHEET_NAME);
var PastSheet = ss.getSheetByName("Historic Sheet");
var lastColumn = Sheet.getLastColumn();
// Check all values from sheets
for(var i = Sheet.getLastRow(); i > 0; i--){
// Check if the value is a valid date
var dateCell = Sheet.getRange(i, 1).getValue(); //Dates in column 1
if(isValidDate(dateCell)){
var today = new Date();
var test = new Date(dateCell);
// If the value is a valid date and is a past date, we remove it from the sheet to paste on the other sheet
if(test < today){
var rangeToMove = Sheet.getRange(i, 1, 1, Sheet.getLastColumn()).getValues();
PastSheet.getRange(PastSheet.getLastRow() + 1, 1, 1, Sheet.getLastColumn()).setValues(rangeToMove);
Sheet.deleteRow(i);
}
}
}}
// Check is a valid date
function isValidDate(value) {
var dateWrapper = new Date(value);
return !isNaN(dateWrapper.getDate());
}
The expected result would be for all historic rows in Area 2,3 & 4 to move to move to the single historic tab.
My spreadsheet with script is available on the following link:
https://docs.google.com/spreadsheets/d/1WiZWok4onddTErdAxlWmU82KRSGfVJr5wi1p-rlbY5E/edit?usp=sharing
The way you defined SHEET_NAME, it will always be "Area 1". You can test this.
function test() {
SHEET_NAME = "Area1" || "Area2" || "Area3"||"Area4";
Logger.log(SHEET_NAME);
}
Instead, SHEET_NAME should be an array, and then you need to loop through that array. Below I've included a sample for how to define that array and get the sheets.
function loopThroughSpecificSheets() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheetNames = ["Area1", "Area2", "Area3", "Area4"];
for (var j in sheetNames) {
var sheet = ss.getSheetByName(sheetNames[j]);
// Do other stuff
}
}
Assuming that the rest of your code works correctly (I haven't analyzed it), your modified script would look like this:
function HistoricDates() {
// Initialising
var ss = SpreadsheetApp.getActiveSpreadsheet();
var pastSheet = ss.getSheetByName("Historic Sheet");
var sheetNames = ["Area1", "Area2", "Area3", "Area4"];
for (var j in sheetNames) {
var sheet = ss.getSheetByName(sheetNames[j]);
var lastColumn = sheet.getLastColumn();
// Check all values from sheets
for(var i = sheet.getLastRow(); i > 0; i--) {
// Check if the value is a valid date
var dateCell = sheet.getRange(i, 1).getValue(); //Dates in column 1
if(isValidDate(dateCell)){
var today = new Date();
var test = new Date(dateCell);
// If the value is a valid date and is a past date, we remove it from the sheet to paste on the other sheet
if(test < today) {
var rangeToMove = sheet.getRange(i, 1, 1, sheet.getLastColumn()).getValues();
pastSheet.getRange(pastSheet.getLastRow() + 1, 1, 1, sheet.getLastColumn()).setValues(rangeToMove);
sheet.deleteRow(i);
}
}
}
}
}
// Check is a valid date
function isValidDate(value) {
var dateWrapper = new Date(value);
return !isNaN(dateWrapper.getDate());
}
I have a spreadsheet that I would like to autosort based on date, delete duplicate rows, and delete rows if the date listed has passed. I have the autosort and deleting duplicates, I just need help with deleting rows based on the date. It will delete all rows except row # 2, regardless of date.
So far I have:
function deleteRow1() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = sheet.getLastRow()-1; // Number of rows to process
var dataRange = sheet.getRange(startRow, 2, numRows);
var data = dataRange.getValues();
for (i = 0; i < data.length; i++) {
var row = data[i];
var date = new Date();
var sheetDate = new Date(row);
var Sdate = Utilities.formatDate(date, 'EST-0500', 'MM:dd:yyyy')
var SsheetDate = Utilities.formatDate(sheetDate, 'EST-0500', 'MM:dd:yyyy')
if (Sdate > SsheetDate) {
sheet.deleteRow(i + 2)
}
}
}
So here is about what it could look like, I think. I changed as little as I could about your routine, focusing on the parts that seemed like they were troubling.
In particular, dates are compared to dates, with times removed/equated. Also, it bothered me to repeatedly construct today, so I took that outside the loop.
Also, I worked from the bottom up to make sure deletions did not affect which row to consider next.
function deleteRow1() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = sheet.getLastRow()-1; // Number of rows to process
var dataRange = sheet.getRange(startRow, 2, numRows);
var data = dataRange.getValues();
var today = new Date();
today.setHours(0,0,0,0);
for (i = data.length-1; i > -1; i--) {
var row = data[i];
var sheetDate = new Date(row);
sheetDate.setHours(0,0,0,0);
if (today > sheetDate) {
sheet.deleteRow(i + 2)
}
}
}
It might be a nice touch to change i+2 to startRow+i.
I have a Spreadsheet with many sheets inside it, Each sheet represents one month, and has dates in column B. I'm trying to create a function that searches for the current date and inserts the current time in column C. I've got a function to work by specifying the sheet, but I want it to find the sheets itself.
I've got the following code:
function insertTime() {
var date = new Date();
var hours = date.getHours()
var minutes = date.getMinutes()
var timeStamp = hours + ':' + minutes
var ss = SpreadsheetApp.getActiveSpreadsheet()//// get the sheet
var sheets = ss.getSheets();// get all the sheets
var today = new Date(); //get todays date
for (var sheetNum = 1; sheetNum < sheets.length; sheetNum++){
var sheet = ss.getSheets()[sheetNum]
var columnB = sheet.getRange(2, 2, sheet.getLastRow()-1, 1); // get all the rows
var bValues = columnB.getValues(); // get the values
for (var i = 0; i < bValues.length; i++) { // repeat loop
var fDate = new Date(bValues[i][0]);
if (fDate.getDate() == today.getDate() &&
fDate.getMonth() == today.getMonth() &&
fDate.getFullYear() == today.getFullYear()) { // if the date in the cell is today's date...
sheet.getRange(i + 2, 3, 1, 1).setValue(timeStamp);
}
}
}
}
Which is giving me the following error: "The coordinates or dimensions of the range are invalid. (line 16)"
At least one of your sheets is empty or has only 1 row of data.
In this case on line 16, sheet.getLastRow()-1 will be 0 or -1 which is creating the error.
I figured it out in the end, I used the forEach function:
function myFunction(){
var date = new Date();
var hours = date.getHours()
var minutes = date.getMinutes()
var timeStamp = hours + ':' + minutes
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
sheets.forEach (function (sheet) {
var columnB = sheet.getRange(2, 2, 70, 1);
var bValues = columnB.getValues();
var today = new Date();
for (var i = 0; i < bValues.length; i++) {
var fDate = new Date(bValues[i][0]);
if (fDate.getDate() == today.getDate() &&
fDate.getMonth() == today.getMonth() &&
fDate.getFullYear() == today.getFullYear()) {
sheet.getRange(i + 2, 7, 1, 1).setValue(timeStamp);
}
}
}
I want a Google Script which checks once a day on my spreadsheet and copies the values to another sheet and than deletes all the rows if the date in that cell is small than the current.
The file looks like this:
And this is what I wrote so far:
function DeleteIfDateIsToSmall(event) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
var today = new Date();
var today2 = Utilities.formatDate(today,'GMT+0200','dd.MM.yyyy');
var startRow = 2; // First row of data to process
var numRows = sheet.getLastRow()-1
for (var i=2; i < numRows; i++) {
var DateCell = s.getRange(i, 13);
var sheetDate = DateCell.getValue()
var sheetDate2 = Utilities.formatDate(sheetDate,'GMT+0200','dd.MM.yyyy');
var row = i;
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Ended or Deleted");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
if (s.getName() == "Start" && sheetDate != 0 && sheetDate != "" && today2.valueOf() > sheetDate2.valueOf()){
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
}
}
}
It doesn't seem to work, please help.
A few things are wrong or suboptimal here.
For a timed trigger, the event object does not have any range/source data; it only has time data. You need to pick a sheet by name (or loop through all sheets obtained by getSheets, if this is what you want).
Utilities.formatDate returns a string, which is not the best way to compare dates; in any case calling valueOf on it seems pointless.
Instead of using getValue in a loop, it is more efficient to obtain values before entering the loop, with getValues. There are some other things you do in the loop that should be outside.
Deleting rows when moving top to bottom in a sheet is tricky, because rows shift, messing up their indexing. For this reason, I collect the rows to be deleted in an array, and then delete them in bottom-to-top order.
function DeleteIfDateIsTooSmall() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName("Start");
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Ended or Deleted");
var today = new Date();
var dates = s.getRange(2, 13, s.getLastRow()-1, 1).getValues();
var rowsToDelete = [];
for (var i = 0; i < dates.length; i++) {
if (dates[i][0] && dates[i][0] < today) {
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(i + 2, 1, 1, numColumns).moveTo(target);
rowsToDelete.push(i + 2);
}
}
for (i = rowsToDelete.length - 1; i >= 0; i--) {
s.deleteRow(rowsToDelete[i]);
}
}