我正在使用xlrd
,xlutils.copy
和xlwt
来打开模板文件,复制它,用新值填充并保存。
但是,似乎没有任何简单的方法来保留单元格的格式;它总是被吹走,并被设置为空白。有什么简单的方法可以做到这一点吗?
谢谢! / YGA
示例脚本:
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')
版本:
xlrd
:0.7.1 xlwt
:0.7.2 答案 0 :(得分:48)
这有两个部分。
首先,您必须在打开源工作簿时启用格式信息的读取。然后,复制操作将复制格式。
import xlrd
import xlutils.copy
inBook = xlrd.open_workbook('input.xls', formatting_info=True)
outBook = xlutils.copy.copy(inBook)
其次,您必须处理这样一个事实:更改单元格值会重置该单元格的格式。
这不太漂亮;我使用以下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')
这几乎保留了所有格式。但是,不会复制单元格注释。
答案 1 :(得分:12)
以下是我将作为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()