Question

I have to sync google contacts with spreadsheet, for this I have to call API so may time to set values in Google spreadsheet, how can I overcome this problem to call google API less times or only once ?

var preContacts = group.getContacts();
  var rowNo = 2;

  for(var y = 0; y < preContacts.length; y++) {

    var FNameContact = preContacts[y].getGivenName();
    var PhoneNoArray = preContacts[y].getPhones();
    var PhoneNoContact = getPhoneNumbers(PhoneNoArray);
    var emailArray = preContacts[y].getEmails();
    var emailAdressContact = getEmailAddresses(emailArray);
    //var customFieldsArray = preContacts.getCustomFields();

    sheettab_bulk_cdb.getRange("J"+rowNo).setValue(emailAdressContact);
    sheettab_bulk_cdb.getRange("G"+rowNo).setValue(emailAdressContact);
    sheettab_bulk_cdb.getRange("F"+rowNo).setValue(emailAdressContact);
    sheettab_bulk_cdb.getRange("A"+rowNo).setValue(emailAdressContact);

  rowNo++;
  }
Was it helpful?

Solution

The most significant optimization available to you is to write the data to the spreadsheet using a single setValues() call instead of the many single-cell setValue() operations you currently have. Read over the answer to What is faster: ScriptDb or SpreadsheetApp? for details.

To take advantage of setValues(), though, you'll have to re-arrange your spreadsheet so that the contact information you're writing is contiguous. Consider a spreadsheet arranged like so:

Screenshot

With that set up, we can collect all the contact info into a two-dimensional array, and then make a single call like so:

sheet.getRange(_row_,_col_,data.length,data[0].length).setValues(data);

... where _row_,_col_ is the top-left corner of the range we want to write the data to.

Script

Here's a complete script that will retrieve all the contacts for a group, and populate that example spreadsheet. It can be easily extended to include other contact information.

/**
 * Retrieves all contacts for a group. If groupName isn't passed as
 * a parameter, user will be prompted.
 */
function getContactGroup(groupName) {
  var ss = SpreadsheetApp.getActiveSpreadsheet();

  groupName = groupName || Browser.inputBox('Get Contact Group', 'Group name:', Browser.Buttons.OK_CANCEL);
  if (groupName === 'cancel') {
    ss.toast('Task canceled', 'Status', 3);
    return;
  }

  var group = ContactsApp.getContactGroup(groupName);
  if (!group) {
    ss.toast('Group not found', 'Status', 3);
    return;
  }
  else {
    var data = []; // Array to hold contact info for spreadsheet
    var contacts = group.getContacts();
    if (contacts.length == 0) {
      ss.toast('No contacts in group', 'Status', 3);
      return;
    }
    else {
      for (var i=0; i<contacts.length; i++) {
        var contactInfo = []
        // Build a row of contact information
        contactInfo.push( contacts[i].getFullName() );
        contactInfo.push( getPhoneNumbers(contacts[i].getPhones()) );
        contactInfo.push( getEmailAddresses( contacts[i].getEmails()) );
        contactInfo.push( contacts[i].getLastUpdated() );

        // Add row to data array
        data.push( contactInfo );
      }
    }
  }

  // Output all contact info to spreadsheet in one shot.
  var sheet = ss.getActiveSheet();
  var headers = 1; // # rows containing headers
  sheet.getDataRange().offset(headers, 0).clearContent();   // Clear old content
  sheet.getRange(1+headers,1,data.length,data[0].length).setValues(data);
};

function getPhoneNumbers( phones ) {
  // Convert array of phones to comma-separated string
  var phoneList = [];
  for (var phone=0; phone < phones.length; phone++) {
    var phoneEntry = phones[phone].getLabel() + ' ' + phones[phone].getPhoneNumber();
    if (phones[phone].isPrimary()) {
      // Add primary phone at front
      phoneList.unshift(phoneEntry);
    }
    else {
      // Add other phones at end
      phoneList.push(phoneEntry);
    }
  }
  return phoneList.join(', ');
}

function getEmailAddresses( emails ) {
  // Convert array of emails to comma-separated string
  var emailList = [];
  for (var email=0; email < emails.length; email++) {
    var emailEntry = emails[email].getLabel() + ' ' + emails[email].getAddress();
    if (emails[email].isPrimary()) {
      // Add primary email at front
      emailList.unshift(emailEntry);
    }
    else {
      // Add other emails at end
      emailList.push(emailEntry);
    }
  }
  return emailList.join(', ');
}

/**
 * Adds a custom menu to the active spreadsheet
 */
function onOpen() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet();
  var entries = [{
    name : "Copy contact group to sheet",
    functionName : "getContactGroup"
  }];
  sheet.addMenu("Script Center Menu", entries);
};

Script version 2

This isn't as efficient as the previous version, because each column of data is written separately. It will also be harder to maintain and expand upon, because it has more code. Still simple, but more.

The column numbering is correct for the example sheet shown above, so would need to be adjusted for your own spreadsheet.

/**
 * Retrieves all contacts for a group. If groupName isn't passed as
 * a parameter, user will be prompted.
 *
 * Version 2: This version allows the columns of contact info to be
 * non-contiguous, but is less efficient than version 1.
 */
function getContactGroup2(groupName) {
  var ss = SpreadsheetApp.getActiveSpreadsheet();

  groupName = groupName || Browser.inputBox('Get Contact Group', 'Group name:', Browser.Buttons.OK_CANCEL);
  if (groupName === 'cancel') {
    ss.toast('Task canceled', 'Status', 3);
    return;
  }

  var group = ContactsApp.getContactGroup(groupName);
  if (!group) {
    ss.toast('Group not found', 'Status', 3);
    return;
  }
  else {
    var contactName = []; // Arrays to hold contact info for spreadsheet
    var contactPhone = [];
    var contactEmail = [];
    var contactLastUpdated = [];

    var contacts = group.getContacts();
    if (contacts.length == 0) {
      ss.toast('No contacts in group', 'Status', 3);
      return;
    }
    else {
      ss.toast('Starting Copy', 'Status', 3);

      for (var i=0; i<contacts.length; i++) {
        // Record contact information in column arrays
        contactName.push( [contacts[i].getFullName()] );
        contactPhone.push( [getPhoneNumbers(contacts[i].getPhones())] );
        contactEmail.push( [getEmailAddresses( contacts[i].getEmails())] );
        contactLastUpdated.push( [contacts[i].getLastUpdated()] );
      }
    }
  }

  ss.toast('Storing to sheet', 'Status', 3);

  // Output all contact info to spreadsheet in one shot per column.
  var sheet = ss.getActiveSheet();
  var headers = 1; // # rows containing headers

  var columnName = 1,  // Column numbers to receive contact info
      columnPhone = 2,
      columnEmail = 3,
      columnLastUpdated = 4;
  sheet.getRange(1+headers,columnName,contactName.length,1).setValues(contactName);
  sheet.getRange(1+headers,columnPhone,contactPhone.length,1).setValues(contactPhone);
  sheet.getRange(1+headers,columnEmail,contactEmail.length,1).setValues(contactEmail);
  sheet.getRange(1+headers,columnLastUpdated,contactLastUpdated.length,1).setValues(contactLastUpdated);

  ss.toast('Operation complete', 'Status', 3);
};
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top