【问题标题】:Loop over PDF files and transform them into doc with word循环PDF文件并将其转换为带有word的文档
【发布时间】:2018-02-04 00:31:15
【问题描述】:

我正在尝试使用 VBA 编码(我很陌生)从 PDF(不是图像)中获取一系列 .doc 文档,也就是说,我正在尝试遍历各种 PDF 文件并保存它们MS Word 格式。我的经验是 word 可以很好地阅读我拥有的 PDF 文档:word 大部分时间都保持 PDF 文件的正确布局。我不确定这是否是解决此问题的正确选择,我要求提供替代建议 - 如果可能,请使用 R。

不管怎样,这是我找到的代码here

Sub convertToWord()

   Dim MyObj As Object, MySource As Object, file As Variant

   file = Dir("C:\Users\username\work_dir_example" & "*.pdf") 'pdf path

   Do While (file <> "")

   ChangeFileOpenDirectory "C:\Users\username\work_dir_example"

          Documents.Open Filename:=file, ConfirmConversions:=False, ReadOnly:= _
        False, AddToRecentFiles:=False, PasswordDocument:="", PasswordTemplate:= _
        "", Revert:=False, WritePasswordDocument:="", WritePasswordTemplate:="", _
        Format:=wdOpenFormatAuto, XMLTransform:=""

    ChangeFileOpenDirectory "C:\Users\username\work_dir_example"

    ActiveDocument.SaveAs2 Filename:=Replace(file, ".pdf", ".docx"), FileFormat:=wdFormatXMLDocument _
        , LockComments:=False, Password:="", AddToRecentFiles:=True, _
        WritePassword:="", ReadOnlyRecommended:=False, EmbedTrueTypeFonts:=False, _
         SaveNativePictureFormat:=False, SaveFormsData:=False, SaveAsAOCELetter:= _
        False, CompatibilityMode:=15

    ActiveDocument.Close

     file = Dir

   Loop

End Sub

将代码粘贴到开发者窗口后,我将代码保存在模块中 -> 关闭开发者窗口 -> 点击“宏”按钮 -> 执行“convertToWord”宏。我在弹出框中收到以下错误:“未定义子或功能”。我该如何解决?另外,以前,由于某些我现在不清楚的原因,我收到了与函数ChangeFileOpenDirectory 相关的错误,该函数似乎也没有定义。

2017 年 8 月 27 日更新

我把代码改成如下:

Sub convertToWord()

   Dim MyObj As Object, MySource As Object, file As Variant

   file = Dir("C:\Users\username\work_dir_example" & "*.pdf")

   ChDir "C:\Users\username\work_dir_example"

   Do While (file <> "")

        Documents.Open Filename:=file, ConfirmConversions:=False, ReadOnly:= _
        False, AddToRecentFiles:=False, PasswordDocument:="", PasswordTemplate:= _
        "", Revert:=False, WritePasswordDocument:="", WritePasswordTemplate:="", _
        Format:=wdOpenFormatAuto, XMLTransform:=""

        ActiveDocument.SaveAs2 Filename:=Replace(file, ".pdf", ".docx"), FileFormat:=wdFormatXMLDocument _
        , LockComments:=False, Password:="", AddToRecentFiles:=True, _
        WritePassword:="", ReadOnlyRecommended:=False, EmbedTrueTypeFonts:=False, _
         SaveNativePictureFormat:=False, SaveFormsData:=False, SaveAsAOCELetter:= _
        False, CompatibilityMode:=15

    ActiveDocument.Close

     file = Dir

   Loop

End Sub

现在我在弹出框中没有收到任何错误消息,但我的工作目录中没有输出。现在可能有什么问题?

【问题讨论】:

  • (a) Dir("C:\Users\...t" &amp; "*.pdf") 是否暗示您的目录以 t 结尾?如果是这样,那应该是Dir("C:\Users\...t\" &amp; "*.pdf")(或者,为了节省一点处理时间,Dir("C:\Users\...t\*.pdf"))。 (b) 我不确定为什么ChangeFileOpenDirectory 会失败,除了您指定的目录可能不存在或您无权访问它。
  • 只需删除两个ChangeFileOpenDirectory ... 行。使用完整路径打开和保存文件
  • 我尝试了一些建议。我会更新问题。
  • 另外,为了避免误会,我把目录路径改成了C:\Users\username\work_dir_example
  • 我知道您请求了 VBA,但正如您所提到的,您可以使用其他选择:如果您可以访问 *nix 机器和 LibreOffice,您可以尝试一下:stackoverflow.com/questions/26358281/…

标签: vba pdf ms-word


【解决方案1】:

正如其他人所说,问题似乎主要在于路径和文件名。这是您发布的代码的第二个版本,有一些更改。

不幸的是,会弹出一条警告消息,将 DisplayAlerts 设置为 false 不会抑制它。但是如果你在第一次弹出时点击了“不再显示此消息”复选框,那么它不会继续为每个文件弹出。

Sub convertToWord()

    Dim MyObj       As Object
    Dim MySource    As Object
    Dim file        As String
    Dim path        As String

    path = "C:\Users\username\work_dir_example\"
    file = Dir(path & "*.pdf")

    Do While (file <> "")
        Documents.Open FileName:=path & file
        With ActiveDocument
            .SaveAs2 FileName:=Replace(path & file, ".pdf", ".docx"), _
                                FileFormat:=wdFormatXMLDocument
            .Close
        End With
        file = Dir
    Loop

End Sub

【讨论】:

    【解决方案2】:

    任何可以读取 PDF 文件和编写 Word 文档(即 XML)的语言都可以执行此操作,但您喜欢的转换(Word 在打开 PDF 时执行的操作)将需要使用应用程序本身的 API。 VBA 是您的简单选择。

    您发布的 sn-ps(以及下面的示例)使用早期绑定和枚举常量,这意味着我们需要对 Word 对象库的引用。这已经为您在 Word 文档中编写的任何代码设置,因此创建一个新的 Word 文档并将代码添加到标准模块中。 (如果您需要更多详细信息,请参阅此Excel tutorial,我们的流程步骤相同。

    您可以从 VB 编辑器(使用“运行”按钮)或普通文档窗口(单击 Word 2010-2016 中“查看”选项卡上的“宏”按钮)运行宏。如果您想在不重新设置代码的情况下重复使用宏,请将您的文档另存为 DOCM 文件。

    现在是代码!

    如 cmets 中所述,如果您确保文件夹路径以反斜杠“\”字符结尾,则您的第二个 sn-p 是有效的。在你修复它之后它仍然不是很好的代码,但这会让你启动并运行。

    我假设您想要加倍努力并拥有一个编写良好的版本,您可以稍后重新调整用途或扩展。为简单起见,我们将使用两个过程:主转换和抑制 PDF 转换警告对话框的过程(由注册表控制)。

    主要程序:

    Sub ConvertPDFsToWord2()
        Dim path As String
        'Manually edit path in the next line before running
        path = "C:\users\username\work_dir_example\"
    
        Dim file As String
        Dim doc As Word.Document
        Dim regValPDF As Integer
        Dim originalAlertLevel As WdAlertLevel
    
    'Generate string for getting all PDFs with Dir command
        'Check for terminal \
        If Right(path, 1) <> "\" Then path = path & "\"
        'Append file type with wildcard
        file = path & "*.pdf"
    
        'Get path for first PDF (blank string if no PDFs exist)
        file = Dir(file)
    
        originalAlertLevel = Application.DisplayAlerts
        Application.DisplayAlerts = wdAlertsNone
    
        If file <> "" Then regValPDF = TogglePDFWarning(1)
    
        Do While file <> ""
            'Open method will automatically convert PDF for editing
            Set doc = Documents.Open(path & file, False)
    
            'Save and close document
            doc.SaveAs2 path & Replace(file, ".pdf", ".docx"), _
                        fileformat:=wdFormatDocumentDefault
            doc.Close False
    
            'Get path for next PDF (blank string if no PDFs remain)
            file = Dir
        Loop
    
    CleanUp:
        On Error Resume Next 'Ignore errors during cleanup
        doc.Close False
        'Restore registry value, if necessary
        If regValPDF <> 1 Then TogglePDFWarning regValPDF
        Application.DisplayAlerts = originalAlertLevel
    
    End Sub
    

    注册表设置功能:

    Private Function TogglePDFWarning(newVal As Integer) As Integer
    'This function reads and writes the registry value that controls
    'the dialog displayed when Word opens (and converts) a PDF file
        Dim wShell As Object
        Dim regKey As String
        Dim regVal As Variant
    
        'setup shell object and string for key
        Set wShell = CreateObject("WScript.Shell")
        regKey = "HKCU\SOFTWARE\Microsoft\Office\" & _
                 Application.Version & "\Word\Options\"
    
        'Get existing registry value, if any
        On Error Resume Next 'Ignore error if reg value does not exist
        regVal = wShell.RegRead(regKey & "DisableConvertPdfWarning")
        On Error GoTo 0      'Break on errors after this point
    
        wShell.regwrite regKey & "DisableConvertPdfWarning", newVal, "REG_DWORD"
    
        'Return original setting / registry value (0 if omitted)
        If Err.Number <> 0 Or regVal = 0 Then
            TogglePDFWarning = 0
        Else
            TogglePDFWarning = 1
        End If
    
    End Function
    

    【讨论】:

    • TogglePDFWarning 函数有问题。我是否将其插入另一个模块?我需要一个库来正确调用它吗?
    • 我已经解决了这个问题。我需要将私有函数作为过程输入。既然你已经设法得到了答案——而且我无法检查你是否及时正确——有没有办法为你“捐赠”额外的 25 分?
    • 运行代码时,我在Set doc = Documents.Open(path &amp; file, False) 行收到一条错误消息,上面写着>运行时错误'-2147221164 (80040154)':未定义类
    • @Capt.Krusty 没有找到 Documents 类,这可能意味着您对 Word 库或相关 DLL 文件的引用存在问题。我会先尝试在新的 DOCM 文件中再次执行这些步骤。如果这不起作用,您将在代码之外进行一些故障排除。 :(
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-25
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-10
    相关资源
    最近更新 更多