#PowerShell, #PowerWiseScripting, #ProjectWise, PWPS_DAB

HowTo: Copy Documents To Folder

In this post, we will be creating a function to add functionality to the Copy-PWDocumentsToFolder cmdlet provided with the PWPS_DAB module. The cmdlet will delete and replace existing documents if the -CreateVersion parameter is not included. This new function will address this shortcoming in the cmdlet.

All of the ProjectWise related cmdlets are available using the PWPS_DAB module. At the time of this post, I am using version 24.01. Take a look at the help for each of the cmdlets to become familiar with their functionality, available parameters, etc.

  • Get-PWDocumentsBySearch
  • Copy-PWDocumentsToFolder

FUNCTION Definition

The following is the function wrapper which will contain the remainder of the code.

FUNCTION Copy-MyPWDocumentsToFolder {
    <#
    .Synopsis
    Used to copy a document(s) to another folder in the same ProjectWise datasource.
    .DESCRIPTION
    Used to copy a document(s) to another folder in the same ProjectWise datasource. 
    One of the three switch parameters must be included. -CreateVersion, ReplaceExisting, or SkipExisting.
    .EXAMPLE
    Replaces existing documents within the target folder.
    Get ProjectWise documents to be copied.
    $pwDocs = Get-PWDocumentsBySearch -FolderID 262045 -JustThisFolder -Verbose
    $Splat_Copy = @{
        InputDocument = $pwDocs
        TargetFolderPath = 'dmsSystem\test2\testSub'
    }
    Copy-MyPWDocumentsToFolder @Splat_Copy -ReplaceExisting -Verbose
    .EXAMPLE
    Skip any existing documents within the target folder.
    Get ProjectWise documents to be copied.
    $pwDocs = Get-PWDocumentsBySearch -FolderID 262045 -JustThisFolder -Verbose
    $Splat_Copy = @{
        InputDocument = $pwDocs
        TargetFolderPath = 'dmsSystem\test2\testSub'
    }
    Copy-MyPWDocumentsToFolder @Splat_Copy -SkipExisting -Verbose
    .EXAMPLE
    Create versions for any existing documents within the target folder.
    Get ProjectWise documents to be copied.
    $pwDocs = Get-PWDocumentsBySearch -FolderID 262045 -JustThisFolder -Verbose
    $Splat_Copy = @{
        InputDocument = $pwDocs
        TargetFolderPath = 'dmsSystem\test2\testSub'
    }
    Copy-MyPWDocumentsToFolder @Splat_Copy -CreateVersion -Verbose
    #>

    [CmdletBinding()]
    param (...) # end param...

    BEGIN {...} # end BEGIN...

    PROCESS {...} # end PROCESS...

    END{...} # end END...
} # end FUNCTION Copy-MyPWDocumentsToFolder...
Export-ModuleMember -Function Copy-MyPWDocumentsToFolder

Parameters

First thing we need to do is create our parameter and value pairs. The help messages will explain the purpose for each parameter. You will see that I have incorporated “ValidateSet” for the Type parameter.

[CmdletBinding()]
param ( 

    # Document(s) to be copied to target folder.
    [ValidateNotNullOrEmpty()]
    [Parameter(
        HelpMessage = "Document(s) to be copied to target folder.",
        Mandatory = $true,
        Position = 0)]
    [PWPS_DAB.CommonTypes+ProjectWiseDocument[]] $InputDocument,

    # Fullpath to the target folder to copy documents into.
    [ValidateNotNullOrEmpty()]
    [ValidateScript({ Get-PWFolders -FolderPath $_ -JustOne })]
    [Parameter(
        HelpMessage = "Fullpath to the target folder to copy documents into.",
        Mandatory = $true,
        Position = 0)]
    [string] $TargetFolderPath,

    # When included, document versions will be copied to target folder.
    [switch] $IncludeVersions,

    # When included, reference relationships will be maintained for copied documents.
    [switch] $CopyReferenceRelationships,

    # When included, a new version will be created if a document exists in the target folder with the same name.
    [Parameter(ParameterSetName = 'CreateVersion',
        Mandatory = $true)]
    [switch] $CreateVersion,

    # When included, if a document exists in the target folder with the same name, it will be skipped. 
    [Parameter(ParameterSetName = 'SkipExisting',
        Mandatory = $true)]
    [switch] $SkipExisting,

    # When included, if a document exists in the target folder with the same name, it will be deleted and replaced. 
    [Parameter(ParameterSetName = 'ReplaceExisting',
        Mandatory = $true)]
    [switch] $ReplaceExisting

) # end param...

Begin

I want to take a second and point out a couple of conventions that I use in my scripts. First, you may notice that I put a comment at the end of many of the blocks of code. Doing this makes it easier for me to determine where a block of code starts and ends. Comes in handy when troubleshooting a script.  I also add text ([BEGIN], [PROCESS], [END]) in the output messages (Write-Verbose, Write-Warning, Write-Error) corresponding to the section of the script I am in. Again, this makes it obvious where something occurs within the script.

BEGIN {
  
    $CmdletName = $MyInvocation.MyCommand.Name
    $StartTime = Get-Date
    Write-Verbose -Message "[BEGIN] $Start - Entering '$CmdletName' Function..."
    
} # end BEGIN...

PROCESS

Now, we will proceed to the PROCESS code block. Here the function will loop through each ProjectWise document object and copy to folder based on the provided parameter values.

PROCESS {
    
    try {

        Write-Verbose -Message "[PROCESS] $($InputDocument.Count) documents to be copied to '$TargetFolderPath' target folder."
        $Splat_CopyDocs = @{
            TargetFolderPath = $TargetFolderPath
            IncludeVersions = $IncludeVersions
            CopyReferenceRelationships = $CopyReferenceRelationships
        }

        if($CreateVersion){
            $Splat_CopyDocs.CreateVersion = $CreateVersion
        }
        if($SkipExisting){
            foreach($pwDoc in $InputDocument){
                try{
                    if($pwDoc_Temp = Get-PWDocumentsBySearch -FolderPath $TargetFolderPath -FileName $pwDoc.FileName -WarningAction SilentlyContinue){
                       Write-Verbose -Message "[PROCESS] '$($pwDoc.FileName)' document exists in target folder. Skipping..."
                    } else {
                        $return = Copy-PWDocumentsToFolder @Splat_CopyDocs -InputDocument $pwDoc -ErrorAction Stop
                        Write-Verbose -Message "[PROCESS] Successfully copied '$($pwDoc.FileName)' to target folder."
                    }
                } catch {
                    Write-Warning -Message "[PROCESS] $_"
                }
            }
        } else {
            $return = Copy-PWDocumentsToFolder @Splat_CopyDocs -InputDocument $InputDocument -Verbose -ErrorAction Stop
            Write-Verbose -Message "[PROCESS] Successfully copied '$($pwDocs.Count)' to target folder."
        }
        
    } catch {
        Write-Warning -Message $_
    } # end try/catch...
} # end PROCESS...

END

Lastly, we will proceed to the END block of code.

END {
    $EndTime = Get-Date
    Write-Verbose -Message "[END] It took $($EndTime - $StartTime) to complete the process."
    Write-Verbose -Message "[END] $EndTime - Exiting '$CmdletName' Function..."
} # end END...

Experiment with it and have fun.
Hopefully, you find this useful. Please let me know if you have any questions or comments.  If you like this post, please click the Like button at the bottom of the page.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.