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; } Default { WriteLog -Message ($localized.PluginUnsupportedSection -f $s.Type) -IsWarning; } } #end switch } #end foreach } #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 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)); $columnCount = $Table.Columns.Count; if ($Table.List) { $columnCount = 2; } 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')) { $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)); [ref] $rblHeader = $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 { $_.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.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, 'portrait'); $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 #endregion OutWord Private Functions # SIG # Begin signature block # MIIX1gYJKoZIhvcNAQcCoIIXxzCCF8MCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUv4VLacKHw7ktBlGoJWHuwDrh # pjqgghMJMIID7jCCA1egAwIBAgIQfpPr+3zGTlnqS5p31Ab8OzANBgkqhkiG9w0B # AQUFADCBizELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTEUMBIG # A1UEBxMLRHVyYmFudmlsbGUxDzANBgNVBAoTBlRoYXd0ZTEdMBsGA1UECxMUVGhh # d3RlIENlcnRpZmljYXRpb24xHzAdBgNVBAMTFlRoYXd0ZSBUaW1lc3RhbXBpbmcg # Q0EwHhcNMTIxMjIxMDAwMDAwWhcNMjAxMjMwMjM1OTU5WjBeMQswCQYDVQQGEwJV # UzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xMDAuBgNVBAMTJ1N5bWFu # dGVjIFRpbWUgU3RhbXBpbmcgU2VydmljZXMgQ0EgLSBHMjCCASIwDQYJKoZIhvcN # AQEBBQADggEPADCCAQoCggEBALGss0lUS5ccEgrYJXmRIlcqb9y4JsRDc2vCvy5Q # WvsUwnaOQwElQ7Sh4kX06Ld7w3TMIte0lAAC903tv7S3RCRrzV9FO9FEzkMScxeC # i2m0K8uZHqxyGyZNcR+xMd37UWECU6aq9UksBXhFpS+JzueZ5/6M4lc/PcaS3Er4 # ezPkeQr78HWIQZz/xQNRmarXbJ+TaYdlKYOFwmAUxMjJOxTawIHwHw103pIiq8r3 # +3R8J+b3Sht/p8OeLa6K6qbmqicWfWH3mHERvOJQoUvlXfrlDqcsn6plINPYlujI # fKVOSET/GeJEB5IL12iEgF1qeGRFzWBGflTBE3zFefHJwXECAwEAAaOB+jCB9zAd # BgNVHQ4EFgQUX5r1blzMzHSa1N197z/b7EyALt0wMgYIKwYBBQUHAQEEJjAkMCIG # CCsGAQUFBzABhhZodHRwOi8vb2NzcC50aGF3dGUuY29tMBIGA1UdEwEB/wQIMAYB # Af8CAQAwPwYDVR0fBDgwNjA0oDKgMIYuaHR0cDovL2NybC50aGF3dGUuY29tL1Ro # YXd0ZVRpbWVzdGFtcGluZ0NBLmNybDATBgNVHSUEDDAKBggrBgEFBQcDCDAOBgNV # HQ8BAf8EBAMCAQYwKAYDVR0RBCEwH6QdMBsxGTAXBgNVBAMTEFRpbWVTdGFtcC0y # MDQ4LTEwDQYJKoZIhvcNAQEFBQADgYEAAwmbj3nvf1kwqu9otfrjCR27T4IGXTdf # plKfFo3qHJIJRG71betYfDDo+WmNI3MLEm9Hqa45EfgqsZuwGsOO61mWAK3ODE2y # 0DGmCFwqevzieh1XTKhlGOl5QGIllm7HxzdqgyEIjkHq3dlXPx13SYcqFgZepjhq # IhKjURmDfrYwggSjMIIDi6ADAgECAhAOz/Q4yP6/NW4E2GqYGxpQMA0GCSqGSIb3 # DQEBBQUAMF4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3Jh # dGlvbjEwMC4GA1UEAxMnU3ltYW50ZWMgVGltZSBTdGFtcGluZyBTZXJ2aWNlcyBD # QSAtIEcyMB4XDTEyMTAxODAwMDAwMFoXDTIwMTIyOTIzNTk1OVowYjELMAkGA1UE # BhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMTQwMgYDVQQDEytT # eW1hbnRlYyBUaW1lIFN0YW1waW5nIFNlcnZpY2VzIFNpZ25lciAtIEc0MIIBIjAN # BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAomMLOUS4uyOnREm7Dv+h8GEKU5Ow # mNutLA9KxW7/hjxTVQ8VzgQ/K/2plpbZvmF5C1vJTIZ25eBDSyKV7sIrQ8Gf2Gi0 # jkBP7oU4uRHFI/JkWPAVMm9OV6GuiKQC1yoezUvh3WPVF4kyW7BemVqonShQDhfu # ltthO0VRHc8SVguSR/yrrvZmPUescHLnkudfzRC5xINklBm9JYDh6NIipdC6Anqh # d5NbZcPuF3S8QYYq3AhMjJKMkS2ed0QfaNaodHfbDlsyi1aLM73ZY8hJnTrFxeoz # C9Lxoxv0i77Zs1eLO94Ep3oisiSuLsdwxb5OgyYI+wu9qU+ZCOEQKHKqzQIDAQAB # o4IBVzCCAVMwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDAO # BgNVHQ8BAf8EBAMCB4AwcwYIKwYBBQUHAQEEZzBlMCoGCCsGAQUFBzABhh5odHRw # Oi8vdHMtb2NzcC53cy5zeW1hbnRlYy5jb20wNwYIKwYBBQUHMAKGK2h0dHA6Ly90 # cy1haWEud3Muc3ltYW50ZWMuY29tL3Rzcy1jYS1nMi5jZXIwPAYDVR0fBDUwMzAx # oC+gLYYraHR0cDovL3RzLWNybC53cy5zeW1hbnRlYy5jb20vdHNzLWNhLWcyLmNy # bDAoBgNVHREEITAfpB0wGzEZMBcGA1UEAxMQVGltZVN0YW1wLTIwNDgtMjAdBgNV # HQ4EFgQURsZpow5KFB7VTNpSYxc/Xja8DeYwHwYDVR0jBBgwFoAUX5r1blzMzHSa # 1N197z/b7EyALt0wDQYJKoZIhvcNAQEFBQADggEBAHg7tJEqAEzwj2IwN3ijhCcH # bxiy3iXcoNSUA6qGTiWfmkADHN3O43nLIWgG2rYytG2/9CwmYzPkSWRtDebDZw73 # BaQ1bHyJFsbpst+y6d0gxnEPzZV03LZc3r03H0N45ni1zSgEIKOq8UvEiCmRDoDR # EfzdXHZuT14ORUZBbg2w6jiasTraCXEQ/Bx5tIB7rGn0/Zy2DBYr8X9bCT2bW+IW # yhOBbQAuOA2oKY8s4bL0WqkBrxWcLC9JG9siu8P+eJRRw4axgohd8D20UaF5Mysu # e7ncIAkTcetqGVvP6KUwVyyJST+5z3/Jvz4iaGNTmr1pdKzFHTx/kuDDvBzYBHUw # ggUwMIIEGKADAgECAhAECRgbX9W7ZnVTQ7VvlVAIMA0GCSqGSIb3DQEBCwUAMGUx # CzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 # dy5kaWdpY2VydC5jb20xJDAiBgNVBAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9v # dCBDQTAeFw0xMzEwMjIxMjAwMDBaFw0yODEwMjIxMjAwMDBaMHIxCzAJBgNVBAYT # AlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2Vy # dC5jb20xMTAvBgNVBAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBDb2RlIFNp # Z25pbmcgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD407Mcfw4R # r2d3B9MLMUkZz9D7RZmxOttE9X/lqJ3bMtdx6nadBS63j/qSQ8Cl+YnUNxnXtqrw # nIal2CWsDnkoOn7p0WfTxvspJ8fTeyOU5JEjlpB3gvmhhCNmElQzUHSxKCa7JGnC # wlLyFGeKiUXULaGj6YgsIJWuHEqHCN8M9eJNYBi+qsSyrnAxZjNxPqxwoqvOf+l8 # y5Kh5TsxHM/q8grkV7tKtel05iv+bMt+dDk2DZDv5LVOpKnqagqrhPOsZ061xPeM # 0SAlI+sIZD5SlsHyDxL0xY4PwaLoLFH3c7y9hbFig3NBggfkOItqcyDQD2RzPJ6f # pjOp/RnfJZPRAgMBAAGjggHNMIIByTASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1Ud # DwEB/wQEAwIBhjATBgNVHSUEDDAKBggrBgEFBQcDAzB5BggrBgEFBQcBAQRtMGsw # JAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBDBggrBgEFBQcw # AoY3aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElE # Um9vdENBLmNydDCBgQYDVR0fBHoweDA6oDigNoY0aHR0cDovL2NybDQuZGlnaWNl # cnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNybDA6oDigNoY0aHR0cDov # L2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNybDBP # BgNVHSAESDBGMDgGCmCGSAGG/WwAAgQwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93 # d3cuZGlnaWNlcnQuY29tL0NQUzAKBghghkgBhv1sAzAdBgNVHQ4EFgQUWsS5eyoK # o6XqcQPAYPkt9mV1DlgwHwYDVR0jBBgwFoAUReuir/SSy4IxLVGLp6chnfNtyA8w # DQYJKoZIhvcNAQELBQADggEBAD7sDVoks/Mi0RXILHwlKXaoHV0cLToaxO8wYdd+ # C2D9wz0PxK+L/e8q3yBVN7Dh9tGSdQ9RtG6ljlriXiSBThCk7j9xjmMOE0ut119E # efM2FAaK95xGTlz/kLEbBw6RFfu6r7VRwo0kriTGxycqoSkoGjpxKAI8LpGjwCUR # 4pwUR6F6aGivm6dcIFzZcbEMj7uo+MUSaJ/PQMtARKUT8OZkDCUIQjKyNookAv4v # cn4c10lFluhZHen6dGRrsutmQ9qzsIzV6Q3d9gEgzpkxYz0IGhizgZtPxpMQBvwH # gfqL2vmCSfdibqFT+hKUGIUukpHqaGxEMrJmoecYpJpkUe8wggU4MIIEIKADAgEC # AhAPxQCJrE9ObGzkCRS7EwyyMA0GCSqGSIb3DQEBCwUAMHIxCzAJBgNVBAYTAlVT # MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j # b20xMTAvBgNVBAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBDb2RlIFNpZ25p # bmcgQ0EwHhcNMTcwNTI2MDAwMDAwWhcNMTkwOTI3MTIwMDAwWjB1MQswCQYDVQQG # EwJHQjETMBEGA1UECBMKR2Fyc2luZ3RvbjEPMA0GA1UEBxMGT3hmb3JkMR8wHQYD # VQQKExZWaXJ0dWFsIEVuZ2luZSBMaW1pdGVkMR8wHQYDVQQDExZWaXJ0dWFsIEVu # Z2luZSBMaW1pdGVkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnB1O # DV2jw/aMIUWnD9f9RCbAoiJ8LQcznYo42P22YEi6g7QY+kKmAzGgEhbsE4UVuGWS # el4y6FxGWq51SK5P/gqgZgzyP8FkIUzLxsCrtx9OBnsPPeL+/An5CpcsKsl2lCSz # NMwcz16hjcE0vCLio1NOcwvfO65qdNT2gRIEnIYhRX88dG3V30BH2aKWG5X9t1IW # RmozjZ8I7iLEoWFJWQSuICSGyvyiPqnXF3nxdroE8O4fc1U90x5qefX0RlwKeq47 # UFuI0Y/59pB3/jss5BYvAXp3g+6EKlDwgW1a/MLVsLQbdzlALFUv5YxEqkXA8IEM # xpwgBjm117SmyZ98QQIDAQABo4IBxTCCAcEwHwYDVR0jBBgwFoAUWsS5eyoKo6Xq # cQPAYPkt9mV1DlgwHQYDVR0OBBYEFL5NkOqMm0S8AyuXI1EZIdoK9DD/MA4GA1Ud # DwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzB3BgNVHR8EcDBuMDWgM6Ax # hi9odHRwOi8vY3JsMy5kaWdpY2VydC5jb20vc2hhMi1hc3N1cmVkLWNzLWcxLmNy # bDA1oDOgMYYvaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NoYTItYXNzdXJlZC1j # cy1nMS5jcmwwTAYDVR0gBEUwQzA3BglghkgBhv1sAwEwKjAoBggrBgEFBQcCARYc # aHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAIBgZngQwBBAEwgYQGCCsGAQUF # BwEBBHgwdjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tME4G # CCsGAQUFBzAChkJodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRT # SEEyQXNzdXJlZElEQ29kZVNpZ25pbmdDQS5jcnQwDAYDVR0TAQH/BAIwADANBgkq # hkiG9w0BAQsFAAOCAQEAQC8qzSz1bIoEqbjDx3VtYDjtUjuFEVDFYi9+vREl6jM+ # iqOiNiwCXUkbxGTuDrWW9I1YOn8a7SCCYapZ+T0G3RMa+rQHXFYKbYTmXC3C41Cd # MQzZn4wTuGRNQLTgNSuclwMnNmFVe7K5S/0Dv+GaLSKuRLAxpcPxeTtmRZIIBXF7 # wwRS0+V28jB9VyeSOdqsPIFYf5GSfu7KcIhmNQ/DUroulaS5JIrPUhwkf1LZMm0B # /0adpaPbFy95M1emij96rrgy2hX8N/FrWBh13/81V6NO3b8mhCfjqb632dG4EUTi # FXDvqP2hpWw0nO/pFZsMsEK88eiV93XDDEG/MjAApzGCBDcwggQzAgEBMIGGMHIx # CzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 # dy5kaWdpY2VydC5jb20xMTAvBgNVBAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJ # RCBDb2RlIFNpZ25pbmcgQ0ECEA/FAImsT05sbOQJFLsTDLIwCQYFKw4DAhoFAKB4 # MBgGCisGAQQBgjcCAQwxCjAIoAKAAKECgAAwGQYJKoZIhvcNAQkDMQwGCisGAQQB # gjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwIwYJKoZIhvcNAQkE # MRYEFGHhnxUREDL7GNFo1TIjnsCKXM9XMA0GCSqGSIb3DQEBAQUABIIBADRY2Lr4 # Tz1hf72ZIlp6RWxJ9duTLZXzr7ZMbAWG7jywNsjqtncDC3X06T7/stqxk1OiaxxO # Boh7BKaGvE8g1tzEUO2+dRABGIcsDKnFeJJhFYI6/Qr2RUMkCA+auP+Z2VeILb8z # 0mdCRAoG46vXg/UufMqNssYHRmRIn6S1g46qzZzM2widvpDzzJBCk7QC11GFcGek # l8zidAV9rGpzpDtCGL3C9+5wO/iv7ksfWS02ywM+WUTrtwNtj51vQzheNAXkDX7a # rMHB1a0EdwBcGc8/N3LZDHh3zixYFrxsjzgasmJvCmavK9rKZadFi0Jy+Atxyb4I # KkaL3LQW6vzEryChggILMIICBwYJKoZIhvcNAQkGMYIB+DCCAfQCAQEwcjBeMQsw # CQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xMDAuBgNV # BAMTJ1N5bWFudGVjIFRpbWUgU3RhbXBpbmcgU2VydmljZXMgQ0EgLSBHMgIQDs/0 # OMj+vzVuBNhqmBsaUDAJBgUrDgMCGgUAoF0wGAYJKoZIhvcNAQkDMQsGCSqGSIb3 # DQEHATAcBgkqhkiG9w0BCQUxDxcNMTgwNDEzMTQzODUwWjAjBgkqhkiG9w0BCQQx # FgQU+7hOonlS4zGpouxxFr1ir2hzfGswDQYJKoZIhvcNAQEBBQAEggEAPiHf9/sW # WaE6gDQZ3Y62K3h+Pud0kJq/Ww5xzFT+h7Lxq7RtTTlx0aeogloWkFnKX9mDZDKc # TaQv5Xr5+AOfCfRhHTMwAml1wcvvDqqKpgklw0l0IcSZCTOLiGnouT+OpgnLFUY9 # NXGYbkurnN5m1RM+yoTZBlhT8RHfhuCbiN2uxiBk64eLWUOmHI22Av5JkdazO9CK # 7UQUmWyP74xhOcxmaj8iphYfbzyDB5I6ACYLN7HGo/pLu23jDfJizbn+3/7rMzbq # OPRu9gdt+lRfMSOEn89mBz5N5tmmxwETA+c8CBxGTa6ts8TlO0HFt4dVYxipq6mr # KGuvFMjgVM+nWQ== # SIG # End signature block |