Préserver les styles en utilisant xlrd,xlwt et xlutils de python.copie

j'utilise xlrd,xlutils.copy et xlwt pour ouvrir un fichier de modèle, le copier, le remplir avec de nouvelles valeurs, et le sauvegarder.

cependant, il ne semble pas y avoir de moyen facile de préserver le formatage des cellules; il est toujours soufflé et mis à blanc. Y a-t-il un moyen simple pour que je puisse faire ça?

Merci! / YGA

Un exemple de script:

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')

Versions:

  • xlrd: 0.7.1
  • xlwt: 0.7.2
49
demandé sur YGA 2010-09-16 08:46:38

2 réponses

Il y a deux parties.

tout d'abord, vous devez activer la lecture des informations de formatage lors de l'ouverture du classeur source. L'opération de copie copiera ensuite le formatage.

import xlrd
import xlutils.copy

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

Deuxièmement, vous devez gérer le fait que changer la valeur d'une cellule réinitialise le formatage de cette cellule.

C'est moins joli; j'utilise le hack suivant où je copie manuellement l'index de formatage (xf_idx) sur:

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')

Cela préserve presque toute la mise en forme. Les commentaires sur les cellules ne sont cependant pas copiés.

44
répondu Søren Løvborg 2011-10-07 11:23:24

voici un exemple d'utilisation du code que je vais proposer comme patch contre 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()
11
répondu John Machin 2011-03-15 01:28:17