Google Sheets - Compare Differing Rows - google-sheets

I have a two spreadsheets with that are practically clones of each other, however there are some differences. I would like to compare two sheets. I will take care of importing it so that it can be easier to compare.
What I am comparing are rows of information including Name, Address, Status. Over the course of time, the status has been updated in one of the sheets. I'd like to be able to identify cells within the rows that are not alike.

You can do that using Google Apps Script. The following code works as an example to accomplish this:
var OTHER_SPREADSHEET_ID = "OTHER_SPREADSHEET_ID";
var NUM_COLUMNS = 4;
function checkDifferences() {
var otherSheet = SpreadsheetApp.openById(OTHER_SPREADSHEET_ID).getSheetByName('Sheet1');
var sheet = SpreadsheetApp.getActive().getSheetByName('Sheet1');
var lastRow = sheet.getLastRow();
var thisValues = sheet.getRange(1, 1, lastRow, NUM_COLUMNS).getValues();
var otherValues = otherSheet.getRange(1, 1, lastRow, NUM_COLUMNS).getValues();
for (var i=0; i<lastRow; i++) {
if (!rowsAreEqual(thisValues[i], otherValues[i])) {
// Mark row
sheet.getRange(i+1, 1, 1, NUM_COLUMNS).setBackground("yellow");
}
}
}
function rowsAreEqual(row1, row2) {
for (var i=0; i<row1.length; i++) {
if (row1[i] !== row2[i]) return false;
}
return true;
}
Simply explained, the code does the following:
Open the Spreadsheet that you want the current spreadsheet to be compared to.
For each row, if the rows differ change the background color of the "host" Spreadsheet (the Spreadsheet that has the code bound to).
Example
After executing the code (bound to the "Modified" Spreadsheet) the sheet becomes as follows:
References
Google Apps Script
SpreadsheetApp
Class Range

Related

"Error parsing int value [#N/A]" when querying a Google Spreadsheet using CDATA

We are trying to query a Google Spreadsheet that has some fields with #N/A in them.
#N/A errors in Google Spreadsheet indicate missing information and signal functions to cease calculation.
We just want want these #N/A values to be treated as NULLs.
What is the best way to do this using the CData connector for Google Spreadsheet?
I presume setting your formulas to ifError isn't an option in your spreadsheet? That seems like the most sensible. Example, =iferror(vlookup(foo),) returns null instead of #N/A.
Assuming not, here's an app script that could review your data and replace values, or create a new sheet in your spreadsheet with updated values.
function fixErrorsInSheet(_sh) {
const errorValues = ["#NULL!", "#DIV/0!", "#VALUE!", "#REF!", "#NAME?", "#NUM!", "#N/A"];
if (_sh === undefined) {
_sh = SpreadsheetApp.getActiveSheet();
}
const ss = _sh.getParent();
var dataRange = _sh.getDataRange();
var allValues = dataRange.getValues();
for (var i = 0; i < allValues.length; i++) {
for (var j = 0; j < allValues[i].length; j++) {
var oneValue = allValues[i][j];
if (errorValues.includes(oneValue)) {
allValues[i].splice(j, 1, null);
}
}
}
//optional to update sheet, or you could query this array directly with cData;
dataRange.setValues(allValues);
//create new sheet with updated values...
//ss.setActiveSheet(_sh);
//var newSheet = ss.duplicateActiveSheet();
//newSheet.getRange(1,1,dataRange.getLastRow(),dataRange.getLastColumn()).setValues(allValues);
}
//use this to run on all sheets
function runFixOnAllWorkbooks() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
ss.getSheets().forEach(fixErrorsInSheet);
}

How do I find and delete duplicate values in a range of cells while keeping the first occurrence of a duplicated value in Google Sheets?

Ideally, I want to be able to search through an entire sheet (or range of cells) and remove any values that have been repeated in that sheet (for example, if "2" appears in A3, B8, and D4, then I want to keep it in A3 and delete it in B8 and D4).
I normally see this problem addressed by looking at one column or row for duplicates (using the UNIQUE function) but not for an entire sheet.
How can I do this?
Here's some code that will do that for an entire sheet.
Please note it will work on text and numbers and it will overwrite any formulas.
function removeDuplicates() {
var sheet = SpreadsheetApp.getActive().getActiveSheet();
var range = sheet.getDataRange();
var values = range.getValues();
var traversedValues = [];
var rowCount = values.length;
var colCount = values[0].length;
for (var row = 0; row < rowCount; ++row) {
for (var col = 0; col < colCount; ++col) {
var value = values[row][col];
if (traversedValues.indexOf(value) > -1) {
values[row][col] = null;
} else {
traversedValues.push(value);
}
}
}
range.setValues(values);
}
References for you
Beginner's guide to coding with Google Apps Script
For loops
if...else statements
Arrays

Removing a row in sheet 2 from imported data from sheet 1 in google spreadsheet

screenshot
Hi all, i need help and i am not a coder. I am trying to achieve the same thing on sheet number 2.
My datas are imported through "=Submission!$b2" from sheet 1
i need help removing rows automatically when a specific cell on column H does not contain the value "Bekreft", i tried both codes shown here with no success.
This is what i added for script:
function onEdit() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName('DATA - Do Not Touch!!!'); // change to your own
var values = s.getDataRange().getValues();
for(var i=values.length;i>0;i-=1){
var lcVal=values[i-1][0].toLowerCase() //Change to all lower case
var index = lcVal.indexOf("vent"); //now you only have to check for contains "vent"
if (lcVal.indexOf("vent") > -1){
s.deleteRow(i)};
}}
Seeing as you state you are "not a coder", and the code you pasted will not help you if you are referencing data from another page, I would suggest using a filter function to achieve your goal. You would add the following formula to your second page:
=FILTER(Submission!B:B,ISNUMBER(SEARCH("Bekreft", Submission!H:H)))
If you are looking to have a script go through your static list and delete out values that do not contain "Bekreft" then you can use the following script.
function onEdit() {
var sheet = SpreadsheetApp.openById("Add Sheet ID").getSheetByName('Sheet1');
var rows = sheet.getDataRange();
var numRows = rows.getNumRows();
var values = rows.getValues();
var rowsDeleted = 0;
for (var i = 0; i <= numRows - 1; i++) {
var row = values[i];
//row for condition
if (row[7].indexOf("Bekreft")) {
sheet.deleteRow((parseInt(i)+1) - rowsDeleted);
rowsDeleted++;
}
}
};

Google Sheets Lookup Tool Assistance

I've taken it upon myself the learn how to "excel". That made a little more sense in my head, but hey.
I have built a "lookup tool" which can be viewed here.
The "Dishwasher search" is working as intended. You can search by noise level or decor panel height to create a list of suitable models then pull the data into an individual search by product code/model no.
I decided to make it a little more difficult and created one for Ovens.
The Layout is like this; Main search>Single Oven Database>Double Oven Database>Built-under oven database.
My goal is to achieve the same search facilities as the "Dishwasher tool", however I have been unsure how to search (Vlookup) from different sources.
I have tried creating a "Master DB" using the formula below;
={Importrange("1mY13e-75dBYfKgkjV8dFFFEvxC838nGNxPrUdusc0PA", "'Single Ovens'!$A:$F");Importrange("1mY13e-75dBYfKgkjV8dFFFEvxC838nGNxPrUdusc0PA", "'Double Ovens'!$A:$F");Importrange("1mY13e-75dBYfKgkjV8dFFFEvxC838nGNxPrUdusc0PA", "'Built-Under Ovens'!$A:$F")))}
However, it only seems to pull data from the first range not the others unless I do it horizontaly rather than vertical, but horizontal wont work with my Vlookup formula (To my knowledge).
The other method I have tried is using this code;
=IF(AND($A$19="Single Oven",$A$4>0), Vlookup($A$4,'Single Ovens'!$B:$F,1,False),IF(AND($A$10="Double Oven",$A$4>0), Vlookup($A$4,'Double Ovens'!$B:$F,1,False),If(AND($A$10="Built-Under Oven",$A$4>0), Vlookup($A$4,'Built-Under Ovens'!$B:$F,1,False),IF($A$10="Single Oven",Vlookup($A$7,'Single Ovens'!$A:$F,2,False),IF($A$10="Double Oven", Vlookup($A$7,'Double Oven'!$A:$F,2,False),If($A$10="Built-Under Oven", Vlookup($A$7,'Built-Under Oven'!$A:$F,2,False)))))))
The above code was inserted and was "meant" to Vlookup all 3 sheets and pull "product Code" through to populate Cell D4 on sheet 'Ovens'.
Now, I'm a bit of a novice at this but I'm working to understand it all :)
Any suggestions you guys can make or point me in the right direction?
Edit -
Sorry guys. It was rude not to post my solution. I have changed my Importrange function to =Importrange("XYZ",""'Single Ovens'!$A2:$F200") and repeated this 3 times with a gap of 200 "rows" between each one. Not a solution, but a viable alternative. My friend is currently working on a script for me to achieve this. The Vlookup formula no longer needs to be as complex thanks to the importrange formula simplifying matters.
So after discussing the problem with McSheehy, and the problem is actually this.
How to get data from ONE spreadsheet, multiple sheets of my choice.
and write To MANY spreadsheets, Multiple sheets within those spreadsheets, of my choice.
Once that data is in the right place, the current formulas should work or can be adapted easily.
I came up with a script solution,
The user creates a settings sheet in the source sheet.
In A2 downwards, Target spreadsheet keys, B2 downwards, Source sheet names you wish to include from current sheet. C2 downwards is the target SHEET names, if you wanted to write data to more than one sheet.
Bits of code are annotated to help explain McSheehy's questions on how it works.
If anyone has any improvements to suggest, and I'm sure there are some, particular the headers bit. (its not needed, but my clearContent/clearConents line kept flipping out), I'm all ears.
Thanks
function getOvenDataV5(){
var settingsSheetName = "monkey_settings";
/* DO NOT EDIT BELOW THIS LINE */
var ss = SpreadsheetApp.getActiveSpreadsheet();
var settings = ss.getSheetByName(settingsSheetName);
// this bit has been edited, note the getValues, not getValue, as we want the whole column now not just a single cell.
var targetSheetsValues = settings.getRange("C2:C").getValues(); // this gets the target sheet names from the settings sheet
var targetSheets = []; // And array added to throw target sheet names into, as there is more than one.
// the reason we use arrays and loops (later on), is because the script has no idea how much data to expect.
// so we go through whatever it's grabbed, the stuff it thinks is data, but we check it later on.
// only a simple check. Our check is that it cannot be blank. ""
// then stuff it in an array, a handy thing to store data, for use later on.
var sSheets = settings.getRange("B2:B").getValues();
var sourceSheets = [];
// new loop below to get the target sheets names. We'll use this in the write bit later.
for(var i = 0; i < targetSheetsValues.length;i++){
if(targetSheetsValues[i][0]!=""){
targetSheets.push(targetSheetsValues[i]);
}
}
for(var i = 0; i < sSheets.length;i++){
if(sSheets[i][0]!=""){
sourceSheets.push(sSheets[i]);
}
}
var dKeys = settings.getRange("A2:A").getValues();
var sKeys = [];
for(var i = 0; i < dKeys.length;i++){
if(dKeys[i][0]!=""){
sKeys.push(dKeys[i]);
}
}
var data = [];
for (var i = 0; i < sourceSheets.length;i++){
var values = ss.getSheetByName(sourceSheets[i]).getDataRange().getValues();
for (var x = 1;x < values.length; x++){
if(values[x][0]!= ""){
data.push(values[x]);
}
}
}
// Below is an array of your column headers, the script was being annoying when clearing sheet data, so decided to clear the whole damn sheet
// then write the headers via here instead
var headers = [["Model No", "Product Code", "Brand", "Model No", "kW", "Amp"]];
for (var i = 0; i< sKeys.length;i++){
var tss = SpreadsheetApp.openById(sKeys[i]);
for(var x = 0; x < targetSheets.length;x++){ // this loop, within the keys loop, goes through the target sheets array
var target = tss.getSheetByName(targetSheets[x]); // this loads the target sheet, one by one
var range = target.getRange(2,1, data.length, data[0].length); // this gets the cells to write to
target.clearContents(); // clear the sheet before writing data
target.getRange("A1:F1").setValues(headers); // write the headers to a1:F1 in target sheet
range.setValues(data); //write the data
}
}
}
I dont know if they will be of any value but here are two things that i wrote in script.
The follow is a vlookup script to set or return to memory with hints of query ish abilites.
//~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`
//--//Dependent on isEmpty_()
// Script Look-up
/*
Benefit of this script is:
-That google sheets will not continually do lookups on data that is not changing with using this function as it is set with hard values until script is kicked off again.
-Unlike Vlookup you can have it look at for reference data at any Column in the row. Does not have to be in the first column for it to work like Vlookup.
-You can return the Lookup to Memory for further processing by other functions
Useage:
Lookup_(Sheetinfo,"Sheet1!A:B",0,[1],"Sheet1!I1","n","y");
//or
Lookup_(Sheetinfo,"Sheet1!A:B",0,[1],"return","n","n");
//or
Lookup_(Sheetinfo,"Sheet1!A:B",0,[0,1],"return","n","n");
//or
Lookup_(Sheetinfo,"Sheet1!A:B",1,[0],"return","y","n");
//or
Lookup_("cat","Sheet1!A:G",4,[0],"Database!A1","y","y");
-Loads all Locations numbers from J2:J into a variable
--looks for Location Numbers in Column 0 of Referance sheet and range eg "Data!A:G"
---Returns results to Column 3 of Target Sheet and range eg "test!A1" or "1,1"
*/
function Lookup_(Search_Key,RefSheetRange,SearchKey_Ref_IndexOffSet,IndexOffSetForReturn,SetSheetRange,ReturnMultiResults,Add_Note)
{
var RefSheetRange = RefSheetRange.split("!");
var Ref_Sheet = RefSheetRange[0];
var Ref_Range = RefSheetRange[1];
if(!/return/i.test(SetSheetRange))
{
var SetSheetRange = SetSheetRange.split("!");
var Set_Sheet = SetSheetRange[0];
var Set_Range = SetSheetRange[1];
var RowVal = SpreadsheetApp.getActive().getSheetByName(Set_Sheet).getRange(Set_Range).getRow();
var ColVal = SpreadsheetApp.getActive().getSheetByName(Set_Sheet).getRange(Set_Range).getColumn();
}
var twoDimensionalArray = [];
var data = SpreadsheetApp.getActive().getSheetByName(Ref_Sheet).getRange(Ref_Range).getValues(); //Syncs sheet by name and range into var
for (var i = 0, Il=Search_Key.length; i<Il; i++) // i = number of rows to index and search
{
var Sending = []; //Making a Blank Array
var newArray = []; //Making a Blank Array
var Found ="";
for (var nn=0, NNL=data.length; nn<NNL; nn++) //nn = will be the number of row that the data is found at
{
if(Found==1 && ReturnMultiResults.toUpperCase() == 'N') //if statement for found if found = 1 it will to stop all other logic in nn loop from running
{
break; //Breaking nn loop once found
}
if (data[nn][SearchKey_Ref_IndexOffSet]==Search_Key[i]) //if statement is triggered when the search_key is found.
{
var newArray = [];
for (var cc=0, CCL=IndexOffSetForReturn.length; cc<CCL; cc++) //cc = numbers of columns to referance
{
var iosr = IndexOffSetForReturn[cc]; //Loading the value of current cc
var Sending = data[nn][iosr]; //Loading data of Level nn offset by value of cc
if(isEmpty_(Sending)) //if statement for if one of the returned Column level cells are blank
{
var Sending = "#N/A"; //Sets #N/A on all column levels that are blank
}
if (CCL>1) //if statement for multi-Column returns
{
newArray.push(Sending);
if(CCL-1 == cc) //if statement for pulling all columns into larger array
{
twoDimensionalArray.push(newArray);
var Found = 1; //Modifying found to 1 if found to stop all other logic in nn loop
break; //Breaking cc loop once found
}
}
else if (CCL<=1) //if statement for single-Column returns
{
twoDimensionalArray.push(Sending);
var Found = 1; //Modifying found to 1 if found to stop all other logic in nn loop
break; //Breaking cc loop once found
}
}
}
if(NNL-1==nn && isEmpty_(Sending)) //following if statement is for if the current item in lookup array is not found. Nessessary for data structure.
{
for(var na=0,NAL=IndexOffSetForReturn.length;na<NAL;na++) //looping for the number of columns to place "#N/A" in to preserve data structure
{
if (NAL<=1) //checks to see if it's a single column return
{
var Sending = "#N/A";
twoDimensionalArray.push(Sending);
}
else if (NAL>1) //checks to see if it's a Multi column return
{
var Sending = "#N/A";
newArray.push(Sending);
}
}
if (NAL>1) //checks to see if it's a Multi column return
{
twoDimensionalArray.push(newArray);
}
}
}
}
if (CCL<=1) //checks to see if it's a single column return for running setValue
{
var singleArrayForm = [];
for (var l = 0,lL=twoDimensionalArray.length; l<lL; l++) //Builds 2d Looping-Array to allow choosing of columns at a future point
{
singleArrayForm.push([twoDimensionalArray[l]]);
}
if(!/return/i.test(SetSheetRange))
{
SpreadsheetApp.getActive().getSheetByName(Set_Sheet).getRange(RowVal,ColVal,singleArrayForm.length,singleArrayForm[0].length).setValues(singleArrayForm);
SpreadsheetApp.flush();
if(/y/i.test(Add_Note))
{
SpreadsheetApp.getActive().getSheetByName(Set_Sheet).getRange(RowVal,ColVal,1,1).setNote("VLookup Script Ran On: " + Utilities.formatDate(new Date(), "PST", "MM-dd-yyyy hh:mm a") + "\nRange: " + Ref_Sheet + "!" + Ref_Range);
}
}
else
{
return singleArrayForm
}
}
if (CCL>1) //checks to see if it's a multi column return for running setValues
{
if(!/return/i.test(SetSheetRange))
{
SpreadsheetApp.getActive().getSheetByName(Set_Sheet).getRange(RowVal,ColVal,twoDimensionalArray.length,twoDimensionalArray[0].length).setValues(twoDimensionalArray);
SpreadsheetApp.flush();
if(/y/i.test(Add_Note))
{
SpreadsheetApp.getActive().getSheetByName(Set_Sheet).getRange(RowVal,ColVal,1,1).setNote("VLookup Script Ran On: " + Utilities.formatDate(new Date(), "PST", "MM-dd-yyyy hh:mm a") + "\nRange: " + Ref_Sheet + "!" + Ref_Range);
}
}
else
{
return twoDimensionalArray
}
}
}
//~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`
//~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`
//--//Dependent on isEmpty_()
//Find Last Row on Database
function getFirstEmptyRowUsingArray_(sheetname)
{
var data = SpreadsheetApp.getActive().getSheetByName(sheetname).getDataRange().getValues();
for(var n = data.length ; n>0 ; n--)
{
if(isEmpty_(data[n])==false)
{
n++;
break;
}
}
n++;
return (n);
}
//~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`
The Following is a ImportRange script because I hate how =importrange() requires you to "request access" on every new formula. If that importrange is embedded you have to take it out and request access and re-embed it. Also a lot of times the formula just breaks. so:
//~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`
//Script Based ImportRange
//Example importRange_('0AodPsggrbsh1dDNH............','Main4NS','A:G','Common','C7','y')
//Explanation importRange_('Importing Spreadsheet Key or URL','Importing Spreadsheet Tab Name','Importing Spreadsheet Tab's Range','Destination Spreadsheet Tab Name','Destination Spreadsheet Tab's placement','Will add note to the first cell of import')
function importRange_(Source_Key,Source_Sheet,Source_Range,Set_Sheet,Set_Pos,Add_Note)
{
var SourceTypeCheck = Source_Key.indexOf("https://");
if(SourceTypeCheck >= 0)
{
var Load = SpreadsheetApp.openByUrl(Source_Key).getSheetByName(Source_Sheet).getRange(Source_Range).getValues();
var Name = SpreadsheetApp.openByUrl(Source_Key).getName();
}
if(SourceTypeCheck == -1)
{
var Load = SpreadsheetApp.openById(Source_Key).getSheetByName(Source_Sheet).getRange(Source_Range).getValues();
var Name = SpreadsheetApp.openById(Source_Key).getName();
}
var RowVal = SpreadsheetApp.getActive().getSheetByName(Set_Sheet).getRange(Set_Pos).getRow();
var ColVal = SpreadsheetApp.getActive().getSheetByName(Set_Sheet).getRange(Set_Pos).getColumn();
if(Add_Note.toUpperCase() == 'Y')
{
SpreadsheetApp.getActive().getSheetByName(Set_Sheet).getRange(RowVal,ColVal,1,1).setNote("Import Script Updated On: " + Utilities.formatDate(new Date(), "PST", "MM-dd-yyyy hh:mm a")+"\nSS Name: "+Name+"\nRange: "+Source_Sheet+"!"+Source_Range+"\nSS Key: "+ Source_Key);
}
SpreadsheetApp.getActive().getSheetByName(Set_Sheet).getRange(RowVal,ColVal,Load.length,Load[0].length).setValues(Load);
SpreadsheetApp.flush();
SpreadsheetApp.getActiveSpreadsheet().toast('At: '+Set_Sheet+'!'+Set_Pos,'Import Completed:');
}
//~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`~,~`
Same thing stands. If you have and ideas for improvement let me know. If you find a way to integrate it, cool beans, Post some code of how you used it.
:)

Google Sheets: Range Not Found

I am new with Google Sheets scripts and I can't seem to figure why I am getting this error: Range not found (line 4, file "Code"). I have followed everything from https://developers.google.com/apps-script/guides/sheets/functions#creating_a_custom_function
Here is my code:
function getBgColor(input) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var range = sheet.getRange(input);
return range.getBackground();
}
I appreciate all the assistance.
Your code should be fine if your input range is only one cell, at least if you pass it in as a string. =getBgColor("D1").
However, if you want to pass in a range, I think you will have to loop to that range in order to get the colors of the whole range. So you'll need something like this (untested):
function getBgColor(input) {
var bgs = SpreadsheetApp.getActiveSheet().getRange(input).getBackgrounds(),
colors = [];
for(var i = 0; i < bgs.length; i++){
colors.push(bgs[i]);
}
return colors;
}
That should give you a range with all the backgroundcolors of the range that you passed it. If you would want those colors in one cell, use: return colors.join(", "). If you want to return only unique colors, there are also ways to do that..
See if this helps first ?

Resources