In my sheet column A is date and column B is time duration values, I want to find the dates which are repeated and sum up the corresponding time values of the repeated dates and show the sum in the last relevant repeated date. And delete all the other repeated dates. ie if 18/07/2019 is repeated 4 times i have to sum up all the four duration values and display the sum value in the 4th repeated position and delete the first three date 18/07/2019. I have to do this all those dates that are repeated. I have wrote code to my best knowledge
function countDate() {
var data = SpreadsheetApp.getActive();
var sheet = data.getSheetByName("Sheet5");
var lastRow = sheet.getLastRow();
var sh = sheet.getRange('A1:A'+lastRow);
var cell = sh.getValues();
var data= sheet.getRange('B1:B'+lastRow).getValues();
for (var i =0; i < lastRow; ++i){
var count = 0;
var column2 = cell[i][0];
for (var j =0; j < i; j++)
{
var p=0;
var column4 = cell[j][0];
if (column4 - column2 === 0 )
{
var value1 = data[j][0];
var value2 = data[i][0];
var d = value2;
d.setHours(value1.getHours()+value2.getHours()+0);
d.setMinutes(value1.getMinutes()+value2.getMinutes());
sheet.getRange('C'+(i+1)).setValue(d).setNumberFormat("[hh]:mm:ss");
sheet.deleteRow(j+1-p);
p++;
}
}
}
}
The copy of the sheet is shown
column C is the values I obtain through the above code AND column D is the desired value
After computing the sum I need to delete the repeated rows till 15 here
Answer:
You can do this by converting your B-column to a Plain text format and doing some data handling with a JavaScript dictionary.
Code:
function sumThemAllUp() {
var dict = {};
var lastRow = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0].getLastRow();
var dates = SpreadsheetApp.getActiveSpreadsheet().getRange('A1:A' + lastRow).getValues();
var times = SpreadsheetApp.getActiveSpreadsheet().getRange('B1:B' + lastRow).getValues();
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
sheet.getRange(1, 1, sheet.getLastRow(), sheet.getLastColumn()).setNumberFormat("#");
for (var i = 0; i < dates.length; i++) {
if (!dict[dates[i][0]]) {
dict[dates[i][0]] = times[i][0];
}
else {
var temp = dict[dates[i][0]];
var hours = parseInt(temp.split(':')[0]);
var minutes = parseInt(temp.split(':')[1]);
var additionalHours = parseInt(times[i][0].split(':')[0]);
var additionalMinutes = parseInt(times[i][0].split(':')[1]);
var newMinutes = minutes + additionalMinutes;
var newHours = hours + additionalHours;
if (newMinutes > 60) {
newHours = newHours + 1;
newMinutes = newMinutes - 60;
}
dict[dates[i][0]] = newHours + ':' + newMinutes;
}
}
SpreadsheetApp.getActiveSpreadsheet().getSheets()[0].getRange('A1:B' + lastRow).clear();
var keys = Object.keys(dict);
for (var i = 0; i < keys.length; i++) {
SpreadsheetApp.getActiveSpreadsheet().getSheets()[0].getRange('A' + (i + 1)).setValue(keys[i]);
SpreadsheetApp.getActiveSpreadsheet().getSheets()[0].getRange('B' + (i + 1)).setValue(dict[keys[i]]);
}
}
Assumptions I made:
There are a few assumptions I made when writing this, you can edit as needed but I figured I should let you know:
There are only dates in Column A and only times in Column B.
The times in column B are either Hours:Minutes or Minutes:Seconds. Either way, if the value to the right of the : hits 60, it adds one to the left value and resets.
The Sheet within the Spreadsheet is the first sheet; that which is returned by Spreadsheet.getSheets()[0].
References:
w3schools - JavaScript Objects
Spreadsheet.getSheets()
w3schools - JavaScript String split() Method
MDN web docs - parseInt() method
Google Sheets > API v4 - Date and Number Formats
I'm trying to make a google sheet script that adds a row based on cell value, basically if I have in the Quantity (Column D) 7x laptops, I want the script to add 6 additional rows below if Column H is marked as "Yes" through data validation.
What I was able to find and to do is only duplicate that row but is without data validation and I would prefer to add the data validation and possible make each quantity split to 1 (instead of 7) after the duplication.
`function autoDup() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var data = sheet.getDataRange().getValues();
var newData = [];
for(var n in data){
newData.push(data[n]);
if(!Number(data[n][3])){continue};// if column 3 is not a number then do nothing
for(var c=1 ; c < Number(data[n][3]) ; c++){ // start from 1 instead of 0 because we have already 1 copy
newData.push(data[n]);//store values
}
}
sheet.getRange(1,1,newData.length,newData[0].length).setValues(newData).sort({column: 1, ascending: false});// write new data to sheet, overwriting old data
}`
Hope someone is able to help me.
Thank you,
Column D contains a qty and goods description. If Column H = "Yes", you want to insert a number of rows below Col D equal to the qty minus one. If Column H <> "Yes, then take no action.
Sample data - Before
Sample data - After
function so5925663201() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheetname = "59256632";
var sheet = ss.getSheetByName(sheetname);
var row = 7;
// get value of Column H
var colHValue = sheet.getRange(row,8).getValue();
if (colHValue === "Yes"){
//Logger.log("DEBUG: Col H = yes. do something")
// get value of Column D
var Value = sheet.getRange(row,4).getValue();
var searchterm = "x";
var indexOfFirst = Value.indexOf(searchterm);
//Logger.log("DEBUG: the first instance of 'x' is "+indexOfFirst);
// get the quantity and convert from a string to a number
var qty = Value.substring(0, indexOfFirst);
var qtynum = +qty;
// var newtype = typeof qtynum; // DEBUG
//Logger.log("DEBUG: the quantity is "+qtynum+", new type = "+newtype)
// This inserts rows after
sheet.insertRowsAfter(row, qtynum-1);
}
else{
//Logger.log("DEBUG: col H <> Yes. do nothing");
}
}
I am currently trying to exchange values between two columns (G and H)
The first sheet column G values don't move if they are found in a first column table reference in another sheet.
if they are found in second column table reference,
they have to swap values with the first sheet column H values the same index.
This code works for column G but not for column H. It gives the elements but not in order.
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet29'); //au cas ou ca bug
var lr = spreadsheet.getLastRow();
var lc = spreadsheet.getLastColumn();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = ss.getSheetByName('Sheet29');
var sheet2 = ss.getSheetByName('Tabs of applications and firmwares');
var range1 = sheet1.getRange(2, 7, sheet1.getLastRow(), 9);
var range2 = sheet2.getRange(2, 1, sheet2.getLastRow(), 4);
var values1 = range1.getValues();
var values2 = range2.getValues();
var compteurBon = 0;
var compteurMauvais = 0;
var tempArray1 = [];
for (var i = 0; i < values1.length; i++) {
for (var j = 0; j < values2.length; j++) {
if (values1[i][0] === values2[j][0]) {
compteurBon++;
} else if (values1[i][0] == values2[j][2]) {
compteurMauvais++;
var tempArrayValue1 = values1[i][0];
tempArray1.push(tempArrayValue1);
values1[i][0] = values1[i][1];
values1[i][1] = tempArray1; // here it doesn't take the right value
}
}
}
range1.setValues(values1);
};
Okay, I think your code is in the good direction but it can be simplified. First of all, I understand that we have two sheets (“Sheet 29” and “Tabs of applications and firmwares”), and you want to copy the values from H to G in case G equals B from the second sheet. As I said in my comment, in case you want to just get two columns in the same range, you should use sheetx.getRange(2, col, sheet1.getLastRow(), 2); This last '2' is the number of columns you are getting into the range (G and H, A and B respectively). If we stick to your approach, we will need another tempArray variable:
for (var i = 0; i < values1.length - 1; i++) {
tempArray1.push(values1[i].toString().split(","));
tempArray2.push(values2[i].toString().split(","));
}
What we are doing here is putting the 4 columns in those two arrays. Each one of them is 2D, so tempArray1 contains all the rows from G and H and the same for tempArray2 with A and B. You can access the data with [x][0] and [x][1] respectively.
After this you can just compare the values of temparray1 and temparray2, and write the values from G (temparray[i][1]) to H (temparray[i, 7])
if (tempArray1[i][0] == tempArray2[i][0]) {
compteurBon++;
} else if (tempArray1[i][0] == tempArray2[i][1]) {
sheet1.getRange(i+2 , 7).setValue(tempArray1[i][1]);
}
I need to transpose column data to rows based on the merged header using Apps Script.
Below is the view what would be my input and the expected output,
Input
Output
Sample sheet
What I've written so far:
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var range = sheet.getRange("A1:AO1");
var mergedValues = [];
//get the header added to the array
mergedValues.push(sheet.getRange("A2:I2").getValues());
Logger.log(mergedValues);
var mergedRanges = range.getMergedRanges();
for (var i = 0; i < mergedRanges.length; i++) {
var calcA1Notation = "A"+(i+3) + ":C"+(i+3);
var monA1Notation = "D"+(i+3) + ":F"+(i+3);
//Load the Transpose values into the array
mergedValues.push([[
sheet.getRange(calcA1Notation).getValues().toString(),
mergedRanges[i].getDisplayValue(),
sheet.getRange(monA1Notation).getValues().toString()
]]);
}
Logger.log(mergedValues[0].length);
for (var i = 0; i < mergedValues.length; i++){
//Writes to the lastrow+1 of the sheet
sheet.getRange(sheet.getLastRow()+1, 1).setValue(mergedValues[i]);
}
}
Can you guys help me in modifying google script to generate the expected result?
The question includes the term "Transpose", but this is misleading.
The goal of the questioner is straight-forward; to copy cells from one sheet to another. With one proviso, to include a column header from one sheet as a cell in the target range.
The questioner demonstrated code though they did not explain to what extent this was purposeful. The code takes three columns of data and concatenates the values into a single cell. At best, one might regard this as an early draft.
The referencing of the source data is uncomplicated; getting the month name is the main complication. I used two loops to work through the rows on the Source sheet because the questioner's intended outcome was that the data should sort by month.
I could have built a routine to convert the month string value to a numeric value, then sorted on that value (I certainly thought about it) - but I didn't;)
The Month names are in UPPERCASE, the questioner's outcome uses TitleCase. Again, I could have built a routine to convert the case, and I did spend some time trying. But in the end I decided that it was not a high priority.
function so5273586002() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
// Declare the two sheets
var sourcesheet = ss.getSheetByName("Input");
var targetsheet = ss.getSheetByName("Output");
// Get the respective starting row and ending rows.'' the target last row is declared in the loop.
var sourcestartrow = 3;
var targetstartrow = 2;
var sourcelastrow = sourcesheet.getLastRow();
// get the the data
var sourcerange = sourcesheet.getDataRange();
var sourcevalues = sourcerange.getValues();
// rubric for copying data.
// each row of the source must create two rows in the target - one row for each month
// the first three columns are repeats on both rows
// each row includes the source data as well as the month name
// target row #1
// source columns A, B & C to target A,B,C
// Month#1; value in D1 Source=> Target Column D (4)
// source columns DEF to target E F G
// target row #2
// source columns A, B & C to target A,B,C
// Month#2: value in G1 Source=> Target D (4)
// source fields G, H I to target E F G
// the questioner's prefered layout is that all the rows are sorted by month; to achive this, I used two loops
// the first to do the first month; the second to do the second month
for (i = sourcestartrow; i < (sourcelastrow + 1); i++) {
// get the last row for the target
var targetlastrow = targetsheet.getLastRow();
// Columns A, B and C -> Columns A, B and C
var targetRange = targetsheet.getRange(targetlastrow + 1, 1); //target: column =A, row = lastrow plus one
var sourcetest = sourcesheet.getRange(i, 1, 1, 3).copyTo(targetRange); // range = active row, column=A, 1 row, 3 columns, copy to SheetTracker
//Logger.log("source range is "+sourcesheet.getRange(i, 1, 1, 3).getA1Notation()+", target range is "+targetsheet.getRange(targetlastrow + 1, 1).getA1Notation());//DEBUG
// Month Name from the header
var targetRange = targetsheet.getRange(targetlastrow + 1, 4); //target: column =D, (month) row = lastrow plus one
var sourcetest = sourcesheet.getRange(1, 4).copyTo(targetRange, {
contentsOnly: true
}); // range = active row, column=A, 1 row, 3 columns, copy to SheetTracker
// Logger.log("source range is "+sourcesheet.getRange(1, 4).getA1Notation()+", target range is "+targetsheet.getRange(targetlastrow + 1, 4).getA1Notation());//DEBUG
// Month details
// Columns D E and F -> Columns E F and G
var targetRange = targetsheet.getRange(targetlastrow + 1, 5); //target: column =E, row = lastrow plus one
var sourcetest = sourcesheet.getRange(i, 4, 1, 3).copyTo(targetRange, {
contentsOnly: true
}); // range = active row, column=D(4), 1 row, 3 columns, copy to SheetTracker
// Logger.log("source range is "+sourcesheet.getRange(i, 4, 1, 3).getA1Notation()+", target range is "+targetsheet.getRange(targetlastrow + 1, 5).getA1Notation());//DEBUG
} // end loop#1
//Loop#2 to generate rows for the second month
for (i = sourcestartrow; i < (sourcelastrow + 1); i++) {
// get the last row for the target
var targetlastrow = targetsheet.getLastRow();
// Columns A, B and C -> Columns A, B and C
var targetRange = targetsheet.getRange(targetlastrow + 1, 1); //target: column =A, row = lastrow plus one
var sourcetest = sourcesheet.getRange(i, 1, 1, 3).copyTo(targetRange); // range = active row, column=A, 1 row, 3 columns, copy to SheetTracker
//Logger.log("source range is "+sourcesheet.getRange(i, 1, 1, 3).getA1Notation()+", target range is "+targetsheet.getRange(targetlastrow + 1, 1).getA1Notation());//DEBUG
// Month Name from the header
var targetRange = targetsheet.getRange(targetlastrow + 1, 4); //target: column =D, (month) row = lastrow plus one
var sourcetest = sourcesheet.getRange(1, 7).copyTo(targetRange, {
contentsOnly: true
}); // range = active row, column=G, 1 row, 3 columns, copy to SheetTracker
//Logger.log("source range is "+sourcesheet.getRange(1, 7).getA1Notation()+", target range is "+targetsheet.getRange(targetlastrow + 1, 4).getA1Notation());//DEBUG
// Month details
// Columns G H and I -> Columns E F and G
var targetRange = targetsheet.getRange(targetlastrow + 1, 5); //target: column =E, row = lastrow plus one
var sourcetest = sourcesheet.getRange(i, 7, 1, 3).copyTo(targetRange, {
contentsOnly: true
}); // range = active row, column=D(4), 1 row, 3 columns, copy to SheetTracker
// Logger.log("source range is "+sourcesheet.getRange(i, 7, 1, 3).getA1Notation()+", target range is "+targetsheet.getRange(targetlastrow + 1, 5).getA1Notation());//DEBUG
} // end loop#2
}
This screenshot shows the Source sheet ("Input").
These screenshots show the Target sheet ("Output") before and after running the code.
UPDATE
As noted in my comments, the earlier draft lacked two things:
1) it was inefficient and followed poor practices because it wrote the value of each field as it was created. The more appropriate approach would have been to write the data to an array, and then copy the array to the target range when the row-by-row processing was complete.
2) the code consisted of two loops to cater for the 2 months in the demonstration data. However, this is an impractical outcome since it is probable that there will be, in reality, any number of months' data in each row. Again, poor practice, when a more appropriate approach was to assume any number of month's data. The more efficient approach would have been to build an array of data while looping through each row.
This revision overcomes both drawbacks.
In addition, since month names do not sort in any meaningful sequence, I added a numeric month id that can be used for filtering and sorting in the output data sheet.
function so5273586003() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
// Declare the two sheets
var sourcesheet = ss.getSheetByName("Input");
var targetsheet = ss.getSheetByName("Output");
// Get the respective starting row and ending rows.'' the target last row is declared in the loop.
var targetstartrow = 2;
var sourcestartrow = 2;
var sourcelastrow = sourcesheet.getLastRow();
var sourcelastcolumn = sourcesheet.getLastColumn();
//Logger.log("the last row is "+sourcelastow+", and the last column is "+sourcelastcolumn);
// get the the data
var sourcerange = sourcesheet.getDataRange();
var sourcevalues = sourcerange.getValues();
var sourcelength = sourcevalues.length;
var i = 0;
var m = 0;
var month = 1;
var dataarray = [];
var masterarray = [];
// start loop by row
for (i = sourcestartrow; i < (sourcelastrow); i++) {
// start loop by month (within row)
for (m = 0; m <= (sourcelastcolumn - 6); m = m + 3) {
dataarray = [];
// add first three columns
dataarray.push(sourcevalues[i][0]);
dataarray.push(sourcevalues[i][1]);
dataarray.push(sourcevalues[i][2]);
//add the month name
dataarray.push(sourcevalues[0][3 + m]);
//add month data
dataarray.push(sourcevalues[i][3 + m]);
dataarray.push(sourcevalues[i][4 + m]);
dataarray.push(sourcevalues[i][5 + m]);
//create month id
switch (sourcevalues[0][3 + m]) {
case "JULY":
month = 1;
break;
case "AUGUST":
month = 2;
break;
case "SEPTEMBER":
month = 3;
break;
case "OCTOBER":
month = 4;
break;
case "NOVEMBER":
month = 5;
break;
case "DECEMBER":
month = 6;
break;
case "JANUARY":
month = 7;
break;
case "FEBRUARY":
month = 8;
break;
case "MARCH":
month = 9;
break;
case "APRIL":
month = 10;
break;
case "MAY":
month = 11;
break;
case "JUNE":
month = 12;
break;
default:
month = 100;
break;
} // end switch
// add the month id to the array (used for sorting)
dataarray.push(month);
// add the data to the master array before zeroing for next month
masterarray.push(dataarray);
} // months loop
} // end row loop
// get the length of the master array
var masterlength = masterarray.length;
// define the target range
var TargetRange = targetsheet.getRange(targetstartrow, 1, masterlength, 8);
// set the array values on the Target sheet
TargetRange.setValues(masterarray);
}
I have the function below where I am trying to scrape 4 websites, and then combine the results into a spreadsheet. Is there a faster way to match over a large array that isn't the INDEX/MATCH formulas. My desired output would be (obv this is an example)
MLBID | FG_ID | PA | K | K% | wOBA
12345 | 12345 | 12 | 5 | 41.7% | .300
While the code I have below works, it takes wayyyy too long reaches the 6-minute limit of Google Script. The matching that I am trying to do is with ~4000 rows. I have commented my code as much as possible.
function minors_batting_stats() {
//this is the spreadsheet where I have a list of all of the IDs -- MLB and FG
var ids = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Player List");
//this is the output sheet
var mb18vR_sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("2018 minors bat vs R");
//various URLs I am trying to scrape
var mb18vR_PA_url = 'https://www.mlb.com/prospects/stats/search?level=11&level=12&level=13&level=14&level=15&level=16&pitcher_throws=R&batter_stands=&game_date_gt=&game_date_lt=&season=2017&home_away=&draft_year=&prospect=&player_type=batter&sort_by=results&sort_order=desc&group_by=name&min_pa=&min_pitches=#results'
var mb18vR_SO_url = 'https://www.mlb.com/prospects/stats/search?pa_result=strikeout&level=11&level=12&level=13&level=14&level=15&level=16&pitcher_throws=R&batter_stands=&game_date_gt=&game_date_lt=&season=2017&home_away=&draft_year=&prospect=&player_type=batter&sort_by=results&sort_order=desc&group_by=name&min_pa=&min_pitches=#results'
var mb18vR_wOBA_url = 'https://www.mlb.com/prospects/stats/search?level=11&level=12&level=13&level=14&level=15&level=16&pitcher_throws=R&batter_stands=&game_date_gt=&game_date_lt=&season=2017&home_away=&draft_year=&prospect=&player_type=batter&sort_by=woba&sort_order=desc&group_by=name&min_pa=&min_pitches=#results'
//creating an array for each scrape
var res = [];
var res1 = [];
var res2 = [];
var res3 = [];
//getting the MLB and FG ids from the spreadsheet
var mlbids = ids.getRange(1, 11, ids.getLastRow()).getValues();
var fgids = ids.getRange(1,9, ids.getLastRow()).getValues();
//scraping SO against RHP
var content_SO = UrlFetchApp.fetch(mb18vR_SO_url).getContentText();
var e_SO = Parser.data(content_SO).from('tbody').to('</tbody>').build();
var rows_SO = Parser.data(e_SO).from('<tr class="player_row"').to('</tr>').iterate();
for (var i=0; i<rows_SO.length; i++) { //rows.length
res1[i] = [];
res1[i][0] = Parser.data(rows_SO[i]).from('/player/').to('/').build();
var SOs = Parser.data(rows_SO[i]).from('<td align="left">').to('</td>').iterate();
res1[i][1] = SOs[1];
}
//scraping wOBA against RHP
var content_wOBA = UrlFetchApp.fetch(mb18vR_wOBA_url).getContentText();
var e_wOBA = Parser.data(content_wOBA).from('tbody').to('</tbody>').build();
var rows_wOBA = Parser.data(e_wOBA).from('<tr class="player_row"').to('</tr>').iterate();
for (var i=0; i<rows_wOBA.length; i++) { //rows.length
res2[i] = [];
res2[i][0] = Parser.data(rows_wOBA[i]).from('/player/').to('/').build();
var wOBAs = Parser.data(rows_wOBA[i]).from('<td align="left">').to('</td>').iterate();
res2[i][1] = wOBAs[2];
}
//scraping PA against RHP
var content = UrlFetchApp.fetch(mb18vR_PA_url).getContentText();
var e = Parser.data(content).from('tbody').to('</tbody>').build();
var rows = Parser.data(e).from('<tr class="player_row"').to('</tr>').iterate();
for (var i=0; i<rows.length; i++) { //rows.length
res[i] = [];
res[i][0] = Parser.data(rows[i]).from('/player/').to('/').build();
res[i][1] = [];
//matching the MLB_ID with FG_ID
var mlbID = res[i][0];
for(var j = 0; j<mlbids.length;j++){
if(mlbids[j] == mlbID){
res[i][1] = fgids[j];
}
}
var PAs = Parser.data(rows[i]).from('<td align="left">').to('</td>').iterate();
res[i][2] = PAs[1];
//matching the MLB_ID from PA (res) with SO (res1)
res[i][3] = 0;
for (var w=0; w<res1.length; w++) {
if (res[i][0] == res1[w][0]) {
res[i][3] = res1[w][1];
}
}
//Calculating K%
res[i][4] = res[i][3] / res[i][2]
//matching the MLB_ID from PA (res) with wOBA (res1)
res[i][5] = 0;
for (var v=0; v<res2.length; v++) {
if (res[i][0] == res2[v][0]) {
res[i][5] = res2[v][1];
}
}
}
//pasting values
mb18vR_sheet.getRange(2, 1, res.length, res[0].length).setValues(res);
}
The issue you have is that you are forcing your script to loop through large datasets many many times for each row of compared data. A better approach is to build a lookup object, which maps between a desired unique identifier and the row of the data array you want to access:
/* Make an object from an Array[][] that has a unique identifier in one of the columns.
* #param Array[][] data The 2D array of data to index, e.g. [ [r1c1, r1c2, ...], [r2c1, r2c2, ...], ... ]
* #param Integer idColumn The column in the data array that is a unique row identifier
e.g. the column index that contains the product's serial number, in a data
array that has only a single row per unique product.
#return Object {} An object that maps between an id and a row index, such that
`object[id]` = the row index for the specific row in data that has id = id
*/
function makeKey(data, idColumn) {
if(!data || !data.length || !data[0].length)
throw new ValueError("Input data argument is not Array[][]");
// Assume the first column is the column with the unique identifier if not given by the caller.
if(idColumn === undefined)
idColumn = 0;
var key = {};
for(var r = 0, rows = data.length; r < rows; ++r) {
var id = data[r][idColumn];
if (key[id])
throw new ValueError("ID is not unique for id='" + id + "'");
key[id] = r;
}
return key;
}
Usage:
var database = someSheet.getDataRange().getValues();
var lookup = makeKey(database, 3); // here we say that the 4th column has the unique values.
var newData = /* read a 2D array from somewhere */;
for(var r = 0, rows < newData.length; r < rows; ++r) {
var id = newData[r][3];
var existingIndex = lookup[id];
if (existingIndex) {
var oldDataRow = database[existingIndex];
} else {
// No existing data.
}
}
By making a lookup object for your data arrays, you no longer have to re-search them and make comparisons, because you did the search once and stored the relationship, rather than discarding it every time. Note that the key that was made is based on a specific (and unique) property of the data. Without that relationship, this particular indexing approach won't work - but a different one will.