Compare ID columns and update Dates if changed - javascript

I have 2 sheets viz., Sht1 & Sht2. I am looping through the ID column in Sht1 and trying to match it with ID column in Sht2. If there is a match, then check if the Date in Sht2 is different than the Date in Sht1. If it is, then update the Date in Sht1 with this new Date.
Sht1:
Sht2:
for e.g.:
From the above screenshots, the Sht1 matching ID's in Sht2 are 10001,10003,10006,10010,10011.
Of these, only 10001,10006,10011 have new Dates. So only for these ID's, these new Dates should get copied to Sht1.
As the Data is large, looping through the ID columns, matching them and then checking if the dates are different and finally updating new dates back to Sht1, is taking a lot of time. Is there an eloquent way to do this without looping and reading/writing to sheet - like picking up the Data in the 2 Sheets as JSON Objects viz., ObjSht1 & ObjSht2, updating the Dates for the matching ID's in ObjSht1, then transferring this JSON Object ObjSht1 to Sht1 in one go?
Edit:
#TheMaster the modified script is :
function myFunction() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sht1 = ss.getSheetByName("Sht1");
const sht2 = ss.getSheetByName("Sht2");
const idMap = sht2.getDataRange().getValues().reduce( (mp,[,id,,date]) => mp.set(id, date), new Map );
console.log(idMap);
const rg1 = sht1.getDataRange();
const values1 = rg1.getValues();
values1.forEach(row => row[2] = idMap.get(row[0]));
rg1.setValues(values1);
}
#TheMaster, This time it replaces the dates in Sht1 with the dates from Sht2 where the ID's match. But it also wipes out the other dates from Sht1 where the ID's do not match.
Also, I think the code is not comparing if dates have changed, but just dumping the dates from Sht2 to Sht1.
See updated Screenshots:

Create a map of {id => date} of the second sheet using reduce
Modify the first sheet values in place using forEach
Sample script:
function datesFromSht2ToSht1() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sht1 = ss.getSheetByName("Sht1");
const sht2 = ss.getSheetByName("Sht2");
const idMap = sht2.getDataRange().getValues().reduce( (mp,[,id,,date]) => mp.set(id, date), new Map );
const rg1 = sht1.getDataRange();
const values1 = rg1.getValues();
values1.forEach(row => row[2] = idMap.get(row[0]) || row[2]);
rg1.setValues(values1);
}

Related

Google Sheets - Delete Row After One Year

I apologise in advance, I'm new at using script with google sheets and after checking for an applicable script for my issue I can't seem to get any of them to work correctly for the sheet I'm working on. Im attempting to replace a paper document that our plant supervisors have for each of their employees. The plant workers have a points based attendance system where infractions drop off one year from the date of infraction.
Ideally the row would delete on its expiration date, thusly removing the points from the employee's total sum. If anyone would care to lend me a hand I would be more than grateful, thanks in advance.
get all values of D1:O13,
check if today > expirDate,
if true, skip the line,
otherwise push the row into result array.
At last, set the results back to the sheet.
function removeExpired() {
const sheet = SpreadsheetApp.getActiveSheet();
const range = sheet.getRange("D1:O13");
const values = range.getValues();
const hearders = values.shift();
const today = new Date().setHours(0,0,0,0);
const results = [hearders];
for (const row of values) {
const expireDate = new Date(row[2]).setHours(0,0,0,0);
const expired = today > expireDate;
if (expired) continue;
results.push(row);
}
range.clear();
sheet.getRange(1,1,results.length,results[0].length).setValues(results);
}

Apps script.. i dont know how do i make Copy sheet`s Specific name

enter image description here
IF I PUSH THE BUTTON .
I WANT TO KNOW HOW CREATE NEW SHEET(COPY SHEET) NAMED NEXT + 1 DAY AND
THE CELL "C24" CONTENTS CHANGE TOO ?
BASIC SHEET NAME IS : 04/18/2022
I PUSH THE =BUTTON
NEW CREATE SHEET (ALL CONTENTS ARE COPY, BUT THE CELL "C24" DATE + 1 DAY
NEW CREATED SHEET`S NAME : 04/19/2022
This code help you to get the latest date form all sheet names and create a new name which is 1 day after the found sheet name.
// get all the sheet names of a spreadsheet and turn them into numbers, if the sheet name cannot be parsed into an int, make it a 0.
const sheetNames = SpreadsheetApp.getActiveSpreadsheet().getSheets()
.map(sheet => {
const name = parseInt(sheet.getName());
return isNaN(name) ? 0 : name;
});
// find the biggest numbers of all sheet names.
const maxDate = Math.max(...sheetNames)+'';
// create a date object with the found number.
const maxDateObj = new Date(`${maxDate.slice(0,4)}-${maxDate.slice(4,6)}-${maxDate.slice(6,8)}`);
// add 1 day on it.
const nextDateArr = JSON.stringify(new Date(maxDateObj.setDate(maxDateObj.getDate() + 1))).split(/"|-|T/g);
// format the date object into your sheet name format.
const nextDate = [nextDateArr[1],nextDateArr[2],nextDateArr[3]].join('');
console.log(nextDate);

how do i filter by date using google script?

I need to filter my spreadsheet based on today's date.
this is the code I used:
function myFunction() {
var SS = SpreadsheetApp.openById("19nlPw9jF8FCFwY-qYwdBILoGDazrH12c8BgYfhwWSKA");
var Sheet = SS.getSheetByName("All Joiners");
var Jun = SS.getSheetByName("01 Jun");
var data = Sheet.getRange(2, 1,Sheet.getLastRow(),Sheet.getLastColumn()).getValues();
var criteria = SpreadsheetApp.FilterCriteriaBuilder.whenDateEqualTo(new Date(Jun.getRange("A1")))
.build();
spreadsheet.getActiveSheet().getFilter().setColumnFilterCriteria(4, criteria);
}
A few things -
Your code retrieves the range of cell A1 on Jun - You also need
to get the value.
FilterCriteriaBuilder is not a function and
should be newFilterCriteria().
spreadsheet.getActiveSheet() should
be SS.getActiveSheet since you declared it as SS
Original Code:
var criteria = SpreadsheetApp.FilterCriteriaBuilder.whenDateEqualTo(new Date(Jun.getRange("A1"))).build();
spreadsheet.getActiveSheet().getFilter().setColumnFilterCriteria(4, criteria);
Should be:
let criteria = SpreadsheetApp.newFilterCriteria().whenDateEqualTo(new Date(Jun.getRange("A1").getValue())).build();
SS.getActiveSheet().getFilter().setColumnFilterCriteria(4, criteria);
Also, side note - you declared Sheet but didn't use it. If your intention was to update the column filter on that specific sheet and not the currently active sheet, then instead of SS.getActiveSheet(), it should be:
Sheet.getFilter().setColumnFilterCriteria(4, criteria);
If your sheet doesn't currently have a filter, you have to create it. In order to do that, retrieve the Range you want to apply the filter to and then call Range.createFilter(). So that line would be something like (Range being your desired range):
Range.createFilter().setColumnFilterCriteria(4, criteria);
Also, if your A1 cell is a Date (and not a string formatted like a Date) there's no need to use new Date() when setting the criteria:
const criteria = SpreadsheetApp.newFilterCriteria().whenDateEqualTo(Jun.getRange("A1").getValue()).build();

Google Sheets Calendar

I would like some help in pulling certain data from a google form linked to a spreadsheet and set a certain value in the date of a certain employee. For example if he/she marked as Vacation Leave then the letter V will be marked under the Date. I have attached the link to my calendar to give an example, I have tried searching the net and this is my second time posting here.
I started the Code but I am stuck in actually finding the Cell for a certain date and inserting the letter.
https://docs.google.com/spreadsheets/d/1uFTR2_B7T0QBr7fTflByFffmmiszbNj_RaCvLEfYRCA/edit?usp=sharing
function setData(){
//Spreadsheets
var ss = SpreadsheetApp;
var data = ss.getActiveSpreadsheet().getSheetByName("Data");
var calendar = ss.getActiveSpreadsheet().getSheetByName("Calendar");
//Get last row / Individual Cells from Form
var lRow = data.getLastRow();
var lRowData = data.getRange(lRow,1,1,17).getValues();
var approval = data.getRange(lRow,17,1,1).getValue();
var leave = data.getRange(lRow,9,1,1).getValue();
var agentName = data.getRange(lRow, 5,1,1).getValue();
var dateBefore = data.getRange(lRow, 10,1,1).getValue();
var dateAfter = data.getRange(lRow, 11,1,1).getValue();
//Calander Variable Arrays
var allDates = calendar.getRange("LA1:NJ1").getValues();
var allNames = calendar.getRange("A4:A160").getValues();
for(var i = 0; i<allNames.length; i++){
if (approval === "Approved" && allNames[i][0] === agentName){
//Here I need it to insert the dates under the correct name and date with a value of V H S M U T.
};
};
};
You are building a spreadsheet-based Leave Calendar based on information from a form response. Based on your existing Calendar, you are having problems identifying the relevant leave dates, and then filling calendar cells to indicate proposed leave.
The problem is there are no fields in rows 1,2 or 3 of Calendar that have the same date format as the Start Date and End Date fields on Form. As a result, there's no easy way to search for a match of the form data fields.
The solution, in my view, is to change the format of the date fields in rows 2 and 3 and enable a search to be match.
Row 2
the existing format is "d" - day of the month (Numeric)
change the format to match the Form Start/End dates: "d-MMM-yyyy".
the font colour for this field can be used to "hide" these dates, and the column width reduced also.
Row 3
the existing format is "E" - day of the week (Name)
change the format to combine the existing formats of rows #2 and #3 - "E-d"
Aspects of the script
the form data is retrieved as getDisplayValues(). The purpose of this is to get the date as a string to facilitate the search.
Two sets of Calendar data are obtained
1) the dates row (Row#2)
2) the names column (Col #1). The Javascript map method is used to convert names from a 2D array to a 1D array. This creates an array that can be easily searched.
the Javascript indexOf method is used to find the Column match for the start and end dates, and to match the name in the Calendar Column (which yields the Row)
the script loops through the number of days leave to create a temporary array of "V" values.
using the row number and the start and end column numbers, a range can be defined on calendar and then updated from the values in the temporary array.
Presumably your function would be triggered by onFormSubmit(e).
Form data
Calendar - Before
Calendar - After
function so5871726503(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var form = ss.getSheetByName("Form");
var calendar = ss.getSheetByName("Calander");
//get form data
var formdataRange = form.getRange(6,1,1,9);// test data
var formData = formdataRange.getDisplayValues(); // display values to format date as string
//get the employee name, start date and end date
var formName = formData[0][1];
var formSD = formData[0][3];
var formED = formData[0][4];
// Logger.log("DEBUG: name = "+formName+", start date = "+formSD+", end date = "+formED);
//get Calendar variables
var calLR = calendar.getLastRow();
var calLC = calendar.getLastColumn();
var caldateStart = 9;
var calnameStart=4;
// get Calendar dates
var calDateRange = calendar.getRange(2,caldateStart,1,calLC-caldateStart+1);
var calDateValues = calDateRange.getDisplayValues();
// get Calendar names
var calNameRange = calendar.getRange(calnameStart,1,calLR-calnameStart+1);
var calNameValues = calNameRange.getValues();
var calNames = calNameValues.map(function(e){return e[0];});//[[e],[e],[e]]=>[e,e,e]
// there should be some error checking on indexof results = -1 in case there is a mismatch.
// find form start date in calender
var startdateresult = calDateValues[0].indexOf(formSD);
var startdateresultcol = startdateresult+caldateStart;
// Logger.log("DEBUG: start date result = "+startdateresult+", column = "+startdateresultcol);
// find form end date in calender
var enddateresult = calDateValues[0].indexOf(formED);
var enddateresultcol = enddateresult+caldateStart;
// Logger.log("DEBUG: end date result = "+enddateresult+", column = "+enddateresultcol);
// find form name in calender
var nameresult = calNames.indexOf(formName);
var nameresultrow = nameresult+calnameStart;
// Logger.log("DEBUG: name result = "+nameresult+", row = "+nameresultrow)
// calculate number of days leave
var daysleave = enddateresultcol-startdateresultcol+1
// Logger.log("DEBUG: days leave = "+daysleave)
// create array variable to hold leave data
var leave=[];
// loop to create data to fill Calendar
for (i=0;i<daysleave;i++){
leave.push("V");
}
// Logger.log(leave); // DEBUG
// build leave range
var calLeave = calendar.getRange(nameresultrow,startdateresultcol,1,daysleave);
//Logger.log(calLeave.getA1Notation()); //DEBUG
// Update the leave range
calLeave.setValues([leave]);
}

Google Spreadsheet + Apps: Get max value of column, it gives me date format

I'm trying to use HTML and JS to write into a Spreadsheet and I found some useful code to do that. I had to add a column to insert an ID for each entry and I did it like this:
var sheet = SpreadsheetApp.openById("myKey").getSheetByName('Richieste');
var column = 1;
var colArray = sheet.getRange(2, column, sheet.getLastRow()).getValues();
var maxi = Math.max.apply(Math, colArray);
var id = maxi+1;
// set other params
var vals = [id, date, name, surname, serial, eMail, area, text, ans, flag];
var sheetObj = sheet.appendRow(vals);
Now, if I have an empty sheet, it works for the first two entries: the third ID is set such as 02/01/1900 0.00.00 and you can see a screenshot here.
I cannot understand what's going on... do you know something about this?
Thanks a lot for your help!
S.
It is hard to tell from the information you provided, but it looks like your cell format is set to date time, not a number.

Categories