odoo14 生成PDF报表详解

发布时间 2023-10-08 13:14:39作者: CrossPython

1. 新建report目录-新建报表xml文件material_storage_pdf.xml

2.  定义xml文件报表参数参数

ir.actions.report报表属性

name:打印动作按钮下的报表名字
model:你的报表相关的模型,也就是说是你下载pdf中,pdf中数据的来源
report_type:PDF报表的qweb-pdf 或HTML的 qweb-html,就是下载的报表类型
groups_id:允许浏览/使用当前报表的组的Many2many 字段
attachment_use:若设置为True, 使用 attachment表达式所生成的名称存储为附件的报表;如果需要仅生成一次报表可以使用它 (例如出于法律原因)
attachment:定义报表名称的python 表达式;记录可作为 object变量访问
paperformat_id:定义纸张格式

 

    <record id="material_storage_report_pdf2" model="ir.actions.report">
        <field name="name">物料标识卡</field>
        <field name="model">material.storage</field>
        <!--报告类型:pdf或html-->
        <field name="report_type">qweb-html</field>
        <!--报告名字:module_name.自定义报表模板名称-->
        <field name="report_name">quality_inspection.material_storage_pdf2</field>
        <field name="report_file">quality_inspection.material_storage_pdf2</field>
        <!--指定报表使用的纸张格式,默认使用公司的格式,这里指定设置的格式-->
        <field name="paperformat_id" ref="material_storage_pdf2_paper"/>
        <!--pdf报告名字,引用记录的编号字段-->
        <field name="print_report_name">'物料标识卡'+ str(object.name)</field>
        <!-- 是否适用附件功能 优点第2+次打印直接读取附件 速度更快 | 缺点由于存储了附件 报表格式或内容改变后 下载依旧是第一次的样子 -->
        <field name="attachment_use">False</field>
        <!--绑定的模型,这里指定你要关联的模型-->
        <field name="binding_model_id" ref="model_material_storage"/>
        <!--绑定的类型-->
        <field name="binding_type">report</field>
    </record>

  

3. 定义报表模板

报表模板在template标签中定义,定义的id的值不是随便定义的,要和report报表成映射关系
所有写的报表的模板需要写在标签web.html_container下,而且,t-call是固定的(调用external_layout 会在报表上添加头部和底部。)
PDF内容体是 <div class="page">内部的内容, 因为这是一个QWeb模板,你可以访问由模板接收的docs对象的所有字段。

有一些可在报表中访问的具体变量,主要有:
①docs针对当前报表的记录

②doc_ids针对 docs记录的id列表

③doc_model针对docs 记录的模型

④time对Python标准库 time的引用

⑤user打印报表的用户的res.user 记录

⑥res_company当前 user的公司的记录

报表中定义页脚,div中class="footer"
<span class="page"/>表示的是一条数据所占的页数的当前页
<span class="topage"/>表示的一条数据所占的页数的总页数

    <!--模板id:module_name.自定义报表模板名称,去掉module_name-->
    <template id="material_storage_pdf2">
        <t t-call="web.html_container">
            <!--循环倒入记录,这里没有定义model文件就可以直接使用记录的所有数据,如果定义了模型就需要自己写返回的数据-->
            <t t-foreach="docs" t-as="record">
                <!-- web.external_layout odoo自带的模板,可以在设置选择使用模板;web.internal_layout 内部模板,基本上没什么样式-->
                <t t-call="web.internal_layout">
                    <div class="page">
                        <table>
                            <tbody>
                                <tr>
                                    <td style="border:1px solid black;vertical-align: middle;text-align: center;" colspan="4">
                                        物料标识卡
                                    </td>
                                </tr>
                                <tr>
                                    <td style="border:1px solid black;vertical-align: middle;text-align: center;">
                                        申购序号
                                    </td>
                                    <td style="border:1px solid black;vertical-align: middle;text-align: center;">
                                        <t t-esc="record.source_id.name"/>
                                    </td>
                                    <td style="border:1px solid black;vertical-align: middle;text-align: center;">
                                        质检人员
                                    </td>
                                    <td style="border:1px solid black;vertical-align: middle;text-align: center;">
                                        <t t-esc="record.maker_id .name"/>
                                    </td>
                                </tr>
                                <tr>
                                    <td style="border:1px solid black;vertical-align: middle;text-align: center;">
                                        物料名称
                                    </td>
                                    <td style="border:1px solid black;vertical-align: middle;text-align: center;" colspan="3">
                                        <t t-esc="record.product_id.name"/>
                                        <t t-esc="record.attribute"/>
                                    </td>
                                </tr>
                                <tr>
                                    <td style="border:1px solid black;vertical-align: middle;text-align: center;" >
                                        入库数量
                                    </td>
                                    <td style="border:1px solid black;vertical-align: middle;text-align: center;">
                                        <t t-esc="record.storage_quantity"/>
                                    </td>
                                    <td style="border:1px solid black;vertical-align: middle;text-align: center;">
                                        入库日期
                                    </td>
                                    <td style="border:1px solid black;vertical-align: middle;text-align: center;">
                                        <t t-esc="record.storage_date"/>
                                    </td>
                                </tr>
                                <tr>
                                    <td style="border:1px solid black;vertical-align: middle;text-align: center;">
                                        备注
                                    </td>
                                    <td style="border:1px solid black;vertical-align: middle;text-align: center;" colspan="3">
                                        <t t-esc="record.note"/>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                    </div>
                </t>
            </t>
        </t>
    </template>

  

4. 还可以定义pdf报表的纸张类型(默认是A4)

纸张格式是report.paperformat 记录并可包含如下属性:

id: id的取值和报表模板中的template的id一样,也就是相等的,相当于做的映射关联
name: 仅用于在某种列表中查看报表的助记内容/描述
description格式的简短描述
format是预定义格式(A0到A9, B0到 B10, 法律文书, 信件, 公报,…) 或 自定义;默认为 A4。你果定义页面大小时不能使用非自定义格式。
dpi输出DPI;默认为90
margin_top, margin_bottom, margin_left, margin_right单位为mm的边框大小page_height, page_width 单位为mm的页面大小
orientation横向或纵向,
header_line显示头部线的布尔值
header_spacing 单位为mm的头部间距

 

 <record id="material_storage_pdf2_paper" model="report.paperformat">
        <field name="name">物料卡纸张定义</field>
        <field name="default" eval="True"/>
        <!--定义纸张类型-->
        <field name="format">A4</field>
        <!--横向打印-->
        <field name="orientation">Landscape</field>
        <!--纵向打印-->
<!--        <field name="orientation">Portrait</field>-->
        <!--边框间距,单位mm。以下同样-->
        <field name="margin_top">10</field>
        <field name="margin_right">10</field>
        <field name="margin_bottom">20</field>
        <field name="margin_left">10</field>
        <!--自定义页面大小-->
<!--        <field name="page_height">297</field>-->
<!--        <field name="page_width">210</field>-->
        <!--显示头部线(页眉线)的布尔值-->
        <field name="header_line" eval="False"/>
        <!--显示头部的间距(页眉到顶部的距离)-->
        <field name="header_spacing">0</field>
        <field name="dpi">90</field>
    </record>

  

以上内容均定义在material_storage_pdf.xml文件中

 
 
 
 
 
 
 

3. 在manifest文件中引入material_storage_pdf.xml文件

    # data: 加载XML文件。有先后顺序,如果有调用需要将被调用的放在前面
    'data': [
        'security/quality_inspection_security.xml',
        'security/ir.model.access.csv',
        'wizard/material_storage_wizard_view.xml',
        'views/inspection_manual_view.xml',
        'views/incoming_inspection_view.xml',
 
        'report/quality_inspection_report_pdf.xml',
        'report/material_storage_report_pdf.xml',
        'report/material_storage_report_pdf2.xml',

  

4.  定义报表模型

(自己测试发现可以不用定义,直接写xml文件也能实现,定义了操作起数据反而更麻烦,全部需要自己写,但这里还是写出定义方法)

@api.model
def _get_report_values(self, docids, data=None):
pass

这个方法是必须继承的,也就是必须要写的 ,return的值是给template里面来用的,可以自己写,该方法里面一般写的就是报表的处理逻辑。

该方法中的参数:
① docids:是你打印时候选的几个数据,这块就是几个数据的id,组成的列表
②data是报表的类型,后台打印出这两个参数的值为

 

from odoo import models, api, fields
  
 
class QualityInspectionReport(models.AbstractModel):
    # _name内容由三部分构成,report. + 关联模块名. + xml文件模板id组成(quality_inspection_report_pdf.xml的template id="quality_inspection_pdf")
    _name = 'report.quality_inspection.quality_inspection_pdf'
    _description = '质检报告pdf'
 
    @api.model
    def _get_report_values(self, docids, data=None):
        report_ids = self.env['purchase.record'].browse(docids)
        docs = []
        for record in report_ids:
            record_dic = {
                'name': record.name,
 
            }
        docs.append(record_dic)
        docargs = {
            'doc_ids': docids,
            'doc_model': 'purchase.record',
            'docs': docs,
        }
        return docargs

  

定义完记得在init文件中导入 模型