text: # -*- coding: utf-8 -*-
  # Part of Odoo. See LICENSE file for full copyright and licensing details.
  
  from collections import deque
  import json
  
  from odoo import http
  from odoo.http import request
  from odoo.tools import ustr
  from odoo.tools.misc import xlwt
  
  
  class TableExporter(http.Controller):
  
      @http.route('/web/pivot/check_xlwt', type='json', auth='none')
      def check_xlwt(self):
          return xlwt is not None
  
      @http.route('/web/pivot/export_xls', type='http', auth="user")
      def export_xls(self, data, token):
          jdata = json.loads(data)
          workbook = xlwt.Workbook()
          worksheet = workbook.add_sheet(jdata['title'])
          header_bold = xlwt.easyxf("font: bold on; pattern: pattern solid, fore_colour gray25;")
          header_plain = xlwt.easyxf("pattern: pattern solid, fore_colour gray25;")
          bold = xlwt.easyxf("font: bold on;")
  
          measure_count = jdata['measure_count']
          origin_count = jdata['origin_count']
  
          # Step 1: writing col group headers
          col_group_headers = jdata['col_group_headers']
  
          # x,y: current coordinates
          # carry: queue containing cell information when a cell has a >= 2 height
          #      and the drawing code needs to add empty cells below
          x, y, carry = 1, 0, deque()
          for i, header_row in enumerate(col_group_headers):
              worksheet.write(i, 0, '', header_plain)
              for header in header_row:
                  while (carry and carry[0]['x'] == x):
                      cell = carry.popleft()
                      for j in range(measure_count * (2 * origin_count - 1)):
                          worksheet.write(y, x+j, '', header_plain)
                      if cell['height'] > 1:
                          carry.append({'x': x, 'height': cell['height'] - 1})
                      x = x + measure_count * (2 * origin_count - 1)
                  for j in range(header['width']):
                      worksheet.write(y, x + j, header['title'] if j == 0 else '', header_plain)
                  if header['height'] > 1:
                      carry.append({'x': x, 'height': header['height'] - 1})
                  x = x + header['width']
              while (carry and carry[0]['x'] == x):
                  cell = carry.popleft()
                  for j in range(measure_count * (2 * origin_count - 1)):
                      worksheet.write(y, x+j, '', header_plain)
                  if cell['height'] > 1:
                      carry.append({'x': x, 'height': cell['height'] - 1})
                  x = x + measure_count * (2 * origin_count - 1)
              x, y = 1, y + 1
  
          # Step 2: writing measure headers
          measure_headers = jdata['measure_headers']
  
          if measure_headers:
              worksheet.write(y, 0, '', header_plain)
              for measure in measure_headers:
                  style = header_bold if measure['is_bold'] else header_plain
                  worksheet.write(y, x, measure['title'], style)
                  for i in range(1, 2 * origin_count - 1):
                      worksheet.write(y, x+i, '', header_plain)
                  x = x + (2 * origin_count - 1)
              x, y = 1, y + 1
  
          # Step 3: writing origin headers
          origin_headers = jdata['origin_headers']
  
          if origin_headers:
              worksheet.write(y, 0, '', header_plain)
              for origin in origin_headers:
                  style = header_bold if origin['is_bold'] else header_plain
                  worksheet.write(y, x, origin['title'], style)
                  x = x + 1
              y = y + 1
  
          # Step 4: writing data
          x = 0
          for row in jdata['rows']:
              worksheet.write(y, x, row['indent'] * '     ' + ustr(row['title']), header_plain)
              for cell in row['values']:
                  x = x + 1
                  if cell.get('is_bold', False):
                      worksheet.write(y, x, cell['value'], bold)
                  else:
                      worksheet.write(y, x, cell['value'])
              x, y = 0, y + 1
  
          response = request.make_response(None,
              headers=[('Content-Type', 'application/vnd.ms-excel'),
                      ('Content-Disposition', 'attachment; filename=table.xls')],
              cookies={'fileToken': token})
          workbook.save(response.stream)
  
          return response
  