web-dev-qa-db-ja.com

Basic Powershell-Word DocxをPDF

PowerShellを使用してWord DocxをPDF-このサイトにあるスクリプトを使用してバッチ変換: http://blogs.technet.com/b/ heyscriptingguy/archive/2013/03/24/weekend-scripter-convert-Word-documents-to-pdf-files-with-powershell.aspx

# 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

何か案は?

また、doc(docXではなく)ファイルも変換し、ローカルファイル(スクリプトの場所と同じ場所にあるファイル)を使用するように変更するにはどうすればよいですか?

申し訳ありませんが、PowerShellスクリプトを実行したことはありません...

24
takabanana

これは、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()
50
MFT

約70,000のWord文書をこの方法で変換するバッチジョブを実行していたため、上記の答えはすべて私にとって不足していました。結局のところ、これを繰り返し行うと、おそらくメモリの問題が原因で、Wordがクラッシュします(エラーは、解析方法がわからないCOMExceptionでした)。それで、それを進めるための私のハックは、100ドキュメント(任意に選択された数)ごとにWordを殺して再起動することでした。

さらに、ときどきクラッシュすると、結果として不正なPDFが生成されます。各PDFのサイズは通常1〜2 kbでした。そのため、すでに生成されたPDFをスキップするときは、少なくとも3kbのサイズであることを確認します。すでに生成されたPDFをスキップしたくない場合は、ifステートメントを削除できます。

私のコードが良く見えない場合、すみませんが、私は通常Windowsを使用しません。これは1回限りのハックでした。したがって、結果のコードは次のとおりです。

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

これは私のために働く(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()
3
David Brabant

ここに投稿されたソリューションはどちらも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()
}
1
Honza Kalfus