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>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM