Add customizable letterhead headers and font formatting to all Excel and CSV exports in Frappe/ERPNext.
- ✅ Custom Letterhead: Add 2-3 rows of letterhead to every export
- ✅ Template Support: Use Jinja2 templates with dynamic variables
- ✅ Font Control: Control font name and size for entire export
- ✅ Auto Timestamp: Automatically add "Printed by" row with user, date, and time
- ✅ Smart Spacing: Automatically inserts a blank separator row before export data
- ✅ Works Everywhere: Applies to all Excel/CSV exports (reports, list views, data exports)
cd $PATH_TO_YOUR_BENCH
bench get-app https://github.com/lijsamuael/export_letterhead/bench --site {your_site_name} install-app export_letterheadbench restart- Log in to your Frappe/ERPNext instance
- Go to Search (press
/or click search icon) - Type:
Export Letterhead Settings - Click on Export Letterhead Settings
- Check the box "Enable Export Letterhead"
- This activates the letterhead functionality
In the "Letterhead Template" field, enter your template using Jinja2 syntax.
Template Rules:
- Each line = one row in the export
- Use
|(pipe) orTabto separate columns - Empty lines are ignored
- The app automatically inserts a blank separator row after the letterhead
Available Variables:
{{ company }}- Company name{{ doctype }}- Document type identifier or filename{{ report_name }}- Report title (e.g.,General Ledger) when available{{ user_fullname }}- Current user's full name{{ date }}- Current date (datetime.date){{ time }}- Current time (datetime.time){{ now }}- Current datetime (datetime.datetime){{ frappe }}- Frappe object for advanced scripting- Date/time objects support
strftime, e.g.,{{ date.strftime('%B %d, %Y') }}or{{ time.strftime('%I:%M %p') }}
Template Examples:
Example 1: Simple Header
{{ company }}
Export Report
Example 2: Multi-Column with Pipe
{{ company }} | {{ report_name or doctype }} | {{ date.strftime('%B %d, %Y') }}
Example 3: Multi-Column with Tab
{{ company }} {{ user_fullname }} {{ time.strftime('%I:%M %p') }}
Example 4: With Conditional Logic
{% if report_name %}
Report: {{ report_name }}
{% else %}
Export: {{ doctype }}
{% endif %}
Example 5: Complex Template
{{ company }}
{{ report_name or doctype }} Export
Generated on: {{ date.strftime('%B %d, %Y') }} at {{ time.strftime('%I:%M %p') }}
Exported by: {{ user_fullname }}
Font Name:
- Select from dropdown: Arial, Helvetica, Times New Roman, Courier New, Verdana, Calibri, Georgia, Comic Sans MS, Impact, Lucida Console
- Default: Arial
Font Size:
- Enter a number (1-409)
- Default: 11
- This applies to ALL rows in the export (letterhead + data)
- "Add 'Printed by' Row": Check/uncheck to enable/disable
- When enabled, automatically adds a row showing:
- Printed by: [User Name]
- Date: [Current Date]
- Time: [Current Time]
Click Save to apply your configuration.
Once configured, the letterhead will automatically appear on all Excel and CSV exports:
- Query Reports: Export any query report → Letterhead added
- List Views: Export any list view → Letterhead added
- Data Exports: Export any doctype data → Letterhead added
- Custom Reports: Any custom report export → Letterhead added
No additional steps required! Just export as you normally would.
Let's create a letterhead for Sales Invoice exports:
- Search:
Export Letterhead Settings - Open the document
- ✅ Check "Enable Export Letterhead"
Enter this in "Letterhead Template":
{{ company }}
Sales Invoice Export
Generated: {{ date }} at {{ time }}
- Font Name:
Calibri - Font Size:
12
- ✅ Check "Add 'Printed by' Row"
- Click Save
- Go to any Sales Invoice report
- Click Export → Excel
- Open the file
- You should see:
- Your company name
- "Sales Invoice Export"
- Generated date/time
- "Printed by: [Your Name]" with date and time
- All rows using Calibri 12pt font
{% if report_name %}
Report: {{ report_name }}
{% else %}
Export: {{ doctype }}
{% endif %}{{ company }}
Company Address: {{ frappe.db.get_value("Company", company, "address_line1") }}{% if report_name == "Sales Invoice" %}
Sales Invoice Report
{% elif report_name == "Purchase Invoice" %}
Purchase Invoice Report
{% else %}
{{ report_name or doctype }} Export
{% endif %}Use pipe (|) for aligned columns:
{{ company }} | Phone: {{ frappe.db.get_value("Company", company, "phone_no") }} | Email: {{ frappe.db.get_value("Company", company, "email") }}- Check if enabled: Verify "Enable Export Letterhead" is checked
- Check template: Ensure template field is not empty
- Clear cache:
bench clear-cache - Restart:
bench restart
- Check font name: Ensure font name is valid (use dropdown options)
- Check font size: Must be between 1-409
- Excel only: Font formatting only applies to Excel files, not CSV
- Check syntax: Ensure Jinja2 syntax is correct
- Check variables: Variables must be wrapped in
{{ }}or{% %} - Test simple: Try a simple template first:
{{ company }}
- Check setting: Verify "Add 'Printed by' Row" is enabled
- Check template: Template must be enabled and not empty
Report: {{ report_name if report_name else doctype }}
{% if report_name %}
Report Type: Query Report
{% else %}
Report Type: List View
{% endif %}Date: {{ date.strftime('%B %d, %Y') if date else '' }}
Time: {{ time.strftime('%I:%M %p') if time else '' }}User: {{ user_fullname }}
Email: {{ frappe.db.get_value("User", frappe.session.user, "email") }}This app uses pre-commit for code formatting and linting. Please install pre-commit and enable it for this repository:
cd apps/export_letterhead
pre-commit installPre-commit is configured to use the following tools:
- ruff
- eslint
- prettier
- pyupgrade
MIT
For issues, questions, or contributions, please visit the GitHub repository.
Made with ❤️ for the Frappe/ERPNext community