zoukankan      html  css  js  c++  java
  • openerp 报表

    报表

    OpenERP 主要有三种类型的报表:

    • OpenOffice.org 报表
    • XML 报表
    • 自定义报表 (基于 PostgreSQL 视图,显示在界面上)

    这一部分主要描述 OpenOffice.org 报表, 和 XSL:XML 报表. 自定义报表在高级建模部分描述 - PostgreSQL 基于数据库视图的报表.

    OpenOffice.org 报表

    文件流

    OpenOffice.org是OpenERP中最常用的报表格式。OpenOffice.org Writer被用来生成RML模板,而RML模板用来生成pdf报表。

    images/ooo_report_overview.png

    内部过程

    images/process_ooo.png

    .SXW 模板文件

    • 我们用OpenOffice1.0的.sxw文件作为模板。模板中包含用中括号括起来的表达式或OpenOffice字段(field),用来提供给OpenERP server填充数据。但这只是作为帮助开发者更直观地生成.RML文件的一种方法。OpenERP并不需要SXW文件产生报表。

    .RML 模板

    • 可以使用Open SXW2RML从SXW文件生成RML文件。RML文件是一种表现PDF文档的XML格式,可以转换为PDF文件。RML是一种更容易的方法,至少XML语法比PDF语法更加通俗易懂。

    报表引擎

    • 报表引擎(report engine)从数据库中读出数据,插入在RML文件的表达式中。

    在.RML文件中,将以发票上客户的城市名称替换掉相应表达式。报表引擎以真实数据替换所有表达式之后,生成相同的.RML文件。

    生成最终文档

    • 最后RML文件会根据OpenReport代码的需要,转换成PDF或者HTML文件。

    生成 SXW 文件

    你可以使用 OpenOffice 设计报表。举个例子,如: server/bin/addons/sale/report/order.sxw.

    images/writer_report.png

    OpenOffice 报表中的动态内容

    动态内容

    SXW/RML报表中,你可以在中括号中加入Python代码,以获得OpenERP中的对象(object)。代码可以使用如下变量

    可用的变量

    可以用的 Python 对象/变量:

    • objects : 将要打印的object记录(例如发票(invoice)对象).
    • data : 向导(wizard)中获得的数据
    • time : Python的time模块(详见Python文档).
    • user : 运行这个报表的用户.
    可用的函数

    可以用的 Python 函数:

    • setLang('fr') : 设置语言,用于自动取得对应翻译.
    • repeatIn(list, varname[, tagname]) : 遍历模板当前部分list中的对象 (整个文档, 当前段落, 表格中的当前行),可以在模板中使用varname作为变量名。 从 4.1.X版开始, 你可以使用第三个(可选的)参数指定循环结果放在哪个.RML标记中.
    • setTag('para','xpre') : 在由sxw转换rml文档过程中,替换指定标记。这里是用xpre替换para (xpre 是一个预定义格式的段落)。(?)
    • removeParentNode('tr') : 移除类型'tr'的父结点, 这个参数经常在条件语句中使用 (如下例)

    标签示例:

    • [[ repeatIn(objects,'o') ]] : 循环objects,指定变量名为o.
    • [[ repeatIn(o.invoice_line,'l') ]] : 对o的invoice_line循环,指定变量名为'l'.
    • [[ repeatIn(o.invoice_line,'l', 'td') ]] : 循环每行,并为每行数据创建一个单元格
    • [[ (o.prop=='draft')and 'YES' or 'NO' ]] : 根据变量‘prop’输出YES或 NO
    • [[ round(o.quantity * o.price * 0.9, 2) ]] : 可以进行变量计算.
    • [[ '%07d' % int(o.number) ]] : 数字的格式化输出
    • [[ reduce(lambda x, obj: x+obj.qty , list , 0 ) ]] : 列表中所有对象 qty 字段值的和 (可以试一下用 “object” 作为列表变量)
    • [[ user.name ]] : 打印报表的当前用户名
    • [[ setLang(o.partner_id.lang) ]] : 从变量中取得语言
    • [[ time.strftime('%d/%m/%Y') ]] : 以dd/MM/YYYY格式输出时间, 查阅python文档获得关于“%d”的帮助, ...
    • [[ time.strftime(time.ctime()[0:10]) ]] 或 [[ time.strftime(time.ctime()[-4:]) ]] : 只输出日期.
    • [[ time.ctime() ]] : 输出当前日期 & 时间
    • [[ time.ctime().split()[3] ]] : 只输出时间
    • [[ o.type in ['in_invoice', 'out_invoice'] and 'Invoice' or removeParentNode('tr') ]] : 如果type是 ‘in_invoice’ 或‘out_invoice’ 那么输出 ‘Invoice’;如果 不是,‘tr’类型的父节点会被删除.

    一个有趣的标记(tag):如果想输出当前记录的创建者(create_uid)或者最后一位修改者你需要在报表要输出的类中加入如下字段:

    'create_uid': fields.many2one('res.users', 'User', readonly=1)
    

    然后在报表中用这个变量输出相应的名字:

    o.create_uid.name
    

    有时你希望根据条件打印。 你可以用python的逻辑操作符"not","and","or"构造自己的判断语句。 Python中的每个对象都有自己的逻辑值(TRUE或FALSE):

    (o.prop=='draft') and 'YES' or 'NO' #prints YES or NO
    

    注意and要比or的优先级高,表达式等价为:

    ((o.prop=='draft') and 'YES') or 'NO'
    
    如果 o.prop是 ‘draft’, 那么计算结果为:
    1. o.prop == 'draft' 为 True.
    2. True and 'YES' 为 'YES'. 左项为 真时, 返回右项, 否则返回左项.这里返回字符串'YES'.
    3. 'YES' or 'NO' is 'YES'. 左项为真, or操作会忽略右项。只计算左项值.返回字符串'YES'.
    如果 o.prop 是‘confirm’之类其他的操作, 那么计算如下:
    1. o.prop == 'draft' 为 False.
    2. False and 'YES' is False. 因为左项为 "false" 值, and 操作截断并忽略右项. 只计算左项.
    3. False or 'NO' is 'NO'. 因为左项为 "false" 值, or 计算右项.

    可以使用更复杂的的结构. 可以参照python 手册章节 `Python's boolean operators`_ .

    可以用python的“filter”函数。示例:

    repeatIn(filter( lambda l: l.product_id.type=='service' ,o.invoice_line), 'line')
    

    只输出每段中product 含有 type=’service’的行.

    报表中显示二进制字段图像

    [[ setTag('para','image',{'width':'100.0','height':'80.0'}) ]] o.image or setTag('image','para')

    [[   p['image']   and  setTag('para','image',{'width':'78.0','height':'78.0'}) or removeParentNode('blockTable') ]] [[ p['image'] ]]

    SXW2RML

    Open Report 手册

    关于

    The OpenERP 的报表引擎.

    Open Report 是一个模块,可让您从OpenOffice的模板文件(sxw)和任何关系数据库中渲染出高质量报表。 它可以用来作为OpenERP模块或作为独立的程序.

    SXW 转 RML 代码的安装,适用于Windows用户

    为了使用python代码‘tiny_sxw2rml.py’,你需要安装如下包:

    SXW 转 RML 代码的安装,适用于linux用户

    tiny_sxw2rml.py 可以在OpenERP 模块 base_report_designer 中找到:

    server/bin/addons/base_report_designer/wizard/tiny_sxw2rml/tiny_sxw2rml.py
    

    确认 normalized_oo2rml.xsl 和 tiny_sxw2rml 在一起,否则你会遇到如下错误:

    • failed to load external entity normalized_oo2rml.xsl
    使用 tiny_sxw2rml

    当你做好必要的准备,打算编辑您自己的报表模板(template)时,使用如下命令:

    tiny_sxw2rml.py template.sxw > template.rml
    

    注释: tiny_sxw2rml.py 帮助 建议你使用”-o OUTPUT”指定输出文件,但貌似0.9.3版本不支持

    OpenERP Server PDF 输出

    Server PDF 输出

    关于

    要根据rml文件生成pdf,OpenERP需要一个rml解释器.

    解释器

    语法解释器可以在模块中添加。例如如下代码:

    import time
    from report import report_sxw
    
    class order(report_sxw.rml_parse):
        def __init__(self, cr, uid, name, context):
            super(order, self).__init__(cr, uid, name, context)
            self.localcontext.update({
                'time': time,
            })
    
    report_sxw.report_sxw('report.sale.order', 'sale.order',
          'addons/sale/report/order.rml', parser=order, header=True)
    

    解释器继承自 report_sxw.rml_parse 对象 并且增加了localcontext变量和函数 time, 因此在报表中可以调用.

    report_sxw.report_sxw 实例生成之后,需要如下参数:
    • 报表的名字

    • report关联的object名字

    • rml文件的路径

    • 默认的rml解释器(默认为rml_parse)

    • 在公司配置报表头部(默认为true)
      • 'external' (默认)
      • 'internal'
      • 'internal landscape'
      • False - 使用报表自己定义的报表头
    xml 定义

    如果要在 client端可见, 报表应该声明在一个 xml 文件中 (一般格式为: "module_name"_report.xml) ,这个文件应该列进 __openerp__.py文件

    下面是销售订单报表的例子:

    <?xml version="1.0"?>
    <openerp>
            <data>
                    <report
                            id="report_sale_order"
                            string="Print Order"
                            model="sale.order"
                            name="sale.order"
                            rml="sale/report/order.rml"
                            auto="False"/>
                            header="False"/>
            </data>
    </openerp>
    

    参数如下:

    • id: OpenERP中的报表id,类似openerp中的其他xml标记
    • string: 客户端按钮显示的文字
    • model: 报表中用到的object
    • name: parse中注册的报表名字去掉"report." 之后的部分
    • rml: rml 文件路径
    • auto: 指定server是否生成默认的解释器
    • header: 是否允许页眉(report header)。 如果需要编辑, 进入如下菜单: Administration -> Users -> Company’s structure -> Companies. 选择并编辑您的公司: 其中 “Header/Footer” 标签 允许你编辑相应的 header/footer.

    XSL:RML 报表

    XML 报表不需要编程,但是需要两种简单的 XML 文件:

    • 一种文件描述输出的数据 (*.xml)
    • 一种文件描述输出的格式 (*.xsl)
    images/automatic-reports.png

    XML模板主要描述记录的哪些字段需要输出. XSL:RML 样式表单(style sheet)处理输出数据,以及报表中的静态文本. 静态文本是指在报表中不怎么变化的部分,比如表格头部的标题.

    示例

    下面给出一个例子,列出用于生成ERP报表的不同文件.

    images/ids-report.png

    XML 模板

    <?xml version="1.0"?>
    
        <ids>
        <id type="fields" name="id">
    
            <name type="field" name="name"/>
            <ref type="field" name="ref"/>
    
        </id>
        </ids>
    

    XML 数据文件 (生成的)

    <?xml version="1.0"?>
    
        <ids>
        <id>
    
            <name>Tiny sprl</name>
            <ref>pnk00</ref>
    
        </id><id>
    
            <name>ASUS</name>
            <ref></ref>
    
        </id><id>
    
            <name>Agrolait</name>
            <ref></ref>
    
        </id><id>
    
            <name>Banque Plein-Aux-As</name>
            <ref></ref>
    
        </id><id>
    
            <name>China Export</name>
            <ref></ref>
    
        </id><id>
    
            <name>Ditrib PC</name>
            <ref></ref>
    
        </id><id>
    
            <name>Ecole de Commerce de Liege</name>
            <ref></ref>
    
        </id><id>
    
            <name>Elec Import</name>
            <ref></ref>
    
        </id><id>
    
            <name>Maxtor</name>
            <ref></ref>
    
        </id><id>
    
            <name>Mediapole SPRL</name>
            <ref></ref>
    
        </id><id>
    
            <name>Opensides sprl</name>
            <ref>os</ref>
    
        </id><id>
    
            <name>Tecsas sarl</name>
            <ref></ref>
    
        </id>
        </ids>
    

    XSL 样式表

    <?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
    
        <xsl:template match="/">
    
            <xsl:apply-templates select="ids"/>
    
        </xsl:template>
    
        <xsl:template match="ids">
    
            <document>
    
                <template pageSize="21cm,29.7cm">
    
                    <pageTemplate>
    
                        <frame id="col1" x1="2cm" y1="2.4cm" width="8cm" height="26cm"/>
                        <frame id="col2" x1="11cm" y1="2.4cm" width="8cm" height="26cm"/>
    
                    </pageTemplate>
    
                </template>
    
            <stylesheet>
    
                <blockTableStyle id="ids">
    
                    <blockFont name="Helvetica-BoldOblique" size="12" start="0,0" stop="-1,0"/>
                    <lineStyle kind="BOX" colorName="black" start="0,0" stop="-1,0"/>
    
                    <lineStyle kind="BOX" colorName="black" start="0,0" stop="-1,-1"/>
    
                </blockTableStyle>
    
            </stylesheet>
    
            <story>
    
                <blockTable colWidths="2cm, 6cm" repeatRows="1" style="ids">
    
                    <tr>
    
                        <td t="1">Ref.</td>
                        <td t="1">Name</td>
    
                    </tr>
                    <xsl:apply-templates select="id"/>
    
                </blockTable>
    
            </story>
            </document>
    
        </xsl:template>
    
        <xsl:template match="id">
    
            <tr>
    
                <td><xsl:value-of select="ref"/></td>
                <td><para><xsl:value-of select="name"/></para></td>
    
            </tr>
    
        </xsl:template>
        </xsl:stylesheet>
    

    生成的RML文件

    <?xml version="1.0"?>
    
        <document>
        ...
    
            <story>
    
                <blockTable colWidths="2cm, 6cm" repeatRows="1" style="ids">
    
                    <tr>
    
                        <td t="1">Ref.</td>
                        <td t="1">Name</td>
    
                    </tr>
                    <tr>
    
                        <td>pnk00</td>
                        <td><para>Tiny sprl</para></td>
    
                    </tr>
                    <tr>
    
                        <td></td>
                        <td><para>ASUS</para></td>
    
                    </tr>
                    <tr>
    
                        <td></td>
                        <td><para>Agrolait</para></td>
    
                    </tr>
                    <tr>
    
                        <td></td>
                        <td><para>Banque Plein-Aux-As</para></td>
    
                    </tr>
                    <tr>
    
                        <td></td>
                        <td><para>China Export</para></td>
    
                    </tr>
                    <tr>
    
                        <td></td>
                        <td><para>Ditrib PC</para></td>
    
                    </tr>
                    <tr>
    
                        <td></td>
                        <td><para>Ecole de Commerce de Liege</para></td>
    
                    </tr>
                    <tr>
    
                        <td></td>
                        <td><para>Elec Import</para></td>
    
                    </tr>
                    <tr>
    
                        <td></td>
                        <td><para>Maxtor</para></td>
    
                    </tr>
                    <tr>
    
                        <td></td>
                        <td><para>Mediapole SPRL</para></td>
    
                    </tr>
                    <tr>
    
                        <td>os</td>
                        <td><para>Opensides sprl</para></td>
    
                    </tr>
                    <tr>
                    <td></td>
    
                        <td><para>Tecsas sarl</para></td>
    
                    </tr>
    
                </blockTable>
    
            </story>
    
        </document>
    

    详见以下文档:

    这些格式都是作为 XML specification. 的拓展。

    XML 模板

    XML 模板是简单XML文件,用来描述报表所有可用的object字段中哪些字段是有用的.

    文件格式

    标签(tag)名称可以任意(但在XML中必须是有效的)。XSL文件中,你要使用到这些名称。大多数情况下,标签名和对象字段保持一致.

    没有类型 type 属性 are transferred identically into the XML destination file (the data file). 的结点(node)被转换成XML目标文件(作为数据用)。有类型属性(type attribute)的结点(node)及其内容被server解释,并由object中的数据替换。这些属性(attribute)根据结点的类型 (每个结点支持或者需要不同的属性,attribute) 而不同。大部分结点类型都有名字 name 属性,指代这相应object的名字字段(name of field) .

    关于object中的 "browse" 方法,报表的字段名称是可以使用一种类似面向对象语言中的notation来表示。这意为着 "(关联字段)是可以用这种类似 "bridges" (桥)的方式获得相关对象数据.

    让我们试用 "account.transfer" 对象来举例。Account.transfer对象包含一个partner_id字段,这个字段是一 个指向"res.partner" 对象的 ("many to one")(多对一)的关系。我们假设要创建一个转账(transfers)的报表,,而报表中需要从partner中选择收款人。我们可以这样写以获得收 款人的名字字段:

    partner_id.name

    其它类型

    这里是可用的字段类型的列表:

    • field: 最简单的类型。有这种类型的结点(node),server都会用已知字段(field)的名字属性替换掉node的内容.
    • fields: 这种结点(node)类型,server会在XML数据文件中生成一个和已知名字属性唯一相同的结点(?).
    注释:
    ** 这个结点(node)类型经常使用 "id" 作为名字属性。user使用选择resource的接口创建结点(node)时,会受到影响. ** 结点(node)的语法 <node type="fields" name="field_name"> 和SQL语句 "SELECT FROM object_table WHERE id in identifier_list GROUP BY field_name" 相似,其中identifier_list 是::user (in the interface)可以通过接口选择使用的resource .
    • eval: 这个结点(node)类型计算 expr 属性中表达式(expression)的值。表达式(expression)可以是python表达式,也可以是object的字段名字.
    • zoom: 这个结点(node)类型允许 "enter" 通过relation字段使用name属性中列出的资源. 意味着子结点(child node)不用其他对象名字字段做前缀也可以使用资源字段(fields of that source)。在上面的例子中,我们可以通过以下方式获得parter的name字段:
    <partner type="zoom" name="partner_id">
    
            <name type="field" name="name"/>
    
    </partner>
    
    在这个例子中, 不用zoom注解,标准格式也同样可以有效果:
    
    <name type="field" name="partner_id.name"/>
    
    zoom 类型往往用于恢复同一个object的多个字段(field).
    • function: 返回name属性中所调用函数的结果。这个函数必须是提前定义的。暂时可用的函数是today,用来返回现在日期.
    • call: calls对象name属性是方法名称,args属性是参数名称。函数的结果放进一个字典(dictionary),形如:{'name_of_variable': value, ... } 这个结果可以被子结点使用。使用call类型的结点必须有相应的value属性,以和调用方法所返回的字典键(key)匹配.

    示例:

    <cost type="call" name="compute_seller_costs" args="">
    
        <name value="name"/>
        <amount value="amount"/>
    
    </cost>
    

    TODO: documenter format methode appellée def compute_buyer_costs(self, cr, uid, ids, *args):

    • attachment: 提取属性name中对应id的资源,作为报表的图像(image).
    示例:
    <image type="attachment" name="id"/>

    示例

    XML 文件的例子:

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <transfer-list>
    
        <transfer type="fields" name="id">
    
            <name type="field" name="name"/>
            <partner_id type="field" name="partner_id.name"/>
            <date type="field" name="date"/>
            <type type="field" name="type"/>
            <reference type="field" name="reference"/>
            <amount type="field" name="amount"/>
            <change type="field" name="change"/>
    
        </transfer>
    
    </transfer-list>
    

    RML 介绍

    有关RML格式的更多信息, 请参照官方文档.

    XSL:RML 样式表

    生成报表的XSL样式表有两个可选项. 两者都可以我们自己定制, 或者,使用我们自己定制的模板(template)

    可以是freestyle,也可以用 corporate_defaults + rml_template

    引入 rml_template.xsl
    需要的模板:
    • frames?
    • stylesheet
    • story
    可选的模板:

    Translations

    OpenERP可以使用多种语言,因此报表必须可以翻译成多种语言。但是一个报表中,并不是所有项目都被翻译,比如动态的文本需要翻译转换,而格式 代码(format code)则不需要。一个字段如果包在XML标签(类似 t="1" ),翻译系统就会处理它。server会在报表生成过程中处理所有这样的字段.

    一些有用的链接

    示例 (使用公司表头 corporate defaults)

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" :xmlns:fo="http://www.w3.org/1999/XSL/Format">
    
        <xsl:import href="http://www.cnblogs.com/custom/corporate_defaults.xsl"/>
        <xsl:import href="http://www.cnblogs.com/base/report/rml_template.xsl"/>
        <xsl:variable name="page_format">a4_normal</xsl:variable>
        <xsl:template match="/">
    
            <xsl:call-template name="rml"/>
    
        </xsl:template>
        <xsl:template name="stylesheet">
    
            </xsl:template>
    
        <xsl:template name="story">
    
            <xsl:apply-templates select="transfer-list"/>
    
        </xsl:template>
        <xsl:template match="transfer-list">
    
            <xsl:apply-templates select="transfer"/>
    
        </xsl:template>
        <xsl:template match="transfer">
    
            <setNextTemplate name="other_pages"/>
            <para>
    
                Document: <xsl:value-of select="name"/>
    
            </para><para>
    
                Type: <xsl:value-of select="type"/>
    
            </para><para>
    
                Reference: <xsl:value-of select="reference"/>
    
            </para><para>
    
                Partner ID: <xsl:value-of select="partner_id"/>
    
            </para><para>
    
                Date: <xsl:value-of select="date"/>
    
            </para><para>
    
                Amount: <xsl:value-of select="amount"/>
    
            </para>
            <xsl:if test="number(change)>0">
    
                <para>
    
                    Change: <xsl:value-of select="change"/>
    
                </para>
    
            </xsl:if>
            <setNextTemplate name="first_page"/>
            <pageBreak/>
    
        </xsl:template>
    
    </xsl:stylesheet>
    

    没有公司表头( corporate header )的示例

    示例 (使用默认的公司表头 corporate defaults):

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" :xmlns:fo="http://www.w3.org/1999/XSL/Format">
         <xsl:import href="http://www.cnblogs.com/base/report/rml_template.xsl"/>
         <xsl:variable name="page_format">a4_normal</xsl:variable>
    
         <xsl:template match="/">
              <xsl:call-template name="rml"/>
         </xsl:template>
    
         <xsl:template name="stylesheet">
          </xsl:template>
    
          <xsl:template name="story">
               <xsl:apply-templates select="transfer-list"/>
          </xsl:template>
    
          <xsl:template match="transfer-list">
               <xsl:apply-templates select="transfer"/>
          </xsl:template>
    
          <xsl:template match="transfer">
               <setNextTemplate name="other_pages"/>
    
               <para>
                     Document: <xsl:value-of select="name"/>
               </para><para>
                     Type: <xsl:value-of select="type"/>
               </para><para>
                     Reference: <xsl:value-of select="reference"/>
               </para><para>
                     Partner ID: <xsl:value-of select="partner_id"/>
               </para><para>
                     Date: <xsl:value-of select="date"/>
               </para><para>
                     Amount: <xsl:value-of select="amount"/>
               </para>
    
               <xsl:if test="number(change)>0">
                    <para>
                          Change: <xsl:value-of select="change"/>
                    </para>
               </xsl:if>
    
               <setNextTemplate name="first_page"/>
              <pageBreak/>
         </xsl:template>
    </xsl:stylesheet>
    

    每个报表都有自己的公司表头( corporate header )

    示例 (使用默认的公司表头 corporate defaults):

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" :xmlns:fo="http://www.w3.org/1999/XSL/Format">
    
        <xsl:import href="http://www.cnblogs.com/custom/corporate_defaults.xsl"/>
        <xsl:import href="http://www.cnblogs.com/base/report/rml_template.xsl"/>
        <xsl:variable name="page_format">a4_normal</xsl:variable>
        .....................
        </xsl:template>
    
    </xsl:stylesheet>
    

    条形码(Bar Codes)

    RML 文件中的条形码(Barcodes)

    可以在RML 文件中使用<barCode>标签生成条形码(Barcodes)。 支持以下格式:

    • codabar
    • code11
    • code128 (如果没有指定 'code' ,则默认code128码)
    • standard39
    • standard93
    • i2of5
    • extended39
    • extended93
    • msi
    • fim
    • postnet
    • ean13
    • ean8
    • usps_4state

    你可以更改以下属性来生成自己的条形码(barcode):

    • 'code': 'char'
    • 'ratio':'float'
    • 'xdim':'unit'
    • 'height':'unit'
    • 'checksum':'bool'
    • 'quiet':'bool'

    示例:

    <barcode code="code128" xdim="28cm" ratio="2.2">`SN12345678</barcode>

    如何生成一个新的报表

    Administration -> Custom -> Low Level -> Base->Actions -> ir.actions.report.xml

    常用标签

    包含在 [[ ]] 标签中的代码是 python 代码

    代码中的内容(你可以使用的变量值)和链接 :ref:`dynamic-report-content` 描述中的相同.

    Unicode 报表

    OpenERP 5.0-rc3 中还是不能使用Unicode 报表的。症结在于OpenERP使用的PDF标准字体(14号字体,不嵌入文档,而是由pdf reader提供)Type1只含有Latin1字符.

    解决办法有三步

    • 提供 TrueType 字体,让ReportLab可以使用他们.
    • 在报表中使用Unicode之前,在ReportLab中注册TrueType 字体.
    • 在xsl和rml模板中替换旧字体名称为TrueType.

    论坛中有更详细的信息

    免费的字体 TrueType fonts

    that can be used for this purpose are in the DejaVu family. http://dejavu-fonts.org/wiki/index.php?title=Main_Page They can be installed

    • 在 ReportLab 字体目录,
    • 系统路径和 rl_config.py 中包含这个目录,
    • 在 OpenERP 安装子目录提供一个路径给ReportLab作为注册字体用.

    在文件 server/bin/report/render/rml2pdf/__init__.py 中

    import reportlab.rl_config
    reportlab.rl_config.warnOnMissingFontGlyphs = 0
    
    from reportlab.pdfbase import pdfmetrics
    from reportlab.pdfbase.ttfonts import TTFont
    import reportlab
    
    enc = 'UTF-8'
    
    #需要的字体做如下类似的重复
    pdfmetrics.registerFont(TTFont('DejaVuSans', 'DejaVuSans.ttf',enc))
    pdfmetrics.registerFont(TTFont('DejaVuSans-Bold', 'DejaVuSans-Bold.ttf',enc))
    
    from reportlab.lib.fonts import addMapping
    
    #需要的字体做如下类似的重复
    addMapping('DejaVuSans', 0, 0, 'DejaVuSans') #normal
    addMapping('DejaVuSans-Bold', 1, 0, 'DejaVuSans') #normal
    

    如果是命令行引用 trml2pdf.py ,则需要做如上修改.

    所有需要修改的 xsl 和 rml 文件

    需要修改调整的清单:

    'Times-Roman',       'DejaVuSerif.ttf'
    'Times-BoldItalic',  'DejaVuSerif-BoldItalic.ttf'
    'Times-Bold',        'DejaVuSerif-Bold.ttf'
    'Times-Italic',      'DejaVuSerif-Italic.ttf'
    
    'Helvetica',     'DejaVuSans.ttf'
    'Helvetica-BoldItalic',  'DejaVuSans-BoldOblique.ttf'
    'Helvetica-Bold',    'DejaVuSans-Bold.ttf'
    'Helvetica-Italic',  'DejaVuSans-Oblique.ttf'
    
    'Courier',           'DejaVuSansMono.ttf'
    'Courier-Bold',      'DejaVuSansMono-Bold.ttf'
    'Courier-BoldItalic','DejaVuSansMono-BoldOblique.ttf'
    'Courier-Italic',    'DejaVuSansMono-Oblique.ttf'
    
    'Helvetica-ExtraLight',  'DejaVuSans-ExtraLight.ttf'
    
    'TimesCondensed-Roman',      'DejaVuSerifCondensed.ttf'
    'TimesCondensed-BoldItalic', 'DejaVuSerifCondensed-BoldItalic.ttf'
    'TimesCondensed-Bold',       'DejaVuSerifCondensed-Bold.ttf'
    'TimesCondensed-Italic',     'DejaVuSerifCondensed-Italic.ttf'
    
    'HelveticaCondensed',        'DejaVuSansCondensed.ttf'
    'HelveticaCondensed-BoldItalic', 'DejaVuSansCondensed-BoldOblique.ttf'
    'HelveticaCondensed-Bold',   'DejaVuSansCondensed-Bold.ttf'
    'HelveticaCondensed-Italic', 'DejaVuSansCondensed-Oblique.ttf
    

    使用Mako模板的HTML报表

    Note

    只在trunk实现的

    Mako的是用Python编写一个模板库。它提供了一个熟悉的,非XML的语法,编译成Python模块以获得最佳性能.

    Mako 模板

    语法

    Mako模板可以解析 XML, HTML, email text, 等文字流(parsed from a text stream) .

    Mako模板含有Mako特有的指令(Mako-specific directives), 包括变量、表达式替换(expression substitution),控制结构(比如条件和循环,conditionals and loops),服务器端命令,完整的Python代码块,这些就像不同功能的标签(tag)一样易用。所有这些指令都解析为Python代码.

    这意味着在Mako模板中,你可以最大化发挥Python的优势.

    表达式替换

    最简单的表达式是变量替换。 Mako模板中使用 ${} 结构,而不是rml中的 [[ ]] .

    eg:

    this is x: ${x}
    
        上式被模板输出流解析(template output stream),从本地上下文(localcontext)传递给模板生成函数(template rendering function).
    
        标签 ${} 中的代码直接被Python解析.
    
    控制结构:  
    在Mako中,控制结构 (i.e. if/else, 循环 (像 while 和 for), 包括 try/except) 都使用 % 标记,之后接上普通的Python控制表达式即可。在控制结构结束时,使用 "end<name>" 标记,"<name>" 是控制结构的关键字:

    eg:

    % if x==5:
      this is some output
    % endif
    

    Python 块

    在 <% %> 标记中, 你可以加入普通的Python代码块。虽然之中的代码可以加入任意的空格,但是还是注意下格式比较好。Mako的编译器会根据周围生成的 Python代码结构,调整Python代码块中的格式.
    有用的链接:
    http://www.makotemplates.org/docs/

    销售订单中的例子

    销售完整的例子请从下面的地址参照 sale_report_html 模块 :
    https://code.launchpad.net/~openerp-community/openobject-addons/trunk-addons-community
    ## -*- coding: utf-8 -*-
    <html>
    <head>
            <%include file="mako_header.html"/>
    </head>
    % for o in objects:
    <body>
        <table width="100" border="0" cellspacing="0" cellpadding="0">
                <tr>
                        <td>
                                    <p><small><b>Shipping address :</b></small>
                            </td>
                    </tr>
                    <tr>
                            <td>
                                    <small>${ o.partner_id.title or '' } ${ o.partner_id.name }</small>
                            </td>
                    </tr>
                    <tr>
                        <td>
                                    <small>${ o.partner_shipping_id.state_id and o.partner_shipping_id.state_id.name or '' } ${ o.partner_shipping_id.country_id and o.partner_shipping_id.country_id.name or '' }</small>
                            </td>
                    </tr>
            </table>
            <table>
                       <tr align="left">
                              <th>Description</th>
                              <th>VAT</th>
                              <th>Quantity</th>
                              <th>Unit Price</th>
                              <th>Disc.(%)</th>
                              <th>Price</th>
                            </tr>
                    % for line in o.order_line:
                              <tr>
                              <td>${line.name}</p>
                              <td>${', '.join(map(lambda x: x.name, line.tax_id))}</td>
                              <td>${line.product_uos and line.product_uos_qty or line.product_uom_qty}
                              ${line.product_uos and line.product_uos.name or line.product_uom.name}</td>
                              <td>${line.price_unit}</td>
                              <td>${line.discount or 0.00 }</td>
                              <td>${line.price_subtotal or 0.00 }</td>
                              </tr>
                      % if line['notes']:
                                <tr>
                                <td>${line.notes}</td>
                                </tr>
    
                      % endif
                      % endfor
            </table>
    </body>
    % endfor
    <%include file="mako_footer.html"/>
    </html>
  • 相关阅读:
    Mac 下安装Ant
    MAMP 10.10下启动报错解决方案
    [转]常用iOS图片处理方法
    Mac下Android SDK更新不了的解决办法
    细说23+1种设计模式
    mysql应该了解的知识点
    java快排思想
    简介一下 i++和++i&&i=i+i,i+=1;的区别
    对int类型的数据,如何让获取长度
    第一次写博客
  • 原文地址:https://www.cnblogs.com/alangwansui/p/2892839.html
Copyright © 2011-2022 走看看