Hi everyone, I want to ask you something to see if...
# advancedpdf
a
Hi everyone, I want to ask you something to see if you can help me. I am editing a NetSuite advance pdf template, but I can't seem to split the table into two or more pages based on the height of one of the columns. Have you done this before? Do you know how I could achieve it? In other words, if the value of the item in that column is larger than the page size, move to the next page with the table header and continue writing the subsequent items. thanks!!
e
Sounds like you just want to avoid page breaks inside the table? That can be done with inline css. https://stackoverflow.com/questions/38721956/freemarker-page-break
s
@Alexander Cuadros it's an issue I've encountered across numerous times, particularly with really long descriptions on manufactured items. The secret is splitting the item and/or description field by the line return. Here is an example:
Copy code
<#if item.description?contains("<br />")>

          <tr>
            <td align="center" colspan="3" line-height="150%">${item.quantity}</td>
            <td colspan="15"><span class="itemname">${item.item}</span></td>
            <td align="right" colspan="4">${item.rate}</td>
            <td align="right" colspan="4">${item.amount}</td>
          </tr>
          <#assign desclines = item.description?split("<br />") />
          <#list desclines as description>
            <tr>
              <td style="padding:1px 2px" align="center" colspan="3"> </td>
              <td style="padding:1px 2px" colspan="15">${description}</td>
              <td style="padding:1px 2px" align="right" colspan="4"></td>
              <td style="padding:1px 2px" align="right" colspan="4"></td>
            </tr>
            </#list>
          <#else>

            <tr>
              <td align="center" colspan="3" line-height="150%">${item.quantity}</td>
              <td colspan="15"><span class="itemname">${item.item}</span><br />${item.description}</td>
              <td align="right" colspan="4">${item.rate}</td>
              <td align="right" colspan="4">${item.amount}</td>
            </tr>
            </#if>
You need to create a new main table row for each description line. Depending on your formatting you may need some added logic to format only the first/last line (if you have top/bottom borders per item etc...) In the example above, the items are shown with the SKU on the first line, then the description on line 2+
Here is the whole "item" table for your reference:
Copy code
<table style="width: 100%; margin-top: 5px;">
      <!-- start items -->
      <#list record.item as item>

        <#if item_index==0>
          <thead>
            <tr>
              <th align="center" colspan="3" style="padding: 5px 5px;">${item.quantity@label}</th>
              <th colspan="15" style="padding: 5px px;">${item.item@label}</th>
              <th align="right" colspan="4" style="padding: 5px 5px;">${item.rate@label}</th>
              <th align="right" colspan="4" style="padding: 5px 5px;">${item.amount@label}</th>
            </tr>
          </thead>
          </#if>
        <#if item.description?contains("<br />")>

          <tr>
            <td align="center" colspan="3" line-height="150%">${item.quantity}</td>
            <td colspan="15"><span class="itemname">${item.item}</span></td>
            <td align="right" colspan="4">${item.rate}</td>
            <td align="right" colspan="4">${item.amount}</td>
          </tr>
          <#assign desclines = item.description?split("<br />") />
          <#list desclines as description>
            <tr>
              <td style="padding:1px 2px" align="center" colspan="3"> </td>
              <td style="padding:1px 2px" colspan="15">${description}</td>
              <td style="padding:1px 2px" align="right" colspan="4"></td>
              <td style="padding:1px 2px" align="right" colspan="4"></td>
            </tr>
            </#list>

          <#else>

            <tr>
              <td align="center" colspan="3" line-height="150%">${item.quantity}</td>
              <td colspan="15"><span class="itemname">${item.item}</span><br />${item.description}</td>
              <td align="right" colspan="4">${item.rate}</td>
              <td align="right" colspan="4">${item.amount}</td>
            </tr>

            </#if>

          </#list>
        <!-- end items -->
        </table>
s
BFO has page-break-before, page-break-after, and page-break-inside attributes, one of which might achieve the desired result: https://bfo.com/products/report/docs/tags/atts/page-break-inside.html
s
To my knowledge, a table "cell" cannot have a page-break inside it.
s
yeah the tricky part is that the Freemarker code/template is totally unaware of where the page breaks will occur because the data inserted is dynamic, so there really no way it can know in advance. So unless it’s possible to leverage BFO features directly (BFO creates the page boundaries, not FReemarker), I don’t think there is a way to pre-compute where a large item will cross a page boundary and split it. Remember that advanced PDF’s can print as both an HTML page and a PDF, and the HTML page has no page breaks in it. It’s strictly a BFO/PDF thing
s
Hence why I split the value that has potentially a large text area and render it per row. Now if someone pastes something that is huge with no line return(s), the same issue can occur. Users gonna do what users gonna do!