Я нашел приведенный ниже код Powershell, который отлично работает для редактирования нескольких документов Word, однако, когда документы защищены паролем, это не удается.
Я знаю пароль (который одинаков для всех файлов).
Я изменил строку 86 для передачи переменной пароля (запрошено пользователем
ранее в сценарии).
086 Функция processDoc ($ pass) {
Строка 87 затем использует переменную в том, что я понимаю (я могу ошибаться), чтобы иметь правильный формат .
087 $ doc = $ word.Documents.Open ($ _. FullName, $ null, $ false, $ null, $ pass, $ null, $ null, $ pass)
Я вызываю строку 96, передавая переменную пароля.
096 $ countr = processDoc ($ passwd)
Это не работает, и я не знаю почему. Я не программист по профессии, поэтому, скорее всего, делаю глупости.
Может кто-нибудь посоветовать, пожалуйста? С нетерпением жду снисходительных комментариев: -)
001 # Find and replace in multiple word docs
002 # Usage: Open in ISE, update the $folderPath, change the find/replace fields in the $textToReplace array, click the run button.
003
004 $folderPath = "C:\Users\tim.handy\Desktop\testchangecontentsword\STANDARD DATA - Copy\CHEMICAL\ANALYSIS\01 Pre-treatment incl strippers\*" # multi-folders: "C:\fso1*", "C:\fso2*"
005 $fileType = "*.doc" # *.doc will take all .doc* files, i.e .docx also
006 $passwd = Read-Host("Type in the password:")
007
008 $textToReplace = @{
009 # "TextToFind" = "TextToReplaceWith" and it's case sensitive.
010 "Bath 01800" = "yay"
011 }
012
013 $word = New-Object -ComObject Word.Application
014 $word.Visible = $false
015
016 #region Find/Replace parameters
017 $matchCase = $true
018 $matchWholeWord = $true
019 $matchWildcards = $false
020 $matchSoundsLike = $false
021 $matchAllWordForms = $false
022 $forward = $true
023 $findWrap = [Microsoft.Office.Interop.Word.WdFindWrap]::wdFindContinue
024 $format = $false
025 $replace = [Microsoft.Office.Interop.Word.WdReplace]::wdReplaceOne
026 #endregion
027
028 $countf = 0 #count files
029 $countr = 0 #count replacements per file
030 $counta = 0 #count all replacements
031
032 Function findAndReplace($objFind, $FindText, $ReplaceWith) {
033 #simple Find and Replace to execute on a Find object
034 #we let the function return (True/False) to count the replacements
035 $objFind.Execute($FindText, $matchCase, $matchWholeWord, $matchWildCards, $matchSoundsLike, $matchAllWordForms, $forward, $findWrap, $format, $ReplaceWith, $replace) #> $null
036 }
037
038 Function findAndReplaceAll($objFind, $FindText, $ReplaceWith) {
039 #make sure we replace all occurrences (while we find a match)
040 $count = 0
041 $count += findAndReplace $objFind $FindText $ReplaceWith
042 While ($objFind.Found) {
043 $count += findAndReplace $objFind $FindText $ReplaceWith
044 }
045 return $count
046 }
047
048 Function findAndReplaceMultiple($objFind, $lookupTable) {
049 #apply multiple Find and Replace on the same Find object
050 $count = 0
051 $lookupTable.GetEnumerator() | ForEach-Object {
052 $count += findAndReplaceAll $objFind $_.Key $_.Value
053 }
054 return $count
055 }
056
057 Function findAndReplaceWholeDoc($Document, $lookupTable) {
058 $count = 0
059 # Loop through each StoryRange
060 ForEach ($storyRge in $Document.StoryRanges) {
061 Do {
062 $count += findAndReplaceMultiple $storyRge.Find $lookupTable
063 #check for linked Ranges
064 $storyRge = $storyRge.NextStoryRange
065 } Until (!$storyRge) #null is False
066
067 }
068 #region Loop through Shapes within Headers and Footers
069 # https://msdn.microsoft.com/en-us/vba/word-vba/articles/shapes-object-word
070 # "The Count property for this collection in a document returns the number of items in the main story only.
071 # To count the shapes in all the headers and footers, use the Shapes collection with any HeaderFooter object."
072 # Hence the .Sections.Item(1).Headers.Item(1) which should be able to collect all Shapes, without the need
073 # for looping through each Section.
074 #endregion
075 $shapes = $Document.Sections.Item(1).Headers.Item(1).Shapes
076 If ($shapes.Count) {
077 #ForEach ($shape in $shapes | Where {$_.TextFrame.HasText -eq -1}) {
078 ForEach ($shape in $shapes | Where {[bool]$_.TextFrame.HasText}) {
079 #Write-Host $($shape.TextFrame.HasText)
080 $count += findAndReplaceMultiple $shape.TextFrame.TextRange.Find $lookupTable
081 }
082 }
083 return $count
084 }
085
086 Function processDoc ($pass) {
087 $doc = $word.Documents.Open($_.FullName, $null, $false, $null, $pass, $null, $null, $pass)
088 $count = findAndReplaceWholeDoc $doc $textToReplace
089 $doc.Close([ref]$true)
090 return $count
091 }
092
093 $sw = [Diagnostics.Stopwatch]::StartNew()
094 Get-ChildItem -Path $folderPath -Recurse -Filter $fileType | ForEach-Object {
095 Write-Host "Processing \`"$($_.Name)\`"..."
096 $countr = processDoc($passwd)
097 Write-Host "$countr replacements made."
098 $counta += $countr
099 $countf++
100 }
101 $sw.Stop()
102 $elapsed = $sw.Elapsed.toString()
103 Write-Host "`nDone. $countf files processed in $elapsed"
104 Write-Host "$counta replacements made in total."
105
106 $word.Quit()
107 $word = $null
108 [gc]::collect()
109 [gc]::WaitForPendingFinalizers()