Salman Arshad
Salman Arshad

Reputation: 272316

Print a very wide HTML table without clipping right hand side

I have a table with several columns.

THE SPECIFIC PROBLEM

When you print such table, the columns on right will not print, not even when you print in landscape orientation.

THE DESIRED BEHAVIOR

The browser should print entire table, use multiple sheets if necessary. CSS/JavaScript solutions are acceptable.

SHORTEST CODE NECESSARY TO REPRODUCE THE PROBLEM

Click the print button in the following demo. Look at the right hand side of page in print preview window.

$(function() {
  $("input:first").click(function() {
    window.print();
  });
  $(".description").each(function() {
    var text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla placerat malesuada sodales. Nulla convallis neque lorem, ac varius enim. Ut dapibus, orci at feugiat eleifend, dui mi lobortis tortor, ac egestas neque enim et neque. Donec tempus mi quis tellus dapibus eu blandit magna sagittis. Curabitur ac ultrices tortor. Aliquam id tincidunt urna. Nunc id neque ac urna congue convallis. Etiam eget massa vitae justo aliquam pulvinar vitae ut diam.";
    text = text.substr(0, Math.ceil(Math.random() * 100));
    $(this).text(text);
  });
  $(".number").each(function() {
    var text = (Math.random() * 1000).toFixed(2);
    $(this).text(text);
  });
});
@media screen {
  input {
    width: 100%;
    margin: 1em 0;
  }
}
@media print {
  input {
    display: none;
  }
}
th {
  font: bold 12px sans-serif;
  border: 1px solid;
  white-space: nowrap;
}
td {
  font: 12px sans-serif;
  border: 1px dotted;
}
td.description {
  min-width: 200px;
  border-style: solid;
}
td.number {
  padding-left: 20px;
  text-align: right;
  border-style: solid;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<input type="button" value="Print">

<table>
  <tr>
    <td></td>
    <td></td>
    <th colspan="12">2009</th>
    <th colspan="12">2010</th>
    <td></td>
  </tr>
  <tr>
    <td></td>
    <th>Description</th>
    <th>Jan</th>
    <th>Feb</th>
    <th>Mar</th>
    <th>Apr</th>
    <th>May</th>
    <th>Jun</th>
    <th>Jul</th>
    <th>Aug</th>
    <th>Sep</th>
    <th>Oct</th>
    <th>Nov</th>
    <th>Dec</th>
    <th>Jan</th>
    <th>Feb</th>
    <th>Mar</th>
    <th>Apr</th>
    <th>May</th>
    <th>Jun</th>
    <th>Jul</th>
    <th>Aug</th>
    <th>Sep</th>
    <th>Oct</th>
    <th>Nov</th>
    <th>Dec</th>
    <th>Total</th>
  </tr>
  <tr>
    <th rowspan="2">Batch number 1</th>
    <td rowspan="2" class="description"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
  </tr>
  <tr>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
  </tr>
  <tr>
    <th rowspan="4">Batch number 2</th>
    <td rowspan="4" class="description"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
  </tr>
  <tr>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
  </tr>
  <tr>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
  </tr>
  <tr>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
  </tr>
  <tr>
    <th rowspan="4">Batch number 3</th>
    <td rowspan="4" class="description"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
  </tr>
  <tr>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
  </tr>
  <tr>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
  </tr>
  <tr>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
  </tr>
  <tr>
    <th rowspan="2">Batch number 4</th>
    <td rowspan="2" class="description"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
  </tr>
  <tr>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
  </tr>
  <tr>
    <th>Total</th>
    <td class="description"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
    <td class="number"></td>
  </tr>
</table>

Upvotes: 26

Views: 27296

Answers (4)

Salman Arshad
Salman Arshad

Reputation: 272316

Here is my go at this:

What I did was:

  • Create a fixed width div that fits nicely on an A4 size page
  • Copied the table inside that div
  • Scroll the table x pixels to bring the desired portion in "focus" using CSS positioning
  • Repeat this process y times

Example: if the table is 2000px wide and page width is set to 600px then y should be 4 and x will be 0, 600, 1200 and 1800.

Upvotes: 23

Astra Bear
Astra Bear

Reputation: 2738

The answer provided by @(Salman A) worked well for me on Chrome and Firefox. I modified it to break at column boundaries with the following:

var acSplitTable = function() {
    var table = $(".ac-print .ac-grid>table"),
        tableWidth = table.outerWidth(),
        pageWidth = 600,
        pageCount = Math.ceil(tableWidth / pageWidth),
        printWrap = $("<div></div>").insertAfter(table),
        i,
        printPage;

    $(".ac-print .ac-grid>table .ac-hidden").remove();

    var positions = [];
    var lastOuterWidth = 0;
    $(".ac-print .ac-grid>table th").each(function() {
        positions.push($(this).position().left);
        lastOuterWidth = $(this).outerWidth;
    });

    var pageWidths = [];
    var endColumns = [];

    var lastPosition = 0;
    for (i = 1; i < positions.length; i++) {
        if ((positions[i] - lastPosition) > pageWidth) {
            pageWidths.push(positions[i - 1] - lastPosition);
            lastPosition = positions[i - 1];
            endColumns.push(i - 1);
        }
        if (i == (positions.length - 1)) {
            pageWidths.push(positions[i] + lastOuterWidth - lastPosition);
            lastPosition = positions[i];
            endColumns.push(i);
        }
    }
    pageCount = pageWidths.length;

    var lastEndColumn = 0;
    for (i = 0; i < pageCount; i++) {
        var thisPageWidth = pageWidth; //pageWidths[i];
        var styleString = "overflow: hidden; width:" + thisPageWidth + "px; page-break-before: " + (i === 0 ? "auto" : "always") + ";";
        var newTable = table.clone().attr("id", "ac-print-page-" + i);
        newTable.attr("style", styleString);
        newTable.appendTo("#formpoint");

        //remove columns either side of our page
        for (var j = positions.length - 1; j >= 0; j--) {
            if (j > endColumns[i] || j <= lastEndColumn) {
                var index = j + 1;
                var heading = $(newTable).find("tr th:nth-child(" + index + ")");
                $(newTable).find("tr th:nth-child(" + index + ")").remove();
                $(newTable).find("tr td:nth-child(" + index + ")").remove();
            }
        }

        lastEndColumn = endColumns[i];
    }

    table.hide();
    $(this).prop("disabled", true);

    window.print();
    setTimeout(window.close, 0);

};

Upvotes: 5

OlliM
OlliM

Reputation: 7113

See this question: Print Stylesheets for pages with long horizontal tables

The point is that you can't get a browser to print horizontal tables the same way as excel does. You have to switch to something that is at most one page wide.

Upvotes: 0

Kalpesh Patel
Kalpesh Patel

Reputation: 2822

use

@media print{@page {size: landscape}}

Upvotes: 3

Related Questions