我正在尝试使用python和win32组件自动化Word(2010)文档(所有大多数40-50个文档)。具体来说,需要选择一部分行并将其全部替换为一些内容。例如,如果在原始文件中有“标签:096-4296-05A ”,我希望将其替换为“标签: _ __ < em> _ __ _ ____ “。只有当所有文件中的数字相同,但实际上它们不相同时,才使用搜索和替换。所以在这种情况下,我希望有一个通用的方法来执行这项任务。
所以我想的是,如果我可以选择包含“标签096-4296-05A ”的行并将其删除,然后再写一个新行,如“标签 _ __ _ __ _ “。
为此,我确实看了@ Selection Object 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,甚至尝试为VB编写一些等效的python代码。
这是我到现在所写的:
... ///
########################
#
# 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()
... ///
当我执行此代码时,我发现app.Selection.Find.Execute能够成功找到并替换提供给它的文本。 即使它打印“文本选择”,这意味着选择了行尾的文本,但它永远不会删除选定的行。
另外,我不确定这是否是完全选择直到结束的正确方法(使用Select with this给我属性错误“AttributeError:'int'对象没有属性'Select'”)
**### **IS THIS THE CORRECT WAY TO SELECT A LINE TILL ITS END** ???**
app.Selection.EndKey(Extend=win32com.client.constants.wdExtend)##.Select()
如果我在这里遗漏了一些东西,请告诉我。欢迎任何建议。
答案 0 :(得分:2)
请注意,您正在执行所有替换功能“Selection.Find”获得的匹配,然后尝试在最后一次匹配后扩展选择 ,I不要以为那就是你想要的。我对扩展选择的方式也有错误,因为Word不接受此常量(wdExtend)。
此外,最好将文档作为finally子句的一部分关闭,以避免将Word保留在内存中的未知状态。
我认为正确的解决方案是遍历文档的所有段落,然后使用正则表达式来匹配和替换要替换的文本。正则表达式比单词find函数强大得多。您可以使用Range属性的Text属性访问段落的文本。类似的东西:
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