将文本文件作为对象嵌入到 Ms Word 2010 中
Embed a text file as an object in Ms Word 2010
我正在构建脚本以使用 PowerShell 编写 word 文档(Windows 7、PS4、.Net 4、Office 2010。
该脚本有效,但它将文本嵌入到文档的顶部。我需要能够像第 2 页那样指定确切位置。
这是我的最新消息:
# Opens an MsWord Doc, does a Search-and-Replace and embeds a text file as an object
# To make this work you need in the same folder as this script:
# -A 2-page MsWord file called "Search_and_replace_Target_Template.doc" with:
# -the string <package-name> on page ONE
# -the string <TextFile-Placeholder> on page TWO
# -A textfile called "TextFile.txt"
#
#The script will:
# -replace <package-name> with something on page one
# -embed the text file <package-name> at the top of page one (but I want it to replace <TextFile-Placeholder> on page 2)
#
# CAVEAT: Using MsWord 2010
[String]$MsWordDocTemplateName = "Search_and_replace_Target_Template.doc"
[String]$TextFileName = "TextFile.txt"
[Int]$wdReplaceAll = 2
[Int]$wdFindContinue = 1 #The find operation continues when the beginning or end of the search range is reached.
[Bool]$MatchCase = $False
[Bool]$MatchWholeWord = $true
[Bool]$MatchWildcards = $False
[Bool]$MatchSoundsLike = $False
[Bool]$MatchAllWordForms = $False
[Bool]$Forward = $True
[Int]$Wrap = $wdFindContinue #The find operation continues when the beginning or end of the search range is reached.
[Bool]$Format = $False
[Int]$wdReplaceNone = 0
$objWord = New-Object -ComObject Word.Application
$objWord.Visible = $true #Makes the MsWord
[String]$ScriptDirectory = [System.IO.Path]::GetDirectoryName($myInvocation.MyCommand.path)
[String]$WordDocTemplatePath = "$ScriptDirectory$MsWordDocTemplateName"
[String]$TextFilePath = "$ScriptDirectory$TextFileName"
[String]$SaveAsPathNew = Join-Path -Path $ScriptDirectory -ChildPath "${MsWordDocTemplateName}-NEW.doc"
#Open Template with MSWord
Try {
$objDoc = $objWord.Documents.Open($WordDocTemplatePath)
} Catch {
[string]$mainErrorMessage = "$($_.Exception.Message) $($_.ScriptStackTrace) $($_.Exception.InnerException)"
Write-Host $mainErrorMessage -ForegroundColor Red
Start-Sleep -Seconds 7
$objDoc.Close()
$objWord.Quit()
}
$objSelection = $objWord.Selection
$objSelection.Find.Forward = 'TRUE'
$objSelection.Find.MatchWholeWord = 'TRUE'
#Replace <package-name>
[String]$FindText = "<package-name>"
[String]$ReplaceWith = "PackageName_v1"
write-host "replacing [$FindText] :" -NoNewline
$objSelection.Find.Execute($FindText,$MatchCase,$MatchWholeWord,$MatchWildcards,$MatchSoundsLike,$MatchAllWordForms,$Forward,$Wrap,$Format,$ReplaceWith,$wdReplaceAll)
#Embed the text file as an object
[System.IO.FileSystemInfo]$TextFileObj = Get-item $TextFilePath
If ( $(Try {Test-Path $($TextFileObj.FullName).trim() } Catch { $false }) ) {
write-host "Embedding [$TextFileName] :" -NoNewline
[String]$FindText = "<TextFile-Placeholder>"
[String]$ReplaceWith = ""
# $objSelection.Find.Execute($FindText,$MatchCase,$MatchWholeWord,$MatchWildcards,$MatchSoundsLike,$MatchAllWordForms,$Forward,$Wrap,$Format,$ReplaceWith,$wdReplaceAll)
#Need code to create a RANGE to the position of <TextFile-Placeholder>
#Embed file into word doc as an object
#$result = $objSelection.InlineShapes.AddOLEObject($null,$TextFileObj.FullName,$false,$true)
$result = $objSelection.Range[0].InlineShapes.AddOLEObject($null,$TextFileObj.FullName,$false,$true) #works too but does the same
Write-host "Success"
} Else {
Write-Host "[$TextFilePath] does not exist!" -ForegroundColor Red
Start-Sleep -Seconds 5
}
Write-Host "Saving updated word doc to [${MsWordDocTemplateName}-NEW.doc] ***"
Start-Sleep -Seconds 2
#List of formats
$AllSaveFormat = [Enum]::GetNames([microsoft.office.interop.word.WdSaveFormat])
$SaveFormat = $AllSaveFormat
$objDoc.SaveAs([ref]$SaveAsPathNew,[ref]$SaveFormat::wdFormatDocument) #Overwrite if exists
$objDoc.Close()
$objWord.Quit()
$null = [System.Runtime.InteropServices.Marshal]::ReleaseComObject([System.__ComObject]$objWord)
[gc]::Collect()
[gc]::WaitForPendingFinalizers()
Remove-Variable objWord
如果您有办法在 Word 2016 中执行此操作,我也会采用它,因为稍后我必须为 office 2016 重做所有操作。
更新:看起来解决方案是在 所在的位置创建 "Range"。默认情况下,您似乎有一个代表整个文档的范围[0]。
我最接近这样做的是:
$MyRange = $objSelection.Range[Start:= 0, End:= 7]
但这不是 PowerShell 的语法,它只处理绝对字符位置,而不处理字符串搜索的结果。
如果我可以创建第二个范围,也许这可行:
$objSelection.Range[1].InlineShapes.AddOLEObject($null,$TextFileObj.FullName,$false,$true)
我无法为您编写 powershell 脚本,但我可以描述您的需求。您确实 on-track 有 Range
想法。要获取整个 Word 文档的范围:
$MyRange = $objDoc.Content
请注意,您可以根据需要自由声明和使用任意数量的 Range 对象。范围不像Selection
那样有限制,只能有一个。只要您不再需要原来的 Range,就可以继续对它执行 Find。如果您确实再次需要原始 Range,则声明并实例化第二个,如上所述实例化它,或者为了使用原始 Range 作为起点:
$MyRange2 = $MyRange.Duplicate
然后在范围上使用 Find
。请注意,当 Find
成功时,Range
的内容是找到的术语,这会将 "focus" 放在正确的页面上。 (但是不会移动选择!)
$MyRange.Find.Execute($FindText,$MatchCase,$MatchWholeWord,$MatchWildcards,$MatchSoundsLike,$MatchAllWordForms,$Forward,$Wrap,$Format,$ReplaceWith,$wdReplaceAll)
如果你想测试查找是否成功 Execute
方法 returns 一个布尔值(如果查找成功则为真)。
尽管我不确定 OLEObject 是否是插入文本文件的最佳方法,但可以使用类似下面的方法来插入文件。我宁愿认为 InsertFile
会更合适。 OLEObject 需要在 Windows 中注册的支持编辑文本文件的 OLE 服务器;它会更慢,并在将尝试更新的文档中放置一个域代码...
$result =$MyRange.InlineShapes.AddOLEObject($null,$TextFileObj.FullName,$false,$true)
我正在构建脚本以使用 PowerShell 编写 word 文档(Windows 7、PS4、.Net 4、Office 2010。
该脚本有效,但它将文本嵌入到文档的顶部。我需要能够像第 2 页那样指定确切位置。
这是我的最新消息:
# Opens an MsWord Doc, does a Search-and-Replace and embeds a text file as an object
# To make this work you need in the same folder as this script:
# -A 2-page MsWord file called "Search_and_replace_Target_Template.doc" with:
# -the string <package-name> on page ONE
# -the string <TextFile-Placeholder> on page TWO
# -A textfile called "TextFile.txt"
#
#The script will:
# -replace <package-name> with something on page one
# -embed the text file <package-name> at the top of page one (but I want it to replace <TextFile-Placeholder> on page 2)
#
# CAVEAT: Using MsWord 2010
[String]$MsWordDocTemplateName = "Search_and_replace_Target_Template.doc"
[String]$TextFileName = "TextFile.txt"
[Int]$wdReplaceAll = 2
[Int]$wdFindContinue = 1 #The find operation continues when the beginning or end of the search range is reached.
[Bool]$MatchCase = $False
[Bool]$MatchWholeWord = $true
[Bool]$MatchWildcards = $False
[Bool]$MatchSoundsLike = $False
[Bool]$MatchAllWordForms = $False
[Bool]$Forward = $True
[Int]$Wrap = $wdFindContinue #The find operation continues when the beginning or end of the search range is reached.
[Bool]$Format = $False
[Int]$wdReplaceNone = 0
$objWord = New-Object -ComObject Word.Application
$objWord.Visible = $true #Makes the MsWord
[String]$ScriptDirectory = [System.IO.Path]::GetDirectoryName($myInvocation.MyCommand.path)
[String]$WordDocTemplatePath = "$ScriptDirectory$MsWordDocTemplateName"
[String]$TextFilePath = "$ScriptDirectory$TextFileName"
[String]$SaveAsPathNew = Join-Path -Path $ScriptDirectory -ChildPath "${MsWordDocTemplateName}-NEW.doc"
#Open Template with MSWord
Try {
$objDoc = $objWord.Documents.Open($WordDocTemplatePath)
} Catch {
[string]$mainErrorMessage = "$($_.Exception.Message) $($_.ScriptStackTrace) $($_.Exception.InnerException)"
Write-Host $mainErrorMessage -ForegroundColor Red
Start-Sleep -Seconds 7
$objDoc.Close()
$objWord.Quit()
}
$objSelection = $objWord.Selection
$objSelection.Find.Forward = 'TRUE'
$objSelection.Find.MatchWholeWord = 'TRUE'
#Replace <package-name>
[String]$FindText = "<package-name>"
[String]$ReplaceWith = "PackageName_v1"
write-host "replacing [$FindText] :" -NoNewline
$objSelection.Find.Execute($FindText,$MatchCase,$MatchWholeWord,$MatchWildcards,$MatchSoundsLike,$MatchAllWordForms,$Forward,$Wrap,$Format,$ReplaceWith,$wdReplaceAll)
#Embed the text file as an object
[System.IO.FileSystemInfo]$TextFileObj = Get-item $TextFilePath
If ( $(Try {Test-Path $($TextFileObj.FullName).trim() } Catch { $false }) ) {
write-host "Embedding [$TextFileName] :" -NoNewline
[String]$FindText = "<TextFile-Placeholder>"
[String]$ReplaceWith = ""
# $objSelection.Find.Execute($FindText,$MatchCase,$MatchWholeWord,$MatchWildcards,$MatchSoundsLike,$MatchAllWordForms,$Forward,$Wrap,$Format,$ReplaceWith,$wdReplaceAll)
#Need code to create a RANGE to the position of <TextFile-Placeholder>
#Embed file into word doc as an object
#$result = $objSelection.InlineShapes.AddOLEObject($null,$TextFileObj.FullName,$false,$true)
$result = $objSelection.Range[0].InlineShapes.AddOLEObject($null,$TextFileObj.FullName,$false,$true) #works too but does the same
Write-host "Success"
} Else {
Write-Host "[$TextFilePath] does not exist!" -ForegroundColor Red
Start-Sleep -Seconds 5
}
Write-Host "Saving updated word doc to [${MsWordDocTemplateName}-NEW.doc] ***"
Start-Sleep -Seconds 2
#List of formats
$AllSaveFormat = [Enum]::GetNames([microsoft.office.interop.word.WdSaveFormat])
$SaveFormat = $AllSaveFormat
$objDoc.SaveAs([ref]$SaveAsPathNew,[ref]$SaveFormat::wdFormatDocument) #Overwrite if exists
$objDoc.Close()
$objWord.Quit()
$null = [System.Runtime.InteropServices.Marshal]::ReleaseComObject([System.__ComObject]$objWord)
[gc]::Collect()
[gc]::WaitForPendingFinalizers()
Remove-Variable objWord
如果您有办法在 Word 2016 中执行此操作,我也会采用它,因为稍后我必须为 office 2016 重做所有操作。
更新:看起来解决方案是在 所在的位置创建 "Range"。默认情况下,您似乎有一个代表整个文档的范围[0]。
我最接近这样做的是:
$MyRange = $objSelection.Range[Start:= 0, End:= 7]
但这不是 PowerShell 的语法,它只处理绝对字符位置,而不处理字符串搜索的结果。
如果我可以创建第二个范围,也许这可行:
$objSelection.Range[1].InlineShapes.AddOLEObject($null,$TextFileObj.FullName,$false,$true)
我无法为您编写 powershell 脚本,但我可以描述您的需求。您确实 on-track 有 Range
想法。要获取整个 Word 文档的范围:
$MyRange = $objDoc.Content
请注意,您可以根据需要自由声明和使用任意数量的 Range 对象。范围不像Selection
那样有限制,只能有一个。只要您不再需要原来的 Range,就可以继续对它执行 Find。如果您确实再次需要原始 Range,则声明并实例化第二个,如上所述实例化它,或者为了使用原始 Range 作为起点:
$MyRange2 = $MyRange.Duplicate
然后在范围上使用 Find
。请注意,当 Find
成功时,Range
的内容是找到的术语,这会将 "focus" 放在正确的页面上。 (但是不会移动选择!)
$MyRange.Find.Execute($FindText,$MatchCase,$MatchWholeWord,$MatchWildcards,$MatchSoundsLike,$MatchAllWordForms,$Forward,$Wrap,$Format,$ReplaceWith,$wdReplaceAll)
如果你想测试查找是否成功 Execute
方法 returns 一个布尔值(如果查找成功则为真)。
尽管我不确定 OLEObject 是否是插入文本文件的最佳方法,但可以使用类似下面的方法来插入文件。我宁愿认为 InsertFile
会更合适。 OLEObject 需要在 Windows 中注册的支持编辑文本文件的 OLE 服务器;它会更慢,并在将尝试更新的文档中放置一个域代码...
$result =$MyRange.InlineShapes.AddOLEObject($null,$TextFileObj.FullName,$false,$true)