HTML Jinja print help - ashish-greycube/help GitHub Wiki

get current url

{{frappe.get_url()}}

loop index

{{loop.index}}

convert negative value to positive

{{doc.total_advance|abs}}

for get length

{{ products | length }} <br>
{% if products | length > 1 %}

set precision 3 to float

{{ " %.3f " | format(sof.vessel_stay_hours) }}

calculating sum

{{doc.items|sum(attribute='discount_percentage')}}

sum of multiplication in child table

{% set td = namespace(total_discount=0) %}  
{% for item in doc.items %}
{% set td.total_discount = td.total_discount+(item.qty * item.discount_amount) %}
{% endfor %}
{{td.total_discount}}

note: sum element must be int or float

format date

{{ frappe.utils.get_datetime(doc.transaction_date).strftime('%d %b %Y') }} <br>

https://support.sendwithus.com/jinja/jinja_time/#datetime-format

calculate day difference between 2 dates

{% set days = frappe.utils.time_diff_in_seconds(doc.schedule_date,doc.transaction_date) %} <br>
                {% set delivery = days / (3600 * 24) %} <br>
		{{ ' %0.0f ' % delivery | float }}  

get currency symbol of currency field of doc

{{ frappe.utils.fmt_money(doc.ctc, currency=doc.salary_currency )}}
get company default currency
{{ frappe.format(doc.ctc, {'fieldtype': 'Currency'}) }}

to convert amount into words

{{ frappe.utils.money_in_words(doc.ctc, cur) }})

replacing values from string

{{ doc.address_display|replace('<br>', ' ') }} <br>
{{ dec|replace('<div class=\"ql-editor read-mode\">', '')|replace('<div>', '')|replace('</div>', '')|replace('<p>', '')|replace('</p>', '') }} 

append data into list

{% set hsn_code = [] %} <br>
		{% if items | length > 0 %} <br>
		{% for item in items %} <br>
		 {{ hsn_code.append(item.gst_hsn_code) or '' }} <br>
		{% endfor %}  <br>	
        {% endif %}

make unique list

{% set unique_code = hsn_code|unique|list %}

join in list

{% set dec = description |join(', ') %}

split string

{% set a = (doc.custom_cargo_sub_type_of_invoice).split("-") %} 

for add suffixes in date

{% set suffixes = [ "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th", 
       "th", "th", "th", "th", "th", "th", "th", "th", "th", "th",
       "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th",
       "th", "st" ] %} <br>
       
{% set d = frappe.utils.get_datetime(doc.date_of_joining).strftime('%d') | int %} <br>
{{frappe.utils.get_datetime(doc.date_of_joining).strftime('%d{} %b %Y').format(suffixes[d])}} <br>

set global variable

  {% set ns = namespace(all_custom_hsn='') %} <br>      
{% for item in doc.items %} <br>
 {% if item.custom_hsn %} <br>
  {% set ns.all_custom_hsn = ns.all_custom_hsn+item.custom_hsn %} <br>
  {% if loop.last %} <br>
   {% else %} <br>
    {% set ns.all_custom_hsn = ns.all_custom_hsn+',' %} <br>
   {% endif %} <br>
 {% endif %} <br>
{% endfor %} <br>
{{ns.all_custom_hsn}}

use python function in jinja

.py file
def get_vessel_grade_details(vessel_name):
    grade_list=frappe.db.get_all('Vessel Details', filters={'parent': vessel_name},fields=['grade'])
    print('grade_list',grade_list)
    if grade_list:
        return ', '.join( ele.grade for ele in grade_list)
    else:
        return ''
in hooks.py file
jinja = {
    "methods": [
        "kict.api.get_vessel_grade_details"]
}
jinja
{{get_vessel_grade_details(doc.vessel_name)}}

HTML for Print Format

Override Print Format Margin (or Any Style)

.print-format {
    margin-bottom: -4px !important;
    margin-top: 100px !important;
}

set width of column

<table class="table table-bordered" style="table-layout: fixed;">
    <thead>
        <tr>
            <th style="width: 5%">Sr</th>
            <th style="width: 25%">Fieldname</th>
            <th style="width: 20%">Type</th>
            <th style="width: 25%">Label</th>
            <th style="width: 25%">Options</th>
        </tr>
    </thead>
    <tbody>
        
        <tr >
            <td>1</td>
            <td class="danger" title="Mandatory"><code>description</code></td>
            <td >
                Text Editor</td>
            <td >
                Description
                
            </td>
            <td></td>
        </tr>
        
    </tbody>
</table>
##### css .table
.table td{
    border-top: 1px solid #000 !important;
}

.print-format td {
        padding: 3px !important;
}

Repeat Table Header

use <thead> to repeat header

<table class="table table-condensed table-hover table-bordered" style="border:1px solid black">
     <thead>
         <tr>
            <th colspan=2><b>Repeat</b></th>
            <th colspan=2><b>Header</b></th>
         </tr>
     </thead>
     <tbody>
         <tr>
            <th>{{_("Item")}} </th>
            <th>{{_("Qty")}}</th>
            <th>{{_("Rate")}}</th>
            <th>{{_("Amount")}} </th>
         </tr>
         
         {% for item in doc.items %}
         <tr>
             <td>{{item.item_code}}</td>
             <td>{{item.qty}}</td>
             <td>{{item.rate}}</td>
             <td>{{item.amount}}</td>
         </tr>
         {% endfor %}
     </tbody>
</table>

.css to avoid page break in row

thead { display: table-header-group } 
tr { page-break-inside: avoid }

Page Break

<div class="page-break"></div>

List nested ordering

.html

<ol style="counter-reset: item">
  <li class="nested_list">Item</li>
  <li class="nested_list">Thing</li>
  <li class="nested_list">Other</li>
  <li class="nested_list">Four
    <ol>
      <li class="nested_list">Foo</li>
      <li class="nested_list">Bar</li>
      <li class="nested_list">Of</li>
      <li class="nested_list">Course</li>
    </ol>
  <li class="nested_list">Else</li>
</ol>

.css

OL { counter-reset: item }
.nested_list { display: block }
.nested_list:before { content: counters(item, ".") " "; counter-increment: item }

image

In Email Template add border in table

set border style in tr, td, th tag

style="border: 1px solid #000;"

For field data type- Text Editor

<div class="ql-snow">{{doc.terms}}</div>

In pdf, table data cuts across page

solution: use

<table class="ql-snow">

Before:


After:


How to generate QR code in Print Format

{% if not doc.irn %}

	<div class="text-center no-preview-available">
		Please generate an e-Invoice to preview it.
	</div>

{% else %}

	{% set e_invoice_log = frappe.db.get_value(
		"e-Invoice Log", doc.irn, ("invoice_data", "signed_qr_code"), as_dict=True
	) %}

	{% if not e_invoice_log %}

		<div class="text-center no-preview-available">
			The e-Invoice Log linked to this Sales Invoice could not be found.
		</div>

	{% else %}

		{% if not e_invoice_log.invoice_data %}

		<div class="text-center no-preview-available">
			Invoice Data is not available in the e-Invoice Log linked to this invoice.
		</div>

		{% else %}

		{%- set invoice_data = _dict(json.loads(e_invoice_log.invoice_data)) -%}

		<div class="row section-break info-section">
			<div class="col-xs-8 column-break">
				{%
					set transaction_details = {
						"IRN": invoice_data.Irn,
						"Ack. No.": invoice_data.AckNo,
						"Ack. Date": frappe.utils.format_datetime(
							invoice_data.AckDt, "dd/MM/yyyy hh:mm:ss"
						),
					}
				%}
				{% for key, value in transaction_details.items() %}
			{% if value %}
				<div class="row data-field">
					<div class="col-xs-4"><label>{{ key }}</label></div>
					<div class="col-xs-8 value">{{ value }}</div>
				</div>
			{% endif %}
		{% endfor %}
			</div>
			<div class="col-xs-4 column-break text-right">
				{{ web_block('e-Invoice QR', values={'e_invoice_qr_text': e_invoice_log.signed_qr_code }) }}	
			</div>
		</div>
		{% endif %}
	{% endif %}
{% endif %}

Set Writing Mode vertical using CSS

Type - 1

<td style="writing-mode: vertical-lr;" rowspan="6">1 Employee Data</td>

image

Type - 2

<td style="text-align: center; writing-mode: vertical-lr; text-orientation: upright;">NEFT/RTGS</td>

image

Set Watermark in Print Format

HTML

<div class="watermark">
   <img src="/files/vb_logo.png" />
</div>

CSS

.watermark {
    position: fixed;
    top: 50%;
    left: 50%;
    font-size: 100px;
    color: rgba(0, 0, 0, 0.3); 
    transform: translate(-50%, -50%);
    z-index: 1;
    pointer-events: none; 
    opacity:0.2;
  }

  @media print {
    .watermark {
      position: fixed;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      z-index: 1;
      opacity:0.2;
    }
  }

Set Page Size in Print Format PDF

HTML

<head>
    <meta name="pdfkit-page-width" content="8.5in"/>
    <meta name="pdfkit-page-height" content="14in"/>
</head>	

Put this code inside your HTML Code and, Change above values(i.e content) according to required page size

Click Here for Different Page size Width and Height Values

Print Format Hacks to use Python Funtions

{# Print format - get data not in doc #}

{# can use frappe usual api - get_doc, get_list etc. #}
{% set user_json = frappe.get_doc("User", "Administrator") %}


{# get data from whitelisted method in a controller #}
{% set so_custom_api_data = frappe.call("amazon_sp_erpnext.amazon_sp_erpnext.report.html_sample.html_sample.get_data")%}

{# get data from existing reports. Note: report_result has columns, result etc #}
{% set report_result = frappe.call('frappe.desk.query_report.run', report_name="item_test") %}

{# get data from query. Works but Not recommended! instead create a py method in controller and call the method here #}
{% set so_data = frappe.db.sql("select name, customer from `tabSales Order` tso limit 3 ", as_dict=True) %}



<h2>{{user_json.username}}</h2>

<hr>

{{
    so_custom_api_data | json
}}


<hr>


<ul>
{% for d in so_data %}
    <li>
        {{d | json}}
    </li>
{% endfor %}
</ul>

Set Footer At Bottom

.footer-wrapper {
    position: fixed;
    bottom: 0%;
    left:0%;
    right:0%;
    z-index:-1;
}

@media print {
    .footer-wrapper {
      position: fixed;
      bottom: 0%;
      left:0%;
      right:0%;
      z-index:-1;
    }
}
⚠️ **GitHub.com Fallback** ⚠️