前面几篇文章,我们已经说明怎么去创建并安装自己的模块。如果你跟着前几篇去做了,那太好了,我们可以一起进行本篇文章的学习了。
本篇实际上为新的odoo开发者说明,如何在odoo中,使用第三方包将数据导出到Excel。事实上,odoo已经提供了数据的Excel导入和导出数据到Excel功能。也许你要问了,既然odoo已经提供了数据的导入导出,那为什么我们还要在这里看这篇文章学习如何自己定义导出数据到EXCEL。
学习自定义导出数据的一个原因是odoo提供的导出,在某些特殊的需求面前,并不能将需求所需要的字段完全展现出来。
举个例子,就是之前系统开发时,数据结构设计的不是很理想,有些该关联的字段没有关联,只是用了个Char类型的字段作为连接某两张表的桥梁,并没有many2one字段关联起来。这时候,在使用odoo提供的导出功能时,因为没有关联关系,是满足不了用户需求的。
再举个例子,如果说一本图书有好几个标签(many2many),但有个需求是,图书的多个标签,用某些符号隔开,放进一列。如果这时你用odoo的导出功能,他不会把所有标签拼接成一列,而是导出到Excel时是多行。总之就是odoo提供的功能满足不了用户需求了,我们才去自定义。
本文将继续在之前的图书管理模块上做开发演示,我将导出图书出版时间在某个时间段内的图书记录。将使用 xlwt 库做演示。
先使用models.TransientModel 做一个导出条件的向导,在zerone_inherit模块下创建文件夹wizard,并创建文件 __init__.py、export_books_data.py 和 export_books_data.xml 文件
__init__.py
# -*- coding: utf-8 -*-
from . import export_books_data
export_books_data.py
from odoo import api, fields, models, _
import xlwt
class ExportBooksData(models.TransientModel):
_name = "export.books.data"
start_date = fields.Date(string="开始时间")
end_date = fields.Date(string="结束时间")
already_export = fields.Boolean(string='已导出')
file_name = fields.Char(string='文件名称', store=True)
xls_file = fields.Binary(string='点击下载', attachment=True)
export_books_data.xml
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="export_book_data_form_view" model="ir.ui.view">
<field name="name">export.books.data.form</field>
<field name="type">form</field>
<field name="model">export.books.data</field>
<field name="priority" eval="20"/>
<field name="arch" type="xml">
<form>
<group>
<field name="start_date" required="1"/>
<field name="end_date" required="1"/>
</group>
<field name="file_name" invisible="1"/>
<field name="already_export" invisible="1"/>
<div attrs="{'invisible': [('already_export', '!=', True)]}">
<separator/>
<p>
点击下载:<field name="xls_file" readonly="1" filename="file_name"/>
</p>
</div>
<footer>
<button name='export_file' string='导出' type='object' class='oe_highlight'/>
<button string="取消" class="oe_link" special="cancel" />
</footer>
</form>
</field>
</record>
<!--action-->
<record id="action_export_books_data" model="ir.actions.act_window">
<field name="name">导出图书数据</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">export.books.data</field>
<field name="view_mode">form</field>
<field name="context">{}</field>
<field name="target">new</field>
</record>
<!--menu-->
<menuitem id="menu_export_books_data"
action="action_export_books_data" name="导出图书数据"
parent="zerone_books.menu_books_root" sequence="150"/>
</odoo>
为导出向导编写导出方法 : export_file 。继续在 export_books_data.py 文件中添加
# -*- coding: utf-8 -*-
import base64
import io
from odoo import api, fields, models, _
import xlwt
class ExportBooksData(models.TransientModel):
_name = "export.books.data"
start_date = fields.Date(string="开始时间")
end_date = fields.Date(string="结束时间")
already_export = fields.Boolean(string='已导出')
file_name = fields.Char(string='文件名称', store=True)
xls_file = fields.Binary(string='点击下载数据汇总', attachment=True)
@staticmethod
def _get_tags_string(book):
tags = book.tags_ids.mapped("name")
tags_str = "、".join(tags)
return tags_str
# 返回header
def _sheet_header(self):
header_list = [
['图书编号', '图书名称', '作者', '出版时间', '标签']
]
return header_list
# 返回data
def _sheet_content(self):
content_list = []
books = self.sudo().env['zerone.book'].search([
("publish_date", "<=", self.end_date),
("publish_date", ">=", self.start_date)
])
for book in books:
content_list.append([
book.code,
book.name,
book.author,
book.publish_date.strftime('%Y-%m-%d'),
self._get_tags_string(book)
])
return content_list
def export_file(self):
result = self._sheet_header() + self._sheet_content()
wbk = xlwt.Workbook()
sheet = wbk.add_sheet('Sheet1', cell_overwrite_ok=True)
style = xlwt.XFStyle()
# 居中
al = xlwt.Alignment()
al.horz = 0x02
al.vert = 0x01
style.alignment = al
# 外边框
borders = xlwt.Borders()
borders.left = 1
borders.right = 1
borders.top = 1
borders.bottom = 1
borders.bottom_colour = 0x3A
style.borders = borders
# 字体
font = xlwt.Font()
font.name = u'微软雅黑'
font.height = 220
style.font = font
for i in range(len(result)):
for j in range(len(result[i])):
sheet.write(i, j, result[i][j], style)
fp = io.BytesIO()
wbk.save(fp)
fp.seek(0)
data = fp.read()
fp.close()
file_name = "%s-%s 图书数据.xls" % (str(self.start_date), str(self.end_date))
self.write({'already_export': True, 'xls_file': base64.b64encode(data), 'file_name': file_name})
return {
'type': 'ir.actions.act_window',
'view_mode': 'form',
'res_model': 'export.books.data',
'target': 'new',
'res_id': self.id,
}