I am trying to write a script for sheets that will move all resolved support tickets older than 30 days to the archive sheet. It'll then delete the entries from the current support sheet. If the ticket does not have a completion date it should be skipped. Currently the script is not moving the all the correct cells. Sometimes it moves things that are newer than 30 days and other times it moves things that have null entries. Thanks in advance.
function moveAfterThirty() {
const sh = SpreadsheetApp.getActive();
const ss = sh.getSheetByName("Current Support Requests"); //requests
const dest = sh.getSheetByName("Archived Support Requests"); //destination
let data = ss.getDataRange().getValues(); //all values
let timeRange = getFullColumn('C', 2).getValues(); //date values for the entire Requests Sheet
var length = timeRange.length;
var date = new Date(); //new date
date.setDate(date.getDate() - 30); //setting date to 30 days ago
for (let i = 0; i < timeRange.length; i++){
var d1 = new Date(timeRange[i]); //setting d1 to the date that corresponds with the position in the array
if (d1 < date)
{
ss.getRange(i+1,1,1,14).moveTo(dest.getRange(dest.getLastRow()+1,1,1,14)); //goes to the row and moves all information
ss.deleteRow(i+1); //deletes row
}
else //if no date of completion do nothing
{
}
}
}
function getFullColumn(column, startIndex){
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var ss = sheet.getSheetByName("Current Support Requests");
var lastRow = ss.getLastRow();
return sheet.getRange(column+startIndex+':'+column+lastRow)
}
I am expected it to purge all the entries that have been completed more than 30 days ago. So far it is giving me a hodgepodge of some things moved and other things not.
As a guess. Try to change this line:
if (d1 < date)
with:
if (d1.getTime() < date.getTime())
Move after 30 days
function moveAfterThirty() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName("Sheet0");
const dsh = ss.getSheetByName("Sheet1");
const dtv = new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate() - 30).valueOf();
let vs = sh.getRange(2, 1, sh.getLastRow() - 1, sh.getLastColumn()).getValues();
var a = [];
var d = 0;
vs.forEach((r, i) => {
let dv = new Date(r[2]).valueOf();
if (dv < dtv) {
a.push(r);
sh.deleteRow(i + 2 - d++)
}
});
dsh.getRange(dsh.getLastRow() + 1, 1, a.length, a[0].length).setValues(a);
}
Related
I am trying to automate moving a row of data from a sheet called Pending to a sheet called Closed if the bid due date (located in column F) is older than 60 days. I am a beginner and use a lot of outside sources to help me build what I want, but I don't fully understand what I am writing, as long as it works.
This is what I have tried to write and I am looking for some fine tuning
function approveRequests() {
// Initialising
var ss = SpreadsheetApp.getActiveSpreadsheet();
var scheduleSheet = ss.getSheetByName("Pending");
var pastSheet = ss.getSheetByName("Closed");
var lastColumn = scheduleSheet.getLastColumn();
for(var i = scheduleSheet.getLastRow(); i > 60; i--){
var dateCell = scheduleSheet.getRange(i, 1).getValue();
if(isValidDate(dateCell)){
var today = new Date();
var test = new Date(dateCell);
if(test < today){
var rangeToMove = scheduleSheet.getRange(i, 1, 1, scheduleSheet.getLastColumn()).getValues();
pastSheet.getRange(pastSheet.getLastRow() + 1, 1, 1, scheduleSheet.getLastColumn()).setValues(rangeToMove);
scheduleSheet.deleteRow(i);
}
}
}
}
function isValidDate(value) {
var dateWrapper = new Date(value);
return !isNaN(dateWrapper.getDate());
}
Move Row is column 1 is older than 60 days:
function approveRequests() {
const ss = SpreadsheetApp.getActive();
const sh1 = ss.getSheetByName("Pending");
const vs1 = sh1.getRange(61,1,sh1.getLastRow() - 60, sh1.getLastColumn()).getValues();
const sh2 = ss.getSheetByName("Closed");
const dt = new Date();
const dtv = new Date(dt.getFullYear(),dt.getMonth(),dt.getDate() - 60);
let d = 0;
vs1.forEach((r,i) => {
if (new Date(r[0]).valueOf() < dtv) {
sh2.getRange(sh2.getLastRow() + 1, 1, 1, r.length).setValues([r]);
sh1.deleteRow(i + 61 - d++);
}
});
}
I currently have a script on Google Sheets that auto deletes rows after a certain date. However, I would like to change it so that it auto archives the rows to another sheet instead. I added in the target sheet , but I'm at a loss on how to move the rows, before it deletes.
function ArchiveOldEntries() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Form Responses 1");
var datarange = sheet.getDataRange();
var lastrow = datarange.getLastRow();
var values = datarange.getValues();
var targetSheet = ss.getSheetByName("Archive");
var currentDate = new Date()//today
var yesterday = new Date();//yesterday
yesterday.setDate(currentDate.getDate() - 1);
for (i=lastrow;i>=2;i--) {
var tempDate = values[i-1][2];
if (tempDate <= yesterday)
{
sheet.deleteRow(i)
}
}
}
Archive and Delete rows one day old or more
function ArchiveOldEntries() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName("Sheet0");//source sheet
const vs = sh.getDataRange().getValues();
const tsh = ss.getSheetByName("Sheet1");//archive sheet
const dt = new Date();
const ytdv = new Date(dt.getFullYear(), dt.getMonth(), dt.getDate() - 1).valueOf();//yesterday value
let d = 0;
vs.forEach((r,i) => {
let cdv = new Date(r[2]).valueOf();//date is in column3
if(cdv <= ytdv) {
tsh.getRange(tsh.getLastRow() + 1,1,1,r.length).setValues([r])
sh.deleteRow(i + 1 - d++)
}
});
}
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();
}
}
}
I found this solution but am struggling to get it to work on my sheet.
The user who submitted that question had 3 header rows and wanted the script to only work on row 4 and down. I have 1 header, and as such need the script to work on row 2 and down.
I've got it leaving row 1 alone - but it ONLY hides rows 2 and 3. I can't figure out where I'm going wrong.
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var menuItems=[{name: 'HideRows', functionName: 'hideRows'}];
ss.addMenu('Hide Rows', menuItems);
};
function hideRows() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName("Responses");
var v = s.getRange("B:B").getValues();
var today = new Date();
var m = today.getMonth();
for(var i=3;i<v.length;i++)
if(v[i][0]=="" || v[i][0].getMonth()>=m) break;
if(i>1) s.hideRows(2,i-1)
};
ETA: Here's a link to my sheet/script: https://docs.google.com/spreadsheets/d/1PkB1_hlJoI-iFYTAN8to_ES9R8QyUxEgPsWtSTUmj8U/edit?usp=sharing
function hideRows() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName('Responses');
// start range from B2 skipping header
// join() + split(',') converts 2D array into plain array
// filter(Boolean) skips all the blank cells in column
var v = s.getRange('B2:B').getValues().join().split(',').filter(Boolean);
// today in milliseconds for date comparison
var today = new Date().getTime();
// one month in milliseconds
var oneMonth = 2629746000;
Logger.log(v.length);
for (var i=0;i<v.length;i++) {
// Date Object from cell in B2:B in milliseconds
var vDate = new Date(v[i]).getTime();
// exit for loop when first date less than one month is found
if (today - vDate <= oneMonth) {
break;
}
}
Logger.log(i+1);
s.hideRows(2, i);
}
You have a syntax error on your for loop as well as the if statements. There should be {} the code to be worked on when in these portions. Then there is an error in your logic. The month of October in row 2 is greater than the current month, February. So you may want to first compare Years for the highest year and then compare months:
function hideRows() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName("Responses");
var v = s.getRange("B:B").getValues();
var today = new Date();
var m = today.getMonth();
var y = today.getYear();
for(var i=3;i<v.length;i++){
if(v[i][0] === "" || v[i][0].getYear() >= y){
if(v[i][0].getMonth() >= m) {
var stophere = 0;
break;
}
}
}
if(i>1) {
s.hideRows(2,i-1);
}
};
function onOpen(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Responses');
var today= new Date();
var today=today.setDate(today.getDate()-30); //minus 30 days
for ( var i = sheet.getLastRow(); i >= 2 ; i-- ) {
var filter = sheet.getRange(i, 2).getValue();//Evaluates Column B
if ( filter.valueOf() < today.valueOf()) {
sheet.hideRows(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);
}
}
}