Creating Custom XLSX Import Wizard in Odoo

Streamline Complex Imports in Odoo

Odoo’s built-in import tools are great for quick data loads, but they don’t always fit custom workflows, especially when dealing with complex models or when you need to update existing records in bulk based on custom logic.

In this tutorial, We'll build a custom import wizard in Odoo that lets users to upload an Excel (.xlsx) file to automatically update fields like Serial Number, IMEI 1, and IMEI 2 for each line item in a custom Bulk Purchase model, matched via a unique field like ISN (Item Serial Number).

Why a Custom Import Wizard?

Imagine you have a custom model named purchase.bulk.item that holds detailed product entries in a purchase order. After receiving your products, the supplier provides an Excel file containing:

  • ISN (Item Serial Number)
  • Serial Number
  • IMEI 1
  • IMEI 2

Manually entering these details for dozens or hundreds of items in the Odoo interface would be time-consuming and error-prone. So, we’ll create a user-friendly import wizard that automates this process, updating records accurately with just a file upload.

Step-by-Step Implementation

1. Create the Wizard Model

# models/import_wizard.py
from odoo import models, fields, api
import base64
import io
import openpyxl
class ImportPurchaseItemsWizard(models.TransientModel):
    _name = 'import.purchase.items.wizard'
    _description = 'Import Serial No and IMEI 1'
    file = fields.Binary('Excel File', required=True)
    file_name = fields.Char('File Name')
    def action_import_file(self):
        if not self.file:
            raise UserError("Please upload a file.")
        data = base64.b64decode(self.file)
        workbook = openpyxl.load_workbook(filename=io.BytesIO(data), data_only=True)
        sheet = workbook.active
        for idx, row in enumerate(sheet.iter_rows(min_row=2), start=2):
            isn = str(row[0].value).strip()
            serial_no = str(row[1].value).strip()
            imei_1 = str(row[2].value).strip()
            if not isn:
                continue
            line = self.env['purchase.bulk.item'].search([('isn', '=', isn)], limit=1)
            if line:
                line.write({
                    'serial_no': serial_no,
                    'imei_1': imei_1
                })
            else:
                _logger.warning(f"Row {idx}: ISN {isn} not found.")
  • This model is a TransientModel — used for temporary data like wizards.
  • It accepts a binary file field, decodes it, reads rows, and updates matching records in the database based on the ISN.

2. Create the Wizard View


<record id='view_import_purchase_items_wizard' model='ir.ui.view'>
    <field name='import.purchase.items.wizard.form' />
    <field name='model'='import.purchase.items.wizard' />
    <field name='arch' type='xml'>
        <form string="Import Purchase Items">
            <group>
                <field name='file' filename='file_name' />
            </group>
            <footer>
                <button name='action_import_file' string="Import" type='object' class='btn-primary' />
                <button string="Cancel" class='btn-secondary' special='cancel' />
            </footer>

The wizard shows a simple form with a file upload field and two buttons — Import and Cancel.

3. Add an Action & Menu

You can attach this wizard to a smart button in the purchase order or product form, depending on your workflow.


<record id="action_import_purchase_items" model="ir.actions.act_window">
    <field name="name" "Import Purchase Items" />
    <field name="res_model" "import.purchase.items.wizard" />
    <field name="view_mode" "form" />
    <field name="target" "new" />
</record>

4. Add Button Access

Example of adding a button on the purchase.bulk.item form view:


<button name="%(action_import_purchase_items)d" string="Import Items" type="action" class="btn-primary" />

Testing the Wizard

To verify that everything works:

  • Create a few purchase.bulk.item records with known ISN values.
  • Prepare an Excel file with headers: ISN, Serial No, IMEI 1, IMEI 2.
  • Go to the wizard and upload your file.
  • Click Import and confirm that the matching records are updated in Odoo.

Wizard View

Custom XLSX Import Wizard in Odoo

Sample Excel Format

Odoo custom import template

Wrap-Up

Custom import wizards in Odoo are a powerful way to automate data processing, especially when the default tools just don’t cut it.

With a bit of Python and XML, you can create user-friendly tools that:

  • Speed up operations
  • Reduce human error
  • Improve data integrity
  • Impress clients with professional polish

This technique is widely applicable across domains: sales, HR, inventory, education, and even finance.

Need more development tips?

Stay tuned to our blog.

Vijay Elangovan 15 April, 2025
Archive
Sign in to leave a comment
How to Migrate an On-Premises Odoo Enterprise Database