【问题标题】:How to change custom properties for many Word documents如何更改许多 Word 文档的自定义属性
【发布时间】:2018-03-28 23:13:42
【问题描述】:

我在这里找到了开始使用脚本的非常有用的信息:

http://blogs.technet.com/b/heyscriptingguy/archive/2010/04/06/hey-scripting-guy-how-can-i-add-custom-properties-to-a-microsoft-word-document.aspx

但我不能对多个 Word 文档执行相同的操作 - 例如同一文件夹中的 3 或 4 个 word 文档。 我尝试了命令ForEach,但总是收到错误消息。

有人可以帮我修改以下脚本以考虑路径文件夹中的所有word文档吗?

$path = "C:\fso\Test.docx"
$application = New-Object -ComObject word.application
$application.Visible = $false
$document = $application.documents.open($path)
$binding = "System.Reflection.BindingFlags" -as [type]

$customProperties = $document.CustomDocumentProperties
$typeCustomProperties = $customProperties.GetType()

$CustomProperty = "Client"
$Value = "My_WayCool_Client"
[array]$arrayArgs = $CustomProperty,$false, 4, $Value

Try {
  $typeCustomProperties.InvokeMember(`
    "add", $binding::InvokeMethod,$null,$customProperties,$arrayArgs) |
    out-null
} Catch [system.exception] {
  $propertyObject = $typeCustomProperties.InvokeMember(`
    "Item", $binding::GetProperty, $null, $customProperties, $CustomProperty)
  $typeCustomProperties.InvokeMember(`
    "Delete", $binding::InvokeMethod, $null, $propertyObject, $null)
  $typeCustomProperties.InvokeMember(`
    "add", $binding::InvokeMethod, $null, $customProperties, $arrayArgs) |
    Out-Null
}

$document.Saved = $false
$document.save()
$application.quit()
$application = $null
[gc]::collect()
[gc]::WaitForPendingFinalizers()

我也试过了

Get-ChildItem -path $path | Where-Object { $_.Name -like '*.docx' }

ForEach cmdlet。

【问题讨论】:

  • 您尝试将ForEach-Object 循环放在哪里以及错误消息是什么。我会把它放在$application.Visible = $false 这一行之后,并在$application.quit() 之前关闭它很可能

标签: powershell ms-word


【解决方案1】:

正如马特建议的那样,我会在应用程序打开后放入一个 ForEach 循环。我还将在 ForEach 循环中添加关闭当前文档。比如:

$path = "C:\fso\*.docx"
$application = New-Object -ComObject word.application
$application.Visible = $false
ForEach($File in (GCI $path|Select -Expand FullName)){
    $document = $application.documents.open($file)
    $binding = "System.Reflection.BindingFlags" -as [type]

    <Other Commands>

    $document.Saved = $false
    $document.save()
    $document.Close()
}
$application.quit()
$application = $null
[gc]::collect()
[gc]::WaitForPendingFinalizers()

【讨论】:

    【解决方案2】:

    我是这样做的:

    #Set the PATH variable to the location where you saved the script and CSV file
    $path = "c:\temp\PowerShell Scripts\"
    
    #Set the DOC variable to the location of the document you want to update
    $doc = "c:\temp\test.docx"
    $application = New-Object -ComObject word.application
    $application.Visible = $false
    $document = $application.documents.open($doc)
    $binding = "System.Reflection.BindingFlags" -as [type]
    
    $customProperties = $document.CustomDocumentProperties
    $typeCustomProperties = $customProperties.GetType()
    
    $CustomPropertiesWorklist = Import-Csv $path\args.csv
    if($CustomPropertiesWorklist.Count){
    for($i = 0; $i -lt $CustomPropertiesWorklist.Count; $i++)
        {
        $CustomProperty = $CustomPropertiesWorklist[$i].CP
        $msoPropertyType = $CustomPropertiesWorklist[$i].Type
        $Value = $CustomPropertiesWorklist[$i].Value
    
    [array]$arrayArgs = $CustomProperty,$false,$msoPropertyType,$Value
    
    Try
     {
      $typeCustomProperties.InvokeMember(`
        "add", $binding::InvokeMethod,$null,$customProperties,$arrayArgs) |
        out-null
     }
    Catch [system.exception]
     {
      $propertyObject = $typeCustomProperties.InvokeMember(`
        "Item", $binding::GetProperty,$null,$customProperties,$CustomProperty)
      $typeCustomProperties.InvokeMember(`
        "Delete", $binding::InvokeMethod,$null,$propertyObject,$null)
      $typeCustomProperties.InvokeMember(`
        "add", $binding::InvokeMethod,$null,$customProperties,$arrayArgs) |
        Out-Null
     }
     }
     }
     else
    
     {
        $CustomProperty = $CustomPropertiesWorklist.CP
        $msoPropertyType = $CustomPropertiesWorklist.Type
        $Value = $CustomPropertiesWorklist.Value
    
    [array]$arrayArgs = $CustomProperty,$false,$msoPropertyType,$Value
    
    Try
     {
      $typeCustomProperties.InvokeMember(`
        "add", $binding::InvokeMethod,$null,$customProperties,$arrayArgs) |
        out-null
     }
    Catch [system.exception]
     {
      $propertyObject = $typeCustomProperties.InvokeMember(`
        "Item", $binding::GetProperty,$null,$customProperties,$CustomProperty)
      $typeCustomProperties.InvokeMember(`
        "Delete", $binding::InvokeMethod,$null,$propertyObject,$null)
      $typeCustomProperties.InvokeMember(`
        "add", $binding::InvokeMethod,$null,$customProperties,$arrayArgs) |
        Out-Null
     }
     }
    
    
    
    $document.Saved = $false
    $document.save()
    $application.quit()
    $application = $null
    [gc]::collect()
    [gc]::WaitForPendingFinalizers()
    

    【讨论】:

      【解决方案3】:

      我改编并结合了我在这个线程中找到的一些解决方案和其他解决方案,以创建我认为这样的脚本应该如何运行,即更改多个 word 文档中的多个自定义属性并自动更新文档中的实际字段.希望这对其他人也有帮助!

      您只需要更改将要添加/更新的属性列表并将路径设置为您的 .docx 文件所在的文件夹,其余的应该由它处理。

      #Comment out (or remove, you barbarian) the properties that do not need updating
      $propertiesToUpdate = @{
          "Product Name" = "Amazing Product"
          "Project Name" = "Best Project"
          "Revision (Record)" = "01.00"
          "Approved By (Record)" = "Me"
          "Date Approved (Record)" = "10.03.2016"
      }
      
      #Update the path to the documents to update:
      $path = "C:\path\*.docx"
      
      Write-Host -ForegroundColor Cyan "Loading Application..."
      $application = New-Object -ComObject word.application
      $application.Visible = $false
      
      function AddOrUpdateCustomProperty ($CustomPropertyName, $CustomPropertyValue, $DocumentToChange)
      {
          $customProperties = $DocumentToChange.CustomDocumentProperties
          $typeCustomProperties = $customProperties.GetType()
          $binding = "System.Reflection.BindingFlags" -as [type]
          [array]$arrayArgs = $CustomPropertyName,$false, 4, $CustomPropertyValue
          Try 
          {
              $typeCustomProperties.InvokeMember("add", $binding::InvokeMethod,$null,$customProperties,$arrayArgs) | out-null
          } 
          Catch [system.exception] 
          {
              $propertyObject = $typeCustomProperties.InvokeMember("Item", $binding::GetProperty, $null, $customProperties, $CustomPropertyName)
              $typeCustomProperties.InvokeMember("Delete", $binding::InvokeMethod, $null, $propertyObject, $null)
              $typeCustomProperties.InvokeMember("add", $binding::InvokeMethod, $null, $customProperties, $arrayArgs) | Out-Null
          }
          Write-Host -ForegroundColor Green "Success! Custom Property:" $CustomPropertyName "set to value:" $CustomPropertyValue
      }
      
      ForEach($File in (GCI $path|Select -Expand FullName))
      {
          Write-Host -ForegroundColor Cyan "Opening Document..." $File
          $document = $application.documents.open($File)
      
          ForEach($property in $propertiesToUpdate.GetEnumerator())
          {
              AddOrUpdateCustomProperty $($property.Name) $($property.Value) $document
          }
      
          Write-Host -ForegroundColor Cyan "Updating document fields."
          $document.Fields.Update() | Out-Null
      
          Write-Host -ForegroundColor Cyan "Saving document."
          $document.Saved = $false
          $document.save()
          $document.close()
      }
      
      $application.quit()
      $application = $null
      [gc]::collect()
      [gc]::WaitForPendingFinalizers()
      
      Write-Host -ForegroundColor Green "Done!"
      

      【讨论】:

        【解决方案4】:

        我无法让上述工作。始终 object.GetType() 无法检索任何内容,从而导致错误。这就是我要为 BuiltIn 属性工作的内容;这同样适用于自定义属性:

        #Properties to update (BuiltIn)
        $propertyUpdates = @{
            "Company" = "Company"
            "Manager" = "Manager"
        }
        
        #Path to the documents to update:
        $path = "C:\FilesToUpdate\*.docx"
        
        Write-Host -ForegroundColor Cyan "Loading Application..."
        $app = New-Object -ComObject Word.Application
        $app.Visible = $false
        
        ForEach($file in (GCI $path|Select -Expand FullName))
        {
            Write-Host -ForegroundColor Cyan "Opening document: " $file
            $doc = $app.Documents.Open($file)
            $binding = "System.Reflection.BindingFlags" -as [type]
        
            Write-Host -ForegroundColor Cyan "Updating document properties..."
            ForEach($p in $propertyUpdates.GetEnumerator())
            {
                Try {
                    $props = $doc.BuiltInDocumentProperties
                    $prop = [System.__ComObject].InvokeMember("Item", $binding::GetProperty, $null, $props, $p.Name)
                    [System.__ComObject].InvokeMember("Value", $binding::SetProperty, $null, $prop, $p.Value)
                }
                Catch [system.exception] { 
                    write-host -ForegroundColor red "Value not found for $p.Name"
                }
            }
            $doc.Fields.Update() | Out-Null
        
            Write-Host -ForegroundColor Cyan "Saving document."
            $doc.Saved = $false
            $doc.save()
            $doc.close()
        }
        
        $app.quit()
        $app = $null
        [gc]::collect()
        [gc]::WaitForPendingFinalizers()
        Write-Host -ForegroundColor Green "Done!"
        

        【讨论】:

        • 对我来说它不起作用,因为它说:“未找到 System.Collections.DictionaryEntry.Name 的值”所以它似乎没有使用自定义创建的键?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多