Blog (6)
Komentarze (3)
Recenzje (0)
@blindroodGenerator PDF w Powershell za pomocą Office Word Automation

Generator PDF w Powershell za pomocą Office Word Automation

09.09.2011 18:11, aktualizacja: 04.02.2012 17:59

Mam tę przyjemność pracować dla ludzi, którzy często operują dużymi plikami biurowymi (doc, pdf, xls). Praca na nich jest w miarę przyjemna, o ile oczywiście mamy wystarczającą ilość pamięci. Gorzej wygląda praca na wielu malutkich plikach

Przyszła dzisiaj do mnie pewna pani i powiedziała, że ma do wydrukowania 717 plików wordowych. Każdy z nich był jednostronicowy. Opcje jakie miała: 1. Po kolei otwierać plik i drukować => Kuuuuupa roboty 2. Wszystkie naraz zaznaczyć i drukować => nie bardzo chciała pamięć współpracować (Partiami tak by długo zeszło) 3. Wykorzystać metodę "Wstaw -> Plik" w Wordzie => niestety się trochę rozjeżdżało i naraz łykało ok. 40 plików.

No więc spiąłem poślady, zakasałem rękawy, chwyciłem za klawirkę i tak oto powstał skrypt w Powershell'u, który zamienia pliki wordowe na PDF.

Po co?

Ano wymyśliłem sobie, że przekształcę wszystkie pliki do PDFa a potem scale je w jeden, ponieważ mam świetne narzędzie do tego. Nazywa się PDFSaM (Split&Merge). Potrafi dzielić i scalać pliki PDF. No i jest do tego darmowy. Większość źródeł WWW odnosi się do wyżej opisanej metody nr 3, która niestety nie zdawała egzaminu.

Mój skrypt działa bardzo prosto. Otwieram plik w Wordzie, zapisuję jako PDF i zamykam plik.


Function PrintTo-PDF {
<#
	.SYNOPSIS
		Save file as PDF 
		
	.DESCRIPTION
		File must be compatible with Microsoft Office Word and Word must be available on the computer

	.PARAMETER  File
		Instance of System.IO.FileInfo
		File to be saved as PDF. Must be Word compatible.

	.EXAMPLE
		PS C:\> get-childitem | select -last 4 | PrintTo-PDF

	.EXAMPLE
		PS C:\> get-item file.doc | PrintTo-PDF -Verbose

	.INPUTS
		System.IO.FileInfo

	.OUTPUTS
		None

        .NOTES
                Author: BlinDRooD
#>

	[CmdletBinding()]
	Param( 
	[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
	[System.IO.FileInfo]$File
	)
	Begin{
		Write-Verbose "Importing libraries"
		[Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Interop.Word") | Out-Null
		Write-Verbose "Starting Word application"
		$Word = New-Object -ComObject Word.Application
		$PDF = [Microsoft.Office.Interop.Word.WdSaveFormat]::wdFormatPDF
		$Close = [Microsoft.Office.Interop.Word.WdSaveOptions]::wdDoNotSaveChanges
	}
	Process{
		Write-Verbose "Openning File $($file.Name)."
		$Word.Documents.Open($File.FullName) | Out-Null
		$Newpath = Join-Path -Path $File.DirectoryName -ChildPath ($File.BaseName + ".pdf")
		Write-Verbose "Saving File $(Split-Path $newpath -Leaf)."
		$Word.ActiveDocument.SaveAs([ref]$Newpath,[ref]$PDF) | Out-Null
		Write-Verbose "Closing File $($file.Name)."
		$Word.ActiveDocument.Close([ref]$Close) | Out-Null
	}
	End{
		Write-Verbose "Quitting Word application."
		$word.Quit()
	}
}

Skrypt nie sprawdza, czy pliki są "otwieralne" w Wordzie. Wydajnością też nie powala. 700 plików mielił ok 3‑4 minuty. Przykład użycia


Get-ChildItem | Where { $_.Extension -eq ".doc" } | PrintTo-PDF
Get-Item file.doc | PrintTo-PDF -Verbose

Następnie wystarczy pliki scalić do jednego PDFa i mamy kilka godzin pracy z głowy. Skrypt można rozbudować, żeby zmieniał pliki na inne formaty przebierając w dostępnych formatach w WdSaveFormat. Można je wylistować używając poniższego polecenia:

[Microsoft.Office.Interop.Word.WdSaveFormat] | Get-Member –Static –Membertype Property | Select-Object -Property Name 

Proste prawda?

Wybrane dla Ciebie
Komentarze (1)