ag-grid filter not working with formatted number values? - ag-grid

I'm using ag grid with angularjs and the filter does not work with formatted numbers. I use formatted numbers with currency values.
Below is the columndef code:
{ headerName:"GBO", field: "GBO", width: 200, editable:true, cellClass: "number-cell",filter:'agNumberColumnFilter',
cellRenderer : function(params){
if(params.value == "" || params.value == null)
return '-';
else return params.value;
}
}
Before assigning the data to the grid, I format the numbers using :
$scope.formatNumberOnly = function(num,c, d, t){
//console.log(num );
var n = getNumber(num);
//var n = this,
c = isNaN(c = Math.abs(c)) ? 2 : c,
d = d == undefined ? "." : d,
t = t == undefined ? "," : t,
s = n < 0 ? "-" : "",
i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + "",
j = (j = i.length) > 3 ? j % 3 : 0;
return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
};
});
The problem here is that the filter doesn't work with these formatted numbers and only seems to be working for values upto 999.
Can anyone please help me with a solution to this filtering problem?

If you want the filter to work on these formatted values, you should use a valueGetter instead of a valueFormatter
You should implement the above formatter function as a valueGetter in column Definition.
Also a number filter won't work as in order for your formatted number to be interpreted, it should be a text filter.
Here is an example from official docs.

Related

Talend - split a string to n rows

I would like to split a string in a column to n rows in Talend.
For example :
column
2aabbccdd
The first number is the "n" which I use to define the row lenght, so the expected result should be :
row 1 = aa
row 2 = bb
row 3 = cc
row 4 = dd
The idea here is to iterate on the string and cut it every 2 characters.
Any idea please ?
I would use a tJavaFlex to split the string, with a trick to have n rows coming out of it.
tJavaFlex's main code:
int n = Integer.parseInt(row1.str.substring(0, 4)); //get n from the first 4 characters
String str2 = row1.str.substring(4); //get the string after n
int nbParts = (str2.length() + 1) / n;
System.out.println("number of parts = " + nbParts);
for (int i = 0; i < nbParts; i++)
{
String part = str2.substring(i * n);
if(part.length() > n)
{
part = part.substring(0, n);
}
row2.str = part;
And tJavaFlex's end code is just a closing brace:
}
The trick is to use a for loop in the main code, but only close it in the end code.
tFixedFlowInput contains just one column holding the input string.

Email sender tweaking help needed

I've been trying to understand this email on edit function.
I just cannot figure it out.
I need to send informations in Columns A, B, C, F, G, H and J. The email trigger is in column K and would be selected from data validation.
I have the following function which works great. It send the email but I cannot adjust which rows to show here.
What am I doing wrong?
I want body of the Email to appear as follows when I choose email in K101
Headers in A3 : Data in cell A101
Headers in B3 : Data in cell B101
Headers in C3 : Data in cell C101
Headers in F3 : Data in cell F101
Headers in G3 : Data in cell G101
Headers in H3 : Data in cell H101
Headers in J3 : Data in cell J101
Help???
function mailOnEdit(e) {
var sheet = e.source.getActiveSheet();
if (sheet.getName() !== 'Registry Sheet' || e.range.columnStart !== 11 || e.range.rowStart < 4 || !e.value) return;
var h = sheet.getRange(1, 1, 1, 8)
.getValues()[0],
val = sheet.getRange(e.range.rowStart, 1, 1, 8)
.getValues()[0],
i = 0,
body = "",
notCols = [3, 4];
while (i < 7) {
if (notCols.indexOf(i) == -1) {
body += h[i] + ": " + val[i] + "\n";
}
i += 1;
}
body += "\n\n Contact customer within 30 minutes and reply. Thanks";
MailApp.sendEmail(e.value, "New job", body)
}
Seems like your headers are in row three and not in row one. So
Change
var h = sheet.getRange(1, 1, 1, 8).getValues()[0]
to
var h = sheet.getRange(3, 1, 1, 8).getValues()[0]

Change sheet cells color onEdit

I figured out how to compare dates in Google Sheets but when I try to enter more dates for some reason all the cells that were green and red become all red. Also how can I make two cells red if only one cell has a date?
Example: In cell D18 the Due date is 4-18-2014 and in cell E18 the cell is blank. I want to make both cells red so I would know that I should find out why is that cell red.
This is the code I have so far:
function onEdit() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName('Copy of Project Sheet 1');
var values1Rule1 = s.getRange('E2:E1000').getValues();
var values2Rule1 = s.getRange('D2:D1000').getValues();
var range3Rule1 = s.getRange('D2:E2');
var color1 = 'Red';
var color2 = 'Green';
for (var row in values1Rule1) {
for (var col in values1Rule1[row]) {
if (values1Rule1[row][col] > values2Rule1[row][col]) s.getRange(s.getRange('D2').offset(row, col, 1, 2).getA1Notation()).setBackgroundColor(color1);
else if (values1Rule1[row][col] < values2Rule1[row][col]) s.getRange(s.getRange('D2').offset(row, col, 1, 2).getA1Notation()).setBackgroundColor(color2);
else s.getRange(s.getRange('D2').offset(row, col, 1, 2).getA1Notation()).setBackgroundColor('white'); }}
};
All you need to do is add this condition as an OR clause in your red condition, e.g.
if (values1Rule1[row][col] > values2Rule1[row][col] || values1Rule1[row][col] === '')
But there's lots of "minor" problems with your code. First of all, you're doing way too many API calls unnecessarily. This is a big performance issue. For example, when you offset, you already have the new range, there's no need to getA1Notation then get the range again, you could do:
s.getRange('D2').offset(row, col, 1, 2).setBackgroundColor(color1);
But that's still two calls, getting D2, then offseting. You could get the desired range at once:
s.getRange(row+1, 4, 1, 2).setBackgroundColor(color1);
I'd go even further and build a matrix of colors and set it all at once after the loop:
s.getRange('D2:E1000').setBackgroundColors(colors);
But even better, inside an onEdit you should only work on what has just being edited, instead of triggering a full recalculation of your colors because the user edited something on another column or another sheet entirely.
I think your code should be something like this:
function onEdit(e) {
var ss = e.source;
var s = ss.getActiveSheet();
if( s.getName() !== 'Copy of Project Sheet 1' ) return; //only interested in one sheet
var r = s.getActiveRange();
var c = r.getColumn();
if( c !== 4 && c !== 5 ) return; //only interested in changes on columns D or E
r = r.offset(0, c === 4 ? 0 : -1, 1, 2);
var v = r.getValues()[0];
r.setBackgroundColor(v[1] === '' || v[1] > v[0] ? 'red' : v[1] < v[0] ? 'green' : 'white');
}
--edit
You can not run this function manually directly, because it needs a parameter that is passed only when it runs automatically. But you can emulate it with a test function, like this:
function testEdit() { onEdit({source:SpreadsheetApp.getActive()}); }

How to sort fancytree nodes with folders at the top

I've reviewed the docs and examples for fancytree for hours soaking up all of fancytree's goodness like a sponge but I can't seem to figure how to sort my fancytree object with folders first by using the API calls. I've initially got around the problem by arranging my initial JSON data so that it's already sorted with folders at the top (a requirement of the project) but now I need to add a new folder to the tree and I need to re-sort the object making sure the newly added folder appears at the top of the tree with the others.
I notice there is a curious option for sortChildren() that allows for a defining a custom compare function but I'm having trouble wrapping my head around how to use it.
Any ideas would be much appreciated!
Snippet below on how I am doing things currently (I am populating the new child with data from some form elements):
//add the new foldername to the tree and re-order
var rootNode = jQuery("#document_objects").fancytree("getRootNode");
var childNode = rootNode.addChildren({
title: jQuery('#newfoldername').val(),
tooltip: jQuery('#description').val(),
folder: true
});
rootNode.sortChildren(null, true);
Thanks in advance!
sortChildren(cmp, deep) allows to pass a compare function:
http://www.wwwendt.de/tech/fancytree/doc/jsdoc/FancytreeNode.html#sortChildren
The default implementation (if you pass null or nothing for the cmp argument) is
function(a, b) {
var x = a.title.toLowerCase(),
y = b.title.toLowerCase();
return x === y ? 0 : x > y ? 1 : -1;
};
but you could add some prefix to force a different order, e.g.:
function(a, b) {
var x = (a.isFolder() ? "0" : "1") + a.title.toLowerCase(),
y = (b.isFolder() ? "0" : "1") + b.title.toLowerCase();
return x === y ? 0 : x > y ? 1 : -1;
};
Try below code:
var cmp= function(a, b) {
var x = (a.data.isFolder ? "0" : "1") + a.data.title.toLowerCase(),
y = (b.data.isFolder ? "0" : "1") + b.data.title.toLowerCase();
return x === y ? 0 : x > y ? 1 : -1;
};
node.sortChildren(cmp, true);

Coffeescript memoization?

I have a function that displays a number as a properly formatted price (in USD).
var showPrice = (function() {
var commaRe = /([^,$])(\d{3})\b/;
return function(price) {
var formatted = (price < 0 ? "-" : "") + "$" + Math.abs(Number(price)).toFixed(2);
while (commaRe.test(formatted)) {
formatted = formatted.replace(commaRe, "$1,$2");
}
return formatted;
}
})();
From what I've been told, repeatedly used regexes should be stored in a variable so they are compiled only once. Assuming that's still true, how should this code be rewritten in Coffeescript?
This is the equivalent in CoffeeScript
showPrice = do ->
commaRe = /([^,$])(\d{3})\b/
(price) ->
formatted = (if price < 0 then "-" else "") + "$" + Math.abs(Number price).toFixed(2)
while commaRe.test(formatted)
formatted = formatted.replace commaRe, "$1,$2"
formatted
You can translate your JavaScript code into CoffeeScript using js2coffee. For given code the result is:
showPrice = (->
commaRe = /([^,$])(\d{3})\b/
(price) ->
formatted = ((if price < 0 then "-" else "")) + "$" + Math.abs(Number(price)).toFixed(2)
formatted = formatted.replace(commaRe, "$1,$2") while commaRe.test(formatted)
formatted
)()
My own version is:
showPrice = do ->
commaRe = /([^,$])(\d{3})\b/
(price) ->
formatted = (if price < 0 then '-' else '') + '$' +
Math.abs(Number price).toFixed(2)
while commaRe.test formatted
formatted = formatted.replace commaRe, '$1,$2'
formatted
As for repeatedly used regexes, I don't know.