odoo excel报表开发总结

  1. 首先定义菜单然后是菜单动作 然后初始化一个报表动作
     
    
        Stock Out Voucher Report
        kthrp.chanyi.stock.out.voucher.report
        form
        form
        new
    
  

    
    
    
    
        Chanyi Stock Out Voucher Report
        kthrp.chanyi.stock.out.voucher.report
        ir.actions.report.xml
        kthrp.chanyi.stock.out.voucher.report.xlsx
        xlsx
        
    

2.首先定义瞬时模型和需要的字段

class KthrpChanyiStockOutVoucher(models.TransientModel):
    _name = "kthrp.chanyi.stock.out.voucher.report"
    _description = "chanyi Kthrp Stock Out Voucher Report"

    # 客户
    customer_id = fields.Many2one(string="Customer", comodel_name="kthrp.base.global.partner", domain="[('customer','=',True)]")
    # 公司
    company_id = fields.Many2one(string='Company', comodel_name="res.company", default=lambda self: self.env.user.company_id.id)
    # 处理日期自
    date_from = fields.Datetime('Processing Date from')
    # 处理日期至
    date_to = fields.Datetime('Processing Date to')
    # 输出格式
    output_format = fields.Selection([('excel', 'EXCEL')], 'Output Format', default='excel', readonly=True)
    # 产品类别
    product_category_ids = fields.Many2many(comodel_name='product.category', string='Product Category')

3.定义页面参数获取方法

@api.model
def get_datas(self):
    tmp_from = datetime.strptime(self.date_from, "%Y-%m-%d %H:%M:%S")
    date_from = (tmp_from + timedelta(hours=8)).strftime("%Y-%m-%d %H:%M:%S")
    tmp_to = datetime.strptime(self.date_from, "%Y-%m-%d %H:%M:%S")
    date_to = (tmp_to + timedelta(hours=8)).strftime("%Y-%m-%d %H:%M:%S")
    form = {
        'lang': self.env.context['lang'],
        'customer_id': self.customer_id,
        'company_id': self.company_id,
        'product_category_ids': self.product_category_ids,
        'date_from': date_from,
        'date_to': date_to,
        'output_format': self.output_format
    }
    datas = {
        'form': form,
    }
    return datas

4.获取到参数之后再通过参数过滤得到需要的数据

@api.model
def get_lines(self, datas):
    customer_id = datas['form']['customer_id']
    company_id = datas['form']['company_id']
    product_category_ids = datas['form']['product_category_ids']
    date_from = datas['form']['date_from']
    date_to = datas['form']['date_to']

    # 以销售出库的产品为维度
    # self.env['stock.move'].search([('state', '=', 'done')])
    stock_move_obj = self.env['stock.move']
    code_list = []
    for rec in stock_move_obj.search([]):
        code_list.append(rec.supplier_id.company_code)
    convert = self.env['kthrp.stock.unit.convert']
    # 客户=库存移动对应业务伙伴  库存移动状态完成   事务处理类型=库房出库
    domain = [('supplier_id.company_code', '=', customer_id.partner_number), ('state', '=', 'done'), ('transaction_type_id.code', '=', 'Stock Shipment')]
    # domain = [('transaction_type_id.code', '=', 'Stock Shipment'), ('state', '=', 'done')]
    if company_id:
        domain += [('company_id', '=', company_id.id)]
    if product_category_ids:
        centralized_cls_ids = []
        for rec in product_category_ids:
            centralized_cls_ids.append(rec.centralized_cls_id.id)
        domain += [('centralized_cls_id', 'in', centralized_cls_ids)]
    if date_from:
        domain += [('date', '>=', date_from)]
    if date_to:
        domain += [('date', '<=', date_to)]
    lines = stock_move_obj.search(domain)
    field_dict = {}
    for line in lines:
        ratio = convert.convert_unit_ratio(line.product_id.id, line.product_id.uom_id.id,
                                           line.actual_unit_id.id)
        product_number = line.product_id.product_number
        # 如果产品编号不在字典中  添加到字典中
        if product_number not in field_dict.keys():
            field_dict[product_number] = line.actual_qty * ratio
        else:
            field_dict[product_number] += line.actual_qty * ratio
    datalist = []
    field_list = []
    # 序号
    number = 1
    for line in lines:
        record = {}
        product_number = line.product_id.product_number
        # 如果该产品不在产品编码列表中
        if product_number not in field_list:
            record['origin'] = number
            record['product_number'] = line.product_id.product_number
            record['product_id'] = line.product_id.name
            record['specification'] = line.specification or ''
            record['actual_qty'] = round(field_dict[product_number], 2)
            record['actual_unit_id'] = line.actual_unit_id.name
            datalist.append(record)
            number += 1
        field_list.append(product_number)
    # 分页
    datalist = [datalist[i:i + 10] for i in range(0, len(datalist), 10)]
    return datalist
  1. 还有两个关键方法 查看方法 和 下载方法,第一个是查看第二个是下载
@api.multi
def report_view(self):

    datas = self.get_datas()
    lines = self.get_lines(datas)
    # 上下文携带数据
    context = {}
    context['customer_id'] = self.customer_id.name
    context['date_from'] = datas['form']['date_from']
    context['date_to'] = datas['form']['date_to']
    context['name'] = _('Stock Out Voucher Report')
    context['lines'] = lines
    return {
        'name': _('Stock Out Voucher Report'),
        'type': 'ir.actions.client',
        'tag': 'stock_out_voucher_report',
        'context': context,
    }

@api.multi
def report_print(self):
    name = _('Stock Out Voucher Report')
    report_name = 'kthrp.chanyi.stock.out.voucher.report.xlsx'
    return {
        'name': name,
        'type': 'ir.actions.report.xml',
        'report_name': report_name,
    }

6.定义解析类和打印数据的类

_ir_translation_name = 'stock.out.voucher.report.xlsx'

class KthrpChanyiStockOutVoucherReportParse(report_sxw.rml_parse):
    def __init__(self, cr, uid, name, context):
        super(KthrpChanyiStockOutVoucherReportParse, self).__init__(cr, uid, name, context=context)
    self.context = context
    template_changes = {}
    self.localcontext.update({
        'datetime': datetime,
        '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 KthrpChanyiStockOutVoucherReportXLSX(ReportXlsxDevelop):
    def generate_xlsx_report(self, wb, data, objs):
        # 获取数据
        data_para = objs.get_datas()
        lines_list = objs.get_lines(data_para)
        def get_lang_value(values):
            lang = self.env.user.lang
            if lang == 'zh_CN':
                return values[1]
            else:
                return values[0]

    # 获取样式(详见_get_format方法)
    general_formats = self._get_format(wb)
    # 列标题 general_formats['rh_header_format']
    other_head_left_format = wb.add_format(self.union(self.font_style, {'align': 'left', 'bold': True}))
    other_head_right_format = wb.add_format(self.union(self.font_style, {'align': 'right', 'bold': True}))
    # 文本格式
    font_format_left = {'align': 'left', 'font_size': '10', 'font_name': 'Microsoft YaHei', 'border': 1,
                        'border_color': 'black', }
    font_format_left = wb.add_format(font_format_left)
    font_format_right = {'align': 'right', 'font_size': '10', 'font_name': 'Microsoft YaHei', 'border': 1,
                        'border_color': 'black', }
    font_format_right = wb.add_format(font_format_right)
    font_format_center = {'align': 'center', 'font_size': '10', 'font_name': 'Microsoft YaHei', 'border': 1,
                         'border_color': 'black', }
    font_format_center = wb.add_format(font_format_center)
    # 设置页签
    ws = wb.add_worksheet(get_lang_value([u'Stock Out Voucher Report', u'出库凭证']))


    blue_fields = [['Origin', u'序号'], ['Product Number', u'产品编码'],
                   ['Product', u'产品'], ['Specification', u'规格'],
                   ['Qty', u'数量'], ['Unit', u'单位']]
    # fields = ['origin', 'product_number', 'product_id', 'specification', 'actual_qty', 'actual_unit_id']

    # 设置列宽
    colums_size = [30, 30, 20, 30, 30, 20]
    length = len(colums_size)
    for col in range(length):
        ws.set_column(col, col, colums_size[col])
    row_pos = 0
    col_pos = 0

    if lines_list:
        # 打印数据(数据格式为列表嵌套字典)
        for index, lines in enumerate(lines_list):

            # 打印标题
            row_pos += 1
            ws.merge_range(row_pos, col_pos, row_pos, length - 1,
                           get_lang_value(
                               [u'Stock Out Voucher Report', u'%s出库凭证' % data_para['form']['company_id'].name]),
                           general_formats['title_format'])
            row_pos += 1

            # 打印表头
            # merge_range写入,参数(行号, 合并起列号, 行号, 合并至列号, 打印数据, 格式)
            # ws.merge_range(row_pos, 0, row_pos, 1, get_lang_value([u'Customer:', u'客户:']) + data_para['form']['customer_id'].name,
            #                other_head_left_format)
            ws.write_rich_string(row_pos, col_pos,
                                 general_formats['font_bold_format'],
                                 get_lang_value([u'Customer:', u'客户:']),
                                 general_formats['font_format'],
                                 data_para['form']['customer_id'].name,
                                 wb.add_format({'align': 'left'}))
            value = u'第%d页/共%d页' % (index + 1, len(lines_list))
            ws.write(row_pos, 5, get_lang_value([u'Number', value]), general_formats['font_format'])
            # ws.merge_range(row_pos, col_pos, general_formats['font_format'])
            row_pos += 1
            ws.write_rich_string(row_pos, col_pos, general_formats['font_bold_format'],
                                 get_lang_value([u'Date From:', u'处理日期自:']),
                                 general_formats['font_format'], data_para['form']['date_from'],
                                 wb.add_format({'align': 'left'}))
            ws.write_rich_string(row_pos, col_pos + length - 1, general_formats['font_bold_format'],
                                 get_lang_value([u'Date To::', u'处理日期至:']),
                                 general_formats['font_right_format'], data_para['form']['date_to'],
                                 wb.add_format({'align': 'right'}))

            row_pos += 1

            # 设置标题栏名称,宽度
            columns = []
            for field in blue_fields:
                columns.append((field[1], 20))

            # 打印标题栏
            for i, column in enumerate(columns):
                ws.set_column(col_pos + i, col_pos + i, column[1])
                ws.write(row_pos, col_pos + i, column[0], general_formats['rh_header_format'])
            row_pos += 1
            # 固定标题
            ws.freeze_panes(row_pos, 0)

            for line in lines:
                ws.write(row_pos, 0, line['origin'], font_format_center)
                ws.write(row_pos, 1, line['product_number'], font_format_left)
                ws.write(row_pos, 2, line['product_id'], font_format_left)
                ws.write(row_pos, 3, line['specification'], font_format_left)
                ws.write(row_pos, 4, line['actual_qty'], font_format_right)
                ws.write(row_pos, 5, line['actual_unit_id'], font_format_left)
                row_pos += 1


            # 打印报表信息(表尾)(固定打印:打印人,打印时间)
            ws.write_rich_string(row_pos, col_pos, general_formats['font_bold_format'], _('Printer:'),
                                 general_formats['font_format'], objs.env.user.related_employee_id.name_get()[0][1])
            ws.write_rich_string(row_pos, col_pos + length - 1, general_formats['font_bold_right_format'], _('Print Time:')
                                 , general_formats['font_right_format'], get_context_datetime(objs, fields.Datetime.now()),
                                 wb.add_format({'align': 'right'}))
            # 首行留空
            row_pos += 1
    else:
        # 打印标题
        row_pos += 1
        ws.merge_range(row_pos, col_pos, row_pos, length - 1,
                       get_lang_value(
                           [u'Stock Out Voucher Report', u'%s出库凭证' % data_para['form']['company_id'].name]),
                       general_formats['title_format'])
        row_pos += 1

        # 打印表头
        # merge_range写入,参数(行号, 合并起列号, 行号, 合并至列号, 打印数据, 格式)
        # ws.merge_range(row_pos, 0, row_pos, 1, get_lang_value([u'Customer:', u'客户:']) + data_para['form']['customer_id'].name,
        #                other_head_left_format)
        ws.write_rich_string(row_pos, col_pos,
                             general_formats['font_bold_format'],
                             get_lang_value([u'Customer:', u'客户:']),
                             general_formats['font_format'],
                             data_para['form']['customer_id'].name,
                             wb.add_format({'align': 'left'}))
        ws.write(row_pos, 5, get_lang_value([u'Number', u'第1页/共1页']), general_formats['font_format'])
        # ws.merge_range(row_pos, col_pos, general_formats['font_format'])
        row_pos += 1
        ws.write_rich_string(row_pos, col_pos, general_formats['font_bold_format'],
                             get_lang_value([u'Date From:', u'处理日期自:']),
                             general_formats['font_format'], data_para['form']['date_from'],
                             wb.add_format({'align': 'left'}))
        ws.write_rich_string(row_pos, col_pos + length - 1, general_formats['font_bold_format'],
                             get_lang_value([u'Date To::', u'处理日期至:']),
                             general_formats['font_right_format'], data_para['form']['date_to'],
                             wb.add_format({'align': 'right'}))

        row_pos += 1

        # 设置标题栏名称,宽度
        columns = []
        for field in blue_fields:
            columns.append((field[1], 20))

        # 打印标题栏
        for i, column in enumerate(columns):
            ws.set_column(col_pos + i, col_pos + i, column[1])
            ws.write(row_pos, col_pos + i, column[0], general_formats['rh_header_format'])
        row_pos += 1
        # 固定标题
        ws.freeze_panes(row_pos, 0)

        # 打印报表信息(表尾)(固定打印:打印人,打印时间)
        ws.write_rich_string(row_pos, col_pos, general_formats['font_bold_format'], _('Printer:'),
                             general_formats['font_format'], objs.env.user.related_employee_id.name_get()[0][1])
        ws.write_rich_string(row_pos, col_pos + length - 1, general_formats['font_bold_right_format'],
                             _('Print Time:')
                             , general_formats['font_right_format'],
                             get_context_datetime(objs, fields.Datetime.now()),
                             wb.add_format({'align': 'right'}))

        KthrpChanyiStockOutVoucherReportXLSX('report.kthrp.chanyi.stock.out.voucher.report.xlsx', 'kthrp.chanyi.stock.out.voucher.report',
                                 parser=KthrpChanyiStockOutVoucherReportParse)

解析类是固定格式,只用修改类名即可,固定格式

7.上面是下载逻辑,接下来所示查看的逻辑,在上述定义了查看方法之后,对应的会有一个js动作

odoo.define('kthrp_chanyi_ext.stock_out_voucher_report', function (require) {
"use strict";

var core = require('web.core');
var Widget = require('web.Widget');
var Model = require('web.Model');
var data = require('web.data');
var QWeb = core.qweb;

var StockOutVoucherReport = Widget.extend({

    init: function (parent, context) {
        this._super(parent);

        if (context.context.active_id) {
            this.report_id = context.context.active_id;
            sessionStorage.setItem("report_id", this.report_id);
        }
        else {
            this.report_id = parseInt(sessionStorage.getItem("report_id"));
        }
        this.context = context.context;
    },
    start:function () {
        var self = this;
        var context = self.context;
        this.$el.append(QWeb.render("StockOutVoucherReport",{
            widget: this,
            name: context.name,
            customer_id: context.customer_id,
            date_from: context.date_from,
            date_to: context.date_to,
            lines: context.lines,
            }
        ));

        this.$("button").click(function () {
            var model_name = "kthrp.chanyi.stock.out.voucher.report";
            var report_model = new Model(model_name);
            report_model.call("report_print",[self.report_id])
                .then(function (action) {
                    action.context = {
                        'active_id': self.report_id,
                        'active_model': 'kthrp.chanyi.stock.out.voucher.report',
                        'active_ids': [self.report_id]
                    };
                    self.do_action(action);
                });
        });
    },
});
core.action_registry.add('stock_out_voucher_report', StockOutVoucherReport);

})
通过js动作打开对应的模板文件,然后渲染出来




    
Customer:
Date From: Date To:

记住,这两个文件都是定义在static文件目录下的
js文件需要引用声明, 类似于以下方式


                    
                    

你可能感兴趣的:(odoo excel报表开发总结)