<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[实现Web Client上的html报表直接打印]]></title><description><![CDATA[<p dir="auto">读了一下openerp新版本的代码，的确有不少的改进。尤其是web client，基本上是推倒重写的。<br />看官方的论坛上很多人在问如何在web client上实现报表的直接打印，想想现在的打印的确是不方便，总是把文件下载下来，然后打开文件打印。<br />html的报表容易想到，因为可以直接在web client打开一个新窗口，用js进行打印。于是就改改openerp代码，实现一个简单的html报表的。供大家参考。<br />时间仓促，勿笑话。<br /><br />(我用的web client是embedded模式)<br />OE新版（6.1）的web client的整个结构和以前都不一样了，所以要先研究报表的controller.<br />在Reports类里，看到：<br /></p>
<pre><code>&lt;br /&gt;(&amp;#039;Content-Disposition&amp;#039;, &amp;#039;attachment; filename=&amp;quot;%s.%s&amp;quot;&amp;#039; % (action&amp;#91;&amp;#039;report_name&amp;#039;], report_struct&amp;#91;&amp;#039;format&amp;#039;]))&lt;br /&gt;
</code></pre>
<p dir="auto"><br />这样的http header的定义。这是要直接下载。修改先：<br /><br /></p>
<pre><code>&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; header_list = [&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;  (&amp;#039;Content-Type&amp;#039;, report_mimetype),&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;  (&amp;#039;Content-Length&amp;#039;, len(report))]&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if report_struct&amp;#91;&amp;#039;format&amp;#039;] not in &amp;#91;&amp;#039;html&amp;#039;]:&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; header_list.append((&amp;#039;Content-Disposition&amp;#039;, &amp;#039;attachment; filename=&amp;quot;%s.%s&amp;quot;&amp;#039; % (action&amp;#91;&amp;#039;report_name&amp;#039;], report_struct&amp;#91;&amp;#039;format&amp;#039;])))&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return req.make_response(report,&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;  headers=header_list,&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;  cookies={&amp;#039;fileToken&amp;#039;: int(token)})&lt;br /&gt;&lt;br /&gt;
</code></pre>
<p dir="auto"><br />没什么好说的。<br /><br />改完，重启服务，测试。发现点击报表按钮后，浏览器无任何反映，也没有打开新窗口。<br />看来6.1的确是不一样。<br />跟踪代码，发现报表这个action在web client的处理函数名为ir_actions_report_xml。<br />内部又调用：<br /></p>
<pre><code>self.session.get_file({&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; url: &amp;#039;/web/report&amp;#039;,&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; data: {action: JSON.stringify(action)},&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; complete: $.unblockUI,&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; success: function(){&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if (!self.dialog &amp;amp;&amp;amp; on_closed) {&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; on_closed();&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; self.dialog_stop();&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; },&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; error: session.webclient.crashmanager.on_rpc_error&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; })
</code></pre>
<p dir="auto"><br /><br />看名字就知道，这货肯定把所有的报表下载下来，而不是打开新窗口。考虑修改。<br /><br /></p>
<pre><code>&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; post_data = {&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; url: &amp;#039;/web/report&amp;#039;,&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; data: {action: JSON.stringify(action)},&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; complete: $.unblockUI,&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; success: function(){&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if (!self.dialog &amp;amp;&amp;amp; on_closed) {&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; on_closed();&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; self.dialog_stop();&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; },&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; error: session.webclient.crashmanager.on_rpc_error&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; };&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if(action.report_type == &amp;#039;mako2html&amp;#039;){&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; self.session.open_report_page(post_data)&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }else{&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; self.session.get_file(post_data)&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;br /&gt;
</code></pre>
<p dir="auto"><br /><br />get_file函数通过jquery调用了服务端的report view.我们也需要做同样的事情：<br /><br />在core.js里：<br /><br /></p>
<pre><code>&lt;br /&gt;&amp;nbsp; &amp;nbsp; /**&lt;br /&gt;&amp;nbsp; &amp;nbsp;  *Open an html report.&lt;br /&gt;&amp;nbsp; &amp;nbsp;  *未处理error&lt;br /&gt;&amp;nbsp; &amp;nbsp; **/&lt;br /&gt;&amp;nbsp; &amp;nbsp; open_report_page: function(options) {&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; var token = new Date().getTime();&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; params = options.data;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; params&amp;#91;&amp;#039;session_id&amp;#039;] = this.session_id;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; params&amp;#91;&amp;#039;token&amp;#039;] = token;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $.post(options.url, params, function(data){&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; report_window=window.open(&amp;#039;&amp;#039;,&amp;#039;&amp;#039;,&amp;#039;width=100,height=100&amp;#039;);&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; report_window.document.write(data);&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; report_window.focus();&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; options.complete();&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if (options.success) { options.success(); }&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; });&lt;br /&gt;&amp;nbsp; &amp;nbsp; },&lt;br /&gt;
</code></pre>
<p dir="auto"><br /><br />ok, 可以在报表模板里写任何js东西，包括打印的代码。<br />我并不是用js代码直接打印，是通过Lodop控件，推荐大家使用。<br />可以直接打印，套打，导出excel。。。。<br /><br /><br />至此，就可以完成html报表的直接打印了。<br /><br /></p>
]]></description><link>https://odoo.net.cn/topic/1553/实现web-client上的html报表直接打印</link><generator>RSS for Node</generator><lastBuildDate>Mon, 05 Oct 2026 15:47:16 GMT</lastBuildDate><atom:link href="https://odoo.net.cn/topic/1553.rss" rel="self" type="application/rss+xml"/><pubDate>Fri, 30 Mar 2012 05:21:35 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to 实现Web Client上的html报表直接打印 on Sat, 31 Mar 2012 04:46:58 GMT]]></title><description><![CDATA[<p dir="auto">[quote author=Joshua link=topic=2860.msg9638#msg9638 date=1333120570]<br />好文！感谢lz的分享<br />[/quote]<br /><br />看来web可能会长期作为一个模块作为存在。<br />而现在看，web模块的精华，在一大堆的js文件里。唉,难搞。</p>
]]></description><link>https://odoo.net.cn/post/11588</link><guid isPermaLink="true">https://odoo.net.cn/post/11588</guid><dc:creator><![CDATA[d_yang]]></dc:creator><pubDate>Sat, 31 Mar 2012 04:46:58 GMT</pubDate></item><item><title><![CDATA[Reply to 实现Web Client上的html报表直接打印 on Fri, 30 Mar 2012 15:16:10 GMT]]></title><description><![CDATA[<p dir="auto">好文！感谢lz的分享</p>
]]></description><link>https://odoo.net.cn/post/11586</link><guid isPermaLink="true">https://odoo.net.cn/post/11586</guid><dc:creator><![CDATA[Joshua]]></dc:creator><pubDate>Fri, 30 Mar 2012 15:16:10 GMT</pubDate></item><item><title><![CDATA[Reply to 实现Web Client上的html报表直接打印 on Fri, 30 Mar 2012 13:39:23 GMT]]></title><description><![CDATA[<p dir="auto">组织学习一下 web 的源码就更棒了....</p>
]]></description><link>https://odoo.net.cn/post/11585</link><guid isPermaLink="true">https://odoo.net.cn/post/11585</guid><dc:creator><![CDATA[mrshelly]]></dc:creator><pubDate>Fri, 30 Mar 2012 13:39:23 GMT</pubDate></item></channel></rss>