Carlos Craig
Carlos Craig

Reputation: 151

Auto Sync google sheets to firebase without button

I used a tutorial to help me sync my sheets to firebase with the use of a SYNC button that activates the script. The SYNC button currently sits just in the middle of the spreadsheet. I want to sync the data from sheets automatically to firebase when there are changes made.

function getFirebaseUrl(jsonPath) {

return (
'https://no-excusas.firebaseio.com/' +
jsonPath +
'.json?auth=' +
secret
  )
}



function syncMasterSheet(sheetHeaders, sheetData) {

  /*
  We make a PUT (update) request,
  and send a JSON payload
  More info on the REST API here : https://firebase.google.com/docs/database/rest/start
  */              
  const outputData = [];
  for(i = 0; i < sheetData.length; i++) {
  var row = sheetData[i];
  var newRow = {};
  for(j = 0; j < row.length; j++) {
    newRow[sheetHeaders[j]] = row[j];
  }
  outputData.push(newRow);
  }

  var options = {
   method: 'put',
  contentType: 'application/json',
  payload: JSON.stringify(outputData)
  }

  var fireBaseUrl = getFirebaseUrl("UsersSheets")


 UrlFetchApp.fetch(fireBaseUrl, options)
}

function startSync() {
 //Get the currently active sheet
  var sheet = SpreadsheetApp.getActiveSheet()

  //Get the number of rows and columns which contain some content

  var [rows, columns] = [sheet.getLastRow(), sheet.getLastColumn()]

  // Get the data contained in those rows and columns as a 2 dimensional array.
  // Get the headers in a separate array.
  var headers = sheet.getRange(1, 1, 1, columns).getValues()[0];  // [0] to unwrap the 
outer array
 var data = sheet.getRange(2, 1, rows - 1, columns).getValues();  // skipping the header 
row means we need to reduce rows by 1.

 //Use the syncMasterSheet function defined before to push this data to the "masterSheet" 
key in the firebase database

  syncMasterSheet(headers, data)
}

Upvotes: 1

Views: 612

Answers (2)

robsiemb
robsiemb

Reputation: 6354

Normally, it would be ok to just define an onEdit function in your code, like this:

function onEdit(event) {
  startSync();
}

However, because you are making external requests via UrlFetchApp.fetch(), this will fail with an error about not having the https://www.googleapis.com/auth/script.external_request permission (gobs more detail about trigger authorization here).

Instead, you need to manually create an installable trigger

This is reasonably straightforward. In the edit menu for your code, go to your project's triggers:

enter image description here

Then, select "add a trigger" and create the on edit trigger, like so:

enter image description here

You should think about if you really want this running on every edit as the requests could be quite large (as it syncs the entire sheet) and run frequently (as you edit), however.

Upvotes: 2

Frank van Puffelen
Frank van Puffelen

Reputation: 598817

When you make a change to a spreadsheet, its onEdit event fires. So that's where you'd trigger that save with something like this:

function onEdit(event) {
  startSync();
}

But since onEdit fires for each edit, this may end up saving a lot more than really necessary. So you may want to debounce to only save after some inactivity.

Something like this:

var timer;
function onEdit(event) {
  // if we're counting down, stop the timer
  if (timer) clearTimeout(timer);
  // starting syncing after 2 seconds
  timer = setTimeout(function() {
    startSync();
  }, 2000);
}

Upvotes: 0

Related Questions