本文介绍了使用HTML / CSS / JS也许XSLT在每个页面上打印小计?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用开放标准来列印报表,此报表需要在每个网页的结尾处加入小计。

I would like to use the open standards for printing reports, this report would need to have subtotals on the end of each page.

线程为了使用XSL-FO而不是CSS2,

The thread Why use XSL-FO instead of CSS2, for transform HTML into good PDF? suggest that HTML with CSS3 is the way to go.

现在,我得到的问题是确定与HTML或与CSS或与JS的地方,A4页面将填充,以便页面拆分将出现。

Now the problem that I get is determining with HTML or with CSS or with JS the place where the A4 page will be filled so that the pagebreak would appear.

有分页选择器:

page-break-before: always | avoid — always/avoid page breaks before the item
page-break-after: always | avoid — always/avoid page breaks after the item
page-break-inside: always | avoid — always/avoid page breaks in the middle of the item

但这些不是真正有用的每个页面上的小计的目的,因为我不知道页面何时会填满,所以我可以在其中放置一个带有这样的CSS的标签。

But these aren't really usefull for the purpose of subtotals on each pages as I don't know when would the page fill up so that I could place a tag there with such CSS applied to it.

HTML TABLE标签支持一些听起来很有前景的表头和页脚:

The HTML TABLE tag suppors somekind of table header and footer that sounds promising:



<TABLE>
<THEAD>
     <TR> ...header information...
</THEAD>
<TFOOT>
     <TR> ...footer information...
</TFOOT>
<TBODY>
     <TR> ...first row of block one data...
     <TR> ...second row of block one data...
</TBODY>
<TBODY>
     <TR> ...first row of block two data...
     <TR> ...second row of block two data...
     <TR> ...third row of block two data...
</TBODY>
</TABLE>

但是这又不是非常有用,因为相同的页脚会出现在所有页面上具有相同的小计而不是每个页面。否则,我应该使用不同的TFOOT和TBODY,一个静态结构根据页面是否填充的表...但我不能得到那种信息,只有行数,我可以指定当构建HTML表。我没有看到的方式来创建它们,因为A4尺寸会适合他们。

But this again isn't very usefull as the same footers would appear on all pages with the same subtotals and not for each page. Otherwise I should make a table with different TFOOTs and TBODYs, a static structure according to when the page is filled... but I can't get that kind of information, only the number of rows is that I could specify when building the HTML table. I dont see the way to create them as the A4 size would fit them.

我不知道,也许XSLT会在这里帮助或javascript?有没有开放的标准CSS3,HTML5或其他解决方案这个问题,我不知道?如果没有,任何人都知道一个解决方法,解决这个问题的示例

I don't know, maybe XSLT would help here or javascript? Is there an open standard CSS3, HTML5 or other solution for this problem that I'm not aware of? If no, anyone knows a workaround, examples for solving this?

推荐答案

下面的代码。

<!DOCTYPE html>
<html>
  <body>
    <table class="data">
      <caption><b>MY TABLE</b></caption>
      <thead>
        <tr>
          <th>Col 1</th><th>Col 2</th>
        </tr>
      </thead>
      <tbody>
        <tr><td>1<td>1<tr><td>0<td>99<tr><td>1<td>1<tr><td>0<td>99<tr><td>1<td>1<tr><td>0<td>99
        <tr><td>2<td>9<tr><td>2<td>88<tr><td>2<td>0<tr><td>2<td>88<tr><td>2<td>0<tr><td>2<td>88
        <tr><td>3<td>1<tr><td>4<td>77<tr><td>3<td>1<tr><td>4<td>77<tr><td>3<td>1<tr><td>4<td>77
        <tr><td>4<td>8<tr><td>6<td>66<tr><td>4<td>1<tr><td>6<td>66<tr><td>4<td>1<tr><td>6<td>66
        <tr><td>5<td>1<tr><td>8<td>55<tr><td>5<td>1<tr><td>8<td>55<tr><td>5<td>1<tr><td>8<td>55
        <tr><td>6<td>7<tr><td>0<td>44<tr><td>6<td>2<tr><td>0<td>44<tr><td>6<td>2<tr><td>0<td>44
        <tr><td>7<td>1<tr><td>2<td>33<tr><td>7<td>1<tr><td>2<td>33<tr><td>7<td>1<tr><td>2<td>33
        <tr><td>8<td>6<tr><td>4<td>22<tr><td>8<td>3<tr><td>4<td>22<tr><td>8<td>3<tr><td>4<td>22
        <tr><td>9<td>1<tr><td>6<td>11<tr><td>9<td>1<tr><td>6<td>11<tr><td>9<td>1<tr><td>6<td>11
        <tr><td>1<td>0<tr><td>0<td>99<tr><td>1<td>4<tr><td>0<td>99<tr><td>1<td>4<tr><td>0<td>99
        <tr><td>2<td>1<tr><td>2<td>88<tr><td>2<td>1<tr><td>2<td>88<tr><td>2<td>1<tr><td>2<td>88
        <tr><td>3<td>1<tr><td>4<td>77<tr><td>3<td>1<tr><td>4<td>77<tr><td>3<td>1<tr><td>4<td>77
        <tr><td>4<td>5<tr><td>6<td>66<tr><td>4<td>5<tr><td>6<td>66<tr><td>4<td>5<tr><td>6<td>66
        <tr><td>5<td>1<tr><td>8<td>55<tr><td>5<td>1<tr><td>8<td>55<tr><td>5<td>1<tr><td>8<td>55
        <tr><td>6<td>4<tr><td>0<td>44<tr><td>6<td>6<tr><td>0<td>44<tr><td>6<td>6<tr><td>0<td>44
        <tr><td>7<td>1<tr><td>2<td>33<tr><td>7<td>1<tr><td>2<td>33<tr><td>7<td>1<tr><td>2<td>33
        <tr><td>8<td>3<tr><td>4<td>22<tr><td>8<td>7<tr><td>4<td>22<tr><td>8<td>7<tr><td>4<td>22
        <tr><td>9<td>1<tr><td>6<td>11<tr><td>9<td>1<tr><td>6<td>11<tr><td>9<td>1<tr><td>6<td>11
        <tr><td>1<td>2<tr><td>0<td>99<tr><td>1<td>8<tr><td>0<td>99<tr><td>1<td>8<tr><td>0<td>99
        <tr><td>2<td>1<tr><td>2<td>88<tr><td>2<td>1<tr><td>2<td>88<tr><td>2<td>1<tr><td>2<td>88
        <tr><td>3<td>0<tr><td>4<td>77<tr><td>3<td>9<tr><td>4<td>77<tr><td>3<td>9<tr><td>4<td>77
        <tr><td>4<td>1<tr><td>6<td>66<tr><td>4<td>1<tr><td>6<td>66<tr><td>4<td>1<tr><td>6<td>66
        <tr><td>5<td>1<tr><td>8<td>55<tr><td>5<td>0<tr><td>8<td>55<tr><td>5<td>0<tr><td>8<td>55
        <tr><td>6<td>1<tr><td>0<td>44<tr><td>6<td>1<tr><td>0<td>44<tr><td>6<td>1<tr><td>0<td>44
        <tr><td>7<td>0<tr><td>2<td>33<tr><td>7<td>1<tr><td>2<td>33<tr><td>7<td>1<tr><td>2<td>33
        <tr><td>8<td>1<tr><td>4<td>22<tr><td>8<td>1<tr><td>4<td>22<tr><td>8<td>1<tr><td>4<td>22
        <tr><td>9<td>0<tr><td>6<td>11<tr><td>9<td>2<tr><td>6<td>11<tr><td>9<td>2<tr><td>6<td>11
        <tr><!--Use this row for on-screen totals if needed; otherwise, leave it empty.-->
      </tbody>
    </table>
  </body>
</html>

<style>
  @media screen {
    .print {
      display: none; /*Prevents print version of table from showing on screen*/
    }
  }
  @media print {
    .data {
      display: none; /*Prevents screen version of table from showing in print*/
    }
    .print {
      display: block;
    }
    .print > .data {
      display: inline-table; /*Prevents page breaks better than page-break-inside: avoid;*/
      vertical-align: top;
    }
    /*The following rule makes rows opaque in IE even if background colors are disabled.*/
    .print.fixIE > .data > thead > tr > th:after,
    .print.fixIE > .data > tbody > tr:first-child > td:after {
      display: block;
      border-bottom: 18pt solid white; /*Border-width = line-height*/
      margin-top: -18pt; /*Negative line-height*/
      margin-right: -.5em; /*Negative td padding-right*/
      margin-left: -.5em; /*Negative td padding-left*/
      content: "";
    }
    .overlap {
      margin-bottom: -20pt; /*Negative row height (including borders)*/
    }
  }
  .data {
    table-layout: fixed; /*Columns must have fixed widths! Set with <col>s, if needed.*/
    width: 100%;
    border-spacing: 0;
    white-space: nowrap;
    font-size: 12pt;
    line-height: 18pt; /*If you change this, other CSS values must also be changed!*/
    border-right: 1pt solid black;
  }
  .data > thead > tr > th {
    border-top: 1pt solid black;
    border-left: 1pt solid black;
    background: white;
    padding: 0 .5em 0 .5em;
  }
  .data > tbody > tr > td {
    border-top: 1pt solid black; /*If you change this, .overlap must also be changed!*/
    border-left: 1pt solid black;
    background: white;
    padding: 0 .5em 0 .5em; /*If you change this, other CSS values must also be changed!*/
  }
  .data > tbody > tr:last-child > td {
    border-bottom: 1pt solid black; /*If you change this, .overlap must also be changed!*/
  }
  .data > tbody {
    text-align: right;
  }
</style>

<script>
  //This function takes two arguments:
  //1) a reference to a table element
  //2) an array of column indexes indicating which columns have numbers to be totalled.
  function printSubtotals(table, columns) {
    var
      tbody = table.tBodies[0],
      row = tbody.rows[0];
    if(!row)
      return;
    var cellCount = row.cells.length;
    if(!cellCount)
      return;
    var
      subtotals = [],
      rows = table.rows,
      thead = table.tHead,
      caption = table.querySelector('caption'),
      colgroup = table.querySelector('colgroup'),
      emptyTable = table.cloneNode(false),
      emptyRow = row.cloneNode(true),
      printDiv = document.createElement('div'),
      overlap = document.createElement('div'),
      subtotalCount = columns.length,
      rowCount = rows.length - 1,
      cells, subtotalCells, i, r;
    if(colgroup && colgroup.parentNode === table)
      emptyTable.appendChild(colgroup.cloneNode(true));
    emptyTable.appendChild(tbody.cloneNode(false));
    printDiv.className = /MSIE /.test(navigator.userAgent) ? 'print fixIE' : 'print';
    overlap.className = 'overlap';
    for(i = subtotalCount; i--; subtotals.push(0));
    for(i = cellCount; i--; emptyRow.cells[i].innerHTML = '');
    for(r = row.rowIndex; r < rowCount; r++) {
      printDiv.appendChild(overlap.cloneNode(true));
      tbody = printDiv.appendChild(emptyTable.cloneNode(true)).tBodies[0];
      cells = tbody.appendChild(rows[r].cloneNode(true)).cells;
      subtotalCells = tbody.appendChild(emptyRow.cloneNode(true)).cells;
      for(i = subtotalCount; i--;) {
        subtotals[i] += parseFloat(cells[columns[i]].innerHTML);
        subtotalCells[columns[i]].innerHTML = '<b>Total: ' + subtotals[i] + '</b>';
      }
    }
    printDiv.removeChild(printDiv.children[0]);
    tbody = printDiv.children[0].tBodies[0];
    if(caption && caption.parentNode === table)
      tbody.parentNode.insertBefore(caption.cloneNode(true), tbody);
    if(thead)
      tbody.parentNode.insertBefore(thead.cloneNode(true), tbody);
    table.parentNode.insertBefore(printDiv, table);
  }

  printSubtotals(document.querySelector('.data'), [0,1]);
</script>

Javascript函数的作用是创建一个只打印版本的表,隐藏小计行连接到它。小计行由下一行覆盖,因此只有在下一行碰到下一页时,或者它是表中的最后一行时,它才会显示。这应该工作在任何浏览器,无论纸张大小。它可能看起来效率低,但是感知的性能命中是可忽略的,因为打印表在页面加载时不呈现。仍然,我不会推荐这种技术用于具有数千行的表。

What the Javascript function does is create a print-only version of the table in which every row has a hidden subtotals row attached to it. The subtotals row is covered up by the next row, so it's only visible if the next row gets bumped to the next page, or it's the last row in the table. This should work in just about any browser regardless of paper size. It may seem inefficient, but the perceived performance hit is negligible since the print table doesn't render on page load. Still, I wouldn't recommend this technique for tables with many thousands of rows.

请注意,上面的代码只是一个概念验证,不是特别鲁棒。我知道的一些事情会破坏:

Note that the above code is just a proof-of-concept, and as such, is not particularly robust. A few things that I know will break it are:

这些东西都可以通过对JavaScript和CSS的正确修改来实现。

Some of these things are doable with the right modifications to the JavaScript and CSS.

这篇关于使用HTML / CSS / JS也许XSLT在每个页面上打印小计?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!