diff --git a/__unported__/report_xls/__init__.py b/__unported__/report_xls/__init__.py index 1f5df8f6..e100e786 100644 --- a/__unported__/report_xls/__init__.py +++ b/__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: diff --git a/__unported__/report_xls/__openerp__.py b/__unported__/report_xls/__openerp__.py index a0b256eb..e53584ff 100644 --- a/__unported__/report_xls/__openerp__.py +++ b/__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, } diff --git a/__unported__/report_xls/report_xls.py b/__unported__/report_xls/report_xls.py index 707fc34b..13fcb5bb 100644 --- a/__unported__/report_xls/report_xls.py +++ b/__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 . +# along with this program. If not, see . # ############################################################################## @@ -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 sheet’s default font) + 2: Column Size (unit = the width of the character ’0′ + as it appears in the sheet’s 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) diff --git a/__unported__/report_xls/static/src/img/icon.png b/__unported__/report_xls/static/src/img/icon.png index b8a2fcdf..44c5db16 100644 Binary files a/__unported__/report_xls/static/src/img/icon.png and b/__unported__/report_xls/static/src/img/icon.png differ diff --git a/__unported__/report_xls/utils.py b/__unported__/report_xls/utils.py index f21644ca..943daae7 100644 --- a/__unported__/report_xls/utils.py +++ b/__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 diff --git a/report_xls/__init__.py b/report_xls/__init__.py new file mode 100644 index 00000000..e100e786 --- /dev/null +++ b/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 . +# +############################################################################## + +from . import ir_report +from . import report_xls +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/report_xls/__openerp__.py b/report_xls/__openerp__.py new file mode 100644 index 00000000..1ca25bbc --- /dev/null +++ b/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 . +# +############################################################################## +{ + '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: diff --git a/report_xls/ir_report.py b/report_xls/ir_report.py new file mode 100644 index 00000000..f35e6069 --- /dev/null +++ b/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 . +# +############################################################################## + +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: diff --git a/report_xls/report_xls.py b/report_xls/report_xls.py new file mode 100644 index 00000000..13fcb5bb --- /dev/null +++ b/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 . +# +############################################################################## + +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 sheet’s 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: diff --git a/report_xls/static/description/help.png b/report_xls/static/description/help.png new file mode 100644 index 00000000..3e7338c8 Binary files /dev/null and b/report_xls/static/description/help.png differ diff --git a/report_xls/static/description/icon.png b/report_xls/static/description/icon.png new file mode 100644 index 00000000..b8a2fcdf Binary files /dev/null and b/report_xls/static/description/icon.png differ diff --git a/report_xls/static/description/icon2.png b/report_xls/static/description/icon2.png new file mode 100644 index 00000000..b8a2fcdf Binary files /dev/null and b/report_xls/static/description/icon2.png differ diff --git a/report_xls/static/description/index.html b/report_xls/static/description/index.html new file mode 100644 index 00000000..1cdf4263 --- /dev/null +++ b/report_xls/static/description/index.html @@ -0,0 +1,84 @@ +
+
+
+

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 +

    +
  • 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 odoo. +

    +
  • + 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 odoo 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. +

+
+
+
+ diff --git a/report_xls/static/description/open_receivables.png b/report_xls/static/description/open_receivables.png new file mode 100644 index 00000000..a00c3ba4 Binary files /dev/null and b/report_xls/static/description/open_receivables.png differ diff --git a/report_xls/utils.py b/report_xls/utils.py new file mode 100644 index 00000000..943daae7 --- /dev/null +++ b/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 . +# +############################################################################## + + +def _render(code): + return compile(code, '', '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: