Jak radzić sobie z podziałami stron podczas drukowania dużej tabeli HTML

261

Mam projekt, który wymaga wydrukowania tabeli HTML z wieloma wierszami.

Moim problemem jest sposób drukowania tabeli na wielu stronach. Czasami przecina rząd na pół, co czyni go nieczytelnym, ponieważ jedna połowa znajduje się na krawędzi krwawiącej strony, a reszta jest drukowana na górze następnej strony.

Jedynym możliwym rozwiązaniem, jakie mogę wymyślić, jest stosowanie skumulowanych DIV zamiast tabeli i wymuszanie podziału strony, jeśli to konieczne .. ale przed przejściem przez całą zmianę pomyślałem, że mógłbym tutaj o to zapytać.

h3.
źródło
28
Na stycznej warto dodać a <thead>do tabeli za pomocą następującego css thead {display: table-header-group; }, aby wydrukować nagłówek tabeli na wszystkich kolejnych stronach (przydatne w przypadku długich tabel danych).
David mówi, że przywraca Monikę

Odpowiedzi:

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
źródło
18
To również nie działa w przeglądarkach WebKit (np. Safari i Chrome)
Michael Haren
5
Chociaż jest to zgodny ze standardami sposób, jedyną przeglądarką, która obecnie implementuje ten standard, jest Opera. Zauważ, że jest to część css2, więc brak implementacji będzie prawdopodobnie problemem przez pewien czas, ponieważ najwyraźniej nikogo to nie obchodzi.
pkh
16
Specyfikacja CSS 2.1 wskazuje, że atrybuty stylu podziału strony są stosowane tylko do elementów na poziomie bloku. Domyślnym trybem wyświetlania wierszy tabeli jest wiersz tabeli. Niestety, żadne elementy tabeli nie są domyślnie elementami poziomu bloku, w tym samą tabelą.
lsuarez
2
@ SinanÜnür Nie jest to wymóg, więc nie możesz na nim polegać, a niestety z moich testów wynika, że ​​webkit zobaczył „może” i zignorował wszystko poza tym. O dziwo, IE ma całkiem niezłą obsługę drukowania dużych tabel. Nigdy nie myślałem, że będę śpiewał pochwały w jakimkolwiek momencie.
lsuarez
6
Mogę potwierdzić, że NIE działa to poprawnie w przeglądarce Chrome ani w żadnej innej przeglądarce Webkit (np. Safari, Opera) - chyba że przez „działa dobrze” masz na myśli „wyklucza wszelkie funkcje, które są uważane za opcjonalne”. Myślę, że większość ludzi chce uruchamiać nagłówki i stopki oraz tabele, które pozwalają tylko na podziały stron między wierszami, z których żaden nie jest zaimplementowany w Webkit od 2015/11/13.
DoctorDestructo,
47

Uwaga: w przypadku korzystania z podziału strony: zawsze dla tagu utworzy podział strony po ostatnim kawałku tabeli, za każdym razem tworząc na końcu całkowicie pustą stronę! Aby to naprawić, po prostu zmień go na podział strony po: auto. Zepsuje się poprawnie i nie utworzy dodatkowej pustej strony.

<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.
źródło
Działa dla mnie w Chrome i jest ładnym, prostym rozwiązaniem CSS.
Ryan
1
Próbuję tego samego rozwiązania, ale nie psuje danych tabeli i nie usuwa dodatkowych danych zamiast wyświetlać je na następnej stronie. Jakieś domysły?
Null Pointer
24

Rozszerzenie z rozwiązania 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>

Wydaje się, że page-break-inside:avoidw niektórych przeglądarkach brane są pod uwagę tylko elementy bloku, a nie komórka, tabela, wiersz ani blok wstawiany.

Jeśli spróbujesz display:blockz TRtagiem i używać tam page-break-inside:avoid, to działa, ale mes wokół z układu tabeli.

Vicenteherrera
źródło
2
Oto prosty sposób na dynamiczne dodawanie div za pomocą jquery:$(document).ready(function(){$("table tbody th, table tbody td").wrapInner("<div></div>");});
Chris Bloom
1
Dzięki sinan ürün, vicenteherrera i Chrisbloom7. Zastosowałem kombinację twoich odpowiedzi i teraz działa!
Nurhak Kaya,
Możesz spróbować ustawić @media CSS tr { display: block; }na Tylko do drukowania, zamiast dodawać wszystkie dodatkowe <div>elementy. (Nie testowałem, ale warto na to spojrzeć)
Stephen R
11

Żadna z odpowiedzi tutaj nie działała dla mnie w Chrome. AAverin na GitHub stworzył w tym celu użyteczny skrypt Javascript i działało to dla mnie:

Po prostu dodaj js do swojego kodu i dodaj klasę „splitForPrint” do swojej tabeli, a on porządnie podzieli tabelę na wiele stron i doda nagłówek tabeli do każdej strony.

MDave
źródło
Czy masz próbkę, jak to zastosować? Próbowałem przypisać moją tabelę nazwa_klasy, ponieważ splitForPrintw JS nigdzie nie wziął odniesienia do elementu za pomocą nazwy klasy splitForPrint. Tylko część gdzie, var splitClassName = 'splitForPrint';ale to wszystko.
Compaq LE2202x
Głosowałem w dół, ponieważ skrypt, z którym się łączysz, nie rozwiązuje problemu OP bez znacznego wyboru i rekonfiguracji, i nie podałeś żadnych przykładów tego, jak można to zrobić.
Chris Bloom
Dla mnie działało to jak urok, żadne inne rozwiązanie nie działało. +1 Musiałem dodać trochę css, aby uzyskać prawidłowe przerwy .page-break {page-break-after: always; }
fhugas
Tak, dodając .page-break {page-break-after: always; } uratowało mi to dzień!
milodky
7

Użyj tych właściwości CSS:

page-break-after

page-break-before 

Na przykład:

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

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

przez

marcgg
źródło
Nie jestem pewien, musisz sprawdzić. Jeśli nie, podziel na różne tablice i rozdziel tablice pustym div
marcgg
Będziesz musiał zastosować go do wiersza tabeli, a nawet komórki, ale myślę, że nie do tabeli. Poza tym powinien działać.
Pekka
2
nie działa w chromie. Jest ignorowany, jakby 6/13/2012, gdy zostanie zastosowany do TR
ladieu
5

Niedawno rozwiązałem ten problem dobrym rozwiązaniem.

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();
}

Działa jak marzenie!

Wendel Tavares
źródło
2

Skończyło się na podejściu @ vicenteherrera, z pewnymi poprawkami (które są prawdopodobnie specyficzne dla bootstrap 3).

Gruntownie; nie możemy złamać trs, lub tds, ponieważ nie są elementami na poziomie bloku. Więc włączamy divs do każdego z nich i stosujemy nasze page-break-*zasady przeciwko div. Po drugie; dodajemy trochę dopełnienia na górze każdego z tych div, aby zrekompensować wszelkie artefakty związane ze stylizacją.

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

Korekty marginesów i dopełnienia były konieczne, aby zrównoważyć wprowadzany jitter (moim zdaniem - z bootstrap). Nie jestem pewien, czy przedstawiam jakieś nowe rozwiązanie z innych odpowiedzi na to pytanie, ale myślę, że to może komuś pomóc.

Aaron
źródło
1

Napotkałem ten sam problem i wszędzie szukałem rozwiązania, w końcu znalazłem coś, co działa dla mnie dla każdej przeglądarki.

html {
height: 0;
}

użyj tego css lub Zamiast css możesz mieć ten javascript

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

Mam nadzieję, że to również zadziała dla ciebie.

Sójka
źródło
0

Sprawdziłem wiele rozwiązań i nikt nie działał dobrze.

Więc wypróbowałem małą sztuczkę i to działa:

tfoot ze stylem: position: fixed; bottom: 0px; jest umieszczany na dole ostatniej strony, ale jeśli stopka jest zbyt wysoka, nakłada się na nią zawartość tabeli.

tfoot with only: display: table-footer-group; nie nakłada się, ale nie znajduje się na dole ostatniej strony ...

Połóżmy dwie stopy:

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>

Jedna rezerwuje miejsce na niekończących się stronach, druga umieszcza stopkę rozliczeniową.

Zenon K.
źródło
-1

Wypróbowałem wszystkie powyższe sugestie i znalazłem proste i działające rozwiązanie tego problemu dla różnych przeglądarek. To rozwiązanie nie wymaga stylów ani podziału strony. Dla rozwiązania format tabeli powinien wyglądać następująco:

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

Powyższy format został przetestowany i działa w różnych przeglądarkach

Ananth Doss
źródło
-2

Cóż, chłopaki ... Większość rozwiązań tutaj nie działała. Tak to dla mnie działało ...

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>

Pierwszy zestaw nagłówka jest używany jako fikcyjny, dzięki czemu podczas łamania strony nie będzie brakującej górnej ramki w drugiej głowie (tj. Oryginalnej).

Aneesh
źródło
-3

Akceptowana odpowiedź nie działała dla mnie we wszystkich przeglądarkach, ale następujące css działało dla mnie:

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

Struktura HTML była:

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

W moim przypadku wystąpiły dodatkowe problemy z thead tr , ale to rozwiązało pierwotny problem powstrzymywania wierszy tabeli przed zerwaniem.

Z powodu problemów z nagłówkiem ostatecznie udało mi się:

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

Nie zapobiegło to łamaniu się wierszy; tylko zawartość każdej komórki.

David Moeller
źródło