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

我使用xlrdxlutils.copyxlwt打开一个模板文件,复制它,用新值填充它,并保存它。

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

谢谢! / 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

这有两个部分。

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

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

这保留了几乎所有的格式。 单元格注释不会被复制。

下面是一个使用代码的例子,我将build议它作为针对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()