/** * Main method is called when the script receives a GET request. * Receives the request, generates and returns the output. */ function doGet(request) { // Get request params. var sheetKey = request.parameters.id; var sheetName = request.parameters.sheet; var callback = request.parameters.callback; var headerRow = request.parameters.header; var startRow = request.parameters.startRow; // Parse the spreadsheet. var spreadsheet = SpreadsheetApp.openById(sheetKey); var keys = getHeaderRowKeys_(spreadsheet, sheetName, headerRow); var data = readData_(spreadsheet, sheetName, keys, startRow); // Filter for matching terms. data = data.filter(function(entry) { var matches = true; for (var k in keys) { var key = keys[k].replace(/\s+/g, '_'); var searchTerm = request.parameters[key]; // Use the string form of the value since params are strings by default if (searchTerm != undefined) matches = matches && ("" + entry[key] == searchTerm); } // Matches is true iff all params are undefined or all values for keys match. return matches; }); // Write and return the response. var response = JSON.stringify({ records: data }); var output = ContentService.createTextOutput(); if (callback == undefined) { // Serve as JSON output.setContent(response).setMimeType(ContentService.MimeType.JSON); } else { // Serve as JSONP output.setContent(callback + "(" + response + ")") .setMimeType(ContentService.MimeType.JAVASCRIPT); } return output; } /** * Get a row in a spreadsheet as an Object, using the values in the header row as * keys and the corresponding row values as the values. * * @param spreadsheet Spreadsheet object housing the sheet and header * @param sheetName Name of the specific sheet in the spreadsheet with the data * @param properties Optional array of keys to use for the row values. Default is the first row. * @param startRowNum Optional top row number of the rows to parse. The default is * the second row (i.e., below the header). */ function readData_(spreadsheet, sheetName, properties, startRowNum) { if (typeof properties == "undefined") { properties = getHeaderRowKeys_(spreadsheet, sheetName); } var rows = getDataRows_(spreadsheet, sheetName, startRowNum); var data = []; for (var r = 0, l = rows.length; r < l; r++) { var row = rows[r]; var record = {}; for (var p in properties) { record[properties[p]] = row[p]; } data.push(record); } return data; } /** * Parse spreadsheet data as an array of Javascript Objects. * * @param spreadsheet Spreadsheet object with the data to get * @param sheetName Name of the specific sheet in the spreadsheet with the data * @param startRowNum Optional top row number of the rows to parse. The default is * the second row (i.e., below the header). */ function getDataRows_(spreadsheet, sheetName, startRowNum) { if (typeof startRowNum == "undefined") startRowNum = 2; var sheet = spreadsheet.getSheetByName(sheetName); return sheet.getRange(startRowNum, 1, sheet.getLastRow(), sheet.getLastColumn()).getValues(); } /** * Return the array of keys used in the header, replacing whitespace with underscores. * * @param spreadsheet Spreadsheet object housing the sheet and header * @param sheetName Name of the specific sheet in the spreadsheet whose header values to get * @param rowNum Optional exact row number of the header. Default is the first row. */ function getHeaderRowKeys_(spreadsheet, sheetName, rowNum) { if (typeof rowNum == "undefined") rowNum = 1; return getHeaderRow_(spreadsheet, sheetName, rowNum).map(function(value) { return value.replace(/\s+/g, '_'); }); } /** * Get the values in the header row of the given sheet in a spreadsheet * * @param spreadsheet Spreadsheet object housing the sheet and header * @param sheetName Name of the specific sheet in the spreadsheet whose header values to get * @param rowNum Exact row number of the header. */ function getHeaderRow_(spreadsheet, sheetName, rowNum) { var sheet = spreadsheet.getSheetByName(sheetName); return sheet.getRange(rowNum, 1, 1, sheet.getLastColumn()).getValues()[0]; } /********************************** TESTS **********************************/ /** * Basic test logs a request and response. Use View -> Logs to check if it's * correct. * (In the future maybe actually check equality to expected output.) * @param request The HTTP request to test */ function runTest_(request) { Logger.log(request); Logger.log(doGet(request).getContent().toString()); } /** * Test the original functionality of returning all objects * in the spreadsheet in JSON. */ function test1() { runTest_({ parameters : { id : "0AgviZ9NWh5fvdDdNMlI2aXRCR2lCX1B1alZ6ZjZxSkE", sheet : "Summary", header : 2, startRow : 3, } }); } /** * Test filtering on the spreadsheet JSON for one value. */ function test2() { runTest_({ parameters : { id : "0AgviZ9NWh5fvdDdNMlI2aXRCR2lCX1B1alZ6ZjZxSkE", sheet : "Summary", header : 2, Status : "Associate" } }); } /** * Test stricter filtering on the spreadsheet for multiple values. */ function test3() { runTest_({ parameters : { id : "0AgviZ9NWh5fvdDdNMlI2aXRCR2lCX1B1alZ6ZjZxSkE", sheet : "Summary", header : 2, startRow : 3, First_Name : "Greatest", Last_Name : "Ever" } }); }