2013-05-14 53 views
19

我试图使用PowerShell做文字DOCX的批量转换为PDF - 使用本网站上的脚本: http://blogs.technet.com/b/heyscriptingguy/archive/2013/03/24/weekend-scripter-convert-word-documents-to-pdf-files-with-powershell.aspx基本PowerShell的 - 批量转换的Word DOCX到PDF

# Acquire a list of DOCX files in a folder 
$Files=GET-CHILDITEM "C:\docx2pdf\*.DOCX" 
$Word=NEW-OBJECT –COMOBJECT WORD.APPLICATION 

Foreach ($File in $Files) { 
    # open a Word document, filename from the directory 
    $Doc=$Word.Documents.Open($File.fullname) 

    # Swap out DOCX with PDF in the Filename 
    $Name=($Doc.Fullname).replace("docx","pdf") 

    # Save this File as a PDF in Word 2010/2013 
    $Doc.saveas([ref] $Name, [ref] 17) 
    $Doc.close() 
} 

我不停的得到这个错误,不知道为什么:

PS C:\docx2pdf> .\docx2pdf.ps1 
Exception calling "SaveAs" with "16" argument(s): "Command failed" 
At C:\docx2pdf\docx2pdf.ps1:13 char:13 
+  $Doc.saveas <<<< ([ref] $Name, [ref] 17) 
    + CategoryInfo   : NotSpecified: (:) [], MethodInvocationException 
    + FullyQualifiedErrorId : DotNetMethodException 

任何想法?

另外 - 我将如何改变它也转换文档(不DOCX)文件,以及使用本地文件(与脚本位置相同的位置的文件)?

对不起 - 从来没有做过PowerShell脚本...

回答

42

这将为DOC以及DOCX文件。

$documents_path = 'c:\doc2pdf' 

$word_app = New-Object -ComObject Word.Application 

# This filter will find .doc as well as .docx documents 
Get-ChildItem -Path $documents_path -Filter *.doc? | ForEach-Object { 

    $document = $word_app.Documents.Open($_.FullName) 

    $pdf_filename = "$($_.DirectoryName)\$($_.BaseName).pdf" 

    $document.SaveAs([ref] $pdf_filename, [ref] 17) 

    $document.Close() 
} 

$word_app.Quit() 
+4

这个工作 - 感谢 - 改变$ documents_path使用'$ documents_path =拆分路径-parent $ MyInvocation.MyCommand.Path' – takabanana 2013-05-14 22:16:27

+0

是OLEDB使用基于脚本的位置是动态在这个转换中? – culter 2013-10-28 14:37:01

+2

您还应该释放COM对象:'[System.Runtime.Interopservices.Marshal] :: ReleaseComObject($ word_app)'。 [The Scripting Guys](http://technet.microsoft.com/zh-cn/library/ff730962.aspx)还建议删除整个变量:'Remove-Variable word_app' – ComFreek 2014-11-02 18:37:50

3

这对我的作品(Word 2007中):

$wdFormatPDF = 17 
$word = New-Object -ComObject Word.Application 
$word.visible = $false 

$folderpath = Split-Path -parent $MyInvocation.MyCommand.Path 

Get-ChildItem -path $folderpath -recurse -include "*.doc" | % { 
    $path = ($_.fullname).substring(0,($_.FullName).lastindexOf(".")) 
    $doc = $word.documents.open($_.fullname) 
    $doc.saveas($path, $wdFormatPDF) 
    $doc.close() 
} 

$word.Quit() 
1

在这里发布的解决方案都不适用于Windows 8.1(顺便说一句,我使用Office 365)。我的PowerShell以某种方式不喜欢[ref]参数(我不知道为什么,我很少使用PowerShell)。

这是为我工作的解决方案:

$Files=Get-ChildItem 'C:\path\to\files\*.docx' 

$Word = New-Object -ComObject Word.Application 

Foreach ($File in $Files) { 
    $Doc = $Word.Documents.Open($File.FullName) 
    $Name=($Doc.FullName).replace('docx', 'pdf') 
    $Doc.SaveAs($Name, 17) 
    $Doc.Close() 
} 
0

以上答案都达不到我,因为我在做一个批处理作业转换约70,000字的文件这种方式。事实证明,重复这样做最终导致Word崩溃,大概是由于内存问题(错误是一些COMException,我不知道如何解析)。所以,我的窍门是让每一百个文档(任意选择的数字)重新开始。

此外,偶尔会发生崩溃,导致格式不正确的pdf,其中每个格式大小通常为1-2 kb。所以,当跳过已经生成的pdf时,我确定它们的大小至少为3kb。如果您不想跳过已生成的PDF,则可以删除该if语句。

对不起,如果我的代码看起来不好,我一般不使用Windows,这是一次性黑客攻击。所以,这里的最终代码:

$Files=Get-ChildItem -path '.\path\to\docs' -recurse -include "*.doc*" 

$counter = 0 
$filesProcessed = 0 
$Word = New-Object -ComObject Word.Application 

Foreach ($File in $Files) { 
    $Name="$(($File.FullName).substring(0, $File.FullName.lastIndexOf("."))).pdf" 
    if ((Test-Path $Name) -And (Get-Item $Name).length -gt 3kb) { 
     echo "skipping $($Name), already exists" 
     continue 
    } 

    echo "$($filesProcessed): processing $($File.FullName)" 
    $Doc = $Word.Documents.Open($File.FullName) 
    $Doc.SaveAs($Name, 17) 
    $Doc.Close() 
    if ($counter -gt 100) { 
     $counter = 0 
     $Word.Quit() 
     [System.Runtime.Interopservices.Marshal]::ReleaseComObject($Word) 
     $Word = New-Object -ComObject Word.Application 
    } 
    $counter = $counter + 1 
    $filesProcessed = $filesProcessed + 1 
}