I've tried both
from xlutils.copy import copy
from xlutils import copy
both works. It seems your python lib is not in your lib path. try the following code:
import sys
print (sys.path)
and check if your lib path is there. if not add the lib path using:
sys.path.append('/your-lib-path')
in python code, or add the lib path to your environment variable PYTHONPATH
Answer from Yang on Stack OverflowYou can install from pypi using pip:
pip install --user xlutils
http://pythonhosted.org/xlutils/installation.html
If pip.exe is not in your PATH use the full path to to pip.exe or replace pip with python -m pip
@Luke's answer filled the key steps to a solution.
A few extra things that I had to do to my vanilla ArcGIS install of ArcPy were:
- Added
;C:\Python27\ArcGIS10.4to myPathso thatpythonwas recognized as a command - Used
python -m pip install --user xlutilswhich I ran inC:\users\PolyGeo - When the
xlutilssite-package still did not import I went toC:\Users\PolyGeo\AppData\Roaming\Python\Python27\site-packagesand cut two foldersxlutilsandxlutils-2.0.0.dist-info - I then pasted those two folders into
C:\Python27\ArcGIS10.4\Lib\site-packages
I was then able to import xlutils.
As commented by @Luke the steps above may not have been necessary:
You should never need to cut and paste pip installed packages/modules. I use the
--userflag as I don't have admin rights to install directly to the python installation directory, but you can leave that out to install directly toC:\Python27\ArcGIS10.4. Also, the user site packages directoryC:\users\username\python27only gets added to your python path if it exists when python starts. So you would need to restart IDLE to get python to register the newly installed module. You would only need to do this once, i.e the first time you ever install using the--userflag.
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:
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.
Here's an example of usage of code that I'll propose as a patch against 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()