Odoo Development

Custom Paper Format in Odoo QWeb Reports

How to create, configure, and bind custom paper formats to Odoo QWeb reports — covering UI setup, XML override, margin control, and header/footer sizing.

iWesabe Editorial TeamJuly 9, 20238 min read

Odoo's QWeb engine renders PDF reports using a paper format that controls page size, orientation, margins, and the space reserved for headers and footers. The default paper format (A4 portrait) suits most standard documents — invoices, purchase orders, delivery slips. When a business needs a custom document size, a landscape layout, or specific margin widths for pre-printed stationery, a custom paper format is required.

This guide covers three approaches: configuring a paper format through the Odoo UI, binding it to a report action in XML, and overriding it directly in a QWeb report template. All three approaches are compatible and can be combined.

What Is a Paper Format in Odoo?

A paper format in Odoo is a record in the `ir.paper.format` model that defines the physical and layout properties of a printed PDF page. Every `ir.actions.report` (report action) has a `paper_format_id` field — when that field is empty, the report falls back to the company default format.

ir.paper.format — Key Fields
Field nameTypeDescriptionCommon values
nameCharDisplay name shown in the UI and report action dropdown"A4 Custom", "Invoice Landscape"
defaultBooleanIf True, this format is the company default for all reports without an explicit paper_format_idTrue / False
formatSelectionNamed standard size — used when custom dimensions are not setA4, A3, Letter, Legal
orientationSelectionPortrait or Landscape page rotationPortrait / Landscape
margin_top / margin_bottom / margin_left / margin_rightFloatPage margins in mm. These values pass directly to wkhtmltopdf10.0, 15.0, 20.0
header_lineBooleanDraw a horizontal rule below the header areaTrue / False
header_spacingIntegerVertical space (in mm) between the top of the page and the start of body content. Must be ≥ the height of your QWeb header template.30, 40, 60
page_width / page_heightFloatCustom page dimensions in mm. When set, these override the `format` field.210.0 / 297.0 for A4

Create a Custom Paper Format via the Odoo UI

  1. Navigate to Settings → Technical → Reporting → Paper Formats.
  2. Click New.
  3. Set Name to a descriptive identifier (e.g. "Invoice A4 Narrow Margin").
  4. Choose Format (A4, A3, Letter, Legal) or leave it blank if you will set custom dimensions via Page Width / Page Height.
  5. Set Orientation to Portrait or Landscape.
  6. Set the four margin fields (Top, Bottom, Left, Right) in mm. A safe starting point for invoices is 10 / 10 / 10 / 10.
  7. Set Header Spacing in mm. This controls the gap between the page top edge and where body content begins. Start with the height of your header in mm and add 5–10 mm buffer.
  8. Save the record. The paper format is now available in the Paper Format dropdown of any report action.

Bind a Paper Format to a Report Action in XML

For custom modules, define both the paper format record and the report action binding in XML data files. This approach is repeatable, version-controlled, and installs correctly on any Odoo instance.

Step 1 — Define the paper format record

xml
<!-- data/paper_format_data.xml -->
<odoo>
  <record id="paperformat_invoice_custom" model="ir.paper.format">
    <field name="name">Invoice A4 Narrow Margin</field>
    <field name="default" eval="False"/>
    <field name="format">A4</field>
    <field name="orientation">Portrait</field>
    <field name="margin_top">10.0</field>
    <field name="margin_bottom">10.0</field>
    <field name="margin_left">10.0</field>
    <field name="margin_right">10.0</field>
    <field name="header_line" eval="False"/>
    <field name="header_spacing">40</field>
  </record>
</odoo>

Step 2 — Bind the paper format to the report action

xml
<!-- report/account_invoice_report.xml -->
<odoo>
  <!-- Define the report action and reference the paper format -->
  <report
    id="account_invoices_custom"
    model="account.move"
    string="Custom Invoice"
    report_type="qweb-pdf"
    name="your_module.report_invoice_custom_document"
    file="your_module.report_invoice_custom_document"
    paper_format="your_module.paperformat_invoice_custom"
    print_report_name="(object.name or 'Invoice')"
  />
</odoo>

QWeb Report Template — Header, Footer, and Body Layout

The paper format controls the available print area. The QWeb report template controls what renders within that area. The three parts — header, footer, and body — are defined using specific `t-call` inheritance points in Odoo's base report layout.

xml
<!-- report/report_invoice_custom_document.xml -->
<odoo>
  <!-- Outer wrapper must inherit web.html_container -->
  <template id="report_invoice_custom_document">
    <t t-call="web.html_container">
      <t t-foreach="docs" t-as="doc">
        <t t-call="web.external_layout">
          <t t-set="doc" t-value="doc.with_context(lang=doc.partner_id.lang)"/>

          <!-- Body content goes here -->
          <div class="page">
            <h2 t-field="doc.name"/>
            <p t-field="doc.invoice_date"/>
            <!-- ... your report body ... -->
          </div>

        </t>
      </t>
    </t>
  </template>
</odoo>

Odoo renders headers and footers via `web.external_layout_header` and `web.external_layout_footer`. To replace them for a specific report, inherit these templates and restrict the override with `t-if` on the `report_name` variable.

xml
<!-- Custom header for a specific report only -->
<template id="report_invoice_custom_header"
          inherit_id="web.external_layout_header">
  <xpath expr="//div[hasclass('header')]" position="replace">
    <!-- Only override for our custom report -->
    <t t-if="report_name == 'your_module.report_invoice_custom_document'">
      <div class="header" style="height: 35mm;">
        <!-- Your custom header HTML here -->
        <img t-att-src="'/web/image/res.company/%s/logo' % company.id"
             style="max-height: 30mm;"/>
        <div class="text-right">
          <strong t-field="company.name"/>
        </div>
      </div>
    </t>
    <t t-else="">
      <!-- Fall back to default header for all other reports -->
      <t t-call="web.external_layout_standard_header"/>
    </t>
  </xpath>
</template>

Common Paper Format Issues and Fixes

QWeb Paper Format Troubleshooting
SymptomRoot causeFix
Header overlaps body content on every pageheader_spacing is smaller than the rendered height of the header HTMLIncrease header_spacing on the paper format. Measure your header height in a browser at 96 DPI (1 mm ≈ 3.78 px), then add 5–10 mm buffer.
PDF is A4 even though a custom page_width / page_height was setThe `format` field on ir.paper.format is still set to "A4", which overrides the custom dimensions in some wkhtmltopdf versionsClear the `format` field (set it to a blank / custom option) when using page_width / page_height. Both fields cannot be active simultaneously.
Report ignores the paper format set on the report actionA company-level default paper format is set to `default = True` and is overriding the action-level formatEither unset `default` on the company paper format, or explicitly set `paper_format_id` on the report action rather than relying on the default.
Right margin is ignored; content bleeds off the pageHardcoded width styles in the QWeb template (e.g. `width: 210mm`) do not account for marginsUse percentage widths or `max-width: 100%` in your QWeb CSS instead of absolute mm widths. Let the paper format margins define the print area.
Footer content is cut off at the bottom of the pagemargin_bottom is too small for the footer HTML heightIncrease margin_bottom on the paper format. The footer renders within the bottom margin area — if the footer HTML is taller than margin_bottom, it gets clipped.

Version Notes and Spot-Check Guide

Paper Format Behaviour by Odoo Version
Odoo versionPDF engineUI pathNotable change
Odoo 16 / 17wkhtmltopdf (primary)Settings → Technical → Reporting → Paper FormatsHeadless Chrome added as optional engine for some reports; QWeb paper format API unchanged
Odoo 18wkhtmltopdf (primary)Settings → Technical → Reporting → Paper FormatsNo API changes to ir.paper.format. Header/footer template inheritance unchanged.
Odoo 19wkhtmltopdf (primary)Settings → Technical → Reporting → Paper FormatsNo API changes to ir.paper.format. Verified June 2026.
Odoo 20 (expected late 2026)TBC — run spot-check aboveExpected stable — verify on releaseCheck if wkhtmltopdf is still primary or replaced by headless Chrome as default. The paper format model API is expected to remain stable.

Need help with custom Odoo reports for your Saudi or Bahrain business?

iWesabe's Odoo development team handles custom QWeb report templates, paper format configuration, and ZATCA-compliant invoice layouts. Get a scoping call.

WhatsApp

Frequently Asked Questions

Where is the Paper Formats menu in Odoo 19?
In Odoo 19 (and 18, 17, 16), Paper Formats are at Settings → Technical → Reporting → Paper Formats. You must have developer mode enabled to see the Technical menu. Activate it via Settings → General Settings → Developer Tools → Activate the developer mode.
How do I set a custom page size (not A4 or Letter) in Odoo?
Set `page_width` and `page_height` on the paper format record (values in mm). When these fields are populated, clear the `format` field — both cannot be active simultaneously. For example, a 100 mm × 150 mm label: page_width = 100, page_height = 150, format = (empty).
How do I apply a paper format only to one report, not all reports?
Set `paper_format_id` on the specific `ir.actions.report` record, and make sure `default = False` on the paper format. The `paper_format_id` on the report action takes precedence over the company default. In XML, use the `paper_format` attribute of the `` shorthand tag.
Why does my QWeb report header overlap the body content?
`header_spacing` on the paper format is smaller than the rendered height of your header HTML. Measure your header at 96 DPI (1 mm ≈ 3.78 px), note the pixel height, convert to mm, and add 5–10 mm buffer. Set that value as `header_spacing`. This is the most common paper format issue in Odoo development.
Can I use a different paper format for the first page vs. subsequent pages?
No — `ir.paper.format` applies a single configuration to all pages in a report. Different first-page layouts must be achieved through CSS (`@page :first { ... }`) inside the QWeb template, not through separate paper formats. The `margin_top` and `header_spacing` values always apply to every page.
Does the paper format affect the report when printed from screen (not downloaded as PDF)?
No. The paper format (ir.paper.format) is used only when Odoo renders the report as a PDF via wkhtmltopdf. When a user prints the on-screen HTML view directly through the browser, the browser's own page setup applies. To control browser print layout, use `@media print` CSS in the QWeb template.
iWesabe Editorial Team

iWesabe Editorial Team

Practitioner insights on Odoo ERP, ZATCA compliance, and Saudi enterprise digital operations — written by iWesabe's consulting, finance, and engineering teams.

About iWesabe

Related Articles