Cara menangani page break saat mencetak tabel HTML besar

261

Saya punya proyek yang membutuhkan pencetakan tabel HTML dengan banyak baris.

Masalah saya adalah cara tabel dicetak di atas beberapa halaman. Terkadang akan memotong satu baris menjadi dua, sehingga tidak dapat dibaca karena satu setengahnya ada di tepi halaman yang berdarah dan sisanya dicetak di bagian atas halaman berikutnya.

Satu-satunya solusi yang masuk akal yang dapat saya pikirkan adalah menggunakan DIV bertumpuk alih-alih sebuah tabel dan memaksa pemecah halaman jika diperlukan .. tetapi sebelum melakukan seluruh perubahan, saya pikir saya bisa bertanya di sini sebelumnya.

h3.
sumber
28
Pada garis singgung, mungkin perlu menambahkan a <thead>ke tabel Anda dengan css berikut thead {display: table-header-group; }untuk mencetak header-tabel pada semua halaman berikutnya (berguna untuk tabel data loooooong).
David mengatakan mengembalikan Monica

Jawaban:

277
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test</title>
<style type="text/css">
    table { page-break-inside:auto }
    tr    { page-break-inside:avoid; page-break-after:auto }
    thead { display:table-header-group }
    tfoot { display:table-footer-group }
</style>
</head>
<body>
    <table>
        <thead>
            <tr><th>heading</th></tr>
        </thead>
        <tfoot>
            <tr><td>notes</td></tr>
        </tfoot>
        <tbody>
        <tr>
            <td>x</td>
        </tr>
        <tr>
            <td>x</td>
        </tr>
        <!-- 500 more rows -->
        <tr>
            <td>x</td>
        </tr>
    </tbody>
    </table>
</body>
</html>
Sinan Ünür
sumber
18
Ini juga gagal di browser WebKit (mis. Safari dan Chrome)
Michael Haren
5
Meskipun ini adalah cara yang sesuai standar untuk melakukan ini, satu-satunya browser yang saat ini menerapkan standar adalah Opera. Perhatikan bahwa ini adalah bagian dari css2, dan kurangnya implementasi kemungkinan akan menjadi masalah untuk beberapa waktu mendatang, karena tampaknya tidak ada yang peduli.
pkh
16
Spesifikasi CSS 2.1 menunjukkan bahwa atribut style page break hanya diterapkan pada elemen tingkat blok. Mode tampilan default untuk baris tabel adalah baris tabel. Sayangnya, tidak ada elemen tabel yang merupakan elemen level blok secara default, termasuk tabel itu sendiri.
lsuarez
2
@ SinanÜnür Ini bukan keharusan, jadi Anda tidak bisa mengandalkannya, dan sayangnya dari pengujian saya, saya bisa melihat bahwa webkit melihat "mungkin" dan mengabaikan apa pun di luarnya. Anehnya, IE mendapat dukungan pencetakan meja besar yang lumayan bagus. Tidak pernah terpikir saya akan menyanyikan pujian pada titik tertentu.
lsuarez
6
Saya dapat mengonfirmasi bahwa ini TIDAK berfungsi dengan baik di Chrome atau browser Webkit lainnya (mis. Safari, Opera) - kecuali, dengan "berfungsi dengan baik" yang Anda maksudkan "mengecualikan semua fitur yang dianggap opsional". Saya pikir apa yang kebanyakan orang inginkan adalah menjalankan header dan footer, dan tabel yang hanya memungkinkan page break di antara baris, yang keduanya tidak diterapkan di Webkit pada 2015/11/13.
DoctorDestructo
47

Catatan: saat menggunakan page-break-after: selalu untuk tag, ia akan membuat page break setelah bit terakhir tabel, membuat halaman yang sama sekali kosong di akhir setiap waktu! Untuk memperbaikinya, ubah saja ke page-break-after: auto. Ini akan rusak dengan benar dan tidak membuat halaman kosong tambahan.

<html>
<head>
<style>
@media print
{
  table { page-break-after:auto }
  tr    { page-break-inside:avoid; page-break-after:auto }
  td    { page-break-inside:avoid; page-break-after:auto }
  thead { display:table-header-group }
  tfoot { display:table-footer-group }
}
</style>
</head>

<body>
....
</body>
</html>
Josh P
sumber
Bekerja untuk saya di Chrome dan merupakan solusi CSS sederhana yang bagus.
Ryan
1
Saya mencoba solusi yang sama, tetapi tidak memecah data tabel dan menghilangkan data tambahan alih-alih menampilkannya di halaman berikutnya. Ada tebakan?
Null Pointer
24

Memperluas dari solusi Sinan Ünür:

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test</title>
<style type="text/css">
    table { page-break-inside:auto }
    div   { page-break-inside:avoid; } /* This is the key */
    thead { display:table-header-group }
    tfoot { display:table-footer-group }
</style>
</head>
<body>
    <table>
        <thead>
            <tr><th>heading</th></tr>
        </thead>
        <tfoot>
            <tr><td>notes</td></tr>
        </tfoot>
        <tr>
            <td><div>Long<br />cell<br />should'nt<br />be<br />cut</div></td>
        </tr>
        <tr>
            <td><div>Long<br />cell<br />should'nt<br />be<br />cut</div></td>
        </tr>
        <!-- 500 more rows -->
        <tr>
            <td>x</td>
        </tr>
    </tbody>
    </table>
</body>
</html>

Tampaknya page-break-inside:avoiddi beberapa browser hanya dipertimbangkan untuk elemen blok, bukan untuk sel, tabel, baris maupun inline-blok.

Jika Anda mencoba untuk display:blockyang TRtag, dan menggunakan ada page-break-inside:avoid, ia bekerja, tetapi messes main dengan tata letak meja Anda.

vicenteherrera
sumber
2
Berikut cara mudah untuk menambahkan div secara dinamis dengan jquery:$(document).ready(function(){$("table tbody th, table tbody td").wrapInner("<div></div>");});
Chris Bloom
1
Berkat sinan ürün, vicenteherrera dan Chrisbloom7. Saya menerapkan kombinasi jawaban Anda dan sekarang berhasil!
Nurhak Kaya
Anda dapat mencoba mengatur @media CSS ke tr { display: block; }untuk Print Only, daripada menambahkan semua <div>elemen asing . (Belum diuji tetapi layak dilihat)
Stephen R
11

Tidak ada jawaban di sini yang berfungsi untuk saya di Chrome. AAverin di GitHub telah membuat beberapa Javascript yang berguna untuk tujuan ini dan ini berhasil untuk saya:

Cukup tambahkan js ke kode Anda dan tambahkan kelas 'splitForPrint' ke tabel Anda dan itu akan membagi tabel dengan rapi menjadi beberapa halaman dan menambahkan header tabel ke setiap halaman.

MDave
sumber
Apakah Anda memiliki sampel tentang cara menerapkan ini? Saya telah mencoba untuk menetapkan className tabel saya splitForPrinttetapi di JS tidak ada tempat mengambil referensi elemen menggunakan className splitForPrint. Hanya bagian mana var splitClassName = 'splitForPrint';tetapi itu saja.
Compaq LE2202x
Down memilih karena skrip yang Anda tautkan tidak menyelesaikan masalah OP tanpa banyak memetik dan mengkonfigurasi ulang ceri, dan Anda tidak memberikan contoh bagaimana orang dapat melakukannya.
Chris Bloom
Bekerja seperti pesona bagi saya, tidak ada solusi lain yang berfungsi. +1 Harus menambahkan sedikit css untuk mendapatkan istirahat yang benar. Halaman-break {page-break-after: always; }
fhugas
Yap dengan menambahkan .page-break {page-break-after: always; } itu menyelamatkan hari saya!
milodky
7

Gunakan properti CSS ini:

page-break-after

page-break-before 

Misalnya:

<html>
<head>
<style>
@media print
{
table {page-break-after:always}
}
</style>
</head>

<body>
....
</body>
</html>

melalui

marcgg
sumber
Saya tidak yakin, Anda harus memeriksa. Jika tidak, pisahkan ke dalam array yang berbeda dan pisahkan array dengan div
marcgg
Anda harus menerapkannya pada baris tabel atau bahkan sel, tetapi tidak ke meja, saya pikir. Selain itu, itu harus bekerja.
Pekka
2
tidak bekerja di chrome. Diabaikan seolah-olah 6/13/2012 ketika diterapkan ke TR
ladieu
5

Saya baru-baru ini memecahkan masalah ini dengan solusi yang bagus.

CSS :

.avoidBreak { 
    border: 2px solid;
    page-break-inside:avoid;
}

JS :

function Print(){
    $(".tableToPrint td, .tableToPrint th").each(function(){ $(this).css("width",  $(this).width() + "px")  });
    $(".tableToPrint tr").wrap("<div class='avoidBreak'></div>");
    window.print();
}

Bekerja seperti pesona!

Wendel Tavares
sumber
2

Saya akhirnya mengikuti pendekatan @ vicenteherrera, dengan beberapa tweak (yang mungkin bootstrap 3 spesifik).

Pada dasarnya; kita tidak dapat memecahkan trs, atau tds karena itu bukan elemen tingkat blok. Jadi kami menanamkan divke dalam masing-masing, dan menerapkan page-break-*aturan kami terhadap div. Kedua; kami menambahkan beberapa bantalan ke bagian atas masing-masing div ini, untuk mengimbangi setiap artefak gaya.

<style>
    @media print {
        /* avoid cutting tr's in half */
        th div, td div {
            margin-top:-8px;
            padding-top:8px;
            page-break-inside:avoid;
        }
    }
</style>
<script>
    $(document).ready(function(){
        // Wrap each tr and td's content within a div
        // (todo: add logic so we only do this when printing)
        $("table tbody th, table tbody td").wrapInner("<div></div>");
    })
</script>

Penyesuaian margin dan padding diperlukan untuk mengimbangi beberapa jenis jitter yang sedang diperkenalkan (menurut tebakan saya - dari bootstrap). Saya tidak yakin bahwa saya menghadirkan solusi baru dari jawaban lain untuk pertanyaan ini, tetapi saya pikir mungkin ini akan membantu seseorang.

Harun
sumber
1

Saya menghadapi masalah yang sama dan mencari solusi di mana-mana, akhirnya, saya menemukan sesuatu yang bekerja untuk saya untuk setiap browser.

html {
height: 0;
}

gunakan css ini atau Alih-alih css Anda dapat memiliki javascript ini

$("html").height(0);

Semoga ini akan bekerja untuk Anda juga.

Jay
sumber
0

Saya memeriksa banyak solusi dan tidak ada yang bekerja dengan baik.

Jadi saya mencoba trik kecil dan berhasil:

tfoot with style: position: fixed; bottom: 0px; ditempatkan di bagian bawah halaman terakhir, tetapi jika footer terlalu tinggi itu tumpang tindih dengan isi tabel.

hanya bicara: display: table-footer-group; tidak tumpang tindih, tetapi tidak ada di bagian bawah halaman terakhir ...

Mari kita beri dua langkah:

TFOOT.placer {
  display: table-footer-group;
  height: 130px;
}

TFOOT.contenter {
  display: table-footer-group;
  position: fixed;
  bottom: 0px;	
  height: 130px;
}
<TFOOT  class='placer'> 
  <TR>
    <TD>
      <!--  empty here
-->
    </TD>
  </TR>
</TFOOT>	
<TFOOT  class='contenter'> 
  <TR>
    <TD>
      your long text or high image here
    </TD>
  </TR>
</TFOOT>

Satu cadangan ditempatkan di halaman non-terakhir, kedua menempatkan di footer aktual Anda.

Zenon K.
sumber
-1

Saya sudah mencoba semua saran yang diberikan di atas dan menemukan solusi lintas browser yang sederhana dan berfungsi untuk masalah ini. Tidak diperlukan style atau page break untuk solusi ini. Untuk solusinya, format tabel harus seperti:

<table>
    <thead>  <!-- there should be <thead> tag-->
        <td>Heading</td> <!--//inside <thead> should be <td> it should not be <th>-->
    </thead>
    <tbody><!---<tbody>also must-->
        <tr>
            <td>data</td>
        </tr>
        <!--100 more rows-->
    </tbody>
</table>

Format di atas diuji dan bekerja di peramban silang

Ananth Doss
sumber
-2

Baiklah Guys ... Sebagian besar Solusi di sini tidak berhasil. Jadi begini cara kerjanya bagi saya ..

HTML

<table>
  <thead>
   <tr>
     <th style="border:none;height:26px;"></th>
     <th style="border:none;height:26px;"></th>
     .
     .
   </tr>
   <tr>
     <th style="border:1px solid black">ABC</th>
     <th style="border:1px solid black">ABC</th>
     .
     .
   <tr>
  </thead>
<tbody>

    //YOUR CODE

</tbody>
</table>

Set kepala pertama digunakan sebagai dummy sehingga tidak akan ada batas atas yang hilang di kepala ke-2 (yaitu kepala asli) saat page break.

Aduh
sumber
-3

Jawaban yang diterima tidak berfungsi untuk saya di semua browser, tetapi mengikuti css berhasil untuk saya:

tr    
{ 
  display: table-row-group;
  page-break-inside:avoid; 
  page-break-after:auto;
}

Struktur html adalah:

<table>
  <thead>
    <tr></tr>
  </thead>
  <tbody>
    <tr></tr>
    <tr></tr>
    ...
  </tbody>
</table>

Dalam kasus saya, ada beberapa masalah tambahan dengan thead tr, tetapi ini menyelesaikan masalah asli menjaga baris tabel dari melanggar.

Karena masalah header, saya akhirnya berakhir dengan:

#theTable td *
{
  page-break-inside:avoid;
}

Ini tidak mencegah baris dari melanggar; hanya konten setiap sel.

David Moeller
sumber