Table of Contents

Migration Process

This page describes the end-to-end procedure to migrate Project Online and SharePoint Online data into Altus PPM.

Important

Complete every step in Prerequisites and Altus POL Migration SharePoint App before starting this process.

Process summary

Project Online

Step Script
1. Export Project Online data ExportAllProjects.ps1
2. Export lookup tables ExportLookupTableData.ps1
3. Import lookup tables ImportLookupTableData.ps1 (configured via LookupTablesToImport.ps1)
4. Load lookup tables Default.ps1
5. Map resource custom fields and create resources ImportResources.ps1, AltusPOLMigration.ps1
6. Map project custom fields and create projects ImportProjects.ps1, AltusPOLMigration.ps1
7. Map task custom fields New-FieldMappingFile.ps1, Set-CustomFieldMapping.ps1
8. Run schedule migration Publish-MPPsToAltus.ps1
9. Post-migration steps (manual)

SharePoint Online

Step Script
Lists – Update export.config.json (config file)
Lists – Run export 1-export-lists.ps1
Lists – Run import 2-import-lists.ps1
Documents – Create/identify target library (manual)
Documents – Run export export script with required parameters
Documents – Post-migration (manual)

Project Online data migration

1. Export Project Online data

Download the scripts

  1. Open the Project Online Migration page on the Altus partner portal.
  2. Download Altus.Project.Online.Migration.Toolkit.<date>.zip.
  3. Unblock the zip file (if Windows reports it as blocked).
  4. Extract the scripts to a working folder, e.g. C:\Users\<you>\Desktop\POLDataMigration.
Note

If you get errors after extraction, you may need to unblock individual .ps1 files via their Properties dialog.

Run the export

You will need:

Property Example
Project Online URL https://<tenant>.sharepoint.com/sites/<pwa>
Script location cd <path>\POLDataMigration\0.Project-Online-Extraction
Files location <path>\POLDataMigration\2.Project-and-Resource-Migration\Files
Important

Microsoft Project Desktop must be open during the export so it can save the .MPP files. Do not connect MS Project to Project Online; it just needs to be running.

  1. Open SharePoint Online Management Shell.

  2. Navigate to the export script folder.

  3. Run the export, optionally filtering by project name (asterisk wildcard supported):

    .\ExportAllProjects.ps1 `
      -Url "https://<tenant>.sharepoint.com/sites/<pwa>" `
      -OutputDirectory "<path>\2.Project-and-Resource-Migration\Files" `
      -ProjectFilter @("Brisbane Roadmap Tool Implementation", "D365 Deployment")
    
  4. Sign in with the Project Online administrator account when prompted.

Note

The export script uses Microsoft's well-known ClientId d3590ed6-52b3-4102-aeff-aad2292ab01c; this does not need to be set. The Altus or custom ClientId is required by ExportLookupTableData.ps1 and Run-Migration.ps1 (see Altus POL Migration SharePoint App).

If you see Set-ExecutionPolicy errors, run:

Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process -Force

Filtering with OData

The -ProjectFilter parameter accepts OData expressions. Operators:

Operator Syntax
Equals eq
Not equals ne
Greater than gt
Greater than or equal ge
Less than lt
Less than or equal le

Examples:

Filter Syntax
Text EnterpriseProjectTypeName eq 'Major Project'
Numbers ProjectFixedCost gt 0
GUIDs EnterpriseProjectTypeId eq guid'7473ef8c-9f25-e911-afb0-00155da06b17'
Booleans ProjectEnterpriseFeatures eq true
Date ProjectStartDate gt datetime'2024-09-01T00:00:00Z'

The Project Online OData API can be browsed at https://<tenant>.sharepoint.com/sites/pwa/_api/ProjectData.

2. Export lookup tables

  1. Open SharePoint Online Management Shell.

  2. Navigate to 1.Lookup-Table-Migration.

  3. Run:

    .\ExportLookupTableData.ps1 `
      -PwaUrl "https://<tenant>.sharepoint.com/sites/<pwa>" `
      -ClientId "<your-client-id>"
    

The lookup tables are exported as .csv to 1.Lookup-Table-Migration\LookupTables.

3. Import lookup tables

Before running this step, the lookup tables must already exist in Altus (created in Prerequisites § Add configuration to a solution layer).

Configure the script

  1. In your solution layer, open each lookup table and copy these values:

    • Logical name (singular)
    • Collection name (plural)
    • Name field logical name
    • (Hierarchical only) Parent field logical name
  2. Open LookupTablesToImport.ps1 for editing.

  3. Update each entry with the source .csv file name and the table details. Example:

    # Flat lookup table
    @{
        SourceFile     = "LookupTable_Employment Status.csv"
        MapAsHierarchy = $false
        DataverseTable = @{
            TableLogicalName    = "ce_employmentstatus"
            TableCollectionName = "ce_employmentstatuses"
            NameField           = "ce_name"
            DescriptionField    = "ce_description"
        }
    }
    
    # Hierarchical lookup table
    @{
        SourceFile     = "LookupTable_Skills.csv"
        MapAsHierarchy = $true
        DataverseTable = @{
            TableLogicalName     = "ce_skills"
            TableCollectionName  = "ce_skillses"
            NameField            = "ce_name"
            DescriptionField     = "ce_description"
            PrevLevelLookupField = "ce_parent"
        }
    }
    
Note

Logical names must be lowercase. Uncomment the script blocks before running (remove leading #).

Run the import

  1. Open SharePoint Online Management Shell and navigate to 1.Lookup-Table-Migration.

  2. Run:

    .\ImportLookupTableData.ps1
    
  3. Enter the Altus environment URL when prompted (e.g. https://<env>.crm6.dynamics.com/).

  4. Sign in to Altus.

Errors are written to a log file in the same folder.

4. Load lookup tables

Update Default.ps1 so the project and resource import scripts can resolve lookup table values.

  1. Open 2.Project-and-Resource-Migration\Default.ps1.

  2. Update $LookupTablesToLoad with each lookup table's table logical name, collection name, and name field. To get the Set Name for the collection, in Power Apps select the table > Tools > Copy Set Name.

    $LookupTablesToLoad = @(
        @{
            Lookup = "lookup_RBS"
            DataverseTable = @{
                TableLogicalName    = "ce_rbs"
                TableCollectionName = "ce_rbses"
                NameField           = "ce_name"
            }
        },
        # ...
    )
    
  3. Update $ChoiceFieldsToLoad for each global/local choice field used by the import:

    $ChoiceFieldsToLoad = @(
        @{
            Name           = "choice_YesNo"
            IsGlobalChoice = $true
            DataverseTable = @{
                TableLogicalName = "sensei_project"
                ChoiceField      = "ce_examplechoicefield"
            }
        }
    )
    
Note

Uncomment the script blocks before running.

5. Map resource custom fields and create resources

Field type mapping

Project Online type Dataverse type Sub-type
Cost Currency
Date (date only) Date and time Date only
Date (date and time) Date and time Date and time
Duration Whole number Duration
Flag Choice Yes/no
Number (whole) Whole number
Number (decimal) Decimal
Text (single line) Single line of text Text
Lookup (single select) Lookup Text
Lookup (multi select) Lookup (via many-to-many) Text

Map resource custom fields

Edit ImportResources.ps1 and add a script block per custom field. Only the field name, Altus logical name, and any Default.ps1 alias references need to change. Refer to Migration Reference § Resources for the full set of code blocks.

Example mappings:

# Text
$textValue = Get-ResourceCustomFieldTextValue -ProjectResource $ProjectResource `
    -CustomFieldName 'Resource Example text field'
if ($textValue) { $resourceBody['ce_resourceexampletextfield'] = [string]$textValue }

# Single-select lookup
Set-ResourceLookupField -ResourceBody $resourceBody -ProjectResource $ProjectResource `
    -POLCustomFieldName 'Resource Example Lookup Field' `
    -LookupName 'lookup_EmploymentStatus' `
    -DataverseFieldName 'ce_ResourceExampleLookupField'

# Multi-select lookup (many-to-many)
Set-ResourceManyToManyRelationship -ResourceBody $resourceBody -ProjectResource $ProjectResource `
    -POLCustomFieldName 'Resource Example Multiselect Lookup Field' `
    -LookupName 'lookup_MultiValueTable' `
    -RelationshipName 'ce_sensei_bookableresource_ce_ExampleMultiSelectLookup_ce_ExampleMultiSelectLookup' `
    -RelatedTableCollectionName 'ce_examplemultiselectlookups' `
    -RelatedTablePrimaryKey 'ce_examplemultiselectlookupid'
Note

Dataverse field names in the lookup helpers (-DataverseFieldName) are case-sensitive.

For multi-select fields, the -RelationshipName, -RelatedTableCollectionName, and -RelatedTablePrimaryKey values are sourced from the table's Relationships and Properties panes in Power Apps.

Create resources

  1. Open SharePoint Online Management Shell.

  2. Navigate to 2.Project-and-Resource-Migration.

  3. Run:

    .\AltusPOLMigration.ps1
    
  4. Enter the Altus environment URL.

  5. Sign in.

  6. Select the mode of operation:

    • E – Execute (commit records)
    • W – What-If (simulate)
  7. Select 2: Import Resources (Named and Generic).

OOTB resource fields are mapped as documented in Migration Reference § Resources.

6. Map project custom fields and create projects

Map project custom fields

Edit ImportProjects.ps1. The pattern is the same as for resources but with the project helpers (Get-ReportingCustomFieldTextValue, Set-ProjectChoiceField, Set-ProjectLookupField, Set-ProjectManyToManyRelationship). See Migration Reference § Projects for the complete list of code blocks.

Create projects

  1. Open SharePoint Online Management Shell and navigate to 2.Project-and-Resource-Migration.
  2. Run .\AltusPOLMigration.ps1, sign in, select E or W, then select 3: Import Projects.
Important

Microsoft Project Desktop will open for each project as the script runs. Do not close it — closing MS Project will cause the script to fail. Resources must already have been imported (run the script twice if you also need to import resources).

A log file is generated when the script completes.

7. Map task custom fields

Project Online supports unlimited task-level enterprise custom fields, but MS Project Desktop is limited to a fixed set of local fields:

Local field type Number available
Date 9 (Date1 – Date9)
Finish 10 (Finish1 – Finish10)
Flag 20 (Flag1 – Flag20)
Number 20 (Number1 – Number20)
Start 10 (Start1 – Start10)
Text 26 (Text1 – Text26)
Outline Code 10 (Outline Code1 – Outline Code10)

The following local fields are reserved by Altus for Project:

Scope Local field Reserved for
Task Text 29 Task GUID
Task Text 30 Task Hash
Task Date 10 Protected Actuals Before
Resource Text 27 Resource Role
Resource Text 28 Resource Type
Resource Text 29 Resource GUID
Resource Text 30 Resource Hash
Note

Custom Cost and Duration task fields are not currently supported. Project Online task lookup fields are migrated to text fields in Project Desktop (no lookup picker). To preserve a controlled list, create the custom field in Altus only and edit it directly in the Altus schedule.

End-to-end process

  1. Create the task custom field in Altus (see Prerequisites § Create custom fields).
  2. Generate the field-mappings.csv file.
  3. Set the field mapping in Altus.
  4. Run the script that maps Project Online enterprise task custom fields to the local MS Project Desktop fields.

Generate the .csv mapping file

  1. Open MS Project Desktop.

  2. Open SharePoint Online Management Shell (not as administrator).

  3. Navigate to 3.Schedule-Migration.

  4. Run:

    .\New-FieldMappingFile.ps1 `
      -Path "<path>\2.Project-and-Resource-Migration\Files" `
      -OutputPath ".\field-mappings.csv"
    
  5. When prompted, choose how decimal Project Online fields map to MS Project local fields.

Set the field mapping in Altus

  1. Open Altus > Settings > Altus for Project Configuration.
  2. Select New Field Mapping.
  3. Specify the Microsoft Project field and the Altus field as per field-mappings.csv > OK.
  4. Repeat for every task custom field.

Run the mapping script

.\Set-CustomFieldMapping.ps1 `
  -MppFolder  "<path>\2.Project-and-Resource-Migration\Files" `
  -MappingFile "<path>\3.Schedule-Migration\field-mappings.csv"

8. Run schedule migration

Connect MS Project to Altus

  1. Open MS Project > Blank Project > save it.
  2. Select the Altus tab > Connect to Altus.
  3. Sign in and select the target Altus environment.
  4. When the project list loads, click Cancel.

Run the publish script

  1. Open SharePoint Online Management Shell (not as administrator).

  2. Navigate to 3.Schedule-Migration.

  3. Ensure MS Project is open and connected to Altus.

  4. Run:

    .\Publish-MPPsToAltus.ps1 `
      -BaselineNumber 0 `
      -IsReportable $true `
      -Path "<path>\2.Project-and-Resource-Migration\Files"
    

Successfully published files are moved to ...\Files\Published. To re-run the migration, move them back to ...\Files.

Note

If your environments use different currencies, also pass -ProjectCurrency and set it to match Altus and Project Online (see Troubleshooting § Script Currency Issue).

To migrate additional baselines, change -BaselineNumber (0–10) and re-run the script. Use -IsReportable $true to flag a baseline as the reportable baseline in Altus.

Resource rates

The publish script also migrates resource rates from MS Project to Altus bookable resources. No additional action is required; matching resources are populated automatically.

MS Project Altus
Resource Sheet Bookable Resources
Cost Rate Table A Bookable Resource > Rates
Standard Rate Rate (Hourly) – sensei_rate
Effective Date Effective Date – sensei_effectivedate

Time-phased resource rates are migrated for each time period.

9. Post-migration steps

The scripts populate only the basic project and resource information. Complete the following manually after the migration.

1. Set project type

Default for all projects is Major Project. Update by opening each project, removing the type and selecting the correct one, then Save & Close.

2. Set project ownership

Re-assign each project to the project manager who owns it in Altus by setting the Project Manager lookup. The Altus security model uses this to scope edit access.

3. Update remaining project information

Suggested fields to update post-migration: Description, Department, Target Finish, Investment Category, Location, Portfolio/Program, Sponsor, Status.

4. Set the current project stage

Each new project starts at the first stage of the Business Process Flow. Walk projects forward through stages by completing the checklist items and selecting Next Stage.

5. Update remaining bookable resource information

Suggested fields: Primary Role, Enterprise Calendar, Location, Start/End Date, Calendar Exceptions.

SharePoint data migration

SharePoint list data

Important

The target Altus projects must already exist before running the SharePoint list migration. If not, complete the Project Online migration first.

The list migration script supports UPSERTs and can be re-run safely. Deletions are not propagated — if you delete a list item in SharePoint, you must remove the corresponding Altus record manually.

By default the scripts map the Risks and Issues lists (see Migration Reference § Risks and § Issues for the OOTB mapping).

1. Update export.config.json

Add a script block per custom field. Only these fields need to change:

Attribute Details
spFieldInternalName SharePoint internal name (set when the field was created; spaces become _x0020_).
entityAttribute Logical name of the Altus column.
type SharePoint type — Text, Bool, DateTime, DateOnly, Decimal, Number, Lookup, Money, OptionSet.
choiceMap (Choice only) Map of SharePoint label → Altus option set value (e.g. 955000000).
lookupEntity (Lookup only) Logical name of the related Altus table.

Example:

{
  "_fielddetails": "Single line of Text",
  "spFieldInternalName": "ExampleTextField",
  "entityAttribute": "ce_examplesptextfield",
  "type": "Text"
}

See Migration Reference § Risks/Issues – Modified Script for the full set of field-type templates (Text, Bool, DateTime, DateOnly, Decimal, Number, Lookup, Money, OptionSet).

2. Run the export

.\1-export-lists.ps1 `
  -SiteCollectionUrl "<pol url>" `
  -MappingJsonPath ".\export.config.json" `
  -OutputFolder ".\Output" `
  -POLExportPath "<path to project Files>"

3. Run the import

.\2-import-lists.ps1 `
  -D365Url "<altus url>" `
  -DataFolder ".\Output" `
  -POLExportPath "<path to project Files>"

Custom lists

Custom lists are configured in export.config.json alongside Risks and Issues. Each custom list entry specifies the SharePoint list title, the target Altus entity, the project lookup attribute, and a columnMap of field mappings. Example:

{
  "spListTitle": "Actions",
  "entityLogicalName": "ce_action",
  "projectLookupAttribute": "ce_sensei_project",
  "projectLookupEntityLogicalName": "ce_sensei_project",
  "projectLookupTextSource": "Web.Title",
  "backlinkAttribute": "sensei_sourceitemurl",
  "columnMap": [
    { "spFieldInternalName": "Title",       "entityAttribute": "ce_name",        "type": "Text" },
    { "spFieldInternalName": "Description", "entityAttribute": "ce_description", "type": "Text" }
  ]
}

SharePoint documents

What is migrated?

Documents are downloaded from each project's SharePoint subsite, including sub-folders, metadata tags, and version history (when enabled).

What is not migrated?

.aspx files are excluded by default; system libraries (Style Library, Preservation Hold Library, Form Templates, Recycle Bin, Site Assets) are excluded by default.

1. Create or identify the target library

Choose one of:

  • A Teams channel for the Altus project.
  • An existing non-Project-Online SharePoint document library.
  • A new non-Project-Online SharePoint document library.

2. Update and run the export script

Configurable parameters:

Parameter Default Notes
-ExcludeVersionHistory $true Set $false to export full version history.
-DetailedMetadata $false Set $true to export all document metadata.
-ExcludeLibraries "Style Library,Preservation Hold Library,Form Templates,Recycle Bin,Site Assets" Comma-separated list. Remove an entry to include that library.
-ExcludeFilePatterns @("*.aspx") Add additional patterns to exclude more file types.
-IncludeRootWeb (switch) Include the root web in the export.

3. Complete post-migration steps

Upload the exported files to the target Teams channel or document library and verify metadata as required.