1

Can anyone help me to delete an xls-file after using xlutils.filter (http://www.python-excel.org/) and fix the following error? I try to remove an excel file from the filesystem (Windows 7 64-bit) but it says:

Traceback (most recent call last):
  File "insert_n_blank_rows.py", line 93, in <module>
    main()
  File "insert_n_blank_rows.py", line 89, in main
    insert_n_blank_rows(inputfile, n_rows, position)
  File "insert_n_blank_rows.py", line 80, in insert_n_blank_rows
    os.remove(filename)
WindowsError: [Error 32] The process cannot access the file because it is being
used by another process: 'text.xls'

I would like to follow the wise advice to open files only using:

with open(inputfile) as f:
    ...

and after the with-clause just remove the file, but I do not know how to cope with that in this case. Can anyone reproduce the error and if so does anyone have a suggestion how to work around this problem? As an inputfile.xls you can just use an Excel 97 format sheet with 4 lines text in 1 column.

My python file "insert_n_blank_rows.py" is:

__author__ = "Arjen Jellema"

"""
This script will insert n empty rows after an excelsheetposition
into a excel sheet using module xlrd and xlwt
first it copies the file
and then inserts empty rows
then saves the new file
then removes the old file
"""

import os
import sys
import xlrd
import xlwt
from xlutils.filter import BaseReader, BaseFilter, BaseWriter, process

def insert_n_blank_rows(filename, n_rows, position):
    # this function will insert n blank row right after position as read from
    # an Excelsheet; so the cell A1 has row 1

    class Reader(BaseReader):
        def get_filepaths(self):
            return [os.path.abspath(filename)]

    class Filter(BaseFilter):
        pending_row = None
        def workbook(self,rdbook,wtbook_name):
            self.next.workbook(rdbook,filename+'.new')
        def row(self,rdrowx,wtrowx):
            self.pending_row = (rdrowx,wtrowx)
        def cell(self,rdrowx,rdcolx,wtrowx,wtcolx):
            row_offset = 0
            col_offset = 0
            buildHistoryIndexEnd = position
            if rdrowx >= buildHistoryIndexEnd:
                row_offset = 1
            if rdcolx > 1:
                col_offset = 0

            self.next.cell(rdrowx,rdcolx,wtrowx+row_offset,wtcolx+col_offset)

    class Writer(BaseWriter):
        def get_stream(self,filename):
            return file(filename,'wb')

    if n_rows == 0 or n_rows < 0:
        # give warning
        print "Warning: number of rows is equal to or smaller than 0,",
        print " nothing inserted"
        raw_input()
        sys.exit()
    elif n_rows == 1:
        # inserts 1 empty row or column in sheet
        process(Reader(),Filter(),Writer())
    elif n_rows == 2:
        # inserts 2 empty rows or columns in sheet
        process(Reader(),Filter(),Filter(),Writer())
    elif n_rows == 3:
        # inserts 3 empty rows or columns in sheet
        process(Reader(),Filter(),Filter(),Filter(),Writer())
    elif n_rows == 4:
        # inserts 4 empty rows or columns in sheet
        process(Reader(),Filter(),Filter(),Filter(),Filter(),Writer())
    elif n_rows == 5:
        # inserts 5 empty rows or columns in sheet
        process(Reader(),Filter(),Filter(),Filter(),Filter(),Filter(),Writer())
    elif n_rows > 5:
        # give warning
        print "Warning: number of rows exceeds 5,",
        print " nothing inserted"
        raw_input()
        sys.exit()
    else:
        print "Warning, something unexpected happened"
        raw_input()
        sys.exit()

    # remove old file
    os.remove(filename)
    os.rename(filename+".new", filename.rstrip('.new'))

def main():
    inputfile = "text.xls"

    # this will insert n rows after position
    n_rows = 3
    position = 1
    insert_n_blank_rows(inputfile, n_rows, position)


if __name__ == "__main__":
    main()
    sys.exit()
Jellema
  • 1,912
  • 1
  • 12
  • 15

2 Answers2

0

Perhaps you have to close the file before removing it.

http://pythonhosted.org/xlutils/filter.html#directorywriter

Shows a close() on a file returned by get_stream.

I'm not familiar with the library you're working with but I hope that helps.

Anthony
  • 3,492
  • 1
  • 14
  • 9
  • Thank you for your answer. After 4hrs of programming I can't find a proper close method which works. I added `def close_file(self): self.filehandle.close()` to the class Writer. But if I try: `w = Writer()`, `w.close_file()` and `print w.filehandle.closed` it outputs `True`, but somehow a file is somewhere opened. Also `proc.get_open_files()` doesn't show a `text.xls` opened. – Jellema Mar 14 '14 at 23:34
0

Ok, the problem was in the on_demand=True option. By simply overwriting the get_filepaths() in the class Reader(BaseReader) I have fixed my problem. So the class has to be written as:

class Reader(BaseReader):
    def get_filepaths(self):
        #print "os.path.abspath(filename): %s" % os.path.abspath(filename)
        return [os.path.abspath(filename)]

    def get_workbooks(self):
        for path in self.get_filepaths():
            yield (
                xlrd.open_workbook(
                    path,
                    formatting_info=1,
                    on_demand=False,
                    ragged_rows=True),
                os.path.split(path)[1]
                )
Jellema
  • 1,912
  • 1
  • 12
  • 15