Method search on google sheet data from one column using google script? - javascript

I had tried to search data like below flow picture and script to search data from google sheet using google app script but the script using is not working properly but can someone tell me how to setup search function to find data like flow on image? thanx
[Flow searching data][1]
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var menuEntries = [ {name: "Search", functionName: "searchRecord"} ];
ss.addMenu("Commands", menuEntries);
}
function searchRecord()
{
var ss = SpreadsheetApp.getActiveSpreadsheet()
var wsSearchingData = ss.getSheetByName("Searching Data")
var wsDatabase = ss.getSheetByName("Database")
var searchString = wsSearchingData.getRange("E4").getValue();
var column =1; //column Index
var columnValues = wsDatabase.getRange(2, column, wsDatabase.getLastRow()).getValues(); //1st is header row
var searchResult = columnValues.findIndex(searchString); //Row Index - 2
var searchValue = wsDatabase.getRange("B2:B2041").getValues()
var matchingDatabase = searchValue.map(searchColumn => {
var matchColumn = columnValues.find(r => r[0] == searchColumn[0])
return matchColumn = matchColumn ? [matchColumn[2]] : null
})
console.log(matchingDatabase)
if(searchResult != -1)
{
//searchResult + 2 is row index.
SpreadsheetApp.getActiveSpreadsheet().setActiveRange(sheet.getRange(searchResult + 1, 1))
}
Array.prototype.findIndex = function(search){
if(search == "") return false;
for (var i=0; i<this.length; i++)
if (this[i] == search) return i;
wsSearchingData.getRange("B11").setValue(search[0]);
wsSearchingData.getRange("C11").setValue(search[1]);
wsSearchingData.getRange("D11").setValue(search[2]);
wsSearchingData.getRange("E11").setValue(search[3]);
wsSearchingData.getRange("F11").setValue(search[4]);
return;
}
}
[1]: https://i.stack.imgur.com/HF9K8.png

var searchResult = columnValues.findIndex(searchString); //Row Index - 2
replace the above code with:
var searchResult = columnValues.filter(r=>r[1]==searchString)
You can then put searchResult directly as output in the sheet. Make sure that [1] in the above contains the column index of Name in the columnValues Array.

Related

GAS Function not setting value as intended in sheet

This is the Google Sheet, it can be copied: https://docs.google.com/spreadsheets/d/1ffIRGiGkiy5WFzSAvWNOY_3cqNXgTAOtO6o8vxS-BFU/edit?usp=sharing
The Function 'AddNewMembers' does not function, even if "isAdded == "No" it will not setValue(recruit_id)
function AddNewMembers(event){
event = {range: SpreadsheetApp.getActiveRange()}
CheckHandleSteamIDNotation(event)
SpreadsheetApp.flush();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var recruitment_log = ss.getSheetByName('RL1');
var main_roster = ss.getSheetByName('Main Roster');
var isAdded = recruitment_log.getRange('R3').getValue();
if(isAdded == "No") {
var recruit_id = "'" + recruitment_log.getRange('J3').getValue();
main_roster.getRange('I100').setValue(recruit_id);
}
}
function CheckHandleSteamIDNotation(event)
{
let formSheet = SpreadsheetApp.getActiveSheet();
let header = formSheet.getRange(1,1,1,formSheet.getMaxColumns()).getValues();
let formRange = formSheet.getRange(formSheet.getLastRow(), 1, 1, formSheet.getMaxColumns());
let formValues = formRange.getValues();
for(let i = 0; i < header[0].length; i++)
{
if(header[0][i].includes("SteamID"))
{
formValues[0][i] = "'" + formValues[0][i];
}
}
formRange.setValues(formValues);
}
Since the provided script above contains var isAdded = recruitment_log.getRange('R3').getValue(); the value of R3 is currently set to "Yes" that is why the condition for the script below is not running.
if(isAdded == "No") {
var recruit_id = "'" + recruitment_log.getRange('J3').getValue();
main_roster.getRange('I100').setValue(recruit_id);
}
Try this modification:
function AddNewMembers(event) {
event = { range: SpreadsheetApp.getActiveRange() }
CheckHandleSteamIDNotation(event)
SpreadsheetApp.flush();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var recruitment_log = ss.getSheetByName('RL1');
var main_roster = ss.getSheetByName('Main Roster');
//Gets all the data values on recruitment_log
var isAdded = recruitment_log.getRange(3, 1, recruitment_log.getLastRow(), recruitment_log.getLastColumn()).getValues();
//Gets the last row starting I17
var lastrow = main_roster.getRange(17, 9, main_roster.getLastRow() , 1).getValues().filter((x => x > 1)).length
//Sets the value on the last blank row
isAdded.map(x => x[17].toString().toLocaleLowerCase() == "no" ? "'" + main_roster.getRange(17 + lastrow,9).setValue(x[9]) : x)
}
I made modifications on your isAdded variable to the following to get the entire range of data on RL1 sheet.
var isAdded = recruitment_log.getRange(3, 1, recruitment_log.getLastRow(), recruitment_log.getLastColumn()).getValues();
This part of script was only used to get the current length of data for the New Operatives. Using .filter() method to filter out empty array elements, since getValues() gets blank cells if there is formatting applied on the spreadsheet.
var lastrow = main_roster.getRange(17, 9, main_roster.getLastRow() , 1).getValues().filter((x => x > 1)).length
Using ES6 .map() method to create a new array for the data that hasn't been added to the main roster sheet file.
isAdded.map(x => x[17].toString().toLocaleLowerCase() == "no" ? "'" + main_roster.getRange(17 + lastrow,9).setValue(x[9]) : x)
Screenshot:
Reference:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter#description

How to compare a value with each item of range

for the last 3 days (my first 3 days of coding) i've been trying to code an script to get my google contacts that have certain keyword, it being "Catamarca", on their name and also to delete that keyword after they've been added to the spreadsheet leaving only their name.
I've been succesfull in all of this. But now i want to only run the script on an existing database, and only run it if the new contacts are not on the sheet already, and not write over the existing ones.
Here is my code so far:
function impContacts() {
// variables
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("GContacts");
var grupo = ContactsApp.getContactGroupById("http://www.google.com/m8/feeds/groups/email#gmail.com/base/6")
const contactos = grupo.getContacts();
const arraycontacts = [];
// get the last row on B with data on it
const lastRow = sheet.getLastRow();
const Avals = sheet.getRange("B2:B" + lastRow).getValues();
const Alast = lastRow - Avals.reverse().findIndex(c => c[0] != '');
Logger.log(Alast);
var rangeInteres = sheet.getRange(2, 1, Alast, sheet.getLastColumn()).getValues();
// look for contacts that has in their name the word "Catamarca", and save them with their id, name and phone.
contactos.forEach(contacto => {
var phone = ""
if (contacto.getPhones()[0]) {
phone = contacto.getPhones()[0].getPhoneNumber()
};
var name = ""
if (contacto.getFullName().match("Catamarca")){
name = contacto.getFullName();
};
var idcont = ""
if (name == rangeInteres.forEach(namme =>
{
oldName = namme[1];
Logger.log(oldName);}))
{
idcont =
rangeInteres.forEach(id => {
oldId= id[0];
Logger.log(oldId);})
}
else
{
idcont = contacto.getId().replace(/\D/g, '')
};
const datoscont = [idcont, name, phone];
arraycontacts.push(datoscont);
})
// save new contact
sheet.getRange(2, 1, arraycontacts.length, 3).setValues(arraycontacts);
// look for "catamarca"
range = sheet.getRange("B2:B")
var textFind = range.createTextFinder("Catamarca");
textFind.matchEntireCell(false);
textFind.ignoreDiacritics(true);
textFind.matchCase(false);
var textFound = textFind.findNext();
// Si encuentra coincidencia reemplazar por ""
if (textFound !== null) {
var vals = textFound.getValues();
textFind.replaceAllWith("");
}
}
What i need to keep the most is the ID of the existing contacts (the IDs are different from the ones coming from google contacts but the names are the same), because they are linked to an app created using AppSheet.
I believe there should be a way to accomplish this by editing this part of the code
var idcont = ""
if (name == rangeInteres.forEach(namme =>
{
oldName = namme[1];
Logger.log(oldName);}))
{
idcont =
rangeInteres.forEach(id => {
oldId= id[0];
Logger.log(oldId);})
}
else
{
idcont = contacto.getId().replace(/\D/g, '')
};
In my head and with my current knowledge, the code should be working, but it's not, I mean, it runs, but overwrites everything.

Log changes on Google Script (Google Spreadsheets)

I'm looking to create a spreadsheet where it logs data and the changes you make on it.
For example in sheet, I used a Google Script to do it but instead of only logging in a particular row when you change the data on Sheet1, it copies all the data you changed since the beginning on Sheet 2. I only want to log a particular row each time I make a change.
Here's my code
* Retrieves all the rows in the active spreadsheet that contain Yes
* in the Include column and copies them to the Report sheet.
*/
function myFunction() {
var sSheet = SpreadsheetApp.getActiveSpreadsheet();
var srcSheet = sSheet.getSheetByName("Sheet1");
var tarSheet = sSheet.getSheetByName("Sheet2");
var lastRow = srcSheet.getLastRow();
for (var i = 2; i <= lastRow; i++) {
var cell = srcSheet.getRange("B" + i);
var val = cell.getValue();
if (val == 'Yes') {
var srcRange = srcSheet.getRange("A" + i + ":D" + i);
var tarRow = tarSheet.getLastRow();
tarSheet.insertRowAfter(tarRow);
var tarRange = tarSheet.getRange("A" + (tarRow+1) + ":D" + (tarRow+1));
srcRange.copyTo(tarRange);
}
}
};
Can anyone please help?
Use onEdit(e)
function onEdit(e) {
var srcSheet = e.source.getActiveSheet();
if (srcSheet.getSheetName() !== 'Sheet1') { return; }
var row = e.range.rowStart;
var cols = 4;
var srcRange = srcSheet.getRange(row, 1, 1, cols);
var values = srcRange.getValues()[0];
if (values[1] == 'Yes') {
var tarSheet = e.source.getSheetByName('Sheet2');
tarSheet.appendRow(values);
}
}

How to add a color stripe to every last row of a student attendance sheet using Google App Scripts?

As part of a student attendance system, I would like to add a color stripe to every last row of a class for attendance using App Scripts. My columns of Google Sheets are: (i) Date, (ii) Email, (iii) Latitude, (iv) Longitude, and (v) Subject-code. Tried many ways but did not find the solution.
var sss = SpreadsheetApp.getActiveSpreadsheet();
var ssID = sss.getId();
var sheetName = sss.getName();
var sheet = sss.getSheetByName("TempDataSet");
var sheet1 = sss.insertSheet('TempDataSet_temp');
sheet.getDataRange().copyTo(sheet1.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);
sheet.getDataRange().copyTo(sheet1.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_FORMAT, false);
var shID = sheet1.getSheetId().toString();
sheet1.getRange(2, 1, sheet.getLastRow() -1, sheet.getLastColumn()).sort({column: 1, ascending: false});
var columns_delete = [7,2]; //[7,5,4,2];
columns_delete.forEach(col=>sheet1.deleteColumn(col));
//const sss = SpreadsheetApp.getActiveSpreadsheet();
//const sheet = sss.getSheetByName("TempDataSet");
const subs = sheet.getRange('F2:F'+sheet.getLastRow()).getValues().flat();
const usubs = subs.filter((value, index, self)=>self.indexOf(value) === index);
const dts = sheet.getRange('A2:A'+sheet.getLastRow()).getDisplayValues().flat();
const udts = dts.filter((value, index, self)=>self.indexOf(value) === index);
if(usubs.length>1){
subs.forEach((s,i)=>{
if(i>1){
if(subs[i]!=subs[i-1]){
sheet.getRange(i+1,1,1,5).setBackground('yellow');
}}});
}
else if (udts.length>1){
dts.forEach((d,i)=>{
if(i>1){
if(dts[i]!=dts[i-1]){
sheet.getRange(i+1,1,1,5).setBackground('yellow');
}}});
}
var from = Session.getActiveUser().getEmail();
var subject = 'Batch Attendance Record for Your Reference';
var body = 'Dear Student,'+ '\n\n' + 'Greetings! Please find the batch attendance record attached. Stay safe and blessed.' + '\n\n' + 'Thank you.';
var requestData = {"method": "GET", "headers":{"Authorization":"Bearer "+ScriptApp.getOAuthToken()}};
var url = "https://docs.google.com/spreadsheets/d/"+ ssID + "/export?format=xlsx&id="+ssID+"&gid="+shID;
var result = UrlFetchApp.fetch(url , requestData);
var contents = result.getContent();
sss.deleteSheet(sss.getSheetByName('TempDataSet_temp'));
var sheet2 = sss.getSheetByName('StudentList');
var data = sheet2.getLastRow();
var students = [];
var students = sheet2.getRange(2, 6, data).getValues();
//MailApp.sendEmail(students.toString(), subject ,body, {attachments:[{fileName:sheetName+".xlsx", content:contents, mimeType:"MICROSOFT_EXCEL"}]});
for (var i=0; i<students.length; i++){ // you are looping through rows and selecting the 1st and only column index
if (students[i][0] !== ''){
MailApp.sendEmail(students[i][0].toString(), subject ,body, {attachments:[{fileName:sheetName+".xlsx", content:contents, mimeType:"MICROSOFT_EXCEL"}]});
//MailApp.sendEmail(students[i][0].toString(), subject ,body, {from: from, attachments:[{fileName:"YourAttendaceRecord.xlsx", content:contents, mimeType:"MICROSOFT_EXCEL"}]});
}
}
Explanation:
Based on your question, I understand the following steps:
Check if you have at least two unique subjects in column E. One way to do that is to find the unique list of subjects. If the length of that list is 2 or more it means that you have different subjects. In that case, the first block of the if statement evaluates to true and you add a yellow line in the row before the subject is changed.
If you have only one subject, namely the length of the unique list of subjects is 1 the first block of the if statement will evaluate to false. In that case, the script will check whether column A has 2 or more unique dates. If it does, the second block of the if statement will be executed and the script will add a yellow line in the row before the date is changed. Otherwise, it won't do anything.
Solution:
You can execute color() as a standalone script. I would advice you to save this function in a new .gs file and then simply call it within your current script. Namely, put color() anywhere you want in the code snippet you provided.
function color() {
const sss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = sss.getSheetByName("TempDataSet");
const subs = sheet.getRange('E2:E'+sheet.getLastRow()).getValues().flat();
const usubs = subs.filter((value, index, self)=>self.indexOf(value) === index);
const dts = sheet.getRange('A2:A'+sheet.getLastRow()).getDisplayValues().flat();
const udts = dts.filter((value, index, self)=>self.indexOf(value) === index);
if(usubs.length>1){
subs.forEach((s,i)=>{
if(i>1){
if(subs[i]!=subs[i-1]){
sheet.getRange(i+1,1,1,5).setBackground('yellow');
}}});
}
else if (udts.length>1){
dts.forEach((d,i)=>{
if(i>1){
if(dts[i]!=dts[i-1]){
sheet.getRange(i+1,1,1,5).setBackground('yellow');
}}});
}
}
Complete Solution:
function sendEmails(){
var sss = SpreadsheetApp.getActiveSpreadsheet();
var ssID = sss.getId();
var sheetName = sss.getName();
var sheet = sss.getSheetByName("TempDataSet");
var sheet1 = sss.insertSheet('TempDataSet_temp');
sheet.getDataRange().copyTo(sheet1.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);
sheet.getDataRange().copyTo(sheet1.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_FORMAT, false);
var shID = sheet1.getSheetId().toString();
sheet1.getRange(2, 1, sheet.getLastRow() -1, sheet.getLastColumn()).sort({column: 1, ascending: true});
var columns_delete = [7,2]; //[7,5,4,2];
columns_delete.forEach(col=>sheet1.deleteColumn(col));
SpreadsheetApp.flush();
const subs = sheet1.getRange('E2:E'+sheet1.getLastRow()).getValues().flat();
const usubs = subs.filter((value, index, self)=>self.indexOf(value) === index);
const dts = sheet1.getRange('A2:A'+sheet1.getLastRow()).getDisplayValues().flat();
const udts = dts.filter((value, index, self)=>self.indexOf(value) === index);
if(usubs.length>1){
subs.forEach((s,i)=>{
if(i>1){
if(subs[i]!=subs[i-1]){
sheet1.getRange(i+1,1,1,5).setBackground('yellow');
}}});
}
else if (udts.length>1){
dts.forEach((d,i)=>{
if(i>1){
if(dts[i]!=dts[i-1]){
sheet1.getRange(i+1,1,1,5).setBackground('yellow');
}}});
}
SpreadsheetApp.flush();
var from = Session.getActiveUser().getEmail();
var subject = 'Batch Attendance Record for Your Reference';
var body = 'Dear Student,'+ '\n\n' + 'Greetings! Please find the batch attendance record attached. Stay safe and blessed.' + '\n\n' + 'Thank you.';
var requestData = {"method": "GET", "headers":{"Authorization":"Bearer "+ScriptApp.getOAuthToken()}};
var url = "https://docs.google.com/spreadsheets/d/"+ ssID + "/export?format=xlsx&id="+ssID+"&gid="+shID;
var result = UrlFetchApp.fetch(url , requestData);
var contents = result.getContent();
sss.deleteSheet(sss.getSheetByName('TempDataSet_temp'));
var sheet2 = sss.getSheetByName('StudentList');
var data = sheet2.getLastRow();
var students = [];
var students = sheet2.getRange(2, 6, data).getValues();
//MailApp.sendEmail(students.toString(), subject ,body, {attachments:[{fileName:sheetName+".xlsx", content:contents, mimeType:"MICROSOFT_EXCEL"}]});
for (var i=0; i<students.length; i++){ // you are looping through rows and selecting the 1st and only column index
if (students[i][0] !== ''){
MailApp.sendEmail(students[i][0].toString(), subject ,body, {attachments:[{fileName:sheetName+".xlsx", content:contents, mimeType:"MICROSOFT_EXCEL"}]});
//MailApp.sendEmail(students[i][0].toString(), subject ,body, {from: from, attachments:[{fileName:"YourAttendaceRecord.xlsx", content:contents, mimeType:"MICROSOFT_EXCEL"}]});
}
}
}

Javascript Read data from spreadsheet

I am using a HTML form to get data from google spreadsheet.
I need to get the row where SerNo= 2 (or any specific number)
I am looping through the sheet and trying to get the values as below - but it does nothing
ex:
SerNo Col2
2 Option1
3 Option2
4 Option3
So,if SerNo=2 ...I want to get Option1.
This has 24 columns so i have used the getLastColumn
{function getDataRows_(ss, sheetname) {
var sh = ss.getSheetByName(sheetname);
var lr= sh.getLastRow();
for(var i=1;i<=lr;i++){
var SerNo1 = sh.getRange(i, 2).getValue();
if(SerNo1==SerNo){
return sh.getRange(i, 2, 1, sh.getLastColumn()).getValues();
}
}
}
----edit---
I have posted the whole code I use since it looks like i am filtering records at the wrong place
function read_value(request,ss){
var output = ContentService.createTextOutput(),
data = {};
var sheet="sheet1";
data.records = readData_(ss, sheet);
var callback = request.parameters.callback;
if (callback === undefined) {
output.setContent(JSON.stringify(data));
} else {
output.setContent(callback + "(" + JSON.stringify(data) + ")");
}
output.setMimeType(ContentService.MimeType.JAVASCRIPT);
return output;
}
function readData_(ss, sheetname, properties) {
if (typeof properties == "undefined") {
properties = getHeaderRow_(ss, sheetname);
properties = properties.map(function(p) { return p.replace(/\s+/g, '_'); });
}
var rows = getDataRows_(ss, sheetname),
data = [];
for (var r = 0, l = rows.length; r < l; r++) {
var row = rows[r],
record = {};
for (var p in properties) {
record[properties[p]] = row[p];
}
data.push(record);
}
return data;
}
function getDataRows_(ss, sheetname) {
var sh = ss.getSheetByName(sheetname);
return sh.getRange(2, 1, sh.getLastRow() -1,sh.getLastColumn()).getValues();
}
function getHeaderRow_(ss, sheetname) {
var sh = ss.getSheetByName(sheetname);
return sh.getRange(1, 1, 1, sh.getLastColumn()).getValues()[0];
}
One thing I would recommend is to not retrieve the data on row at a time; in other words retrieve all of the data that you want to search through into an array (i.e. row 1 through last row) and then test each row of the array, looking for your value.

Categories