osbzr/gooderp_addons

View on GitHub
web_export_view_good/controllers/controllers.py

Summary

Maintainability
C
1 day
Test Coverage
# -*- coding: utf-8 -*-
##############################################################################
#
#    Copyright (C) 2012 Domsense srl (<http://www.domsense.com>)
#    Copyright (C) 2012-2013:
#        Agile Business Group sagl (<http://www.agilebg.com>)
#    Copyright (C) 2016 开阖有限公司 (<http://www.osbzr.com>)
#
#    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/>.
#
##############################################################################
try:
    import json
except ImportError:
    import simplejson as json
import time
import odoo.http as http
from odoo.http import request
from odoo.addons.web.controllers.main import ExcelExport
from odoo import models, fields, api
import xlwt
import xlrd
import datetime
import StringIO
import re
from xlutils.copy import copy
from odoo.tools import misc
from odoo import http
import odoo
import urllib2


class ReportTemplate(models.Model):
    _name = "report.template"
    _description = u'报表模板'

    model_id = fields.Many2one('ir.model', u'模型',required=True)
    file_address = fields.Char(u'模板文件路径',required=True)
    active = fields.Boolean(u'可用', default=True)
    blank_rows = fields.Integer(u'空白行数',required=True)
    header_rows = fields.Integer(u'表头行数')

    @api.model
    def get_time(self, model):
        ISOTIMEFORMAT = "%Y-%m-%d"
        report_model = self.env['report.template'].search(
            [('model_id.model', '=', model)], limit=1)
        file_address = report_model and report_model[0].file_address or False
        blank_rows = report_model and report_model[0].blank_rows or False
        header_rows = report_model and report_model[0].header_rows or False
        return (str(time.strftime(ISOTIMEFORMAT, time.localtime(time.time()))), file_address,blank_rows,header_rows)


def content_disposition(filename):
    filename = odoo.tools.ustr(filename)
    escaped = urllib2.quote(filename.encode('utf8'))
    browser = request.httprequest.user_agent.browser
    version = int(
        (request.httprequest.user_agent.version or '0').split('.')[0])
    if browser == 'msie' and version < 9:
        return "attachment; filename=%s" % escaped
    elif browser == 'safari' and version < 537:
        return u"attachment; filename=%s.xls" % filename.encode('ascii', 'replace')
    else:
        return "attachment; filename*=UTF-8''%s.xls" % escaped


class ExcelExportView(ExcelExport, ):
    def __getattribute__(self, name):
        if name == 'fmt':
            raise AttributeError()
        return super(ExcelExportView, self).__getattribute__(name)

    @http.route('/web/export/export_xls_view', type='http', auth='user')
    def export_xls_view(self, data, token):
        data = json.loads(data)
        files_name = data.get('files_name', [])
        columns_headers = data.get('headers', [])
        rows = data.get('rows', [])
        file_address = data.get('file_address', [])

        return request.make_response(
            self.from_data_excel(columns_headers, [rows, file_address]),
            headers=[
                ('Content-Disposition', content_disposition(files_name)),
                ('Content-Type', self.content_type)],
            cookies={'fileToken': token}
        )

    # 修改值

    def setOutCell(self, outSheet, col, row, value):
        """ Change cell value without changing formatting. """

        # 本方法来自 葡萄皮的数据空间[http://biotopiblog.sinaapp.com]
        # 链接http://biotopiblog.sinaapp.com/2014/06/python读写excel如何保留原有格式/
        def _getOutCell(outSheet, colIndex, rowIndex):
            """ HACK: Extract the internal xlwt cell representation. """
            # row = outSheet._Worksheet__rows.get(rowIndex)
            row = outSheet._Worksheet__rows.get(rowIndex)
            if not row:
                return None
            cell = row._Row__cells.get(colIndex)
            return cell

        previousCell = _getOutCell(outSheet, col, row)
        if value:
            outSheet.write(row, col, value)
        # HACK, PART II
        if previousCell:
            newCell = _getOutCell(outSheet, col, row)
            if newCell:
                newCell.xf_idx = previousCell.xf_idx
                # END HACK

    def style_data(self):
        style = xlwt.easyxf(
            'font: bold on,height 300;align: wrap on,vert centre, horiz center;')
        colour_style = xlwt.easyxf('align: wrap yes,vert centre, horiz center;pattern: pattern solid, \
                                   fore-colour light_orange;border: left thin,right thin,top thin,bottom thin')

        base_style = xlwt.easyxf('align: wrap yes,vert centre, horiz left; pattern: pattern solid, \
                                     fore-colour light_yellow;border: left thin,right thin,top thin,bottom thin')
        float_style = xlwt.easyxf('align: wrap yes,vert centre, horiz right ; pattern: pattern solid,\
                                      fore-colour light_yellow;border: left thin,right thin,top thin,bottom thin')
        date_style = xlwt.easyxf('align: wrap yes; pattern: pattern solid,fore-colour light_yellow;border: left thin,right thin,top thin,bottom thin\
                                     ', num_format_str='YYYY-MM-DD')
        datetime_style = xlwt.easyxf('align: wrap yes; pattern: pattern solid, fore-colour light_yellow;\
                                         protection:formula_hidden yes;border: left thin,right thin,top thin,bottom thin',
                                     num_format_str='YYYY-MM-DD HH:mm:SS')
        return style, colour_style, base_style, float_style, date_style, datetime_style

    def from_data_excel(self, fields, rows_file_address):
        rows, file_address = rows_file_address
        if file_address:
            bk = xlrd.open_workbook(misc.file_open(
                file_address).name, formatting_info=True)
            workbook = copy(bk)
            worksheet = workbook.get_sheet(0)
            for i, fieldname in enumerate(fields):
                self.setOutCell(worksheet, 0, i, fieldname)
            for row, row_vals in enumerate(rows):
                for col, col_value in enumerate(row_vals):
                    if isinstance(col_value, basestring):
                        col_value = re.sub("\r", " ", col_value)
                    self.setOutCell(worksheet, col, row + 1, col_value)
        else:
            workbook = xlwt.Workbook()
            worksheet = workbook.add_sheet('Sheet 1')
            style, colour_style, base_style, float_style, date_style, datetime_style = self.style_data()
            worksheet.write_merge(0, 0, 0, len(
                fields) - 1, fields[0], style=style)
            worksheet.row(0).height = 400
            worksheet.row(2).height = 400
            columnwidth = {}
            for row_index, row in enumerate(rows):
                for cell_index, cell_value in enumerate(row):
                    if cell_index in columnwidth:
                        if len("%s" % (cell_value)) > columnwidth.get(cell_index):
                            columnwidth.update(
                                {cell_index: len("%s" % (cell_value))})
                    else:
                        columnwidth.update(
                            {cell_index: len("%s" % (cell_value))})
                    if row_index == 0:
                        cell_style = colour_style
                    elif row_index != len(rows) - 1:
                        cell_style = base_style
                        if isinstance(cell_value, basestring):
                            cell_value = re.sub("\r", " ", cell_value)
                        elif isinstance(cell_value, datetime.datetime):
                            cell_style = datetime_style
                        elif isinstance(cell_value, datetime.date):
                            cell_style = date_style
                        elif isinstance(cell_value, float) or isinstance(cell_value, int):
                            cell_style = float_style
                    else:
                        cell_style = xlwt.easyxf()
                    worksheet.write(row_index + 1, cell_index,
                                    cell_value, cell_style)
            for column, widthvalue in columnwidth.items():
                """参考 下面链接关于自动列宽(探讨)的代码
                 http://stackoverflow.com/questions/6929115/python-xlwt-accessing-existing-cell-content-auto-adjust-column-width"""
                if (widthvalue + 3) * 367 >= 65536:
                    widthvalue = 50
                worksheet.col(column).width = (widthvalue + 4) * 367
        # frozen headings instead of split panes
        worksheet.set_panes_frozen(True)
        # in general, freeze after last heading row
        worksheet.set_horz_split_pos(3)
        # if user does unfreeze, don't leave a split there
        worksheet.set_remove_splits(True)
        fp_currency = StringIO.StringIO()
        workbook.save(fp_currency)
        fp_currency.seek(0)
        data = fp_currency.read()
        fp_currency.close()
        return data