Overview
report_xlsx is a base reporting module maintained by the Odoo Community Association (OCA). It provides a clean, Python-only way to generate XLSX (Excel) reports in Odoo, without QWeb, HTML, or PDF rendering.
The module is officially available on Odoo Apps and can be downloaded from:
https://apps.odoo.com/apps/modules/17.0/report_xlsx
This module acts as an abstract engine. It does not generate reports by itself. Instead, it exposes a base class that developers extend to build custom Excel reports using xlsxwriter.
Tutorial
1. Ensure system dependency
Make you already installed these library in your pip list:
- xlsxwriter
- xlrd
2. Directory Standart
A typical module that implements an XLSX report
my_module/
├─ __manifest__.py
├─ reports/
│ ├─ __init__.py
│ └─ my_model_report_xlsx.py
└─ views/
└─ report_action.xml
3. Implementing the XLSX Report Class
Every XLSX report must inherit from report.report_xlsx.abstract.
from odoo import models
class MyModelReportXlsx(models.AbstractModel):
_name = 'report.my_module.my_model_report_xlsx'
_inherit = 'report.report_xlsx.abstract'
def generate_xlsx_report(self, workbook, data, records):
sheet = workbook.add_worksheet('Summary')
header = workbook.add_format({
'bold': True,
'border': 1,
'align': 'center'
})
sheet.write(0, 0, 'Name', header)
sheet.write(0, 1, 'Amount', header)
row = 1
for rec in records:
sheet.write(row, 0, rec.name)
sheet.write(row, 1, rec.amount)
row += 1
Parameter:
- workbook: xlsxwriter.Workbook
- data: optional payload (wizard input)
- records: active recordset passed by the report action
4. Create the Report Action
To expose an XLSX report in Odoo, you must register an ir.actions.report record.
This action binds your Python report_xlsx class to a model and makes it callable from the UI or code.
<odoo>
<record id="action_my_model_xlsx" model="ir.actions.report">
<field name="name">My Model Excel Report</field>
<field name="model">my.model</field>
<field name="report_type">xlsx</field>
<field name="report_name">my_module.my_model_report_xlsx</field>
<field name="report_file">my_model_report_xlsx</field>
<field name="binding_type">report</field>
</record>
</odoo>
5. Calling XLSX Report from a Function
In Odoo, an XLSX report can be executed from a button by calling report_action() inside a model method.
The button uses type="object" and calls a Python function.
from odoo import models
class MyModel(models.Model):
_name = 'my.model'
_description = 'My Model'
def create_pdf_report(self):
return self.env.ref(
'my_module.action_my_model_xlsx'
).report_action(self)
XLSX Formatting
Formatting in report_xlsx is handled entirely through xlsxwriter formats.
There is no template layer. Every visual decision is explicit and deterministic.
Basic Format Definitions
header_format = workbook.add_format({
'bold': True,
'border': 1,
'align': 'center',
'valign': 'vcenter',
'bg_color': '#D9D9D9'
})
text_format = workbook.add_format({
'border': 1,
'align': 'left'
})
number_format = workbook.add_format({
'border': 1,
'align': 'right',
'num_format': '#,##0.00'
})
date_format = workbook.add_format({
'border': 1,
'num_format': 'yyyy-mm-dd'
})
Writing Data Rows with Format
row = 1
for rec in records:
sheet.write(row, 0, rec.partner_id.name or '', text_format)
sheet.write(row, 1, rec.amount_total, number_format)
sheet.write(row, 2, rec.invoice_date_due, date_format)
row += 1
Column Width and Row Height
Always set column width explicitly.
sheet.set_column('A:A', 30)
sheet.set_column('B:B', 18)
sheet.set_column('C:C', 15)
Merging Cells
title_format = workbook.add_format({
'bold': True,
'font_size': 14,
'align': 'center',
'valign': 'vcenter'
})
sheet.merge_range('A1:C1', 'Aged Payable Report', title_format)
