find value but replace a different cell - google-apps-script

I have a 2 columns 1 column with data and the other with with drop-down lists in every cell.
When I make a choice on the dropdown list I want google sheet to auto select the same items the the other dropdown lists based on the value of the cell from the first row.
(I dont want to do the same thing over and over)
Currently I am struggeling on when I found a cell with a specific value, how do I then replace the value of another cell. I found some examples using textFinder, but now it replaces the value of the current cell.
When I found the value I need to target the cell that I want to modify (the cell on the second column)
I have the following script:
function onEdit() {
var activesheet = SpreadsheetApp.getActiveSheet()
var Cell = SpreadsheetApp.getActiveSheet().getActiveCell();
var Column = Cell.getColumn();
if (activesheet.getName()=='Transacties'){
if (Column == 5 && SpreadsheetApp.getActiveSheet()){
var Target = SpreadsheetApp.getActiveSheet().getRange(Cell.getRow(), Column + 1);
var Reknr = SpreadsheetApp.getActiveSheet().getRange(Cell.getRow(), Column + -1); //this is the bill column
var Juistecat = SpreadsheetApp.getActiveSheet().getRange(Cell.getRow(), Column + 0); //this is the drop-list column
var Options = SpreadsheetApp.getActiveSpreadsheet().getRangeByName(Cell.getValue());
var Valrek = Reknr.getValue(); //waarde huidig rekening nr
var Valcat = Juistecat.getValue(); //waarde huidig rekening nr
SubcategoryDropdown(Target, Options);
}
//Reknr.setValue("Hello"); //werkt, juiste cell iig
// var vv = SpreadsheetApp.getActiveSheet().getActiveCell().getValue();
SpreadsheetApp.getUi().alert("The active cell value is "+Valrek);
SpreadsheetApp.getUi().alert("The active cell value is "+Valcat);
var textFinder = Reknr.createTextFinder(Valrek);
var range = SpreadsheetApp.getActive().getRangeByName("Reknr");
var values = range.getValues();
SpreadsheetApp.getUi().alert("The active cell value is "+valrek);
values.forEach(function(row) {
row.forEach(function(col) {
textFinder.replaceAllWith(Valrek); // But I dont want to replace the current, I need to replace
//Target.setValue("Hello");
});
});
}

I made a sample code which should do what you need. However, since I do not know how the information is arranged in your Google Sheet, I cannot customize the code to match exactly with the information on your sheet and some changes will be necessary.
I tried to comment on the code as much as possible so it can be easily changed and customized to your data.
This is how I arrange my data:
function onEdit(e) {
// you need to add the name of your sheet
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1');
// Automatically gets the range that was edited
const range = e.range;
// Gets the A1 notation of the cell example 'B2'
let current_cell =range.getA1Notation();
// Gets the value in the range that was modify
// In this case the value inside the drop-down
let value_selected = sheet.getRange(current_cell).getValue();
// Gets the column that was edited
col = range.getColumn();
// My drop-down was in column B
// This will filter only the changes on column B, and excludes the rest
// you can change this to the column where you drop-down is located
if (col == 2){
//Gets the number of row where the value in column B was change
let row = range.getRow();
// The data I was searching was in column 1, so I use 'A'+row
// You can replace the A for the column where the search will be done
new_cell = sheet.getRange('A'+row).getValue();
// Searches all the values in column A
// that match the one next to the value edited
list = sheet.createTextFinder(new_cell).findAll();
// Loops inside the list of array that was created with the search
for (let i = 0; i < list.length; i++){
let ranges_info = list[i];
// Gets the row in each iteration of the range inside 'list'
let ranges_row = ranges_info.getRow();
// set the value, I selected in the first drop-down
// to the rest of the cells in B that match the same value in A
sheet.getRange('B' + ranges_row).setValue(value_selected)
};
}
}
And here is a gif with the code running:

Related

Can I add multiple checkboxes in rows when a cell in each row contains a value?

Please help me out with this script that I found?
I'm not an experienced coder, so I'm just winging it at this point.
I want to simply make the process of adding check boxes to each new row automated with the following script:
function onEdit() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1"); //change this to the name of your sheet
ui = SpreadsheetApp.getUi();
//PICK ONE & comment out the other one:
var names = ss.getRange("Ranger");//Use this if you are naming the range (Refer Range)
//var names = ss.getRange("B3:B");//Use this if you are naming the ranges
var namesValues = names.getValues(); //Get array of all the names
//PICK ONE & comment out the other one:
var checkboxes = ss.getRange("Checkboxes"); //Use this if you are naming the range
//var checkboxes = ss.getRange("C2:E2"); //Use this if you want to hard-code your range
var cbRows = checkboxes.getHeight(); //Get # of rows in the ranges
var cbValues = checkboxes.getValues(); //Get array of all the checkbox column cell values
//Logger.log(cbValues);
var newCBValues = new Array(cbRows); //Create an array to store all the new checkboxes values before we edit the actual spreadsheet
for (var row = 0; row < cbRows; row++) {
newCBValues[row] = new Array(0); // Make the array 2 dimensional (even though it only has 1 column, it must be 2D).
if (namesValues[row] == "" || namesValues[row] == " ") { //If the name cell of this row is empty or blank then...
newCBValues[row][0] = " "; //Set the value to one space (which will make the cell NOT true or false, and thus NOT display a checkbox).
//Logger.log("newCBValues[" + row + "][0]: " + newCBValues[row][0]);
}else{ //otherwise, if the name cell isn't blank...
if (cbValues[row][0] === true) {
newCBValues[row][0] = true; //Keep the checkbox checked if it's already checked
}else{ //If the name cell isn't blank, and it's not true...
newCBValues[row][0] = false; //Then Keep it or set it to False (an empty checkbox):
}
}
}
checkboxes.setValues(newCBValues); // now that we have a completed array of our new checkbox values, let's edit the sheet with them!
}
I'm only able to add check boxes into one column, I would like to add check boxes into like 10 separate columns based on the value of 1 Row's cell values.Spreadsheet I'm working on to capture data
You use [row][0] which refers to the 1st column of a range
If you want to perform an an action for all columns, you need to loop through those columns.
Sample:
if (cbValues[row][0] == true) {
for( var j = 0; j < newCBValues.length; j++){
newCBValues[row][j] = true;
}
}
Btw., see here how to build checkboxes instead of copying them.

Dependent Data Validation in Google Apps Script

I need to add Data Validation to a range of cells based on the State chosen in the previous cell.
I've run this code which works ok for a limited amount of data but is not working on the actual spreadsheet.
function onEdit(e) { // Runs automatically when the user edits the sheet
var value = e.value; // Get the new value entered into the edited cell
var col = e.range.getColumn(); // Get the column number of the edited cell
var row = e.range.getRow(); // Get the row number of the edited cell
if (col == 6 && row >= 10 && row <= 854) { // Make sure that the edited cell is part of the table
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Hoja 1');
var sheet2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Localidades'); // Get the sheet that has the table with the list of cities
var dropdownData = sheet2.getRange("A1:X594").getValues(); // Get the table with the list of cities.
var listOfCountries = dropdownData[0]; // The top row is the list of countries
var countryColumn = listOfCountries.indexOf(value); // Find the column in which the country name appears
if (countryColumn != -1) { // If the new country name is in the list
var cityList = [];
for (var dataRow = 1; dataRow < dropdownData.length; dataRow++) {
cityList.push(dropdownData[dataRow][countryColumn]);
}
var cityCell = sheet.getRange(row, col + 1);
cityCell
.clearDataValidations() // Remove any existing data validation in the target cell
.clearContent(); // Clear the cell
var rule = SpreadsheetApp.newDataValidation().requireValueInList(cityList, true).build();
cityCell.setDataValidation(rule);
}
}
}
I've debugged and it gets the CityList all right so don't know what's the problem really. Any help??
There is a limited amount of allowed dropdown options
Through testing you can easily verify that it is 500 options.
So, if you hardcode "A1:X594" you are above the limit.
However, for most of the provinces in your data the amount of options is less than 594 and your array contains many empty values.
You can remove all duplicates inlcuding emoty values by filtering, e.g.
cityList = cityList.filter(function (value, index, self) {
return self.indexOf(value) === index;
})
As for the provinces where you have many entries (e.g. Buenos Aires), maybe you can try to subdivide it into smaller regions so you have less than 500 dropdown options per dropdown?

How to use offset after obtaining reference cell using indexOf in Google Script

I've written a script to find a match of a given cell via for loop variable (it works great). When logged out, it provides the position 11.0 in the searched column of data. What I then want to do is uncheck a checkbox that is offset by (0,-5) from that referenced cell. When I try to use offset, I get the TypeError: offset is not a function. How do I accomplish this?
Below is the script I've written to get to where I am stuck. What I am doing is checking a box on Sheet2, which is on the same row for a given product. The row on which the product and its checkbox reside will not always be the same (could be row 5, could be row 12). Once I check the box, the script determines what the name of the product is (in this case, Product L), and then looks for its match via indexOf on Sheet1. IndexOf finds the location on Sheet1 (in this case, 11.0, which is row 13, col 10). There is a corresponding checkbox on Sheet1 row 13 in column 5 which then needs to be unchecked. And that is where I am stuck. The sheet is dynamic, and the rows for checkboxes and corresponding products will constantly be changing.
function findText() {
var spreadsheet = SpreadsheetApp.getActive();
var sheet2 = spreadsheet.getSheetByName("Sheet2");
var sheet1 = spreadsheet.getSheetByName("Sheet1");
var lr = sheet1.getLastRow();
var lookupRangeArray = sheet1.getRange(3,10,lr,1).getValues();
var newRange = lookupRangeArray.map(function(r){ return r[0]; });
for (var i=0; i <= lr; i++){
var checkboxRange = sheet2.getRange(i+1,2);
var checkboxStatus = checkboxRange.getValue();
if(checkboxStatus == true){
var text = checkboxRange.offset(0, 2).getValue();
Logger.log(text);
var position = newRange.indexOf(text);
Logger.log(position)
position.offset(0,-5).setValue(false);
You need to retrieve the cell to offset
You can do it e.g. by specifying the row and column position of the cell reference or its A1 notation.
Sample
var row=1;
var column = 11;
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var cell = sheet.getRange(row, column);
var newCell = cell.offset(0, -5);

How to create in-cell drop down that will create & sync new Google Sheets?

I'm wondering how to do the following in Google Sheets...
Create an in-cell drop-down so that the values that I select will
create a new sheet for each row when there's a new value selected for the in-cell drop-down, and then
sync the rows with the in-cell drop-down selected values in the newly created sheets
Create an in-cell drop-down that will
create new tabbed sheets for each row when there's a new value selected for the in-cell drop-down, and then
sync the rows with the in-cell drop-down selected values in the newly created tabbed sheets
On entering a dropdown value in a column, if this is the first use of that dropdown value, then you want to create a sheet with the name of the dropdown value. If it isn't the first use, then there is no action (other than to populate the dropdown).
This requires a combination of factors:detecting the dropdown, ensuring it is in the right sheet, column and row, determining whether the value has been used before and, if not, to create the new sheet. There are probably many ways that this might be done; consider the following just one example.
In this example, the relevant sheet to watch is "Sheet1", and the relevant column is "Column A". There is one header row, and there are dropdown cells in the rows below the header row.
The logic flow is:
use a simple onEdit(e) trigger to detect data entry.
use Event objects to determine the edited column, row, sheet name and value.
use other variables to manage the number of header rows, and the relevant column to watch.
create an IF statement to confirm that the edit was in the relevant sheet, column and row, then
get the range and values in Column A - include row 1 so that setValues() will always apply
flatten the resulting 2D array to 1D using the Javascript map method
find the first and last occurence of the dropdown value in the range using Javascript indexOf and lastIndexOf
if the first and last values are the same, then this must be the first and only use of the dropdown value, so create a new sheet insertSheet(sheetName) where "sheetname" is the dropdown value.
function onEdit(e){
//so5842003001
var ss = SpreadsheetApp.getActiveSpreadsheet()
var sheetname = "Sheet1";
var sheet = ss.getSheetByName(sheetname);
//Logger.log(JSON.stringify(e));//DEBUG
var eColumn = e.range.getColumn();
var eRow = e.range.getRow();
var eSheet = e.source.getSheetName();
var eValue = e.value;
var headerrow = 1; // number of header rows
var column = 1; // the data validation is in Column A
//Logger.log("DEBUG: column = "+eColumn+", sheet = "+eSheet+", Row = "+eRow+", header = "+headerrow);
if (sheetname === eSheet && eColumn === column && eRow > headerrow){
// column. row, and sheet are OK
// Logger.log("DEBUG: running the if");
//get the last row
var rows = sheet.getLastRow();
// Logger.log("DEBUG: last row = "+rows);
//define the range
var columnRange = sheet.getRange(1, column, rows);
// Logger.log("DEBUG: range = "+columnRange.getA1Notation());
// get the values
var columnvalue = columnRange.getValues();
// Logger.log(columnvalue); // DEBUG
// flatten the 2D array to 1D
var column1D= columnvalue.map(function(d){return d[0];});//[[d],[d],[d]]=>[d,d,d]
// Logger.log(column1D);// DEBUG
// get the first time this value appears in the range
var result = column1D.indexOf(eValue);
// get the last time this value appears in the range
var lastresult = column1D.lastIndexOf(eValue);
// Logger.log("DEBUG: result = "+result+", lastresult = "+lastresult)
// if the first time equals the last time, then this must be the first time it has appeared
// so insert the sheet
if (result === lastresult){
//Logger.log("first use of this value"); // DEBUG
// insert the sheet named for the cell
ss.insertSheet(eValue);
}
}
else {
// Logger.log("DEBUG: running the else");
}
}
Screenshot of answer layout

Find string and get its column

Let's say I have a lot of columns and one of them contains "impressions" string (on row 3). What I need to do is to:
1) Find the cell with "impressions" string
2) Get column number or i.e. "D"
3) Based on what I got paste a formula into i.e. D2 cell which gets AVERAGE from a range D4:D*last*
I couldn't find it anywhere so I have to ask here without any "sample" code, since I have no idea on how to achieve what I want. (3rd one is easy but I need to get that "D" first)
There's no way to search in Google Apps Script. Below is a function that will accomplish the first 2 parts for you (by iterating over every cell in row 3 and looking for "impressions"):
function findColumnNumber() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Sheet1'); // insert name of sheet here
var range = sheet.getDataRange(); // get the range representing the whole sheet
var width = range.getWidth();
// search every cell in row 3 from A3 to the last column
for (var i = 1; i <= width; i++) {
var data = range.getCell(3,i)
if (data == "impressions") {
return(i); // return the column number if we find it
}
}
return(-1); // return -1 if it doesn't exist
}
Hopefully this will allow you to accomplish what you need to do!
The indexOf method allows one to search for strings:
function findColumnNumber() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet() //whatever tab the code is run on
var data = sheet.getDataRange().getValues();
var header_row_num = 1; // TODO: change this to whichever row has the headers.
var header = data[header_row_num -1] //Remember JavaScript, like most programming languages starts counting (is indexed) at 0. For the value of header_row_num to work with a zero-index counting language like JavaScript, you need to subtract 1
//define the string you want to search for
var searchString = "impressions";
//find that string in the header and add 1 (since indexes start at zero)
var colNum = header.indexOf(searchString) + 1;
return(colNum);