使用HTML / CSS / JS也许XSLT在每个页面上打印小计? [英] Print subtotals on each page with HTML/CSS/JS maybe XSLT?

查看:96
本文介绍了使用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:


表行可以分组为表头,表脚和一个或
多个表体部分,分别使用THEAD,TFOOT和TBODY元素,
。这种划分使用户代理能够独立于表头和脚来支持滚动
的表体。当打印long
表时,表头和脚信息可以是包含表数据的每个页面上重复的

Table rows may be grouped into a table head, table foot, and one or more table body sections, using the THEAD, TFOOT and TBODY elements, respectively. This division enables user agents to support scrolling of table bodies independently of the table head and foot. When long tables are printed, the table head and foot information may be repeated on each page that contains table data.



<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:


  • 数据列中的空单元格

  • 数据列中的数字值

  • tbody单元格中的多行内容

  • 改变tbody行中的单元格数量(例如有些列包含colspans,

  • 在不更改其他相关CSS值的情况下更改行高或边框宽度

  • b $ b
  • empty cells in data columns
  • non-numeric values in data columns
  • multi-line content in tbody cells
  • varying cell count in tbody rows (e.g. some have colspans and others don't)
  • letting cell content determine column width
  • changing line-height or border-width without changing other, related CSS values

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

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

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

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆