I need some help working through this problem. I have multiple columns of data and I want to make it so that I only keep unique values and return the items to their respective columns.
1 2 3 6
1 1 4 7
2 3 5 8
would end up like this:
1 3 4 6
2 5 7
8
Right now I can do with one column using the =unique() function but I want to be able to put a new column of data and it would only spit out the unique items from that into the new table.
This is an attempt at doing it with an array formula: assumes cells do not contain negative numbers, commas or pipe symbols.
=ArrayFormula(transpose(split(transpose(split(join(",",text(unique(transpose(split(textjoin(",",true,{transpose(A1:D3),-transpose(column(A1:D3))}),","))),"0;|")),"|")),",")))
Also works with full-column references
=ArrayFormula(transpose(split(transpose(split(join(",",text(unique(transpose(split(textjoin(",",true,{transpose(A:D),-transpose(column(A:D))}),","))),"0;|")),"|")),",")))
var sheet = SpreadsheetApp.getActive().getSheetByName("Sheet5");
var sheet2 = SpreadsheetApp.getActive().getSheetByName("Sheet6");
var info = sheet.getDataRange().getValues();
var lastRow = sheet.getLastRow();
var lastCol = sheet.getLastColumn();
var seen = {}; // make object acts as a hash table
var data = info; // make array same size as original array that has the entire sheet
for (var x = 0; x < info[x].length; x++){
for (var i = 0; i < info.length; i++) {
if (!(info[i][x] in seen)) { // if item is not in seen
data[i][x] = info[i][x]; // put item in location
seen[data[i][x]] = true;}
else {
data[i][x] = "";}}} // if its not then add blank item to array
The previous answer had a join limit of 50,000 characters, so it had its own limit. this option helps for bigger sets of data. I think it could be tweaked still and improved
Paste these scripts in the script editor.
function onOpen() {
SpreadsheetApp.getUi().createMenu('My Menu')
.addItem('Show uniques', 'onlyShowUniques')
.addToUi()
}
function onlyShowUniques() {
var r, d, u, t, row, i, j;
r = SpreadsheetApp.getActive().getActiveRange();
d = transpose(r.getValues());
u = [];
t = [];
for (var i = 0, rl = d.length; i < rl; i++) {
row = []
for (var j = 0, cl = d[0].length; j < cl; j++) {
if (d[i][j] && (!~u.indexOf(d[i][j]) || i == 0 && j == 0)) {
u.push(d[i][j])
row.push(d[i][j])
} else {
row.push(null)
}
row.sort(function (a, b) {
return (a === null) - (b === null) || +(a > b) || -(a < b);
})
}
t.push(row)
}
r.setValues(transpose(t))
}
function transpose(array) {
return Object.keys(array[0])
.map(function (col) {
return array.map(function (row) {
return row[col];
});
});
}
Reopen the spreadsheet and see if an extra menu-item ('My Menu') is created.
Select the range you want to clear of duplicates.
Go to the menu item and select 'Show uniques'.
See if that brings about the expected output.
Related
I've been jogging my brain trying to figure out how to write this script to transpose data from one sheet to another from a pretty dirty sheet.
There are other questions like this but none seem to be like my particular use case.
This is how the sheet is currently structured (somewhat):
The biggest issue here is I have no concrete idea how many rows a particular group of data will be, But I know there are always a bunch of blank rows between each group of data.
I found a script that took me half way:
function myFunction() {
//Get values of all nonEmpty cells
var ss = SpreadsheetApp.getActiveSheet();
var values = ss.getRange("D:D").getValues().filter(String);
//Create object with 3 columns max
var pasteValues = [];
var row = ["","",""];
for (i = 1; i<values.length+1; i++){
row.splice((i%3)-1,1,values[i-1]);
if(i%3 == 0){
pasteValues.push(row);
var row = ["","",""]
}
}
if(row != []){
pasteValues.push(row)
}
//Paste the object in columns A to C
ss.getRange(1,1,pasteValues.length,pasteValues[0].length).setValues(pasteValues);
}
But in that case the asker dataset was fixed. I can loosely say that the max number of rows each group would have is 10(this is an assumption after browsing 3000 rows of the sheet...but if the script can know this automatically then it would be more dynamic). So with that in mind...and after butchering the script...I came up with this...which in no way works how it should currently(not all the data is being copied):
function myFunction() {
var copyfrom = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('copyfrom')
var copyto = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('copyto')
var values = copyfrom.getRange("A:A").getValues().filter(Array);
var pasteValues = [];
var row = [];
for (i = 1; i<values.length; i++){
if(values[i] != ""){
row.push(values[i])
}
Logger.log(row);
if(i%10 == 0){
pasteValues.push(row);
row = []
}
}
if(row != []){
pasteValues.push(row)
}
copyto.getRange(1,1,pasteValues.length,pasteValues[0].length).setValues(pasteValues);
}
I'm pretty sure I should maybe still be using array.splice() but haven't been successful trying to implement it achieve what i want, here's how the transposed sheet should look:
Info:
Each group of addresses inside the "copyfrom" sheet would be separated by at least 1 blank line
The length of an address group is not static, some can have 5 rows, others can have 8, but address groups are always separated by blank rows
Any help is appreciated
You are right to iterate all input values, and I can suggest the similar code:
function myFunction() {
var copyfrom = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('copyfrom')
var copyto = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('copyto')
var values = copyfrom.getRange("A:A").getValues();
var pasteValues = [[]]; // keep result data here
values.forEach(function(v) { // Iterate all input values
// The last row to be filled in currently
var row = pasteValues[pasteValues.length - 1];
if (v[0]) {
row.push(v[0]);
} else if (row.length > 0) {
while (row.length < 10) {
row.push(''); // Adjust row length
}
pasteValues.push([]);
}
});
if (pasteValues[pasteValues.length - 1].length == 0) pasteValues.pop();
copyto.getRange(1, 1, pasteValues.length, pasteValues[0].length).setValues(pasteValues);
}
Solution:
Assuming that every new row begins with Name, you can use this script to rearrange the column:
function myFunction() {
var copyfrom = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('copyFrom');
var copyto = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('copyTo');
var lastRow = copyfrom.getLastRow();
var values = copyfrom.getRange(1,1,lastRow).getValues().filter(Array);
var pasteValues = [];
var row = [];
var maxLen = 1;
// rearrange rows
for (i = 0; i < values.length; i++) {
if (values[i] == "Name" && i > 0) {
pasteValues.push(row);
row = [values[i]];
}
else if (values[i] != "") {
row.push(values[i]);
if (row.length > maxLen) {
maxLen = row.length;
}
}
}
pasteValues.push(row);
// append spaces to make the row lengths the same
for (j = 0; j < pasteValues.length; j++) {
while (pasteValues[j].length < maxLen) {
pasteValues[j].push('');
}
}
copyto.getRange(1,1,pasteValues.length,maxLen).setValues(pasteValues);
}
Sample I/O:
As far as I can tell, there is no way to get the columns to line up in the output since you don't have any way to tell the difference between, for example, an "address 2" and a "City".
However, as far as merely grouping and transposing each address. This one formula, in one cell, in the tab here called MK.Help will work from the data you provided. It will work for as many contacts as you have.
=ARRAYFORMULA(QUERY(QUERY({A:A,IFERROR(LOOKUP(ROW(A:A),FILTER(ROW(A:A),A:A="")),0),COUNTIFS(IFERROR(LOOKUP(ROW(A:A),FILTER(ROW(A:A),A:A="")),0),IFERROR(LOOKUP(ROW(A:A),FILTER(ROW(A:A),A:A="")),0),A:A,"<>",ROW(A:A),"<="&ROW(A:A))},"select MAX(Col1) where Col1<>'' group by Col2 pivot Col3",0),"offset 1",0))
The script would count the number of times all VIN numbers are repeated & if all parts have arrived for that VIN Number (Car).
In example, if the VIN number is repeated 5 times then that means there are five parts going to arrive, so then the next step would be to check the arrived column for such VIN if there are 5 "Yes" values then
(VIN number repeated) 5/5 (Number of "Yes" values)
would trigger it to change the [Master] tab Parts Order column to "Yes" for that particular VIN number.
User would manually update the [Parts] tab, arrived column with either "Yes" or leave blank. (If blank then part has not arrived.)
See link for google sheet Template:
https://docs.google.com/spreadsheets/d/1wlGV_QCWpRwmI5FWiOli6lXuzRATy_Goygp3lhtm-Ek/edit?usp=sharing
My attempt:
Special function to get the last value of a column:
function getLastRowSpecial(range){
var rowNum = 0;
var blank = false;
for(var row = 0; row < range.length; row++){
if(range[row][0] === "" && !blank){
rowNum = row;
blank = true;
}else if(range[row][0] !== ""){
blank = false;
};
};
return rowNum;
};
Here I was able to count the number of times each VIN Number appears, but I was unable to count the number of "Yes" values for each unique VIN number. This needs to be dynamic. My approach at the end was not dynamic. Regarding in particular the, var number
Main Script:
/** ---------------------- SPREAD SHEETS ---------------------- **/
var masterS = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Master");
var partS = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Parts");
/** ----------------- Selecting Range of Cells ----------------- **/
/** ----- Parts Spread Sheet ----- **/
/** VIN to Match */
var vinPartOrderRangeP = partS.getRange("C5:C");
var vinPartValuesP = vinPartOrderRangeP.getValues();
var columnCheckPartVINP = getLastRowSpecial(vinPartValuesP);
var partVINDataRangeP = partS.getRange(5, 3, columnCheckPartVINP, 1);
var partsVinSetP = partVINDataRangeP.getValues();
/** Part Arrived */
var partOrderedRangeP = partS.getRange("N5:N");
var partOrderedValuesP = partOrderedRangeP.getValues();
var partOrderedValuesCorrectLengthP = partOrderedValuesP.splice(0,partsVinSetP.length);
/** Combining VINs with Parts Arrived */
var vinPartsArrivedP = [];
vinPartsArrivedP.push(partsVinSetP,partOrderedValuesCorrectLengthP);
/** ----- Master Spread Sheet ----- **/
/** VIN to Match */
var vinPartOrderRangeM = masterS.getRange("B5:B");
var vinPartValuesM = vinPartOrderRangeM.getValues();
var columnCheckPartVINM = getLastRowSpecial(vinPartValuesM);
var partVINDataRangeM = masterS.getRange(5, 2, columnCheckPartVINM, 1);
var partsVinSetM = partVINDataRangeM.getValues();
/** Part Arrived */
var partPastRangeM = masterS.getRange("I5:I");
var partPastValuesM = partPastRangeM.getValues();
/** ---- For-Loop getting Number of Parts that need to Arrive ---- **/
var vinNumber = [], arrivalPartsRequired = [], prev;
for (var i = 0; i < vinPartsArrivedP[0].length; i++) {
if (vinPartsArrivedP[0][i][0] !== prev) {
vinNumber.push(vinPartsArrivedP[0][i][0]);
arrivalPartsRequired.push(1);
} else {
arrivalPartsRequired[arrivalPartsRequired.length - 1]++;
}
prev = vinPartsArrivedP[0][i][0];
}
console.log('[' + vinNumber[0] + ']','[' + arrivalPartsRequired[0] + ']')
/**
* Now we can say arrivalPartsRequired has the number of Yes's we need
* per each VIN number.
**/
console.log(vinPartsArrivedP[0][3][0])
var number = 0;
var number2 = 0;
var number3 = 0;
var number4 = 0;
var number5 = 0;
for (var j = 0; j < partsVinSetM.length; j++) {
};
for (var k=0; k<vinPartsArrivedP[0].length; k++){
if(vinNumber[0] == vinPartsArrivedP[0][k][0]){
number++
for (var i=0; i<partOrderedValuesP[0].length; i++){
for (var j = 0; j < partOrderedValuesP[0].length; j++) {
if (partOrderedValuesP[i][j] == 'Yes') {
console.log(i);
return i+1;
}
}
return -1;
}
}
if(vinNumber[1] == vinPartsArrivedP[0][k][0]){
number2++
}
if(vinNumber[2] == vinPartsArrivedP[0][k][0]){
number3++
}
if(vinNumber[3] == vinPartsArrivedP[0][k][0]){
number4++
}
if(vinNumber[4] == vinPartsArrivedP[0][k][0]){
number5++
}
};
console.log(number);
console.log(number2);
console.log(number3);
console.log(number4);
console.log(number5);
I believe your goal as follows.
You want to retrieve the values from the columns "C" and "N" from "Parts" sheet, and want to check whether the number of same VIN # at the column "C" and the number of yes at the column "N".
When both numbers are the same, you want to put yes to the column "I" of "Master" sheet.
You want to achieve this using Google Apps Script.
In this case, in order to achieve your goal, how about the following flow?
Retrieve values from "Parts" sheet.
Create an object for checking the number of VIN # and yes.
Create an array for putting to the "Master" sheet.
Put the values to the "Master" sheet.
When this flow is reflected to a sample script, it becomes as follows.
Sample script:
function sample() {
// 1. Retrieve values from "Master" sheet.
var masterS = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Master");
var valuesOfParts = partS.getRange("C5:N" + partS.getLastRow()).getValues();
// 2. Create an object for checking the number of `VIN #` and `yes`.
var obj = valuesOfParts.reduce((o, [c,,,,,,,,,,,n]) => {
if (o[c]) {
o[c].c += 1;
if (n == "yes") o[c].yes += 1;
} else {
o[c] = {c: 1, yes: n == "yes" ? 1 : 0};
}
return o;
}, {});
// 3. Create an array for putting to the "Master" sheet.
var partS = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Parts");
var rangeOfMaster = masterS.getRange("B5:B" + masterS.getLastRow());
var valuesOfMaster = rangeOfMaster.getValues().map(([b]) => [obj[b] && obj[b].c == obj[b].yes ? "yes" : ""]);
// 4. Put the values to the "Master" sheet.
rangeOfMaster.offset(0, 7).setValues(valuesOfMaster);
}
References:
reduce()
map()
I am trying to create a formula to calculate Net Promoter Score on Google Sheets. I have the formula working but only when I specify the exact range. My issue is that this specific sheet will grow with data over time and I do not want to have to keep reselecting the range. What I want to do is select the entire row and just let it auto-update the NPS score. My issue with this approach is every empty cell is considered a zero which is screwing up my percentages. How can I make my function ignore the empty cells???
Here is my attempt:
/**
This is a custom formula that calculates the Net Promoter Score.
#customFunction
*/
function NPS(numArr) {
var detractors = new Array();
var passive = new Array();
var promoters = new Array();
var i = 0;
for (i = 0; i < numArr.length; i++) {
if (isNaN(numArr[i])) {
console.log(numArr[i]);
} else {
if (numArr[i] >= 9) {
promoters.push(numArr[i]);
} else if (numArr[i] === 7 || numArr[i] === 8) {
passive.push(numArr[i]);
} else if (numArr[i] <= 6) {
detractors.push(numArr[i]);
}
}
}
var promoPercentage = promoters.length / numArr.length;
var detractorsPercentage = detractors.length / numArr.length;
return (promoPercentage - detractorsPercentage) * 100;
}
You can use JavaScript filter [1] function to filter the empty values from the array you're getting (numArr). Also, notice that you're selecting a range of cells so the argument will be a 2D array [2], where each value is a "row" array filled with the column values for that row, in case you just want the first value of each row (for a one column range like A1:A25) you need to access the first element of each "row" array to get the actual value:
function NPS(numArr) {
var detractors = new Array();
var passive = new Array();
var promoters = new Array();
var i = 0;
//Filter empty elements
numArr = numArr.filter(function(element) {
return element[0] !== '';
})
for (i = 0; i < numArr.length; i++) {
if (isNaN(numArr[i][0])) {
console.log(numArr[i][0]);
} else {
if (numArr[i][0] >= 9) {
promoters.push(numArr[i][0]);
} else if (numArr[i][0] === 7 || numArr[i][0] === 8) {
passive.push(numArr[i][0]);
} else if (numArr[i][0] <= 6) {
detractors.push(numArr[i][0]);
}
}
}
var promoPercentage = promoters.length / numArr.length;
var detractorsPercentage = detractors.length / numArr.length;
return (promoPercentage - detractorsPercentage) * 100;
}
[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
[2] https://developers.google.com/apps-script/guides/sheets/functions#arguments
I'm trying to get the list of names from the Column A, randomize the list, and then distribute them evenly (as much as possible, including the remainders from division) by the user-specified number of groups.
An example of what I need is like this:
List of Names: A, B, C, D, E, F, G, H, I, J, K
Result of 3 Groups:
Group 1: D, A, F
Group 2: B, H, G, K
Group 3: E, C, I, J
Edited: I've cleaned up the code: I have assigned the list of names to an empty array and randomized the array successfully. Now I've got to figure out how to paste these values in their own columns for each groups. How do I paste the values to the right and down each column also accounting for the remainders (the first values are the headers for each columns):
Column C: Group 1, D, A, F
Column D: Group 2, B, H, G, K
Column E: Group 3, E, C, I, J
This is what I have so far:
function onOpen() {
SpreadsheetApp.getUi() // Or DocumentApp or FormApp.
.createMenu('Custom Menu')
.addItem('Show prompt', 'showPrompt')
.addToUi();
}
function SortNames() {
var ui = SpreadsheetApp.getUi();
var result = ui.prompt(
'How many groups?',
ui.ButtonSet.OK_CANCEL);
// Process the user's response.
var button = result.getSelectedButton();
var groupquantity = result.getResponseText();
if (button == ui.Button.OK) {
// User clicked "OK" - Need to clear the cells from the previous sorting in this step
// Get the last row number of the names list
var Avals = SpreadsheetApp.getActiveSheet().getRange("A1:A").getValues();
var Alast = Avals.filter(String).length;
// Set an empty Array
var ar = [];
/****** In its original order, append the names to the array *****/
for (var i = 2; i < Alast+1; i++) {
var source = 'A' + i;
var Avals = SpreadsheetApp.getActiveSheet().getRange(source).getValues();
ar.push(Avals);
}
/***************************/
/****** Shuffle the array *****/
function shuffle(a) {
var j, x, i;
for (i = a.length; i; i--) {
j = Math.floor(Math.random() * i);
x = a[i - 1];
a[i - 1] = a[j];
a[j] = x;
}
}
shuffle(ar);
/***************************/
/****** Calculates the rounded down # of members per group *****/
var memberspergroup = ar.length / groupquantity;
var memberspergroup = Math.floor(memberspergroup);
/*********************************/
/****** Copy and Paste the rounded down number of members to each groups until
the remainder is 0, then distribute evenly with remaining number of groups *****/
// First Cell location to paste
var pasteloc = "C1";
for (var i = 1; i <= groupquantity; i++) {
SpreadsheetApp.getActiveSheet().getRange(pasteloc).setValue('Group ' + i);
var source = 'A' + i;
var Avals = SpreadsheetApp.getActiveSheet().getRange(source).getValues();
}
/*********************************/
}
else if (button == ui.Button.CANCEL) {
// User clicked "Cancel".
ui.alert('The request has been cancelled');
}
else if (button == ui.Button.CLOSE) {
// User clicked X in the title bar.
ui.alert('You closed the dialog.');
}
}
I have found the solution to my question. It is not in the best shape - it can use an improvement to account for empty cells in the names list. However, it functions properly, and does everything I was looking for:
It assigns the list of names in an array
Randomizes the array
Distributes completely evenly which takes account for remainders (Just like the example I provided above)
function onOpen() {
SpreadsheetApp.getUi() // Or DocumentApp or FormApp.
.createMenu('Custom Menu')
.addItem('Show prompt', 'showPrompt')
.addToUi();
/******closing function onOpen()*********************/
}
function SortNames() {
var ui = SpreadsheetApp.getUi();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var result = ui.prompt(
'How many groups?',
ui.ButtonSet.OK_CANCEL);
// Process the user's response.
var button = result.getSelectedButton();
var groupquantity = result.getResponseText();
if (button == ui.Button.OK) {
// User clicked "OK"
// Get the last row number of the names list
var Avalues = sheet.getRange("A1:A").getValues();
var Alast = Avalues.filter(String).length;
if(groupquantity > 0 && groupquantity <= Alast)
{
// User inputted a valid group quantity - Need to clear the cells from the previous sorting in this step
var lastRow = SpreadsheetApp.getActiveSheet().getMaxRows();
sheet.getRange('C1:Z'+lastRow).clearContent();
// Set an empty Array
var ar = [];
/****** In its original order, append the names to the array *****/
for (var i = 2; i < Alast+1; i++) {
var source = 'A' + i;
var Avals = sheet.getRange(source).getValues();
ar.push(Avals);
}
/***************************/
/****** Shuffles array *****/
function shuffle(a) {
var j, x, i;
for (i = a.length; i; i--) {
j = Math.floor(Math.random() * i);
x = a[i - 1];
a[i - 1] = a[j];
a[j] = x;
}
/**********closing function shuffle(a)*****************/
}
shuffle(ar);
/****** Calculates the rounded down # of members per group *****/
var memberspergroup = Math.floor(ar.length / groupquantity);
/*********************************/
/****** Main Goal: Copy and Paste the rounded down number of members to each groups until
the remainder is 0, then distribute evenly with remaining number of groups *****/
// 1. Define the first Cell location to paste
var pasteloc = "C1";
// 2. Begin a for-loop: Navigate Horizontally across from the first cell location
for (var i = 1; i <= groupquantity; i++)
{
// 3. Set the Column Headings in the current column, i
sheet.getRange(1,i+2).setValue('Group ' + i);
/************** 4. Fill in the Rows of names for each groups **********/
// List out the values in array "ar" by the expected group qty, until the remainder is zero
if ((ar.length)%(groupquantity-(i-1)) > 0)
{
for (var rows = 2; rows <= memberspergroup+1; rows++)
{
var j = 0;
sheet.getRange(rows,i+2).setValue(ar[j]);
var index = ar.indexOf(ar[j]);
ar.splice(index, 1);
}
}
else
{
var memberspergroup = ar.length/(groupquantity-(i-1))
for (var rows = 2; rows <= memberspergroup+1; rows++)
{
var j = 0;
sheet.getRange(rows,i+2).setValue(ar[j]);
var index = ar.indexOf(ar[j]);
ar.splice(index, 1);
}
}
}
/*********************************/
}
/*****************closing if(groupquantity > 0 && groupquantity <= Alast)****************/
else{
ui.alert("Error: " + '"' + groupquantity + '"' +" is not a proper group quantity")
}
}
else if (button == ui.Button.CANCEL) {
// User clicked "Cancel".
}
else if (button == ui.Button.CLOSE) {
// User clicked X in the title bar.
}
}
I hope this helps!
I am working with Col A, B & C. Col A contains A-E, Col B Contains 1, a, 3, b, 5 and Col C will be where I will store duplicated information (a and b would go into C1 & C2). Any help would be appreciated. In summary; compare A and B for similarity, output result into C
function appendString() {
var range = SpreadsheetApp.getActiveSheet().getRange("A1:A5");
var range2 = SpreadsheetApp.getActiveSheet().getRange("B1:B5");
var range3 = SpreadsheetApp.getActiveSheet().getRange("C1:C5")
var numRows = range.getNumRows();
var x = 0
// var numCols = range.getNumColumns();
j = 1 // row A
k = 2 // row B
m = 3 // row C
n = 1
// First loop though B
for (var i = 1; i <= numRows; i++) {
// set the current value...
var currentValue = range.getCell(i, j).getValue();
// In the log tell us the current value
Logger.log("Set A:" + currentValue);
// Loops though col B to compare to col A
for (var l = 1; l <= numRows; l++) {
// Sets the current value to compare value
var compareValue = range2.getCell(l, j).getValue();
Logger.log("Set B:" + compareValue)
// If the compareValue and the currentValue (match)
if (compareValue === currentValue) {
Logger.log("MATCHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH");
// We will write the result to col C down one row
for (n; n <= x; n++) {
// this makes it only run once'
range3.setValue(currentValue);
Logger.log("Appending.................");
x = n + 3
}
}
}
}
}
I think your problem statement boils down to this: Fill column C with a list of unique values that appear in both column A and B.
There is a built-in javascript Array method Array.indexOf() that makes it very easy to search for matching elements. As the problem is defined, we want to search in a column, so to use that method we need a column to be represented as an Array. The Range.getValues() method allows us to load a whole range of values at once, and delivers them as a two-dimensional array, with rows as the first dimension. We need columns there, and we can achieve that by a matrix transposition.
So here's what we end up with. There isn't a built-in transpose(), so I've included one. As we search for matches, results are stored in an Array C, using the built-in Array.push() method. Finally, array C is treated as a two-dimensional array, transposed, and written out to the sheet in column C.
function recordMatches() {
var range = SpreadsheetApp.getActiveSheet().getRange("A1:B5");
var data = range.getValues();
// For convenience, we'll transpose the data, so
// we can treat columns as javascript arrays.
var transposed = transpose(data);
var A = transposed[0],
B = transposed[1],
C = [];
// Go through A, looking for matches in B - if found, add match to C
for (var i=0; i < A.length; i++) {
if (B.indexOf(A[i]) !== -1) C.push(A[i]);
}
// If any matches were found, write the resulting array to column C
if (C.length > 0) {
var rangeC = SpreadsheetApp.getActiveSheet().getRange(1,3,C.length);
rangeC.setValues(transpose([C]));
}
}
function transpose(a) {
return Object.keys(a[0]).map(function (c) { return a.map(function (r) { return r[c]; }); });
}