# encoding: ascii
# api: powershell
# title: HighlightWord
# description: Search a Word DocX document and highlight each instance of a pattern.
# version: 0.1
# author: Joel Bennett
# license: CC0
# x-poshcode-id: 5731
# x-archived: 2015-02-15T05:50:59
# x-published: 2015-02-07T08:38:00
#
# Requires the OpenXML SDK
#
[CmdletBinding()]
param(
    [Parameter(Mandatory)]
    $FilePath,
    [Parameter(Mandatory)]
    $Pattern,
    $Color = "Yellow"
)

Add-Type -AssemblyName "DocumentFormat.OpenXml, Version=2.5.5631.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"

$Color = [DocumentFormat.OpenXml.Wordprocessing.HighlightColorValues]$Color


$Doc = [DocumentFormat.OpenXml.Packaging.WordprocessingDocument]::Open( $FilePath, $true )
$Body = $Doc.MainDocumentPart.Document.Body
# $Candidates = $Body.Descendants() | ? { $_ -is [DocumentFormat.OpenXml.Wordprocessing.Run] -and $_.InnerText -match $Pattern }

$preserveSpace = New-Object documentformat.openxml.openxmlattribute "xml", "space","http://www.w3.org/XML/1998/namespace","preserve"
# $preserveSpace = New-Object documentformat.openxml.openxmlattribute "space","xml","preserve"

foreach($Node in $Body.Descendants()){
    if($Node -is [DocumentFormat.OpenXml.Wordprocessing.Run] -and $Node.Text -match $Pattern) {
        $Parent = $Node.Parent
        $Previous = $Node

        $Blocks = $Node.Text -split $Pattern
        for($t=0;$t -lt $Blocks.Count;$t++) {
            $run = $Node.CloneNode($true)

            foreach($text in $run.Descendants()) { 
                if($text -is [DocumentFormat.OpenXml.Wordprocessing.Text]) {
                    $text.Text = $Blocks[$t] 
                    $text.SetAttribute( $preserveSpace )
                    $text.RemoveNamespaceDeclaration("xml")
                }
            }

            $Parent.InsertAfter($run, $Previous)
            $Previous = $Run

            if(($t + 1) -lt $Blocks.Count) {
                $Run = $Node.CloneNode($true)
                foreach($text in $run.Descendants()) { 
                    if($text -is [DocumentFormat.OpenXml.Wordprocessing.Text]) {
                        $text.Text = $Pattern
                    }
                }

                $hilite = New-Object DocumentFormat.OpenXml.Wordprocessing.Highlight
                $hilite.Val = $Color
                $RunProps = New-Object DocumentFormat.OpenXml.Wordprocessing.RunProperties
                $RunProps.Append($hilite)
                $Run.InsertAt($RunProps, 0)
                $Parent.InsertAfter($Run, $Previous)
                $Previous = $Run
            }
        }
        $Parent.RemoveChild($Node)
        Write-Verbose $Parent.OuterXml
    }
}

$Doc.Close()
