Saturday, November 7, 2015

Google Spreadsheet Getting the last 5 values before the previous last 5

Question:

Hi, I am trying to get the average values in a row present at the last 5 rows before the last 5 rows, in other words in a sheet with 15 rows in a column I would like to know how to attain the average value of rows 5 to 10.

Solution:

Following is the screenshot of the sheet having data in column A:


Now I have the following formula in cell C1:
=arrayformula({A:A,row(A:A)})
to get the same values in column C and the row number in column D


Now I have the following formula in cell C1:
=query(arrayformula({A:A,row(A:A)}),"select Col1,Col2 where Col1 is not null",0)
to get the both columns having equal number of rows (that is rows having values in Column C)


Now I have the following formula in cell C1:
=query(arrayformula({A:A,row(A:A)}),"select Col1,Col2 where Col1 is not null order by Col2 desc",0)
to get the data in descending order of row number, as we want second last 5 rows...


Now I have the following formula in cell C1:
=query(arrayformula({A:A,row(A:A)}),"select Col1,Col2 where Col1 is not null order by Col2 desc offset 5",0)
to start the data from second last 5 rows, I have used "offset" in query formula.


Now I have the following formula in cell C1:
=query(arrayformula({A:A,row(A:A)}),"select Col1,Col2 where Col1 is not null order by Col2 desc limit 5 offset 5",0)
to limit the data upto only 5 rows.


Now I have the following formula in cell C1:
=query(arrayformula({A:A,row(A:A)}),"select Col1 where Col1 is not null order by Col2 desc limit 5 offset 5",0)
to get the data in only column C of second last 5 rows.


Now I have the following formula in cell C1:
=average(iferror(query(arrayformula({A:A,row(A:A)}),"select Col1 where Col1 is not null order by Col2 desc limit 5 offset 5",0)))
to finally get the average of second last 5 rows.



Wednesday, November 4, 2015

Google Spreadsheet Script for manipulating JSON

The following URL "http://shanghai.anjuke.com/ajax/pricetrend/comm?cid=10052", has the JSON data:

Now to fetch this data in Google Spreadsheet, use the following script:

/////////////////////////////////////////////////

function extract(url){
  var response = UrlFetchApp.fetch(url);
  var data = JSON.parse(response.getContentText());
  var comm = data.comm;
  
  var keyVal = function(o) {
    var key = Object.keys(o)[0];
    return [parseInt(key),parseInt(o[key])];
  } ;
  
  var result = new Array();
  var count=0;
  for (i in comm){
    result[count] = new Array();
    result[count] = keyVal(comm[count]);
    count++;
  }

  return result;
};

/////////////////////////////////////////////////

save the above script code in the script editor of your Spreadsheet and then you can call the custom function "extract" directly from your spreadsheet.

Have a look at the following screenshot:


I have the URL in cell A1, and the following formula in cell B1:
=transpose(extract(A1))


Friday, October 23, 2015

Google Spreadsheet return a subset given complex criteria

Question:


Here is my sample sheet:





Given the example data in this sheet, I want to return a subset automatically that meets the following criteria:
* 4 total rows
* 1 row where color=green
* 1 row where color=red
* 2 rows where color=blue
* The COMBINED value of the PRICE column of the four returned rows cannot exceed a sum of 30
* The returned set should provide the highest possible COMBINED value of the POINTS column of the four returned rows. 

In short, I would like to find the four records in the entire table that result in the highest possible combined POINTS value, without exceeding a combined PRICE value of 30.

Help is greatly appreciated!


Solution:

Insert the following script code in the script code of your spreadsheet:

////////////////////////////////////////////////////////

function subset(v) {
  //var ss = SpreadsheetApp.getActiveSpreadsheet();
  //var s = ss.getSheetByName('Sheet1');
  //var r = s.getRange('A:E');
  //var v = r.getValues();
  var lastrow = getLastPopulatedRow(v);
  var green = new Array();
  var red = new Array();
  var blue = new Array();
  
  for(var i=0;i<lastrow;i++) {
    if(v[i][2]=='green')
      green.push(v[i]);
    else if(v[i][2]=='red')
      red.push(v[i]);
    else if(v[i][2]=='blue')
      blue.push(v[i]);
  }
  
  var combinations = new Array();
  var c=0;
  var total = new Array();
  
  for(var w=0;w<green.length;w++) {
    for(var x=0;x<red.length;x++) {
      for(var y=0;y<blue.length-1;y++) {
        for(var z=y+1;z<blue.length;z++) {
          combinations[c] = new Array();
          combinations[c].push(green[w]);
          combinations[c].push(red[x]);
          combinations[c].push(blue[y]);
          combinations[c].push(blue[z]);
          total.push([c,(green[w][3]+red[x][3]+blue[y][3]+blue[z][3]),(green[w][4]+red[x][4]+blue[y][4]+blue[z][4])]);
          c=c+1;
        }
      }
    }
  }
  var total = total.sort(function(a,b) { return a[1] - b[1]; });
  //Logger.log(total);
  for(var j=total.length-1;j>=0;j--)
    if(total[j][2]<=30) break;
  
  return combinations[total[j][0]];
};

function getLastPopulatedRow(data) {
  for (var i=data.length-1;i>=0;i--)
    for (var j=0;j<data[0].length;j++)
      if (data[i][j]) return i+1;
  return 0;
};

////////////////////////////////////////////////////////

Now you can use the following custom function in your spreadsheet:
=subset(A2:E)

Following is the screenshot of the spreadsheet, showing the desired subset in range G2:K5
I have inserted the custom formula in cell G2.



Friday, October 9, 2015

Google Spreadsheet generating a list of the most frequently used words in an entire sheet

Question:

Hey guys,
I have a spreadsheet made up of columns that list the top 100 search terms on a website for each month of the year. Is there a formula I can use to search all of the columns and generate a list of the overall top 20 terms?


Any help would be greatly appreciated.

Thanks!

Solution:

Screenshot of "Sheet2":


First of all to get the unique values of Sheet1, I have the following formula in cell A1:
=unique({Sheet1!B3:B102;Sheet1!C3:C102;Sheet1!D3:D102;Sheet1!E3:E102;Sheet1!F3:F102;Sheet1!G3:G102;Sheet1!H3:H102;Sheet1!I3:I102;Sheet1!J3:J102;Sheet1!K3:K102;Sheet1!L3:L102;Sheet1!M3:M102;Sheet1!N3:N102;Sheet1!O3:O102;Sheet1!P3:P102;Sheet1!Q3:Q102})

and then to count the values in Column A, I have the following formula in cell B1:
=arrayformula(if(len(A1:A),countif(Sheet1!B3:Q102,A1:A),))

and then to sort the values of Column A and B in descending order of Column B, I have the following formula in cell E1:
=sort(A:B,2,false)


========================================


Alternatively you can also have the solution with a following single advanced formula:

=query(arrayformula({unique({Sheet1!B3:B102;Sheet1!C3:C102;Sheet1!D3:D102;Sheet1!E3:E102;Sheet1!F3:F102;Sheet1!G3:G102;Sheet1!H3:H102;Sheet1!I3:I102;Sheet1!J3:J102;Sheet1!K3:K102;Sheet1!L3:L102;Sheet1!M3:M102;Sheet1!N3:N102;Sheet1!O3:O102;Sheet1!P3:P102;Sheet1!Q3:Q102}),countif(Sheet1!B3:Q102,unique({Sheet1!B3:B102;Sheet1!C3:C102;Sheet1!D3:D102;Sheet1!E3:E102;Sheet1!F3:F102;Sheet1!G3:G102;Sheet1!H3:H102;Sheet1!I3:I102;Sheet1!J3:J102;Sheet1!K3:K102;Sheet1!L3:L102;Sheet1!M3:M102;Sheet1!N3:N102;Sheet1!O3:O102;Sheet1!P3:P102;Sheet1!Q3:Q102}))}),"select * order by Col2 desc",0)

Screenshot of "Sheet3":




Wednesday, October 7, 2015

Google Sheet Select items by column that contains few parameters separated by comma

Question:

Hi everyone, I am trying to create some sort of inventory database using google sheets. I have one sheet 'Inventory' that lists all the items in my database. In another sheet 'Search' I want to have an ability to display items that qualify size dispersion. The problem is that items have multiple sizes listed in one cell separated by comma.

TimestampNameWeightPriceTire sizes
07.10.2015 11:04:01Chain 1220100200, 300
07.10.2015 14:04:44Chain 2135350100
07.10.2015 14:05:27Chain 3453560100, 200, 300

I need to come up with formula that would take following input

Size fromSize to
50120

And would display items that qualify this input dispersion like

TimestampNameWeightPriceTire sizes
07.10.2015 14:04:44Chain 2135350100
07.10.2015 14:05:27Chain 3453560100, 200, 300


Solution:

Following is the screenshot of Sheet "Inventory"


Now, put the following script in the script editor of your spreadsheet:


function inventory() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var s = ss.getSheetByName('Inventory');
  var r = s.getRange('A:E');
  var v = r.getValues();
  var lastrow  = getLastPopulatedRow(v);
  var arr = new Array();
  arr.push(v[0]);
  
  for(var i=1;i<lastrow;i++) {
    var e = v[i][4].toString().split(',');
    for(var j=0;j<e.length;j++){
      arr.push( [ v[i][0],v[i][1],v[i][2],v[i][3],e[j].trim()*1 ] );
    }
  }
  return arr;
};

function getLastPopulatedRow(data) {
  for (var i=data.length-1;i>=0;i--)
    for (var j=0;j<data[0].length;j++)
      if (data[i][j]) return i+1;
  return 0;
};


save the above code and then refresh your spreadsheet.

Now, just try the following custom function in a new sheet in your spreadsheet:
=inventory()

The above custom function will give you the following output:


Now, we can use this output in a Query formula, try the following formula in cell A2 of sheet "Search":
=query(inventory();"select * where Col5>="&A2&" and Col5<="&B2;1)

Following is the screenshot of Sheet "Search":