Comparing Dates Formated with: "Utilities.formatDate()" in Google script - javascript

I have searched many of the date questions on here, but I am still stumped:
for (nn=3;nn<datacommit.length;++nn){
var duedate1 = datacommit[nn][4]
var duedate = Utilities.formatDate(duedate1,'GMT+0200','yyyy:MM:dd');
var sevendaysfromnow1 = datacommit[nn][9]
var sevendaysfromnow = Utilities.formatDate(sevendaysfromnow1,'GMT+0200','yyyy:MM:dd');
if (+duedate==+sevendaysfromnow) { do my thing}};
Does not find a match when the same date is in those two separate columns. What am I doing wrong?

Related

nodejs turn string into array to upload to google sheets

Main Goals
Retrieve string from google sheets tab.
Edit string to remove "s and ,s.
re-format the string for upload into google sheets.
I have accomplished the first 2 tasks of my goal. Although I will explain in full the situation.
I am querying google sheets to return a row which contains a specified string so it can be added to a new sheet. currently I have been able to retrieve the row fine. the data comes back looking like this.
"12/24/2020, 3:40:33 PM","SanguineDepths+5","The Key Is
Timed","1000","Aegwynn","#name #name #name #[Manager]
name-name","name#0000 name#0000 name#0000
name#0000","Advertiser-Realm","testing-testing","Ticket","33p2bdlfto9g45","Customer-Realm","Horde",""
I have then used the following code to remove all of the "s and ,s.
const result = `"12/24/2020, 3:40:33 PM","SanguineDepths+5","The Key Is Timed","1000","Aegwynn","#name #name #name #[Manager] name-name ","name#0000 name#0000 name#0000 name#0000","Advertiser-Realm","testing-testing","Ticket","33p2bdlfto9g45","Customer-Realm","Horde",""`
var result1 = result.replace (/,/g, " ");
var result2 = result1.replace (/"/g, "");
Now my string is looking like this.
12/24/2020 3:40:33 PM SanguineDepths+5 Timed 1000 Aegwynn #name #name
#name #[Manager] name-name name#0000 name#0000 name#0000
name#0000 Advertiser-Realm testing-testing Ticket 33p2bdlfto9g45
Customer-Realm Horde
When uploading the above string which removes the characters I do not require, google sheets actually inputs all of the data in one cell instead of multiple, is there a way I can fix this? I did try to use arguments although I would like the 4 discord name#0000 in one cell and the 4 discord #name also in their own cell, like this.
Desired format for data to be entered in
So my main goal is to format the result in such a way I can write them to google sheets in their own cells.
Edit #1
I have used the .split(',') function but google API returns the following error:
"The API returned an error: Error: Invalid values[1][0]: list_value"
You could try to target the comma's in between to split the data at that point to an array and then take care of removing charcters.
Try:
result.split(',')
That should give you an Array.
And you could resuse your code to take out the characters you don't need with an array helper: something like:
result.split(',').map((part) => {
return part.replace (/"/g, "")
})
I was hoping for an easier solution, but I ended up using this method with multiple arguments for the string I got back from the sheet.
var result1 = result.replace (/,/g, " ");
var result2 = result1.replace (/"/g, "");
const argsRUN = result2.split(' ');
const command = argsRUN.shift().toLowerCase();
var date1 = (argsRUN[0]);
var time1 = (argsRUN[1]);
var ampm = (argsRUN[2]);
var dungeonkey = (argsRUN[3]);
var timedornot = (argsRUN[4]);
var costofboost = (argsRUN[5]);
var paymentrealm1 = (argsRUN[6]);
var boost1ID = (argsRUN[7]);
var boost2ID = (argsRUN[8]);
var boost3ID = (argsRUN[9]);
var boost4ID = (argsRUN[10]);
var boost1tag = (argsRUN[11]);
var boost2tag = (argsRUN[12]);
var boost3tag = (argsRUN[13]);
var boost4tag = (argsRUN[14]);
var advertiserrealm = (argsRUN[15]);
var commentup = (argsRUN[16]);
var ticketornot = (argsRUN[17]);
var uniquerunid = (argsRUN[18]);
var customerrealm = (argsRUN[19]);
var customerfaction = (argsRUN[20]);

Cannot Read Property 'getSheetId' of null; Not sure why this happens

I have a the following snippet of code
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var driverArray = sheet.getRange("H2:H33").getValues().flat().filter(r=>r!="");
var ssname = ss.getName();
var length = ssname.length;
var shName = sheet.getName();
var date = ssname.substring(0,length-15);
var scheduleDate = ss.getSheets()[7].getRange("G27").getValue(); //this contains a formula, but it evaluates to a date coinciding with the title of a sheet
const body = "Hello, <br><br>Attached is the pay stub for the week ending "+ date+"."+"<br><br> Thank you, <br> Elizabeth";
var arrayLength = driverArray.length;
var scheduleSheet = SpreadsheetApp.openById("SpreadsheetURL");
var scheduleSS = scheduleSheet.getId();
var nextSchedule = scheduleSheet.getSheetByName(scheduleDate);
var scheduleID = nextSchedule.getSheetId(); // I believe the error is coming here
I am trying to get the ID of a sheet on a different spreadsheet. I believe that I am navigating to that sheet correctly, but I get the error "cannot read property of 'getSheetId' of null". Does this mean that it did not find a sheet with the name?
G27 contains the formula
=(Leftb(Summary!$A$2,2)&"-"&Midb(Summary!$A$2,3,2)&"-"&rightb(Summary!$A$2,2))+7
but it evaluates to a date. And the format of the date matches correctly with the title of the sheet.
Instead of
var scheduleDate = ss.getSheets()[7].getRange("G27").getValue()
use
var scheduleDate = ss.getSheets()[7].getRange("G27").getDisplayValue()
The above because getValue() returns a Date object for cells holding a date value and usually the Date object is parsed as string in a long format rather than the usual date formats.

A string of form nnnn-nnnn is displayed in a spreadsheet as a date or otherwise incorrectly

I have a script I have been using in my test environment to programmically create a tracking number by parsing the year from timestamp and padding the response index.
function setTrackingNumber(ss, lastRowInx, createDateColumn) //This block generates and stores a tracking number in Column AU on the backend
{
var padTrackNo = "" + lastRowInx;
var trackSize = 4;
var trackingNumberColumn = createDateColumn-3; //trackingNumberColumn is currently in AU (Column 47) Calculating using it's relative position to createDateColumn Position
if (ss.getRange(lastRowInx, trackingNumberColumn).getValue() == "") // so that subsequent edits to Google Form don't overwrite original tracking number
{
if (padTrackNo > trackSize)
{
var padTrackNo = pad(padTrackNo, trackSize);
}
else {} //do nothing
var shortYear = setShortYear(ss, lastRowInx, createDateColumn);
var trackingNumber = shortYear + "-" + padTrackNo;
var createTrackingNumber = ss.getRange(lastRowInx, trackingNumberColumn);
createTrackingNumber.setValue(trackingNumber);
}
else {} //should do nothing
return;
}//This is the end of the setTrackingNumber function
function setShortYear(ss, lastRowInx, createDateColumn)
{
var newCreateDate = ss.getRange(lastRowInx,createDateColumn).getValue();
var strDate = "" + newCreateDate;
var splitDate = strDate.split(" ");
var trimYear = splitDate[3];
var shortYear = trimYear;
return shortYear;
}//This is the end of the shortYear function
function pad(padTrackNo, trackSize)
{
while (padTrackNo.length < trackSize)
{
padTrackNo = "0"+padTrackNo;
}
return padTrackNo;
}//This is the end of pad function
That gets me test result which is as expected ex. 2016-0005. However when we added it to another production sheet it seemed to work with test data and then production data showed up like a date 3/1/2016. production result - first cell.
I thought it must just be formatting the string as a date because of the numbers so I tried formatted the column as plain text but that just changed the date to a plain text version of the date.
I thought this might be similar to needing to specify the format like I did in this question Appending initial timestamp from Google Form to end of record in order to permanently store create date onFormSubmit at #SandyGood 's suggestion so I tried setting the number format as [0000-0000] by changing
createTrackingNumber.setValue(trackingNumber);
to
createTrackingNumber.setValue(trackingNumber).setNumberFormat("0000-0000");
which resulted in the [production result - second cell] which again doesn't match the expected result.
Oddly, some submissions seem to work just fine like [production result - third cell]. Over the past 3 days and approximately 10 records it has been fine, then hinky, then fine, they hinky, then fine again. I am not really sure what else to try to debug this odd behaviour.
Note: I had to parse the date as a string as I was having trouble getting it to parse the date correctly from the create date which is taken from initial timestamp.
To my understanding, "2016-0005" is not a number but a string, so the cell containing it should be formatted as plain text. With a script, this can be done by
range.setNumberFormat('#STRING#')
(source), and this must be done before you set the value to the cell. Like this:
createTrackingNumber.setNumberFormat('#STRING#').setValue(trackingNumber);

Adding to a Google Doc from a Google Spreadsheet Using Apps Script

I'm new to using the DocumentApp in Google Apps, so looking for some help!
I'm trying to create an FAQ (in a Google Doc) automatically from a spreadsheet. If certain conditions are met in the spreadsheet row, I want the script to find the category of the question in the document and insert a new question and response underneath it (pushing anything already there back).
So I'd have a document that looks like this:
https://docs.google.com/document/d/1fjb3RO6hUY6n7x0bu6WvtcleMWRNC8VQ9U82hXiGqcY/edit?usp=sharing
And a spreadsheet that looks like this:
https://docs.google.com/spreadsheets/d/1fb3ceqP6142_C7QQ1PfkWtVNswOyzOxkWCofvauf4Ps/edit?usp=sharing
And this is the code I'm trying to use. I'm getting a ton of errors- mainly because I don't have a good grasp on what the different elements involved are. Can anyone point me in the right direction?
function insertnewquestion() {
//(works fine)Get active document and related spreadsheet
var doc = DocumentApp.getActiveDocument().getBody();
var ss = SpreadsheetApp.openById("xxxxxxx");
var sheet = ss.getSheetByName("xxxxx");
//(works fine)Go through the various rows in the spreadsheet up to the last row
for (var row = 2; row <= sheet.getLastRow(); ++row) {
var status = sheet.getRange(row,4).getValue();
var question = sheet.getRange(row,1).getValue();
var response = sheet.getRange(row,2).getValue();
var category = sheet.getRange(row,3).getValue();
var date = sheet.getRange(row,5).getValue();
//(works fine)find rows with blank status and a response filled in
if (status !== "Entered" && response !== "") {
//(errors! this is where i need help) find the pertinent header
var categoryposition = body.findText(category); //looking for the category header- new text should be added after this, the idea is that what was already under this header will move down
var questionheader = categoryposition.appendText(question); //trying here to add in question text after where the category was found
questionheader.setHeading(DocumentApp.ParagraphHeading.HEADING3); //set question text as heading 3 (so it shows up on table of contents)
questionheader.appendText("\r"+"\r"+response+"\r\r"); //add line breaks and then the response text in normal font, then more line breaks to put space between new stuff and old stuff
//(works fine)Mark in the spreadsheet that it was entered in FAQ and the date so that it isn't double entered next time the script runs
sheet.getRange(row,4).setValue("Entered");
var currentTime = new Date()
var month = currentTime.getMonth() + 1
var day = currentTime.getDate()
var year = currentTime.getFullYear()
var date = (month + "/" + day + "/" + year)
sheet.getRange(row,5).setValue(date);
}
else {continue}
}
//(need help!) Refresh table of contents to include new questions
//no idea how to do this!
}
In the code you are referring to body.findText(category); where it should be doc.findText(category);. Also for the line:
var categoryposition = body.findText(category);
it returns the RangeElement — a search result indicating the position of the search text, or null if there is no match
Before adding any lines of code you have to check for null value in categoryposition.
The text class has a method to insert text in particular offset value to particular String value gives as shown here.
Hope that is helpful.

Multiple RegExp in single function

This is not exactly a problem, but more a question of method.
I am working on a project where people are able to type shorthand dates in input field, for example if you simply type "20", the input will automatically display the full date for 20th of this month.
There are many shorthand types possible, so I had to make multiple RegExp and then check each and every one.
My question is, is there a better way to deal with this? I am no javaScript expert,but I have a feeling that this is not exacty "best practise".
Here is the function
function dateParser(date) {
var splitDate = date.split(/[.:\s]/);
var day = new RegExp(/\b\d{1,2}\b/);
var dateHour = new RegExp(/\b\d{1,2}\s\d{1,2}\b/);
var dateHourMin = new RegExp(/\b\d{1,2}\s\d{1,2}[:]\d{1,2}\b/);
var dateMonth = new RegExp(/\b\d{1,2}[\/\-\,\.]\d{1,2}\b/);
var dateMonthHour = new RegExp(/\b\d{1,2}[\/\-\,\.]\d{1,2}\s\d{1,2}\b/);
var dateMonthHourMin = new RegExp(/\b\d{1,2}[\/\-\,\.]\d{1,2}\s\d{1,2}[:]\d{1,2}\b/);
var dateMonthYear = new RegExp(/\b\d{1,2}[\/\-\,\.]\d{1,2}[\/\-\,\.]\d{1,4}\b/);
var dateMonthYearHour = new RegExp(/\b\d{1,2}[\/\-\,\.]\d{1,2}[\/\-\,\.]\d{1,4}\s\d{1,2}\b/);
var dateMonthYearHourMin = new RegExp(/\b\d{1,2}[\/\-\,\.]\d{1,2}[\/\-\,\.]\d{1,4}\s\d{1,2}[:]\d{1,2}\b/);
var month = new Date().getMonth() + 1;
var year = new Date().getFullYear();
var newDate;
if(dateMonthYearHourMin.test(date)) {
newDate = splitDate[0]+"."+splitDate[1]+"."+splitDate[2]+" "+splitDate[3]+":"+splitDate[4];
}
else if(dateMonthYearHour.test(date)) {
newDate = splitDate[0]+"."+splitDate[1]+"."+splitDate[2]+" "+splitDate[3]+":00";
}
else if(dateMonthYear.test(date)) {
newDate = splitDate[0]+"."+splitDate[1]+"."+splitDate[2]+" 12:00";
}
else if(dateMonthHourMin.test(date)) {
newDate = splitDate[0]+"."+splitDate[1]+"."+year+" "+splitDate[2]+":"+splitDate[3];
}
else if(dateMonthHour.test(date)) {
newDate = splitDate[0]+"."+splitDate[1]+"."+year+" "+splitDate[2]+":00";
}
else if(dateMonth.test(date)) {
newDate = splitDate[0]+"."+splitDate[1]+"."+year+" 12:00";
}
else if(dateHourMin.test(date)) {
newDate = splitDate[0]+"."+month+"."+year+" "+splitDate[1]+":"+splitDate[2];
}
else if(dateHour.test(date)) {
newDate = splitDate[0]+"."+month+"."+year+" "+splitDate[1]+":00";
}
else if(day.test(date)) {
newDate = splitDate[0]+"."+month+"."+year+" 12:00";
}
return newDate;
}
I believe you can consolidate some of your regular expressions and make this more compact.
The first thing I notice is that whitespace appears to be an important separator in your input strings. Specifically, the date (or day) is always separated from the hour/minute with a space. So the first thing I would do is split your input on a space:
var parts = date.split( /\s/ );
var datePart = parts[0];
var timePart = parts[1]; // could be undefined
Now we can process the date part and the time part (if it exists) separately. The components of your date part are always separated by a slash, a dash, a comma, or a period, so again we can just split it:
parts = datePart.split( /[\/\-\,\.]/ );
var day = parts[0];
var month = parts[1] // could be undefined
var year = parts[2]; // could be undefined
You can split the time similarly, since hours and minutes are always separated by a colon:
if( timePart ) {
parts = timePart.split( /:/ );
var hour = parts[0];
var minute = parts[1]; // could be undefined
}
This should make this a little more compact and easy to read and maintain. You could go even more compact with a singular regular expression with groups, but I feel that this approach would be better.
The problem you described is tackled by Natural Language Processing, Programming/Query Language Design fields.
One of the approaches for solving those kind of problems is manually written scanner using RegExp/other string scanning and working with the result the way you did. It works for simple languages, doesn't require much knowledge in language design department and usually is intuitive to modify.
If you however have feeling that input is going to grow to something more complicated I recommend replacing RegExp scanning with full-fledged parser/lexer using for example Jison "Your friendly JavaScript parser generator!" or anything else that suits you.

Categories

Resources