2013-05-14 4 views
19

Sto cercando di utilizzare PowerShell per fare una conversione batch di Word Docx in PDF - utilizzando uno script trovato su questo sito: http://blogs.technet.com/b/heyscriptingguy/archive/2013/03/24/weekend-scripter-convert-word-documents-to-pdf-files-with-powershell.aspxbase PowerShell - convertire in batch Word Docx in 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() 
} 

E continuo a ricevendo questo errore e non riesco a capire perché:

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 

Qualche idea?

Inoltre, come dovrei cambiarlo per convertire anche i file doc (non docX) e utilizzare i file locali (file nella stessa posizione del percorso dello script)?

Sorry - mai fatto PowerShell script ...

risposta

42

questo lavoro per doc così come i file 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

Questo ha funzionato - grazie - ha cambiato $ documents_path essere dinamici in base alla posizione script utilizzando '$ documents_path = Split-Path -parent $ MyInvocation.MyCommand.Path' – takabanana

+0

è oledb usato in questa conversione? – culter

+2

Dovresti anche rilasciare l'oggetto COM: '[System.Runtime.Interopservices.Marshal] :: ReleaseComObject ($ word_app)'. La rimozione dell'intera variabile è suggerita anche da [The Scripting Guys] (http://technet.microsoft.com/en-us/library/ff730962.aspx): 'Remove-Variable word_app' – ComFreek

3

Questo funziona per me (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

Nessuna delle soluzioni postato qui ha lavorato per me su Windows 8.1 (btw. Sto usando Office 365). Il mio PowerShell in qualche modo non mi piace gli argomenti [ref] (non so perché, io uso molto raramente PowerShell).

Questa è la soluzione che ha funzionato per me:

$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

Le risposte di cui sopra tutte venute meno per me, come io stavo facendo un lavoro conversione batch circa 70.000 documenti word in questo modo. A quanto pare, fare questo ripetutamente porta a crash di Word, presumibilmente a causa di problemi di memoria (l'errore era qualche COMException che non sapevo come analizzare). Quindi, il mio trucco per farlo procedere è stato quello di uccidere e riavviare la parola ogni 100 documenti (numero scelto arbitrariamente).

Inoltre, quando si è verificato un arresto anomalo di tanto in tanto, si sarebbero verificati file PDF non validi, ciascuno dei quali aveva generalmente una dimensione di 1-2 kb. Quindi, saltando i pdf già generati, mi assicuro che abbiano una dimensione di almeno 3kb. Se non si desidera saltare i PDF già generati, è possibile eliminare tale istruzione if.

Scusami se il mio codice non ha un bell'aspetto, di solito non uso Windows e questo è stato un hack un-off. Quindi, ecco il codice risultante:

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