Updating a sheet with a value if strings match on two sheets - javascript

Sheet 2 has all the items and their statuses, while Sheet 1 has only some of the items from Sheet 2. I want to be able to see every time an item mentioned on Sheet 1 is listed as having a status update, i.e. e date, on Sheet 2.
Here's what I have so far, but having trouble calling the right range to work with. Is there a simpler way to do what I want to do?
function statusupdate() {
var activesht = SpreadsheetApp.getActiveSpreadsheet();
var statussht = activesht.getSheetByName("Sheet 2"); //get sheet on which status update occurs
var statusrng1 = statussht.getRangeByName('B');
var statusrng2 = statussht.getRangeByName('C');
var mainsht = activesht.getSheetByName("Sheet 1"); //get sheet where you show a specific thing has been updated, if that thing mentioned here.
var mainrng = mainsht.getRangeByName('F');
if (statusrng1 == mainrng) {
var date = statusrng2.getValue();
var daterng = mainrng.getRangeByName('E');
daterng.setValues(date);
}
}

Spreadsheet formula
You can have the rows in one sheet follow those in another without using a script. For example, say we have a sheet named Items that contains one row for every item we carry, with the item number in the first column.
We can use VLOOKUP() to search for the row containing info about individual items, and select specific columns from it.
For example, this formula would be used in B2, and could be copied to other cells in our sheet:
=VLOOKUP($A2,Items!$A$2:$C$7,COLUMN(),false)
Script
There are a few issues with your script.
.getRangeByName('B') - This method gets a named range. Given the name, I suspect you mean to get column B, and NOT a named range. If that's the case, you could use this instead:
var statusrng1 = statussht.getRange('B:B');
In A1Notation, the range B:B is the entire column B.
You intend to copy values, so there is another step required beyond identifying ranges; you need to first read the values from a range, and then later write them to a different range. For that, you need to use methods like getValues() and setValues().
Here's an updated version of your script, adapted to the example spreadsheet described above.
function statusupdate() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
//get sheet on which status update occurs
var statusSheet = ss.getSheetByName("Items");
var statusRange = statusSheet.getDataRange();
var statusData = statusRange.getValues();
//get sheet where you show a specific thing has been updated, if that thing mentioned here.
var trackingSheet = ss.getSheetByName("Tracking");
var trackingRange = trackingSheet.getDataRange();
var trackingData = trackingRange.getValues();
// Loop over all rows in the Tracking sheet to update from the Items sheet
// Start with row=1, because row 0 contains headers
for (var row=1; row<trackingData.length; row++) {
var item = trackingData[row][0];
if (item == '') continue; // skip rows without item #
// Look for item in Items sheet
var statusRow = null;
for (var sRow=1; sRow<statusData.length; sRow++) {
if (statusData[sRow][0] == item) {
// Found our match, grab that row
statusRow = statusData[sRow];
break;
}
}
// If we found a matching row, copy the status
if (statusRow) {
// Customize this depending on how your sheets are organized
trackingData[row][1] = statusRow[1];
trackingData[row][2] = statusRow[2];
}
}
// All values have been copied to trackingData, now write to sheet
trackingRange.setValues(trackingData);
}

Related

Google Script return value from one sheet to another sheet

This is my first Google Script and I'm struggling a little bit while trying to bring back the values from a specific cell & sheet to another sheet.
I have a total of 18 columns, being the first one the ID which is going to be the input that the user would need to add in order to retrieve the data from one sheet to another. As the first one is the ID, and will be already be inputted by the user, I would need to retrieve the data from columns 2 to 18
Here is my code:
function SearchID() {
var columnIndex = 0;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formS = ss.getSheetByName("Manual Costs App"); // App sheet
var str = formS.getRange("D6").getValue(); // The ID to search will be inputted here
var dataS = ss.getSheetByName("Inputs").getDataRange().getValues(); // Retrieving the data based on the user input
for (var i = 0; i<=dataS.length; i++) {
var row = dataS[i];
if (row[columnIndex] == str) {
formS.getRange("D9").setValue(row[1]);
formS.getRange("D13").setValue(row[2]);
formS.getRange("D14").setValue(row[3]);
formS.getRange("D15").setValue(row[4]);
formS.getRange("D16").setValue(row[5]);
formS.getRange("D18").setValue(row[6]);
formS.getRange("D19").setValue(row[7]);
formS.getRange("D20").setValue(row[8]);
formS.getRange("D21").setValue(row[9]);
formS.getRange("D22").setValue(row[10]);
formS.getRange("D23").setValue(row[11]);
formS.getRange("D25").setValue(row[12]);
formS.getRange("D26").setValue(row[13]);
formS.getRange("D27").setValue(row[14]);
formS.getRange("D28").setValue(row[15]);
formS.getRange("D29").setValue(row[16]);
formS.getRange("D30").setValue(row[17]);
break;
}
}
}
The link to a sample spreadsheet of what I'm building is here
Update: Everything is fixed now! What I did was removing the space in the for loop. After that, it retrieved the data but a TypeError: Cannot read property '0'. Also solved it adding a break after the loop to avoid it.
It's a type in your for loop, notice how spelled length:
for (var i = 1; i <= values.lenght; i++)
You also don't want to set values line by line like you do, get a longer range and set the values with setValues() rather than setValue(). There's quite a bit of refactoring to do there actually.
The user did found the answer and updated it on the question.
Posting here as community wiki so it can be seen more clearly.
User's answer:
Update: Everything is fixed now! What I did was removing the space in the for loop. After that, it retrieved the data but a TypeError: Cannot read property '0'. Also solved it adding a break after the loop to avoid it.
function SearchID() {
var columnIndex = 0;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formS = ss.getSheetByName("Manual Costs App"); // App sheet
var str = formS.getRange("D6").getValue(); // The ID to search will be inputted here
var dataS = ss.getSheetByName("Inputs").getDataRange().getValues(); // Retrieving the data based on the user input
for (var i = 0; i<=dataS.length; i++) {
var row = dataS[i];
if (row[columnIndex] == str) {
formS.getRange("D9").setValue(row[1]);
formS.getRange("D13").setValue(row[2]);
formS.getRange("D14").setValue(row[3]);
formS.getRange("D15").setValue(row[4]);
formS.getRange("D16").setValue(row[5]);
formS.getRange("D18").setValue(row[6]);
formS.getRange("D19").setValue(row[7]);
formS.getRange("D20").setValue(row[8]);
formS.getRange("D21").setValue(row[9]);
formS.getRange("D22").setValue(row[10]);
formS.getRange("D23").setValue(row[11]);
formS.getRange("D25").setValue(row[12]);
formS.getRange("D26").setValue(row[13]);
formS.getRange("D27").setValue(row[14]);
formS.getRange("D28").setValue(row[15]);
formS.getRange("D29").setValue(row[16]);
formS.getRange("D30").setValue(row[17]);
break;
}
}
}

how to change value in a range of cell to a data array in google AppScript?

How to pull data in a range of cell and then push those values into an array of data?
In this code I tried to get those values in range E2:E97 and then push those values to an array such as [E2 value, E3 Value, etc] then set value to database sheet using dataS.getRange(dataS.getLastRow()+1).setValue(value);
but it seems I can't get it done with those code. so any idea to do this?
// Save Data
function saveData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formS = ss.getSheetByName("newform");
var dataS = ss.getSheetByName("newdb");
var dataBaseNameColIndex = 1;
var formDataRange = ['E2:E97'];
var ui = SpreadsheetApp.getUi();
var response = ui.alert(
'Save Data ?',
ui.ButtonSet.YES_NO);
// Process the user's response.
if (response == ui.Button.YES) {
for (var i = 2; i < formDataRange.length; i++) {
var value = formS.getRange(formDataRange[i], 5).getValue();
dataS.getRange(dataS.getLastRow() + 1).setValue(value);
console.log(saveData);
}
}
}
Instead of trying to copy and paste data cell-by-cell, you may want to do it in one go. That would be more efficient.
So instead of:
var value = formS.getRange(formDataRange[i], 5).getValue();
you could use the following without the for loop:
var allValues = formS.getRange('E2:E97').getValues();
And then post the data to the new range like this:
dataS.getRange(dataS.getLastRow() + 1, 2, allValues.length, allValues[0].length).setValues(value);
I am assuming you want to paste the data into column 2 onwards. Adjust the 2nd value in getRange() above accordingly.
The 3rd and 4th values in getRange() above are the number of rows and columns to pasts.
allValues.length is the number of rows of data. In this case it would be 95.
and allValues[0].length would the number of columns in the top row of the data copied. And in this case it should be one.
I am suggesting this way as you won't need to keep fiddling with the number of rows and columns if you change the copy range dimensions later on.
PS:
dataS.getRange(dataS.getLastRow() + 1).setValue(value);
is missing the column number in getRange()

Looping through column untill empty row, looking up each value in different SS and return row position

I'm trying to accomplish somewhat of a database table editor that edits rows based on a Trans ID.
I've accomplished vlookups and return values with a vlookup similar script I have, but this time I need to return position and not value.
I need help on how to set this script flow up. I've drawn and wrote everything out on a picture, it was a lot easier to write out that way.
This is what I'm starting with and need some suggestions.
I want to return row position instead of value and repeat until hit first empty row as seen in example picture I attached.
function vlookup(sheet, column, index, value) {
var sheet = sheet
var lastRow= sheet.getLastRow();
var data=sheet.getRange(1,column,lastRow,column+index).getValues();
for(i=0;i<data.length;++i){
if (data[i][0]==value){
return data[i][index];
}
}
}
The row number is just the index of the array + 1 as arrays start at 0.
return i + 1;
Heres the script on how I accomplished the task.
function doit(){
var lastrow = gv.glr(gv.invhelper,"A") // global function getting last row of target/loop column
for (var i = 4; i < lastrow+1; i++){ //loop statement
// actions to repeat
var id = gv.invhelper.getRange("A"+i).getValue(); //get id from row
var duradj = gv.invhelper.getRange("D"+i).getValue(); //get billing adjustment from row
var dbidrow = gv.dblkup(id); // global function to lookup id and find row position in other ss
var invstat = gv.dbtimetest.getRange("G"+dbidrow).setValue('TRUE'); // set invoiced status
var billadjust = gv.dbtimetest.getRange("M"+dbidrow).setValue(duradj); // set billing adjustment
}
}

Compare multiple values in one array

I need some help determining how i can compare 4 columns of one row with 4 columns of another row.
To explain, I have two tables, which both have four columns: State, Area, City & Location.
PINPOINT table - this table has a unique combination of values
FEED table - this table has a recurring combination of values, as well as the KEY value from the PINPOINT Table.
What i want is a code that says
"If a row from column CL in the FEED sheet contains the Key Value from column K in the PINPOINT sheet,
...but columns CN to CQ that FEED sheet row doesn't have the same values as column A-D in the PINPOINT table...
update column CN to CQ the FEED sheet with the same combination of values as A-D in the PINPOINT table."
I pasted the latest code i have below, as well as the images. Admittedly, this code is a mess I just started learning code, so I'm happy to rewrite this if someone proposes a solution.
In any case, any insight into how i should write this will be quite helpful.
var Data = SpreadsheetApp.getActiveSpreadsheet(); // DATA spreadsheet
var PinpointDataSheet = Data.getSheetByName("The Pinpoints") // DATA "Pinpoint" sheet
var PinpointAllValues = PinpointDataSheet.getRange(2, 1, PinpointDataSheet.getLastRow()-1,PinpointDataSheet.getLastColumn()).getValues();
var FeedDataSheet = Data.getSheetByName("The Feed_Raw") // DATA "Feed" sheet
var FeedAllValues = FeedDataSheet.getRange(2, 1, FeedDataSheet.getLastRow()-1,FeedDataSheet.getLastColumn()).getValues();
var PinpointStateObj = {}; // Object for "Locale" values
var PinpointAreaObj = {}; // Object for "Locale" values
var PinpointCityObj = {}; // Object for "Locale" values
var PinpointSpotObj = {}; // Object for "Locale" values
for(var P = PinpointAllValues.length-1;P>=0;P--) // put Pinpoint values in array..
{
PinpointStateObj[PinpointAllValues[P][0]] = PinpointAllValues[P][10];
PinpointAreaObj[PinpointAllValues[P][1]] = PinpointAllValues[P][10];
PinpointCityObj[PinpointAllValues[P][2]] = PinpointAllValues[P][10];
PinpointSpotObj[PinpointAllValues[P][3]] = PinpointAllValues[P][10];
}
for(var F = FeedAllValues.length-1;F>=0;F--) // for each row in the "Feed" sheet...
{
var Feed_GeotagKey = FeedAllValues[F][90]; // Pinpoint Key values in Feed sheet
{
// If Pinpoint array dont match feed values
if ((PinpointStateObj[Feed_GeotagKey] != FeedAllValues[F][95]) || (PinpointAreaObj[Feed_GeotagKey] != FeedAllValues[F][96])
|| (PinpointCityObj[Feed_GeotagKey] != FeedAllValues[F][97]) || (PinpointSpotObj[Feed_GeotagKey] != FeedAllValues[F][97]))
{
FeedAllValues[F][95] = PinpointAllValues[P][0]; // ...Change FYI Category Name in FYI Topic Sheet
FeedAllValues[F][96] = PinpointAllValues[P][1];
FeedAllValues[F][97] = PinpointAllValues[P][2];
FeedAllValues[F][98] = PinpointAllValues[P][3];
}
}
}
Geotag Sheet - unique values "Dark column"
Feed Sheet - recurring values - "Highlighted column"

How to search array for product 'item type' and send to sheet with name of the 'Item Type'?

I'm putting together a Google sheet to assemble custom drone builds from a parts list.
The master parts list and compiler are on the MASTER sheet.
I've got my script to assemble an array of the rows based on item type (alphabetical order).
I want to make it so that on the button press, the script assembles and sorts an array, then copies the rows to their item type page so the compiler can make a dropdown menu (menu part exists and works). Just need to populate the item type pages with the data from the master list.
My idea was to run an if statement e.g if string matches, write array string to empty range on matched sheet. Is this possible or is there a much simpler way to do this?
/** #customFunction
What I want the script to do:
Read Column 1 from A26:A100 or lookahead for end of list
If current cell contains Sheet Name, copy row to corresponding sheet.
*/
/** function myFunction() {
Browser.msgBox('You clicked it!');
}
#customFunction
*/
/** var PDB = app.getActiveSpreadsheet().getSheetByName("PDB"); //Target sheet for PDB
var VTX = app.getActiveSpreadsheet().getSheetByName("VTX"); //Target sheet for VTX
var FRAME = app.getActiveSpreadsheet().getSheetByName("FRAME"); //Target sheet for FRAME
var MOTOR = app.getActiveSpreadsheet().getSheetByName("MOTOR"); //Target sheet for MOTOR
var FPVCAM = app.getActiveSpreadsheet().getSheetByName("FPVCAM"); //Target sheet for FPVCAM
var AIOFC = app.getActiveSpreadsheet().getSheetByName("AIO FC"); //Target sheet for AIO FC
var ESC = app.getActiveSpreadsheet().getSheetByName("ESC"); //Target sheet for ESC
var PROPS = app.getActiveSpreadsheet().getSheetByName("PROPS"); //Target sheet for PROPS
var itemType = activeSheet.getRange(i, 1).getValue();
*/
function sortscript() {
Logger.clear();
var app = SpreadsheetApp //selects app
var activeSheet = app.getActiveSpreadsheet().getActiveSheet(); //selects Spreadsheet and Sheet
var itemListArr = [];
for(var i=27;i<=58;i++){
var itemListGet = activeSheet.getRange(i, 1, 1, 7).getValues(); //Create Array of Items and rows
itemListArr.push(itemListGet);
itemListArr.sort(); //Groups by item type alphabetically
}
if(itemListArr.indexOf("PDB") > -1) {
activeSheet.getActiveCell()
Logger.log() //Does nothing right now ik
}
}
Maybe that's not what you are looking for but I think this is too simple a task to use scripts (unless you plan on adding more automation features).
You can simply go to your individual item sheets and use formulas to filter the range on the master sheet.
For the "PBD" sheet, the formula will look like this:
=FILTER(MASTER!A27:G,MASTER!A27:A="PDB")
Here's the result.
On the 'Master' sheet, you can then set data validation to reference column 'B' of the 'PBD' sheet. If you include all rows in column B, your items list will automatically update (for example, if there are more than 2 "PDB" items in the dataset)
After reading your question, I assume the following:
You want to populate different sheets from data of a table.
You desire to do it based on a column of the table (ITEM).
If my assumptions are correct, you can use the following answer to achieve your requests.
CODE
function sortScript() {
var spreadsheet = SpreadsheetApp.openById(
"{SPREADSHEET ID}");
var sheet = spreadsheet.getSheetByName("MASTER");
var row = 27; // First row of the item table
do {
var item = sheet.getRange(row, 1, 1, 7).getValues();
var destinySheet = spreadsheet.getSheetByName(item[0][0]);
destinySheet.appendRow(item[0]);
row++;
} while (sheet.getRange(row + 1, 1, 1, 7).getValues()[0][0] != "");
}
BEHAVIOUR
The code will load the first row of the table, read the first column out of it (column ITEM) and append the row in the sheet with the same name. Then it will iterate until no more rows are found.
OBSERVATIONS
On your sample spreadsheet, on the 30th row, there are one product which ITEM column is FC. I have considered that it must be AIO FC instead. If that is not correct, you will need to create a FC sheet.
ALLUSIONS
appendRow(rowContents)

Categories