使用 python 的 xlrd、xlwt 和 xlutils.copy 保留样式

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3723793/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 12:25:22  来源:igfitidea点击:

Preserving styles using python's xlrd,xlwt, and xlutils.copy

pythonxlrdxlwt

提问by YGA

I'm using xlrd, xlutils.copy, and xlwtto open up a template file, copy it, fill it with new values, and save it.

我正在使用xlrd, xlutils.copy, andxlwt打开一个模板文件,复制它,用新值填充它,然后保存它。

However, there doesn't seem to be any easy way to preserve the formatting of the cells; it always gets blown away and set to blank. Is there any simple way I can do this?

但是,似乎没有任何简单的方法可以保留单元格的格式。它总是被吹走并设置为空白。有什么简单的方法可以做到这一点吗?

Thanks! /YGA

谢谢!/YGA

A sample 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
  • xlrd: 0.7.1
  • xlwt: 0.7.2

回答by John Machin

Here's an example of usage of code that I'll propose as a patch against xlutils 1.4.1

这是我将建议作为针对 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()

回答by S?ren L?vborg

There are two parts to this.

这有两个部分。

First, you must enable the reading of formatting info when opening the source workbook. The copy operation will then copy the formatting over.

首先,您必须在打开源工作簿时启用格式信息的读取。然后复制操作将复制格式。

import xlrd
import xlutils.copy

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

Secondly, you must deal with the fact that changing a cell value resets the formatting of that cell.

其次,您必须处理更改单元格值会重置该单元格格式的事实。

This is less pretty; I use the following hack where I manually copy the formatting index (xf_idx) over:

这不那么漂亮;我使用以下 hack 手动复制格式索引 ( xf_idx):

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

This preserves almost all formatting. Cell comments are not copied, though.

这几乎保留了所有格式。但是,不会复制单元格注释。