Odoo中文社区可以通过以下三个域名访问:shine-it.net , odoocn.org,odoo.net.cn

原论坛用户的基本信息和发帖这里都予以保留,请注意:原论坛用户无需重新注册新用户,但是您的密码需要重置

开发人员可以登录gitter讨论组: http://gitter.im/odoo-china/Talk, 需要github账号

如果您登录系统碰到问题,请在微信公众号留言:

基于Lodop的报表打印模块



  • 前段时间写了个小模块,来解决OE中报表打印不方便的问题。
    借鉴了 @buke 兄的 openerp-web-pdf-preview-print 模块的部分代码。

    介绍:
    Lodop是一款优秀的国产打印控件(activeX): [url=http://mtsoftware.v053.gokao.net/download.html]http://mtsoftware.v053.gokao.net/download.html[/url]
    ActiveX只支持windows,所以本控件不适用linux,mac osx.

    模块使用mako标签,html的模版。

    我只贴代码,不加附件,这样各位会体会更深。

    模块结构:
    [attach=1]


    openerp.py

    [code]
    {
        "name": "Lodop控件报表",
        "category": "web",
        "description":
            """
            Lodop控件模块, 针对于报表。
            """,
        "version": "6.0.5.6",
        "depends": [],
        "js": ["static/lib/Lodop6.145/.js", "static/js/.js"],
        'active':True,
        'installable': True,
        'active': False,
        'application':False,
    }

    [/code]


    服务端的controller(没啥一样的,继续借鉴@buke):

    [code]
    # -- coding: utf-8 --


    import openerp.addons.web.http as openerpweb
    from openerp.addons.web.controllers.main import View

    import urllib2
    import simplejson
    import base64
    import time
    import zlib
    import cPickle
    import hashlib


    class LodopReport(View):
        _cp_path = "/web/lodop/report"
        POLLING_DELAY = 0.25

        @openerpweb.jsonrequest
        def index(self, req, action):
            action = simplejson.loads(action)
            report_srv = req.session.proxy("report")
            context = dict(req.context)
            context.update(action["context"])
            report_data = {}
            report_ids = context["active_ids"]
            if 'report_type' in action:
                report_data['report_type'] = action['report_type']
            if 'datas' in action:
                if 'ids' in action['datas']:
                    report_ids = action['datas'].pop('ids')
                report_data.update(action['datas'])
            report_id = report_srv.report(
                req.session._db, req.session._uid, req.session._password,
                action["report_name"], report_ids,
                report_data, context)
            report_struct = None
            while True:
                report_struct = report_srv.report_get(
                    req.session._db, req.session._uid, req.session._password, report_id)
                if report_struct["state"]:
                    break
                time.sleep(self.POLLING_DELAY)

            report = base64.b64decode(report_struct['result'])
            return dict(report = report)

    [/code]


    主要部分是js部分:
    [code]

    openerp.fg_lodop = function(instance) {

        instance.web.ActionManager = instance.web.ActionManager.extend({

            init: function (parent, action) {
                this._super(parent);
                //activex的标签放在页面里。
                var obj_string = '<object style="width:0px;height:0px;" id="LODOP_OB" classid="clsid:2105C259-1E0C-4534-8141-A753534CB4CA" width=0 height=0><embed id="LODOP_EM" type="application/x-print-lodop" width=0 height=0 pluginspage="/fg_lodop/static/lib/lodop6.145/install_lodop32.exe"></embed></object>';
                $(obj_string).appendTo("body");
            },
           
            ir_actions_report_xml: function(action, options) {
                var self = this;
                instance.web.blockUI();
                return instance.web.pyeval.eval_domains_and_contexts({
                    contexts: [action.context],
                    domains: []
                }).then(function(res) {
                    action = .clone(action);
                    action.context = res.context;
                    var os = navigator.platform || "Unknown OS";
                    linux = os.indexOf("Linux") > -1;
                    mac = os.indexOf("Mac") > -1;

                    self.rpc("/web/lodop/report", {
                        action: JSON.stringify(action)
                    }).done(function(result) {
                        if(result.error){
                            instance.web.unblockUI();
                            self.dialog_stop();
                            return;
                        }
                        instance.web.unblockUI();
                        self.dialog_stop();
                        if(linux || mac) {
                            //不支持linux, mac, 这点没考虑过。
                            report_window=window.open('','','width=600,height=500');
                            report_window.document.write(result.report);
                            report_window.focus();
                        }
                        else {
                            //do magic.
                            // 等会解释这个由来。
                            format_obj = action.attachment.split(',');

                            LODOP=getLodop(document.getElementById('LODOP'),document.getElementById('LODOP_EM')); 
                            LODOP.SET_LICENSES("","xxxxxx","","");  //不设置授权码照样可以打印。
                            LODOP.PRINT_INIT("FG ERP Order");
                            LODOP.SET_PRINT_PAGESIZE(1, 2300, 1390, 'fg_lodop_print_job'); //公司用的各种单据的打印纸都是统一规格,所以写死了。
                           
                            var tables = $.parseHTML(result.report);
                            $.each( tables, function( i, el ) {
                                if(el.nodeName == "TABLE"){
                                    LODOP.ADD_PRINT_TABLE(format_obj[0],format_obj[1],format_obj[2], format_obj[3], el.outerHTML);
                                    LODOP.NEWPAGE();
                                }
                            });
                            LODOP.PREVIEW();
                        }
                    });
                });
            },
        });


    };



    [/code]


    安装后,本模块将会替代系统默认的报表动作。

    使用方法:

    [code]

    <report auto="False" id="report_fg_sale_cust_order_html" model="fg_sale.cust.order"
                    name="fg_sale.cust.order.html" rml="fg_sale/report/cust_order.html"
                    string="定制单" report_type="mako2html" attachment="0mm,0mm,220mm,98mm"/>

    [/code]

    因为需要确定打印的范围,所以借用了attachment这个属性----实在是不想修改系统的rng文件了。
    * 这就是刚才代码 “format_obj = action.attachment.split(',');” 这一行的原因。


    mako的html模版大概是这样的:


    [code]
    # -- coding: utf-8 --
        % for o in objects:
            % if o.state == 'review':
                        <table border="0" cellspacing="2" cellpadding="2" bordercolor="#000000" style="font-size:14px;width:850px;">
                          <thead>
                              <tr>
                                <td colspan="8" align="center">
                                  <span style="font-size:18px;font-weight:bold;">定制清单  </span> ${ o.name }</td>
                              </tr>
                              <tr>
                                  <td colspan="1"  height="18">客户名称:
                                    ${ o.partner_id.name }
                                  </td>
                                  <td colspan="3"  height="18">要求到货日期: ${ o.date_arrival_req or '' }</td>
                                  <td colspan="4" height="18">
                                      交货日期: ${ o.date_delivery or '' }
                                  </td>
                              </tr>
                              % if o.contact or o.phone or o.delivery_addr:
                              <tr>
                                <td colspan="1">联系人: ${ o.contact or '' }</td>
                                <td colspan="3">联系电话: ${ o.phone or '' }</td>
                                <td colspan="3">交货地址: ${ o.delivery_addr or '' }</td>
                              </tr>
                              % endif
                              <tr>
                                <td colspan="1">已付金额: ${ o.amount_paid or '' }</td>
                                <td colspan="3">付款方式: ${ o.amount_paid_method or '' }</td>
                                <td colspan="3">发票:
                                  % if o.invoice_type == 'common':
                                  普通发票
                                  % elif o.invoice_type == 'va':
                                  增值发票
                                  % else:
                                  暂不开票
                                  % endif
                                </td>
                              </tr>
                              <tr>
                                <td colspan="1">定制版面:  ${ o.client }</td>
                                <td colspan="3">运费承担方: ${ o.delivery_fee or '' }</td>
                                <td colspan="3">送货方式: ${ o.delivery_method or '' }</td>
                              </tr>
                              <tr height="18">
                            <td style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;" align="center">品名</td>
                            <td style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;" align="center">数量(只)</td>
                                <td style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;" align="center">开票价</td>
                                <td style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;" align="center">版费</td>
                                <td style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;" align="center">已发货</td>
                                <td style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;" align="center">小计</td>
                                <td style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;" align="center">附注</td>
                              </tr>
                          </thead>
                          <tbody>
                              % for line in o.order_line:
                              <tr>
                                  <td height="18" style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;" >${ line.product_id.name }</td>
                                  <td width="10%" height="18" style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;">${ line.product_uom_qty }</td>
                                  <td width="10%" height="18" style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;" >${ line.unit_price }</td>
                                  <td width="10%" height="18" style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;">${ line.cust_price }</td>
                                  <td width="10%" height="18" style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;">${ line.delivered and '是' or '否' }</td>
                                  <td width="10%" height="18" style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;">${ line.subtotal_amount }</td>
                                  <td width="20%" height="18" style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;">${ line.note or '' }</td>
                                </tr>
                              % endfor
                          </tbody>
                          <tfoot>
                              <tr>
                                <td colspan="1" style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;text-align:right;" tdata="allSum" format="#,##0.00" tindex="6">
                                    共计: #
                                </td>
                                <td colspan="4" style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;" tdata="allSum" format="UpperMoney" tindex="6">
                                    #
                                </td>
                                <td colspan="2" style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;" tdata="subSum" format="#,##0.00">
                                    本页小计: #
                                </td>
                              </tr>
                              <tr>
                                  <td colspan="2">
                                    开单人: ${ o['user_id']['name'] } &nbsp;&nbsp;
                                    开单日期:${ o.date_order }
                                  </td>
                                  <td colspan="4">
                                    业务部确认: ${ o['confirmer_id']['name'] }&nbsp;&nbsp;
                                    业务经办人:${ o.employee_id.name }
                                  </td>
                                  <td colspan="1" style="font-size:14px;height:18px;text-align:right;">第<span tdata="pageNO" format="#">#</span>页-共<span tdata="pageCount" format="#">#</span>页</td>
                              </tr>
                          </tfoot>
                        </table>
                % endif
          % endfor
    [/code]


    注意:
    1. 模版只包含table标签,支持多table(多单打印)。
    2. lodop的使用方法请参看其文档。


    大功告成。

    献丑了。如需改进,有问题请 @杨振宇






  • 前段时间写了个小模块,来解决OE中报表打印不方便的问题。
    借鉴了 @buke 兄的 openerp-web-pdf-preview-print 模块的部分代码。

    介绍:
    Lodop是一款优秀的国产打印控件(activeX): [url=http://mtsoftware.v053.gokao.net/download.html]http://mtsoftware.v053.gokao.net/download.html[/url]
    ActiveX只支持windows,所以本控件不适用linux,mac osx.

    模块使用mako标签,html的模版。

    我只贴代码,不加附件,这样各位会体会更深。

    模块结构:
    [attach=1]


    openerp.py

    [code]
    {
        "name": "Lodop控件报表",
        "category": "web",
        "description":
            """
            Lodop控件模块, 针对于报表。
            """,
        "version": "6.0.5.6",
        "depends": [],
        "js": ["static/lib/Lodop6.145/.js", "static/js/.js"],
        'active':True,
        'installable': True,
        'active': False,
        'application':False,
    }

    [/code]


    服务端的controller(没啥一样的,继续借鉴@buke):

    [code]
    # -- coding: utf-8 --


    import openerp.addons.web.http as openerpweb
    from openerp.addons.web.controllers.main import View

    import urllib2
    import simplejson
    import base64
    import time
    import zlib
    import cPickle
    import hashlib


    class LodopReport(View):
        _cp_path = "/web/lodop/report"
        POLLING_DELAY = 0.25

        @openerpweb.jsonrequest
        def index(self, req, action):
            action = simplejson.loads(action)
            report_srv = req.session.proxy("report")
            context = dict(req.context)
            context.update(action["context"])
            report_data = {}
            report_ids = context["active_ids"]
            if 'report_type' in action:
                report_data['report_type'] = action['report_type']
            if 'datas' in action:
                if 'ids' in action['datas']:
                    report_ids = action['datas'].pop('ids')
                report_data.update(action['datas'])
            report_id = report_srv.report(
                req.session._db, req.session._uid, req.session._password,
                action["report_name"], report_ids,
                report_data, context)
            report_struct = None
            while True:
                report_struct = report_srv.report_get(
                    req.session._db, req.session._uid, req.session._password, report_id)
                if report_struct["state"]:
                    break
                time.sleep(self.POLLING_DELAY)

            report = base64.b64decode(report_struct['result'])
            return dict(report = report)

    [/code]


    主要部分是js部分:
    [code]

    openerp.fg_lodop = function(instance) {

        instance.web.ActionManager = instance.web.ActionManager.extend({

            init: function (parent, action) {
                this._super(parent);
                //activex的标签放在页面里。
                var obj_string = '<object style="width:0px;height:0px;" id="LODOP_OB" classid="clsid:2105C259-1E0C-4534-8141-A753534CB4CA" width=0 height=0><embed id="LODOP_EM" type="application/x-print-lodop" width=0 height=0 pluginspage="/fg_lodop/static/lib/lodop6.145/install_lodop32.exe"></embed></object>';
                $(obj_string).appendTo("body");
            },
           
            ir_actions_report_xml: function(action, options) {
                var self = this;
                instance.web.blockUI();
                return instance.web.pyeval.eval_domains_and_contexts({
                    contexts: [action.context],
                    domains: []
                }).then(function(res) {
                    action = .clone(action);
                    action.context = res.context;
                    var os = navigator.platform || "Unknown OS";
                    linux = os.indexOf("Linux") > -1;
                    mac = os.indexOf("Mac") > -1;

                    self.rpc("/web/lodop/report", {
                        action: JSON.stringify(action)
                    }).done(function(result) {
                        if(result.error){
                            instance.web.unblockUI();
                            self.dialog_stop();
                            return;
                        }
                        instance.web.unblockUI();
                        self.dialog_stop();
                        if(linux || mac) {
                            //不支持linux, mac, 这点没考虑过。
                            report_window=window.open('','','width=600,height=500');
                            report_window.document.write(result.report);
                            report_window.focus();
                        }
                        else {
                            //do magic.
                            // 等会解释这个由来。
                            format_obj = action.attachment.split(',');

                            LODOP=getLodop(document.getElementById('LODOP'),document.getElementById('LODOP_EM')); 
                            LODOP.SET_LICENSES("","xxxxxx","","");  //不设置授权码照样可以打印。
                            LODOP.PRINT_INIT("FG ERP Order");
                            LODOP.SET_PRINT_PAGESIZE(1, 2300, 1390, 'fg_lodop_print_job'); //公司用的各种单据的打印纸都是统一规格,所以写死了。
                           
                            var tables = $.parseHTML(result.report);
                            $.each( tables, function( i, el ) {
                                if(el.nodeName == "TABLE"){
                                    LODOP.ADD_PRINT_TABLE(format_obj[0],format_obj[1],format_obj[2], format_obj[3], el.outerHTML);
                                    LODOP.NEWPAGE();
                                }
                            });
                            LODOP.PREVIEW();
                        }
                    });
                });
            },
        });


    };



    [/code]


    安装后,本模块将会替代系统默认的报表动作。

    使用方法:

    [code]

    <report auto="False" id="report_fg_sale_cust_order_html" model="fg_sale.cust.order"
                    name="fg_sale.cust.order.html" rml="fg_sale/report/cust_order.html"
                    string="定制单" report_type="mako2html" attachment="0mm,0mm,220mm,98mm"/>

    [/code]

    因为需要确定打印的范围,所以借用了attachment这个属性----实在是不想修改系统的rng文件了。
    * 这就是刚才代码 “format_obj = action.attachment.split(',');” 这一行的原因。


    mako的html模版大概是这样的:


    [code]
    # -- coding: utf-8 --
        % for o in objects:
            % if o.state == 'review':
                        <table border="0" cellspacing="2" cellpadding="2" bordercolor="#000000" style="font-size:14px;width:850px;">
                          <thead>
                              <tr>
                                <td colspan="8" align="center">
                                  <span style="font-size:18px;font-weight:bold;">定制清单  </span> ${ o.name }</td>
                              </tr>
                              <tr>
                                  <td colspan="1"  height="18">客户名称:
                                    ${ o.partner_id.name }
                                  </td>
                                  <td colspan="3"  height="18">要求到货日期: ${ o.date_arrival_req or '' }</td>
                                  <td colspan="4" height="18">
                                      交货日期: ${ o.date_delivery or '' }
                                  </td>
                              </tr>
                              % if o.contact or o.phone or o.delivery_addr:
                              <tr>
                                <td colspan="1">联系人: ${ o.contact or '' }</td>
                                <td colspan="3">联系电话: ${ o.phone or '' }</td>
                                <td colspan="3">交货地址: ${ o.delivery_addr or '' }</td>
                              </tr>
                              % endif
                              <tr>
                                <td colspan="1">已付金额: ${ o.amount_paid or '' }</td>
                                <td colspan="3">付款方式: ${ o.amount_paid_method or '' }</td>
                                <td colspan="3">发票:
                                  % if o.invoice_type == 'common':
                                  普通发票
                                  % elif o.invoice_type == 'va':
                                  增值发票
                                  % else:
                                  暂不开票
                                  % endif
                                </td>
                              </tr>
                              <tr>
                                <td colspan="1">定制版面:  ${ o.client }</td>
                                <td colspan="3">运费承担方: ${ o.delivery_fee or '' }</td>
                                <td colspan="3">送货方式: ${ o.delivery_method or '' }</td>
                              </tr>
                              <tr height="18">
                            <td style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;" align="center">品名</td>
                            <td style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;" align="center">数量(只)</td>
                                <td style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;" align="center">开票价</td>
                                <td style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;" align="center">版费</td>
                                <td style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;" align="center">已发货</td>
                                <td style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;" align="center">小计</td>
                                <td style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;" align="center">附注</td>
                              </tr>
                          </thead>
                          <tbody>
                              % for line in o.order_line:
                              <tr>
                                  <td height="18" style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;" >${ line.product_id.name }</td>
                                  <td width="10%" height="18" style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;">${ line.product_uom_qty }</td>
                                  <td width="10%" height="18" style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;" >${ line.unit_price }</td>
                                  <td width="10%" height="18" style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;">${ line.cust_price }</td>
                                  <td width="10%" height="18" style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;">${ line.delivered and '是' or '否' }</td>
                                  <td width="10%" height="18" style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;">${ line.subtotal_amount }</td>
                                  <td width="20%" height="18" style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;">${ line.note or '' }</td>
                                </tr>
                              % endfor
                          </tbody>
                          <tfoot>
                              <tr>
                                <td colspan="1" style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;text-align:right;" tdata="allSum" format="#,##0.00" tindex="6">
                                    共计: #
                                </td>
                                <td colspan="4" style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;" tdata="allSum" format="UpperMoney" tindex="6">
                                    #
                                </td>
                                <td colspan="2" style="BORDER-COLLAPSE: collapse; BORDER:groove 1px;" tdata="subSum" format="#,##0.00">
                                    本页小计: #
                                </td>
                              </tr>
                              <tr>
                                  <td colspan="2">
                                    开单人: ${ o['user_id']['name'] } &nbsp;&nbsp;
                                    开单日期:${ o.date_order }
                                  </td>
                                  <td colspan="4">
                                    业务部确认: ${ o['confirmer_id']['name'] }&nbsp;&nbsp;
                                    业务经办人:${ o.employee_id.name }
                                  </td>
                                  <td colspan="1" style="font-size:14px;height:18px;text-align:right;">第<span tdata="pageNO" format="#">#</span>页-共<span tdata="pageCount" format="#">#</span>页</td>
                              </tr>
                          </tfoot>
                        </table>
                % endif
          % endfor
    [/code]


    注意:
    1. 模版只包含table标签,支持多table(多单打印)。
    2. lodop的使用方法请参看其文档。


    大功告成。

    献丑了。如需改进,有问题请 @杨振宇






  • ActiveX只支持windows,所以本控件不适用linux,mac osx.
    是不是指客户端只能在WINDOWS上,还是服务器必须在WINDOWS上?



  • 又见大作


  • 管理员

    mako模板能重复表头么?



  • 重复表头是?

    是由lodop完成的。页眉页脚。



  • [quote author=dquo link=topic=7397.msg16900#msg16900 date=1373108877]
    ActiveX只支持windows,所以本控件不适用linux,mac osx.
    是不是指客户端只能在WINDOWS上,还是服务器必须在WINDOWS上?
    [/quote]
    sorry, 没说清楚。
    客户端不支持非Windows.



  • [quote author=Joshua link=topic=7397.msg16902#msg16902 date=1373109235]
    mako模板能重复表头么?
    [/quote]

    lodop里,addprinttable方法可以把table里面 <theader>标签转为你说的,表头,tfoot标签转换为页脚。
    tbody里,就是明细部分了,自动根据页面高度分页。

    另外lodop还支持一些标签,比如,总页数,当前页数,数字大写转换,统计,等。



  • [quote author=ccdos link=topic=7397.msg16901#msg16901 date=1373109017]
    又见大作
    [/quote]

    不敢,自己方便,也希望与人方便。


  • 管理员

    [quote author=d_yang link=topic=7397.msg16907#msg16907 date=1373119368]
    [quote author=Joshua link=topic=7397.msg16902#msg16902 date=1373109235]
    mako模板能重复表头么?
    [/quote]

    lodop里,addprinttable方法可以把table里面 <theader>标签转为你说的,表头,tfoot标签转换为页脚。
    tbody里,就是明细部分了,自动根据页面高度分页。

    另外lodop还支持一些标签,比如,总页数,当前页数,数字大写转换,统计,等。
    [/quote]

    好东西。谢谢@d_yang分享。



  • 先留记号,慢慢研究,谢谢分享 ~



  • mark,马上研究报表开发了



  • ActiveX 代码不开源的哦?
    会不会存在一些安全漏洞?
    我看API有一些关于硬件操作的东西...



  • [quote author=mrshelly link=topic=7397.msg16915#msg16915 date=1373239851]
    ActiveX 代码不开源的哦?
    会不会存在一些安全漏洞?
    我看API有一些关于硬件操作的东西...
    [/quote]

    未知。
    这个控件用两年了,本想自己写一个,但是这个确实很方便。
    如果不是为了进行硬件操作,activex就省了。 ;D



  • 跟rml 区别不是很大的样子



  • 首先,非常感谢 LZ 的 分享大作。 刚好在弄打印这块,而且还真的是要用lodop来做这个。 所以受益匪浅。
    然后,这里有个问题,想跟LZ请教下,

    在使用以下我的sample.mako模板代码时,发现maktohtml2html.py文件中的 方法 format_body中,有一个问题。

    body[:-1]得到是一个空的list, 因为 body = html.findall("body"), 对于一个Html文件来说, <body>标签只有1个。 所以这个我觉得是个问题,不知道LZ是什么解决的? 我一个小打算,是直接提bug,修改openerp的源码来搞定这件事情。 不知道还有其他的方法没有?

    openerp 的源码部分:

        def format_body(self, html):
            body = html.findall('body')
            body_list = []
            footer =  self.format_footer(body[-1].getchildren())
            for b in body[:-1]:
                body_list.append(etree.tostring(b).replace('\t', '').replace('\n',''))


    mako文件的代码。(文件名不是html,在openerp报告中没有问题。)
    <html>
    <head>
    <title>test mako template</title>
    </head>
    <body>

    <table>
    order_number: 12345
    </table>

    <footer>
    </footer>
    </body>
    </html>


登录后回复
 

与 Odoo 中文社区 的连接断开,我们正在尝试重连,请耐心等待