2013-04-17 1 views
1

Я пытаюсь автоматизировать документы Word (2010) (все 40-50 документов) с использованием компонента python и win32. В частности, нужно выбрать часть строки и заменить ее вместе с некоторым контентом. Для примера, если в исходном файле есть "Label: 096-4296-05A", я хочу, чтобы заменить "Метка: _ __ _ ___ ____". Использование поиска и замены будет работать только в том случае, если числа, присутствующие во всех файлах, одинаковы, но на самом деле это не так. Поэтому в этом случае я хочу иметь общий подход для выполнения этой задачи.Выбор и удаление строки в документе Word с использованием Python/Win32

Так что я думаю есть, если по каким-то образом я мог выбрать строку, содержащую «Ярлык 096-4296-05A» и удалить его, а затем снова написать новую строку "Этикетка _ __ _ __ _ ".

Для этого я действительно посмотрел @ Объект выбора http://msdn.microsoft.com/en-us/library/bb221235%28v=office.12%29.aspx и http://msdn.microsoft.com/en-us/library/bb208865%28v=office.12%29.aspx и даже попытался написать эквивалентный код на Python для VB.

Вот что я написал до сих пор:

... ///

######################## 
# 
# Purpose : Replace all occurrences of `find_str` with `replace_str` 
#    in `word_file 
# 
####################### 

def delete_and_add_line(word_file, find_str, replace_str): 
    wdFindContinue = 1 
    wdReplaceAll = 2 

    # Dispatch() attempts to do a GetObject() before creating a new one. 
    # DispatchEx() just creates a new one. 
    app = win32com.client.DispatchEx("Word.Application") 

    app.Visible = 0 
    app.DisplayAlerts = 0 
    app.Documents.Open(IP_Directory_Dest + "\\" + word_file) ## (word_file) 

    # expression.Execute(FindText, MatchCase, MatchWholeWord, 
    # MatchWildcards, MatchSoundsLike, MatchAllWordForms, Forward, 
    # Wrap, Format, ReplaceWith, Replace) 
    app.Selection.Find.Execute(find_str, True, True, \ 
     False, False, False, True, \ 
     wdFindContinue, False, replace_str, wdReplaceAll) 

    app.Selection.EndKey(Extend=win32com.client.constants.wdExtend)##.Select() 

    # determine if the text is selected or not 
    if (app.Selection.Type == win32com.client.constants.wdSelectionIP): 
     print 'Nothing is selected' 
    else: 
     print 'Text Selected ' 

    # to delete the selected line 
    app.Selection.Delete() 

    app.ActiveDocument.Close(SaveChanges=True) 
    app.Quit() 

... ///

Когда я выполняю этот код, я обнаружил, что приложение .Selection.Find.Execute успешно может найти и заменить текст, который ему предоставляется. Даже он печатает «Text Selected», что означает, что текст до конца строки выбран, но он никогда не удаляет выбранную строку.

Кроме того, я не уверен, что это правильный способ полностью выбрать строку до ее окончания (с помощью Select с этим дает мне ошибку атрибута "AttributeError: объект" int "не имеет атрибута 'Select'")

**### **IS THIS THE CORRECT WAY TO SELECT A LINE TILL ITS END** ???** 
    app.Selection.EndKey(Extend=win32com.client.constants.wdExtend)##.Select() 

Сообщите мне, если мне что-то не хватает. Любые предложения приветствуются.

ответ

2

Обратите внимание, что вы выполняете замену из всех матчей, что функция «Selection.Find» получает, а затем пытается расширить выбор после последнего матча, я не думаю, что это то, что вы хотите , Я также получил ошибку в том, как вы расширяете выделение, поскольку эта константа (wdExtend) не была принята Word.

Кроме того, рекомендуется закрыть документ как часть предложения finally, чтобы не оставлять Word в памяти в неизвестном состоянии.

Я думаю, что правильное решение будет проходить по всем абзацам, которые документ имеет, а затем используя регулярные выражения для соответствия и замены текста, который вы хотите заменить. Регулярные выражения намного мощнее, чем функция поиска слов. Вы можете получить доступ к тексту абзаца, используя свойство Text свойств Range. Что-то вроде:

import win32com.client 
import re 

# This is the regular expression to match the text you are after 
regexp = "Label: [0-9A-Z-]+" 

def replace_label(word_file): 
    app = win32com.client.DispatchEx("Word.Application") 
    app.Visible = 0 
    app.DisplayAlerts = 0 
    app.Documents.Open("C:\\" + word_file) 
    try: 
     doc = app.ActiveDocument 
     # Iterate over all the paragraphs 
     for parNo in range(1,doc.Paragraphs.Count): 
      paragraph = doc.Paragraphs(parNo) 
      # Get the text of the paragraph. 
      current_text = paragraph.Range.Text 
      # Check if there is a match in the paragraph 
      if re.search(regexp,current_text): 
       # We found a match... do the replace 
       paragraph.Range.Text = re.sub(regexp,"Label _______",current_text) 
    finally: 
     app.ActiveDocument.Close(SaveChanges=True) 
     app.Quit() 

Я не уверен в регулярном выражении, которое я предлагаю, поэтому вам, возможно, придется его подстроить.Лучший гид для регулярных выражений, которые я знаю, это:

http://www.zytrax.com/tech/web/regex.htm И http://docs.python.org/2/library/re.html

+0

@ Jujara: Цените свои усилия. Обязательно попробуем их и придумаем мои результаты. Однако, как вы сказали, «я также получил ошибку с тем, как вы расширяете выделение, поскольку эта константа (wdExtend) не была принята Word.», Пожалуйста, убедитесь, что вы запустили файл makepy (обычно расположенный @ C: \ Python27 \ Lib \ site-packages \ win32com \ client) и выбрали "Microsoft Word 14.0 Object Library (8.5)" из выпадающего меню. – Varun

+0

Наряду с этим, «из констант импорта win32com.client» – Varun

+0

Спасибо за информацию констант. Я снова выполнил ваш оригинальный код и обнаружил некоторые вещи, которые стоит заметить: – jujaro