Src/Plugins/Private/OutWord.Internal.ps1
#region OutWord Private Functions function ConvertToWordColor { <# .SYNOPSIS Converts an HTML color to RRGGBB value as Word does not support short Html color codes #> [CmdletBinding()] param ( [Parameter(Mandatory, ValueFromPipeline)] [System.String] $Color ) process { $Color = $Color.TrimStart('#') if ($Color.Length -eq 3) { $Color = '{0}{0}{1}{1}{2}{2}' -f $Color[0], $Color[1], $Color[2] } return $Color.ToUpper() } } #end function ConvertToWordColor function OutWordSection { <# .SYNOPSIS Output formatted Word section (paragraph). #> [CmdletBinding()] param ( [Parameter(Mandatory, ValueFromPipeline)] [System.Object] $Section, [Parameter(Mandatory)] [System.Xml.XmlElement] $RootElement, [Parameter(Mandatory)] [System.Xml.XmlDocument] $XmlDocument ) process { $xmlnsMain = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main' $p = $RootElement.AppendChild($XmlDocument.CreateElement('w', 'p', $xmlnsMain)); $pPr = $p.AppendChild($XmlDocument.CreateElement('w', 'pPr', $xmlnsMain)); if (-not [System.String]::IsNullOrEmpty($Section.Style)) { #if (-not $Section.IsExcluded) { ## If it's excluded we need a non-Heading style :( Could explicitly set the style on the run? $pStyle = $pPr.AppendChild($XmlDocument.CreateElement('w', 'pStyle', $xmlnsMain)) [ref] $null = $pStyle.SetAttribute('val', $xmlnsMain, $Section.Style) #} } if ($Section.Tabs -gt 0) { $ind = $pPr.AppendChild($XmlDocument.CreateElement('w', 'ind', $xmlnsMain)); [ref] $null = $ind.SetAttribute('left', $xmlnsMain, (720 * $Section.Tabs)); } $spacing = $pPr.AppendChild($XmlDocument.CreateElement('w', 'spacing', $xmlnsMain)); ## Increment heading spacing by 2pt for each section level, starting at 8pt for level 0, 10pt for level 1 etc $spacingPt = (($Section.Level * 2) + 8) * 20 [ref] $null = $spacing.SetAttribute('before', $xmlnsMain, $spacingPt) [ref] $null = $spacing.SetAttribute('after', $xmlnsMain, $spacingPt) $r = $p.AppendChild($XmlDocument.CreateElement('w', 'r', $xmlnsMain)) $t = $r.AppendChild($XmlDocument.CreateElement('w', 't', $xmlnsMain)) if ($Document.Options['EnableSectionNumbering']) { [System.String] $sectionName = '{0} {1}' -f $Section.Number, $Section.Name } else { [System.String] $sectionName = '{0}' -f $Section.Name } [ref] $null = $t.AppendChild($XmlDocument.CreateTextNode($sectionName)) foreach ($s in $Section.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 $RootElement -XmlDocument $XmlDocument } 'PScribo.Paragraph' { [ref] $null = $RootElement.AppendChild((OutWordParagraph -Paragraph $s -XmlDocument $XmlDocument)) } 'PScribo.PageBreak' { [ref] $null = $RootElement.AppendChild((OutWordPageBreak -PageBreak $s -XmlDocument $XmlDocument)) } 'PScribo.LineBreak' { [ref] $null = $RootElement.AppendChild((OutWordLineBreak -LineBreak $s -XmlDocument $XmlDocument)) } 'PScribo.Table' { OutWordTable -Table $s -XmlDocument $XmlDocument -Element $RootElement } 'PScribo.BlankLine' { OutWordBlankLine -BlankLine $s -XmlDocument $XmlDocument -Element $RootElement } 'PScribo.Image' { [ref] $null = $RootElement.AppendChild((OutWordImage -Image $s -XmlDocument $XmlDocument)) } Default { WriteLog -Message ($localized.PluginUnsupportedSection -f $s.Type) -IsWarning } } #end switch } #end foreach if ($Section.IsSectionBreakEnd) { $sectionPrParams = @{ PageHeight = if ($Section.Orientation -eq 'Portrait') { $Document.Options['PageHeight'] } else { $Document.Options['PageWidth'] } PageWidth = if ($Section.Orientation -eq 'Portrait') { $Document.Options['PageWidth'] } else { $Document.Options['PageHeight'] } PageMarginTop = $Document.Options['MarginTop']; PageMarginBottom = $Document.Options['MarginBottom']; PageMarginLeft = $Document.Options['MarginLeft']; PageMarginRight = $Document.Options['MarginRight']; Orientation = $Section.Orientation; } [ref] $null = $pPr.AppendChild((GetWordSectionPr @sectionPrParams -XmlDocument $xmlDocument)); } } #end process } #end function OutWordSection function OutWordParagraph { <# .SYNOPSIS Output formatted Word paragraph. #> [CmdletBinding()] [OutputType([System.Xml.XmlElement])] param ( [Parameter(Mandatory, ValueFromPipeline)] [System.Object] $Paragraph, [Parameter(Mandatory)] [System.Xml.XmlDocument] $XmlDocument ) process { $xmlnsMain = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main' $p = $XmlDocument.CreateElement('w', 'p', $xmlnsMain); $pPr = $p.AppendChild($XmlDocument.CreateElement('w', 'pPr', $xmlnsMain)); if ($Paragraph.Tabs -gt 0) { $ind = $pPr.AppendChild($XmlDocument.CreateElement('w', 'ind', $xmlnsMain)) [ref] $null = $ind.SetAttribute('left', $xmlnsMain, (720 * $Paragraph.Tabs)) } if (-not [System.String]::IsNullOrEmpty($Paragraph.Style)) { $pStyle = $pPr.AppendChild($XmlDocument.CreateElement('w', 'pStyle', $xmlnsMain)) [ref] $null = $pStyle.SetAttribute('val', $xmlnsMain, $Paragraph.Style) } $spacing = $pPr.AppendChild($XmlDocument.CreateElement('w', 'spacing', $xmlnsMain)) [ref] $null = $spacing.SetAttribute('before', $xmlnsMain, 0) [ref] $null = $spacing.SetAttribute('after', $xmlnsMain, 0) if ([System.String]::IsNullOrEmpty($Paragraph.Text)) { $lines = $Paragraph.Id -Split [System.Environment]::NewLine } else { $lines = $Paragraph.TexT -Split [System.Environment]::NewLine } ## Create a separate run for each line/break for ($l = 0; $l -lt $lines.Count; $l++) { $r = $p.AppendChild($XmlDocument.CreateElement('w', 'r', $xmlnsMain)) $rPr = $r.AppendChild($XmlDocument.CreateElement('w', 'rPr', $xmlnsMain)) ## Apply custom paragraph styles to the run.. if ($Paragraph.Font) { $rFonts = $rPr.AppendChild($XmlDocument.CreateElement('w', 'rFonts', $xmlnsMain)) [ref] $null = $rFonts.SetAttribute('ascii', $xmlnsMain, $Paragraph.Font[0]) [ref] $null = $rFonts.SetAttribute('hAnsi', $xmlnsMain, $Paragraph.Font[0]) } if ($Paragraph.Size -gt 0) { $sz = $rPr.AppendChild($XmlDocument.CreateElement('w', 'sz', $xmlnsMain)) [ref] $null = $sz.SetAttribute('val', $xmlnsMain, $Paragraph.Size * 2) } if ($Paragraph.Bold -eq $true) { [ref] $null = $rPr.AppendChild($XmlDocument.CreateElement('w', 'b', $xmlnsMain)) } if ($Paragraph.Italic -eq $true) { [ref] $null = $rPr.AppendChild($XmlDocument.CreateElement('w', 'i', $xmlnsMain)) } if ($Paragraph.Underline -eq $true) { $u = $rPr.AppendChild($XmlDocument.CreateElement('w', 'u', $xmlnsMain)) [ref] $null = $u.SetAttribute('val', $xmlnsMain, 'single') } if (-not [System.String]::IsNullOrEmpty($Paragraph.Color)) { $Color = $rPr.AppendChild($XmlDocument.CreateElement('w', 'color', $xmlnsMain)) [ref] $null = $Color.SetAttribute('val', $xmlnsMain, (ConvertToWordColor -Color $Paragraph.Color)) } $t = $r.AppendChild($XmlDocument.CreateElement('w', 't', $xmlnsMain)) [ref] $null = $t.SetAttribute('space', 'http://www.w3.org/XML/1998/namespace', 'preserve') ## needs to be xml:space="preserve" NOT w:space... [ref] $null = $t.AppendChild($XmlDocument.CreateTextNode($lines[$l])) if ($l -lt ($lines.Count - 1)) { ## Don't add a line break to the last line/break $brr = $p.AppendChild($XmlDocument.CreateElement('w', 'r', $xmlnsMain)) $brt = $brr.AppendChild($XmlDocument.CreateElement('w', 't', $xmlnsMain)) [ref] $null = $brt.AppendChild($XmlDocument.CreateElement('w', 'br', $xmlnsMain)) } } #end foreach line break if ($Paragraph.IsSectionBreakEnd) { $paragraphPrParams = @{ PageHeight = if ($Paragraph.Orientation -eq 'Portrait') { $Document.Options['PageHeight'] } else { $Document.Options['PageWidth'] } PageWidth = if ($Paragraph.Orientation -eq 'Portrait') { $Document.Options['PageWidth'] } else { $Document.Options['PageHeight'] } PageMarginTop = $Document.Options['MarginTop']; PageMarginBottom = $Document.Options['MarginBottom']; PageMarginLeft = $Document.Options['MarginLeft']; PageMarginRight = $Document.Options['MarginRight']; Orientation = $Paragraph.Orientation; } [ref] $null = $pPr.AppendChild((GetWordSectionPr @paragraphPrParams -XmlDocument $xmlDocument)); } return $p; } #end process } #end function OutWordParagraph function OutWordPageBreak { <# .SYNOPSIS Output formatted Word page break. #> [CmdletBinding()] [OutputType([System.Xml.XmlElement])] param ( [Parameter(Mandatory, ValueFromPipeline)] [System.Object] $PageBreak, [Parameter(Mandatory)] [System.Xml.XmlDocument] $XmlDocument ) process { $xmlnsMain = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main' $p = $XmlDocument.CreateElement('w', 'p', $xmlnsMain) $r = $p.AppendChild($XmlDocument.CreateElement('w', 'r', $xmlnsMain)) $br = $r.AppendChild($XmlDocument.CreateElement('w', 'br', $xmlnsMain)) [ref] $null = $br.SetAttribute('type', $xmlnsMain, 'page') return $p } } #end function OutWordPageBreak function OutWordLineBreak { <# .SYNOPSIS Output formatted Word line break. #> [CmdletBinding()] [OutputType([System.Xml.XmlElement])] param ( [Parameter(Mandatory, ValueFromPipeline)] [System.Object] $LineBreak, [Parameter(Mandatory)] [System.Xml.XmlDocument] $XmlDocument ) process { $xmlnsMain = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main' $p = $XmlDocument.CreateElement('w', 'p', $xmlnsMain) $pPr = $p.AppendChild($XmlDocument.CreateElement('w', 'pPr', $xmlnsMain)) $pBdr = $pPr.AppendChild($XmlDocument.CreateElement('w', 'pBdr', $xmlnsMain)) $bottom = $pBdr.AppendChild($XmlDocument.CreateElement('w', 'bottom', $xmlnsMain)) [ref] $null = $bottom.SetAttribute('val', $xmlnsMain, 'single') [ref] $null = $bottom.SetAttribute('sz', $xmlnsMain, 6) [ref] $null = $bottom.SetAttribute('space', $xmlnsMain, 1) [ref] $null = $bottom.SetAttribute('color', $xmlnsMain, 'auto') return $p } } #end function OutWordLineBreak function GetWordTable { <# .SYNOPSIS Creates a scaffold Word <w:tbl> element #> [CmdletBinding()] [OutputType([System.Xml.XmlElement])] param ( [Parameter(Mandatory, ValueFromPipeline)] [ValidateNotNull()] [System.Object] $Table, [Parameter(Mandatory)] [System.Xml.XmlDocument] $XmlDocument ) process { $xmlnsMain = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main' $tableStyle = $Document.TableStyles[$Table.Style] $tbl = $XmlDocument.CreateElement('w', 'tbl', $xmlnsMain) $tblPr = $tbl.AppendChild($XmlDocument.CreateElement('w', 'tblPr', $xmlnsMain)) if ($Table.Tabs -gt 0) { $tblInd = $tblPr.AppendChild($XmlDocument.CreateElement('w', 'tblInd', $xmlnsMain)) [ref] $null = $tblInd.SetAttribute('w', $xmlnsMain, (720 * $Table.Tabs)) } if ($Table.ColumnWidths) { $tblLayout = $tblPr.AppendChild($XmlDocument.CreateElement('w', 'tblLayout', $xmlnsMain)) [ref] $null = $tblLayout.SetAttribute('type', $xmlnsMain, 'fixed') } elseif ($Table.Width -eq 0) { $tblLayout = $tblPr.AppendChild($XmlDocument.CreateElement('w', 'tblLayout', $xmlnsMain)) [ref] $null = $tblLayout.SetAttribute('type', $xmlnsMain, 'autofit') } if ($Table.Width -gt 0) { $tblW = $tblPr.AppendChild($XmlDocument.CreateElement('w', 'tblW', $xmlnsMain)) [ref] $null = $tblW.SetAttribute('type', $xmlnsMain, 'pct') $tableWidthRenderPct = $Table.Width if ($Table.Tabs -gt 0) { ## We now need to deal with tables being pushed outside the page margin $pageWidthMm = $Document.Options['PageWidth'] - ($Document.Options['PageMarginLeft'] + $Document.Options['PageMarginRight']) $indentWidthMm = ConvertPtToMm -Point ($Table.Tabs * 36) $tableRenderMm = (($pageWidthMm / 100) * $Table.Width) + $indentWidthMm if ($tableRenderMm -gt $pageWidthMm) { ## We've over-flowed so need to work out the maximum percentage $maxTableWidthMm = $pageWidthMm - $indentWidthMm $tableWidthRenderPct = [System.Math]::Round(($maxTableWidthMm / $pageWidthMm) * 100, 2) WriteLog -Message ($localized.TableWidthOverflowWarning -f $tableWidthRenderPct) -IsWarning } } [ref] $null = $tblW.SetAttribute('w', $xmlnsMain, $tableWidthRenderPct * 50) } $spacing = $tblPr.AppendChild($XmlDocument.CreateElement('w', 'spacing', $xmlnsMain)) [ref] $null = $spacing.SetAttribute('before', $xmlnsMain, 72) [ref] $null = $spacing.SetAttribute('after', $xmlnsMain, 72) #$tblLook = $tblPr.AppendChild($XmlDocument.CreateElement('w', 'tblLook', $xmlnsMain)); #[ref] $null = $tblLook.SetAttribute('val', $xmlnsMain, '04A0'); #[ref] $null = $tblLook.SetAttribute('firstRow', $xmlnsMain, 1); ## <w:tblLook w:val="04A0" w:firstRow="1" w:lastRow="0" w:firstColumn="1" w:lastColumn="0" w:noHBand="0" w:noVBand="1"/> #$tblStyle = $tblPr.AppendChild($XmlDocument.CreateElement('w', 'tblStyle', $xmlnsMain)); #[ref] $null = $tblStyle.SetAttribute('val', $xmlnsMain, $Table.Style); if ($tableStyle.BorderWidth -gt 0) { $tblBorders = $tblPr.AppendChild($XmlDocument.CreateElement('w', 'tblBorders', $xmlnsMain)) foreach ($border in @('top', 'bottom', 'start', 'end', 'insideH', 'insideV')) { $b = $tblBorders.AppendChild($XmlDocument.CreateElement('w', $border, $xmlnsMain)) [ref] $null = $b.SetAttribute('sz', $xmlnsMain, (ConvertMmToOctips $tableStyle.BorderWidth)) [ref] $null = $b.SetAttribute('val', $xmlnsMain, 'single') [ref] $null = $b.SetAttribute('color', $xmlnsMain, (ConvertToWordColor -Color $tableStyle.BorderColor)) } } $tblCellMar = $tblPr.AppendChild($XmlDocument.CreateElement('w', 'tblCellMar', $xmlnsMain)) $top = $tblCellMar.AppendChild($XmlDocument.CreateElement('w', 'top', $xmlnsMain)) [ref] $null = $top.SetAttribute('w', $xmlnsMain, (ConvertMmToTwips $tableStyle.PaddingTop)) [ref] $null = $top.SetAttribute('type', $xmlnsMain, 'dxa') $left = $tblCellMar.AppendChild($XmlDocument.CreateElement('w', 'start', $xmlnsMain)) [ref] $null = $left.SetAttribute('w', $xmlnsMain, (ConvertMmToTwips $tableStyle.PaddingLeft)) [ref] $null = $left.SetAttribute('type', $xmlnsMain, 'dxa') $bottom = $tblCellMar.AppendChild($XmlDocument.CreateElement('w', 'bottom', $xmlnsMain)) [ref] $null = $bottom.SetAttribute('w', $xmlnsMain, (ConvertMmToTwips $tableStyle.PaddingBottom)) [ref] $null = $bottom.SetAttribute('type', $xmlnsMain, 'dxa') $right = $tblCellMar.AppendChild($XmlDocument.CreateElement('w', 'end', $xmlnsMain)) [ref] $null = $right.SetAttribute('w', $xmlnsMain, (ConvertMmToTwips $tableStyle.PaddingRight)) [ref] $null = $right.SetAttribute('type', $xmlnsMain, 'dxa') $tblGrid = $tbl.AppendChild($XmlDocument.CreateElement('w', 'tblGrid', $xmlnsMain)) for ($i = 0; $i -lt $Table.Columns.Count; $i++) { [ref] $null = $tblGrid.AppendChild($XmlDocument.CreateElement('w', 'gridCol', $xmlnsMain)) } return $tbl } #end process } #end function GetWordTable function OutWordTable { <# .SYNOPSIS Output formatted Word table. .NOTES Specifies that the current row should be repeated at the top each new page on which the table is displayed. E.g, <w:tblHeader />. #> [CmdletBinding()] param ( [Parameter(Mandatory, ValueFromPipeline)] [ValidateNotNull()] [System.Object] $Table, ## Root element to append the table(s) to. List view will create multiple tables [Parameter(Mandatory)] [ValidateNotNull()] [System.Xml.XmlElement] $Element, [Parameter(Mandatory)] [System.Xml.XmlDocument] $XmlDocument ) process { $xmlnsMain = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main' $tableStyle = $Document.TableStyles[$Table.Style] $headerStyle = $Document.Styles[$tableStyle.HeaderStyle] if ($Table.List) { for ($r = 0; $r -lt $Table.Rows.Count; $r++) { $row = $Table.Rows[$r] if ($r -gt 0) { ## Add a space between each table as Word renders them together.. [ref] $null = $Element.AppendChild($XmlDocument.CreateElement('w', 'p', $xmlnsMain)) } ## Create <tr><tc></tc></tr> for each property $tbl = $Element.AppendChild((GetWordTable -Table $Table -XmlDocument $XmlDocument)) $properties = @($row.PSObject.Properties) for ($i = 0; $i -lt $properties.Count; $i++) { $propertyName = $properties[$i].Name ## Ignore __Style properties if (-not $propertyName.EndsWith('__Style', 'CurrentCultureIgnoreCase')) { $tr = $tbl.AppendChild($XmlDocument.CreateElement('w', 'tr', $xmlnsMain)) $tc1 = $tr.AppendChild($XmlDocument.CreateElement('w', 'tc', $xmlnsMain)) $tcPr1 = $tc1.AppendChild($XmlDocument.CreateElement('w', 'tcPr', $xmlnsMain)) if ($null -ne $Table.ColumnWidths) { ## TODO: Refactor out [ref] $null = ConvertMmToTwips -Millimeter $Table.ColumnWidths[0] $tcW1 = $tcPr1.AppendChild($XmlDocument.CreateElement('w', 'tcW', $xmlnsMain)) [ref] $null = $tcW1.SetAttribute('w', $xmlnsMain, $Table.ColumnWidths[0] * 50) [ref] $null = $tcW1.SetAttribute('type', $xmlnsMain, 'pct') } if ($headerStyle.BackgroundColor) { [ref] $null = $tc1.AppendChild((GetWordTableStyleCellPr -Style $headerStyle -XmlDocument $XmlDocument)) } $p1 = $tc1.AppendChild($XmlDocument.CreateElement('w', 'p', $xmlnsMain)) $pPr1 = $p1.AppendChild($XmlDocument.CreateElement('w', 'pPr', $xmlnsMain)) $pStyle1 = $pPr1.AppendChild($XmlDocument.CreateElement('w', 'pStyle', $xmlnsMain)) [ref] $null = $pStyle1.SetAttribute('val', $xmlnsMain, $tableStyle.HeaderStyle) $r1 = $p1.AppendChild($XmlDocument.CreateElement('w', 'r', $xmlnsMain)) $t1 = $r1.AppendChild($XmlDocument.CreateElement('w', 't', $xmlnsMain)) [ref] $null = $t1.AppendChild($XmlDocument.CreateTextNode($propertyName)) $tc2 = $tr.AppendChild($XmlDocument.CreateElement('w', 'tc', $xmlnsMain)) $tcPr2 = $tc2.AppendChild($XmlDocument.CreateElement('w', 'tcPr', $xmlnsMain)) if ($null -ne $Table.ColumnWidths) { ## TODO: Refactor out $tcW2 = $tcPr2.AppendChild($XmlDocument.CreateElement('w', 'tcW', $xmlnsMain)) [ref] $null = $tcW2.SetAttribute('w', $xmlnsMain, $Table.ColumnWidths[1] * 50) [ref] $null = $tcW2.SetAttribute('type', $xmlnsMain, 'pct') } $p2 = $tc2.AppendChild($XmlDocument.CreateElement('w', 'p', $xmlnsMain)) $cellPropertyStyle = '{0}__Style' -f $propertyName if ($row.PSObject.Properties[$cellPropertyStyle]) { if (-not (Test-Path -Path Variable:\cellStyle)) { $cellStyle = $Document.Styles[$row.$cellPropertyStyle] } elseif ($cellStyle.Id -ne $row.$cellPropertyStyle) { ## Retrieve the style if we don't already have it $cellStyle = $Document.Styles[$row.$cellPropertyStyle] } if ($cellStyle.BackgroundColor) { [ref] $null = $tc2.AppendChild((GetWordTableStyleCellPr -Style $cellStyle -XmlDocument $XmlDocument)) } if ($row.$cellPropertyStyle) { $pPr2 = $p2.AppendChild($XmlDocument.CreateElement('w', 'pPr', $xmlnsMain)) $pStyle2 = $pPr2.AppendChild($XmlDocument.CreateElement('w', 'pStyle', $xmlnsMain)) [ref] $null = $pStyle2.SetAttribute('val', $xmlnsMain, $row.$cellPropertyStyle) } } if ($null -ne $row.($propertyName)) { ## Create a separate run for each line/break $lines = $row.($propertyName).ToString() -split [System.Environment]::NewLine; for ($l = 0; $l -lt $lines.Count; $l++) { $r2 = $p2.AppendChild($XmlDocument.CreateElement('w', 'r', $xmlnsMain)); $t2 = $r2.AppendChild($XmlDocument.CreateElement('w', 't', $xmlnsMain)); [ref] $null = $t2.AppendChild($XmlDocument.CreateTextNode($lines[$l])); if ($l -lt ($lines.Count -1)) { ## Don't add a line break to the last line/break $r3 = $p2.AppendChild($XmlDocument.CreateElement('w', 'r', $xmlnsMain)); $t3 = $r3.AppendChild($XmlDocument.CreateElement('w', 't', $xmlnsMain)); [ref] $null = $t3.AppendChild($XmlDocument.CreateElement('w', 'br', $xmlnsMain)); } } #end foreach line break } } } #end for each property } #end foreach row } #end if Table.List else { $tbl = $Element.AppendChild((GetWordTable -Table $Table -XmlDocument $XmlDocument)) $tr = $tbl.AppendChild($XmlDocument.CreateElement('w', 'tr', $xmlnsMain)) $trPr = $tr.AppendChild($XmlDocument.CreateElement('w', 'trPr', $xmlnsMain)) $null = $trPr.AppendChild($XmlDocument.CreateElement('w', 'tblHeader', $xmlnsMain)) ## Flow headers across pages for ($i = 0; $i -lt $Table.Columns.Count; $i++) { $tc = $tr.AppendChild($XmlDocument.CreateElement('w', 'tc', $xmlnsMain)) if ($headerStyle.BackgroundColor) { $tcPr = $tc.AppendChild((GetWordTableStyleCellPr -Style $headerStyle -XmlDocument $XmlDocument)) } else { $tcPr = $tc.AppendChild($XmlDocument.CreateElement('w', 'tcPr', $xmlnsMain)) } $tcW = $tcPr.AppendChild($XmlDocument.CreateElement('w', 'tcW', $xmlnsMain)) if (($null -ne $Table.ColumnWidths) -and ($null -ne $Table.ColumnWidths[$i])) { [ref] $null = $tcW.SetAttribute('w', $xmlnsMain, $Table.ColumnWidths[$i] * 50) [ref] $null = $tcW.SetAttribute('type', $xmlnsMain, 'pct') } else { [ref] $null = $tcW.SetAttribute('w', $xmlnsMain, 0) [ref] $null = $tcW.SetAttribute('type', $xmlnsMain, 'auto') } $p = $tc.AppendChild($XmlDocument.CreateElement('w', 'p', $xmlnsMain)) $pPr = $p.AppendChild($XmlDocument.CreateElement('w', 'pPr', $xmlnsMain)) $pStyle = $pPr.AppendChild($XmlDocument.CreateElement('w', 'pStyle', $xmlnsMain)) [ref] $null = $pStyle.SetAttribute('val', $xmlnsMain, $tableStyle.HeaderStyle) $r = $p.AppendChild($XmlDocument.CreateElement('w', 'r', $xmlnsMain)) $t = $r.AppendChild($XmlDocument.CreateElement('w', 't', $xmlnsMain)) [ref] $null = $t.AppendChild($XmlDocument.CreateTextNode($Table.Columns[$i])) } #end for Table.Columns $isAlternatingRow = $false foreach ($row in $Table.Rows) { $tr = $tbl.AppendChild($XmlDocument.CreateElement('w', 'tr', $xmlnsMain)) foreach ($propertyName in $Table.Columns) { $cellPropertyStyle = '{0}__Style' -f $propertyName if ($row.PSObject.Properties[$cellPropertyStyle]) { ## Cell style overrides row/default styles $cellStyleName = $row.$cellPropertyStyle } elseif (-not [System.String]::IsNullOrEmpty($row.__Style)) { ## Row style overrides default style $cellStyleName = $row.__Style } else { ## Use the table row/alternating style.. $cellStyleName = $tableStyle.RowStyle if ($isAlternatingRow) { $cellStyleName = $tableStyle.AlternateRowStyle } } if (-not (Test-Path -Path Variable:\cellStyle)) { $cellStyle = $Document.Styles[$cellStyleName] } elseif ($cellStyle.Id -ne $cellStyleName) { ## Retrieve the style if we don't already have it $cellStyle = $Document.Styles[$cellStyleName] } $tc = $tr.AppendChild($XmlDocument.CreateElement('w', 'tc', $xmlnsMain)) if ($cellStyle.BackgroundColor) { [ref] $null = $tc.AppendChild((GetWordTableStyleCellPr -Style $cellStyle -XmlDocument $XmlDocument)) } $p = $tc.AppendChild($XmlDocument.CreateElement('w', 'p', $xmlnsMain)) $pPr = $p.AppendChild($XmlDocument.CreateElement('w', 'pPr', $xmlnsMain)) $pStyle = $pPr.AppendChild($XmlDocument.CreateElement('w', 'pStyle', $xmlnsMain)) [ref] $null = $pStyle.SetAttribute('val', $xmlnsMain, $cellStyleName) if ($null -ne $row.($propertyName)) { ## Create a separate run for each line/break $lines = $row.($propertyName).ToString() -split [System.Environment]::NewLine; for ($l = 0; $l -lt $lines.Count; $l++) { $r = $p.AppendChild($XmlDocument.CreateElement('w', 'r', $xmlnsMain)); $t = $r.AppendChild($XmlDocument.CreateElement('w', 't', $xmlnsMain)); [ref] $null = $t.AppendChild($XmlDocument.CreateTextNode($lines[$l])); if ($l -lt ($lines.Count -1)) { ## Don't add a line break to the last line/break $r = $p.AppendChild($XmlDocument.CreateElement('w', 'r', $xmlnsMain)); $t = $r.AppendChild($XmlDocument.CreateElement('w', 't', $xmlnsMain)); [ref] $null = $t.AppendChild($XmlDocument.CreateElement('w', 'br', $xmlnsMain)); } } #end foreach line break } } #end foreach property $isAlternatingRow = !$isAlternatingRow } #end foreach row } #end if not Table.List } #end process } #end function OutWordTable function OutWordTOC { <# .SYNOPSIS Output formatted Word table of contents. #> [CmdletBinding()] [OutputType([System.Xml.XmlElement])] param ( [Parameter(Mandatory, ValueFromPipeline)] [System.Object] $TOC, [Parameter(Mandatory)] [System.Xml.XmlDocument] $XmlDocument ) process { $xmlnsMain = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main' $sdt = $XmlDocument.CreateElement('w', 'sdt', $xmlnsMain) $sdtPr = $sdt.AppendChild($XmlDocument.CreateElement('w', 'sdtPr', $xmlnsMain)) $docPartObj = $sdtPr.AppendChild($XmlDocument.CreateElement('w', 'docPartObj', $xmlnsMain)) $docObjectGallery = $docPartObj.AppendChild($XmlDocument.CreateElement('w', 'docPartGallery', $xmlnsMain)) [ref] $null = $docObjectGallery.SetAttribute('val', $xmlnsMain, 'Table of Contents') [ref] $null = $docPartObj.AppendChild($XmlDocument.CreateElement('w', 'docPartUnique', $xmlnsMain)) [ref] $null = $sdt.AppendChild($XmlDocument.CreateElement('w', 'stdEndPr', $xmlnsMain)) $sdtContent = $sdt.AppendChild($XmlDocument.CreateElement('w', 'stdContent', $xmlnsMain)) $p1 = $sdtContent.AppendChild($XmlDocument.CreateElement('w', 'p', $xmlnsMain)) $pPr1 = $p1.AppendChild($XmlDocument.CreateElement('w', 'pPr', $xmlnsMain)) $pStyle1 = $pPr1.AppendChild($XmlDocument.CreateElement('w', 'pStyle', $xmlnsMain)) [ref] $null = $pStyle1.SetAttribute('val', $xmlnsMain, 'TOC') $r1 = $p1.AppendChild($XmlDocument.CreateElement('w', 'r', $xmlnsMain)) $t1 = $r1.AppendChild($XmlDocument.CreateElement('w', 't', $xmlnsMain)) [ref] $null = $t1.AppendChild($XmlDocument.CreateTextNode($TOC.Name)) $p2 = $sdtContent.AppendChild($XmlDocument.CreateElement('w', 'p', $xmlnsMain)) $pPr2 = $p2.AppendChild($XmlDocument.CreateElement('w', 'pPr', $xmlnsMain)) $tabs2 = $pPr2.AppendChild($XmlDocument.CreateElement('w', 'tabs', $xmlnsMain)) $tab2 = $tabs2.AppendChild($XmlDocument.CreateElement('w', 'tab', $xmlnsMain)) [ref] $null = $tab2.SetAttribute('val', $xmlnsMain, 'right') [ref] $null = $tab2.SetAttribute('leader', $xmlnsMain, 'dot') [ref] $null = $tab2.SetAttribute('pos', $xmlnsMain, '9016') #10790?! $r2 = $p2.AppendChild($XmlDocument.CreateElement('w', 'r', $xmlnsMain)) ##TODO: Refactor duplicate code $fldChar1 = $r2.AppendChild($XmlDocument.CreateElement('w', 'fldChar', $xmlnsMain)) [ref] $null = $fldChar1.SetAttribute('fldCharType', $xmlnsMain, 'begin') $r3 = $p2.AppendChild($XmlDocument.CreateElement('w', 'r', $xmlnsMain)) $instrText = $r3.AppendChild($XmlDocument.CreateElement('w', 'instrText', $xmlnsMain)) [ref] $null = $instrText.SetAttribute('space', 'http://www.w3.org/XML/1998/namespace', 'preserve') [ref] $null = $instrText.AppendChild($XmlDocument.CreateTextNode(' TOC \o "1-3" \h \z \u ')) $r4 = $p2.AppendChild($XmlDocument.CreateElement('w', 'r', $xmlnsMain)) $fldChar2 = $r4.AppendChild($XmlDocument.CreateElement('w', 'fldChar', $xmlnsMain)) [ref] $null = $fldChar2.SetAttribute('fldCharType', $xmlnsMain, 'separate') $p3 = $sdtContent.AppendChild($XmlDocument.CreateElement('w', 'p', $xmlnsMain)) $r5 = $p3.AppendChild($XmlDocument.CreateElement('w', 'r', $xmlnsMain)) #$rPr3 = $r3.AppendChild($XmlDocument.CreateElement('w', 'rPr', $xmlnsMain)); $fldChar3 = $r5.AppendChild($XmlDocument.CreateElement('w', 'fldChar', $xmlnsMain)) [ref] $null = $fldChar3.SetAttribute('fldCharType', $xmlnsMain, 'end') return $sdt } #end process } #end function OutWordTOC function OutWordBlankLine { <# .SYNOPSIS Output formatted Word xml blank line (paragraph). #> [CmdletBinding()] param ( [Parameter(Mandatory, ValueFromPipeline)] [System.Object] $BlankLine, [Parameter(Mandatory)] [System.Xml.XmlDocument] $XmlDocument, [Parameter(Mandatory)] [System.Xml.XmlElement] $Element ) process { $xmlnsMain = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main' for ($i = 0; $i -lt $BlankLine.LineCount; $i++) { [ref] $null = $Element.AppendChild($XmlDocument.CreateElement('w', 'p', $xmlnsMain)) } } } #end function OutWordLineBreak function GetWordStyle { <# .SYNOPSIS Generates Word Xml style element from a PScribo document style. #> [CmdletBinding()] [OutputType([System.Xml.XmlElement])] param ( ## PScribo document style [Parameter(Mandatory, ValueFromPipeline)] [System.Object] $Style, [Parameter(Mandatory)] [System.Xml.XmlDocument] $XmlDocument, [Parameter(Mandatory)] [ValidateSet('Paragraph', 'Character')] [System.String] $Type ) process { $xmlnsMain = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main' if ($Type -eq 'Paragraph') { $styleId = $Style.Id $styleName = $Style.Name $linkId = '{0}Char' -f $Style.Id } else { $styleId = '{0}Char' -f $Style.Id $styleName = '{0} Char' -f $Style.Name $linkId = $Style.Id } $documentStyle = $XmlDocument.CreateElement('w', 'style', $xmlnsMain) [ref] $null = $documentStyle.SetAttribute('type', $xmlnsMain, $Type.ToLower()) if ($Style.Id -eq $Document.DefaultStyle) { ## Set as default style [ref] $null = $documentStyle.SetAttribute('default', $xmlnsMain, 1) $uiPriority = $documentStyle.AppendChild($XmlDocument.CreateElement('w', 'uiPriority', $xmlnsMain)) [ref] $null = $uiPriority.SetAttribute('val', $xmlnsMain, 1) } elseif ($Style.Hidden -eq $true) { ## Semi hide style (headers and footers etc) [ref] $null = $documentStyle.AppendChild($XmlDocument.CreateElement('w', 'semiHidden', $xmlnsMain)) } elseif (($Document.TableStyles.Values | ForEach-Object -Process { $_.HeaderStyle $_.RowStyle $_.AlternateRowStyle }) -contains $Style.Id) { ## Semi hide styles behind table styles (except default style!) [ref] $null = $documentStyle.AppendChild($XmlDocument.CreateElement('w', 'semiHidden', $xmlnsMain)) } [ref] $null = $documentStyle.SetAttribute('styleId', $xmlnsMain, $styleId) $documentStyleName = $documentStyle.AppendChild($XmlDocument.CreateElement('w', 'name', $xmlnsMain)) [ref] $null = $documentStyleName.SetAttribute('val', $xmlnsMain, $styleName) $basedOn = $documentStyle.AppendChild($XmlDocument.CreateElement('w', 'basedOn', $xmlnsMain)) [ref] $null = $basedOn.SetAttribute('val', $xmlnsMain, 'Normal') $link = $documentStyle.AppendChild($XmlDocument.CreateElement('w', 'link', $xmlnsMain)) [ref] $null = $link.SetAttribute('val', $xmlnsMain, $linkId) $next = $documentStyle.AppendChild($XmlDocument.CreateElement('w', 'next', $xmlnsMain)) [ref] $null = $next.SetAttribute('val', $xmlnsMain, 'Normal') [ref] $null = $documentStyle.AppendChild($XmlDocument.CreateElement('w', 'qFormat', $xmlnsMain)) $pPr = $documentStyle.AppendChild($XmlDocument.CreateElement('w', 'pPr', $xmlnsMain)) [ref] $null = $pPr.AppendChild($XmlDocument.CreateElement('w', 'keepNext', $xmlnsMain)) [ref] $null = $pPr.AppendChild($XmlDocument.CreateElement('w', 'keepLines', $xmlnsMain)) $spacing = $pPr.AppendChild($XmlDocument.CreateElement('w', 'spacing', $xmlnsMain)) [ref] $null = $spacing.SetAttribute('before', $xmlnsMain, 0) [ref] $null = $spacing.SetAttribute('after', $xmlnsMain, 0) ## Set the <w:jc> (justification) element $jc = $pPr.AppendChild($XmlDocument.CreateElement('w', 'jc', $xmlnsMain)) if ($Style.Align.ToLower() -eq 'justify') { [ref] $null = $jc.SetAttribute('val', $xmlnsMain, 'distribute') } else { [ref] $null = $jc.SetAttribute('val', $xmlnsMain, $Style.Align.ToLower()) } if ($Style.BackgroundColor) { $shd = $pPr.AppendChild($XmlDocument.CreateElement('w', 'shd', $xmlnsMain)) [ref] $null = $shd.SetAttribute('val', $xmlnsMain, 'clear') [ref] $null = $shd.SetAttribute('color', $xmlnsMain, 'auto') [ref] $null = $shd.SetAttribute('fill', $xmlnsMain, (ConvertToWordColor -Color $Style.BackgroundColor)) } [ref] $null = $documentStyle.AppendChild((GetWordStyleRunPr -Style $Style -XmlDocument $XmlDocument)) return $documentStyle } #end process } #end function GetWordStyle function GetWordTableStyle { <# .SYNOPSIS Generates Word Xml table style element from a PScribo document table style. #> [CmdletBinding()] [OutputType([System.Xml.XmlElement])] param ( ## PScribo document style [Parameter(Mandatory, ValueFromPipeline)] [System.Object] $tableStyle, [Parameter(Mandatory)] [System.Xml.XmlDocument] $XmlDocument ) process { $xmlnsMain = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main' $Style = $XmlDocument.CreateElement('w', 'style', $xmlnsMain) [ref] $null = $Style.SetAttribute('type', $xmlnsMain, 'table') [ref] $null = $Style.SetAttribute('styleId', $xmlnsMain, $tableStyle.Id) $name = $Style.AppendChild($XmlDocument.CreateElement('w', 'name', $xmlnsMain)) [ref] $null = $name.SetAttribute('val', $xmlnsMain, $tableStyle.Id) $tblPr = $Style.AppendChild($XmlDocument.CreateElement('w', 'tblPr', $xmlnsMain)) $tblStyleRowBandSize = $tblPr.AppendChild($XmlDocument.CreateElement('w', 'tblStyleRowBandSize', $xmlnsMain)) [ref] $null = $tblStyleRowBandSize.SetAttribute('val', $xmlnsMain, 1) if ($tableStyle.BorderWidth -gt 0) { $tblBorders = $tblPr.AppendChild($XmlDocument.CreateElement('w', 'tblBorders', $xmlnsMain)) foreach ($border in @('top', 'bottom', 'start', 'end', 'insideH', 'insideV')) { $b = $tblBorders.AppendChild($XmlDocument.CreateElement('w', $border, $xmlnsMain)) [ref] $null = $b.SetAttribute('sz', $xmlnsMain, (ConvertMmToOctips $tableStyle.BorderWidth)) [ref] $null = $b.SetAttribute('val', $xmlnsMain, 'single') [ref] $null = $b.SetAttribute('color', $xmlnsMain, (ConvertToWordColor -Color $tableStyle.BorderColor)) } } [ref] $null = $Style.AppendChild((GetWordTableStylePr -Style $Document.Styles[$tableStyle.HeaderStyle] -Type Header -XmlDocument $XmlDocument)) [ref] $null = $Style.AppendChild((GetWordTableStylePr -Style $Document.Styles[$tableStyle.RowStyle] -Type Row -XmlDocument $XmlDocument)) [ref] $null = $Style.AppendChild((GetWordTableStylePr -Style $Document.Styles[$tableStyle.AlternateRowStyle] -Type AlternateRow -XmlDocument $XmlDocument)) return $Style } } #end function GetWordTableStyle function GetWordStyleParagraphPr { <# .SYNOPSIS Generates Word paragraph (pPr) formatting properties #> [CmdletBinding()] [OutputType([System.Xml.XmlElement])] param ( [Parameter(Mandatory)] [System.Object] $Style, [Parameter(Mandatory)] [System.Xml.XmlDocument] $XmlDocument ) process { $xmlnsMain = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main' $pPr = $XmlDocument.CreateElement('w', 'pPr', $xmlnsMain) $spacing = $pPr.AppendChild($XmlDocument.CreateElement('w', 'spacing', $xmlnsMain)) [ref] $null = $spacing.SetAttribute('before', $xmlnsMain, 0) [ref] $null = $spacing.SetAttribute('after', $xmlnsMain, 0) [ref] $null = $pPr.AppendChild($XmlDocument.CreateElement('w', 'keepNext', $xmlnsMain)) [ref] $null = $pPr.AppendChild($XmlDocument.CreateElement('w', 'keepLines', $xmlnsMain)) $jc = $pPr.AppendChild($XmlDocument.CreateElement('w', 'jc', $xmlnsMain)) if ($Style.Align.ToLower() -eq 'justify') { [ref] $null = $jc.SetAttribute('val', $xmlnsMain, 'distribute') } else { [ref] $null = $jc.SetAttribute('val', $xmlnsMain, $Style.Align.ToLower()) } return $pPr } #end process } #end function GetWordTableCellPr function GetWordStyleRunPrColor { <# .SYNOPSIS Generates Word run (rPr) text colour formatting property only. .NOTES This is only required to override the text colour in table rows/headers as I can't get this (yet) applied via the table style? #> [CmdletBinding()] [OutputType([System.Xml.XmlElement])] param ( [Parameter(Mandatory)] [System.Object] $Style, [Parameter(Mandatory)] [System.Xml.XmlDocument] $XmlDocument ) process { $rPr = $XmlDocument.CreateElement('w', 'rPr', $xmlnsMain) $Color = $rPr.AppendChild($XmlDocument.CreateElement('w', 'color', $xmlnsMain)) [ref] $null = $Color.SetAttribute('val', $xmlnsMain, (ConvertToWordColor -Color $Style.Color)) return $rPr } } #end function GetWordStyleRunPrColor function GetWordStyleRunPr { <# .SYNOPSIS Generates Word run (rPr) formatting properties #> [CmdletBinding()] [OutputType([System.Xml.XmlElement])] param ( [Parameter(Mandatory)] [System.Object] $Style, [Parameter(Mandatory)] [System.Xml.XmlDocument] $XmlDocument ) process { $rPr = $XmlDocument.CreateElement('w', 'rPr', $xmlnsMain) $rFonts = $rPr.AppendChild($XmlDocument.CreateElement('w', 'rFonts', $xmlnsMain)) [ref] $null = $rFonts.SetAttribute('ascii', $xmlnsMain, $Style.Font[0]) [ref] $null = $rFonts.SetAttribute('hAnsi', $xmlnsMain, $Style.Font[0]) if ($Style.Bold) { [ref] $null = $rPr.AppendChild($XmlDocument.CreateElement('w', 'b', $xmlnsMain)) } if ($Style.Underline) { [ref] $null = $rPr.AppendChild($XmlDocument.CreateElement('w', 'u', $xmlnsMain)) } if ($Style.Italic) { [ref] $null = $rPr.AppendChild($XmlDocument.CreateElement('w', 'i', $xmlnsMain)) } $Color = $rPr.AppendChild($XmlDocument.CreateElement('w', 'color', $xmlnsMain)) [ref] $null = $Color.SetAttribute('val', $xmlnsMain, (ConvertToWordColor -Color $Style.Color)) $sz = $rPr.AppendChild($XmlDocument.CreateElement('w', 'sz', $xmlnsMain)) [ref] $null = $sz.SetAttribute('val', $xmlnsMain, $Style.Size * 2) return $rPr } #end process } #end function GetWordStyleRunPr function GetWordTableStyleCellPr { <# .SYNOPSIS Generates Word table cell (tcPr) formatting properties #> [CmdletBinding()] [OutputType([System.Xml.XmlElement])] param ( [Parameter(Mandatory)] [System.Object] $Style, [Parameter(Mandatory)] [System.Xml.XmlDocument] $XmlDocument ) process { $xmlnsMain = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main' $tcPr = $XmlDocument.CreateElement('w', 'tcPr', $xmlnsMain) if ($Style.BackgroundColor) { $shd = $tcPr.AppendChild($XmlDocument.CreateElement('w', 'shd', $xmlnsMain)) [ref] $null = $shd.SetAttribute('val', $xmlnsMain, 'clear') [ref] $null = $shd.SetAttribute('color', $xmlnsMain, 'auto') [ref] $null = $shd.SetAttribute('fill', $xmlnsMain, (ConvertToWordColor -Color $Style.BackgroundColor)) } return $tcPr } #end process } #end function GetWordTableCellPr function GetWordTableStylePr { <# .SYNOPSIS Generates Word table style (tblStylePr) formatting properties for specified table style type #> [CmdletBinding()] [OutputType([System.Xml.XmlElement])] param ( [Parameter(Mandatory)] [System.Object] $Style, [Parameter(Mandatory)] [ValidateSet('Header', 'Row', 'AlternateRow')] [System.String] $Type, [Parameter(Mandatory)] [System.Xml.XmlDocument] $XmlDocument ) process { $xmlnsMain = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main' $tblStylePr = $XmlDocument.CreateElement('w', 'tblStylePr', $xmlnsMain) [ref] $null = $tblStylePr.AppendChild($XmlDocument.CreateElement('w', 'tblPr', $xmlnsMain)) switch ($Type) { 'Header' { $tblStylePrType = 'firstRow' } 'Row' { $tblStylePrType = 'band2Horz' } 'AlternateRow' { $tblStylePrType = 'band1Horz' } } [ref] $null = $tblStylePr.SetAttribute('type', $xmlnsMain, $tblStylePrType) [ref] $null = $tblStylePr.AppendChild((GetWordStyleParagraphPr -Style $Style -XmlDocument $XmlDocument)) [ref] $null = $tblStylePr.AppendChild((GetWordStyleRunPr -Style $Style -XmlDocument $XmlDocument)) [ref] $null = $tblStylePr.AppendChild((GetWordTableStyleCellPr -Style $Style -XmlDocument $XmlDocument)) return $tblStylePr } #end process } #end function GetWordTableStylePr function GetWordSectionPr { <# .SYNOPSIS Outputs Office Open XML section element to set page size and margins. #> [CmdletBinding()] [OutputType([System.Xml.XmlElement])] param ( [Parameter(Mandatory)] [System.Single] $PageWidth, [Parameter(Mandatory)] [System.Single] $PageHeight, [Parameter(Mandatory)] [System.Single] $PageMarginTop, [Parameter(Mandatory)] [System.Single] $PageMarginLeft, [Parameter(Mandatory)] [System.Single] $PageMarginBottom, [Parameter(Mandatory)] [System.Single] $PageMarginRight, [Parameter(Mandatory)] [System.String] $Orientation, [Parameter(Mandatory)] [System.Xml.XmlDocument] $XmlDocument ) process { $xmlnsMain = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'; $sectPr = $XmlDocument.CreateElement('w', 'sectPr', $xmlnsMain); $pgSz = $sectPr.AppendChild($XmlDocument.CreateElement('w', 'pgSz', $xmlnsMain)); [ref] $null = $pgSz.SetAttribute('w', $xmlnsMain, (ConvertMmToTwips -Millimeter $PageWidth)); [ref] $null = $pgSz.SetAttribute('h', $xmlnsMain, (ConvertMmToTwips -Millimeter $PageHeight)); [ref] $null = $pgSz.SetAttribute('orient', $xmlnsMain, $Orientation.ToLower()); $pgMar = $sectPr.AppendChild($XmlDocument.CreateElement('w', 'pgMar', $xmlnsMain)); [ref] $null = $pgMar.SetAttribute('top', $xmlnsMain, (ConvertMmToTwips -Millimeter $PageMarginTop)); [ref] $null = $pgMar.SetAttribute('bottom', $xmlnsMain, (ConvertMmToTwips -Millimeter $PageMarginBottom)); [ref] $null = $pgMar.SetAttribute('left', $xmlnsMain, (ConvertMmToTwips -Millimeter $PageMarginLeft)); [ref] $null = $pgMar.SetAttribute('right', $xmlnsMain, (ConvertMmToTwips -Millimeter $PageMarginRight)); return $sectPr; } #end process } #end GetWordSectionPr function OutWordStylesDocument { <# .SYNOPSIS Outputs Office Open XML style document #> [CmdletBinding()] [OutputType([System.Xml.XmlDocument])] param ( ## PScribo document styles [Parameter(Mandatory, ValueFromPipeline)] [System.Collections.Hashtable] $Styles, ## PScribo document tables styles [Parameter(Mandatory, ValueFromPipeline)] [System.Collections.Hashtable] $TableStyles ) process { ## Create the Style.xml document $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')) $documentStyles = $XmlDocument.AppendChild($XmlDocument.CreateElement('w', 'styles', $xmlnsMain)) ## Create default style $defaultStyle = $documentStyles.AppendChild($XmlDocument.CreateElement('w', 'style', $xmlnsMain)) [ref] $null = $defaultStyle.SetAttribute('type', $xmlnsMain, 'paragraph') [ref] $null = $defaultStyle.SetAttribute('default', $xmlnsMain, '1') [ref] $null = $defaultStyle.SetAttribute('styleId', $xmlnsMain, 'Normal') $defaultStyleName = $defaultStyle.AppendChild($XmlDocument.CreateElement('w', 'name', $xmlnsMain)) [ref] $null = $defaultStyleName.SetAttribute('val', $xmlnsMain, 'Normal') [ref] $null = $defaultStyle.AppendChild($XmlDocument.CreateElement('w', 'qFormat', $xmlnsMain)) foreach ($Style in $Styles.Values) { $documentParagraphStyle = GetWordStyle -Style $Style -XmlDocument $XmlDocument -Type Paragraph [ref] $null = $documentStyles.AppendChild($documentParagraphStyle) $documentCharacterStyle = GetWordStyle -Style $Style -XmlDocument $XmlDocument -Type Character [ref] $null = $documentStyles.AppendChild($documentCharacterStyle) } foreach ($tableStyle in $TableStyles.Values) { $documentTableStyle = GetWordTableStyle -TableStyle $tableStyle -XmlDocument $XmlDocument [ref] $null = $documentStyles.AppendChild($documentTableStyle) } return $XmlDocument } #end process } #end function OutWordStyleDocument function OutWordSettingsDocument { <# .SYNOPSIS Outputs Office Open XML settings document #> [CmdletBinding()] [OutputType([System.Xml.XmlDocument])] param ( [Parameter()] [System.Management.Automation.SwitchParameter] $UpdateFields ) process { ## Create the Style.xml document $xmlnsMain = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main' # <w:settings xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" # xmlns:o="urn:schemas-microsoft-com:office:office" # xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" # xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" # xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w10="urn:schemas-microsoft-com:office:word" # xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" # xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" # xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" # xmlns:sl="http://schemas.openxmlformats.org/schemaLibrary/2006/main" # mc:Ignorable="w14 w15"> $settingsDocument = New-Object -TypeName 'System.Xml.XmlDocument' [ref] $null = $settingsDocument.AppendChild($settingsDocument.CreateXmlDeclaration('1.0', 'utf-8', 'yes')) $settings = $settingsDocument.AppendChild($settingsDocument.CreateElement('w', 'settings', $xmlnsMain)) ## Set compatibility mode to Word 2013 $compat = $settings.AppendChild($settingsDocument.CreateElement('w', 'compat', $xmlnsMain)) $compatSetting = $compat.AppendChild($settingsDocument.CreateElement('w', 'compatSetting', $xmlnsMain)) [ref] $null = $compatSetting.SetAttribute('name', $xmlnsMain, 'compatibilityMode') [ref] $null = $compatSetting.SetAttribute('uri', $xmlnsMain, 'http://schemas.microsoft.com/office/word') [ref] $null = $compatSetting.SetAttribute('val', $xmlnsMain, 15) if ($UpdateFields) { $wupdateFields = $settings.AppendChild($settingsDocument.CreateElement('w', 'updateFields', $xmlnsMain)) [ref] $null = $wupdateFields.SetAttribute('val', $xmlnsMain, 'true') } return $settingsDocument } #end process } #end function OutWordSettingsDocument function OutWordImage { <# .SYNOPSIS Output Image to Word. #> [CmdletBinding()] [OutputType([System.Xml.XmlElement])] param ( [Parameter(Mandatory, ValueFromPipeline)] [System.Object] $Image, [Parameter(Mandatory)] [System.Xml.XmlDocument] $XmlDocument ) process { $xmlnsMain = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main' $xmlnswpDrawingWordProcessing = 'http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing' $xmlnsDrawingMain = 'http://schemas.openxmlformats.org/drawingml/2006/main' $xmlnsDrawingPicture = 'http://schemas.openxmlformats.org/drawingml/2006/picture' $xmlnsRelationships = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships' $p = $XmlDocument.CreateElement('w', 'p', $xmlnsMain) $pPr = $p.AppendChild($XmlDocument.CreateElement('w', 'pPr', $xmlnsMain)) $spacing = $pPr.AppendChild($XmlDocument.CreateElement('w', 'spacing', $xmlnsMain)) [ref] $null = $spacing.SetAttribute('before', $xmlnsMain, 0) [ref] $null = $spacing.SetAttribute('after', $xmlnsMain, 0) $jc = $pPr.AppendChild($XmlDocument.CreateElement('w', 'jc', $xmlnsMain)) [ref] $null = $jc.SetAttribute('val', $xmlnsMain, $Image.Align.ToLower()) $r = $p.AppendChild($XmlDocument.CreateElement('w', 'r', $xmlnsMain)) $rPr = $r.AppendChild($XmlDocument.CreateElement('w', 'rPr', $xmlnsMain)) $drawing = $rPr.AppendChild($XmlDocument.CreateElement('w', 'drawing', $xmlnsMain)) $inline = $drawing.AppendChild($XmlDocument.CreateElement('wp', 'inline', $xmlnswpDrawingWordProcessing)) [ref] $null = $inline.SetAttribute('distT', '0') [ref] $null = $inline.SetAttribute('distB', '0') [ref] $null = $inline.SetAttribute('distL', '0') [ref] $null = $inline.SetAttribute('distR', '0') $extent = $inline.AppendChild($XmlDocument.CreateElement('wp', 'extent', $xmlnswpDrawingWordProcessing)) [ref] $null = $extent.SetAttribute('cx', $Image.WidthEm) [ref] $null = $extent.SetAttribute('cy', $Image.HeightEm) $effectExtent = $inline.AppendChild($XmlDocument.CreateElement('wp', 'effectExtent', $xmlnswpDrawingWordProcessing)) [ref] $null = $effectExtent.SetAttribute('l', '0') [ref] $null = $effectExtent.SetAttribute('t', '0') [ref] $null = $effectExtent.SetAttribute('r', '0') [ref] $null = $effectExtent.SetAttribute('b', '0') $docPr = $inline.AppendChild($XmlDocument.CreateElement('wp', 'docPr', $xmlnswpDrawingWordProcessing)) [ref] $null = $docPr.SetAttribute('id', $Image.ImageNumber) [ref] $null = $docPr.SetAttribute('name', $Image.Name) [ref] $null = $docPr.SetAttribute('descr', $Image.Name) $cNvGraphicFramePr = $inline.AppendChild($XmlDocument.CreateElement('wp', 'cNvGraphicFramePr', $xmlnswpDrawingWordProcessing)) $graphicFrameLocks = $cNvGraphicFramePr.AppendChild($XmlDocument.CreateElement('a', 'graphicFrameLocks', $xmlnsDrawingMain)) [ref] $null = $graphicFrameLocks.SetAttribute('noChangeAspect', '1') $graphic = $inline.AppendChild($XmlDocument.CreateElement('a', 'graphic', $xmlnsDrawingMain)) $graphicData = $graphic.AppendChild($XmlDocument.CreateElement('a', 'graphicData', $xmlnsDrawingMain)) [ref] $null = $graphicData.SetAttribute('uri', 'http://schemas.openxmlformats.org/drawingml/2006/picture') $pic = $graphicData.AppendChild($XmlDocument.CreateElement('pic', 'pic', $xmlnsDrawingPicture)) $nvPicPr = $pic.AppendChild($XmlDocument.CreateElement('pic', 'nvPicPr', $xmlnsDrawingPicture)) $cNvPr = $nvPicPr.AppendChild($XmlDocument.CreateElement('pic', 'cNvPr', $xmlnsDrawingPicture)) [ref] $null = $cNvPr.SetAttribute('id', $Image.ImageNumber) [ref] $null = $cNvPr.SetAttribute('name', $Image.Name) [ref] $null = $cNvPr.SetAttribute('descr', $Image.Name) $cNvPicPr = $nvPicPr.AppendChild($XmlDocument.CreateElement('pic', 'cNvPicPr', $xmlnsDrawingPicture)) $picLocks = $cNvPicPr.AppendChild($XmlDocument.CreateElement('a', 'picLocks', $xmlnsDrawingMain)) [ref] $null = $picLocks.SetAttribute('noChangeAspect', '1') [ref] $null = $picLocks.SetAttribute('noChangeArrowheads', '1') $blipFill = $pic.AppendChild($XmlDocument.CreateElement('pic', 'blipFill', $xmlnsDrawingPicture)) $blip = $blipFill.AppendChild($XmlDocument.CreateElement('a', 'blip', $xmlnsDrawingMain)) [ref] $null = $blip.SetAttribute('embed', $xmlnsRelationships, $Image.Name) [ref] $null = $blip.SetAttribute('cstate', 'print') $extlst = $blip.AppendChild($XmlDocument.CreateElement('a', 'extlst', $xmlnsDrawingMain)) $ext = $extlst.AppendChild($XmlDocument.CreateElement('a', 'ext', $xmlnsDrawingMain)) [ref] $null = $ext.SetAttribute('uri', '') [ref] $null = $blipFill.AppendChild($XmlDocument.CreateElement('a', 'srcRect', $xmlnsDrawingMain)) $stretch = $blipFill.AppendChild($XmlDocument.CreateElement('a', 'stretch', $xmlnsDrawingMain)) [ref] $null = $stretch.AppendChild($XmlDocument.CreateElement('a', 'fillRect', $xmlnsDrawingMain)) $spPr = $pic.AppendChild($XmlDocument.CreateElement('pic', 'spPr', $xmlnsDrawingPicture)) [ref] $null = $spPr.SetAttribute('bwMode', 'auto') $xfrm = $spPr.AppendChild($XmlDocument.CreateElement('a', 'xfrm', $xmlnsDrawingMain)) $off = $xfrm.AppendChild($XmlDocument.CreateElement('a', 'off', $xmlnsDrawingMain)) [ref] $null = $off.SetAttribute('x', '0') [ref] $null = $off.SetAttribute('y', '0') $ext = $xfrm.AppendChild($XmlDocument.CreateElement('a', 'ext', $xmlnsDrawingMain)) [ref] $null = $ext.SetAttribute('cx', $Image.WidthEm) [ref] $null = $ext.SetAttribute('cy', $Image.HeightEm) $prstGeom = $spPr.AppendChild($XmlDocument.CreateElement('a', 'prstGeom', $xmlnsDrawingMain)) [ref] $null = $prstGeom.SetAttribute('prst', 'rect') [ref] $null = $prstGeom.AppendChild($XmlDocument.CreateElement('a', 'avLst', $xmlnsDrawingMain)) $null = $spPr.AppendChild($XmlDocument.CreateElement('a', 'noFill', $xmlnsDrawingMain)) $ln = $spPr.AppendChild($XmlDocument.CreateElement('a', 'ln', $xmlnsDrawingMain)) $null = $ln.AppendChild($XmlDocument.CreateElement('a', 'noFill', $xmlnsDrawingMain)) return $p } #end process } #end function OutWordImage #endregion OutWord Private Functions # SIG # Begin signature block # MIIcawYJKoZIhvcNAQcCoIIcXDCCHFgCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQU2aJr2nCd3NXqqFzSorf07p2n # IQSggheaMIIFIzCCBAugAwIBAgIQAsbTxa4q6RSRmx0hkVyicTANBgkqhkiG9w0B # AQsFADByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD # VQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFz # c3VyZWQgSUQgQ29kZSBTaWduaW5nIENBMB4XDTE5MDcwMzAwMDAwMFoXDTIxMTEw # MzEyMDAwMFowYDELMAkGA1UEBhMCR0IxDzANBgNVBAcTBkxvbmRvbjEfMB0GA1UE # ChMWVmlydHVhbCBFbmdpbmUgTGltaXRlZDEfMB0GA1UEAxMWVmlydHVhbCBFbmdp # bmUgTGltaXRlZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJ/s4NME # JLA1Aji4EHJ85uwyEEAepndYn1X8pRnGkOlTzVHITAeH7BQnehjbNwCj7MHUPTSM # zSucXhyfaMZthCNYtugyZ2uU4uVjB1f3xdmXXFX+aukMYgCk1ZQFbQMBqbzRY4Cl # DwlLNGVEjDJeLBUL6ciIETqDc27YLg772WLpuvIXne13EYXN422Y83XRqEMf4v9S # 398S8MRk5qdasRtxYZY6GciZZQnAL/XObpXDM3tDFgcQuyGcZttRuXVZXEj+mlY8 # gUIzkSJ0aJn1pVVTsa+tCvAZuJMJwdPhyM7NUa7Ysm7n9qdF7BvcrWBmaYRfDyya # lLwRoOcI2HVodX8CAwEAAaOCAcUwggHBMB8GA1UdIwQYMBaAFFrEuXsqCqOl6nED # wGD5LfZldQ5YMB0GA1UdDgQWBBSDFWXl70FjVfl8IBwATpE46qvGeDAOBgNVHQ8B # Af8EBAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwMwdwYDVR0fBHAwbjA1oDOgMYYv # aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NoYTItYXNzdXJlZC1jcy1nMS5jcmww # NaAzoDGGL2h0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9zaGEyLWFzc3VyZWQtY3Mt # ZzEuY3JsMEwGA1UdIARFMEMwNwYJYIZIAYb9bAMBMCowKAYIKwYBBQUHAgEWHGh0 # dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCAYGZ4EMAQQBMIGEBggrBgEFBQcB # AQR4MHYwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBOBggr # BgEFBQcwAoZCaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0U0hB # MkFzc3VyZWRJRENvZGVTaWduaW5nQ0EuY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZI # hvcNAQELBQADggEBAJ1VZZNMAy8KyQLBqwRWAWDqcOxjVly6FTIeqO2/ul9rEYm8 # B9mNx60/AL+TbTbUwBzia2pwBuIin70eClZHFstvQcASBbB0k14R/rs+jestfFRm # rsEz272POc6vsKce3TOlqBc2rtvVyuUPRvI2yQm1WYTpOgQnnp3ix2LBd+fgRANs # P9yurvnGdEFFzToFDXFVkFHBQ9Pr5tAb4i7ZkSFC52BtB7NVuoiH83lx07SyjIxU # 11ELEDZBpO3HiTsTzbhPAEw4CP++ONK8fieWZevDK9DFEiNIC0gWL/DH1+c7eihO # oJdJqRAT9wkAMIjcskZ5LObGvMst/hqwBewpLzYwggUwMIIEGKADAgECAhAECRgb # X9W7ZnVTQ7VvlVAIMA0GCSqGSIb3DQEBCwUAMGUxCzAJBgNVBAYTAlVTMRUwEwYD # VQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAi # BgNVBAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0xMzEwMjIxMjAw # MDBaFw0yODEwMjIxMjAwMDBaMHIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdp # Q2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xMTAvBgNVBAMTKERp # Z2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBDb2RlIFNpZ25pbmcgQ0EwggEiMA0GCSqG # SIb3DQEBAQUAA4IBDwAwggEKAoIBAQD407Mcfw4Rr2d3B9MLMUkZz9D7RZmxOttE # 9X/lqJ3bMtdx6nadBS63j/qSQ8Cl+YnUNxnXtqrwnIal2CWsDnkoOn7p0WfTxvsp # J8fTeyOU5JEjlpB3gvmhhCNmElQzUHSxKCa7JGnCwlLyFGeKiUXULaGj6YgsIJWu # HEqHCN8M9eJNYBi+qsSyrnAxZjNxPqxwoqvOf+l8y5Kh5TsxHM/q8grkV7tKtel0 # 5iv+bMt+dDk2DZDv5LVOpKnqagqrhPOsZ061xPeM0SAlI+sIZD5SlsHyDxL0xY4P # waLoLFH3c7y9hbFig3NBggfkOItqcyDQD2RzPJ6fpjOp/RnfJZPRAgMBAAGjggHN # MIIByTASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjATBgNVHSUE # DDAKBggrBgEFBQcDAzB5BggrBgEFBQcBAQRtMGswJAYIKwYBBQUHMAGGGGh0dHA6 # Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBDBggrBgEFBQcwAoY3aHR0cDovL2NhY2VydHMu # ZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNydDCBgQYDVR0f # BHoweDA6oDigNoY0aHR0cDovL2NybDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNz # dXJlZElEUm9vdENBLmNybDA6oDigNoY0aHR0cDovL2NybDMuZGlnaWNlcnQuY29t # L0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNybDBPBgNVHSAESDBGMDgGCmCGSAGG # /WwAAgQwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQ # UzAKBghghkgBhv1sAzAdBgNVHQ4EFgQUWsS5eyoKo6XqcQPAYPkt9mV1DlgwHwYD # VR0jBBgwFoAUReuir/SSy4IxLVGLp6chnfNtyA8wDQYJKoZIhvcNAQELBQADggEB # AD7sDVoks/Mi0RXILHwlKXaoHV0cLToaxO8wYdd+C2D9wz0PxK+L/e8q3yBVN7Dh # 9tGSdQ9RtG6ljlriXiSBThCk7j9xjmMOE0ut119EefM2FAaK95xGTlz/kLEbBw6R # Ffu6r7VRwo0kriTGxycqoSkoGjpxKAI8LpGjwCUR4pwUR6F6aGivm6dcIFzZcbEM # j7uo+MUSaJ/PQMtARKUT8OZkDCUIQjKyNookAv4vcn4c10lFluhZHen6dGRrsutm # Q9qzsIzV6Q3d9gEgzpkxYz0IGhizgZtPxpMQBvwHgfqL2vmCSfdibqFT+hKUGIUu # kpHqaGxEMrJmoecYpJpkUe8wggZqMIIFUqADAgECAhADAZoCOv9YsWvW1ermF/Bm # MA0GCSqGSIb3DQEBBQUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2Vy # dCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lD # ZXJ0IEFzc3VyZWQgSUQgQ0EtMTAeFw0xNDEwMjIwMDAwMDBaFw0yNDEwMjIwMDAw # MDBaMEcxCzAJBgNVBAYTAlVTMREwDwYDVQQKEwhEaWdpQ2VydDElMCMGA1UEAxMc # RGlnaUNlcnQgVGltZXN0YW1wIFJlc3BvbmRlcjCCASIwDQYJKoZIhvcNAQEBBQAD # ggEPADCCAQoCggEBAKNkXfx8s+CCNeDg9sYq5kl1O8xu4FOpnx9kWeZ8a39rjJ1V # +JLjntVaY1sCSVDZg85vZu7dy4XpX6X51Id0iEQ7Gcnl9ZGfxhQ5rCTqqEsskYnM # Xij0ZLZQt/USs3OWCmejvmGfrvP9Enh1DqZbFP1FI46GRFV9GIYFjFWHeUhG98oO # jafeTl/iqLYtWQJhiGFyGGi5uHzu5uc0LzF3gTAfuzYBje8n4/ea8EwxZI3j6/oZ # h6h+z+yMDDZbesF6uHjHyQYuRhDIjegEYNu8c3T6Ttj+qkDxss5wRoPp2kChWTrZ # FQlXmVYwk/PJYczQCMxr7GJCkawCwO+k8IkRj3cCAwEAAaOCAzUwggMxMA4GA1Ud # DwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMI # MIIBvwYDVR0gBIIBtjCCAbIwggGhBglghkgBhv1sBwEwggGSMCgGCCsGAQUFBwIB # FhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMIIBZAYIKwYBBQUHAgIwggFW # HoIBUgBBAG4AeQAgAHUAcwBlACAAbwBmACAAdABoAGkAcwAgAEMAZQByAHQAaQBm # AGkAYwBhAHQAZQAgAGMAbwBuAHMAdABpAHQAdQB0AGUAcwAgAGEAYwBjAGUAcAB0 # AGEAbgBjAGUAIABvAGYAIAB0AGgAZQAgAEQAaQBnAGkAQwBlAHIAdAAgAEMAUAAv # AEMAUABTACAAYQBuAGQAIAB0AGgAZQAgAFIAZQBsAHkAaQBuAGcAIABQAGEAcgB0 # AHkAIABBAGcAcgBlAGUAbQBlAG4AdAAgAHcAaABpAGMAaAAgAGwAaQBtAGkAdAAg # AGwAaQBhAGIAaQBsAGkAdAB5ACAAYQBuAGQAIABhAHIAZQAgAGkAbgBjAG8AcgBw # AG8AcgBhAHQAZQBkACAAaABlAHIAZQBpAG4AIABiAHkAIAByAGUAZgBlAHIAZQBu # AGMAZQAuMAsGCWCGSAGG/WwDFTAfBgNVHSMEGDAWgBQVABIrE5iymQftHt+ivlcN # K2cCzTAdBgNVHQ4EFgQUYVpNJLZJMp1KKnkag0v0HonByn0wfQYDVR0fBHYwdDA4 # oDagNIYyaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElE # Q0EtMS5jcmwwOKA2oDSGMmh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2Vy # dEFzc3VyZWRJRENBLTEuY3JsMHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYY # aHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2Fj # ZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURDQS0xLmNydDANBgkq # hkiG9w0BAQUFAAOCAQEAnSV+GzNNsiaBXJuGziMgD4CH5Yj//7HUaiwx7ToXGXEX # zakbvFoWOQCd42yE5FpA+94GAYw3+puxnSR+/iCkV61bt5qwYCbqaVchXTQvH3Gw # g5QZBWs1kBCge5fH9j/n4hFBpr1i2fAnPTgdKG86Ugnw7HBi02JLsOBzppLA044x # 2C/jbRcTBu7kA7YUq/OPQ6dxnSHdFMoVXZJB2vkPgdGZdA0mxA5/G7X1oPHGdwYo # FenYk+VVFvC7Cqsc21xIJ2bIo4sKHOWV2q7ELlmgYd3a822iYemKC23sEhi991VU # QAOSK2vCUcIKSK+w1G7g9BQKOhvjjz3Kr2qNe9zYRDCCBs0wggW1oAMCAQICEAb9 # +QOWA63qAArrPye7uhswDQYJKoZIhvcNAQEFBQAwZTELMAkGA1UEBhMCVVMxFTAT # BgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEk # MCIGA1UEAxMbRGlnaUNlcnQgQXNzdXJlZCBJRCBSb290IENBMB4XDTA2MTExMDAw # MDAwMFoXDTIxMTExMDAwMDAwMFowYjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERp # Z2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMY # RGlnaUNlcnQgQXNzdXJlZCBJRCBDQS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A # MIIBCgKCAQEA6IItmfnKwkKVpYBzQHDSnlZUXKnE0kEGj8kz/E1FkVyBn+0snPgW # Wd+etSQVwpi5tHdJ3InECtqvy15r7a2wcTHrzzpADEZNk+yLejYIA6sMNP4YSYL+ # x8cxSIB8HqIPkg5QycaH6zY/2DDD/6b3+6LNb3Mj/qxWBZDwMiEWicZwiPkFl32j # x0PdAug7Pe2xQaPtP77blUjE7h6z8rwMK5nQxl0SQoHhg26Ccz8mSxSQrllmCsSN # vtLOBq6thG9IhJtPQLnxTPKvmPv2zkBdXPao8S+v7Iki8msYZbHBc63X8djPHgp0 # XEK4aH631XcKJ1Z8D2KkPzIUYJX9BwSiCQIDAQABo4IDejCCA3YwDgYDVR0PAQH/ # BAQDAgGGMDsGA1UdJQQ0MDIGCCsGAQUFBwMBBggrBgEFBQcDAgYIKwYBBQUHAwMG # CCsGAQUFBwMEBggrBgEFBQcDCDCCAdIGA1UdIASCAckwggHFMIIBtAYKYIZIAYb9 # bAABBDCCAaQwOgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cuZGlnaWNlcnQuY29tL3Nz # bC1jcHMtcmVwb3NpdG9yeS5odG0wggFkBggrBgEFBQcCAjCCAVYeggFSAEEAbgB5 # ACAAdQBzAGUAIABvAGYAIAB0AGgAaQBzACAAQwBlAHIAdABpAGYAaQBjAGEAdABl # ACAAYwBvAG4AcwB0AGkAdAB1AHQAZQBzACAAYQBjAGMAZQBwAHQAYQBuAGMAZQAg # AG8AZgAgAHQAaABlACAARABpAGcAaQBDAGUAcgB0ACAAQwBQAC8AQwBQAFMAIABh # AG4AZAAgAHQAaABlACAAUgBlAGwAeQBpAG4AZwAgAFAAYQByAHQAeQAgAEEAZwBy # AGUAZQBtAGUAbgB0ACAAdwBoAGkAYwBoACAAbABpAG0AaQB0ACAAbABpAGEAYgBp # AGwAaQB0AHkAIABhAG4AZAAgAGEAcgBlACAAaQBuAGMAbwByAHAAbwByAGEAdABl # AGQAIABoAGUAcgBlAGkAbgAgAGIAeQAgAHIAZQBmAGUAcgBlAG4AYwBlAC4wCwYJ # YIZIAYb9bAMVMBIGA1UdEwEB/wQIMAYBAf8CAQAweQYIKwYBBQUHAQEEbTBrMCQG # CCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQwYIKwYBBQUHMAKG # N2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJv # b3RDQS5jcnQwgYEGA1UdHwR6MHgwOqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0 # LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwOqA4oDaGNGh0dHA6Ly9j # cmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwHQYD # VR0OBBYEFBUAEisTmLKZB+0e36K+Vw0rZwLNMB8GA1UdIwQYMBaAFEXroq/0ksuC # MS1Ri6enIZ3zbcgPMA0GCSqGSIb3DQEBBQUAA4IBAQBGUD7Jtygkpzgdtlspr1LP # UukxR6tWXHvVDQtBs+/sdR90OPKyXGGinJXDUOSCuSPRujqGcq04eKx1XRcXNHJH # hZRW0eu7NoR3zCSl8wQZVann4+erYs37iy2QwsDStZS9Xk+xBdIOPRqpFFumhjFi # qKgz5Js5p8T1zh14dpQlc+Qqq8+cdkvtX8JLFuRLcEwAiR78xXm8TBJX/l/hHrwC # Xaj++wc4Tw3GXZG5D2dFzdaD7eeSDY2xaYxP+1ngIw/Sqq4AfO6cQg7Pkdcntxbu # D8O9fAqg7iwIVYUiuOsYGk38KiGtSTGDR5V3cdyxG0tLHBCcdxTBnU8vWpUIKRAm # MYIEOzCCBDcCAQEwgYYwcjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0 # IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTExMC8GA1UEAxMoRGlnaUNl # cnQgU0hBMiBBc3N1cmVkIElEIENvZGUgU2lnbmluZyBDQQIQAsbTxa4q6RSRmx0h # kVyicTAJBgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEKMAigAoAAoQKAADAZBgkq # hkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGC # NwIBFTAjBgkqhkiG9w0BCQQxFgQUZze/p5cErB+uNZKnw3LQJPRAcwswDQYJKoZI # hvcNAQEBBQAEggEAKZr/u2A8MAbIMjVRaPcogllqEFzSwiVH+U12YEOG1t3AQCbK # m95lQIyi5RLRVS/54wDIDJnDxWwII7M/SwjyZdPOsQY2f3j+J0ptfsNI9Ph/mmZT # Dy1FaOl8ASlWnlx1374pqch3DMlLHAhtkPuEsvbwtUILbrJIPYYw53duh8JNKMuE # eWen5QIneNUpVNQ5zR5jzRoNpfImDsvW7ezhvSdndspUa6C7suIEo0w/wAKSp5pb # qF82vzwceCjxv3sqlNGnMqqIO0GN5NU1KxSzGQgTmoiavn3KMakcZ+nVURAHJuox # fqpVQG2qWrALVrM3O5rqHziSp4qNZOFPvVVE4aGCAg8wggILBgkqhkiG9w0BCQYx # ggH8MIIB+AIBATB2MGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJ # bmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0 # IEFzc3VyZWQgSUQgQ0EtMQIQAwGaAjr/WLFr1tXq5hfwZjAJBgUrDgMCGgUAoF0w # GAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMjAwMjI0 # MDk0MzIyWjAjBgkqhkiG9w0BCQQxFgQU02Z7g+kHULNb2xxW4OfduP9GEw8wDQYJ # KoZIhvcNAQEBBQAEggEAb8ElsDJYyo1qPRkz/zm1ScFPhUiyA2F3yIAjlABSDA8X # za5xJdv5aqSznGZzIWC1CHjRJIuztrfQYdLhDD5W+ulfKl5oq0/ZAe2NpWUCshua # W0sJXiZZiJ/NvGjTQLUZgouwJExY6/Q36qPL4i6th5M9Yn/gvgYV7PnlKRDd4BO6 # WW3IfGzs7Xi+XBGtsiLFDzZqok87y1NrvuyY48QvZ2rPz07hv+xYnt2BNNwPrrLE # ySQSvVPpWh3dNvS7C3fxHZPsXx0GbMTFPYgblFR8xUPuSxOYNONEHa52+je11aHV # jv07vEanoV2H05V0kjGK+tzbgCyP7dHOj8Fp9Hbirw== # SIG # End signature block |