1

I write python script to edit MS Office Word documents. It is very important for me to edit .docx file when it is opened in Word. Python must change it. I use python library docx to do it. Code works fine, but it cannot edit ms-word document when it is opened in MS Word. I get error

PermissionError: [Errno 13] Permission denied: 'demo.docx'

To solve this problem I tried everything recommended in this post:

PermissionError: [Errno 13] Permission denied

  1. Running cmd.exe as and admin
  2. Creating shortcut with elevated privileges
  3. Changing the permissions on the python executable

Nothing helps. I always get Error:

PermissionError: [Errno 13] Permission denied: 'demo.docx'

Python code doesn't matter, but I post it here too (code works, problem is in permissions):

from docx import Document
from docx.shared import Inches
import traceback 
try: 
    document = Document()
    document.add_heading('Document Title', 0)
    p = document.add_paragraph('A plain paragraph having some ')
    p.add_run('bold').bold = True
    p.add_run(' and some ')
    p.add_run('italic.').italic = True
    document.add_heading('Heading, level 1', level=1)
    document.add_paragraph('Intense quote', style='Intense Quote')
    document.add_paragraph(
        'first item in unordered list', style='List Bullet'
    )
    document.add_paragraph(
        'first item in ordered list', style='List Number'
    )
    #document.add_picture('monty-truth.png', width=Inches(1.25))
    records = (
        (3, '101', 'Spam'),
        (7, '422', 'Eggs'),
        (4, '631', 'Spam, spam, eggs, and spam')
    )
    table = document.add_table(rows=1, cols=3)
    hdr_cells = table.rows[0].cells
    hdr_cells[0].text = 'Qty'
    hdr_cells[1].text = 'Id'
    hdr_cells[2].text = 'Desc'
    for qty, id, desc in records:
        row_cells = table.add_row().cells
        row_cells[0].text = str(qty)
        row_cells[1].text = id
        row_cells[2].text = desc
    document.add_page_break()
    document.save('demo.docx')
except:
    traceback.print_exc() 
Charles Kenyon
  • 869
  • 1
  • 8
  • 19
Igor K.
  • 813
  • 6
  • 17
  • 1
    You're asking how to break the contract the operating system has made with the MS Word application when it granted it exclusive write access to the file so that your program can make concurrent changes? – kjhughes Nov 28 '20 at 16:57
  • @kjhughes I don't have a lot of knowledge in this field. Your answer means this is impossible? May be VBA-Python binds can help? – Igor K. Nov 28 '20 at 17:00
  • I'll leave "impossible" declarations to those with detailed Windows systems programming expertise, but realize that what you're trying to do is in direct conflict with the fact that the MS Word application has opened the document with exclusive write access. The "permission denied" error that you're receiving is the operating system saying that it's already given away write access to another program -- you can't also have it. – kjhughes Nov 28 '20 at 17:07
  • Have you considered writing an [add-in](https://support.microsoft.com/en-us/office/view-manage-and-install-add-ins-in-office-programs-16278816-1948-4028-91e5-76dca5380f8d)? – kjhughes Nov 28 '20 at 17:12
  • @kjhughes now I try to do it with xlwings. But I don't know will it help.https://docs.xlwings.org/en/0.21.4/index.html – Igor K. Nov 28 '20 at 17:27
  • I second the suggestion to write a Word add-in to do this. VBA, VB or C# Interop, and Office.js are your options for add-in technology. – John Korchok Nov 28 '20 at 17:43

1 Answers1

1

As mentioned in the comments, you cannot modify a Word document that is already open with another application (namely: python-docx module).

However, you can access directly Word (same thing with Excel) by using win32api / pywin32.

You can do everything you could do with VBA with a syntax that is similar (just translated to Python).

It's heavy and ugly, but at least it works.

This is an example of code from this blog: https://www.blog.pythonlibrary.org/2010/07/16/python-and-microsoft-office-using-pywin32/

import win32com.client as win32

RANGE = range(3, 8)

def edit_word():
    word = win32.gencache.EnsureDispatch('Word.Application')
    doc = word.Documents.Add()
    word.Visible = True
    rng = doc.Range(0,0)
    rng.InsertAfter('Hacking Word with Python\r\n\r\n')
    sleep(1)
    for i in RANGE:
        rng.InsertAfter('Line %d\r\n' % i)
        sleep(1)
    rng.InsertAfter("\r\nPython rules!\r\n")
    doc.Close(False)
    word.Application.Quit()
Jean-Francois T.
  • 11,549
  • 7
  • 68
  • 107