如何在 Odoo 中使用 Wkhtmltopdf 打印尺寸准确的 div?

How to print divs with an accurate size using Wkhtmltopdf in Odoo?

我正在尝试在 Odoo 10 中创建新的产品标签 Qweb 报告。

报告的纸张格式必须是无边距的 A4。每个标签的宽度必须为 70 毫米,高度为 42.4 毫米。这意味着每行将有三个标签,每页将有七行(A4 = 210mm x 297mm。所以 70mm x 3 = 210mm,42.4mm x 7 = 297mm)。我以这种方式创建了 paperformat:

<record id="paperformat_euro_no_margin" model="report.paperformat">
    <field name="name">European A4 (no margins)</field>
    <field name="default" eval="True" />
    <field name="format">A4</field>
    <field name="page_height">0</field>
    <field name="page_width">0</field>
    <field name="orientation">Portrait</field>
    <field name="margin_top">0</field>
    <field name="margin_bottom">0</field>
    <field name="margin_left">0</field>
    <field name="margin_right">0</field>
    <field name="header_line" eval="False"/>
    <field name="header_spacing">0</field>
    <field name="dpi">90</field>
</record>

我为我的自定义报告分配了纸张格式,我检查它工作正常:

<report
    id="report_product_template_labels_custom"
    string="Custom Products Labels"
    model="product.template"
    report_type="qweb-pdf"
    name="my_module.report_producttemplatelabel_custom"
    file="my_module.report_producttemplatelabel_custom"/>

<record id="report_product_template_labels_custom" model="ir.actions.report.xml">
    <field name="paperformat_id" ref="paperformat_euro_no_margin"/>
</record>

然而,看到 Odoo 如何忽略值为 0 的 margin_leftmargin_right 属性令人恼火(我认为它已被 Odoo S.A 报告和修复)。我必须将 margin-left:-5mm;margin-right:-5mm; 样式应用于报告页面,以避免默认值覆盖我的值。 有没有更简洁的方法来解决这个问题?

但我的主要问题来了。这是我的报告代码:

<template id="report_producttemplatelabel_custom">
    <t t-call="report.html_container">
        <div class="page" style="margin-left:-5mm !important; margin-right:-5mm !important;">
            <t t-foreach="docs" t-as="template">
                <t t-foreach="template.product_variant_ids" t-as="product">
                    <t t-call="my_module.report_simple_label_custom">
                        <t t-set="product" t-value="product"/>
                    </t>
                </t>
            </t>
        </div>
    </t>
</template>

如您所见,对于产品的每个变体,我都展示了一个自定义的 Qweb 模板 (report_simple_label_custom)。其代码如下:

<template id="report_simple_label_custom">
    <div style="position: relative; display: block; width:70mm; height:42.4mm; float:left; margin:0; padding:0;">
        <div style="width:100%; height:100%; border: 1px solid white; background: green;"></div>
    </div>
</template>

代码非常简单。如果产品有 21 个变体,我应该会看到 21 个绿色 div,每行 3 个,非常适合 A4。但是,当我打印报告时,它们根本不适合。每个div的高度似乎都比42.4mm少了很多。我试过修改 paperformat dpi 但我找不到一个值使 CSS 毫米与 PDF 毫米相同。

在尝试了很多事情之后,我决定忽略毫米并使用百分比,以使标签非常适合 PDF 大小。

修改后,当我在 HTML 中打印报告时,一切看起来都很好,但是当我以 PDF 格式打印时,宽度可以但高度不行(div 重叠) .这是因为我猜有些父元素的高度不同于 100%。我将此高度应用于 page div,但问题仍然存在。

那么,谁能告诉我如何解决这个问题?我只想要一个A4填满相同大小的矩形,每行三个,每列七个(如果少于21个变体,左边的space必须是空白)

我终于找到了解决整个问题的好方法。

避免在 PDF 的左右尺寸上看到烦人的边距的解决方案

Wkhtmltopdf 在这种情况下没有罪。当我以 HTML 格式打印报告时,我意识到它的两页边距也有 space。事实上它是一个填充,由于 .container class。所以解决方案是覆盖我报告中的 class 属性,这样:

<template id="report_simple_label_custom">
    <style type="text/css">
        .container {
            padding: 0 !important;
        }
    </style>
    <div style="position: relative; display: block; width:70mm; height:42.4mm; float:left; margin:0; padding:0;">
        <div style="width:100%; height:100%; border: 1px solid white; background: green;"></div>
    </div>
</template>

将HTML大小精确转换为PDF大小的解决方案

当Odoo执行wkhtmltopdf将HTML代码转换为PDF时,它没有使用选项--disable-smart-shrinking。如果我们直接(在 Odoo 之外)执行 wkhtmltopdf 将任何 HTML 代码转换为 PDF,我们可以传递该参数以获得准确的结果。所以问题是:如何让 Odoo 在转换我们的报告时通过该参数?简单的答案是从 repo reporting-engine 安装官方 OCA 模块。它的名字是report_wkhtmltopdf_param。它允许您告诉 Odoo 在打印特定纸张格式时将附加参数传递给 wkhtmltopdf

所以我必须添加这段代码来将参数传递给我的 paperformat 报告,当然,还要让我的模块依赖于 report_wkhtmltopdf_param app:

<record id="paperformat_euro_no_margin" model="report.paperformat">
    <field name="name">European A4 (no margins)</field>
    <field name="default" eval="True" />
    <field name="format">custom</field>
    <field name="page_height">297</field>
    <field name="page_width">210</field>
    <field name="orientation">Portrait</field>
    <field name="margin_top">0</field>
    <field name="margin_bottom">0</field>
    <field name="margin_left">0</field>
    <field name="margin_right">0</field>
    <field name="header_line" eval="False"/>
    <field name="header_spacing">0</field>
    <field name="dpi">96</field>
</record>

<record id="paperformat_euro_no_margin_disable_smart_shrinking" model="report.paperformat.parameter">
    <field name="paperformat_id" ref="my_module.paperformat_euro_no_margin"/>
    <field name="name">--disable-smart-shrinking</field>
</record>

注意:paperformat 的 dpi 必须为 96 才能获得最佳和更准确的结果。