Browse Source

8.0 port of report_xls module

pull/5/head
luc-demeyer 10 years ago
parent
commit
74c3afa363
  1. 1
      __unported__/report_xls/__init__.py
  2. 28
      __unported__/report_xls/__openerp__.py
  3. 65
      __unported__/report_xls/report_xls.py
  4. BIN
      __unported__/report_xls/static/src/img/icon.png
  5. 3
      __unported__/report_xls/utils.py
  6. 25
      report_xls/__init__.py
  7. 82
      report_xls/__openerp__.py
  8. 36
      report_xls/ir_report.py
  9. 249
      report_xls/report_xls.py
  10. BIN
      report_xls/static/description/help.png
  11. BIN
      report_xls/static/description/icon.png
  12. BIN
      report_xls/static/description/icon2.png
  13. 84
      report_xls/static/description/index.html
  14. BIN
      report_xls/static/description/open_receivables.png
  15. 51
      report_xls/utils.py

1
__unported__/report_xls/__init__.py

@ -20,5 +20,6 @@
#
##############################################################################
from . import ir_report
from . import report_xls
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

28
__unported__/report_xls/__openerp__.py

@ -21,7 +21,7 @@
##############################################################################
{
'name': 'Excel report engine',
'version': '0.4.1',
'version': '0.6',
'license': 'AGPL-3',
'author': 'Noviat',
'website': 'http://www.noviat.com',
@ -30,7 +30,8 @@
Excel report engine
===================
This module adds Excel export capabilities to the standard OpenERP reporting engine.
This module adds Excel export capabilities to the standard odoo reporting
engine.
Report development
''''''''''''''''''
@ -38,8 +39,8 @@ In order to create an Excel report you can\n
- define a report of type 'xls'
- pass ``{'xls_export': 1}`` via the context to the report create method
The ``report_xls`` class contains a number of attributes and methods to facilitate
the creation XLS reports in OpenERP.
The ``report_xls`` class contains a number of attributes and methods to
facilitate the creation XLS reports in OpenERP.
* cell types
@ -52,28 +53,29 @@ the creation XLS reports in OpenERP.
* cell formulas
Cell formulas can be easily added with the help of the ``rowcol_to_cell()`` function which
you can import from the ``utils.py`` module.
Cell formulas can be easily added with the help of the ``rowcol_to_cell()``
function which you can import from the ``utils.py`` module.
* Excel templates
It is possible to define Excel templates which can be adapted by 'inherited' modules.
Download the ``account_move_line_report_xls`` module from http://apps.openerp.com
as example.
It is possible to define Excel templates which can be adapted
by 'inherited' modules.
Download the ``account_move_line_report_xls`` module
from http://apps.odoo.com as example.
* XLS with multiple sheets
Download the ``account_journal_report_xls`` module from http://apps.openerp.com as example.
Download the ``account_journal_report_xls`` module
from http://apps.odoo.com as example.
Development assistance
''''''''''''''''''''''
Contact info@noviat.com for help with the development of Excel reports in OpenERP.
Contact info@noviat.com for help with the development of
Excel reports in odoo.
""",
'depends': ['base'],
'external_dependencies': {'python': ['xlwt']},
'demo': [],
'data': [],
'active': False,
'installable': False,
}

65
__unported__/report_xls/report_xls.py

@ -3,7 +3,7 @@
#
# OpenERP, Open Source Management Solution
#
# Copyright (c) 2013 Noviat nv/sa (www.noviat.com). All rights reserved.
# Copyright (c) 2014 Noviat nv/sa (www.noviat.com). All rights reserved.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@ -16,7 +16,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
@ -60,8 +60,8 @@ class report_xls(report_sxw):
# header/footer
hf_params = {
'font_size': 8,
'font_style': 'I', # B: Bold, I: Italic, U: Underline
'font_size': 8,
'font_style': 'I', # B: Bold, I: Italic, U: Underline
}
# styles
@ -77,8 +77,12 @@ class report_xls(report_sxw):
'fill': 'pattern: pattern solid, fore_color %s;' % _pfc,
'fill_blue': 'pattern: pattern solid, fore_color 27;',
'fill_grey': 'pattern: pattern solid, fore_color 22;',
'borders_all': 'borders: left thin, right thin, top thin, bottom thin, '
'left_colour %s, right_colour %s, top_colour %s, bottom_colour %s;' % (_bc, _bc, _bc, _bc),
'borders_all':
'borders: '
'left thin, right thin, top thin, bottom thin, '
'left_colour %s, right_colour %s, '
'top_colour %s, bottom_colour %s;'
% (_bc, _bc, _bc, _bc),
'left': 'align: horz left;',
'center': 'align: horz center;',
'right': 'align: horz right;',
@ -93,15 +97,17 @@ class report_xls(report_sxw):
self.cr = cr
self.uid = uid
report_obj = self.pool.get('ir.actions.report.xml')
report_ids = report_obj.search(cr, uid,
[('report_name', '=', self.name[7:])], context=context)
report_ids = report_obj.search(
cr, uid, [('report_name', '=', self.name[7:])], context=context)
if report_ids:
report_xml = report_obj.browse(cr, uid, report_ids[0], context=context)
report_xml = report_obj.browse(
cr, uid, report_ids[0], context=context)
self.title = report_xml.name
if report_xml.report_type == 'xls':
return self.create_source_xls(cr, uid, ids, data, context)
elif context.get('xls_export'):
self.table = data.get('model') or self.table # use model from 'data' when no ir.actions.report.xml entry
# use model from 'data' when no ir.actions.report.xml entry
self.table = data.get('model') or self.table
return self.create_source_xls(cr, uid, ids, data, context)
return super(report_xls, self).create(cr, uid, ids, data, context)
@ -110,6 +116,7 @@ class report_xls(report_sxw):
context = {}
parser_instance = self.parser(cr, uid, self.name2, context)
self.parser_instance = parser_instance
self.context = context
objs = self.getObjects(cr, uid, ids, context)
parser_instance.set_context(objs, data, ids, 'xls')
objs = parser_instance.localcontext['objects']
@ -120,10 +127,14 @@ class report_xls(report_sxw):
self.xls_headers = {
'standard': '',
}
report_date = datetime_field.context_timestamp(cr, uid, datetime.now(), context).strftime(DEFAULT_SERVER_DATETIME_FORMAT)
report_date = datetime_field.context_timestamp(
cr, uid, datetime.now(), context)
report_date = report_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
self.xls_footers = {
'standard': ('&L&%(font_size)s&%(font_style)s' + report_date +
'&R&%(font_size)s&%(font_style)s&P / &N') % self.hf_params,
'standard': (
'&L&%(font_size)s&%(font_style)s' + report_date +
'&R&%(font_size)s&%(font_style)s&P / &N'
) % self.hf_params,
}
self.generate_xls_report(_p, _xs, data, objs, wb)
wb.save(n)
@ -138,7 +149,8 @@ class report_xls(report_sxw):
- wanted: element from the wanted_list
- col_specs : cf. specs[1:] documented in xls_row_template method
- rowtype : 'header' or 'data'
- render_space : type dict, (caller_space + localcontext) if not specified
- render_space : type dict, (caller_space + localcontext)
if not specified
"""
if render_space == 'empty':
render_space = {}
@ -151,7 +163,6 @@ class report_xls(report_sxw):
if isinstance(row[i], CodeType):
row[i] = eval(row[i], render_space)
row.insert(0, wanted)
#_logger.warn('row O = %s', row)
return row
def generate_xls_report(self, parser, xls_styles, data, objects, wb):
@ -163,11 +174,13 @@ class report_xls(report_sxw):
Returns a row template.
Input :
- 'wanted_list': list of Columns that will be returned in the row_template
- 'wanted_list': list of Columns that will be returned in the
row_template
- 'specs': list with Column Characteristics
0: Column Name (from wanted_list)
1: Column Colspan
2: Column Size (unit = the width of the character 0 as it appears in the sheets default font)
2: Column Size (unit = the width of the character 0
as it appears in the sheets default font)
3: Column Type
4: Column Data
5: Column Formula (or 'None' for Data)
@ -186,7 +199,8 @@ class report_xls(report_sxw):
if s_len > 5 and s[5] is not None:
c.append({'formula': s[5]})
else:
c.append({'write_cell_func': report_xls.xls_types[c[3]]})
c.append({
'write_cell_func': report_xls.xls_types[c[3]]})
# Set custom cell style
if s_len > 6 and s[6] is not None:
c.append(s[6])
@ -201,23 +215,28 @@ class report_xls(report_sxw):
col += c[1]
break
if not found:
_logger.warn("report_xls.xls_row_template, column '%s' not found in specs", w)
_logger.warn("report_xls.xls_row_template, "
"column '%s' not found in specs", w)
return r
def xls_write_row(self, ws, row_pos, row_data, row_style=default_style, set_column_size=False):
def xls_write_row(self, ws, row_pos, row_data,
row_style=default_style, set_column_size=False):
r = ws.row(row_pos)
for col, size, spec in row_data:
data = spec[4]
formula = spec[5].get('formula') and xlwt.Formula(spec[5]['formula']) or None
formula = spec[5].get('formula') and \
xlwt.Formula(spec[5]['formula']) or None
style = spec[6] and spec[6] or row_style
if not data:
# if no data, use default values
data = report_xls.xls_types_default[spec[3]]
if size != 1:
if formula:
ws.write_merge(row_pos, row_pos, col, col + size - 1, data, style)
ws.write_merge(
row_pos, row_pos, col, col + size - 1, data, style)
else:
ws.write_merge(row_pos, row_pos, col, col + size - 1, data, style)
ws.write_merge(
row_pos, row_pos, col, col + size - 1, data, style)
else:
if formula:
ws.write(row_pos, col, formula, style)

BIN
__unported__/report_xls/static/src/img/icon.png

3
__unported__/report_xls/utils.py

@ -28,7 +28,8 @@ def _render(code):
def rowcol_to_cell(row, col, row_abs=False, col_abs=False):
# Code based upon utils from xlwt distribution
"""
Convert numeric row/col notation to an Excel cell reference string in A1 notation.
Convert numeric row/col notation to an Excel cell
reference string in A1 notation.
"""
d = col // 26
m = col % 26

25
report_xls/__init__.py

@ -0,0 +1,25 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
#
# Copyright (c) 2014 Noviat nv/sa (www.noviat.com). All rights reserved.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from . import ir_report
from . import report_xls
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

82
report_xls/__openerp__.py

@ -0,0 +1,82 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
#
# Copyright (c) 2014 Noviat nv/sa (www.noviat.com). All rights reserved.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
'name': 'Excel report engine',
'version': '0.6',
'license': 'AGPL-3',
'author': 'Noviat',
'website': 'http://www.noviat.com',
'category': 'Reporting',
'description': """
Excel report engine
===================
This module adds Excel export capabilities to the standard odoo reporting
engine.
Report development
''''''''''''''''''
In order to create an Excel report you can\n
- define a report of type 'xls'
- pass ``{'xls_export': 1}`` via the context to the report create method
The ``report_xls`` class contains a number of attributes and methods to
facilitate the creation XLS reports in OpenERP.
* cell types
Supported cell types : text, number, boolean, date.
* cell styles
The predefined cell style definitions result in a consistent
look and feel of the OpenERP Excel reports.
* cell formulas
Cell formulas can be easily added with the help of the ``rowcol_to_cell()``
function which you can import from the ``utils.py`` module.
* Excel templates
It is possible to define Excel templates which can be adapted
by 'inherited' modules.
Download the ``account_move_line_report_xls`` module
from http://apps.odoo.com as example.
* XLS with multiple sheets
Download the ``account_journal_report_xls`` module
from http://apps.odoo.com as example.
Development assistance
''''''''''''''''''''''
Contact info@noviat.com for help with the development of
Excel reports in odoo.
""",
'depends': ['base'],
'external_dependencies': {'python': ['xlwt']},
'active': False,
'installable': True,
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

36
report_xls/ir_report.py

@ -0,0 +1,36 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
#
# Copyright (c) 2014 Noviat nv/sa (www.noviat.com). All rights reserved.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp.osv import fields, orm
class ir_actions_report_xml(orm.Model):
_inherit = 'ir.actions.report.xml'
def _check_selection_field_value(self, cr, uid,
field, value, context=None):
if field == 'report_type' and value == 'xls':
return
return super(ir_actions_report_xml, self)._check_selection_field_value(
cr, uid, field, value, context=context)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

249
report_xls/report_xls.py

@ -0,0 +1,249 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
#
# Copyright (c) 2014 Noviat nv/sa (www.noviat.com). All rights reserved.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import xlwt
from xlwt.Style import default_style
import cStringIO
from datetime import datetime
from openerp.osv.fields import datetime as datetime_field
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
import inspect
from types import CodeType
from openerp.report.report_sxw import *
from openerp import pooler
from openerp.tools.translate import translate, _
import logging
_logger = logging.getLogger(__name__)
class AttrDict(dict):
def __init__(self, *args, **kwargs):
super(AttrDict, self).__init__(*args, **kwargs)
self.__dict__ = self
class report_xls(report_sxw):
xls_types = {
'bool': xlwt.Row.set_cell_boolean,
'date': xlwt.Row.set_cell_date,
'text': xlwt.Row.set_cell_text,
'number': xlwt.Row.set_cell_number,
}
xls_types_default = {
'bool': False,
'date': None,
'text': '',
'number': 0,
}
# TO DO: move parameters infra to configurable data
# header/footer
hf_params = {
'font_size': 8,
'font_style': 'I', # B: Bold, I: Italic, U: Underline
}
# styles
_pfc = '26' # default pattern fore_color
_bc = '22' # borders color
decimal_format = '#,##0.00'
date_format = 'YYYY-MM-DD'
xls_styles = {
'xls_title': 'font: bold true, height 240;',
'bold': 'font: bold true;',
'underline': 'font: underline true;',
'italic': 'font: italic true;',
'fill': 'pattern: pattern solid, fore_color %s;' % _pfc,
'fill_blue': 'pattern: pattern solid, fore_color 27;',
'fill_grey': 'pattern: pattern solid, fore_color 22;',
'borders_all':
'borders: '
'left thin, right thin, top thin, bottom thin, '
'left_colour %s, right_colour %s, '
'top_colour %s, bottom_colour %s;'
% (_bc, _bc, _bc, _bc),
'left': 'align: horz left;',
'center': 'align: horz center;',
'right': 'align: horz right;',
'wrap': 'align: wrap true;',
'top': 'align: vert top;',
'bottom': 'align: vert bottom;',
}
# TO DO: move parameters supra to configurable data
def create(self, cr, uid, ids, data, context=None):
self.pool = pooler.get_pool(cr.dbname)
self.cr = cr
self.uid = uid
report_obj = self.pool.get('ir.actions.report.xml')
report_ids = report_obj.search(
cr, uid, [('report_name', '=', self.name[7:])], context=context)
if report_ids:
report_xml = report_obj.browse(
cr, uid, report_ids[0], context=context)
self.title = report_xml.name
if report_xml.report_type == 'xls':
return self.create_source_xls(cr, uid, ids, data, context)
elif context.get('xls_export'):
# use model from 'data' when no ir.actions.report.xml entry
self.table = data.get('model') or self.table
return self.create_source_xls(cr, uid, ids, data, context)
return super(report_xls, self).create(cr, uid, ids, data, context)
def create_source_xls(self, cr, uid, ids, data, context=None):
if not context:
context = {}
parser_instance = self.parser(cr, uid, self.name2, context)
self.parser_instance = parser_instance
self.context = context
objs = self.getObjects(cr, uid, ids, context)
parser_instance.set_context(objs, data, ids, 'xls')
objs = parser_instance.localcontext['objects']
n = cStringIO.StringIO()
wb = xlwt.Workbook(encoding='utf-8')
_p = AttrDict(parser_instance.localcontext)
_xs = self.xls_styles
self.xls_headers = {
'standard': '',
}
report_date = datetime_field.context_timestamp(
cr, uid, datetime.now(), context)
report_date = report_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
self.xls_footers = {
'standard': (
'&L&%(font_size)s&%(font_style)s' + report_date +
'&R&%(font_size)s&%(font_style)s&P / &N'
) % self.hf_params,
}
self.generate_xls_report(_p, _xs, data, objs, wb)
wb.save(n)
n.seek(0)
return (n.read(), 'xls')
def render(self, wanted, col_specs, rowtype, render_space='empty'):
"""
returns 'evaluated' col_specs
Input:
- wanted: element from the wanted_list
- col_specs : cf. specs[1:] documented in xls_row_template method
- rowtype : 'header' or 'data'
- render_space : type dict, (caller_space + localcontext)
if not specified
"""
if render_space == 'empty':
render_space = {}
caller_space = inspect.currentframe().f_back.f_back.f_locals
localcontext = self.parser_instance.localcontext
render_space.update(caller_space)
render_space.update(localcontext)
row = col_specs[wanted][rowtype][:]
for i in range(len(row)):
if isinstance(row[i], CodeType):
row[i] = eval(row[i], render_space)
row.insert(0, wanted)
return row
def generate_xls_report(self, parser, xls_styles, data, objects, wb):
""" override this method to create your excel file """
raise NotImplementedError()
def xls_row_template(self, specs, wanted_list):
"""
Returns a row template.
Input :
- 'wanted_list': list of Columns that will be returned in the
row_template
- 'specs': list with Column Characteristics
0: Column Name (from wanted_list)
1: Column Colspan
2: Column Size (unit = the width of the character 0
as it appears in the sheets default font)
3: Column Type
4: Column Data
5: Column Formula (or 'None' for Data)
6: Column Style
"""
r = []
col = 0
for w in wanted_list:
found = False
for s in specs:
if s[0] == w:
found = True
s_len = len(s)
c = list(s[:5])
# set write_cell_func or formula
if s_len > 5 and s[5] is not None:
c.append({'formula': s[5]})
else:
c.append({
'write_cell_func': report_xls.xls_types[c[3]]})
# Set custom cell style
if s_len > 6 and s[6] is not None:
c.append(s[6])
else:
c.append(None)
# Set cell formula
if s_len > 7 and s[7] is not None:
c.append(s[7])
else:
c.append(None)
r.append((col, c[1], c))
col += c[1]
break
if not found:
_logger.warn("report_xls.xls_row_template, "
"column '%s' not found in specs", w)
return r
def xls_write_row(self, ws, row_pos, row_data,
row_style=default_style, set_column_size=False):
r = ws.row(row_pos)
for col, size, spec in row_data:
data = spec[4]
formula = spec[5].get('formula') and \
xlwt.Formula(spec[5]['formula']) or None
style = spec[6] and spec[6] or row_style
if not data:
# if no data, use default values
data = report_xls.xls_types_default[spec[3]]
if size != 1:
if formula:
ws.write_merge(
row_pos, row_pos, col, col + size - 1, data, style)
else:
ws.write_merge(
row_pos, row_pos, col, col + size - 1, data, style)
else:
if formula:
ws.write(row_pos, col, formula, style)
else:
spec[5]['write_cell_func'](r, col, data, style)
if set_column_size:
ws.col(col).width = spec[2] * 256
return row_pos + 1
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

BIN
report_xls/static/description/help.png

After

Width: 300  |  Height: 235  |  Size: 30 KiB

BIN
report_xls/static/description/icon.png

After

Width: 88  |  Height: 85  |  Size: 11 KiB

BIN
report_xls/static/description/icon2.png

After

Width: 88  |  Height: 85  |  Size: 11 KiB

84
report_xls/static/description/index.html

@ -0,0 +1,84 @@
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2 class="oe_slogan">Excel report engine</h2>
</div>
<div class="oe_span6">
<div class="oe_demo oe_picture oe_screenshot">
<img src="open_receivables.png">
</div>
</div>
<div class="oe_span6">
<p class="oe_mt32">
<br><br>This module adds Excel export capabilities to the standard odoo reporting engine.
</p>
</div>
</div>
</section>
<section class="oe_spaced oe_container oe_dark">
<div class="oe_row">
<h2 class="oe_slogan">Report development</h2>
<p class="oe_mt32">
In order to create an Excel report you can
<ul>
<li>define a report of type 'xls'</li>
<li>pass <code>{'xls_export': 1}</code> via the context to the report create method</li>
</ul>
</p>
<p class="oe_mt32">
The <code>report_xls</code> class contains a number of attributes and methods to facilitate the creation XLS reports in odoo.
<ul>
<li>
cell types
<br>Supported cell types : text, number, boolean, date.
</li>
</ul>
<ul>
<li>
cell styles
<br>The predefined cell style definitions result in a consistent look and feel of the odoo Excel reports.
</li>
</ul>
<ul>
<li>
cell formulas
<br>Cell formulas can be easily added with the help of the <code>rowcol_to_cell()</code> function which you can import from the <code>utils.py</code> module.
</li>
</ul>
<ul>
<li>
Excel templates
<br>It is possible to define Excel templates which can be adapted by 'inherited' modules.
<br>Download the <b>account_move_line_report_xls</b> module from <a href="http://apps.odoo.com">http://apps.odoo.com</a> as example.
</li>
</ul>
<ul>
<li>
XLS with multiple sheets
<br>Download the <b>account_journal_report_xls</b> module from <a href="http://apps.odoo.com">http://apps.odoo.com</a> as example.
</li>
</ul>
</p>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2 class="oe_slogan">Development assistance</h2>
</div>
<div class="oe_span6">
<br>
<div class="oe_picture">
<center><img src="help.png" height="150"></center>
</div>
</div>
<div class="oe_span6">
<p class="oe_mt32">
<br><br>Contact <a href="mailto:info@noviat.com">info@noviat.com</a> for help with the development of Excel reports in odoo.
</p>
</div>
</div>
</section>

BIN
report_xls/static/description/open_receivables.png

After

Width: 854  |  Height: 507  |  Size: 49 KiB

51
report_xls/utils.py

@ -0,0 +1,51 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
#
# Copyright (c) 2014 Noviat nv/sa (www.noviat.com). All rights reserved.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
def _render(code):
return compile(code, '<string>', 'eval')
def rowcol_to_cell(row, col, row_abs=False, col_abs=False):
# Code based upon utils from xlwt distribution
"""
Convert numeric row/col notation to an Excel cell
reference string in A1 notation.
"""
d = col // 26
m = col % 26
chr1 = "" # Most significant character in AA1
if row_abs:
row_abs = '$'
else:
row_abs = ''
if col_abs:
col_abs = '$'
else:
col_abs = ''
if d > 0:
chr1 = chr(ord('A') + d - 1)
chr2 = chr(ord('A') + m)
# Zero index to 1-index
return col_abs + chr1 + chr2 + row_abs + str(row + 1)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
Loading…
Cancel
Save