2010年4月28日 星期三

透過 CSS 讓列印時 Table 的標頭內容可以每頁重複

希望透過 CSS 在使用 window.print() 時,列印出來的 Table 內容(假設資料量很大),可以在每一頁都能重複標頭(Header)內容。首先,可以使用 CSS 裡的 page-break-before: always,可以強迫換頁。所以,我在範例中定義了:

<style type="text/css">
.newpage
{
page-break-before: always; 
}
</style>

假設我目前的 Table 內容如下:

<table border="1" id="tbDemo" >
  <thead>
  <tr><th id="pageHeader">編號</th></tr>
  </thead>
  
  <tbody>
  <tr><td>1</td></tr>
  <tr><td>2</td></tr>
  <tr><td>3</td></tr>
  <tr><td>4</td></tr>
  <tr><td>5</td></tr>
  <tr><td>6</td></tr>                             
  </tbody>
</table>    
接下來,使用 jQuery 讓 Table 每兩筆資料(實際上是情況而調整筆數設定)就自動產生一個標頭內容,且將這標頭內容套用剛剛加入的 CSS 設定。

<script>
$(function(){

var $rows=$("#tbDemo > tbody > tr");  
$rows.each(function(i) {
//取2的倍數,排除最後一筆
if((i+1) % 2==0 && i!=($rows.size()-1))
{
   $(this).after("<tr class='newpage'><th>"+$("#pageHeader").text()+"</th></tr>");      
}
})
})
</scrip>

如此,在使用預覽列印時,就可以看到以下每兩筆資料一頁且有標頭的結果:

原本以為,故事這樣就結束了,但...唉,看一下 FireFox 的結果~

在 FireFox (ver 3.6.3) 的標頭檔,卻重複了兩次。主要原因,是因為我的 Table 定義,用了 <thead> 與 <tbody> 的樣式。在 FireFox 裡,如果遇到換頁的時候,他會自動為每一頁的 Table 內容加上 <thead>  ,而我剛剛又手動用 jQuery 新增了一次,所以才會得到這結果。換言之,使用 FireFox 的瀏覽器,只要你的 Table 內容有用<thead> 與 <tbody> 的樣式,那每一頁自動都會幫你加上標頭喔。只是,目前我真的不希望他主動幫我加。

此時,或許加上判斷瀏覽器的程式,來決定是否要使用 jQuery 來手動增加標頭,會是一個辦法。但,我沒有這麼做。我索性就不用<thead> 與 <tbody> 的樣式。我將 Table 的定義改成以下:

<table id="tGen"  border="1" >
<tr class="trHeader"><td>編號</td></tr>
<tr class="trBody"><td>1</td></tr>
<tr class="trBody"><td>2</td></tr>
<tr class="trBody"><td>3</td></tr>
<tr class="trBody"><td>4</td></tr>
<tr class="trBody"><td>5</td></tr>
<tr class="trBody"><td>6</td></tr>
</table>

而 jQuery 也調整如下:
<script>
$(function(){
 var $rows=$("#tGen tr[class=trBody]");  
   $rows.each(function(i) {
   //取2的倍數,排除最後一筆
  if((i+1) % 2==0 && i!=($rows.size()-1))
  {     
      $(this).after("<tr class='newpage' ><td>"+$("#tGen tr[class=trHeader]").text()+"</td></tr>");
  }
   })    
});   
</script>

而最後出來的結果,就皆大歡喜了。

文章參考:
MEMO-網頁列印強迫分頁
CSS page-break-before Property
.after()
web打印中如何强制分页
Printing Tables
Printing Headers

測試程式下載:
https://sites.google.com/site/paladinsharefiles/home/filelist/RPT.zip?attredirects=0&d=1

6 則留言:

  1. 您好, 拜讀了您這篇文章,使用thead tbody 的方式解決的我的問題, 真是感謝您. 不過, 另外一個問題出現了. 一般印表機可以在第二頁列印出表頭, 但是點陣式的印表機卻不行, 請問這個問題有解決方案嗎? 謝謝

    回覆刪除
  2. Hi,Vickie ~

    我也很好奇,這方法能否在點陣式印表機下行得通,只是目前身邊一時還沒機會借到。但我有個疑問,一般我們在網頁上壓列印時,預設的紙張是 A4。但當你選擇輸出點陣式印表機時,是否有設定列印格式,將紙張選項挑選為「Letter」(或是符合您報表的紙張大小)呢?

    回覆刪除
  3. :) Letter 選擇了之後,用一般印表機可以執行, 但是換成點陣式印表機, 第二頁的表頭就不見了. 我不確定到底是為什麼? 難道是因為點陣式太老舊?

    回覆刪除
  4. 真的好特別喔!另外,不知道你是否方便測試一下。利用 Chrome 瀏覽器,瀏覽該頁面,並使用 Chrome 的列印功能(Ctrl+P),目的地選「列印成 PDF」,然後將 PDF 用那台有歷史的印表機印,不知道會不會正常一些些。

    回覆刪除
  5. 基本上, thead tbody 這個code, 完全不能在CHROME上呈現. 有在國外的討論區看到這似乎是Chrome 的bug.(我花了一整天才發現這個事實) 另外, 我想嘗試您第二種寫法, 卻完全不成功Orz....

    回覆刪除
  6. 阿阿~ 剛測了一下, Chrome 真的有 Bug ... 暈倒
    不過是發現 Chrome 對於 page-break-before: always 的 CSS 判讀會跟 IE、Firefox 有所不同。
    http://www.google.com/support/forum/p/Chrome/thread?tid=20090828aa91bc90&hl=en

    回覆刪除