mirror of
https://github.com/OCA/reporting-engine.git
synced 2025-02-16 16:30:38 +02:00
Add sql_export_excel
This commit is contained in:
108
sql_export_excel/models/sql_export.py
Normal file
108
sql_export_excel/models/sql_export.py
Normal file
@@ -0,0 +1,108 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2019 Akretion
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from openerp import api, exceptions, fields, models, _
|
||||
from cStringIO import StringIO
|
||||
import logging
|
||||
import base64
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
try:
|
||||
import openpyxl
|
||||
except ImportError:
|
||||
_logger.debug('Can not import openpyxl')
|
||||
|
||||
|
||||
class SqlExport(models.Model):
|
||||
_inherit = 'sql.export'
|
||||
|
||||
file_format = fields.Selection(
|
||||
selection_add=[('excel', 'Excel')])
|
||||
header = fields.Boolean(
|
||||
default=True,
|
||||
help="Indicate if the header should be exported to the file.")
|
||||
attachment_id = fields.Many2one(
|
||||
'ir.attachment', string='Excel Template',
|
||||
help="If you configure an excel file (in xlsx format) here, the "
|
||||
"result of the query will be injected in it.\nIt is usefull to "
|
||||
"feed data in a excel file pre-configured with calculation")
|
||||
sheet_position = fields.Integer(
|
||||
default=1,
|
||||
help="Indicate the sheet's position of the excel template where the "
|
||||
"result of the sql query should be injected.")
|
||||
row_position = fields.Integer(
|
||||
default=1,
|
||||
help="Indicate from which row the result of the query should be "
|
||||
"injected.")
|
||||
col_position = fields.Integer(
|
||||
string="Column Position",
|
||||
default=1,
|
||||
help="Indicate from which column the result of the query should be "
|
||||
"injected.")
|
||||
|
||||
@api.constrains('sheet_position')
|
||||
def check_sheet_position(self):
|
||||
for export in self:
|
||||
if export.sheet_position < 1:
|
||||
raise exceptions.ValidationError(
|
||||
_("The sheet position can't be less than 1."))
|
||||
|
||||
@api.constrains('row_position')
|
||||
def check_row_position(self):
|
||||
for export in self:
|
||||
if export.row_position < 1:
|
||||
raise exceptions.ValidationError(
|
||||
_("The row position can't be less than 1."))
|
||||
|
||||
@api.constrains('col_position')
|
||||
def check_column_position(self):
|
||||
for export in self:
|
||||
if export.col_position < 1:
|
||||
raise exceptions.ValidationError(
|
||||
_("The column position can't be less than 1."))
|
||||
|
||||
@api.multi
|
||||
def _get_file_extension(self):
|
||||
self.ensure_one()
|
||||
if self.file_format == 'excel':
|
||||
return 'xlsx'
|
||||
else:
|
||||
return super(SqlExport, self)._get_file_extension()
|
||||
|
||||
@api.multi
|
||||
def excel_get_datas_from_query(self, variable_dict):
|
||||
self.ensure_one()
|
||||
res = self._execute_sql_request(
|
||||
params=variable_dict, mode='fetchall', header=self.header)
|
||||
# Case we insert data in an existing excel file.
|
||||
if self.attachment_id:
|
||||
datas = self.attachment_id.datas
|
||||
infile = StringIO()
|
||||
infile.write(base64.b64decode(datas))
|
||||
infile.seek(0)
|
||||
wb = openpyxl.load_workbook(filename=infile)
|
||||
sheets = wb.worksheets
|
||||
try:
|
||||
ws = sheets[self.sheet_position - 1]
|
||||
except IndexError:
|
||||
raise exceptions.ValidationError(
|
||||
_("The Excel Template file contains less than %s sheets "
|
||||
"Please, adjust the Sheet Position parameter."))
|
||||
row_position = self.row_position or 1
|
||||
col_position = self.col_position or 1
|
||||
# Case of excel file creation
|
||||
else:
|
||||
wb = openpyxl.Workbook()
|
||||
ws = wb.active
|
||||
row_position = 1
|
||||
col_position = 1
|
||||
for index, row in enumerate(res, row_position):
|
||||
for col, val in enumerate(row, col_position):
|
||||
ws.cell(row=index, column=col).value = val
|
||||
output = StringIO()
|
||||
wb.save(output)
|
||||
output.getvalue()
|
||||
output_datas = base64.b64encode(output.getvalue())
|
||||
output.close()
|
||||
return output_datas
|
||||
Reference in New Issue
Block a user