Find value on any sheet in spreadsheets using Google Script - search

Using the code below I'm able to look through multiple sheets in a spreadsheet to find the first value that equals the selected cell. The only problem with this bit is: The cell with the value found is highlighted yellow, but the cell with the value found isn't selected. See code below for hopping through sheets. I can't get my head around this :)
Funny thing is that the code for highlighting and selecting a value does work when I'm not hopping through the list of sheets, see the best answer: Find value in spreadsheet using google script
function SearchAndFind() {
//determine value of selected cell
var sh = SpreadsheetApp.getActiveSpreadsheet();
var ss = sh.getActiveSheet();
var cell = ss.getActiveCell();
var value = cell.getValue();
//create array with sheets in active spreadsheet
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
//loop through sheets to look for value
for (var i in sheets) {
//Set active cell to A1 on each sheet to start looking from there
SpreadsheetApp.setActiveSheet(sheets[i])
var sheet = sh.getActiveSheet();
var range = sheet.getRange("A1");
sheet.setActiveRange(range);
//set variables to loop through data on each sheet
var activeR = cell.getRow()-1;
var activeC = cell.getColumn()-1;
var data = sheets[i].getDataRange().getValues()
var step = 0
//loop through data on the sheet
for(var r=activeR;r<data.length;++r){
for(var c=activeC;c<data[0].length;++c){
step++
Logger.log(step+' -- '+value+' = '+data[r][c]);
if(data[r][c]==''||step==1){ continue };
if(value.toString().toLowerCase()==data[r][c].toString().toLowerCase()){
sheet.getRange(r+1,c+1).activate().setBackground('#ffff55');
return;
}
}
}
}
}

This code is able to search across multiple sheets, it is obviously based on your published code but uses a memory (scriptProperties) to keep the search value 'alive' when changing from one sheet to the next one and to know when to search for it.
It has 2 non-optimal aspects : 1° you have to keep searching up to the last occurrence before you can begin a new search.
2° : when it switches from sheet n to sheet n+1 it first selects cell A1 before finding the value occurrence.
I guess it should be possible to get rid of these issues but right now I don't find how :-)
Maybe the approach is simply not the best, I started from a simple one sheet script modified and complexified... that's usually not the best development strategy (I know), but anyway, it was a funny experiment and a good logic exercise ...
Thanks for that.
function SearchAndFind() {
//determine value of selected cell
var sh = SpreadsheetApp.getActiveSpreadsheet();
var ss = sh.getActiveSheet();
var cell = ss.getActiveCell();
var value = cell.getValue();
if(ScriptProperties.getProperty('valueToFind')!=''){value = ScriptProperties.getProperty('valueToFind')};
//create array with sheets in active spreadsheet
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets()
var sheetNumber = sheets.length;
var currentSheet = ss.getIndex()-1;
Logger.log(currentSheet);
//loop through sheets to look for value
for (var i = currentSheet ; i<sheetNumber ; ++i ){
Logger.log('currentSheet = '+i)
//Set active cell to A1 on each sheet to start looking from there
SpreadsheetApp.setActiveSheet(sheets[i])
// sheets[i].getRange(1,1).activate();
//set variables to loop through data on each sheet
var activeR = cell.getRow()-1;
var activeC = cell.getColumn()-1;
var data = sheets[i].getDataRange().getValues()
var step = 0;
//loop through data on sheet
for(var r=activeR;r<data.length;++r){
for(var c=activeC;c<data[0].length;++c){
step++
Logger.log('sheet : '+i+' step:'+step+' value '+value+' = '+data[r][c]);
if(data[r][c]==''||(step==1&&i==currentSheet)){ continue };
if(value.toString().toLowerCase()==data[r][c].toString().toLowerCase()){
sheets[i].getRange(r+1,c+1).activate().setBackground('#ffff55');
ScriptProperties.setProperty('valueToFind',value);
return;
}
}
}
cell = sheets[i].getRange(1,1);
}
ScriptProperties.setProperty('valueToFind','');
Logger.log('reset');
}

Related

match single cell value with column of values for every match return those rows Google-apps-script

I have a spreadsheet with 2 tabbed sheets. I am trying to run a macro so that when the user inputs a name in B2 of the 2nd sheet, it is matched with every instance of that name in the 1st sheet, column B. I then need to copy all of the data that appears in the matched cell's rows and have that pasted in the 2nd sheet starting with cell B3.
I have limited experience with VBA, but none with JS/Google-apps-script. Any help with how to write this would be greatly appreciated! Here is my first shot:
function onSearch() {
// raw data sheet
var original = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Form Responses 2");
// search for student sheet
var filtered = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Student Progress Search");
// retrieving the values in the raw data array of names
var searchColumn = 2;
var lr = original.getLastRow();
var searchRange = original.getRange(2,searchColumn, lr, 1).getValues();
// retrieving the name submitted on search
var inputName = filtered.getRange(2, 2).getValue();
// loop through all the names in the raw data and identify any matches to the search name
for (var i = 0; i < lr; i++){
var dataValue = searchRange[i];
var r = dataValue.getRow();
var line = [[r]];
var paste = filtered.getRange(3, 3);
// if the data is a match, return the value of that cell in the searched sheet
if (dataValue == inputName){ return paste.setValues(line);
}
}
}
Not sure if the built-in QUERY function would work for you. This here does exactly what you are looking for:
=QUERY(Sheet1!B:B,"select B where LOWER(B) like LOWER('%" &B2& "%')")
For example, if a user enters 'joe', the function will match any entry containing 'joe', regardless of case.

auto copy value of cell from sheet 2 to sheet 1 using google apps script

I’m trying to get the value of column Notes in Sheet 2 and put it to column Notes of Sheet 1. To do that, they should have the same column Company value. When I enter a value in Company (Sheet 2), the code will find if it has the same value in Company (Sheet 1). If the code finds the same value of Company, the value in Notes (Sheet 2) that I enter will automatically put in Notes (Sheet 1). I used the if/else statement in my code but it is not running.
Any help would be greatly appreciated.
Ex:
Sheet 1
enter image description here
Sheet 2
enter image description here
Here's my code :)
function onEdit() {
var sheetId = SpreadsheetApp.openById('1fx59GrC_8WEU5DCM5y2N8YR3PK936RLqZVknQ66WWUA'); //replace with source ID
var sourceSheet = sheetId.getSheetByName('Notes'); //replace with source Sheet tab name
var notesActiveCell = sourceSheet.getActiveCell();
var notesRow = notesActiveCell.getRow();
var notesComp = SpreadsheetApp.getActiveSheet().getRange('B' + notesRow.toString());
var destSheet = sheetId.getSheetByName('Companies'); //replace with destination Sheet tab name
var compActiveCell = destSheet.getActiveCell();
var compRow = compActiveCell.getRow();
var companies = SpreadsheetApp.getActiveSheet().getRange('B' + compRow.toString());
if (notesComp.getValues() == companies.getValues()) {
Logger.log(notesComp.getValues());
var sourceRange = SpreadsheetApp.getActiveSheet().getRange('C' + notesRow.toString()); //assign the range you want to copy
var notesData = sourceRange.getValues();
destSheet.getRange('F' + compRow.toString()).setValues(notesData);
}
}
There are a lot of errors in your code. I'm not a very experienced programmer, but form what you have said I think the script below should give you a good starting point.
Don't forget, you also need to add an onEdit trigger to run the script when you enter a value.
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheet = ss.getActiveSheet();
var sourceCellRow = sourceSheet.getActiveCell().getRowIndex();
var sourceData = sourceSheet.getRange(sourceCellRow, 1, 1, 2).getValues();
var destSS = SpreadsheetApp.openById('Paste destination Spreadsheet ID here');
var destSheet = destSS.getSheetByName('Companies');
var searchData = destSheet.getRange(1, 1, destSheet.getLastRow()).getValues();
for (var i = 0; i < searchData.length; i ++){
if(searchData[i][0] == sourceData[0][0]){
destSheet.getRange(i + 1, 2).setValue(sourceData[0][1]);
break;
}
}
}
Try using the copyTo(destination)
Copies the data from a range of cells to another range of cells. Both the values and formatting are copied.
// The code below will copy the first 5 columns over to the 6th column.
var sheet = SpreadsheetApp.getActiveSheet();
var rangeToCopy = sheet.getRange(1, 1, sheet.getMaxRows(), 5);
rangeToCopy.copyTo(sheet.getRange(1, 6));
}
I think that will be invaluable inside your onEdit() function.\
You might also want to check this sample from this google forum
function Copy() {
var sss = SpreadsheetApp.openById('spreadsheet_key'); //replace with source ID
var ss = sss.getSheetByName('Source'); //replace with source Sheet tab name
var range = ss.getRange('A2:E6'); //assign the range you want to copy
var data = range.getValues();
var tss = SpreadsheetApp.openById('spreadsheet_key'); //replace with destination ID
var ts = tss.getSheetByName('SavedData'); //replace with destination Sheet tab name
ts.getRange(ts.getLastRow()+1, 1,5,5).setValues(data); //you will need to define the size of the copied data see getRange()
}

How to make Google form submission sort into separate sheets?

I can only get this to sort automatically when I input the text manually into the cell. I've tried changing to OnFormSubmit but no luck. How can I rewrite this to have Google Docs automatically sort the form-submitted answers to separate tabs?
function onEdit(event) {
// assumes source data in sheet named Needed
// target sheet of move to named Acquired
// test column with yes/no is col 4 or D
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = SpreadsheetApp.getActiveSheet();
var r = SpreadsheetApp.getActiveRange();
if(s.getName() == "Inbox" && r.getColumn() == 6 && r.getValue() == "Los Angeles") {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Los Angeles");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row)
}
}
Dont write the sorted sheet data manually. Instead use a single QUERY formula per sheet. With it you can filter sort grouo and pivot your data as you like.

Find value in spreadsheet using google script

Situation:
1 spreadsheet
multiple sheets
1 cell selected (may vary)
What I'd like to do is to find and set focus to the next cell in any sheet that matches the selected cell (case insensitive) upon clicking a button-like image in the spreadsheet. Sort of like a custom index MS Word can create for you.
My approach is:
- set value of the selected cell as the variable (succeeded)
- find the first cell that matches that variable (not the selected cell) (no success)
- set value of found cell as variable2 (no success)
- set the focus of spreadsheet to variable2 (no success)
function FindSetFocus()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var activecell = sheet.getActiveCell();
var valueactivecell = activecell.getValue();
//here comes the code :)
}
I have found this snippet in the following topic, but I'm having a little trouble setting the input and doing something with the output: How do I search Google Spreadsheets?
I think I can replace 'value' with 'valueactivecell', but I don't know how to set the range to search through all sheets in the spreadsheet. Also, I'd like the output to be something I can set focus to using something like 'ss.setActiveSheet(sheet).setActiveSelection("D5");'
/**
* Finds a value within a given range.
* #param value The value to find.
* #param range The range to search in.
* #return A range pointing to the first cell containing the value,
* or null if not found.
*/
function find(value, range) {
var data = range.getValues();
for (var i = 0; i < data.length; i++) {
for (var j = 0; j < data[i].length; j++) {
if (data[i][j] == value) {
return range.getCell(i + 1, j + 1);
}
}
}
return null;
}
also found this but no luck on getting it to work on the selected cell and setting focus: How do I search for and find the coordinates of a row in Google Spreadsheets best answer, first code.
Please bear in mind that I'm not a pro coder :) If code samples are provided, please comment inline hehe.
Thanks in advance for any help.
Edit 24/10: Used the code from the answer below and edited it a bit. Now able to look through multiple sheets in a spreadsheet to find the value. The only problem with this bit is: My cell is highlighted yellow, but the cell with the value found isn't selected. See code below for hopping through sheets. I can't get my head around this :)
function SearchAndFind() {
//determine value of selected cell
var sh = SpreadsheetApp.getActiveSpreadsheet();
var ss = sh.getActiveSheet();
var cell = ss.getActiveCell();
var value = cell.getValue();
//create array with sheets in active spreadsheet
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
//loop through sheets to look for value
for (var i in sheets) {
//Set active cell to A1 on each sheet to start looking from there
SpreadsheetApp.setActiveSheet(sheets[i])
var sheet = sh.getActiveSheet();
var range = sheet.getRange("A1");
sheet.setActiveRange(range);
//set variables to loop through data on each sheet
var activeR = cell.getRow()-1;
var activeC = cell.getColumn()-1;
var data = sheets[i].getDataRange().getValues()
var step = 0
//loop through data on the sheet
for(var r=activeR;r<data.length;++r){
for(var c=activeC;c<data[0].length;++c){
step++
Logger.log(step+' -- '+value+' = '+data[r][c]);
if(data[r][c]==''||step==1){ continue };
if(value.toString().toLowerCase()==data[r][c].toString().toLowerCase()){
sheet.getRange(r+1,c+1).activate().setBackground('#ffff55');
return;
}
}
}
}
}
Here is an example of such a function, I inserted a drawing in my spreadsheet representing a button which I assigned the script so it's easy to call.
I added a feature to set a light yellow background on the resulting selected cell so it's easier to see the selected cell but this is optional.
Code
function findAndSelect(){
var sh = SpreadsheetApp.getActiveSpreadsheet();
var ss = sh.getActiveSheet();
var cell = ss.getActiveCell();
cell.setBackground('#ffff55');// replace by cell.setBackground(null); to reset the color when "leaving" the cell
var activeR = cell.getRow()-1;
var activeC = cell.getColumn()-1;
var value = cell.getValue();
var data = ss.getDataRange().getValues();
var step = 0
for(var r=activeR;r<data.length;++r){
for(var c=activeC;c<data[0].length;++c){
step++
Logger.log(step+' -- '+value+' = '+data[r][c]);
if(data[r][c]==''||step==1){ continue };
if(value.toString().toLowerCase()==data[r][c].toString().toLowerCase()){
ss.getRange(r+1,c+1).activate().setBackground('#ffff55');
return;
}
}
}
}
Caveat
This code only searches 'downwards', i.e. any occurrence in a row that would precede the selected cell is ignored, same for columns...
If that's an issue for you then the code should be modified to start iterating from 0. But in this case if one need to ignore the initial starting cell then you should also memorize its coordinates and skip this value in iteration.

Get and use user data from another sheet in Google Docs

We use google spreadsheets for reporting by quite a big number of users.
I have written a basic script, which opens a specific sheet depending on the current user:
var CurrentUser = Session.getUser().getEmail()
var ss = SpreadsheetApp.getActive();
switch(CurrentUser){
case "usermail1#gmail.com":
SpreadsheetApp.setActiveSheet(ss.getSheetByName("sheet1"));
break;
case "usermail2#gmail.com":
SpreadsheetApp.setActiveSheet(ss.getSheetByName("sheet2"));
break;
case "usermail3#gmail.com":
SpreadsheetApp.setActiveSheet(ss.getSheetByName("sheet3"));
break;
etc...
I would like to put the userdata and sheetnames into an external table and get these data depending on that table, so it is easier to maintain the list of e-mails and users.
How can I get data from a specific google spreadsheet and let the script work according to that?
You can try this. It simulates a VLOOKUP on a different sheet and switches to the 'matched' sheet in your current workbook. This doesn't handle non-matches, but that should be relatively straightforward to add to suit your case.
function switchSheets() {
// Current sheet
var ss = SpreadsheetApp.getActive();
// Target sheet (using the key found in the URL)
var target = SpreadsheetApp.openById("my_other_sheet_id");
var rows = target.getDataRange();
var values = rows.getValues();
// Get the current user
var CurrentUser = Session.getUser().getEmail();
// Now iterate through all of the rows in your target sheet,
// looking for a row that matches your current user (this assumes that
// it will find a match - you'll want to handle non-matches as well)
for (var i = 1; i <= rows.getNumRows() - 1; i++) {
// Match the leftmost column
var row = values[i][0];
if (row == CurrentUser) {
// If we match, grab the corresponding sheet (one column to the right)
target_sheet = values[i][1];
break;
}
}
// Now switch to the matched sheet (rememeber to handle non-matches)
ss.setActiveSheet(ss.getSheetByName(target_sheet));
};

Resources