问题描述
我正在尝试在 odoo 10 中创建产品标签的新 Qweb 报告。
报告的纸张格式必须是 A4 纸,没有边距。每个标签的宽度必须为 70 毫米,高度为 42.4 毫米。这意味着每行有 3 个标签,每页有 7 行(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>
我将 paperformat 分配给了我的自定义报告,并检查它是否工作正常:
<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 如何在 margin_left
和 margin_right
属性值为 0 时忽略它们(我认为它已被 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 大小。
- Div 宽度 = 100 / 3 ~ 33.2%
- Div 高度 = 100 / 7 ~ 14.28%
修改后,当我用 HTML 打印报告时,一切看起来都很好,但是当我用 PDF 打印时,宽度可以,但高度不行(div 重叠)。这是因为我猜有一些父元素的高度与 100% 不同。我将此高度应用于 page
div,但问题仍然存在。
那么,谁能给我一个提示,我该如何解决这个问题?我只想要一个 A4,里面填满相同大小的矩形,每行三个,每列七个(如果变体少于 21 个,则左边的空间必须为空白)。
解决方法
我终于找到了解决整个问题的好方法。
避免在 PDF 的左右尺寸上看到烦人的边距的解决方案
Wkhtmltopdf 不是本案的罪魁祸首。当我以 HTML 格式打印我的报告时,我意识到它的两个边距上也有空格。实际上,由于 .container
类,它是一个填充。因此,解决方案是在我的报告中覆盖该类属性,如下所示:
<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 在转换我们的报告时传递该参数?简单的答案是从存储库 reporting-engine
安装官方 OCA 模块。它的名字是report_wkhtmltopdf_param
。它允许您在打印特定纸张格式时告诉 Odoo 将附加参数传递给 wkhtmltopdf
。
所以我必须添加这段代码以将参数传递给我的 paperformat 报告,当然,让我的模块依赖于 report_wkhtmltopdf_param
应用程序:
<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 才能获得最佳和更准确的结果。