Thursday, February 27, 2014

Passing data from a Google spreadsheet into an array object

What's the deal here? I have 4 columns in my Google spreadsheet consisting of an index, a first name, a second name and a web address and I want to pass this data into an array so I can then perform functions, such as searching or displaying a specific entry. (I'm building a mini database app to manage contacts, so the next few blog posts will all be building blocks - small programs that can all be bolted together to create my full application.)

The following diagram shows my test data setup:


I'm working from the following tutorial and simplifying the code to fit my needs:

Extending Google Sheets

Before diving into the code, it's worth thinking about what we're trying to do here. I want to pass the data from each row into an array of elements e.g. [index, name1, name2, web] and then I want to hold all of these row arrays in a main array like this:

row 1:   [index[0], name1[0], name2[0], web[0]]
row 2:   [index[1], name1[1], name2[1], web[1]]
row 3:   [index[2], name1[2], name2[2], web[2]]
etc..

So in my case, with the above data, the array I want to have is:

[1, James, Smith, www.example1.com],
[2, Laura, Jones, www.example2.com],
[3, Bob, Philips, www.example3.com],
etc...

Moving now to the code, I need to start by making sure I'm in the correct spreadsheet and the correct sheet within that spreadsheet. Then I select the range of my data (I'm doing this with static references at the moment but will want to change to be dynamic further down the line). Finally, I call the function "getRowsData" (see below) with the arguments "sheet" (i.e. my current sheet) and "dataRange" (i.e. my range of data):

function arrayTest() {
  // select the current spreadsheet and first sheet within
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheets()[0];
  
  //select the data range - static for now
  var dataRange = sheet.getRange("A1:D8");
  
    // For every row of employee data, generate an employee object.
  var employeeObjects = getRowsData(sheet, dataRange);
}

The function "getRowsData":
This function takes an input of two arguments: sheet and range. By passing the current sheet from the arrayTest function above I can reference it to identify the names in the header row, and thereby use these to name each item in my array e.g. for the column "name1" I want to identify each row entry as: name1[1] = "James"

function getRowsData(sheet,range) {
  var headersRange = sheet.getRange("A1:D1");
  var headers = headersRange.getValues()[0];
  return getObjects(range.getValues(), headers);
}

The function "getObjects":
You'll see that within "getRowsData" we also call on another function called "getObjects". We pass the data range and the header values (to use as names for each piece of data in the row arrays) to this function and it returns an array object consisting of each row of data.

// For every row of data in data, generates an object that contains the data.
function getObjects(data, keys) {
  var objects = [];
  for (var i = 0; i < data.length; i++) {
    var object = {};
    var hasData = false;
    for (var j = 0; j < data[i].length; j++) {
      var cellData = data[i][j];
      object[keys[j]] = cellData;
      hasData = true;
    }
    if (hasData) {
      objects.push(object);
    }
  }
  return objects;
}

In a nutshell what's happening here is that we declare an array object called "objects". Then for each row of data (the number of rows identified by the "data.length" syntax in the first for loop), each cell in turn in a given row is "pushed" into the array. The whole array, called "objects", is then returned as the output of this function.

So how do I know if it works?

Well, we can test it by writing a couple of lines of code to choose some information from the array. So in the first function, "arrayTest", drop in these two lines of code just above the final "}" (here, I've chosen the third entry as an example):

  //choose a test entry from the array
  var thirdEntry = employeeObjects[3];

and then finally, add these two lines to display the requested entry from the array (note, I'm only displaying name1 and name2 back but you could easily add in "index" and "web" as well):

  var stringToDisplay = "The third row is: " + thirdEntry.name1 + " " + thirdEntry.name2;
  Browser.msgBox(stringToDisplay);

And voila! You should get the following output:


Lastly, a caveat - I'm new to Javascript and I'm learning as I go so I don't promise that everything I write is perfect by any shot. However, by trying to explain what I'm doing, it's really helping me to understand the code and what each line does. Thank you for your patience. Any constructive feedback appreciated. Happy coding!

No comments:

Post a Comment