Add Column when using rowFormatter (Cheese Example) - tabulator

I feel I am missing something simple... The cheese example of how to use the rowFormatter is exactly how I want to implement something, except I'd like to add various additional columns...
I've noted the warning it is important to include only one column in your column definition array to ensure the table renders correctly, however it is exactly what I want to do.
So I tried adding another column to the table constructor which added a column heading but no data.
What an I missing? Surely this is a common use case?

Use the formatter option as apposed to the rowFormatter - which overwrites the entire rows contents.
Based on the printIcon and cheese examples in the Tabulator docs, construct a column formatter, but pass the row as apposed to the cell.
Then its just a matter of constructing the html table as per the cheese example, but return the table, don't append to the element.
My Test Example:
//Generate details
var details = function(row, formatterParams){ //plain text value
var element = row.getElement(),
data = row.getData(),
width = element.outerWidth(),
table;
//define a table layout structure and set width of row
table = $("<table style='width:" + (width - 18) + "px;'><tr></tr></table>");
//add image on left of row
$("tr", table).append("<td><img src='./img/teams/small-60x80/55015.png'></td>");
//add row data on right hand side
$("tr", table).append("<td><div><strong>Type:</strong> " + data.type + "</div><div><strong>Age:</strong> " + data.age + "</div><div><strong>Rind:</strong> " + data.rind + "</div><div><strong>Colour:</strong> " + data.color + "</div></td>");
//append newly formatted contents to the row
//element.append(table);
return table;
//return "<image src='./img/teams/small-60x80/55015.png'>";
};
//define Tabulator
$("#example-table").tabulator({
height:"600px",
layout:"fitColumns",
resizableColumns:false,
columns:[
{formatter:details},
{title:"Cheese", field:"type", sorter:"string"},
{title:"Something Else", field:"blah", sorter:"string"},
],
})

Related

How to keep table formatting when sorting table generated by PHPSpreadsheet?

I have generated an Excel table using PHPSpreadsheet including the style and the autofilter:
The problem is when I sort the data by the second and third columns, the table formatting is gone. This is how it looks like compared if I use Table Style directly from Excel (using Home-> Format as Table):
Is there any way to keep the formatting when I sort the table generated from PHPSpreadsheet?
Relevant PHP Code:
for ($rowNumber = 0, $rowNumberMax = sizeof($rows); $rowNumber < $rowNumberMax; $rowNumber++) //rows (all data)
{
$columnNumber = 0; //1 = A
for ($i = 0, $j = sizeof($tableColumns); $i < $j; $i++) //loop through table header label
{
foreach ($rows[$rowNumber] as $rowKey => $rowValue) //loop through single row data
{
if($tableColumns[$i] == $rowKey)
{
$sheet->setCellValueByColumnAndRow($columnNumber + 1, ($rowNumber + 5), $rowValue);
$currentCell = Utilities::num2alpha($columnNumber) .''. ($rowNumber + 5);
$sheet->getStyle($currentCell)->getNumberFormat()->setFormatCode('#');
$sheet->getStyle($currentCell)->getAlignment()->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_LEFT);
if(($rowNumber+5) % 2 == 0)
{
//even row
$sheet->getStyle($currentCell)->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)->getStartColor()->setARGB('ffd9e1f2');
}
else
{
//odd row
}
$columnNumber++;
break;
}
}
}
}
//set autofilter
$headerFirstCellPosition = 'A4';
$tableLastCellPosition = Utilities::num2alpha(sizeof($tableColumns) - 1) . '' . (sizeof($rows) + 4);
$sheet->setAutoFilter($headerFirstCellPosition . ':' . $tableLastCellPosition);
The problem is you were just applying formatting to the cells based on if the row was even or odd, but it wasn't actually replicating a table in Excel. You would find the same result in Excel if you just formatted every other row like you did with your PHP code, where the "table" format would get lost.
Somebody just recently implemented a first pass of the actual table feature in Excel: https://github.com/PHPOffice/PhpSpreadsheet/pull/2671
You need to be on PHPSpreadSheet version 1.23.0 in order to be able to use this.
Using that, you would have to modify your code but you can go to the Samples section in the code area and view how to implement it: https://github.com/PHPOffice/PhpSpreadsheet/tree/master/samples/Table
https://github.com/PHPOffice/PhpSpreadsheet/blob/master/samples/Table/01_Table.php
Here is the relevant code (I removed some of the lines and added additional comments from the 01_Table.php sample at the link provided).
Table styles can be found here: https://github.com/PHPOffice/PhpSpreadsheet/blob/master/src/PhpSpreadsheet/Worksheet/Table/TableStyle.php
// Create Table
$table = new Table('A1:D17', 'Sales_Data');
// Create Table Style
$tableStyle = new TableStyle();
// this line is the style type you want, you can verify this in Excel by clicking the "Format as Table" button and then hovering over the style you like to get the name
$tableStyle->setTheme(TableStyle::TABLE_STYLE_MEDIUM2);
// this gives you the alternate row color; I suggest to use either this or columnStripes as both together do not look good
$tableStyle->setShowRowStripes(true);
// similar to the alternate row color but does it for columns; I suggest to use either this or rowStripes as both together do not look good; I personally set to false and only used the rowStripes
$tableStyle->setShowColumnStripes(true);
// this will bold everything in the first column; I personally set to false
$tableStyle->setShowFirstColumn(true);
// this will bold everything in the last column; I personally set to false
$tableStyle->setShowLastColumn(true);
$table->setStyle($tableStyle);
Also make sure that you include the following to be able to use these:
use PhpOffice\PhpSpreadsheet\Worksheet\Table;
use PhpOffice\PhpSpreadsheet\Worksheet\Table\TableStyle;
Implementing that into your code will then allow you to sort using the auto filters and keep the formatting like you are expecting.
There are a few caveats such as:
Note that PreCalculateFormulas needs to be disabled when saving spreadsheets containing tables with formulae (totals or column formulae).
Also, as I am actually currently working on doing this, it doesn't look like you can apply an autofilter and have a table at the same time at this point.
That does appear to be on the todo list though, as the first link I provided the contributor has "Filter expressions similar to AutoFilter."
Otherwise, that should get you what you want and aside from being able to auto filter prior to creating the Excel file, it has worked well in my small testing.
Edit to add:
I think you can actually simplify your code a bit by using the functionality of PHPSpreadsheet to create a a spreadsheet from an array.
Documentation from PHPSpreadsheet can be found here: https://phpspreadsheet.readthedocs.io/en/latest/topics/accessing-cells/#setting-a-range-of-cells-from-an-array
You'll need to change it so that the array that is holding the info starts with your headers, so I believe that would look similar to this for your code:
$rows = [
['header1', 'header2', 'header3', 'header4']
];
Then you can populate the $rows array with your data from the rows either with a loop or just a single declaration depending on what you are putting in there, but basically using the below to populate the array.
$rows[] = [
$field1Data,
$field2Data,
$field3Data,
$field4Data
];
After you do that, you can then generate the spreadsheet using the following:
$sheet->getActiveSheet()
->fromArray(
$rows, // the data to set
NULL, // array values with this value will not be set
'A1', // top left coordinate of the worksheet range where we want to set these values (default is A1)
true // adds 0 to cell instead of blank if a 0 is the value
);
After doing the above, you can then add the code to create the table I posted and then save the file and you should be good.
Also, if you are in a situation where you still need to use the autofilter (for instance if you want to pre-filter the file on one or more columns which at this point you can't use a table when doing), you can make the autofilter call a bit easier.
// determine the the number of rows in the active sheet
$highestRow = $spreadsheet->getActiveSheet()->getHighestRow();
// get the highest column letter
$highestColumn = $spreadsheet->getActiveSheet()->getHighestColumn();
// set autofilter range
$spreadsheet->getActiveSheet()->setAutoFilter('A1:'.$highestColumn.$highestRow);
I realize the additional edit goes beyond the question, but figured I'd point it out since there are some built-in methods that you could use to reduce some of your code.
-Matt

tabulator get column from custom column titleFormatter

I have a custom function that hides/shows columns in my tabulator. The column I click on is supposed to hide and several other columns are shown. I have this function working correctly from onclick on an object in a custom cell formatter, but I would like to call it from clicking on the column header. It works except that I can't seem to get a handle of the column I clicked on from column header in order to hide the column.
I'm trying to get the column object and pass it to my function so I can hide that column while I show the others. I'm open to other ways to do this.
this works (cell formatter)
var showForecastCell = function(cell, formatterParams, onRendered){
...
span.onclick = function(){showForecast(cell.getColumn())};
return span
}
this doesn't work (column titleFormatter)
var showForecastHeader = function(t,e,o,i,n){
...
span.onclick = function(){showForecast(t.getColumn())};
return span
}
Is there any way to pass the column object from clicking on the column header? otherwise, if there is a simpler way to hide the column after clicking on the header, I am open to suggestions. I must admit that javascript isn't my strongest language and if I am overlooking something basic, please let me know.
You can check this JsFiddle it hides all other columns except the one you click
for Column call backs you can check documentation here and here
const hideAllButThis = function(e, column) {
const showField = column._column.field;
const columns = column._column.table.columnManager.columns;
for (let i = 0; i < columns.length; i++) {
if (columns[i].field !== showField) {
table.hideColumn("" + columns[i].field + "")
}
}
};

JQuery in VirtualDOM Buffer Rows

I have a column of checkboxes in my table that I want to have checked with parity in row.isSelected().
When using the VirtualDOM the rows in the buffer don't get checked/unchecked as part of a table.getRows() loop to un-check the box. The rows DO get unselected from the table POV via row.deselect().
The checkbox is added with a mutator to the first column:
checkboxMutator = function (value, data) {
return '<input type="checkbox" class="rowCheckBox" name="' + value + '">';
}
The select all logic:
$("#select-all").click(function () {
var rows = table.getRows(true);
rows.forEach(function(row){
row.select();
$("input[name='" + row.getData().index + "']:checkbox").prop('checked', true);
});
});
The rows that don't exist in the DOM at all yet can be checked by adding some logic into rowFormatter to check them on render the first time.
It might not be possible to fix, but I thought it was worth asking about.
Because Tabulator uses a vitrual DOM only the rows that are visible actually exists, rows are created and destroyed as you scroll.
Because of this it is not safe to try and manipulate any DOM elements inside the table from outside.
In your case you should be using a Custom Formatter that uses the isSelected function on the row component to determine if the checkbox should be selected when it is created.
//custom formatter
function checkboxFormatter(cell, formatterParams, onRendered){
//create input element
var input = document.createElement("input");
input.setAttribute("type", "checkbox");
//set checked state
input.checked = cell.getRow().isSelected();
return input;
}
//assign formatter in column definition
{title:"selected?", formatter:checkboxFormatter}
You should then be using the rowSelectionChanged option to redraw the row after selection has changed, which will then cause the formatter to run and update the checkbox.
rowSelectionChanged:function(data, rows){
//rows - array of row components for the selected rows in order of selection
//data - array of data objects for the selected rows in order of selection
//reformat all rows that have changed
rows.forEach(function(row){
row.reformat();
})
}
You can then select all rows in the table by calling the selectRow function on the table.
table.selectRow();

DataTables - How do I get/set the value of a cell in a row?

I´m iterating through the rows of my DataTable with the example I found here in documentation but I want to get the data of the second column, analyze that value and then set my processed value on that cell.
tablaProgDetalle.rows().every( function ( rowIdx, tableLoop, rowLoop ) {
// I suppose here goes the processing and the setting of the cells values.
});
SOLUTION
You can use row().data() inside the anonymous function to get and set row's data. Please note that variable this in inside the anonymous function refers to row being iterated.
var table = $('#example').DataTable();
table.rows().every( function ( rowIdx, tableLoop, rowLoop ) {
var data = this.data();
data[0] = '* ' + data[0];
this.data(data);
});
DEMO
See this jsFiddle for code and demonstration.
You can use rowID to do this; we can set rowID in rowCreated: callback of Datatable, or manually while inserting rows upon table creation. Here I am incrementing 3rd column value upon some event in my project.
//DOM only addition
var rowID = your rowID goes here;
var cols = Table.row(rowID).data();
var count = parseInt(cols[2]);
count = count + 1
cols[2] = count.toString();
Table.row(rowID).data(cols);

Formula Field exception:The Tab formula is not valid

I am getting the exception Tab Formula for tab, t4 is invalid. Formula = [t2]+[t1]: Tag Label must be unique.
I have checkbox, a fundname and amount to invest in fund.
if user check the checkbox he need to fill the amount in amount box and there is total amount calculated based on the no of amount box has amount entered.
Evertything is working fine but only issue is with formula field. it is throwing an exception formula is invalid.
below is what I am using for showing the calculation:
var fullAnchor4 = new Tab
{
Type = TabTypeCode.Custom,
CustomTabType = CustomTabType.Formula,
CustomTabTypeSpecified = true,
AnchorTabItem =
new AnchorTab
{
AnchorTabString = "tbx4_1_text",
XOffset = -10,
YOffset = -5
},
CustomTabWidth = 100,
CustomTabWidthSpecified = true,
Formula = "<formula>[t2]+[t1]</formula>"
};
fullAnchor4.DocumentID = "1";
fullAnchor4.PageNumber = "1";
fullAnchor4.RecipientID = "1";
fullAnchor4.TabLabel = "t4";
fullAnchor4.RoundDecimalPlaces = 2;
runningList.Add(fullAnchor4);
is there something I am doing wrong?
EDIT--
Attached the raw request. removed sensitive info
http://wikisend.com/download/218254/RawRequest 1.txt
Per DocuSign's documentation, Formula Fields cannot be Anchored (link below). Unsure if this is still true today. Also, I noticed in your document you have the Formula Field's Anchor String listed twice. You have it also listed where an email address would be placed "Email Address: tbx4_1_text". Once I removed that duplicate string from the document the call was successful and the Formula Field appears to be calculating correctly.
https://www.docusign.com/support/classic/documentation/cdse-user-guide/advanced-sending/using-the-calculated-fields-feature
Your Formula value should not have XML tags in it. Your resulting API request looks like this:
<Formula><formula>[t2]+[t1]</formula></Formula>
You should use something like this:
Formula = "[t2]+[t1]"
The resulting XML will end up like this:
<Formula>[tw]+[t1]</Formula>

Resources