如何更改许多Word文档的自定义属性

时间:2015-01-05 14:18:50

标签: powershell ms-word

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

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个单词文档。 我尝试了命令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。

4 个答案:

答案 0 :(得分:1)

正如Matt建议的那样,我会在应用程序打开后放入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()

答案 1 :(得分:1)

以下是我能够做到的事情:

#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()

答案 2 :(得分:1)

我调整并组合了我在这个线程中找到的一些解决方案,并创建了我认为这样的脚本应该如何表现的方式,即更改多个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!"

答案 3 :(得分:1)

我无法完成上述工作。始终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!"
相关问题