PSWritePDF.psm1
function Remove-EmptyValues { [CmdletBinding()] param([System.Collections.IDictionary] $Hashtable, [switch] $Recursive, [int] $Rerun) foreach ($_ in [string[]] $Hashtable.Keys) { if ($Recursive) { if ($Hashtable[$_] -is [System.Collections.IDictionary]) { if ($Hashtable[$_].Count -eq 0) { $Hashtable.Remove($_) } else { Remove-EmptyValues -Hashtable $Hashtable[$_] -Recursive:$Recursive } } else { if ($null -eq $Hashtable[$_]) { $Hashtable.Remove($_) } elseif ($Hashtable[$_] -is [string] -and $Hashtable[$_] -eq '') { $Hashtable.Remove($_) } } } else { if ($null -eq $Hashtable[$_]) { $Hashtable.Remove($_) } elseif ($Hashtable[$_] -is [string] -and $Hashtable[$_] -eq '') { $Hashtable.Remove($_) } } } if ($Rerun) { for ($i = 0; $i -lt $Rerun; $i++) { Remove-EmptyValues -Hashtable $Hashtable -Recursive:$Recursive } } } function Add-PDFDocumentContent { [CmdletBinding()] param( [object] $Object ) if ($Script:Document) { $null = $Script:Document.Add($Object) } else { $Splat = $Script:PDFStart.DocumentSettings $Settings = New-PDFPage @Splat #-MarginTop $MarginTop -MarginBottom $MarginBottom -MarginLeft $MarginLeft -MarginRight $MarginRight -PageSize $PageSize -Rotate:$Rotate.IsPresent New-InternalPDFPage -PageSize $Settings.Settings.PageSize -Rotate:$Settings.Settings.Rotate $null = $Script:Document.Add($Object) } } class CustomSplitter : iText.Kernel.Utils.PdfSplitter { [int] $_order [string] $_destinationFolder [string] $_outputName CustomSplitter([iText.Kernel.Pdf.PdfDocument] $pdfDocument, [string] $destinationFolder, [string] $OutputName) : base($pdfDocument) { $this._destinationFolder = $destinationFolder $this._order = 0 $this._outputName = $OutputName } [iText.Kernel.Pdf.PdfWriter] GetNextPdfWriter([iText.Kernel.Utils.PageRange] $documentPageRange) { $Name = -join ($this._outputName, $this._order++, ".pdf") $Path = [IO.Path]::Combine($this._destinationFolder, $Name) return [iText.Kernel.Pdf.PdfWriter]::new($Path) } } function Initialize-PDF { [CmdletBinding()] param( [Array] $Elements ) foreach ($Element in $Elements) { $Splat = $Element.Settings Remove-EmptyValues -Hashtable $Splat if ($Element.Type -eq 'Page') { if (-not $Script:PDFStart.FirstPageUsed) { #$Area = New-PDFArea -PageSize $Element.Settings.PageSize -Rotate:$Element.Settings.Rotate -AreaType ([iText.Layout.Properties.AreaBreakType]::LAST_PAGE) New-InternalPDFPage -PageSize $Element.Settings.PageSize -Rotate:$Element.Settings.Rotate #Add-PDFDocumentContent -Object $Area $Script:PDFStart.FirstPageUsed = $true } else { $Area = New-PDFArea -PageSize $Element.Settings.PageSize -Rotate:$Element.Settings.Rotate Add-PDFDocumentContent -Object $Area } # New-InternalPDFPage -PageSize $Element.Settings.PageSize -Rotate:$Element.Settings.Rotate # New-InternalPDFOptions -Settings $Element.Settings if ($Element.Settings.PageContent) { Initialize-PDF -Elements $Element.Settings.PageContent } } elseif ($Element.Type -eq 'Text') { $Paragraph = New-InternalPDFText @Splat foreach ($P in $Paragraph) { #$null = $Script:Document.Add($P) Add-PDFDocumentContent -Object $P } } elseif ($Element.Type -eq 'List') { New-InternalPDFList -Settings $Element.Settings } elseif ($Element.Type -eq 'Paragraph') { } elseif ($Element.Type -eq 'Options') { $SplatMargins = $Splat.Margins New-InternalPDFOptions @SplatMargins } elseif ($Element.Type -eq 'Table') { $Table = New-InteralPDFTable @Splat #$null = $Script:Document.Add($Table) Add-PDFDocumentContent -Object $Table } } } function New-InternalPDF { [CmdletBinding()] param( [string] $FilePath, [string] $Version #, # [ValidateScript( { & $Script:PDFPageSizeValidation } )][string] $PageSize, # [switch] $Rotate ) if ($Version) { $PDFVersion = Get-PDFConstantVersion -Version $Version $WriterProperties = [iText.Kernel.Pdf.WriterProperties]::new() $null = $WriterProperties.SetPdfVersion($PDFVersion) } try { if ($Version) { $Script:Writer = [iText.Kernel.Pdf.PdfWriter]::new($FilePath, $WriterProperties) } else { $Script:Writer = [iText.Kernel.Pdf.PdfWriter]::new($FilePath) } } catch { if ($_.Exception.Message -like '*The process cannot access the file*because it is being used by another process.*') { Write-Warning "New-InternalPDF - File $FilePath is in use. Terminating." Exit } else { Write-Warning "New-InternalPDF - Terminating error: $($_.Exception.Message)" Exit } } if ($Script:Writer) { $PDF = [iText.Kernel.Pdf.PdfDocument]::new($Script:Writer) } else { Write-Warning "New-InternalPDF - Terminating as writer doesn't exists." Exit } return $PDF } <# function New-InternalPDF { param( ) if ($Script:Writer) { if ($Script:PDF) { #$Script:PDF.Close() } $Script:PDF = [iText.Kernel.Pdf.PdfDocument]::new($Script:Writer) } else { Write-Warning "New-InternalPDF - Terminating as writer doesn't exists." Exit } } #> Register-ArgumentCompleter -CommandName New-InternalPDF -ParameterName PageSize -ScriptBlock $Script:PDFPageSize Register-ArgumentCompleter -CommandName New-InternalPDF -ParameterName Version -ScriptBlock $Script:PDFVersion function New-InternalPDFList { [CmdletBinding()] param( [System.Collections.IDictionary] $Settings ) $List = [iText.Layout.Element.List]::new() if ($null -ne $Settings.Indent) { $null = $List.SetSymbolIndent($Settings.Indent) } if ($Settings.Symbol) { if ($Settings.Symbol -eq 'hyphen') { # Default } elseif ($Settings.Symbol -eq 'bullet') { $Symbol = [regex]::Unescape("\u2022") $null = $List.SetListSymbol($Symbol) } } foreach ($_ in $Settings.Items) { $null = $List.Add([iText.Layout.Element.ListItem]::new($_.Text)) } $null = $Script:Document.Add($List) } function New-InternalPDFOptions { [CmdletBinding()] param( [nullable[float]] $MarginLeft, [nullable[float]] $MarginRight, [nullable[float]] $MarginTop, [nullable[float]] $MarginBottom ) if ($Script:Document) { if ($MarginLeft) { $Script:Document.SetLeftMargin($MarginLeft) } if ($MarginRight) { $Script:Document.SetRightMargin($MarginRight) } if ($MarginTop) { $Script:Document.SetTopMargin($MarginTop) } if ($MarginBottom) { $Script:Document.SetBottomMargin($MarginBottom) } } #if ($Settings.PageSize) { # $Script:Document.GetPdfDocument().SetDefaultPageSize([iText.Kernel.Geom.PageSize]::($Settings.PageSize)) # } } function New-InternalPDFPage { [CmdletBinding()] param( [string] $PageSize, [switch] $Rotate ) if ($PageSize -or $Rotate) { if ($PageSize) { $Page = [iText.Kernel.Geom.PageSize]::($PageSize) } else { $Page = [iText.Kernel.Geom.PageSize]::Default } if ($Rotate) { $Page = $Page.Rotate() } } if ($Page) { $null = $Script:PDF.AddNewPage($Page) } else { $null = $Script:PDF.AddNewPage() } $Script:Document = [iText.Layout.Document]::new($Script:PDF) } Register-ArgumentCompleter -CommandName New-InternalPDFPage -ParameterName PageSize -ScriptBlock $Script:PDFPageSize function New-InteralPDFTable { [CmdletBinding()] param( [Array] $DataTable ) if ($DataTable[0] -is [System.Collections.IDictionary]) { [Array] $ColumnNames = 'Name', 'Value' # $DataTable[0].Keys [Array] $TemporaryTable = foreach ($_ in $DataTable2) { $_.GetEnumerator() | Select-Object Name, Value } } else { [Array] $ColumnNames = $DataTable[0].PSObject.Properties.Name [Array] $TemporaryTable = $DataTable } [iText.layout.element.Table] $Table = [iText.Layout.Element.Table]::new($ColumnNames.Count) $Table = $Table.UseAllAvailableWidth() foreach ($Column in $ColumnNames) { $Splat = @{ Text = $Column #Font = $Font #FontFamily = $FontFamily #FontColor = $FontColor #FontBold = $FontBold } $Paragraph = New-InternalPDFText @Splat #$Paragraph = New-PDFText -Text $Column [iText.Layout.Element.Cell] $Cell = [iText.Layout.Element.Cell]::new().Add($Paragraph) $null = $Table.AddCell($Cell) } foreach ($_ in $TemporaryTable) { foreach ($Column in $ColumnNames) { $Splat = @{ Text = $_.$Column #Font = $Font #FontFamily = $FontFamily #FontColor = $FontColor #FontBold = $FontBold } $Paragraph = New-InternalPDFText @Splat #$Paragraph = New-PDFText -Text $_.$Column [iText.Layout.Element.Cell] $Cell = [iText.Layout.Element.Cell]::new().Add($Paragraph) $null = $Table.AddCell($Cell) } } $Table } function New-InternalPDFText { [CmdletBinding()] param( [string[]] $Text, [ValidateScript( { & $Script:PDFFontValidation } )][string[]] $Font, #[string[]] $FontFamily, [ValidateScript( { & $Script:PDFColorValidation } )][string[]] $FontColor, [bool[]] $FontBold ) $Paragraph = [iText.Layout.Element.Paragraph]::new() if ($FontBold) { [Array] $FontBold = $FontBold $DefaultBold = $FontBold[0] } if ($FontColor) { [Array] $FontColor = $FontColor $DefaultColor = $FontColor[0] } if ($Font) { [Array] $Font = $Font $DefaultFont = $Font[0] } for ($i = 0; $i -lt $Text.Count; $i++) { [iText.Layout.Element.Text] $PDFText = $Text[$i] if ($FontBold) { if ($null -ne $FontBold[$i]) { if ($FontBold[$i]) { $PDFText = $PDFText.SetBold() } } else { if ($DefaultBold) { $PDFText = $PDFText.SetBold() } } } if ($FontColor) { if ($null -ne $FontColor[$i]) { if ($FontColor[$i]) { $ConvertedColor = Get-PDFConstantColor -Color $FontColor[$i] $PDFText = $PDFText.SetFontColor($ConvertedColor) } } else { if ($DefaultColor) { $ConvertedColor = Get-PDFConstantColor -Color $DefaultColor $PDFText = $PDFText.SetFontColor($ConvertedColor) } } } if ($Font) { if ($null -ne $Font[$i]) { if ($Font[$i]) { $ConvertedFont = Get-PDFConstantFont -Font $Font[$i] $ApplyFont = [iText.Kernel.Font.PdfFontFactory]::CreateFont($ConvertedFont) $PDFText = $PDFText.SetFont($ApplyFont) } } else { if ($DefaultColor) { $ConvertedFont = Get-PDFConstantFont -Font $DefaultFont $ApplyFont = [iText.Kernel.Font.PdfFontFactory]::CreateFont($ConvertedFont) $PDFText = $PDFText.SetFont($ApplyFont) } } } $null = $Paragraph.Add($PDFText) } $Paragraph } # Validation for Actions $Script:PDFAction = { ([iText.Kernel.Pdf.Action.PdfAction] | Get-Member -static -MemberType Property).Name } $Script:PDFActionValidation = { $Array = @( (& $Script:PDFAction) '' ) $_ -in $Array } function Get-PDFConstantAction { [CmdletBinding()] param( [ValidateScript( { & $Script:PDFActionValidation } )][string] $Action ) return [iText.Kernel.Pdf.Action.PdfAction]::$Action } Register-ArgumentCompleter -CommandName Get-PDFConstantAction -ParameterName Action -ScriptBlock $Script:PDFAction # Validation for Colors $Script:PDFColor = { ([iText.Kernel.Colors.ColorConstants] | Get-Member -static -MemberType Property).Name } $Script:PDFColorValidation = { $Array = @( (& $Script:PDFColor) '' ) $_ -in $Array } function Get-PDFConstantColor { [CmdletBinding()] param( [ValidateScript( { & $Script:PDFColorValidation } )][string] $Color ) return [iText.Kernel.Colors.ColorConstants]::$Color } Register-ArgumentCompleter -CommandName Get-PDFConstantColor -ParameterName Color -ScriptBlock $Script:PDFColor # Validation for Fonts $Script:PDFFont = { ([iText.IO.Font.Constants.StandardFonts] | Get-Member -static -MemberType Property).Name } $Script:PDFFontValidation = { $Array = @( (& $Script:PDFFont) '' ) $_ -in $Array } function Get-PDFConstantFont { [CmdletBinding()] param( [ValidateScript( { & $Script:PDFFontValidation } )][string] $Font ) return [iText.IO.Font.Constants.StandardFonts]::$Font } Register-ArgumentCompleter -CommandName Get-PDFConstantFont -ParameterName Font -ScriptBlock $Script:PDFFont # Validation for PageSize $Script:PDFPageSize = { ([iText.Kernel.Geom.PageSize] | Get-Member -static -MemberType Property).Name } $Script:PDFPageSizeValidation = { # Empty element is added to allow no parameter value $Array = @( (& $Script:PDFPageSize) '' ) $_ -in $Array } function Get-PDFConstantPageSize { [CmdletBinding()] param( [ValidateScript( { & $Script:PDFPageSizeValidation } )][string] $PageSize ) return [iText.Kernel.Geom.PageSize]::$PageSize } Register-ArgumentCompleter -CommandName Get-PDFConstantPageSize -ParameterName Version -ScriptBlock $Script:PDFPageSize # Validation for Fonts $Script:PDFVersion = { ([iText.Kernel.Pdf.PdfVersion] | Get-Member -static -MemberType Property).Name } $Script:PDFVersionValidation = { $Array = @( (& $Script:PDFVersion) '' ) $_ -in $Array } function Get-PDFConstantVersion { [CmdletBinding()] param( [ValidateScript( { & $Script:PDFVersionValidation } )][string] $Version ) return [iText.Kernel.Pdf.PdfVersion]::$Version } Register-ArgumentCompleter -CommandName Get-PDFConstantVersion -ParameterName Version -ScriptBlock $Script:PDFVersion function Convert-PDFToText { [CmdletBinding()] param( [string] $FilePath, [int[]] $Page ) if ($FilePath -and (Test-Path -LiteralPath $FilePath)) { $ResolvedPath = Resolve-Path -LiteralPath $FilePath $Source = [iText.Kernel.Pdf.PdfReader]::new($ResolvedPath) try { [iText.Kernel.Pdf.PdfDocument] $SourcePDF = [iText.Kernel.Pdf.PdfDocument]::new($Source); [iText.Kernel.Pdf.Canvas.Parser.Listener.LocationTextExtractionStrategy] $ExtractionStrategy = [iText.Kernel.Pdf.Canvas.Parser.Listener.LocationTextExtractionStrategy]::new() } catch { $ErrorMessage = $_.Exception.Message Write-Warning "Convert-PDFToText - Processing document $ResolvedPath failed with error: $ErrorMessage" } $PagesCount = $SourcePDF.GetNumberOfPages() if ($Page.Count -eq 0) { for ($Count = 1; $Count -le $PagesCount; $Count++) { try { $ExtractedPage = $SourcePDF.GetPage($Count) [iText.Kernel.Pdf.Canvas.Parser.PdfTextExtractor]::GetTextFromPage($ExtractedPage, $ExtractionStrategy) } catch { $ErrorMessage = $_.Exception.Message Write-Warning "Convert-PDFToText - Processing document $ResolvedPath failed with error: $ErrorMessage" } } } else { foreach ($Count in $Page) { if ($Count -le $PagesCount -and $Count -gt 0) { try { $ExtractedPage = $SourcePDF.GetPage($Count) [iText.Kernel.Pdf.Canvas.Parser.PdfTextExtractor]::GetTextFromPage($ExtractedPage, $ExtractionStrategy) } catch { $ErrorMessage = $_.Exception.Message Write-Warning "Convert-PDFToText - Processing document $ResolvedPath failed with error: $ErrorMessage" } } else { Write-Warning "Convert-PDFToText - File $ResolvedPath doesn't contain page number $Count. Skipping." } } } } else { Write-Warning "Convert-PDFToText - Path $FilePath doesn't exists. Terminating." } } function Merge-PDF { [CmdletBinding()] param( [string[]] $InputFile, [string] $OutputFile ) if ($OutputFile) { try { [iText.Kernel.Pdf.PdfWriter] $Writer = [iText.Kernel.Pdf.PdfWriter]::new($OutputFile) [iText.Kernel.Pdf.PdfDocument] $PDF = [iText.Kernel.Pdf.PdfDocument]::new($Writer); [iText.Kernel.Utils.PdfMerger] $Merger = [iText.Kernel.Utils.PdfMerger]::new($PDF) } catch { $ErrorMessage = $_.Exception.Message Write-Warning "Merge-PDF - Processing document $OutputFile failed with error: $ErrorMessage" } foreach ($File in $InputFile) { if ($File -and (Test-Path -LiteralPath $File)) { $ResolvedFile = Resolve-Path -LiteralPath $File try { $Source = [iText.Kernel.Pdf.PdfReader]::new($ResolvedFile) [iText.Kernel.Pdf.PdfDocument] $SourcePDF = [iText.Kernel.Pdf.PdfDocument]::new($Source); $null = $Merger.merge($SourcePDF, 1, $SourcePDF.getNumberOfPages()) $SourcePDF.close() } catch { $ErrorMessage = $_.Exception.Message Write-Warning "Merge-PDF - Processing document $ResolvedFile failed with error: $ErrorMessage" } } } try { $PDF.Close() } catch { $ErrorMessage = $_.Exception.Message Write-Warning "Merge-PDF - Saving document $OutputFile failed with error: $ErrorMessage" } } else { Write-Warning "Merge-PDF - Output file was empty. Please give a name to file. Terminating." } } function Split-PDF { [CmdletBinding()] param( [Parameter(Mandatory)][string] $FilePath, [Parameter(Mandatory)][string] $OutputFolder, [string] $OutputName = 'OutputDocument', [int] $SplitCount = 1 ) if ($SplitCount -eq 0) { Write-Warning "Split-PDF - SplitCount is 0. Terminating." return } if ($FilePath -and (Test-Path -LiteralPath $FilePath)) { $ResolvedPath = Resolve-Path -LiteralPath $FilePath if ($OutputFolder -and (Test-Path -LiteralPath $OutputFolder)) { try { $PDFFile = [iText.Kernel.Pdf.PdfReader]::new($ResolvedPath) $Document = [iText.Kernel.Pdf.PdfDocument]::new($PDFFile) $Splitter = [CustomSplitter]::new($Document, $OutputFolder, $OutputName) $List = $Splitter.SplitByPageCount($SplitCount) foreach ($_ in $List) { $_.Close() } } catch { $ErrorMessage = $_.Exception.Message Write-Warning "Split-PDF - Error has occured: $ErrorMessage" } } else { Write-Warning "Split-PDF - Destination folder $OutputFolder doesn't exists. Terminating." } } else { Write-Warning "Split-PDF - Path $FilePath doesn't exists. Terminating." } } function New-PDF { [CmdletBinding()] param( [scriptblock] $PDFContent, [string] $FilePath, [string] $Version, [nullable[float]] $MarginLeft, [nullable[float]] $MarginRight, [nullable[float]] $MarginTop, [nullable[float]] $MarginBottom, [ValidateScript( { & $Script:PDFPageSizeValidation } )][string] $PageSize, [switch] $Rotate, [alias('Open')][switch] $Show ) # The types needs filling in for the workaround below. DONT FORGET! $Script:Types = 'Text', 'List', 'Paragraph', 'Table', 'Image' $Script:PDFStart = @{ Start = $true FilePath = $FilePath DocumentSettings = @{ MarginTop = $MarginTop MarginBottom = $MarginBottom MarginLeft = $MarginLeft MarginRight = $MarginRight PageSize = $PageSize Rotate = $Rotate.IsPresent } FirstPageUsed = $false UsedTypes = [System.Collections.Generic.List[string]]::new() } if ($PDFContent) { [Array] $Elements = @( [Array] $Content = & $PDFContent # This is workaround to support multiple scenarios: # New-PDF { New-PDFPage, New-PDFPage } # New-PDF { } # New-PDF { New-PDFText, New-PDFPage } # This is there to make sure we allow for New-PDF to allow control for -Rotate/PageSize to either whole document or to text/tables # and other types until New-PDFPage is given # It's ugly but seems to wrok foreach ($_ in $Content) { if ($_.Type -in $Script:Types) { $Script:PDFStart.UsedTypes.Add($_.Type) } elseif ($_.Type -eq 'Page') { if ($Script:PDFStart.UsedTypes.Count -ne 0) { New-PDFPage -PageSize $PageSize -Rotate:$Rotate } break } } $Content ) $Script:PDF = New-InternalPDF -FilePath $FilePath -Version $Version #-PageSize $PageSize -Rotate:$Rotate } else { $Script:PDFStart['Start'] = $false # if there's no scriptblock that means we're using standard way of working with PDF $Script:PDF = New-InternalPDF -FilePath $FilePath -Version $Version #-PageSize $PageSize -Rotate:$Rotate return $Script:PDF } $Script:PDFStart['Start'] = $true $Script:Document = New-PDFDocument -PDF $Script:PDF New-InternalPDFOptions -MarginLeft $MarginLeft -MarginRight $MarginRight -MarginTop $MarginTop -MarginBottom $MarginBottom Initialize-PDF -Elements $Elements if ($Script:PDF) { $Script:PDF.Close(); } if ($Show) { if (Test-Path -LiteralPath $FilePath) { Invoke-Item -LiteralPath $FilePath } } $Script:PDFStart = $null #$Script:PDFStart['Start'] = $false } Register-ArgumentCompleter -CommandName New-PDF -ParameterName PageSize -ScriptBlock $Script:PDFPageSize Register-ArgumentCompleter -CommandName New-PDF -ParameterName Version -ScriptBlock $Script:PDFVersion function New-PDFArea { param( [iText.Layout.Properties.AreaBreakType] $AreaType = [iText.Layout.Properties.AreaBreakType]::NEXT_AREA, [string] $PageSize, [switch] $Rotate ) # https://api.itextpdf.com/iText7/dotnet/7.1.8/classi_text_1_1_kernel_1_1_geom_1_1_page_size.html $AreaBreak = [iText.Layout.Element.AreaBreak]::new($AreaType) if ($PageSize) { $Page = [iText.Kernel.Geom.PageSize]::($PageSize) } else { $Page = [iText.Kernel.Geom.PageSize]::Default } if ($Rotate) { $Page = $Page.Rotate() } $AreaBreak.SetPageSize($Page) return $AreaBreak } Register-ArgumentCompleter -CommandName New-PDFArea -ParameterName PageSize -ScriptBlock $Script:PDFPageSize function New-PDFDocument { [CmdletBinding()] param( [iText.Kernel.Pdf.PdfDocument] $PDF ) [iText.Layout.Document] $Document = [iText.Layout.Document]::new($PDF) return $Document } function New-PDFInfo { [CmdletBinding()] param( [iText.Kernel.Pdf.PdfDocument] $PDF, [string] $Title, [string] $Author, [string] $Creator, [string] $Subject, [string[]] $Keywords, [switch] $AddCreationDate, [switch] $AddModificationDate ) try { [iText.Kernel.Pdf.PdfDocumentInfo] $info = $pdf.GetDocumentInfo() } catch { Write-Warning "New-PDFInfo - Error: $($_.Exception.Message)" return } if ($Title) { $null = $info.SetTitle($Title) } if ($AddCreationDate) { $null = $info.AddCreationDate() } if ($AddModificationDate) { $null = $info.AddModDate() } if ($Author) { $null = $info.SetAuthor($Author) } if ($Creator) { $null = $info.SetCreator($Creator) } if ($Subject) { $null = $info.SetSubject($Subject) } if ($Keywords) { $KeywordsString = $Keywords -join ',' $null = $info.SetKeywords($KeywordsString) } } function New-PDFList { [CmdletBinding()] param( [ScriptBlock] $ListItems, [nullable[float]] $Indent, [ValidateSet('bullet', 'hyphen')][string] $Symbol = 'hyphen' ) $Output = & $ListItems $Items = foreach ($_ in $Output) { if ($_.Type -eq 'ListItem') { $_.Settings } } [PSCustomObject] @{ Type = 'List' Settings = @{ Items = $Items Indent = $Indent Symbol = $Symbol } } } function New-PDFListItem { [CmdletBinding()] param( [string] $Text ) [PSCustomObject] @{ Type = 'ListItem' Settings = @{ Text = $Text } } } function New-PDFOptions { [CmdletBinding()] param( [nullable[float]] $MarginLeft, [nullable[float]] $MarginRight, [nullable[float]] $MarginTop, [nullable[float]] $MarginBottom #[ValidateScript( { & $Script:PDFPageSizeValidation } )][string] $PageSize ) [PSCustomObject] @{ Type = 'Options' Settings = @{ Margins = @{ MarginLeft = $MarginLeft MarginRight = $MarginRight MarginTop = $MarginTop MarginBottom = $MarginBottom } #PageSize = $PageSize } } } Register-ArgumentCompleter -CommandName New-PDFOptions -ParameterName PageSize -ScriptBlock $Script:PDFPageSize function New-PDFPage { [CmdletBinding()] param( [ScriptBlock] $PageContent, [nullable[float]] $MarginLeft, [nullable[float]] $MarginRight, [nullable[float]] $MarginTop, [nullable[float]] $MarginBottom, [ValidateScript( { & $Script:PDFPageSizeValidation } )][string] $PageSize, [switch] $Rotate ) if ($null -ne $Script:PDFStart -and $Script:PDFStart['Start']) { $Page = [PSCustomObject] @{ Type = 'Page' Settings = @{ Margins = @{ Left = $MarginLeft Right = $MarginRight Top = $MarginTop Bottom = $MarginBottom } PageSize = $PageSize Rotate = $Rotate.IsPresent PageContent = if ($PageContent) { & $PageContent } else { $null } } } $Page } else { # New-InternalPDFPage -PageSize $PageSize -Rotate:$Rotate.IsPresent } } Register-ArgumentCompleter -CommandName New-PDFPage -ParameterName PageSize -ScriptBlock $Script:PDFPageSize function New-PDFTable { [CmdletBinding()] param( [Array] $DataTable ) if ($null -ne $Script:PDFStart -and $Script:PDFStart['Start']) { $Settings = [PSCustomObject] @{ Type = 'Table' Settings = @{ DataTable = $DataTable } } $Settings } else { New-InteralPDFTable -DataTable $DataTable } } function New-PDFText { [CmdletBinding()] param( [string[]] $Text, [ValidateScript( { & $Script:PDFFontValidation } )][string[]] $Font, #[string[]] $FontFamily, [ValidateScript( { & $Script:PDFColorValidation } )][string[]] $FontColor, [bool[]] $FontBold ) $Splat = @{ } if ($Text) { $Splat['Text'] = $Text } if ($Font) { $Splat['Font'] = $Font } #FontFamily = $FontFamily if ($FontColor) { $Splat['FontColor'] = $FontColor } if ($FontBold) { $Splat['FontBold'] = $FontBold } if ($null -ne $Script:PDFStart -and $Script:PDFStart['Start']) { $Settings = [PSCustomObject] @{ Type = 'Text' Settings = $Splat } $Settings } else { New-InternalPDFText @Splat } } Register-ArgumentCompleter -CommandName New-PDFText -ParameterName Font -ScriptBlock $Script:PDFFont Register-ArgumentCompleter -CommandName New-PDFText -ParameterName FontColor -ScriptBlock $Script:PDFColor Export-ModuleMember -Function @('Convert-PDFToText', 'Get-PDFConstantAction', 'Get-PDFConstantColor', 'Get-PDFConstantFont', 'Get-PDFConstantPageSize', 'Get-PDFConstantVersion', 'Merge-PDF', 'New-PDF', 'New-PDFArea', 'New-PDFDocument', 'New-PDFInfo', 'New-PDFList', 'New-PDFListItem', 'New-PDFOptions', 'New-PDFPage', 'New-PDFTable', 'New-PDFText', 'Split-PDF') -Alias @() |