前面幾篇文章,我們已經說明怎麼去創建並安裝自己的模塊。如果你跟着前幾篇去做了,那太好了,我們可以一起進行本篇文章的學習了。
本篇實際上爲新的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,
}