Google Sheets - Two-way lookup pulling data from multiple sheet tabs - google-apps-script

I've been working on a sheet where I want to have and input tab and output tab.
The input tab is basically a table and the output tab will be a calendar (of sorts).
In my example:
Sheet1 = input tab
Sheet2 = output tab
I wish to have a vlookup that will pull its search_key from Sheet2 (output) and search it against a range in Sheet1.
I've been messing around with the following (green cell Sheet2 in example):
=IFERROR(VLOOKUP(A2,Sheet1!$A$2:$C$7,MATCH(B1,Sheet1!$A$2:$C$7,0),False))
I had also tried a variation of this using hlookup instead of MATCH but didn't have much luck with it.
The problem I have is that I no longer know where to place my column index. In my example sheet I have it working with a one way vlookup (blue cell Sheet2) that returns the desired value from Sheet1 (Length Column) using this index. Is it not possible to do so in the two way lookup??
Here's a link to the example:
https://docs.google.com/spreadsheets/d/1_nqH-XOxNhQAUVJzesNBZeMci7AV9RowSQUnptAruPc/edit?usp=sharing

Try running this function in Apps Script:
function myFunction() {
var ss = SpreadsheetApp.getActive();
var sheet1 = ss.getSheetByName('Sheet1');
var sheet2 = ss.getSheetByName('Sheet2');
var firstRow = 2;
var numRows = sheet1.getLastRow() - 1;
var firstCol = 1;
var numCols = sheet1.getLastColumn();
var inputData = sheet1.getRange(firstRow, firstCol, numRows, numCols).getValues();
var numBrands = sheet2.getLastRow();
var outputRange = sheet2.getDataRange();
var outputData = outputRange.getValues();
// Iterating through each row in Sheet1 data:
for(var i = 0; i < numRows; i++) {
// Iterating through each row in Sheet2:
for(var j = 1; j < outputData.length; j++) {
// Iterates through each cell for each row in Sheet2.
for(var k = 1; k < outputData[0].length; k++) {
var inputBrand = inputData[i][0];
var outputBrand = outputData[j][0];
var inputDate = inputData[i][1];
var outputDate = outputData[0][k];
// It checks whether the date and brand corresponding to each cell
// (same row or column) matches the date and brand in the current
// row in Sheet1
if(inputBrand == outputBrand && inputDate.toString() == outputDate.toString()) {
var inputLength = inputData[i][2];
sheet2.getRange(j+1, k+1, 1, 1).setValue(inputLength);
}
}
}
}
}

Related

Google Sheets - Expand Single Date Variable into a Date Range Within A Script

Been working on a sheet that started out as a vlookup and match function but with the help of user Iamblichus grew into a script. The script pulls data from a table on Sheet1 and matches and populates it on a calendar on Sheet2. I was trying to adjust the script a little to expand on the data it pulls from Sheet1. Currently it is able to recognize a single date from Sheet1 (column b) but I'd like to be able to change that single date variable into a date range so that the value in Sheet1 column c (Length) is populated within the date range on the calendar on Sheet2.
Here's what the script currently looks like:
function onEdit() {
var ss = SpreadsheetApp.getActive();
var sheet1 = ss.getSheetByName('Sheet1');
var sheet2 = ss.getSheetByName('Sheet2');
var firstRow = 2;
var numRows = sheet1.getLastRow() - 1;
var firstCol = 1;
var numCols = sheet1.getLastColumn();
var inputData = sheet1.getRange(firstRow, firstCol, numRows, numCols).getValues();
var numBrands = sheet2.getLastRow();
var outputRange = sheet2.getDataRange();
var outputData = outputRange.getValues();
for(var i = 0; i < numRows; i++) {
for(var j = 1; j < outputData.length; j++) {
for(var k = 1; k < outputData[0].length; k++) {
var inputBrand = inputData[i][0];
var outputBrand = outputData[j][0];
var inputDate = inputData[i][1];
var outputDate = outputData[0][k];
if(inputBrand == outputBrand && inputDate.toString() == outputDate.toString()) {
var inputLength = inputData[i][2];
sheet2.getRange(j+1, k+1, 1, 1).setValue(inputLength);
}
}
}
}
}
Here's a link to my example single date sheet where the script works as intended:
https://docs.google.com/spreadsheets/d/13VMZJ7SZQJs8l-fJjn1RX5BVsqPY2qiS4bT_7jwmuWo/edit?usp=sharing
Here is an example of the date range I want to implement in Sheet1 and the script not working:
https://docs.google.com/spreadsheets/d/1ie9c0AKsCA7MmYBBB81eW5BwnOM_d63kqxc2Fi3uyt8/edit?usp=sharing
I want to expand the script to be able recognize the date range set between the "Start Date" and "End Date". Then pull the value from "Length" columns in Sheet1 and fill the "Length" column value within the Date Range on Sheet2.

Update replace values from one sheet to another google script

I'm trying to figure out how to update rows if they are found in sheet1 with data from sheet2 based on a key column. Also if the key is not found then add a new row. I have figured out iterating over the range from sheet2, but not how to lookup the value in sheet1. Any suggestions welcome. (I upddated the post here.)
function getJulaUpdates2() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = ss.getSheetByName("Franco-Jula");
var range1 = sheet1.getDataRange();
var values1 = range1.getValues()
var sheet2 = ss.getSheetByName("Jula-Alternatives");
var range2 = sheet2.getDataRange();
var values2 = range2.getValues()
// Iterate through sheet2
// Start at 1 to avoid header row
for (var i = 1; i < values2.length; i++) {
// Now loop through Values1 sheet
for (var x = 1; x < values1.length; x++) {
logthis = values2[i][0] + "," + values1[x][1];
if (values1[x][1] == values2[i][0]) {
values1[x][2] = values2[i][2]
values1[x][12] = values2[i][12]
values1[x][13] = values2[i][13]
Logger.log(logthis);
}
}
}
range1.setValues(values1)
}

Merging google sheets: match with specific col values and merge data in 2 different sheets

I would like to ask if there is any possible way to set up a simple version of app script that is similar to the below add-ons.
https://chrome.google.com/webstore/detail/merge-sheets/gdmgbiccnalapanbededmeiadjfbfhkl?utm_source=ablebits
Basically, I've got sheet 1 and sheet 3, both sheets will have a common key column with specific values in each cell, and I would like to map both sheets with the data in that column then update the whole row data in the other sheets (For example, if i updated the sheet 3 then it map that col value in sheet 1, then paste the data in the corresponding row)
I have came up with a code that runs but no changes have been made, could anyone please advise how can I modify it to a simple version similar to the above add-ons? Thanks in advance.
I would like to populate the date from sheet 3 to sheet 1 after the code run, while the data from col C is matched in both sheets, please see example below, thanks!
For example, the data in sheet 1 highlighted row is having its key col with col C for common lookup value with sheet 3 while the row sequence is diff with sheet 3 (Please see the next photo, thanks!)
As you can see in sheet 3, the data of the whole row is inserted to the correct row according to the col C key col value which matched with sheet 1.
function myFunction2(){
// Get your spreadsheet and the sheets "TB" and "2"
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = ss.getSheetByName("Sheet 1");
var sheet3 = ss.getSheetByName("Sheet 3");
// Get the range on sheet "TB"
var tabsheet1 = sheet1.getRange(2, 2, sheet1.getLastRow(),
sheet1.getLastColumn());
// Get the values to compare
var datasheet1 = tabsheet1.getValues();
var datasheet3 = sheet3.getRange(2, 2, sheet3.getLastRow(), sheet3.getLastColumn());
for(var i = 0; i < datasheet1.length; i++){
for(var j = 0; j < datasheet3.length; j++){
// Compare data: if they're the same, put the value
if(datasheet1[i][0]=(datasheet3[j][0]) == 0){
//if(datasheet1[i][0].localeCompare(datasheet3[j][0]) == 0){
datasheet1[i][1] = datasheet3[j][1];
}
}
}
// Take the modified tab and put it on the spreadsheet
tabsheet1.setValues(datasheet1);
}
You want to copy the data of sheet 3 to sheet 1. For this situation, when the values of column C of sheet 3 and sheet 1 is the same, you want to copy the row of sheet 3 to sheet 1, because the order of rows for sheet 3 and sheet 1 are different. If my understanding is correct, how about this modification?
Modification points :
In order to retrieve the values from column C to last column, it uses getRange(2, 3, sheet1.getLastRow(), sheet1.getLastColumn()).
In your script, datasheet3 is the range.
About if(datasheet1[i][0]=(datasheet3[j][0]) == 0){, in order to comare the date, I used getDisplayValues().
By this, the values retrieved as a string are compared.
Modified script :
function myFunction2(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = ss.getSheetByName("Sheet 1");
var sheet3 = ss.getSheetByName("Sheet 3");
var tabsheet1 = sheet1.getRange(2, 3, sheet1.getLastRow(), sheet1.getLastColumn());
var datasheet1 = tabsheet1.getValues();
var datasheet1d = tabsheet1.getDisplayValues(); // Added
var tabsheet3 = sheet3.getRange(2, 3, sheet3.getLastRow(), sheet3.getLastColumn()); // Added
var datasheet3 = tabsheet3.getValues(); // Modified
var datasheet3d = tabsheet3.getDisplayValues(); // Added
for (var i = 0; i < datasheet1.length; i++) {
for (var j = 0; j < datasheet3.length; j++) {
if (datasheet1d[i][0] == datasheet3d[j][0]) { // Modified
datasheet1[i] = datasheet3[j]; // Modified
}
}
}
tabsheet1.setValues(datasheet1);
}
Reference :
getDisplayValues()
If I misunderstand your question, please tell me. I would like to modify it. At that time, in order to modify, can you share the sample sheet? Of course, please remove your private information from it.
Edit 1 :
function myFunction2(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = ss.getSheetByName("Sheet 1");
var sheet3 = ss.getSheetByName("Sheet 3");
var tabsheet1 = sheet1.getRange(2, 3, sheet1.getLastRow() - 1, sheet1.getLastColumn() - 2); // Modified
var datasheet1 = tabsheet1.getValues();
var datasheet1d = tabsheet1.getDisplayValues(); // Added
var tabsheet3 = sheet3.getRange(2, 3, sheet3.getLastRow() - 1, sheet3.getLastColumn() - 2); // Added
var datasheet3 = tabsheet3.getValues(); // Modified
var datasheet3d = tabsheet3.getDisplayValues(); // Added
for (var i = 0; i < datasheet1.length; i++) {
for (var j = 0; j < datasheet3.length; j++) {
if (datasheet1d[i][0] == datasheet3d[j][0]) { // Modified
datasheet3[j].push(""); // Modified
datasheet1[i] = datasheet3[j]; // Modified
}
}
}
tabsheet1.setValues(datasheet1);
}
Edit 2 :
function myFunction2(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = ss.getSheetByName("comment_log");
var sheet3 = ss.getSheetByName("CM");
var tabsheet1 = sheet1.getRange(2, 3, sheet1.getLastRow() - 1, sheet1.getLastColumn() - 2); // Modified
var datasheet1 = tabsheet1.getValues();
var datasheet1d = tabsheet1.getDisplayValues(); // Added
var tabsheet3 = sheet3.getRange(2, 3, sheet3.getLastRow() - 1, sheet3.getLastColumn() - 2); // Added
var datasheet3 = tabsheet3.getValues(); // Modified
var datasheet3d = tabsheet3.getDisplayValues(); // Added
for (var i = 0; i < datasheet1.length; i++) {
for (var j = 0; j < datasheet3.length; j++) {
if (datasheet1d[i][0] == datasheet3d[j][0]) { // Modified
if (datasheet1[i].length != datasheet3[j].length) {
for (var k = 0; k < datasheet1[i].length - datasheet3[j].length; k++) {
datasheet3[j].push(datasheet1[i][datasheet1[i].length - 1]);
}
}
datasheet1[i] = datasheet3[j]
}
}
}
tabsheet1.setValues(datasheet1);
}

google script note row colorGoogle Script row color detector

I need a little assistance writing a google script function.
I have a Google Sheet where each individual row may have a different color assigned to it.
I need a script that can note the html color code found in the first cell of each row, in that cell.
So for example lets say row 1 is a green row and row 2 is a blue row, the cell A1 should say #00ff00 and A2 should say #0000ff after running the script. Below is what I have so far.
function colorDetector() {
var startRow = 1; // First row of data to process
var numRows = 3; // Number of rows to process
var currentsheet = 'Production' // What sheet you would like to process (must be within ' ')
//This section prepares the document to be read
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName(currentsheet);
var dataRange = sheet.getRange(startRow, 1, numRows, 15) // Fetch values for each row in the Range (row, column, numRows, numColumns)
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
//this is the section i cant seem to get working correctly
var color = row[0].getbackground(); //should set the variable "color" to the html color found in the first cell of the current row.
sheet.getRange(startRow + i, 1).setValue(color); // notes the variable found
SpreadsheetApp.flush();
}
}
Here is what I ended up figuring out on my own. It works perfectly.
function colorDetector2() {
var startRow = 1; // First row of data to process
var currentsheet = 'sheet 4' // What sheet you would like to process (must be within ' ')
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName(currentsheet);
var numRows = 10; // Number of rows to process
var dataRange = sheet.getRange(startRow, 1, numRows, 20) // Fetch values for each row in the Range (row, column, numRows, numColumns)
var colordata = dataRange.getBackgrounds();
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var color = colordata[i]
var colorconv = String(color[1]);
if (colorconv == "#00ff00") {
//do something here;
} else {
//do something else here;
}
}
}

Google Apps Script - Find Row number based on a cell value

I'm looking for some assistance on find the row number for a cell that contains a specific value.
The spreadsheet has lots of data across multiple rows & columns. I'm looping over the .getDataRange and can located the cell containing the value I'm looking for. Once found I'd like to know the row that his cell is in, so that I can further grab additional cell values since I know exactly how many rows down and/or columns over the additional information is from the found cell.
Here is a bit of the code for finding the cell containing a specific string.
function findCell() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var dataRange = sheet.getDataRange();
var values = dataRange.getValues();
for (var i = 0; i < values.length; i++) {
var row = "";
for (var j = 0; j < values[i].length; j++) {
if (values[i][j] == "User") {
row = values[i][j+1];
Logger.log(row);
}
}
}
}
When outputting Logger.log(row) it gives me the values I'm looking for. I want to determine what row each value is in, so I can then go down X number of rows and over X columns to get the contents of other cells.
I don't know much about google apps but it looks like [i] is your row number in this circumstance.
So if you did something like:
function findCell() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var dataRange = sheet.getDataRange();
var values = dataRange.getValues();
for (var i = 0; i < values.length; i++) {
var row = "";
for (var j = 0; j < values[i].length; j++) {
if (values[i][j] == "User") {
row = values[i][j+1];
Logger.log(row);
Logger.log(i); // This is your row number
}
}
}
}
This method finds the row number in a particular column for a given value:
function rowOf(containingValue, columnToLookInIndex, sheetIndex) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets();
var dataRange = sheet[sheetIndex].getDataRange();
var values = dataRange.getValues();
var outRow;
for (var i = 0; i < values.length; i++)
{
if (values[i][columnToLookInIndex] == containingValue)
{
outRow = i+1;
break;
}
}
return outRow;
}
But if you do it like that, it won't refresh unless you change any of the parameters, that's because a custom function should be deterministic, that is, for the same parameters, it should always give the same result.
So instead, it's better to do it this way:
function rowOf(containingValue, range) {
var outRow = null;
if(range.constructor == Array)
{
for (var i = 0; i < range.length; i++)
{
if(range[i].constructor == Array && range[i].length > 0)
{
if (range[i][0] == containingValue)
{
outRow = i+1;
break;
}
}
}
}
return outRow;
}
In this case, you need to pass the full column range your looking for like so:
rowOf("MyTextToLookFor", 'MySheetToLookIn'!A1:A)
Where you would replace A by the colum of your choice, and MySheetToLookIn by your sheet's name and MyTextToLookFor by the text you are looking for.
This will allow it to refresh on adding rows and removing rows.
Since 2018 this can be done without a loop using flat().
function findRow(searchVal) {
var sheet = SpreadsheetApp.getActiveSheet();
var data = sheet.getDataRange().getValues();
var columnCount = sheet.getDataRange().getLastColumn();
var i = data.flat().indexOf(searchVal);
var columnIndex = i % columnCount
var rowIndex = ((i - columnIndex) / columnCount);
Logger.log({columnIndex, rowIndex }); // zero based row and column indexes of searchVal
return i >= 0 ? rowIndex + 1 : "searchVal not found";
}
ES6 gave us a one liner for this (but expanded for full detail).
function findRow() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss. getActiveSheet(); // OR GET DESIRED SHEET WITH .getSheetByName()
const dataRange = sheet.getDataRange();
const values = dataRange.getValues();
const columnIndex = 3 // INDEX OF COLUMN FOR COMPARISON CELL
const matchText = "User"
const index = values.findIndex(row => row[columnIndex] === matchText)
const rowNumber = index + 1
return rowNumber
}
This can be done with the Text Finder:
function findRow(searchValue){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var thisSheet = ss.getActiveSheet();
var tf = thisSheet.createTextFinder(searchValue)
var thisRow = tf.findNext().getRow()
return thisRow
}
Discovered through this post: Google App Scripts find text in spreadsheet and return location index
Implementing: https://developers.google.com/apps-script/reference/spreadsheet/text-finder
To find a row in a Google Sheets sheet based on the value of a specific column (in this case, the invoice_id column) and edit another column (in this case, the send column) in that row, you can use the following script:
// Replace "Sheet1" with the name of your sheet
var sheet = SpreadsheetApp.getActive().getSheetByName("Sheet1");
// Replace "A" with the column letter for the invoice_id column
// and "B" with the column letter for the send column
var invoiceIdColumn = "A";
var sendColumn = "B";
// Replace "12345" with the invoice_id you want to search for
var invoiceIdToSearch = "12345";
// Find the row number of the row with the matching invoice_id
var data = sheet.getDataRange().getValues();
var row = data.findIndex(row => row[invoiceIdColumn - 1] == invoiceIdToSearch) + 1;
// If a row with the matching invoice_id was found
if (row) {
// Set the value of the send column in that row to "true"
sheet.getRange(row, sendColumn).setValue(true);
}
This script will search through the entire sheet for a row with an invoice_id value that matches the invoiceIdToSearch variable, and then set the value of the send column in that row to true.
Note that this script assumes that the invoice_id column is the first column in the sheet (column A) and the send column is the second column (column B). If your columns are in different positions, you will need to adjust the invoiceIdColumn and sendColumn variables accordingly.