Google Sheet Retune Row Between Column Match Value in Google sheet script - google-apps-script

The employee sheet contains the id of the employee in Column B. image may help to understand how this code should be work.
How can I get the rows matches the employee id?
I tried the following script and more but it doesn't seem to work.
Sample Image
function getTwoVal() {
var idUrl = "idi";
var sheet = SpreadsheetApp.openById(idUrl).getSheetByName("Sheet1");
var data = sheet.getDataRange().getValues()
var filteredRows = data.filter(function (row) {
if (row[5] === '102' || row[5] === '106') {
return row;
}
});
console.log(filteredRows )
}

Try
var filteredRows = data.filter(function (row) {
if (row[1] == '102' || row[1] == '106') {
return row;
}
});
if id is in column B, use row[1] instead of row[5]
if id may be numeric, use == instead of ===
or, if you want between as the title suggests
var filteredRows = data.filter(function (row) {
if (row[1] >= 102 && row[1] <= 106) {
return row;
}
});

Related

How can I create a filter area in Google Sheets using Google Apps Script?

enter image description here
I want to create a filter area in A1 and A2 cells so that when I put drivers' name on these cells, the table (A:C) should be filtered according to the value entered in A1 and A2. Can someone explain me how to write Apps Script to perform such function?
Thank you in advance!
Try, with both names in C1 and C2 (pls, change sheet name as necessary)
function onEdit(e) {
var col = 3
var sh = e.source.getActiveSheet()
if (sh.getName() != "Sheet1") return;
if (e.range.columnStart > col || e.range.columnEnd < col) return;
if (e.range.rowStart > 2) return;
var names = sh.getRange(1, col, 2, 1).getValues().flat()
var range = sh.getRange(3, col, sh.getLastRow() - 2, sh.getLastColumn() - col + 1);
var filter = sh.getFilter();
if (filter !== null) filter.remove();
if (countNotOccurrences(names, '') == 0) return;
var hiddenNames = range.getValues().slice(1).map(row => row[0]).filter(who => names.indexOf(who) == -1);
range.createFilter();
var criteria = SpreadsheetApp.newFilterCriteria().setHiddenValues([...new Set(hiddenNames)]).build();
sh.getFilter().setColumnFilterCriteria(col, criteria);
}
const countNotOccurrences = (arr, val) => arr.reduce((a, v) => (v !== val ? a + 1 : a), 0);
Driver Data
function MyFunction() {
const ss = SpreadsheetApp.getActive()
const sh = ss.getSheetByName('Sheet0');
const osh = ss.getSheetByName('Sheet1');
osh.clearContents();
const sr = 3;
const dA = sh.getRange(1,1,2).getValues().flat();
const name = dA[0] + ' ' + dA[1];
const nameColumn = 1;
const vo = sh.getRange(sr,1,sh.getLastRow() - sr + 1, sh.getLastColumn()).getValues().filter(r => r[nameColumn -1] == name);
osh.getRange(1,1,vo.length,vo[0].length).setValues(vo);
}
It can be something like this probably:
function onEdit(e) {
if (e.range.columnStart > 1) return;
if (e.range.rowStart > 2) return;
filter_table(e.value);
}
function filter_table(name) {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange(3,1,sheet.getLastRow(),3);
var data = range.getValues();
var hidden_values = data.map(x => x[0]).filter(x => x != name);
var filter = sheet.getFilter();
if (filter !== null) filter.remove();
range.createFilter();
var criteria = SpreadsheetApp.newFilterCriteria().setHiddenValues(hidden_values).build();
sheet.getFilter().setColumnFilterCriteria(1, criteria);
}
It filteres the range A3:C every time you edit cell A1 or cell A2.
But I'm not sure though what do you want to get when the two cells contain different names.
Update
Here is the 'multi-filter' solution :
function onEdit(e) {
if (e.range.columnStart > 1) return;
if (e.range.rowStart > 2) return;
var sheet = SpreadsheetApp.getActiveSheet();
if(sheet.getName() != 'Filter') return; // <-- to limit the trigger only one sheet 'Filter'
var range = sheet.getRange(1,1,sheet.getLastRow(),3);
var [name1, name2, ...data] = range.getValues();
var hidden_values = data.map(x => x[0])
.filter(x => x != name1[0] && x != name2[0]);
var filter = sheet.getFilter();
if (filter !== null) filter.remove();
range.offset(2,0).createFilter();
if (name1[0] + name2[0] == '') return;
var criteria = SpreadsheetApp.newFilterCriteria()
.setHiddenValues(hidden_values).build();
sheet.getFilter().setColumnFilterCriteria(1, criteria);
}
If both of the cells are empty you will see all the rows.

Automatically generate a unique sequential ID in Google Sheets

In Google Sheets, I have a spreadsheet called Events/Incidents which staff from various branches populate. I want Column B to automatically generate a unique ID based on the year in column A and the previously populated event. Given that there could be several events on a particular day, rows in column A could have duplicate dates.
The following is an example of what I am looking for in column B:
There can be no duplicates. Would really appreciate some help with either code or formula.
There are my thoughts https://github.com/contributorpw/google-apps-script-snippets/blob/master/snippets/spreadsheet_autoid/autoid.js
The main function gets a sheet and makes the magic
/**
*
* #param {GoogleAppsScript.Spreadsheet.Sheet} sheet
*/
function autoid_(sheet) {
var data = sheet.getDataRange().getValues();
if (data.length < 2) return;
var indexId = data[0].indexOf('ID');
var indexDate = data[0].indexOf('DATE');
if (indexId < 0 || indexDate < 0) return;
var id = data.reduce(
function(p, row) {
var year =
row[indexDate] && row[indexDate].getTime
? row[indexDate].getFullYear() % 100
: '-';
if (!Object.prototype.hasOwnProperty.call(p.indexByGroup, year)) {
p.indexByGroup[year] = [];
}
var match = ('' + row[indexId]).match(/(\d+)-(\d+)/);
var idVal = row[indexId];
if (match && match.length > 1) {
idVal = match[2];
p.indexByGroup[year].push(+idVal);
}
p.ids.push(idVal);
p.years.push(year);
return p;
},
{ indexByGroup: {}, ids: [], years: [] }
);
// Logger.log(JSON.stringify(id, null, ' '));
var newId = data
.map(function(row, i) {
if (row[indexId] !== '') return [row[indexId]];
if (isNumeric(id.years[i])) {
var lastId = Math.max.apply(
null,
id.indexByGroup[id.years[i]].filter(function(e) {
return isNumeric(e);
})
);
lastId = lastId === -Infinity ? 1 : lastId + 1;
id.indexByGroup[id.years[i]].push(lastId);
return [
Utilities.formatString(
'%s-%s',
id.years[i],
('000000000' + lastId).slice(-3)
)
];
}
return [''];
})
.slice(1);
sheet.getRange(2, indexId + 1, newId.length).setValues(newId);
}
I think it can be simplified in the feature.
There is an easier way to generate unique values that works for me, pick a #, then do +1. Ctrl C, then Ctrl shift V to paste back and remove the formula. Now you are left with thousands of unique IDs.
This is a manual solution but you can do an entire database in a matter of seconds every once in a while.

Depending on (Id). How to place this database (Ppt) in (MP04 / MP 05)

Description: I have a sheet (Ppto) with a list of IDs (Id), Credits(Cedent) and Debits(Recept). I would like to move these transactions to MP05, If Id are equal. If Ids are not equal move to MP04. Criterion: If Id = use MP05. If Id ≠ use MP04.
I'm a novice in google script, I need some support.
Thanks for your attention
function mp() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ppto = ss.getSheetByName('Ppto.');
var Id = ppto.getRange('B5:B12').getValues();
var cedent = ppto.getRange('D5:D12').getValues();
var recept = ppto.getRange('E5:E12').getValues();
for (var i = 0; i < cedent.length; i++) {
for (var j = 0; j < recept.length; j++) {
if (cedent[i] != '' ) {
if (recept[j] != '' ) {
//if (Id === Id) // MP-05
//if (Id != Id) // MP-04
{
ppto.getRange('H5:H12').setValues(cedent);
ppto.getRange('I5:I12').setValues(recept);
Logger.log(cedent[i]);
ppto.getRange('j5:j12').setValues(cedent);
ppto.getRange('k5:k12').setValues(recept);
}
}
}
}
}
}
Strategy:
FIFO: First-In First Out
Loop through all rows using forEach
If credit is present, Loop again through all rows using some to look for receipts
If credit e[2] in first loop equals receipts f[3] in second loop, Check for id [0]
If ID is equal, splice two empty columns at the end, else at the 2nd position to create a uniform 6-column array
Set that array back to the sheet.
Sample Script:
function transactionSegregator() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ppto = ss.getSheetByName('Ppto.');
var data = ppto.getRange('B5:E12').getValues();
data.forEach(function(e) {
//e: Each row
if (e[2] && e.length == 4) {
//e[2]:credits; If this row is not spliced
data.some(function(f) {
//f:Each row; Second loop
if (e[2] == f[3]) {
//if credits = debit
if (e[0] == f[0]) {
//if id = id, splice two empty columns after Col4, else after Col2
e.splice(4, 0, '', '');
f.splice(4, 0, '', '');
} else {
e.splice(2, 0, '', '');
f.splice(2, 0, '', '');
}
return true;
}
});
}
});
Logger.log(data);
ppto.getRange(5, 6, data.length, data[0].length).setValues(data);// F5
}
References:
Javascript tutorial
Array#forEach
Array#some
Array#splice

Google Script past row, script works on 1 column only. If you edit the column then it change 2 column

The script works when you change 1st and 2second column when you edit each cell on it's own. But when you past a row in it. It only change the 1st column
function onEdit(e) {
var range = e.range;
var column = range.getColumn();
var value = range.getValue();
var sheet = range.getSheet();
var sheetName = sheet.getName();
//Logger.log(value);
//Logger.log(Date(value).getMonth());
Logger.log(range.getColumn());
switch (sheetName) {
case "sheetnameeee":
if(column == 1||column == 2)
{
range.getCell(1, 1).setValue(dateChange(value)).setNumberFormat("yyyy-MM-dd");
range.getCell(1, 2).setValue(dateChange(value)).setNumberFormat("yyyy-MM-dd");
};
break;
}
Input :
Start date | Eind date
okt 15, 2018 | okt 21, 2018
Copy and past:
Start date | Eind date
2018-10-15 | okt 21, 2018
But it need todo :
Start date | Eind date
2018-10-15 | 2018-10-21
This is my solution. It's not great but it works..
switch (sheetName) {
case "Sheetnameeeee":
var ss = SpreadsheetApp.getActiveSpreadsheet();
var test222 = ss.getSheetName();
var startRow = 1
var rowRange = ss.getRange("A:B");
var rowLength = getRange.getLastRow();
var RangeValues = getRange.getValues();
for (var i=startRow; i < rowLength; i++) {
if(typeof RangeValues[i][0] === 'string')
{
RangeValues[i][0] = dateChange(RangeValues[i][0]);
};
if(typeof RangeValues[i][1] === 'string')
{
RangeValues[i][1] = dateChange(RangeValues[i][1]);
};
}
rowRange.setValues(RangeValues);
rowRange.setNumberFormats([["yyyy-MM-dd","yyyy-MM-dd"]]);
I'm not sure about your logic. It seems that getCell(1,1) and getCell(1,2) would end up with the same value. However, this may work for you with some minor name modifications assuming dateChange returns a Date.
function onEdit(e) {
try {
if( e.range.getSheet().getName() === "Sheet4" ) {
var range = null;
if( e.range.getColumn() === 1 ) {
range = e.range.offset(0,0,1,2);
}
else if( e.range.getColumn() === 2 ) {
range = e.range.offset(0,-1,1,2);
}
var values = range.getValues();
values[0][0] = dateChange(values[0][0]);
values[0][1] = dateChange(values[0][1]);
range.setValues(values);
range.setNumberFormats([["yyyy-MM-dd","yyyy-MM-dd"]]);
}
}
catch(err) {
Logger.log(err);
}
}

Copying or updating the row based on the occurrence of a row cell value

I'm trying to add a given row or update an existing row to a Google Sheet based on a specific value in the row data. My row data is represented as an array object, like this: [id, number, date, type, url, count].
What I expect is that, if there exists a row with a matching number, I increment the count by 1 in the same range in the Google Sheet, else I add a new row with my row data.
Here's what I've tried so far, but it works only for count=2 and not beyond that.
function copyRowBasedOnNumber(sheetId, sheetName, rowData) {
var sheet = SpreadsheetApp.openById(sheetId);
var sheetname = sheet.getSheetByName(sheetName);
var count = 0;
var matchingRow = sheetname.getLastRow();
var values = sheetname.getDataRange().getValues();
for (var row in values) {
for (var col in values[row]) {
if (values[row][col] == rowData[1]) { // rowData[1] corresponds to the number
matchingRow = row;
count++;
break;
}
}
}
if(count == 0) {
var lastRowNum = sheetname.getLastRow();
sheet.insertRowAfter(lastRowNum);
rowData[5] = 1;
sheetname.getRange(lastRowNum + 1, 1, 1, rowData.length).setValues([rowData]);
} else {
sheetname.getRange(parseInt(matchingRow) + 1, 6).setValue(count + 1);
}
return count + 1;
}
I've figured it out. In case this helps someone in future, here's the code. Here, count is the value I want to check before I add a new entry or update an existing entry.
function copyRowToSheetWithoutDuplicate(sheetId, tabName, rowData) {
var sheet = SpreadsheetApp.openById(sheetId);
var sheetname = sheet.getSheetByName(tabName);
var count = 0;
var existingCount = 0;
var existingEntryRow = 0;
var allValues = sheetname.getDataRange().getValues();
var numColumns = sheetname.getLastColumn();
var numRows = sheetname.getLastRow();
for(var i=0;i<numRows;i++) {
var dateFromRowData = rowData[3].substring(0,10);
var todayDate = Utilities.formatDate(new Date(), "GMT+05:30", "''yyyy-MM-dd");
if(allValues[i][1]==rowData[1] && dateFromRowData!=todayDate) {
count++;
existingCount = allValues[i][6];
existingEntryRow = i + 1;
break;
}
}
if(count == 0) {
// insert a row and make an entry
sheetname.insertRowAfter(numRows);
rowData.push(1); // count
sheetname.getRange(numRows + 1, 1, 1, rowData.length).setValues([rowData]);
return 1;
} else {
// update the existing count by incrementing it by 1
existingCount++;
rowData.push(existingCount); // count
sheetname.getRange(existingEntryRow, 1, 1, rowData.length).setValues([rowData]);
return existingCount;
}
}