Get data from variable "Users" and put data in fields in Spreadsheet - javascript

I have this script from Google Developer site that fetches all the domain users:
function listAllUsers() {
var pageToken, page;
do {
page = AdminDirectory.Users.list({
domain: 'wter.se',
orderBy: 'givenName',
maxResults: 100,
pageToken: pageToken
});
var users = page.users;
if (users) {
for (var i = 0; i < users.length; i++) {
var user = users[i];
}
}
pageToken = page.nextPageToken;
} while (pageToken);
}
I would like to get each users parameters and add them to a spreadsheet.
The variable users have all these parameters (users.EmailAdress etc), but how do i put them in a spreadsheet?

You have to build an array of arrays (a 2D array) with one array for each row in the sheet, here is an example with 3 columns that list all the users of my domain using the simple UserManager class.
The code structure is pretty much the same, a for loop and users[i] properties...
The output array here is called 'r' and is written in the sheet using the final setValues(r); - the code has also a sorting function that you don't need but I left it here for info if ever someone needs it.
function listUsers(s) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet()
sheet.getDataRange().clear()
var users = UserManager.getAllUsers();
var r = new Array();
var f = new Array();
for( var i = 0 ; i < users.length ; i++ ){
var Umail = users[i].getEmail();
var UnomF = users[i].getFamilyName()
var UnomP = users[i].getGivenName()
r.push([UnomF,UnomP,Umail]);
}
r.sort(function(x,y){
var xp = x[0].toLowerCase();
var yp = y[0].toLowerCase();
return xp == yp ? 0 : xp < yp ? -1 : 1;// sort on name ascending
}
)
var header = ['Nom de famille','Prénom','Email']
sheet.getRange(1,1,1,r[0].length).setValues([header]).setFontWeight('bold')
.setBackground('silver').setBorder(true,true,true,true,true,true);
sheet.getRange(2,1,r.length,r[0].length).setValues(r);
}

Related

Add contact if contact does not exist under google contacts with “ContactsApp.getContact”

I found the following code as a response to the same question at Check if contact exists under google contacts with "ContactsApp.getContact" but am having some trouble. I am trying to create a Google Script that checks to see if a respondent to a Google Survey already has a contact card in 'System Group: My Contacts' and if not, create a contact card and then add their phone number.
I've updated the following code to reference my fields, but am receiving an error for the line if(emailjson[email.toLowerCase()].id) - which is meant to check to see if that contact existed:
TypeError: Cannot read property "id" from undefined. (line 36, file "Code")
I thought that there was a problem with the IF statement, but I'm not completely familiar with Javascript (or JSON). As an Excel and Access person I'm accustomed to IF statements having a IF something is null, then do this, which so I tried adding === undefined, changing the code to if(emailjson[email.toLowerCase()].id === undefined) but that didn't solve the problem. In looking at the Execution Transcript, it hangs up as soon as it hits someone who doesn't have a contact card.
If I remove new contacts from the beginning of my spreadsheet and go back to the original code (without === undefined), then it creates duplicate contact cards for everyone who already had a card to start with until it reaches the next person who is new, and then it errors out again.
For the people who already have contact cards, I've also received an error on the next line if the phone number in the spreadsheet is just numbers, if(!emailjson[email.toLowerCase()]['phones'][phone.replace(/[_)(\s.-]/g,'')]) {.
TypeError: Cannot find function replace in object 2024313437. (line 37, file "Code")
If I add formatting to the phone number, then it doesn't throw an error (although as I mentioned before, it creates a duplicate contact). Oddly, I I run the function emailsasJSON afterwards, it only shows one contact card as opposed to a duplicate card, even though on the Google Contacts screen I see a contact card for every time I've attempted to run the script.
Thanks in advance for your thoughts.
function emailsasJSON() {
var emailjson = {}
var myContacts = ContactsApp.getContactGroup('System Group: My Contacts').getContacts();
for (var i = 0; i < myContacts.length; i++) {
var emails = myContacts[i].getEmails();
var phonesobj = myContacts[i].getPhones();
var phones = {}
for (var j = 0; j < phonesobj.length; j++) {
phones[phonesobj[j].getPhoneNumber().replace(/[_)(\s.-]/g,'')] = 1;
}
for (var j = 0; j < emails.length; j++) {
emailjson[emails[j].getAddress().toLowerCase()] = {id: myContacts[i].getId(), phones: phones};
}
}
Logger.log(JSON.stringify(emailjson))
return emailjson;
}
function addClient() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheetNew = ss.getActiveSheet();
var clientsgroup = ContactsApp.getContactGroup('System Group: My Contacts')
//this is where we will insert the function from above to get the emailjson obj
var emailjson = emailsasJSON()
var contactarray = sheetNew.getDataRange().getValues();
for (var i = 1 ; i < contactarray.length; i++){
var name = contactarray[i][1]
var email = contactarray[i][4]
var phone = contactarray[i][3]
if(emailjson[email.toLowerCase()].id) { //check if email exists
if(!emailjson[email.toLowerCase()]['phones'][phone.replace(/[_)(\s.-]/g,'')]) { //if email exists but phone doesn't, add phone
ContactsApp.getContactById(emailjson[email.toLowerCase()].id).addPhone(ContactsApp.Field.MOBILE_PHONE, phone)
emailjson[email.toLowerCase()]['phones'][phone.replace(/[_)(\s.-]/g,'')] = 1; //add it to the emailjson object in case there are more iterations of this contact in the sheet
}
} else { //add new contact if it doesn't exist
var newcontact = ContactsApp.createContact(name.split(' ')[0],name.split(' ')[1], email)
newcontact.addPhone(ContactsApp.Field.MOBILE_PHONE, phone)
emailjson[email.toLowerCase()]['id'] = newcontact.getId();
emailjson[email.toLowerCase()]['phones'][phone.toString().replace(/[_)(\s.-]/g,'')] = 1;
clientsgroup.addContact(newcontact)
}
}
}
Sample Data:
Your main issue is that your function emailsasJSON() stringified the json object (i.e it was a string) and therefore you could not access successfully the key pair values of the JSON object. To solve this I just parsed the object to make sure it was consistent but as long as you wouldn't have converted it into a string it would have been ok.
The next change is in the first if condition. You don't actually need to check for the id to see if the element exists as just by checking the element itself would do the job (although checking the id would work too).
Finally the way you constructed your json object for the new contact was not done correctly so I have corrected it accordingly to add the appropriate key value pairs.
function emailsasJSON() {
var emailjson = {}
var myContacts = ContactsApp.getContactGroup('System Group: My Contacts').getContacts();
for (var i = 0; i < myContacts.length; i++) {
var emails = myContacts[i].getEmails();
var phonesobj = myContacts[i].getPhones();
var phones = {}
for (var j = 0; j < phonesobj.length; j++) {
phones[phonesobj[j].getPhoneNumber().replace(/[_)(\s.-]/g,'')] = 1;
}
for (var j = 0; j < emails.length; j++) {
emailjson[emails[j].getAddress().toLowerCase()] = {id: myContacts[i].getId(), phones: phones};
}
}
emailjson = JSON.stringify(emailjson);
emailjson = JSON.parse(emailjson);
return emailjson;
}
function addClient() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheetNew = ss.getActiveSheet();
var clientsgroup = ContactsApp.getContactGroup('System Group: My Contacts')
//this is where we will insert the function from above to get the emailjson obj
var emailjson = emailsasJSON()
var contactarray = sheetNew.getDataRange().getValues();
for (var i = 1 ; i < contactarray.length; i++){
var name = contactarray[i][1]
var email = contactarray[i][4]
var phone = contactarray[i][3]
if(emailjson[email.toLowerCase()]) { //check if email exists
if(!emailjson[email.toLowerCase()]['phones'][phone.toString().replace(/[_)(\s.-]/g,'')]) { //if email exists but phone doesn't, add phone
ContactsApp.getContactById(emailjson[email.toLowerCase()].id).addPhone(ContactsApp.Field.MOBILE_PHONE, phone)
emailjson[email.toLowerCase()]['phones'][phone.toString().replace(/[_)(\s.-]/g,'')] = 1; //add it to the emailjson object in case there are more iterations of this contact in the sheet
}
} else { //add new contact if it doesn't exist
var newcontact = ContactsApp.createContact(name.split(' ')[0],name.split(' ')[1], email);
var newContactId = newcontact.getId();
var phoneNumber = phone.toString().replace(/[_)(\s.-]/g,'');
ContactsApp.getContactById(newContactId).addPhone(ContactsApp.Field.MOBILE_PHONE, phone);
emailjson[email.toLowerCase()] = {id:newContactId,phones:{phoneNumber : 1}}
clientsgroup.addContact(newcontact)
}
}
}
Reference
Guide for working with JSON in JavaScript

How to get all items list on NetSuite?

I am just starting with NetSuite and trying to pull all items with details using Restlet. With some research, I am able to pull all the items but the way I am doing now is not straightforward. I first pull the all ids of item using nlapiSearchRecord and loop through each id to get details of each item using nlapiLoadRecord and added to array. This way, it is taking to much time. Is there other way to pull all items with their details? Below is my code.
function getAllIDs() {
return nlapiSearchRecord('item', null, null, null);
}
function getRecord() {
var all_IDs = getAllIDs();
var len=all_IDs.length;
var result =new Array();
for(var i=0;i<all_IDs.length;i++) {
if(all_IDs[i].getRecordType()==="inventoryitem")
result[i]=nlapiLoadRecord(all_IDs[i].getRecordType(),all_IDs[i].id)
}
return result;
}
You can use what #Krypton suggested but you will always get 1000 results at max.
Try following if you have requirement to get more than 1000 (using Suitescript 2.0):
var columns = [];
var filters = [['isinactive', 'is', 'F']];
columns.push(search.createColumn({ name: "itemid"}));
columns.push(search.createColumn({ name: "displayname"}));
columns.push(search.createColumn({ name: "salesdescription"}));
columns.push(search.createColumn({ name: "baseprice"}));
var inventoryitemSearch = search.create({
type: search.Type.INVENTORY_ITEM, //Change the type as per your requirement
filters: filters,
columns: columns
});
var arrResults = [];
var count = 1000;
var startIndex = 0;
var endIndex = 1000;
var resultSet= inventoryitemSearch.run();
while (count == 1000) {
var results = resultSet.getRange(startIndex, endIndex);
arrResults = arrResults.concat(results);
startIndex = endIndex;
endIndex += 1000;
count = results.length;
}
log.debug({title: 'arrResults ', details: arrResults });
You can include the details you want in the search. So, for example, you can include an nlobjSearchFilter so that the search only returns inventory items, and add an nlobjSearchColumn for each field you want to see in the details. This way all the details you want to see are returned with the search and you can loop through the results to do what you want with them without loading every record individually - which will be where most of the performance hit is happening.
An example:
var inventoryitemSearch = nlapiSearchRecord("inventoryitem",null,
[
["type","anyof","InvtPart"]
],
[
new nlobjSearchColumn("itemid",null,null).setSort(false),
new nlobjSearchColumn("displayname",null,null),
new nlobjSearchColumn("salesdescription",null,null),
new nlobjSearchColumn("baseprice",null,null)
]
);
Then you can loop through the results to get details:
var name, displayName, description, price;
for ( var i = 0; inventoryitemSearch != null && i < searchresults.length; i++ ) {
var searchresult = inventoryitemSearch[ i ];
name = searchresult.getValue( 'itemid' );
displayName = searchresult.getValue( 'displayname' );
description = searchresult.getValue( 'salesdescription' );
price = searchresult.getValue( 'baseprice' );
}
There is a lot to learn about scripted searches in NetSuite, so I'd recommend starting here (NetSuite login required) and follow the links and keep reading / experimenting until your eyes glaze over.
I just like to use a generic function that accepts a search object...
const getAllResults = searchObj => {
try {
const Resultset = searchObj.run()
const maxResults = searchObj.runPaged().count
let ResultSubSet = null
let index = 0
const maxSearchReturn = 1000
let AllSearchResults = []
do {
let start = index
let end = index + maxSearchReturn
if (maxResults && maxResults <= end) {
end = maxResults
}
ResultSubSet = Resultset.getRange(start, end)
if (ResultSubSet.length === 0) {
break
}
// we could intriduce a record processor to lighetn up the load
AllSearchResults = AllSearchResults.concat(ResultSubSet)
index = index + ResultSubSet.length
if (maxResults && maxResults == index) {
break
}
} while (ResultSubSet.length >= maxSearchReturn)
return AllSearchResults
} catch (e) {
log.error(`getAllResults()`, `error : ${e}`)
}
}

Google script says - Exceeded maximum execution time

I am using the below script to delete duplicate rows from the google spreadsheet. The script was working good but as the data in the spreadsheet is being added daily, now the script is throwing "Exceeded maximum execution time" error. As I am new to scripting I don't understand what is my problem.
Could someone help me in solving this problem of mine.
function Deleteduplicates() {
var SpreadSheetKey = "My key";
var sheetD = SpreadsheetApp.openById(SpreadSheetKey).getSheetByName("Daily");
var sheetW = SpreadsheetApp.openById(SpreadSheetKey).getSheetByName("Weekly");
var dataD = sheetD.getDataRange().getValues();
var dataW = sheetW.getDataRange().getValues();
//Daily
var newDataD = new Array();
for(i in dataD){
var row = dataD[i];
var duplicate = false;
for(j in newDataD){
if(row.join() == newDataD[j].join()){
duplicate = true;
}
}
if(!duplicate){
newDataD.push(row);
}
}
//weekly
var newDataW = new Array();
for(i in dataW){
var row = dataW[i];
var duplicate = false;
for(j in newDataW){
if(row.join() == newDataW[j].join()){
duplicate = true;
}
}
if(!duplicate){
newDataW.push(row);
}
}
sheetD.clearContents();
sheetW.clearContents();
sheetD.getRange(1, 1, newDataD.length, newDataD[0].length).setValues(newDataD);
sheetW.getRange(1, 1, newDataW.length, newDataW[0].length).setValues(newDataW);
}
Conceptually, this should be quite a bit faster. I have not tried it on a large data set. The first version will leave the rows sorted as they were originally. The second version will be faster but will leave the rows sorted according to the columns from first to last on first text.
function Deleteduplicates() {
var SpreadSheetKey = "My key";
var ss = SpreadsheetApp.openById(SpreadSheetKey);
var sheetD = ss.getSheetByName("Daily");
var sheetW = ss.getSheetByName("Weekly");
var sheets = [sheetD, sheetW];
var toSs = {};
for(s in sheets) {
var data = sheets[s].getDataRange().getValues();
for(i in data){
// EDIT: remove commas from join("") for blank test
data[i].unshift(data[i].join(""),(1000000 + i).toString());
}
data.sort();
// remove blank rows -- Edit
var blank = 0;
while(data[blank][0].trim().length == 0) {blank++};
if(blank > 0) data.splice(0, blank);
// end Edit
var len = data.length - 1;
for(var x = len; x > 0; x-- ) {
if(data[x][0] == data[x-1][0]) {
data.splice(x, 1);
};
};
for(i in data) {
data[i].splice( 0, 1);
};
data.sort();
for(i in data) {
data[i].splice(0, 1);
};
toSs[sheets[s].getSheetName()] = data;
};
for(s in sheets) {
var data = toSs[sheets[s].getSheetName()];
sheets[s].clearContents();
sheets[s].getRange(1, 1, data.length, data[0].length).setValues(data);
}
}
Faster leaving rows sorted by join() created to test for duplicates
function Deleteduplicates() {
var SpreadSheetKey = "My key";
var ss = SpreadsheetApp.openById(SpreadSheetKey);
var sheetD = ss.getSheetByName("Daily");
var sheetW = ss.getSheetByName("Weekly");
var sheets = [sheetD, sheetW];
var toSs = {};
for(s in sheets) {
var data = sheets[s].getDataRange().getValues();
for(i in data){
// EDIT: remove commas from join("") for blank test
data[i].unshift(data[i].join(""));
}
data.sort();
// remove blank rows -- Edit
var blank = 0;
while(data[blank][0].trim().length == 0) {blank++};
if(blank > 0) data.splice(0, blank);
// end Edit
var len = data.length - 1;
for(var x = len; x > 0; x-- ) {
if(data[x][0] == data[x-1][0]) {
data.splice(x, 1);
};
};
for(i in data) {
data[i].splice( 0, 1);
};
toSs[sheets[s].getSheetName()] = data;
};
for(s in sheets) {
var data = toSs[sheets[s].getSheetName()];
sheets[s].clearContents();
sheets[s].getRange(1, 1, data.length, data[0].length).setValues(data);
}
}
Edited per Henrique's comment.
Edited 5/8: Remove blank rows(2 edited areas marked)
There is no problem with your script. It is just exceeding the "maximum execution time" allowed for any script (which is currently 6 minutes).
To workaround this problem you'll have to split your problem into "less than 6 minutes" parts.
For example, in your code you're clearing duplicates from 2 sheets. Trying creating two functions, one for each, and run them separately.
Also, there could be some performance enhancements that could make the script run under 6 minutes. For example, I'm not sure joining each row is the best way (performance-wise) to do an array comparison.
Creating a new array to re-set the data might not be optimal either, I'd probably go with a map verification, which is constant-time, instead of O(n^2) double array checking you're doing.
Bottom line, this is a limitation you have to live with in Apps Script. And any solution anyone proposes is just a workaround, that will also eventually fail if your data gets overly big.

Javascript - Associative Arrays not working?

So I have csv files that basically include lists of students, what school they are in, and what subjects they are taking(ex. chem, spanish, biology, etc). I want to have my program let the user type in a subject area(s) and have the page return the amount of times each subject is being taken.
I then have some javascript that basically takes in some user input from a text field, parse that, and puts it into an array. Then, it imports the csv file and compares the subject columns to what the user inputs, and calculates the amount of time each subject is taking.
My javascript looks like this:
var globalArray = [];
var schoolList = [];
var splitTextInput = [];
var count = 0;
var splitSubjectArea = [];
function myFunction()
{
var textInput = document.getElementById('numb').value;
var needsTrimTextInput = textInput.split(","); //creating an array to store user input
for( var q = 0; q < needsTrimTextInput.length; q++) //getting rid of whitespace in user input
{
splitTextInput[q] = needsTrimTextInput[q].trim();
}
for(var j = 0; j< splitTextInput.length; j++)
{
var sSubjectArea = {};
sSubjectArea[ splitTextInput[j] ] = 0; //assigning the value to 0 to store the count of each subject
}
var fileName = document.getElementById("UniversitySelect").value;
if( fileName.indexOf(".csv") > 0 )
{
d3.csv( "./" + document.getElementById("UniversitySelect").value, bob, counting);
}
function bob(d){
return { Area: d.Area };
}
function counting(error, rows)
{
globalArray = rows;
for( var i = 0; i < rows.length; i++ ) //for the row in the CSV file
{
for( var k = 0; k < splitTextInput.length; k++ ) // loop to go through the different inputed subject areas
{
if( rows[i].Area.toLowerCase().indexOf( splitTextInput[k].toLowerCase() ) > -1)
{
count++; //stores the overall count
sSubjectArea[splitTextInput[k]] += 1;
//console.log(sResearchArea[splitTextInput[k]]);
}
}
}
console.log(rows);
for(r = 0; r < splitTextInput.length; r++)
{
console.log( sSubjectArea[ splitTextInput[r] ] );
}//for
}//function
}//function
I know it partially works, because if I enter in 2 subjects, say Chemistry and Biology, which are taken 3 times each, then the count will be 6. However, I cannot get sSubjectArea to hold the count for each individual subject. What am I doing wrong? When I added the console.log(sSubjectArea[splitTextInput[k]]) line, the output I get is:
1
NaN
2
3
4
NaN
5
6
Array [ Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, 86 more… ]
NaN
6
And I don't really understand why I get those numbers & especially NaN.... can anyone help? I'm really new to javascript, so I might have made some sort of fundamental error in understanding objects, but I can't figure it out. Any help would be much appreciated, thanks!!

How can I remove rows with unique values, keeping rows with duplicate values?

I have a spreadsheet of surveys, in which I need to see how particular users have varied over time. As such, I need to disregard all rows with unique values in a particular column. The data looks like this:
Response Date Response_ID Account_ID Q.1
10/20/2011 12:03:43 PM 23655956 1168161 8
10/20/2011 03:52:57 PM 23660161 1168152 0
10/21/2011 10:55:54 AM 23672903 1166121 7
10/23/2011 04:28:16 PM 23694471 1144756 9
10/25/2011 06:30:52 AM 23732674 1167449 7
10/25/2011 07:52:28 AM 23734597 1087618 5
I've found a way to do so in Excel VBA:
Sub Del_Unique()
Application.ScreenUpdating = False
Columns("B:B").Insert Shift:=xlToRight
Columns("A:A").Copy Destination:=Columns("B:B")
i = Application.CountIf(Range("A:A"), "<>") + 50
If i > 65536 Then i = 65536
Do
If Application.CountIf(Range("B:B"), Range("A" & i)) = 1 Then
Rows(i).Delete
End If
i = i - 1
Loop Until i = 0
Columns("B:B").Delete
Application.ScreenUpdating = True
End Sub
I'd like to do it in Google Spreadsheets with a script that won't have to be changed. Closest I can get is retrieving all duplicate user ids from the range, but can't associate that with the row. That code follows:
function findDuplicatesInSelection() {
var activeRange = SpreadsheetApp.getActiveRange();
var values = activeRange.getValues();
// values that appear at least once
var once = {};
// values that appear at least twice
var twice = {};
// values that appear at least twice, stored in a pretty fashion!
var final = [];
for (var i = 0; i < values.length; i++) {
var inner = values[i];
for (var j = 0; j < inner.length; j++) {
var cell = inner[j];
if (cell == "") continue;
if (once.hasOwnProperty(cell)) {
if (!twice.hasOwnProperty(cell)) {
final.push(cell);
}
twice[cell] = 1;
} else {
once[cell] = 1;
}
}
}
if (final.length == 0) {
Browser.msgBox("No duplicates found");
} else {
Browser.msgBox("Duplicates are: " + final);
}
}
This is maybe not very efficient, but I think it's what you want:
var ar=[1,3,3,5,6,8,6,6];
console.log("Before:");
display(ar);//1 3 3 5 6 8 6 6
var index=[];
var ar2=[];
for(var a=0;a<ar.length;a++)
{
var duplicate=false;
for(var b=0;b<ar.length;b++)
{
if(ar[a]==ar[b]&&a!=b)
{
duplicate=true;
}
}
if(!duplicate)
{
index.push(a);
}
}
for(var a=0;a<index.length;a++)
{
ar[index[a]]=null;
}
for(var a=0;a<ar.length;a++)
{
if(ar[a]!=null)ar2.push(ar[a]);
}
console.log("After:");
display(ar2);//3 3 6 6 6
function display(x)
{
for(var a=0;a<x.length;a++)console.log(x[a]);
}
The fiddle : http://jsfiddle.net/mageek/6AGQ4/
And a shorter version that is as a function :
var ar=[1,3,3,5,6,8,6,6];
function removeUnique(x)
{
var index=[];
var ar2=[];
for(var a=0;a<ar.length;a++)
{
var duplicate=0;
for(var b=0;b<ar.length;b++)if(ar[a]==ar[b]&&a!=b)duplicate=1;
if(!duplicate)index.push(a);
}
for(var a=0;a<index.length;a++)ar[index[a]]=null;
for(var a=0;a<ar.length;a++)if(ar[a]!=null)ar2.push(ar[a]);
return x;
}
ar=removeUnique(ar);
The fiddle : http://jsfiddle.net/mageek/6AGQ4/2
I'd suggest going for something simple.
Create a short script that flags duplicates
Write the formula directly into the cell "=flagDuplicate(C2,C$2:C$10)"
Copy the forumla down the column
Use Spreadsheet's built in QUERY formula to pull the information you need
"=QUERY(A1:E10; "SELECT * WHERE E = TRUE"; 1)"
Here is a simple function to flag duplicates
function flagDuplicate(value, array) {
var duplicateCounter = 0;
for (var i=0; i<array.length; i++){
if (array[i] == value){ // I avoid === in Spreadsheet functions
duplicateCounter++;
}
}
if (duplicateCounter > 1){
return true;
}else{
return false;
}
}
Too many functions on a large table can slow things down. If it becomes a problem, you can always copy and "paste values only" - that will retain the information but remove the functions.
Best of luck.
Note: When I tested this I noticed that can take a while before the spreadsheet recognizes the new custom function (gives error like can't find function FLAGDUPLICATE)
You could also do it using arrays to handle the whole sheet at once :
function removeUnique(){
var col = 2 ; // choose the column you want to check for unique elements
var sh = SpreadsheetApp.getActiveSheet();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var data=ss.getDataRange().getValues();// get all data
data.sort(function(x,y){
// var xp = Number(x[col]);// use these to sort on numeric values
// var yp = Number(y[col]);
var xp = x[col];// use these for non-numeric values
var yp = y[col];
Logger.log(xp+' '+yp); // just to check the sort is OK
return xp == yp ? 0 : xp < yp ? -1 : 1;// sort on column col numeric ascending
});
var cc=0;
var newdata = new Array();
for(nn=0;nn<data.length-1;++nn){
if(data[nn+1][col]==data[nn][col]||cc>0){
newdata.push(data[nn]);
++cc;
if(cc>1){cc=0}}
}
ss.getDataRange().clearContent(); // clear the sheet
sh.getRange(1,1,newdata.length,newdata[0].length).setValues(newdata);// paste new values sorted and without unique elements
}
EDIT : here is the version that keeps all duplicates (the working one)
function removeUnique(){
var col = 2 ; // choose the column you want to check for unique elements
var sh = SpreadsheetApp.getActiveSheet();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var data=ss.getDataRange().getValues();// get all data
data.sort(function(x,y){
// var xp = Number(x[col]);// use these to sort on numeric values
// var yp = Number(y[col]);
var xp = x[col];// use these for non-numeric values
var yp = y[col];
Logger.log(xp+' '+yp); // just to check the sort is OK
return xp == yp ? 0 : xp < yp ? -1 : 1;// sort on column col numeric ascending
});
var newdata = new Array();
for(nn=0;nn<data.length-1;++nn){
if(data[nn+1][col]==data[nn][col]){
newdata.push(data[nn]);
}
}
if(data[nn-1][col]==data[nn][col]){newdata.push(data[nn])}
ss.getDataRange().clearContent(); // clear the sheet
sh.getRange(1,1,newdata.length,newdata[0].length).setValues(newdata);// paste new values sorted and without unique elements
}

Categories

Resources