Excel VBA在循环中打开多个Word文件

时间:2009-05-06 19:59:41

标签: vba excel-vba word-vba excel

我提前为新手问题道歉 - 我的大多数VBA体验都是在Excel或Word到Excel中。在这种情况下,我将从Excel转到Word。我试图从一些Word表单中捕获一些数据并将其存储在Excel文件中。

现在,我的代码适用于该文件夹中的第一个文档,但在此之后,它出现了自动化错误“服务器引发了异常”(goo!)

这是我的代码:

Dim objWordApp As Object

strCurFileName = Dir(strFilePath)

Set objWordApp = CreateObject("word.application")
objWordApp.Visible = True

Do While strCurFileName <> ""

    objWordApp.documents.Open strFilePath & strCurFileName
    objWordApp.activedocument.Unprotect password:="testcode"

    {EXCEL PROCESSING HERE}

    strCurFileName = Dir
    objWordApp.activedocument.Close 0

Loop

objWordApp.Quit
Set objWordApp = Nothing

我注意到如果我退出应用程序并在循环中设置object = nothing,代码就可以正常工作。但就现在的方式而言,它在“objWordApp.documents.Open strFilePath&amp; strCurFileName”行的文件夹中的第二个文件上进行了轰炸。

我可以在循环中打开和关闭Word文档而无需反复创建对象吗?当我这样做时,它真的很慢。


感谢您的帮助 - 我更喜欢您的方式。不幸的是,我得到了相同的结果。程序第二次通过循环读取:

Set objWordDoc = objWordApp.Documents.Open(objFile.Path)

我得到的错误是:

运行时错误-2147417851(80010105) 自动化错误 服务器抛出异常。

我在常规word文档(不是我正在处理的文档)上尝试了你的代码,它运行正常。我正在运行的文档有表单字段和宏 - 不确定这是否有所不同。我已将Word中的宏安全性设置为“低”和“非常高”,以确保其他宏不会干扰。

我无法弄明白为什么它适用于第一个文档然后不适用于下一个文档。我甚至克隆了第一份文件,但没有任何区别。


但是,仍然没有运气。我唯一可以工作的是,如果我完全擦除对象并在每次打开文件时重新创建它们。

Set objFolder = FSO.GetFolder(strFilePath)

For Each objFile In objFolder.Files

    Set objWordApp = CreateObject("word.application")
    objWordApp.Visible = True

    If Right(objFile.Name, 4) = ".doc" Then
        Set objWordDoc = objWordApp.documents.Open(Filename:=objFile.Path, ConfirmConversions:=False, _
            ReadOnly:=True, AddToRecentFiles:=False, PasswordDocument:="", _
            PasswordTemplate:="", Revert:=False, WritePasswordDocument:="", _
            WritePasswordTemplate:="", Format:=wdOpenFormatAuto)

        [Process DOC]

        objWordDoc.Close 0, 1
    End If

    Set objWordDoc = Nothing
    objWordApp.Quit
    Set objWordApp = Nothing

Next

我不确定为什么会起作用以及为什么它不起作用。如果我必须走这条路,我可以 - 它看起来真的很慢而且效率低下。这是个坏主意吗?

1 个答案:

答案 0 :(得分:1)

我将Dir更改为FileSystemObject(转到Tools \ References并添加Microsoft Scripting Runtime),我能够成功打开多个文件。如果遇到问题,请描述您在调试器中看到的错误。此外,如果你需要递归到子目录,你需要重构它。

Private mobjWordApp As Word.Application

Sub Test()
  ProcessDirectory "PathName"
End Sub

Property Get WordApp() As Word.Application
  If mobjWordApp Is Nothing Then
    Set mobjWordApp = CreateObject("Word.Application")
    mobjWordApp.Visible = True
  End If
  Set WordApp = mobjWordApp
End Property

Sub CloseWordApp()
  If Not (mobjWordApp Is Nothing) Then
    On Error Resume Next
    mobjWordApp.Quit
    Set mobjWordApp = Nothing
  End If
End Sub

Function GetWordDocument(FileName As String) As Word.Document
    On Error Resume Next
    Set GetWordDocument = WordApp.Documents.Open(FileName)
    If Err.Number = &H80010105 Then
      CloseWordApp
      On Error GoTo 0
      Set GetWordDocument = WordApp.Documents.Open(FileName)
    End If
End Function

Sub ProcessDirectory(PathName As String)
  Dim fso As New FileSystemObject
  Dim objFile As File
  Dim objFolder As Folder
  Dim objWordDoc As Object

  On Error Goto Err_Handler

  Set objFolder = fso.GetFolder(PathName)
  For Each objFile In objFolder.Files
    If StrComp(Right(objFile.Name, 4), ".doc", vbTextCompare) = 0 Then
      Set objWordDoc = GetWordDocument(objFile.Path)
      ' objWordDoc.Unprotect Password:="testcode" ' Need to check if it has Password?
      ProcessDocument objWordDoc
      objWordDoc.Close 0, 1
      Set objWordDoc = Nothing
    End If
  Next

Exit_Handler:
  CloseWordApp
  Exit Sub

Err_Handler:
  MsgBox "Error " & Err.Number & ": " & Err.Description
  Resume Exit_Handler
  'Resume Next ' or as above
End Sub

Sub ProcessDocument(objWordDoc As Document)
  '{EXCEL PROCESSING HERE}'
End Sub

编辑:我添加了一些错误处理和一些重构,尽管可以完成更多的重构。

您正在打开的文件必须有一些特别之处。您可以尝试使用不同的参数来打开文档,例如:

Set objWordDoc = objWordApp.Documents.Open( _
  FileName:=objFile.Path, ReadOnly:=True)

您可能需要添加Microsoft Word作为参考,如果您这样做,则开始使用Word常量(wdDoNotSaveChanges等)。查看Documents.Open上的帮助并测试不同的参数。

此外,在调试期间使用上下文菜单中的“设置下一个语句”,也可以跳过第一个文档并直接打开第二个文档,看看是否存在问题。

编辑:如果您收到所描述的自动化错误,我已将代码更改为关闭并重新打开Word。您可能需要调整错误编号,或者只是在任何错误上关闭Word(如果Err.Number&lt;&gt; 0那么......)。

同样,对于您的文档(宏,保护等)必须有一些特殊之处,因为此代码适用于我尝试过的测试用例。您是否尝试按照与脚本相同的顺序手动打开Word中的文档,更新类似于您的流程脚本的信息,然后关闭文档以查看Word是否有什么奇怪之处?

关闭Word.Application不会伤害任何东西,但显然会明显变慢。