ERPNext Version: v15.46.2 (version-15)
Frappe Framework Version: v15.50.1 (version-15)
Issue:
I created a Custom Print Format for Sales Order and added a Letterhead.
However, I am facing an issue with the items table:
- When an item has a very long description, the row breaks badly across pages.
- Sometimes text is hidden or overlaps awkwardly between pages.
- The row structure is not preserved when page breaks happen.
- Even though the page breaks, the lines for the table rows do not continue correctly.
I have attached a sample PDF output showing the issue.
What I have already tried:
- Adding
page-break-inside: avoid;
on<tr>
and<td>
. - Setting
white-space: normal; word-break: break-word;
for description columns. - Playing with
table-layout: fixed
and width styles. - Using Frappe’s standard print format classes like
.print-format
and.print-heading
. - Adjusting the Letterhead margins and page sizes.
Still, the issue persists.
Screenshots
My Setup:
- Custom Print Format (HTML Based)
- Standard Letterhead (HTML Based)
Help Needed:
- How can i add some space around header and footer?
- How can I ensure table rows do not break badly across pages?
- How can I preserve the table structure even if descriptions are long?
- Should I adjust styles differently or is there a best practice for long text in tables in ERPNext v15?
- Is there any known fix or recommended CSS for custom print formats with long tables and letterheads?
Custom Print Format code
{%- macro add_header(page_num, max_pages, doc, letter_head, no_letterhead, footer, print_settings=None, print_heading_template=None) -%}
{% if letter_head and not no_letterhead %}
<div class="letter-head">{{ letter_head }}</div>
{% endif %}
{% if print_heading_template %}
{{ frappe.render_template(print_heading_template, {"doc":doc}) }}
{% else %}
{% endif %}
{%- if doc.meta.is_submittable and doc.docstatus==2-%}
<div class="text-center" document-status="cancelled">
<h4 style="margin: 0px;">{{ _("CANCELLED") }}</h4>
</div>
{%- endif -%}
{%- endmacro -%}
{% for page in layout %}
<div class="page-break">
<div {% if print_settings.repeat_header_footer and loop.index == 0 %} id="header-html" class="hidden-pdf" {% endif %}>
{{ add_header(loop.index, layout|len, doc, letter_head, no_letterhead, footer, print_settings) }}
</div>
<!-- Footer Start-->
{% if print_settings %}
<div id="footer-html" class="visible-pdf">
{% if not no_letterhead and footer %}
<div class="letter-head-footer">
{{ footer }}
</div>
{% endif %}
<p class="text-center small page-number visible-pdf">
{{ _("Page {0} of {1}").format('<span class="page"></span>', '<span class="topage"></span>') }}
</p>
</div>
{% endif %}
<!-- Footer End -->
<div class="section-break">
<!-- Document Title -->
<h2 class="document-title text-center">{{ doc.doctype|upper }}</h2>
<!-- Document Information -->
<table style="width: 100%; font-size: 10pt; margin-top: 10px;">
<tr class="table-row">
<td style="width: 33%; vertical-align: top;">
<strong>Customer:</strong><br>
{{ doc.customer_name or doc.party_name }}<br>
</td>
<td style="width: 33%; vertical-align: top;">
<strong>Shipping Address:</strong><br>
</td>
<td style="width: 33%; vertical-align: top;">
<strong>Order No:</strong> {{ doc.name }}<br>
</td>
</tr>
</table>
<!-- CUSTOMER NOTE -->
<div style="margin-top: 10px; font-size: 10pt;">
<p>Dear {{ doc.customer_name if doc.doctype != 'Quotation' else doc.party_name }},<br>
Thank you for your interest in our order.</p>
</div>
<div class="section-break">
<!-- ITEM TABLE -->
<table style="width: 100%; font-size: 10pt; border-collapse: collapse; margin-top: 30px;">
<thead>
<tr style="background-color: #f5f5f5;">
<th style="padding: 6px; border: 1px solid #ccc;">#</th>
<th style="padding: 6px; border: 1px solid #ccc;">Item Code</th>
<th style="padding: 6px; border: 1px solid #ccc;">Qty</th>
<th style="padding: 6px; border: 1px solid #ccc;">UOM</th>
<th style="padding: 6px; border: 1px solid #ccc;">Rate</th>
<th style="padding: 6px; border: 1px solid #ccc;">Amount</th>
</tr>
</thead>
<tbody>
{% for item in doc.items %}
<tr {% if loop.index == 1 %}style="page-break-inside: avoid;"{% endif %}>
<td style="padding: 6px; border: 1px solid #ccc;">{{ loop.index }}</td>
<td style="padding: 6px; border: 1px solid #ccc;">
<div>{{ item.item_code }}</div>
<div style="font-size: 9pt; color: #555; white-space: pre-wrap; word-break: break-word;">
{{ item.description or '' }}
</div>
</td>
<td style="padding: 6px; border: 1px solid #ccc; text-align: right;">{{ item.qty }}</td>
<td style="padding: 6px; border: 1px solid #ccc;">{{ item.uom }}</td>
<td style="padding: 6px; border: 1px solid #ccc; text-align: right;">{{ item.rate }}</td>
<td style="padding: 6px; border: 1px solid #ccc; text-align: right;">{{ item.amount }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endfor %}
Custom Letter Head
// Header
<div style="width: 100%; font-size: 10pt; padding-bottom: 5px;">
<table style="width: 100%;">
<tbody><tr>
<td style="width: 60%; vertical-align: top;">
<strong>Company Name</strong><br>
Near, NY Tower<br>
Bldg 42<br>
37392 Milan<br>
Italy
</td>
<td style="width: 40%; text-align: right;">
<img src="http://site-name.com:8013/files/sample-logo.jpg" alt="Test Company" style="max-height: 60px;"><br>
<span style="font-size: 9pt;">Technology for Behaviour Analysis</span>
</td>
</tr>
</tbody></table>
<hr style="margin: 5px 0;">
</div>
// Footer
<div style="width: 100%; font-size: 8pt; margin-top: 10px;">
<table style="width: 100%;">
<tbody><tr>
<td style="width: 25%; vertical-align: top;">
<strong>Company Name</strong><br>
Near, NY Tower<br>
Bldg 42<br>
37392 Milan<br>
Italy
</td>
<td style="width: 25%; vertical-align: top;">
<strong>Phone:</strong> +82 7282927287<br>
</td>
<td style="width: 25%; vertical-align: top;">
<strong>Bank:</strong> US BANK<br>
<strong>Bank Code:</strong> 839 8398 838<br>
<strong>Account:</strong> 89272 83982 723<br>
<strong>IBAN:</strong> IT012 7389 927 839 8382 82<br>
<strong>SWIFT:</strong> BELADEBE
</td>
</tr>
</tbody></table>
</div>
Thank you in advance!
Really appreciate any suggestions or working examples if anyone have!