openerp模块收藏 基于Lodop的报表打印模块(转载)
基于Lodop的报表打印模块
原文:http://shine-it.net/index.php/topic,7397.0.html
前段时间写了个小模块,来解决OE中报表打印不方便的问题。
借鉴了 @buke 兄的 openerp-web-pdf-preview-print 模块的部分代码。
介绍:
Lodop是一款优秀的国产打印控件(activeX): http://mtsoftware.v053.gokao.net/download.html
ActiveX只支持windows,所以本控件不适用linux,mac osx.
模块使用mako标签,html的模版。
我只贴代码,不加附件,这样各位会体会更深。
模块结构:
__openerp__.py
程序代码:
{ "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, }
服务端的controller(没啥一样的,继续借鉴@buke):
程序代码:
# -*- 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)
主要部分是js部分:
程序代码:
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(); } }); }); }, }); };
安装后,本模块将会替代系统默认的报表动作。
使用方法:
程序代码:
<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"/>
因为需要确定打印的范围,所以借用了attachment这个属性----实在是不想修改系统的rng文件了。
* 这就是刚才代码 “format_obj = action.attachment.split(',');” 这一行的原因。
mako的html模版大概是这样的:
程序代码:
# -*- 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'] } 开单日期:${ o.date_order } </td> <td colspan="4"> 业务部确认: ${ o['confirmer_id']['name'] } 业务经办人:${ 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
注意:
1. 模版只包含table标签,支持多table(多单打印)。
2. lodop的使用方法请参看其文档。
大功告成。
献丑了。如需改进,有问题请 @杨振宇_
lodop里,addprinttable方法可以把table里面 <theader>标签转为你说的,表头,tfoot标签转换为页脚。
tbody里,就是明细部分了,自动根据页面高度分页。
另外lodop还支持一些标签,比如,总页数,当前页数,数字大写转换,统计,等。