2010-09-16 14 views
47

Estoy usando xlrd, xlutils.copy y xlwt para abrir un archivo de plantilla, copiarlo, completarlo con nuevos valores y guardarlo.Preservar estilos utilizando python's xlrd, xlwt y xlutils.copy

Sin embargo, no parece haber una manera fácil de preservar el formateo de las celdas; siempre sale volando y se pone en blanco. ¿Hay alguna manera simple de que pueda hacer esto?

Gracias! /Yga

un script de ejemplo:

from xlrd import open_workbook 
from xlutils.copy import copy 
rb = open_workbook('output_template.xls',formatting_info=True) 
rs = rb.sheet_by_index(0) 
wb = copy(rb) 
ws = wb.get_sheet(0) 
for i,cell in enumerate(rs.col(8)): 
    if not i: 
     continue 
    ws.write(i,2,22,plain) 
wb.save('output.xls') 

Versiones:

  • xlrd: 0.7.1
  • xlwt: 0.7.2

Respuesta

10

Aquí está un ejemplo de uso del código que voy a proponer como un parche contra xlutils 1.4.1

# coding: ascii 

import xlrd, xlwt 

# Demonstration of copy2 patch for xlutils 1.4.1 

# Context: 
# xlutils.copy.copy(xlrd_workbook) -> xlwt_workbook 
# copy2(xlrd_workbook) -> (xlwt_workbook, style_list) 
# style_list is a conversion of xlrd_workbook.xf_list to xlwt-compatible styles 

# Step 1: Create an input file for the demo 
def create_input_file(): 
    wtbook = xlwt.Workbook() 
    wtsheet = wtbook.add_sheet(u'First') 
    colours = 'white black red green blue pink turquoise yellow'.split() 
    fancy_styles = [xlwt.easyxf(
     'font: name Times New Roman, italic on;' 
     'pattern: pattern solid, fore_colour %s;' 
     % colour) for colour in colours] 
    for rowx in xrange(8): 
     wtsheet.write(rowx, 0, rowx) 
     wtsheet.write(rowx, 1, colours[rowx], fancy_styles[rowx]) 
    wtbook.save('demo_copy2_in.xls') 

# Step 2: Copy the file, changing data content 
# ('pink' -> 'MAGENTA', 'turquoise' -> 'CYAN') 
# without changing the formatting 

from xlutils.filter import process,XLRDReader,XLWTWriter 

# Patch: add this function to the end of xlutils/copy.py 
def copy2(wb): 
    w = XLWTWriter() 
    process(
     XLRDReader(wb,'unknown.xls'), 
     w 
     ) 
    return w.output[0][1], w.style_list 

def update_content(): 
    rdbook = xlrd.open_workbook('demo_copy2_in.xls', formatting_info=True) 
    sheetx = 0 
    rdsheet = rdbook.sheet_by_index(sheetx) 
    wtbook, style_list = copy2(rdbook) 
    wtsheet = wtbook.get_sheet(sheetx) 
    fixups = [(5, 1, 'MAGENTA'), (6, 1, 'CYAN')] 
    for rowx, colx, value in fixups: 
     xf_index = rdsheet.cell_xf_index(rowx, colx) 
     wtsheet.write(rowx, colx, value, style_list[xf_index]) 
    wtbook.save('demo_copy2_out.xls') 

create_input_file() 
update_content() 
+0

Una mejor solución sería xlwt agregando un 'wb.write_value (row, col, value)'. Esto funciona, pero tiene mucho olor a código en mi libro, trabajando en torno a una implementación deficiente de xlwt. – boatcoder

+0

¿Pasó esto alguna vez? – YGA

42

Hay dos partes en esto.

Primero, debe habilitar la lectura de la información de formato al abrir el libro de trabajo de origen. La operación de copiado luego copiará el formateo.

import xlrd 
import xlutils.copy 

inBook = xlrd.open_workbook('input.xls', formatting_info=True) 
outBook = xlutils.copy.copy(inBook) 

En segundo lugar, debe lidiar con el hecho de que el cambio de un valor de celda restablece el formato de esa célula.

Esto es menos bonito; Yo uso este truco donde copio manualmente el índice de formato (xf_idx) sobre: ​​

def _getOutCell(outSheet, colIndex, rowIndex): 
    """ HACK: Extract the internal xlwt cell representation. """ 
    row = outSheet._Worksheet__rows.get(rowIndex) 
    if not row: return None 

    cell = row._Row__cells.get(colIndex) 
    return cell 

def setOutCell(outSheet, col, row, value): 
    """ Change cell value without changing formatting. """ 
    # HACK to retain cell style. 
    previousCell = _getOutCell(outSheet, col, row) 
    # END HACK, PART I 

    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 

outSheet = outBook.get_sheet(0) 
setOutCell(outSheet, 5, 5, 'Test') 
outBook.save('output.xls') 

Esto conserva casi todo el formato. Sin embargo, los comentarios de la celda no se copian.

+0

pero las referencias de celda en las otras hojas ¡faltan! – deeshank

Cuestiones relacionadas