You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Odoo Journal Entry模块Excel导入报错,求助排查缺失变量

Odoo导入Excel数据到account.move.line时报错排查

问题背景

代码实现以下功能:

  • 读取Excel文件的行数据
  • 将每行数据分配到对应字段
  • 逐行将数据存储到数据库

运行时触发AttributeError: 'NoneType' object has no attribute 'res_id'错误。

原代码

import json
import os
from openpyxl import load_workbook
from odoo import models, fields, api
from odoo.exceptions import ValidationError

class AccountMoveInherit(models.Model):
    _inherit = 'account.move'

    def importar_action(self):
        # Cargar el archivo de Excel sin espacios en el nombre.
        ruta_modulo = os.path.dirname(os.path.abspath(__file__))
        archivo_ruta = os.path.join(ruta_modulo, 'static', 'src', 'lineasdefacturas5.xlsx')

        workbook = load_workbook(archivo_ruta)
        # Seleccionar la hoja de origen
        ws_origen = workbook['Query1']

        #obtenemos la longitud de las filas y columnas
        filas_origen = ws_origen.max_row
        columnas_origen = 8
    
        for fila in range(2, filas_origen + 1):
            lista_valores = [None] * 8
            numero = 0
            for columna in range(1, columnas_origen + 1):
                valor_celda = ws_origen.cell(row=fila, column=columna).value
                lista_valores[numero] = valor_celda
                numero += 1

                idFact = self.env['ir.model.data'].search([('name','=',lista_valores[1])]).res_id
                idProduct = self.env['product.template'].search([('name','=',lista_valores[2])]).id
                
            objeto = {
                'id': lista_valores[0],
                'move_id': idFact,
                'product_id': idProduct,
                'quantity': lista_valores[3],
                'price_unit': lista_valores[4],
                'company_currency_id': lista_valores[5],
                'journal_id': lista_valores[6],
                'account_id': lista_valores[7],
                }
            record = self.env['account.move.line'].create(objeto)

报错原因分析

  1. 空值访问错误:报错指向idFact = self.env['ir.model.data'].search([('name','=',lista_valores[1])]).res_id,说明search未找到匹配记录,返回None,直接访问res_id触发NoneType属性错误。同理idProduct的获取逻辑也存在相同风险。
  2. 循环逻辑错误:获取idFact和idProduct的代码写在列循环内部,会在读取每一列时重复执行搜索,完全冗余且影响效率。
  3. 手动指定ID风险:手动传入id字段可能与Odoo自动生成的ID冲突,导致数据异常。

修正方案

1. 修正核心逻辑

for fila in range(2, filas_origen + 1):
    lista_valores = [None] * 8
    numero = 0
    for columna in range(1, columnas_origen + 1):
        valor_celda = ws_origen.cell(row=fila, column=columna).value
        lista_valores[numero] = valor_celda
        numero += 1

    # 移到列循环外,避免重复执行
    # 处理idFact:添加空值检查
    ir_data_record = self.env['ir.model.data'].search([('name','=',lista_valores[1])], limit=1)
    idFact = ir_data_record.res_id if ir_data_record else False
    if not idFact:
        raise ValidationError(f"第{fila}行:未找到name为{lista_valores[1]}的ir.model.data记录")

    # 处理idProduct:添加空值检查
    product_template_record = self.env['product.template'].search([('name','=',lista_valores[2])], limit=1)
    idProduct = product_template_record.id if product_template_record else False
    if not idProduct:
        raise ValidationError(f"第{fila}行:未找到name为{lista_valores[2]}的product.template记录")
    
    objeto = {
        'move_id': idFact,
        'product_id': idProduct,
        'quantity': lista_valores[3],
        'price_unit': lista_valores[4],
        'company_currency_id': lista_valores[5],
        'journal_id': lista_valores[6],
        'account_id': lista_valores[7],
    }
    # 移除手动指定的id字段,由Odoo自动生成
    record = self.env['account.move.line'].create(objeto)

2. 额外优化建议

  • 批量创建提升性能:如果数据量较大,建议收集所有待创建对象到列表,最后一次性调用create:
    records_to_create = []
    for fila in range(2, filas_origen + 1):
        # ... 上述处理逻辑,生成objeto
        records_to_create.append(objeto)
    self.env['account.move.line'].create(records_to_create)
    
  • 数据校验:提前检查Excel中对应列的内容是否与系统中ir.model.data和product.template的name字段完全匹配(注意大小写、空格)。

内容的提问来源于stack exchange,提问作者Erick Toledo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 17:52:55