Plugins/OutWord.ps1
function OutWord { <# .SYNOPSIS Microsoft Word output plugin for PScribo. .DESCRIPTION Outputs a Word document representation of a PScribo document object. #> [CmdletBinding()] [OutputType([System.IO.FileInfo])] param ( ## ThePScribo document object to convert to a text document [Parameter(Mandatory, ValueFromPipeline)] [System.Object] $Document, ## Output directory path for the .txt file [Parameter(Mandatory, ValueFromPipelineByPropertyName)] [ValidateNotNull()] [System.String] $Path, ### Hashtable of all plugin supported options [Parameter()] [AllowNull()] [System.Collections.Hashtable] $Options ) begin { $pluginName = 'Word'; <#! OutWord.Internal.ps1 !#> } process { $stopwatch = [Diagnostics.Stopwatch]::StartNew(); WriteLog -Message ($localized.DocumentProcessingStarted -f $Document.Name); $xmlnsMain = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'; $xmlDocument = New-Object -TypeName 'System.Xml.XmlDocument'; [ref] $null = $xmlDocument.AppendChild($xmlDocument.CreateXmlDeclaration('1.0', 'utf-8', 'yes')); $documentXml = $xmlDocument.AppendChild($xmlDocument.CreateElement('w', 'document', $xmlnsMain)); [ref] $null = $xmlDocument.DocumentElement.SetAttribute('xmlns:xml', 'http://www.w3.org/XML/1998/namespace'); $body = $documentXml.AppendChild($xmlDocument.CreateElement('w', 'body', $xmlnsMain)); ## Setup the document page size/margins $sectionPrParams = @{ PageHeight = $Document.Options['PageHeight']; PageWidth = $Document.Options['PageWidth']; PageMarginTop = $Document.Options['MarginTop']; PageMarginBottom = $Document.Options['MarginBottom']; PageMarginLeft = $Document.Options['MarginLeft']; PageMarginRight = $Document.Options['MarginRight']; } [ref] $null = $body.AppendChild((GetWordSectionPr @sectionPrParams -XmlDocument $xmlDocument)); foreach ($s in $Document.Sections.GetEnumerator()) { if ($s.Id.Length -gt 40) { $sectionId = '{0}[..]' -f $s.Id.Substring(0,36); } else { $sectionId = $s.Id; } $currentIndentationLevel = 1; if ($null -ne $s.PSObject.Properties['Level']) { $currentIndentationLevel = $s.Level +1; } WriteLog -Message ($localized.PluginProcessingSection -f $s.Type, $sectionId) -Indent $currentIndentationLevel; switch ($s.Type) { 'PScribo.Section' { $s | OutWordSection -RootElement $body -XmlDocument $xmlDocument; } 'PScribo.Paragraph' { [ref] $null = $body.AppendChild((OutWordParagraph -Paragraph $s -XmlDocument $xmlDocument)); } 'PScribo.PageBreak' { [ref] $null = $body.AppendChild((OutWordPageBreak -PageBreak $s -XmlDocument $xmlDocument)); } 'PScribo.LineBreak' { [ref] $null = $body.AppendChild((OutWordLineBreak -LineBreak $s -XmlDocument $xmlDocument)); } 'PScribo.Table' { OutWordTable -Table $s -XmlDocument $xmlDocument -Element $body; } 'PScribo.TOC' { [ref] $null = $body.AppendChild((OutWordTOC -TOC $s -XmlDocument $xmlDocument)); } 'PScribo.BlankLine' { OutWordBlankLine -BlankLine $s -XmlDocument $xmlDocument -Element $body; } Default { WriteLog -Message ($localized.PluginUnsupportedSection -f $s.Type) -IsWarning; } } #end switch } #end foreach ## Generate the Word 'styles.xml' document part $stylesXml = OutWordStylesDocument -Styles $Document.Styles -TableStyles $Document.TableStyles; ## Generate the Word 'settings.xml' document part if (($Document.Properties['TOCs']) -and ($Document.Properties['TOCs'] -gt 0)) { ## We have a TOC so flag to update the document when opened $settingsXml = OutWordSettingsDocument -UpdateFields; } else { $settingsXml = OutWordSettingsDocument; } $destinationPath = Join-Path -Path $Path ('{0}.docx' -f $Document.Name); Add-Type -AssemblyName WindowsBase; try { $package = [System.IO.Packaging.Package]::Open($destinationPath, [System.IO.FileMode]::Create, [System.IO.FileAccess]::ReadWrite); } catch { WriteLog -Message ($localized.OpenPackageError -f $destinationPath) -IsWarning; throw $_; } ## Create document.xml part $documentUri = New-Object System.Uri('/word/document.xml', [System.UriKind]::Relative); WriteLog -Message ($localized.ProcessingDocumentPart -f $documentUri); $documentPart = $package.CreatePart($documentUri, 'application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml'); $streamWriter = New-Object System.IO.StreamWriter($documentPart.GetStream([System.IO.FileMode]::Create, [System.IO.FileAccess]::ReadWrite)); $xmlWriter = [System.Xml.XmlWriter]::Create($streamWriter); WriteLog -Message ($localized.WritingDocumentPart -f $documentUri); $xmlDocument.Save($xmlWriter); $xmlWriter.Close(); $streamWriter.Close(); ## Create styles.xml part $stylesUri = New-Object System.Uri('/word/styles.xml', [System.UriKind]::Relative); WriteLog -Message ($localized.ProcessingDocumentPart -f $stylesUri); $stylesPart = $package.CreatePart($stylesUri, 'application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml'); $streamWriter = New-Object System.IO.StreamWriter($stylesPart.GetStream([System.IO.FileMode]::Create, [System.IO.FileAccess]::ReadWrite)); $xmlWriter = [System.Xml.XmlWriter]::Create($streamWriter); WriteLog -Message ($localized.WritingDocumentPart -f $stylesUri); $stylesXml.Save($xmlWriter); $xmlWriter.Close(); $streamWriter.Close(); ## Create settings.xml part $settingsUri = New-Object System.Uri('/word/settings.xml', [System.UriKind]::Relative); WriteLog -Message ($localized.ProcessingDocumentPart -f $settingsUri); $settingsPart = $package.CreatePart($settingsUri, 'application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml'); $streamWriter = New-Object System.IO.StreamWriter($settingsPart.GetStream([System.IO.FileMode]::Create, [System.IO.FileAccess]::ReadWrite)); $xmlWriter = [System.Xml.XmlWriter]::Create($streamWriter); WriteLog -Message ($localized.WritingDocumentPart -f $settingsUri); $settingsXml.Save($xmlWriter); $xmlWriter.Close(); $streamWriter.Close(); ## Create the Package relationships WriteLog -Message $localized.GeneratingPackageRelationships; [ref] $null = $package.CreateRelationship($documentUri, [System.IO.Packaging.TargetMode]::Internal, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument', 'rId1'); [ref] $null = $documentPart.CreateRelationship($stylesUri, [System.IO.Packaging.TargetMode]::Internal, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles', 'rId1'); [ref] $null = $documentPart.CreateRelationship($settingsUri, [System.IO.Packaging.TargetMode]::Internal, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings', 'rId2'); WriteLog -Message ($localized.SavingFile -f $destinationPath); $package.Flush(); $package.Close(); $stopwatch.Stop(); WriteLog -Message ($localized.DocumentProcessingCompleted -f $Document.Name); WriteLog -Message ($localized.TotalProcessingTime -f $stopwatch.Elapsed.TotalSeconds); ## Return the file reference to the pipeline Write-Output (Get-Item -Path $destinationPath); } #end process } #end function OutWord |