I'm using the highcharts data module to build a chart from an html table. In the data configuration of the chart I just have:
data: {
table: table
}
But if I have string values such as "null", "NA", or even comma separators in the HTML table I get highcharts error 14, 'string value passed to chart...'
What I've tried:
Since HC should be able to handle null values I replaced NA will null in the tables. I also tried just leaving the blanks "" blank. But the issue is with the thousand separators. So I added thousandsSep: ',' hoping the chart output would understand that commas are part of the display but that doesn't work.
My next thought was to use a formatter function:
data: {
table: function(){...change strings to float etc}
}
None of my attempts at the latter seem to work as I can't figure out what the data object looks like when accessed from a table. Any advice would be appreciated.
A solution that seems to have fixed the issue was to add a "parsed" function here is the api reference: http://api.highcharts.com/highcharts/data.parsed
I added the following to the data property:
data: {
table: 'datatable',
parsed: function()
{
var chartData = this.columns;
var nData = [];
for(var a in chartData)
{
var tempArray = [];
for(var e in chartData[a])
{
var v = chartData[a][e].replace(/\,/g,"").replace("NA","0");
/\d/g.test(v) == true ? v = parseFloat(v) : v = v;
tempArray.push(v);
}
nData.push(tempArray);
}
this.columns = nData;
//alert(JSON.stringify(nData));
//this.columns = [];
//this.columns.push(nData[0]);
//this.columns.push(nData[1]);
}
},
...etc
Related
I am currently using table sorter and just want to know if there is a way to have a value by default always shows up regardless of the selected filter from the filter-select list. I tried using filter functions, but after I added a filter function for a column that has a filter-select, it loses the filter-select list with all of the available values.
For example, here is the filter function that I tried using, it should show "John" regardless of the values that are selected:
0 : function(e, n, f, i, $r, c, data) {
var x = e===f;
var y = e==='John';
var show = x|y;
return show;
},
Am I missing something?
In javascript, the OR operator requires two vertical bars:
0 : function(e, n, f, i, $r, c, data) {
var x = e===f;
var y = e==='John';
var show = x || y;
return show;
},
Maybe a better method would be to use the filter_defaultFilter option which can be used as follows (demo):
$(function() {
$('table').tablesorter({
theme: 'blue',
widgets: ['zebra', 'filter'],
widgetOptions: {
filter_defaultFilter: {
// Ox will always show
// {q} is replaced by the user query
2: '{q}|Ox'
}
}
});
});
Also, make sure to include a "filter-match" class name in the header cell:
<th class="filter-match">...</th>
otherwise "OR" queries default to exact cell content matches.
I have a google sheet that I would like to have generate an email alert when one column is greater than the other. Specifically, column F > column G. Here is what I have so far, any advice would be greatly appreciated, as I do not have much skill writing functions.
function readCell() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Watch list");
var value = sheet.getRange("F2").getValue();
var value1 = sheet.getRange("G2").getValue();
if(value>value1) MailApp.sendEmail('example#gmail.com', 'subject', 'message');
};
Currently this only attempts to compare cell F2 to cell G2. Is there a way to make the function compare the entire F column against column G, and generate an email for each individual case where Fx > Gx ?
Thank you!!
You have to loop all over the range.
first instead of getting the content of one cell you'll need to get the content of all the column:
var value = sheet.getRange("F2").getValue();
become that
var values = sheet.getRange("F2:F").getValues();
(same for value1)
then you need to create an empty table that will collect the results:
var results = [];
and now you need to loop throught all the values:
for(var i=0;i<values.length;i++){
//do the comparaison and store result if greater for example
}
then you may send the result.
all put together it give something like that:
function readCell() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Watch list");
var values = sheet.getRange("F2:F").getValues();
var value1s = sheet.getRange("G2:G").getValues();
var results = [];
for(var i=0;i<values.length;i++){
if(values[i]<value1s[i]){
results.push("alert on line: "+(i+2)); // +2 because the loop start at zero and first line is the second one (F2)
}
}
MailApp.sendEmail('example#gmail.com', 'subject', results.join("\n"));
};
If you want to trigger that function automatically you'll also need to change the way you call the spreadsheet (instead of getActive.... you'll need to use openById)
I have a google form and I would like to sort it's responses in a separate sheet on google sheets. The results of the form look sort of like this.
Id Job
1 Shelving, Sorting
2 Sorting
1 Cleaning, Shelving
3 Customer Service
2 Shelving, Sorting
which I would like to format into
Id Jobs
1 Cleaning, Shelving, Sorting
2 Shelving, Sorting
3 Customer Service
Is there a formula I can use to accomplish this, noting that it ignores duplicates and groups the different ids? Ordering of the jobs does not matter.
Working example here.
The code is like:
=unique(transpose(split(join(", ",filter(B1:B10,A1:A10=1)),", ")))
where
filter(B1:B10,A1:A10=1) gives you all the B values where A = 1
join(",", filter(...)) joins the list with the ", " separator (e.g. "apple, orange" and "kiwi" becomes "apple, orange, kiwi"
split(join(...)) splits the list into an array (e.g. back to [apple, orange, kiwi]
transpose(split(...)) converts the horizontal list to vertical list
unique(transpose(...)) gives you the unique values (unique() only works with vertical list)
After this, you need to transpose then join the list
Note you must keep the separator consistent (e.g. always "," or ", ")
This is Apps Script code instead of a function. To use it, you will need to use the Tools menu, and open the script editor. Then select the function name from the drop down list, and then click the "Run" button.
To use this code, you need to have a source and a destination sheet. You will need to change the sheet names in the code to your sheet names. In this code, the source sheet is named 'Data'. You will need to change that to the name of your source sheet. In this code, the destination sheet is named 'Output', and is at the bottom of the code. This code gets data starting in row two, and writes the output data starting in row two. I tested it with your values and it works.
function concatCellData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheetByName('Data');
var colOneData = sh.getRange(2, 1, sh.getLastRow()-1, 1).getValues();
var colTwoData = sh.getRange(2, 2, sh.getLastRow()-1, 1).getValues();
var newData = [],
newDataColOne = [],
colOneValue,
existInNewData = false,
colB_One,
colB_Two,
dataPosition,
thisValue,
combinedArrays = [],
arrayTemp = [];
for (var i=0;i<colOneData.length;i+=1) {
colOneValue = colOneData[i][0];
dataPosition = newDataColOne.indexOf(colOneValue);
existInNewData = dataPosition !== -1;
if (!existInNewData) {//If it doesn't exist in the new data, just write the values
newDataColOne.push(colOneValue);
newData.push([colOneValue, colTwoData[i][0]]);
continue;
};
colB_One = [];
colB_Two = [];
combinedArrays = []
arrayTemp = [];
colB_One = colTwoData[i][0].split(",");
colB_Two = newData[dataPosition][1];
colB_Two = colB_Two.split(",");
var combinedArrays = colB_One.concat(colB_Two);
//Get unique values
for (var j=0;j<combinedArrays.length;j+=1) {
thisValue = combinedArrays[j].trim();
if (arrayTemp.indexOf(thisValue) === -1) {
arrayTemp.push(thisValue);
};
};
newData[dataPosition] = [colOneValue, arrayTemp.toString()]; //Overwrite existing data
};
ss.getSheetByName('Output').getRange(2, 1, newData.length, newData[0].length).setValues(newData);
};
I'm using angular ui-grid (no ng-grid) and want to pass a function to calculate a column's total value. In the documentation they explicitly say it is possible; it is just that I canĀ“t find how to do it.
This is how I'm showing a total (sum) for another columns:
aggregationType: uiGridConstants.aggregationTypes.sum,
aggregationHideLabel: true,
footerCellFilter: 'currencyFilter',
footerCellClass: 'ui-grid-centerCell'
Now, instead of using uiGridConstants.aggregationTypes.sum, I want to pass a function to calculate the value.
Many thanks and bye ...
My Idea is to Create a method in your Controller like
$scope.sum = function(row){
var sum1 = row.entity.sum1 + row.entity.sum2;
console.log('Sum of Value is = ',sum1);
}
Note : sum1 and sum2 is columnDefs of Field value like
$scope.gridsOptions = {
columnDefs : [
{
field : 'sum1',
name :'xx'
},
{
field : 'sum2',
name : 'xxx'
}
]}
You can also solve this by adding custom tree aggregation.
treeCustomAggregations: {
sum: {
aggregationFn: stats.aggregator.sumSquareErr, finalizerFn: function (aggregation) {
//Do rest of your calculations here
var total = $scope.gridApi.grid.columns[column_number].getAggregationValue() ;
aggregation.value = total ;
aggregation.rendered = (aggregation.value).toFixed(1);
}
Or you can refer this question for custom aggregate template and calling your custom function from it.
Lets say i have the following JSON
{
names: ["John", "Peter", "Ron", "John", "James", "John"]
}
I need DustJS to render the following names
John
Peter
Ron
James
Notice that these are unique values in an array. Any ideas? Thank you so much!
This can be done using a common algorithm to 'unique' an array:
Array.prototype.getUnique = function(){
var u = {}, a = [];
for(var i = 0, l = this.length; i < l; ++i){
if(u.hasOwnProperty(this[i])) {
continue;
}
a.push(this[i]);
u[this[i]] = 1;
}
return a;
}
It's done by taking the values, attempting to add them as keys to an object (which will only work if they're different). If success, it adds that key to an array. If fail, it ignores the key. It then returns the array. I have a working dust.js demo here:
Working Demo
I believe this will generate your "also acceptable" form:
{#options}] {.} {#variants} {.options[$idx]} {/variants} {/options}