Find duplicates of two column combination - google-sheets

Let I have two column, A and B . How I can find duplicates of this two column combination?
As shown in the picture, duplicate of combination of two column will be colored.

You can get the duplicates highlighted, with the help of following script:
function onOpen() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var entries = [{name : "Check Duplicates",functionName : "duplicates"}];
sheet.addMenu("Scripts", entries);
};
function duplicates() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName('Sheet1');
var r = s.getRange("A:B");
var v = r.getValues();
r.setBackground('white');
var f = r.getBackgrounds();
var lastrow = getLastPopulatedRow(v);
for( var i=0;i<lastrow;i++){
for( var j=i+1;j<lastrow;j++){
if( ( v[i][0]==v[j][0] && v[i][1]==v[j][1] ) || ( v[i][0]==v[j][1] && v[i][1]==v[j][0] ) ) {
f[i][0]='lightgreen';
f[i][1]='lightgreen';
f[j][0]='lightgreen';
f[j][1]='lightgreen';
}
}
}
r.setBackgrounds(f);
};
function getLastPopulatedRow(data) {
for (var i=data.length-1;i>=0;i--)
for (var j=0;j<data[0].length;j++)
if (data[i][j]) return i+1;
return 0;
};
Run the function "duplicates" from the script editor. You will also be able to run it from the custom menu "Scripts" from your spreadsheet.
Here is the Screenshot

I think #jwilson gave the proper answer.
However, here is a shortcut method, it may help you.
Select a cell and use CONCATENATE function to join two column value with a space between them. Then you can search the current column if they have duplicates.
For example, using your example image, select your column C1 and add =CONCATENATE(A1," ",B1) and drag this to applicable the formula for all cells in column C. Then add a conditional format rules for column C to check duplicates using =countif(C:C,C1)>1.
Here what is happening is, value of column A and B is concatenating first, then compared if those have duplicate entry in the record.

Use the following Custom formula for Conditional formatting:
=countif(arrayformula($A:$A&"|"&$B:$B);$A1&"|"&$B1)>1

Related

Split cell values into new rows with common values

CONTEXT
I have a source table with multiple columns (Source B table in example spreadsheet).
On column E we have max one name and on column F we can have from 0 to multiple names separated by a comma.
AIM
When there are values in F, add one row per each name (E,F - the last one can have more than one separated by a comma) and duplicate the common values.
It should keep the rows where there are no values in F.
The final result will have one less column than Source table.
WHAT I'VE TRIED
=ARRAYFORMULA(QUERY(IFERROR(SPLIT(FLATTEN(IF(ISBLANK(E3:F6);;
A3:A6&"♦"&B3:B6&"♦"&C3:C6&"♦"&D3:E6&"♦"&E3:E6&"♦"&G3:G6&"♦"&H3:H6&"♦"&I3:I6&"♦"&J3:J6&"♦"&K3:K6&"♦"&L3:L6)); "♦"));
"where Col3 <> 0"; 0))
Problem
This formula was applied to Source A table (in the example spreadsheet and that's = Source B table but without comma separated values in F), which didn't have more than one value in F at the time, and:
duplicates the common values as expected but it's not showing the values from F. Just duplicates the ones from E.
ads blank row if the source row doesn't have values in F
because in column K only one row has a value, it messes up the final data
doesn't do anything different with or without comma separated values in F
Example spreadsheet
--- EDIT ---
I've found this other post with a script that I also tested on the example sheet. I've reduced the number of columns to ease the test and because I think it's aiming for the last column being the one that is supposed to be splitted, if applicable.
It does split but it repeats the "Main" client on the left column and the splited one on the right, where I would like the outcome to have all clients on the same column.
To give you an idea, you can try the following script, I used the "Source for Script" Sheet and created another sheet called "Result". As you can see in the script, I used arrays to collect the data, then added it to the "Result" Sheet.
function splitNewRow() {
var source = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Source for Script");
var data = source.getRange(2, 1, source.getLastRow(), source.getLastColumn()).getValues();
var outcomeSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Result");
newArray = [];
newRow = [];
for (i=0; i < data.length; i++){
var claim = source.getRange(i+2,1).getValue();
var mainClient = source.getRange(i+2,2).getValue();
var others = source.getRange(i+2, 3).getValue();
hasComma = others.indexOf(",") != -1;
if (others != "" && hasComma == true){
newArray = [];
newArray = others.split(",");
newArray.push(mainClient);
for (j=0; j < newArray.length; j++){
newRow = [claim, newArray[j]];
outcomeSheet.appendRow(newRow);
}
}
else if(others != "" && hasComma == false){
newRow = [claim, mainClient];
outcomeSheet.appendRow(newRow);
newRow = [claim, others];
outcomeSheet.appendRow(newRow);
}
else{
newRow = [claim, mainClient];
outcomeSheet.appendRow(newRow);
}
}
}
After running the script, you get the following:
If you have any questions, let me know.

Formula to ignore hidden columns

I am trying to count visible columns in a spreadsheet with no luck. I've been trying using SUBTOTAL function but it's applied to hidden/visible rows only. I also tried working with CELL("width") function, but it doesn't return 0 when a cell is hidden
Is there any other option to ignore hidden columns in a count formula?
You can definitely create your own custom function using Google Apps Script.
For example, the following function counts the number of visible columns in your active sheet:
function countVisibleColumns() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet()
var n_cols = sheet.getMaxColumns();
var hidden_cols = []
var cnt = 0;
for (var i=1; i<=n_cols ; i++) {
if ( sheet.isColumnHiddenByUser(i) ){
continue;}
else {cnt +=1} }
Logger.log(cnt)
return cnt;
}
You just need to click on Tools => Script editor and then copy the aforementioned code into a blank script. Then you can directly use the function as a formula in the google sheet like =countVisibleColumns().
See screenshot attached for more information.

How to pass cell value to a SUM function

I am trying to do a SUM of last 12 rows in the column (I'll be adding more rows into this column so I wanted to automate the calculation).
First of all, I am able to get the value of last cell with some value in this column by =SUMPRODUCT(MAX((B1:B200<>"")*ROW(B1:B200))) - result is stored in C1. However, I am not sure how to use this value inside the SUM formula, I was thinking something like =SUM(B(get value of C1)-12:B(get value of C1).
I tried multiple things but none of them have worked - I also don't mind using a different approach if it gets the job done.
You can create your own custom function to do that using Google Apps Script (GAS).
Try the following:
function onEdit(e){
var row = e.range.getRow();
var col = e.range.getColumn();
if ( col==2 && e.source.getActiveSheet().getName() == "Sheet1" ){
e.source.getActiveSheet().getRange("C1").setValue(sumLast12());
}
}
function sumLast12() {
var sheet = SpreadsheetApp.getActive().getSheetByName("Sheet1");
var sheet_size = sheet.getLastRow();
var elmt = sheet.getRange("B1:B"+sheet_size).getValues().flat([1]);
var elmt12 = elmt.slice(-12);
var sum = 0;
for( var i = 0; i < elmt12.length; i++ ){
sum += parseInt( elmt12[i], 10 );
}
return sum;
}
Explanation:
In order to activate this functionality go the menu bar on top of the
spreadsheet file and click on Tools => Script editor and copy the
aforementioned code into a blank script document (see attached
screenshot for more information) and save the document (cntrl+s).
After the script has been saved, everytime you edit a cell in column
B (either by adding a new value on the bottom or modify an existing value, the script will automatically update the value in
cell C1 with the sum of the last 12 values in column B.
Note that if you don't want to change my code, name the sheet you are working with as Sheet1.
Does this work?
=SUM(FILTER(B:B,ROW(B:B)>=MAX(ROW(B:B))-12)

Google script to send conditional emails based on cells in google sheets

I have a google sheet that I would like to have generate an email alert when one column is greater than the other. Specifically, column F > column G. Here is what I have so far, any advice would be greatly appreciated, as I do not have much skill writing functions.
function readCell() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Watch list");
var value = sheet.getRange("F2").getValue();
var value1 = sheet.getRange("G2").getValue();
if(value>value1) MailApp.sendEmail('example#gmail.com', 'subject', 'message');
};
Currently this only attempts to compare cell F2 to cell G2. Is there a way to make the function compare the entire F column against column G, and generate an email for each individual case where Fx > Gx ?
Thank you!!
You have to loop all over the range.
first instead of getting the content of one cell you'll need to get the content of all the column:
var value = sheet.getRange("F2").getValue();
become that
var values = sheet.getRange("F2:F").getValues();
(same for value1)
then you need to create an empty table that will collect the results:
var results = [];
and now you need to loop throught all the values:
for(var i=0;i<values.length;i++){
//do the comparaison and store result if greater for example
}
then you may send the result.
all put together it give something like that:
function readCell() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Watch list");
var values = sheet.getRange("F2:F").getValues();
var value1s = sheet.getRange("G2:G").getValues();
var results = [];
for(var i=0;i<values.length;i++){
if(values[i]<value1s[i]){
results.push("alert on line: "+(i+2)); // +2 because the loop start at zero and first line is the second one (F2)
}
}
MailApp.sendEmail('example#gmail.com', 'subject', results.join("\n"));
};
If you want to trigger that function automatically you'll also need to change the way you call the spreadsheet (instead of getActive.... you'll need to use openById)

Concatenate certain rows into a cell ignoring duplicates

I have a google form and I would like to sort it's responses in a separate sheet on google sheets. The results of the form look sort of like this.
Id Job
1 Shelving, Sorting
2 Sorting
1 Cleaning, Shelving
3 Customer Service
2 Shelving, Sorting
which I would like to format into
Id Jobs
1 Cleaning, Shelving, Sorting
2 Shelving, Sorting
3 Customer Service
Is there a formula I can use to accomplish this, noting that it ignores duplicates and groups the different ids? Ordering of the jobs does not matter.
Working example here.
The code is like:
=unique(transpose(split(join(", ",filter(B1:B10,A1:A10=1)),", ")))
where
filter(B1:B10,A1:A10=1) gives you all the B values where A = 1
join(",", filter(...)) joins the list with the ", " separator (e.g. "apple, orange" and "kiwi" becomes "apple, orange, kiwi"
split(join(...)) splits the list into an array (e.g. back to [apple, orange, kiwi]
transpose(split(...)) converts the horizontal list to vertical list
unique(transpose(...)) gives you the unique values (unique() only works with vertical list)
After this, you need to transpose then join the list
Note you must keep the separator consistent (e.g. always "," or ", ")
This is Apps Script code instead of a function. To use it, you will need to use the Tools menu, and open the script editor. Then select the function name from the drop down list, and then click the "Run" button.
To use this code, you need to have a source and a destination sheet. You will need to change the sheet names in the code to your sheet names. In this code, the source sheet is named 'Data'. You will need to change that to the name of your source sheet. In this code, the destination sheet is named 'Output', and is at the bottom of the code. This code gets data starting in row two, and writes the output data starting in row two. I tested it with your values and it works.
function concatCellData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheetByName('Data');
var colOneData = sh.getRange(2, 1, sh.getLastRow()-1, 1).getValues();
var colTwoData = sh.getRange(2, 2, sh.getLastRow()-1, 1).getValues();
var newData = [],
newDataColOne = [],
colOneValue,
existInNewData = false,
colB_One,
colB_Two,
dataPosition,
thisValue,
combinedArrays = [],
arrayTemp = [];
for (var i=0;i<colOneData.length;i+=1) {
colOneValue = colOneData[i][0];
dataPosition = newDataColOne.indexOf(colOneValue);
existInNewData = dataPosition !== -1;
if (!existInNewData) {//If it doesn't exist in the new data, just write the values
newDataColOne.push(colOneValue);
newData.push([colOneValue, colTwoData[i][0]]);
continue;
};
colB_One = [];
colB_Two = [];
combinedArrays = []
arrayTemp = [];
colB_One = colTwoData[i][0].split(",");
colB_Two = newData[dataPosition][1];
colB_Two = colB_Two.split(",");
var combinedArrays = colB_One.concat(colB_Two);
//Get unique values
for (var j=0;j<combinedArrays.length;j+=1) {
thisValue = combinedArrays[j].trim();
if (arrayTemp.indexOf(thisValue) === -1) {
arrayTemp.push(thisValue);
};
};
newData[dataPosition] = [colOneValue, arrayTemp.toString()]; //Overwrite existing data
};
ss.getSheetByName('Output').getRange(2, 1, newData.length, newData[0].length).setValues(newData);
};

Resources