apps script - search value from sheet1 in array in sheet2 (google sheets) - google-apps-script

I'm completely new to apps script and java.
I have a tracker where users insert IDs in col1 sheet1. I need to be able to prevent and alert them whenever their input DOESN'T exists in an array in col2 sheet 2.
so far I've got this, but this is not working for me at all.
var ss = SpreadsheetApp.getActiveSpreadsheet();
function onEdit(e) {
var sheet = ss.getSheetByName("Sheet1")
var so = ss.getSheetByName("Sheet2"); so.activate();
var vltest = sheet.getActiveCell().getValue()
var vlary = so.getActiveCell().getValue()
var r = sheet.getActiveRange().getRow()
var c = sheet.getActiveRange().getColumn();
if(vltest!=="" && c==1 && r>1 && sheet == "Sheet1"){
var data = so.getRange("B1:B").getValues().filter(String).flat()
if(data.indexOf(vlary)=data.lastIndexOf(vlary)){
e.range.setValue("")}
if(data.indexOf(vlary)=data.lastIndexOf(vlary)){SpreadsheetApp.getUi().alert("Alert", "Alert", SpreadsheetApp.getUi().ButtonSet.OK);}}}
Any ideas?

You need to get all values from compare sheet, loop them through and look for match of the value, that onEdit() gives you back. Something like this:
function onEdit(e) {
var ss = SpreadsheetApp.openById('sheet_ID'); //or getActive();
var so = ss.getSheetByName("Sheet2");
// let's say you get all rows from column 1
var compareData = so.getRange(1, 1, so.getLastRow(), 1).getValues();
for (var d = 0; d < compareData.length; d++) {
if (compareData[d] === e.value) {
SpreadsheetApp.getUi().alert("Alert", "Alert", SpreadsheetApp.getUi().ButtonSet.OK)
}
}

Related

Functions all executing at the same time

I am trying to copy data from one sheet, paste it into another and then delete the row that have a "flag" attached to them (Column D). When I execute this code, it just deletes the flag and not the whole row. What is going on here? The functions seem to execute in the wrong order.
Tried using Utilities.sleep(), as well as
separating both into different functions
using a for loop writing out all the columns I want deleted
applying flush to the functions before executing the next
//copies the code
function myFunction() {
var url = 'https://docs.google.com/spreadsheets/d/1ie2Fyj2piVV8XC0XUGX-fTAHcQ0UUUdec4Mtr1QdXtQ/edit#gid=293227072'
var ss = SpreadsheetApp.openByUrl(url)
var sheet = ss.getSheetByName('Bad Emails Input')
var range = sheet.getRange("K:N")
var values = range.getValues()
var target = ss.getSheetByName("worklist")
target.getRange("A:D").setValues(values)
SpreadsheetApp.flush()
Utilities.sleep(5 * 1000)
}
//deletes the rows with flags in them
function myFunction2() {
var url = 'https://docs.google.com/spreadsheets/d/1ie2Fyj2piVV8XC0XUGX-fTAHcQ0UUUdec4Mtr1QdXtQ/edit#gid=293227072'
var ss = SpreadsheetApp.openByUrl(url)
var sheet = ss.getSheetByName('Bad Emails Input')
var range = sheet.getRange("K:N")
var values = range.getValues()
var target = ss.getSheetByName("worklist")
Utilities.sleep(6 * 1000)
var oldnews = target.getRange("D:D")
for (i = oldnews.length; i > 0; i--){
if (oldnews[i] !== undefined) {
target.getRange(i,1)
target.getRange(i,2)
target.getRange(i,3)
target.getRange(i,4)
}
}
SpreadsheetApp.flush()
}
It's not really clear what your asking. So I just guessed at some of this.
function myFunction() {
var ss = SpreadsheetApp.openById("id");
var sheet = ss.getSheetByName('Bad Emails Input')
var range = sheet.getRange(1,11,sheet.getLastRow(),4);
var values = range.getValues()
var target = ss.getSheetByName("worklist")
target.getRange(1,1,values.length,values[0].length).setValues(values);
SpreadsheetApp.flush();
var d=0;
for(var i=0;i<values.length;i++) {
if(values[i][3]) {
target.deleteRow(i+1-d++);
}
}
}
Try the below code:
function myFunction() {
var url = 'https://docs.google.com/spreadsheets/d/1ie2Fyj2piVV8XC0XUGX-fTAHcQ0UUUdec4Mtr1QdXtQ/edit#gid=293227072'
var ss = SpreadsheetApp.openByUrl(url);
var sheet = ss.getSheetByName('Bad Emails Input');
var range = sheet.getRange("K:N");
var values = range.getValues();
var target = ss.getSheetByName("worklist");
target.getRange("A:D").setValues(values);
SpreadsheetApp.flush();
//If you have a header row change the below to A2:D and count to 2
var data=ss.getSheetByName("worklist").getRange("A:D").getValues(),count=1;
for (i in data) {
var rowdata=data[i];
if (!rowdata[0] || rowdata[0]==''){break;}
if (rowdata[3] == 'flag') {//change the flag to however it is in column D
ss.getSheetByName("worklist").deleteRow(count);
count++;
}
}
}

How to get and set column number based on value in source spreadsheet

Trying to copy a range (L2:L9) to another spreadsheet based on a data validation selection (ID #) in a specific cell (G11) on the source spreadsheet.
The ID#s are all in alphanumeric order on the target spreadsheet along row 5, so all I need is to get the column number that corresponds to the choice made in the data validation field.
Before I had to convert the ID#s to Alphanumeric values, I simply had numeric values and the script worked fine. Now I'm having trouble converting the script to work with this modification.
function Submit() {
var ss = SpreadsheetApp.getActiveSpreadsheet(); // ss = source spreadsheet
var source_sheet = ss.getActiveSheet();
if (source_sheet.getName() == "Pre-Season CC") {
var SRange = source_sheet.getRange('L2:L9');
var A1Range = SRange.getA1Notation();
var SData = SRange.getValues();
var target = SpreadsheetApp.openById('1MpKdxFyBrVQT3EumePQvtCZpgzcDW5xlYe4B1DKZCA8');
var target_sheet = target.getSheetByName('Pre-Season');
var idNumber = source_sheet.getRange('Pre-Season CC!G11').getValue();
for (var i = 0; i < idNumber.length; i++) {
for (var j = 0; j < idNumber.length;j++){
if (target_sheet[4][j] == idNumber){
Logger.log((j+1))
return j+1;
target_sheet.getRange('B6:B13').offset(0,valueA1 = ss.getRange('Pre-Season!G11').getValue(idNumber)+1).setValues(SData);
}
}
}
}
At that point, I need the data copied from source spreadsheet onto the target spreadsheet in it's designated column, according to the ID#. Please help!
Try below code.
function Submit() {
var ss = SpreadsheetApp.getActiveSpreadsheet(); // ss = source spreadsheet
var source_sheet = ss.getActiveSheet();
if (source_sheet.getName() == 'Pre-Season CC') {
// source sheet items
var SData = source_sheet.getRange('L2:L9').getValues();
var idNumber = source_sheet.getRange('Pre-Season CC!G11').getValue();
// target sheet items
var targetSS = SpreadsheetApp.openById('1MpKdxFyBrVQT3EumePQvtCZpgzcDW5xlYe4B1DKZCA8');
var target_sheet = targetSS.getSheetByName('Pre-Season');
// 5 = row where IDs are
var TData = target_sheet.getRange(5, 1, 1, target_sheet.getLastColumn()).getValues()[0];
// column index of #ID in target sheet
var colIndex = TData.indexOf(idNumber) + 1;
// write data in that column, rows from 6 to 13
target_sheet.getRange(6, colIndex, SData.length, 1).setValues(SData);
}
}

Google App Script update cell value in another sheet

I'm a little stuck on this one. I'm trying to find the corresponding row and update the last column in another google spreadsheet after updating the first column of another spreadsheet.
When the user selects "Restocked" in ColA of spreadsheet X , I need to lookup the ID value in ColB on another sheet (Y). Then I need to access spreadsheet Y, find the row that contains that same ID. Access the last column or columnAZ (52) and change the cell value to "Restocked".
Here is what I have so far...
function restockComplete(){
var s = SpreadsheetApp.getActiveSpreadsheet();
if( s.getName() == "Restock Queue"){
var r = s.getActiveCell();
if ( r.getColumn() == 1 && r.getValue() == "Restocked"){
var nextCell = r.offset(0, 1);
var buybackId = nextCell.getValue();
// Opens SS by its ID
var ss = SpreadsheetApp.openById("xxxxxxxxxxxxxxxSheetIDHerexxxxxxxxxxx");
var sheet = ss.getSheetByName('NameOfSheetHere'); // Name of sheet
// var range = sheet.getRange(1,1); // Gets Column 1 Cell 1 value
//var data = range.getValue();
var data = sheet.getDataRange().getValues();
//var buyback = sheet.getRange(buybackId).getValue();
for(var i = 0; i<data.length;i++){
if(data[i][1] == buybackId){ //[1] because column B
Logger.log((i+1))
i.offset(0, 52).setValue('Restocked');
return i+1;
}
}
}
}
};
You're close, save for one error. Right now, to test for the sheet name, you have to actually get the sheet. I would do the following to fix the immediate problem:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getActiveSheet() // call this for the active sheet
...
You also had an error in your loop setting the value:
for(var i = 0; i<data.length;i++){
if(data[i][1] == buybackId){ //[1] because column B
// Get the range of the cell, not the index.
sheet.getRange((i+1), 1).setValue('Restocked');
}
}
...
Rename your secondary sheet from ss to something else to avoid a conflict.
Beyond this fix, there are some changes I'd recommend making to make the script more efficient for your users. Rather than look for the active cell, you can use the onEdit simple trigger with an e event object. This will allow your script to modify cells regardless of where the active cell is.
function onEdit(e){
var ss = SpreadsheetApp.getActiveSpreadsheet()
var s = ss.getActiveSheet();
if( s.getName() == "Restock Queue"){
if ( (e.range.getColumn() == 1.0) && (e.range.getValue() == "Restocked") ){
var nextCell = e.range.offset(0, 1);
var buybackId = nextCell.getValue();
var ss2 = SpreadsheetApp.openById('xxx');
var sheet = ss2.getSheetByName('NameOfSheetHere'); // Name of sheet
var data = sheet.getDataRange().getValues();
for(var i = 0; i<data.length;i++){
if(data[i][1] == buybackId){ //[1] because column B
// Get the range of the cell, not the index.
sheet.getRange((i+1), 52).setValue('Restocked');
}
}
}
}
}

One trigger to activate two functions

Self taught noob, working in google sheets, sorry in advance for the mess here. I am trying to pull data from two cells into a new sheet. Both of these are pulled in after I trigger them with an onEdit. I need to enter a value and hit enter on both cells for them to be placed into the new sheet. How would I set this up so that when I trigger "D9" I would pull in "C9" plus "D9"?
function onEdit(e){
// Set a comment on the edited cell to indicate when it was changed.
if(e.range.getA1Notation() === 'C9'){
var input = e.range.getValue();
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var inputSheet = sheet.getSheetByName("input")
var masterSheet = sheet.getSheetByName("master inventory");
var currentRow = inputSheet.getRange("E9").getValue();
masterSheet.getRange("A3:A1000").getCell(currentRow, 1).setValue(input);
inputSheet.getRange("E9").setValue(currentRow, 1);
}
if(e.range.getA1Notation() === 'D9'){
var input = e.range.getValue();
e.range.clearContent();
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var inputSheet = sheet.getSheetByName("input")
var masterSheet = sheet.getSheetByName("master inventory");
var currentRow = inputSheet.getRange("E9").getValue();
masterSheet.getRange("B3:B1000").getCell(currentRow, 1).setValue(input);
inputSheet.getRange("E9").setValue(currentRow + 1);
}
}
I am not sure exactly what you are trying to do, but try this:
function onEdit(e) {
var x=e.source.getSheetName()
if( x == "input" ) { //checks that we're on the correct sheet
var y = e.range.getSheet().getActiveCell();
var z= e.range.getSheet().getActiveCell().getA1Notation()
var row=e.range.getSheet().getActiveCell().getRow()
if(z=="D9" && x=="input"){
var cell=e.range.getSheet().getActiveCell().getValue()
e.range.getSheet().getActiveCell().clearContent()
var nextCell =e.range.getSheet().getActiveCell().offset(0,-1).getValue()
e.range.getSheet().getActiveCell().offset(0,-1).clearContent()
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var masterSheet = sheet.getSheetByName("master inventory");
masterSheet.getRange("A3:A1000").getCell(row-2, 1).setValue(nextCell);
masterSheet.getRange("B3:B1000").getCell(row-2, 1).setValue(cell);
}}}

Google Spreadsheet: run script on cell value change

In a spreadsheet I have two sheets, * and Calculator. When I change the value on "*"!B1 (i.e. cell B1 of sheet *), I want to run the script: to change (actually clear) the value of "Calculator"!B3 (i.e. cell B3 of sheet "Calculator").
Here's my code. I created it through Spreadsheet > Tools > Script editor, so it's not an standalone:
The difference between Version 1 and 2 is that in Version 1 the first function is run and the second is missed (vice versa in Version 2), plus one thing I'll detail below.
Version 1
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var languageSheet = ss.getSheetByName("*").getSheetName();
var languageCell = languageSheet.getRange("B1");
var sheets = ss.getSheets()[0];
var languageCellCheck = sheets.getActiveCell();
var cookingMethodSheet = ss.getSheetByName("Calculator").getSheetName();
var cookingMethodCell = cookingMethodSheet.getRange("B3");
var range = e.range;
if (range == languageCell)
cookingMethodCell.setValue("A");
}
//function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var languageCell = ss.getSheetByName("*").getRange("B1");
var sheets = ss.getSheets()[0];
var languageCellCheck = sheets.getActiveCell();
var cookingMethodCell = ss.getSheetByName("Calculator").getRange("B3");
var range = e.range;
if (range == languageCell)
cookingMethodCell.setValue("A");
//}
Version 2
//function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var languageSheet = ss.getSheetByName("*").getSheetName();
var languageCell = languageSheet.getRange("B1");
var sheets = ss.getSheets()[0];
var languageCellCheck = sheets.getActiveCell();
var cookingMethodSheet = ss.getSheetByName("Calculator").getSheetName();
var cookingMethodCell = cookingMethodSheet.getRange("B3");
var range = e.range;
if (range == languageCell)
cookingMethodCell.setValue("A");
//}
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var languageCell = ss.getSheetByName("*").getRange("B1");
var sheets = ss.getSheets()[0];
var languageCellCheck = sheets.getActiveCell();
var cookingMethodCell = ss.getSheetByName("Calculator").getRange("B3");
var range = e.range;
if (range == languageCell)
cookingMethodCell.setValue("A");
}
When I say "Version 1" I mean I changed the value of "*"!B1 from "Something" to "Whatever", and cell "Calculator"!B3 wasn't changed. Then, using Version 2, I tried the same but got the same result (no change in B3).
The idea of having two functions (same for both versions) is because I don't know if using ss.getSheetByName("Calculator").getSheetName(); or directly selecting in as in ss.getSheetByName("*").getRange("B1"); will make a difference. Apparently, it doesn't.
What's and where's the error?
Going by your variable name var languageSheet = ss.getSheetByName("*").getSheetName(); it seems that you expect languageSheet to actually be a sheet object and not a string. That seems to be reaffirmed var sheets = ss.getSheets()[0];
As such you must edit that line to say var languageSheet = ss.getSheetByName("*") and the same goes further on with var cookingMethodSheet = ss.getSheetByName("Calculator")
Now the real problem:
if (range == languageCell)
cookingMethodCell.setValue("A");
this will always return false. You are comparing two different objects. They will never be the same. You need to compare their column and row or A1 notation instead by using something like range.getColumn() and range.getRow() or range.getA1Notation(). Currently it's like you write the number 3 on two pieces of paper and ask if the two pieces of paper are the same thing. They will both have the same value and be comparable, but they will never be the same piece of paper.
Furthermore, going by your code, you are getting the edited range and then you get the active cell which will always be the same cell. So you might as well have the logic be if (1 == 1) or more specifically, because you are comparing to range type objects, it's like writing if (1 == 2)
EDIT: With the things considered in the comments of this answer you are making things more complicated then they need to be. Here is a function that will clear B1:B3 in Calculator only if B1 in * is changed:
function onEdit(e) {
var langName = '*'
var langCell = 'B1'
var curSheet = e.range.getSheet()
if (curSheet.getName() === langName) {
if (e.range.getA1Notation() === langCell) {
var cookingMethodSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Calculator')
var range = cookingMethodSheet.getRange('B1:B3')
range.clear()
}
}
which you can make a little shorter by doing
function onEdit(e) {
if (e.range.getSheet().getName() === '*') {
if (e.range.getA1Notation() === 'B1') {
SpreadsheetApp
.getActiveSpreadsheet()
.getSheetByName('Calculator')
.getRange('B1:B3')
.clear()
}
}
The indentation is there only so the line is not too long.