PDF output of grouped rows is messed up

PDF output of grouped rows is messed up

dnagirldnagirl Posts: 36Questions: 2Answers: 0
edited November 2011 in TableTools
Hi,

I've got a table that I'm grouping on the 1st column. I'm dynamically adding [code]{group Name}{ytd subtotal}{cur value[/code] for the grouping rows. I've also added a Totals row to the footer. The table works and looks great in the browser. But when I hit the PDF button, the "hidden" column[0] data overprints the column[1] data making it unreadable and all the subtotal and total rows are missing. What do I need to do? Optimally, I'd like the pdf to look exactly like the browser output.

Here's my setup:

[code]

var oTable=$('.datatable').dataTable( {
"fnDrawCallback": function ( oSettings ) {
if(oSettings.aiDisplay.length == 0) return;
var nTrs = $('.datatable tbody tr');
$(nTrs).removeData();//so that subtotals from different draws are not summed
var iColspan = nTrs[0].getElementsByTagName('td').length -2;//need 2 columns for the subtotals
var sLastGroup = "";

$(nTrs).each(function(i){
$('td:first',this).css('padding-left','2em');//indent the strain names
var iDisplayIndex = oSettings._iDisplayStart + i;
var sGroup = oSettings.aoData[ oSettings.aiDisplay[iDisplayIndex] ]._aData[0];
if($(nTrs).data()[sGroup] === undefined) $(nTrs).data()[sGroup]={'ytd':0,'cur':0};
$(nTrs).data()[sGroup].ytd += parseFloat(oSettings.aoData[ oSettings.aiDisplay[iDisplayIndex] ]._aData[2]); //subtotal ytd
$(nTrs).data()[sGroup].cur += parseFloat(oSettings.aoData[ oSettings.aiDisplay[iDisplayIndex] ]._aData[3]);//subtotal cur

if(sGroup != sLastGroup){
var nGroup = $('').addClass('group');
var nCell = $(''+sGroup+'' ).attr('colspan',iColspan);
var nProdTot = $('').addClass('ytd');
var nCurTot = $('').addClass('cur');

$(nGroup).append(nCell,nProdTot,nCurTot);

$(this).before(nGroup);
sLastGroup = sGroup;
}
});

for(var g in $(nTrs).data()){
var nSTot=$('.datatable tbody tr.group').has('th:contains("'+ g +'")');
$('th.ytd',nSTot).append($(nTrs).data()[g].ytd);
$('th.cur',nSTot).append($(nTrs).data()[g].cur);
}

},
"fnFooterCallback":function(nRow, aasData, iStart, iEnd, aiDisplay ){
if(0==parseInt(iEnd)) return;
fnTots=function(iColnum){
var total=0;
for(var i=iStart;i



Foo
AB wt
6
20


Bar
Tub wt
43
0


Bar
Ztag
1
74


Bar
KDR-eGFP
17
33


Foo
BTTP6.2-Luc
2
1


Foo
Tg(hsp70tolgfp)v28
354
786



[/code]

Replies

  • dnagirldnagirl Posts: 36Questions: 2Answers: 0
    I should note that if I add the following to the 'oTableTools' options, the overprinting no longer occurs, but the subtotal and total rows still aren't included.

    [code]
    'aButtons':[
    {
    'sExtends':'csv',
    'mColumns':'visible'
    },
    {
    'sExtends':'copy',
    'mColumns':'visible'
    },
    {
    'sExtends':'pdf',
    'mColumns':'visible'
    },
    {
    'sExtends':'print',
    'mColumns':'visible'
    }
    [/code]
  • allanallan Posts: 61,821Questions: 1Answers: 10,127 Site admin
    Can you possibly link us to your (non-working) example? :-). It should work with the code above - by default TableTools should be exporting the footer elements, as long as you are using TH elements for the footer rather than TD.

    Allan
  • dnagirldnagirl Posts: 36Questions: 2Answers: 0
    You may be able to see a live example here: http://sedna.imb.nrc.ca/zbroomdev/Zuncommit/test.php if my sysadmin is allowing access. If not, I did a jsbin here: http://live.datatables.net/ixuneh/17

    That jsbin may also have access difficulties because the TableTools file I've referred to is on my server rather than yours. For some reason the TableTools available from your site complains that
    [quote]
    Message: 'ZeroClipboard' is undefined
    Line: 36 //line 1147 in TableTools.js
    Char: 135
    Code: 0
    URI: http://datatables.net/download/build/TableTools.min.js
    [/quote]
    as can be seen here: http://live.datatables.net/ucijil/

    The pdfs produced by the script on my home server and the one on jsbin are identical. I have not edited the TableTools source file.
  • allanallan Posts: 61,821Questions: 1Answers: 10,127 Site admin
    Thanks very much for setting up the live example - really really useful :-).

    So basically the problem you are facing is that you are dynamically deleting and adding TH nodes in the footer. The problem with this is that DataTables keeps a reference to those nodes - so if they disappear, DataTables is still holding a reference to the old ones - not the new ones! Hence why they don't show up in the PDF, you are dynamically adding them, so DataTables doesn't know that there is a footer!

    So to address this, just create the TH elements in the table like normal and update them on-the-fly, without deleting the elements. Here is a modification of your example which does export the footer: http://live.datatables.net/ixuneh/20/edit .

    Allan
  • dnagirldnagirl Posts: 36Questions: 2Answers: 0
    Excellent to know about the footer issue. Thanks!

    Unfortunately, it doesn't resolve the subtotal issue. I expect the cause is similar? The subtotal rows (ie grouping rows) don't exist/are replaced each time fnDrawCallback is called. I suppose I could add some empty rows to the table for use as grouping rows rather than create them on the fly, but that seems like a brittle solution.

    Suggestions?
  • allanallan Posts: 61,821Questions: 1Answers: 10,127 Site admin
    Sorry - I hadn't really clocked the sub-total rows. They present much for of a challenge I'm afraid, because as you rightly point out, DataTables knows nothing about those rows and thus the data isn't in the datasource that TableTools is looking at.

    There is an internal function in TableTools which does the data get ( https://github.com/DataTables/TableTools/blob/master/media/js/TableTools.js#L1493 ) and I suspect that this would need to be modified to include the extra rows by doing a query on the DOM to get all TR rows, and then checking with DataTables if the data is available for each row. If there data is then use it, if not then its a sub-total row and you need to pull the data in from the DOM.

    Sorry there isn't an easy option with that one.

    Allan
  • dnagirldnagirl Posts: 36Questions: 2Answers: 0
    It's been a while since I posted on this because I was trying out a number of solutions. It turns out that the easiest way to resolve this is to make a button for TableTools like this one :

    [code] {
    'sExtends':'text',
    'sButtonText':'Download PDF',
    'sAction': 'text',
    'bFooter':true,
    'bHeader':true,
    'fnClick':function(nButton, oConfig, oFlash){
    var sFiletext=$('div.dataTables_scroll').html();
    $('form#mpdf input[name="pdf_fn"]').val('TT.pdf');//or something dynamic
    $('#mpdf textarea[name="pdf_html"]').val(sFiletext);
    $('form#mpdf').submit();
    }
    }[/code]

    and a target form like this:

    [code]


    [/code]

    The revised HTML (rather than the pre-DataTable HTML) is submitted to the HTML-to-PDF script (I'm using mPDF: http://mpdf1.com/manual/index.php) which returns a PDF file for download.

    It would be nice if I could avoid the invisible form, but this method allows me output exactly what the DataTable is showing without requiring me to somehow build the table anew serverside. I did try to get ajax to work, but no luck. If anyone had an idea how I could avoid the invisible form, I'd love to hear it.
This discussion has been closed.