2013-05-14 8 views
19

Próbuję użyć PowerShell zrobić konwersję Word Docx to PDF - za pomocą skryptu znajdującego się na tej stronie: http://blogs.technet.com/b/heyscriptingguy/archive/2013/03/24/weekend-scripter-convert-word-documents-to-pdf-files-with-powershell.aspxPodstawowe PowerShell - konwertowanie Słowo Docx to 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() 
} 

I dalej pojawia się ten błąd i nie można ustalić, dlaczego:

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 

Jakieś pomysły?

Ponadto - w jaki sposób należy go zmienić, aby przekonwertować pliki doc (nie docX), a także użyć plików lokalnych (plików w tej samej lokalizacji, co lokalizacja skryptu)?

Niestety - nigdy zrobić skryptów PowerShell ...

Odpowiedz

42

To będzie pracować dla doc jak pliki 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

ten pracował - Dzięki - zmienił $ documents_path być dynamiczne oparte na lokalizacji przy użyciu skryptu '$ documents_path = Split-Path -parent $ MyInvocation.MyCommand.Path' – takabanana

+0

Czy stosowany OLEDB w tej konwersji? – culter

+2

Powinieneś również zwolnić obiekt COM: '[System.Runtime.Interopservices.Marshal] :: ReleaseComObject ($ word_app)'. Usunięcie całej zmiennej jest również zalecane przez [The Scripting Guys] (http://technet.microsoft.com/en-us/library/ff730962.aspx): 'Remove-Variable word_app' – ComFreek

3

Działa to dla mnie (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

Żadne z zamieszczonych tutaj rozwiązań nie działa w Windows 8.1 (przy okazji korzystam z usługi Office 365). Mój PowerShell w jakiś sposób nie lubi argumentów [ref] (nie wiem dlaczego, bardzo rzadko używam PowerShella).

Jest to rozwiązanie, które pracował dla mnie:

$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

Powyższe odpowiedzi wszystkie spadł krótki dla mnie, jak robię zadanie wsadowe konwersji około 70.000 dokumenty słowo w ten sposób. Jak się okazuje, robienie tego wielokrotnie powoduje w końcu awarię programu Word, prawdopodobnie z powodu problemów z pamięcią (błąd był wyjątkiem COMException, którego nie potrafiłem przeanalizować). Tak więc, moim hack, aby to kontynuować, było zabicie i ponowne uruchomienie słowa co 100 dokumentów (arbitralnie wybrany numer).

Co więcej, w przypadku awarii od czasu do czasu pojawiały się zniekształcone pliki PDF, z których każdy miał rozmiar 1-2 kilogramów. Tak więc, pomijając już wygenerowane pliki pdf, upewniam się, że mają rozmiar co najmniej 3 kb. Jeśli nie chcesz pomijać już wygenerowanych plików PDF, możesz usunąć tę instrukcję if.

Przepraszam, jeśli mój kod nie wygląda dobrze, generalnie nie używam systemu Windows i był to jednorazowy hack. Tak więc, oto otrzymany kod:

$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 
}