How can i generate xls report in odoo

ぐ巨炮叔叔 提交于 2019-12-08 12:15:35

问题


I want to generate my own excel report using Excel report engine in odoo 8. someone please send me a simple excel report sample or any helping URL. I'll be very thankful to you ....


回答1:


Here is a simple piece of code. There is really a lot of examples on the internet with good explanations. I suggest you go through the code in detail to see how it works (by the way I have copied the code also from somewhere - I cannot remember where. Also have a look at the examples here:https://github.com/OCA/reporting-engine/tree/8.0 The version 8 branch also have a number of examples.

You can add columns by editing the "my_change" variable.

from openerp.osv import orm
from openerp.addons.report_xls.utils import rowcol_to_cell, _render
from openerp.tools.translate import _

class account_move_line(orm.Model):
    _inherit = 'abc.salesforecast'

# override list in custom module to add/drop columns or change order
    def _report_xls_fields(self, cr, uid, context=None):
    return [
        'contract', 'proposal', 'description', 
        #'amount_currency', 'currency_name',
        ]

# Change/Add Template entries
    def _report_xls_template(self, cr, uid, context=None):   
    """  
    Template updates, e.g. 

    my_change = {
        'move':{
            'header': [1, 20, 'text', _('My Move Title')],
            'lines': [1, 0, 'text', _render("line.move_id.name or ''")],
            'totals': [1, 0, 'text', None]},
        }
    return my_change
    """   
    return {}

The code for the parser is as follows.

import xlwt
import time
from datetime import datetime
from openerp.osv import orm

from openerp.report import report_sxw
from openerp.addons.report_xls.report_xls import report_xls
from openerp.addons.report_xls.utils import rowcol_to_cell, _render
from openerp.tools.translate import translate, _
from openerp import pooler
import logging
_logger = logging.getLogger(__name__)


class contract_sales_forecast_xls_parser(report_sxw.rml_parse):

    def __init__(self, cr, uid, name, context):
    super(contract_sales_forecast_xls_parser, self).__init__(cr, uid, name, context=context)
    forecast_obj = self.pool.get('msr.salesforecast')
    self.context = context
    wanted_list = forecast_obj._report_xls_fields(cr, uid, context)
    template_changes = forecast_obj._report_xls_template(cr, uid, context)
    self.localcontext.update({
        'datetime': datetime,
        'wanted_list': wanted_list,
        'template_changes': template_changes,
        '_': self._,
    })

def _(self, src):
    lang = self.context.get('lang', 'en_US')
    return translate(self.cr, _ir_translation_name, 'report', lang, src) or src

class contract_sales_forecast_xls(report_xls):

def __init__(self, name, table, rml=False, parser=False, header=True, store=False):
    super(contract_sales_forecast_xls, self).__init__(name, table, rml, parser, header, store)

    # Cell Styles
    _xs = self.xls_styles        
    # header
    rh_cell_format = _xs['bold'] + _xs['fill'] + _xs['borders_all']
    self.rh_cell_style = xlwt.easyxf(rh_cell_format)
    self.rh_cell_style_center = xlwt.easyxf(rh_cell_format + _xs['center'])
    self.rh_cell_style_right = xlwt.easyxf(rh_cell_format + _xs['right'])
    # lines  
    aml_cell_format = _xs['borders_all']
    self.aml_cell_style = xlwt.easyxf(aml_cell_format)
    self.aml_cell_style_center = xlwt.easyxf(aml_cell_format + _xs['center'])
    self.aml_cell_style_date = xlwt.easyxf(aml_cell_format + _xs['left'], num_format_str = report_xls.date_format)
    self.aml_cell_style_decimal = xlwt.easyxf(aml_cell_format + _xs['right'], num_format_str = report_xls.decimal_format)
    # totals
    rt_cell_format = _xs['bold'] + _xs['fill'] + _xs['borders_all']
    self.rt_cell_style = xlwt.easyxf(rt_cell_format)
    self.rt_cell_style_right = xlwt.easyxf(rt_cell_format + _xs['right'])       
    self.rt_cell_style_decimal = xlwt.easyxf(rt_cell_format + _xs['right'], num_format_str = report_xls.decimal_format)

    # XLS Template
    self.col_specs_template = {
        'contract':{
            'header': [1, 20, 'text', _render("_('Contract Number')")],
            'lines': [1, 0, 'text', _render("msr_contract_id or ''")],
            'totals': [1, 0, 'text', None]},
        'proposal':{      
            'header': [1, 42, 'text', _render("_('Proposal Number')")],
            'lines': [1, 0, 'text', _render("msr_proposal or ''")],                
            'totals': [1, 0, 'text', None]},
        'description':{      
            'header': [1, 42, 'text', _render("_('Description')")],
            'lines': [1, 0, 'text', _render("name or ''")],                
            'totals': [1, 0, 'text', None]},
    }

def generate_xls_report(self, _p, _xs, data, objects, wb):

    wanted_list = _p.wanted_list
    self.col_specs_template.update(_p.template_changes)
    _ = _p._



    #report_name = objects[0]._description or objects[0]._name
    report_name = _("Sales forecast from current contracts")        
    ws = wb.add_sheet(report_name[:31])
    ws.panes_frozen = True
    ws.remove_splits = True
    ws.portrait = 0 # Landscape
    ws.fit_width_to_pages = 1
    row_pos = 0

    # set print header/footer
    ws.header_str = self.xls_headers['standard']
    ws.footer_str = self.xls_footers['standard']

    # Title
    cell_style = xlwt.easyxf(_xs['xls_title'])
    c_specs = [
        ('report_name', 1, 0, 'text', report_name),
    ]       
    row_data = self.xls_row_template(c_specs, ['report_name'])
    row_pos = self.xls_write_row(ws, row_pos, row_data, row_style=cell_style)
    row_pos += 1

    # Column headers
    c_specs = map(lambda x: self.render(x, self.col_specs_template, 'header', render_space={'_': _p._}), wanted_list)
    row_data = self.xls_row_template(c_specs, [x[0] for x in c_specs])
    row_pos = self.xls_write_row(ws, row_pos, row_data, row_style=self.rh_cell_style, set_column_size=True)        
    ws.set_horz_split_pos(row_pos)   

    # account move lines
    for line in objects:
        c_specs = map(lambda x: self.render(x, self.col_specs_template, 'lines'), wanted_list)
        row_data = self.xls_row_template(c_specs, [x[0] for x in c_specs])
        row_pos = self.xls_write_row(ws, row_pos, row_data, row_style=self.aml_cell_style)

    # Totals           

contract_sales_forecast_xls('report.contract.sales.forecast.xls', 
    'abc.salesforecast',
    parser="contract_sales_forecast_xls_parser")

The xml file will look as follows to setup the necessary actions etc.

<?xml version="1.0" encoding="utf-8"?>
<openerp>
  <data>

    <record id="action_contract_sales_forecast_xls"     model="ir.actions.report.xml">
      <field name="name">Export Selected Lines To Excel</field>
      <field name="model">abc.salesforecast</field>
      <field name="type">ir.actions.report.xml</field>
      <field name="report_name">contract.sales.forecast.xls</field>
      <field name="report_type">xls</field>
      <field name="auto" eval="False"/>
    </record>

    <record model="ir.values" id="contract_sales_forecast_xls_values">
      <field name="name">Export Selected Lines</field>
      <field name="key2">client_action_multi</field>
      <field name="value" eval="'ir.actions.report.xml,' +str(ref('action_contract_sales_forecast_xls'))" />
      <field name="model">abc.salesforecast</field>
    </record>   

  </data>
</openerp>



回答2:


A second example. First the xml to create a button. This is only an extract.

<form string = "Contract Search Wizard" version="7.0">
<sheet>
<group>
    <button icon="gtk-ok" name="print_contract_list" string="Print Contract List" type="object" />
    <button icon="gtk-ok" name="export_contract_product" string="Export Contract vs. Product Pivot Table" type="object" />
    <button icon="gtk-ok" name="export_contract_country" string="Export Contract vs. Country Pivot Table" type="object" />                      
    <button icon="gtk-cancel" special="cancel" string="Cancel" />
</group>
</sheet>
</form>

The below code is a wizard with several buttons. I removed some code to save space. The report is activated from a button:

class abc_contract_search_wizard(osv.osv):

def _prd_report_xls_fields(self, cr, uid, context=None):

    SQLstring = "SELECT abc_product_list.name FROM abc_product_list;"
    cr.execute(SQLstring)
    tbl_products = cr.dictfetchall()

    header_list=['contract_id','contract_name','exclusive']

    for t in tbl_products:
        header_list.append(t['name'])

    return header_list

# Change/Add Template entries
def _prd_report_xls_template(self, cr, uid, context=None):   
    """  
    Template updates, e.g. 

    my_change = {
        'move':{
            'header': [1, 20, 'text', _('My Move Title')],
            'lines': [1, 0, 'text', _render("line.move_id.name or ''")],
            'totals': [1, 0, 'text', None]},
    }
    return my_change
    """   

    SQLstring = "SELECT abc_product_list.name FROM abc_product_list;"
    cr.execute(SQLstring)
    tbl_products = cr.dictfetchall()


    abc_tmpl = {
            'contract_id':
                {
                    'header':[1,20, 'text', _render("_('Contract ID')")],
                    'lines':[1,0, 'text', _render("line.abc_contract_id.name or ''")],
                    'totals':[1, 0, 'text', None],
                },
            'contract_name' :
                {
                    'header':[1,40, 'text', _render("_('Contract Name')")],
                    'lines':[1,0, 'text', _render("line.abc_contract_name or ''")],
                    'totals':[1, 0, 'text', None],
                },
            'exclusive':
                {
                    'header':[1,10, 'text', _render("_('Exlusive')")],
                    'lines':[1,0, 'text', _render("line.abc_country.name or ''")],
                    'totals':[1, 0, 'text', None],
                 },
    }



    for t in tbl_products:
        abc_tmpl[t['name']]={
                    'header':[1,3, 'text', _render("_('" + t['name']+"')")],
                    'lines':[1,0, 'text', _render("line.abc_contract_id.name or ''")],
                    'totals':[1, 0, 'text', None],
                             }
    return abc_tmpl


_name='abc.contract.search.wizard'
_columns={
    'country':fields.many2one('abc.countries','Country'),
    'product':fields.many2one('abc.product.list','Product'),
    'start_date':fields.date('Start Date'),
    'end_date':fields.date('End Date'),
    'partner':fields.many2one('res.partner','Partner'),
    'product_type':fields.many2one('abc.product.type','Product Type'),
    'regions':fields.many2one('abc.regions', 'Regions'),
    'exclusive':fields.boolean('Exclusive'),
    'contract_type':fields.many2one('abc.contract.types','Contract Type'),
    }

def find_product(self, tbl_contractproducts, product_id):
    is_there=False
    for t in tbl_contractproducts:
        if product_id==t['product_id']:
            is_there=True
    return is_there

def get_contract_products(self, cr, uid, ids, context, contract_id, tbl_products):

    products={}
    SQLstring = "SELECT abc_contract_product_list.product_id, abc_contract_product_list.contract_id FROM abc_contract_product_list " \
    + "WHERE (((abc_contract_product_list.contract_id) =" + str(contract_id) + "));"    
    cr.execute(SQLstring)
    tbl_contractproducts = cr.dictfetchall()
    for t in tbl_products:    
        if self.find_product(tbl_contractproducts,t['product_id']):
            products[t['product_name']]='X'
        else:
            products[t['product_name']]=''                
    return products

def export_contract_product(self, cr, uid, ids, context=None):

    rst = self.browse(cr, uid, ids)[0]
    country_id = rst.country.id
    product_id = rst.product.id
    start_date = rst.start_date
    end_date = rst.end_date
    product_type_id = rst.product_type.id
    partner_id = rst.partner.id
    region_id = rst.regions.id
    exclusive = rst.exclusive
    contract_type_id = rst.contract_type.id

    SQLwhere = ""   
    SQLstring = "SELECT DISTINCT abc_official_documents.id, abc_official_documents.contract_id, abc_official_documents.name AS doc_name,  abc_official_documents.contract_exclusive_agreemnet " \
    + "FROM res_partner INNER JOIN (((abc_contract_countries INNER JOIN (((abc_contract_product_list INNER JOIN (abc_product_type INNER JOIN abc_product_list " \
    + "ON abc_product_type.id = abc_product_list.product_type) ON abc_contract_product_list.product_id = abc_product_list.id) INNER JOIN abc_official_documents ON "\
    + "abc_contract_product_list.contract_id = abc_official_documents.id) INNER JOIN abc_contract_types ON abc_official_documents.contract_type = abc_contract_types.id) "\
    + "ON abc_contract_countries.contract_id = abc_official_documents.id) INNER JOIN abc_countries ON abc_contract_countries.country_id = abc_countries.id) INNER JOIN "\
    + "abc_regions ON abc_countries.country_region = abc_regions.id) ON res_partner.id = abc_official_documents.contract_partner_id "

    if country_id:
        SQLwhere = " AND ((abc_contract_countries.country_id) = " + str(country_id) + ")"
    if product_id:
        SQLwhere = SQLwhere + " AND ((abc_contract_product_list.product_id) = " + str(product_id) + ")"
    if start_date:
        SQLwhere = SQLwhere + " AND ((abc_official_documents.contract_start_date) < " + str(start_date) + ")"
    if end_date:
        SQLwhere = SQLwhere + " AND ((abc_official_documents.contract_termination_date) < " + str(end_date) + ")"
    if partner_id:
        SQLwhere = SQLwhere + " AND ((abc_official_documents.contract_partner_id) = " + str(partner_id) +")"
    if region_id:
        SQLwhere = SQLwhere + " AND ((abc_countries.country_region) = " + str(region_id) + ")"
    if exclusive:
        SQLwhere = SQLwhere + " AND ((abc_official_documents.contract_exclusive_agreemnet) = true )"
    if contract_type_id:
        SQLwhere = SQLwhere + " AND ((abc_official_documents.contract_type) = " + str(contract_type_id) + ")"    
    if product_type_id:    
        SQLwhere = SQLwhere + " AND ((abc_product_list.product_type) = " +str(product_type_id) + ")"

    SQLwhere = SQLwhere[-(len(SQLwhere)-5):]      #Vat die eerste "AND" weg (5 karakters)

    if ((not SQLwhere) | (len(SQLwhere)==0)):
        SQLstring = SQLstring + " LIMIT 100;"
    else:
        SQLstring = SQLstring + "WHERE (" + SQLwhere + ") LIMIT 100;"

    cr.execute(SQLstring)

    tblContracts = cr.dictfetchall()

    SQLstring = "SELECT abc_product_list.id AS product_id, abc_product_list.name as product_name FROM abc_product_list;"

    cr.execute(SQLstring)
    tbl_products = cr.dictfetchall()

    pivot_table = []
    datas={'ids':context.get('active_ids', [])}
    for t in tblContracts:
        if t:
            if t['contract_exclusive_agreemnet']:
                excl="Yes"
            else:
                excl = "No"    
            contract_table = {
                    'contract_id': t['contract_id'],
                    'contract_name': t['doc_name'],
                    'exclusive':excl,
                }
            product_table=self.get_contract_products(cr, uid, ids, context, t['id'], tbl_products)
            full_table = dict(contract_table.items() + product_table.items())
            pivot_table.append(full_table)
    datas['contract_list']= pivot_table    



    return {
        'type':'ir.actions.report.xml',
        'report_name': 'contract_products',
        'datas':datas,
    }

abc_contract_search_wizard()

Here is the code for the parser:

class contract_products_parser(report_sxw.rml_parse):

def __init__(self, cr, uid, name, context):
    super(contract_products_parser, self).__init__(cr, uid, name, context=context)
    forc_obj = self.pool.get('abc.contract.search.wizard')
    self.context = context
    wanted_list = forc_obj._prd_report_xls_fields(cr, uid, context)
    template_changes = forc_obj._prd_report_xls_template(cr, uid, context)
    self.localcontext.update({
        'datetime': datetime,
        'wanted_list': wanted_list,
        'template_changes': template_changes,
        '_': self._,
    })

def _(self, src):
    lang = self.context.get('lang', 'en_US')
    return translate(self.cr, _ir_translation_name, 'report', lang, src) or src

class contract_products_xls(report_xls):

def __init__(self, name, table, rml=False, parser=False, header=True, store=False):
    super(contract_products_xls, self).__init__(name, table, rml, parser, header, store)

    # Cell Styles
    _xs = self.xls_styles        
    # header
    rh_cell_format = _xs['bold'] + _xs['fill'] + _xs['borders_all'] 
    self.rh_cell_style = xlwt.easyxf(rh_cell_format)
    self.rh_cell_style_center = xlwt.easyxf(rh_cell_format + _xs['center'])
    self.rh_cell_style_right = xlwt.easyxf(rh_cell_format + _xs['right'])
    # lines  
    aml_cell_format = _xs['borders_all']
    self.aml_cell_style = xlwt.easyxf(aml_cell_format)
    self.aml_cell_style_center = xlwt.easyxf(aml_cell_format + _xs['center'])
    self.aml_cell_style_date = xlwt.easyxf(aml_cell_format + _xs['left'], num_format_str = report_xls.date_format)
    self.aml_cell_style_decimal = xlwt.easyxf(aml_cell_format + _xs['right'], num_format_str = report_xls.decimal_format)
    # totals
    rt_cell_format = _xs['bold'] + _xs['fill'] + _xs['borders_all']
    self.rt_cell_style = xlwt.easyxf(rt_cell_format)
    self.rt_cell_style_right = xlwt.easyxf(rt_cell_format + _xs['right'])       
    self.rt_cell_style_decimal = xlwt.easyxf(rt_cell_format + _xs['right'], num_format_str = report_xls.decimal_format)

    self.col_specs_template = {

        }

def get_c_specs(self, wanted, col_specs, rowtype, data):

    """
    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
    """

    row = col_specs[wanted][rowtype][:]

    row[3]=data[wanted]

    row.insert(0, wanted)
    return row



    return True

def new_xls_write_row(self, ws, row_pos, row_data, header, headrot_style, dark_style,
                  row_style=default_style, set_column_size=False ):
    r = ws.row(row_pos)
    orig_style=row_style
    for col, size, spec in row_data:    

        data = spec[4]
        if header:
            if (col!=0) & (col!=1) & (col!=2):
                row_style=headrot_style #+  'align: rotation 90;'
        else:
            if data=="X":
                row_style=dark_style #+ 'pattern: pattern solid, fore_color 0;'
            else:
                row_style=orig_style
        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



def generate_xls_report(self, _p, _xs, data, objects, wb):

    wanted_list = _p.wanted_list
    self.col_specs_template.update(_p.template_changes)
    _ = _p._
    #report_name = objects[0]._description or objects[0]._name
    report_name = _("Export Contract Countries")        
    ws = wb.add_sheet(report_name[:31])
    ws.panes_frozen = True
    ws.remove_splits = True
    ws.portrait = 0 # Landscape
    ws.fit_width_to_pages = 1
    row_pos = 0

    _xs = self.xls_styles 
    headrot_style = _xs['bold'] + _xs['fill'] + _xs['borders_all'] + 'align: rotation 90'
    xlwt_headrot=xlwt.easyxf(headrot_style) 
    dark_style = _xs['borders_all']+'pattern: pattern solid, fore_color 0;'

    #self.rh_cell_style = xlwt.easyxf(rh_cell_format)
    #self.rh_cell_style_center = xlwt.easyxf(rh_cell_format + _xs['center'])


    # set print header/footer
    ws.header_str = self.xls_headers['standard']
    ws.footer_str = self.xls_footers['standard']

    # Title
    cell_style = xlwt.easyxf(_xs['xls_title'])
    c_specs = [
        ('report_name', 1, 0, 'text', report_name),
    ]       
    row_data = self.xls_row_template(c_specs, ['report_name'])
    row_pos = self.new_xls_write_row(ws, row_pos, row_data, False, xlwt_headrot , xlwt.easyxf(dark_style), row_style=cell_style )
    row_pos += 1

    # Column headers
    c_specs = map(lambda x: self.render(x, self.col_specs_template, 'header', render_space={'_': _p._}), wanted_list)
    row_data = self.xls_row_template(c_specs, [x[0] for x in c_specs])
    row_pos = self.new_xls_write_row(ws, row_pos, row_data, True, xlwt_headrot, xlwt.easyxf(dark_style), row_style=self.rh_cell_style, set_column_size=True)        
    ws.set_horz_split_pos(row_pos)   

    # account move lines
    for line in data['contract_list']:
        c_specs = map(lambda x: self.get_c_specs(x, self.col_specs_template, 'lines', line), wanted_list)
        row_data = self.xls_row_template(c_specs, [x[0] for x in c_specs])
        row_pos = self.new_xls_write_row(ws, row_pos, row_data, False, xlwt_headrot, xlwt.easyxf(dark_style), row_style=self.aml_cell_style)


contract_products_xls('report.contract_products', 
'abc.contract.search.wizard',
parser=contract_products_parser)



回答3:


To Create an Excel file or a spreadsheet

“import xlwt” package functionality to create sheet in your Py file.We can define the title, header, number, date, and normal style using xlwt.easyxf().

For example title style is given below new_style = xlwt.easyxf(‘font:height 230; align: wrap No;border: top thick;border: bottom thick;’)

Define how the border should appear.define the workbook. Workbook is actually what we view in our spreadsheet. To define workbook, wbk = xlwt.Workbook() sheet = wbk.add_sheet(‘New_sheet’, cell_overwrite_ok=True) for write in to the sheet sheet.write(4, 4, ‘Spellbound Soft Solution’,font_size) To change the width and height of a cell, sheet.col(1).width = 500*12 sheet.row(5).height = 70*5

for more goto : http://spellboundss.com/xls-report-in-odoo/ Thanks




回答4:


  • Simply add this report_xlsx module from the app store.
  • your_module_name --> report--> my_report.py
  • your_module_name --> report--> my_report.xml

my_report.py

try:
    from openerp.addons.report_xlsx.report.report_xlsx import ReportXlsx
except ImportError:
    class ReportXlsx(object):
        def __init__(self, *args, **kwargs):
            pass

class PartnerXlsx(ReportXlsx):

    def generate_xlsx_report(self, workbook, data, partners):
        for obj in partners:
            report_name = obj.name
            # One sheet by partner
            sheet = workbook.add_worksheet(report_name[:31])
            bold = workbook.add_format({'bold': True})
            sheet.write(0, 0, obj.name, bold)


PartnerXlsx('report.res.partner.xlsx', 'res.partner')

my_report.xml

`<report
  id="partner_xlsx"
  model="res.partner"
  string="Print to XLSX"
  report_type="xlsx"
  name="res.partner.xlsx"
  file="res.partner.xlsx"
  attachment_use="False"
 />`


来源:https://stackoverflow.com/questions/37651058/how-can-i-generate-xls-report-in-odoo

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!