Подтвердить что ты не робот

Basic Powershell - пакетное преобразование Word Docx в PDF

Я пытаюсь использовать PowerShell для пакетного преобразования Word Docx в PDF - используя script, найденный на этом сайте: 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 (not docX), а также использовать локальные файлы (файлы в том же месте, что и расположение script)?

Извините - никогда не выполнялся сценарий PowerShell...

4b9b3361

Ответ 1

Это будет работать как с документами, так и с документами 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()

Ответ 2

Это работает для меня (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

Ни одно из решений, размещенных здесь, не работало для меня в 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()
}

Ответ 4

Вышеупомянутые ответы все мне не подходят, так как я делал пакетную работу, конвертируя около 70 000 текстовых документов таким образом. Как оказалось, повторение этого в конечном итоге приводит к сбою Word, по-видимому, из-за проблем с памятью (ошибка была каким-то COMException, что я не знал, как разбираться). Итак, мой взлом, чтобы заставить его продолжить, было убить и перезапустить слово каждые 100 документов (произвольно выбранный номер).

Кроме того, когда он иногда рушился, появлялись искаженные pdf файлы, каждый из которых обычно составлял 1-2 kb. Таким образом, при пропуске уже созданных PDF файлов я уверен, что они имеют размер не менее 3 КБ. Если вы не хотите пропускать уже сгенерированные 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
}