day and month are swapped? - google-apps-script

I have a column 'C' containing dates and in that some cell values are having values like " Due on Date". I have written app script code that if a cell value contains "Due on" it will be copied to another column,else copied to different column.But on running I found that cells having "due on " on running the date and month are interchanged. for eg: if a cell contains "Due on 08/02/2022(dd/MM/yyyy)" is changed to "02/08/2022(MM/dd/yyyy)". Is there any method to retain the same date format.I have already done the date format methods in the spreadsheet and maintained the same time zone .
Here is the sample code:
for(var i=value.length-1;i>=0;i--){
var chn = value[i];
if(chn[2]!="NA"){
// var rdate= new Date(chn[2]);
var dat=Utilities.formatDate(new Date(chn[2]), "GMT+5:30", "dd-MMMM-yyyy");
var mat= chn[2].toString();
if(mat.match(/Due on/)){
var d1= mat.replace("Due on", "");
var ds = new Date(dat);
var year = ds.getFullYear();
var month = ds.getDate();
var day = ds.getMonth();
Logger.log(chn[2]);
Logger.log(dat);
Logger.log(ds);
Logger.log(month);
// var pubdate = new Date(year, day,month);
// Logger.log(pubdate);
ss.getRange("C"+(i+2)).setValue("Valid till "+Utilities.formatDate(ds, "GMT+5:30", "dd-MMMM-yyyy"));
}
else{
.................
}
}
A copy of the spreadsheet and the executions log is attached here:
Execution log:

You code works for me correctly, however here are some thoughts for troubleshooting
You do not specify into which sheet you want to write (I assume ss is SpreadsheetApp.getActiveSpreadsheet()). This is dangerous when your spreadsheet has several sheets. It's best to sue the method getSheetByName()
Reduce your code snippet to something simpler to reduce potential error sources
Change you spreadsheet locale for changing the date formatting
Since your date is concatenated to a string (and the method formatDate() returns a date anyway), the output should not be affected by any locales and date formatting, however to be sure, try to set it explicitly to a string.
Make sure you pass to new Date() a valid date object or date string.
This code snippet works for me regardless of the spreadsheet locale and the number formatting of the cells:
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
for(var i = 10; i >= 0; i--){
var dat=Utilities.formatDate(new Date("2022-05-15"), "GMT+5:30", "dd-MMMM-yyyy");
ss.getRange("C"+(i+2)).setValue(("Due on " + dat).toString());
}
}
UPDATE:
If the problem is the format of the original date string, you need to convert it to the necessary format for new Date(). To do so, you need to know the formatting of the original date string.
For a date string with the format ddmmyyyy , you can do it as following:
var chn = [];
chn[2] = "15052022";
var day = Number(chn[2].substring(0,2));
var month = Number(chn[2].substring(2,4));
var year = Number(chn[2].substring(4,8));
console.log("day: " + day)
console.log("month: " + month)
console.log("year: " + year)
var dat= Utilities.formatDate(new Date(year, month - 1, day), "GMT+5:30", "dd-MMMM-yyyy");
ss.getRange("C2").setValue(("Due on " + dat).toString());

Related

Deleting row from google sheets that are older than 30 days but date column is plain text format

I have a Google Sheet that has entries with one of the Columns having a date when it's entered. I want the code to check if a date in Column E is older than 30 days and delete the row.
However, I have column E specifically formatted in plain text under the sheet options. The reason for doing so is I have a different script pull the data from the sheets as JSON and setting the column to plain text makes it show up as a string how I wanted in my JSON.
My code works if I format the column "E" in a date format.
Data is currently added as so "May 11th, 2021" whereas the closest date format in sheets is "May 11, 2021" without the "th" or "rd" after the dates but I would like to keep it how I have it if possible.
The code below works if Column E is formatted in date format but is there a way to get it to work as plain text format option which I currently have it set to?
Made a dummy Google Sheet for visual:
https://docs.google.com/spreadsheets/d/1_156bLL03lFo9NdjE6KmrGiFJvYXkvReel_9znMwT4M/edit?usp=sharing
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("sheet1"); //assumes Sheet 1 is the name of the sheet
var datarange = sheet.getDataRange();
var lastrow = datarange.getLastRow();
var values = datarange.getValues();// get all data in a 2D array
var monthOld = new Date()
monthOld = new Date(monthOld.getTime()-30*3600000*24) //Set date 30 days in past from today
Logger.log(monthOld) // confirm I am getting date 30 days ago
for (i=lastrow;i>=2;i--) {
var tempDate = values[i-1][4];// arrays are 0 indexed so row2 = values[1] and colE = [4]
Logger.log(tempDate)
if (tempDate <= monthOld)
{
sheet.deleteRow(i);
Logger.log(`Row ${i} was deleted`);
} else {
Logger.log(`Nothing was deleted`);
}
}
}
Try
var tempDate = new Date(values[i-1][4].replace(/(th|rd|st|nd)/gm,""));
Using the testbelow function as an intermediate function to pass the appropriate arguments to isOlderThan(). You pass the datestring in ds and the number of days in days. isOlderThan returns true or false based upon todays date.
function testbelow() {
isOlderThan({ds:"Jul 30th, 2021",days:30})
}
function isOlderThan(obj) {
const dA = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug"]
const dt = new Date();
const dtv = new Date(dt.getFullYear(),dt.getMonth(),dt.getDate() - obj.days).valueOf();
let t = obj.ds.split(" ");
let idtv = new Date(t[2],dA.indexOf(t[0]),parseInt(t[1])).valueOf();
Logger.log(idtv < dtv);
return idtv < dtv
}
Mike Steelson provided the line of code I needed to convert the plain text by parsing out the values that didn't apply and converting it to a date.
var tempDate = new Date(values[i-1][4].replace(/(th|rd|st|nd)/gm,""));

Cant format date using apps script how to change a string to a date

I have a sheet with dates along the top. The dates are not all in the same format. I'm in Europe so they are dd/mm/yy normally or dd/mm/yyyy. I put this function into the apps script area
function dateChange() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var column = sheet.getRange("D1:Y1");
column.setNumberFormat("dd/mm/yy");
}
To make everything the same format but none of the values changed, still lots of things show as dd/mm/yyyy. I also tried just highlighting the row and selecting format - then making it dd/mm/yy - still no good.
Commenter below suggested that they might be strings, not dates. How can I test to see if a cells content is a string or a date? If it is a string like 31/03/21 or 31/03/2021 how can I change that into a date please?
Here is a link to a cut down version of the sheet where you can see the mixed "date" formats in the cells: https://docs.google.com/spreadsheets/d/1N0DwwON-7u7Rsqu8tSLYCPfogKCmZBaQHise-vthHII/edit?usp=sharing
I have tried this function as well with the results shown in the comments:
function datestuff() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var lastColumn = sheet.getLastColumn()
for(i = 1; i < lastColumn; i++){
var range = sheet.getRange(1, i);
var data = range.getValue();
Logger.log(data) // results are 20/3/2021, 19/3/21 etc. a mixture of dd/mm/yyyy and dd/mm/yy
dateValue = new Date(data)
Logger.log(dateValue) // results are all Wed Dec 31 19:00:00 GMT-05:00 1969, Wed Dec 31 19:00:00 GMT-05:00 1969
}
}
To check whether a cell contains a numeric date or a text string that just looks like a date, use an =isnumber() formula.
If you are importing the data from a text file or similar to the spreadsheet, set the locale of the spreadsheet so that it matches the data through File > Spreadsheet settings and re-import all data. This should get the dates converted correctly.
If the spreadsheet is your only copy of the data, you can use a formula to convert the text string dates to numeric dates. To best get help with that, please share a publicly editable sample spreadsheet with realistic-looking data.
There doesn't appear to be a simple way to do what I needed to do so I selected the row, formatted to number>plain text, find replaced /21 with /2021 then I ran the following function:
function datestuff() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var lastColumn = sheet.getLastColumn()
for(i = 1; i = lastColumn; i++){
var range = sheet.getRange(1, i);
var data = range.getValue();
if(data != "") {
Logger.log("Cell contents are: " + data)
var dataArray = data.split("/")
Logger.log(dataArray)
var dataDay = dataArray[0]
Logger.log("Day part is " + dataDay)
dataDay = parseInt(dataDay)
var dataMonth = dataArray[1]
Logger.log("month part is " + dataMonth)
dataMonth = parseInt(dataMonth) - 1
var dataYear = dataArray[2]
Logger.log("year part is " + dataYear)
dataYear = parseInt(dataYear)
if(dataYear < 2000) {dataYear = dataYear + 2000}
Logger.log("Day is: " + dataDay + " Month is: " + dataMonth + " Year is: " + dataYear)
dateValue = new Date(dataYear, dataMonth, dataDay)
Logger.log(dateValue)
range.setValue(dateValue)
}
}
}
I'm still shocked there isn't a very simple way to say "is this formatted into a date? if no, do it!"

How to sum up date values to a number (days' sum)?

In Google Sheets I have a list of activities with a start date, and a number that specifies the duration in days of that activity. I need to use Google Apps Script to sum those numbers to the date, to obtain the deadline for the activity.
I've tried the solution posted in this question: Adding Days to a Date - Google Script.
The problem with that solution is that the script editor of the spreadsheet doesn't recognize the "Date" Class, so I can't instantiate a Date element.
Summing directly only takes the date and the number as a string.
Trying the method above results in a #NUM! error in the cell I want to convert.
EDIT:
I've tried this, where V3 holds the date I want to sum:
var fecha= new Date (ss.getSheetByName(camada).getRange("V3").getValue());
var fecha2= new Date();
fecha2.setDate(fecha.getDate() + 1);
ss.getSheetByName(camada).getRange("W3").setValue(fecha2);
It apparently works, but the problem is that V3 holds 5/13/2019 and the date returned is 4/14/2019, so it is a day more (13->14) but it is a month less (5->4).
The answer was in Adding Days to a Date - Google Script.
Three things:
don't define fecha2 as new Date(); this gives it no context and instead returns today's date.
let fecha2 be a variable name
the correct statement is var fecha2 = new Date(fecha.setDate(fecha.getDate() + 1));
function so55593876() {
var ss = SpreadsheetApp.getActiveSheet();
var range = ss.getRange("C3");
var value = range.getValue();
Logger.log("DEBUG: Date Range: "+range.getA1Notation()+", Date value: "+value);//DEBUG
var date = new Date(value); // make the sheet value a date object
Logger.log("DEBUG: new date(value) = "+date);//DEBUG
var dateTime = new Date(date.getTime()+1*3600000*24);
Logger.log("DEBUG: Method 1 (add one day = getTime()+1*3600000*24) = "+dateTime);//DEBUG
var dateDate = new Date(date.setDate(date.getDate()+1));
Logger.log('DEBUG: Method 2 (add one day = getdate()+1) = '+dateDate);//DEBUG
ss.getRange("C4").setValue(dateDate);
Logger.log("<<<<<<<<<<<FETCHA>>>>>>>>>>>>>");
var fecha = new Date(value); // make the sheet value a date object
Logger.log("DEBUG: fecha: new date(value) = "+fecha);//DEBUG
var fecha2= new Date(); // note there are no parameters; this will return TODAY's date
Logger.log("DEBUG: fecha2 = "+fecha2);//DEBUG
var fecha3 = fecha2.setDate(fecha.getDate() + 1);
Logger.log("DEBUG: fecha3 = "+fecha3); //DEBUG
var fecha2 = new Date(fecha.setDate(fecha.getDate() + 1));
Logger.log("DEBUG: fecha2 = "+fecha2); //DEBUG
ss.getRange("C5").setValue(fecha2);
}
I have left all the Logger statements in the code so that you can identify the various values at different states of the script.

Google script -- adding days to a date

I realize this is likely very easy but I'm a struggling newbie. I have dates in spreadsheet cells D3, D4, and D5 (mm/dd/yyyy) and simply need a macro to add 7 days to each of them. I've managed to mangle together some code that may be working but the output is in milliseconds rather than mm/dd/yyyy format.
I can't seem to get the syntax right to convert it. Any hints? Thank you!
function UpdateDates() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var First = new Date();
var Second = new Date();
var Third = new Date();
var First = ss.getRange('D3').getValue();
var Second = ss.getRange('D4').getValue();
var Third = ss.getRange('D5').getValue();
ss.getRange('D3').setValue(First.getTime() + 7);
ss.getRange('D4').setValue(Second.getTime() + 7);
ss.getRange('D5').setValue(Third.getTime() + 7);
}
Adding days to date provides a unique challenge mainly because you have to take care of year, month and date. And increment each accordingly, hence just using getDate() doesn't work. You will need to keep track of the month and year. So as to change them if adding the seven days change the month or the year.
However, by using getTime() you can get the measure of time in milliseconds since Jan 1, 1970. And, add 7 days in milliseconds and convert it back to a date using new Date() constructor. Thus the constructor would take of figuring out the correct date based on the time.
Your code will look like so:
function UpdateDates() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
//Get the dates from the cell and convert them into Milliseconds since 1970/01/01
var First = new Date(ss.getRange('D3').getValue()).getTime();
var Second = new Date(ss.getRange('D4').getValue()).getTime()
var Third = new Date(ss.getRange('D5').getValue()).getTime();
var dayInMs = 24*60*60*1000 //one day in Milliseconds
//add sevendays to each date in milliseconds
First = First + (7*dayInMs)
Second += (7*dayInMs)
Third += (7*dayInMs)
//Convert Milliseconds to date use new Date(time in ms) and set Values of the cell
ss.getRange('D3').setValue(new Date(First));
ss.getRange('D4').setValue(new Date(Second));
ss.getRange('D5').setValue(new Date(Third));
}

Set Value in Date format in first Empty Column : Google Script

I have a column in which dates are saved in string format like this: "Tuesday, 18th November(11:00)"
I want to take this string date and save its equivalent date in Date format corresponding to its row in new column (first empty column in sheet), so that I can later compare that date with current date.
I have written this function and I am in test phase. However I have two questions :
1) This function is not inserting value in corresponding row in new column.
2) Since setValue is Object type it will not save value in Date type, for me setDay, set Month methods are not working (may be because of wrong object).
Here is my code:
function replaceStringDate(e) {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2;
var lastRow = SpreadsheetApp.getActiveSheet().getLastRow();
var lastColumn = SpreadsheetApp.getActiveSheet().getLastColumn();
var dataRange = sheet.getRange(startRow,2,lastRow,12);
var values = dataRange.getValues();
var index = dataRange.getRowIndex();
for(i=0;i<values.length;++i){
var lastCell = sheet.getRange(index,14);
var appointmentDateFirst = values[i][8] ;
if (appointmentDateFirst == "Thursday, 18th November (11:00 to 12:00)") {lastCell.setValue('18/11/2011');}
index=index+1;
} //end for loop
} //end function
here is a piece of code to start with, I played with string manipulation and regex... It's kind of fragile and needs to be improved to handle different cases but the idea is working...
I'm sure it can be done more efficiently with only regex but this string approach was easier...
function convertToDateTest(){
Logger.log(convertToDate("Tuesday, 18th November(11:00)"))
}
function convertToDate(str){
Logger.log(str.substring(str.indexOf(', ')+1,str.indexOf('(')).replace('th','')+' '+new Date().getFullYear());
var date = new Date(str.substring(str.indexOf(', '),str.indexOf('(')).replace('th','')+' '+new Date().getFullYear());
var time = str.match(/((([0-1]?[0-9])|([2][0-3])):)([0-5][0-9])/g);
Logger.log(time);
new Date(date).setHours(time[0]);
return date;
}