I have a table in Tabulator and would like to show all 0 values in the cells as blank. What's the best way to achieve this?
My first attempt was to write a custom mutator:
mutator: function(value, data, type, params, component){
if (value == 0){
return "";
}
else{
return value;
}
}
This works but feels wrong. Further, I would like to create calculated fields on top of this and this doesn't work properly with the blank strings. Then I need to re-convert them back to zeroes in the next function.
Thanks for your help
you can create a function that returns a copy of the original array but with all 0 values in the cells as blank then you display it, and each time you need to calculate or update you do it based on/in the original one then you always display the copy
Just use a cell formatter. A mutator will change the data but I don't think you want this - you just want to change the display of the data.
See my Codepen here and take a look at the moneyColFormatter function.
Specifically, in the cell definition:
...
formatter: (cell) => this.moneyColFormatter(cell),
and then implement it somehow
private moneyColFormatter(cell): string {
// If we want to show 0 values as blank:
if (!cell.getValue()) {
return "";
}
return cell.getValue();
}
The Codepen also contains aggregated functions, calculated cols and custom dynamic columns.
Related
I have recently discovered Tabulator.js and its possibility to have e. g. the average of all values of a column at the bottom.
I wondered whether one can also have the minimum and maximum instead of just one thing. I did not find that in the docs, but it might be possible by extending the library? (I would not want to have one at the top, and as I need more than two calculations, that would not be a solution anyway.)
This is similar to another answer recently for the topCalc property.
You can put, effectively, whatever you want in a footer row. Use the bottomCalc and bottomCalcFormatter properties of the column definition along with a custom function to get the appropriate content.
In the custom function you can use bult in functions such as the table.getCalcResult() method.
eg: return an array of sum, average, count
let table = new Tabulator("#my-table-id", {
...
columns:[
...
{
title: 'My col',
...,
bottomCalc: function(v, d, p) {
// v - array of column values
// d - all table data
// p - params passed from the column definition object
let res = table.getCalcResults();
// eg Get sum and count for a column with id 'C1'
let c1_calc = 0, c1_count = 0;
d.forEach(function(row) {
c1_calc += row["c1"];
c1_count++;
});
return [
(parseInt(res.bottom["COL_1_ID"], 10) + parseInt(res.bottom["COL_2_ID"], 10)),
(parseInt(res.bottom["COL_1_ID"], 10) + parseInt(res.bottom["COL_2_ID"], 10)) / 2,
c1_calc,
c1_count
];
}
}
],
...
);
Once you have the content you can use a custom formatter to display it nicely.
See Custom Calculation Function and Calculation Results in the docs.
I have updated my Codepen again to add a bottomCalc function and formatter. See the definition for the AggregateFn column, the getBottomAggregate function that implements it and the bottomAggregateFormatter function that formats it.
Hope that helps.
I have a simplified test scenario created where I have a spreadsheet with two cells (C2/C3) having an array formula:
{=NaNTest()}
My simplified CustomFunction is as follows:
public class NaNTest : CustomFunctions.Function
{
public NaNTest() : this( "NaNTest" ) { }
public NaNTest( string name ) : base( name, CustomFunctions.Volatility.Invariant, CustomFunctions.ValueType.Variant ) { }
public override void Evaluate( CustomFunctions.IArguments a, CustomFunctions.IValue r )
{
var result = new double[ 1, 2 ];
result[ 0, 0 ] = double.NaN;
result[ 0, 1 ] = 0d;
r.SetArray( result );
}
}
This sets both C2 and C3 to #NUM! when I'd expect only C2 to be. Is there a way to make it correctly* assign C3 to 0?
Thanks in advance.
* I say correctly because we have to implement an Excel add-in that our clients use to author spreadsheets and it provides same 'functionality' that we provide on 'our servers' when we open/process the spreadsheet in our 'SpreadsheetGear calculations' (i.e. the NaNTest() function above). The libraries we use to create the add-in only assign C2 to #NUM! and having the two implementations (client side add-in vs server side SpreadsheetGear) behaving differently makes maintenance/debugging difficult.
This behavior is by design. Note the comment in the documentation for the IValue.SetArray(...) method:
If any of the numbers in the array are not valid numbers, the result
of the custom function will be ValueError.Num.
Since NaN isn't a valid number the entire array will resolve to #NUM! instead. Actually, if you try to set a cell value on its out (outside of a custom function), such as...
worksheet.Cells["A1"].Value = double.NaN;
...you should find that cell evaluates to #NUM! as well. If such cases can occur in your custom function, you'll likely just need to write a check for this condition and respond in whatever manner is required by your application.
I can not find a formulat that multiplies chances the way i want.
I can not use additional cells or VBA because this is a company excel sheet that is locked to a certain format.
Here is some pseudocode that illustrates what i want to do;
value oneminus(value) //typeof delegate
{
return 1 - value;
}
value ProductDelegate(range, delegate)
{
Result result = 1;
foreach value in range
{
result *= delegate(value);
}
return result;
}
What i would want to call is a prefabricated version of the ProductDelegate. I would call it like so =ProductDelegate(J56:J73, "1-"&J). I do not think that ProductDelegate actually exists so i feel like what i am asking is not implemented in excel. Are there any options for this particular usecase? Any statistics function i am missing?
You don't need VBA for this. Just type the following formula but hold down CTRL-SHFT when hitting enter:
=PRODUCT(1-J56:J73)
I want to sort the elements in my list and have the option of filter them the same way MS Excel does.
So it should be able to keep the filtered elements in the table and apply a filter within those results as well. Also be able to sort them without refreshing the whole table.
Any help is greatly appreciated!
you can do it with a criteria in you list action of your controller
def result
if ( params?.filter && params?.filterVal) {
result = Book.createCriteria().list(max: params?.max, offset: params?.offset) {
eq(params?.filter,params?.filterVal)
}
} else {
// normal list retrieval code
}
where params?.filter is the property to filter on and params?.filterVal is the value
I'm having issues using YUI's DataTable Column Selection Functionality. I've tried,
myEndColDataTable.subscribe("theadCellClickEvent", myEndColDataTable.onEventSelectColumn);
and
myEndColDataTable.subscribe("cellClickEvent", function (oArgs) {
this.selectColumn(this.getColumn(oArgs.target));
});
The issue is, I have an initial column selected programmatically. I can highlight the other column, but it doesn't remove the selection from the initially-selected column.
You are correct - there is no quick clean solution.
YUI DataTable currently (as of 2.8) lacks an unselectAllColmns method to match unselectAllRows (which is called by onEventSelectRow).
It is also worth noting that onEventSelectColumn selects the column header, so unselectAllCells will not work.
You could implement your own unselectAllColumns() function like this:
function unselectAllColumns (dataTable) {
var i, oColumn, oColumnSet = dataTable.getColumnSet();
for (i=0; i<oColumnSet.keys.length; i++) {
oColumn = oColumnSet.keys[i];
if (oColumn.selected) {
dataTable.unselectColumn(oColumn);
}
}
}
This will be marginally more efficient than using getSelectedColumns() because you will not need to build an intermediate array of only selected columns (looking at the source getSelectedColumns calls getColumnSet and walks the array just as above).
I guess I can do this, but its not elegant. There has to be a better way.
myEndColDataTable.subscribe("cellClickEvent", function (oArgs) {
var colUnSelect = myEndColDataTable.getSelectedColumns();
myEndColDataTable.unselectColumn(colUnSelect[0]);
myEndColDataTable.selectColumn(myEndColDataTable.getColumn(oArgs.target));
});