Skip to main content
guideliving

Migrating Power Apps SharePoint list forms between sites (Dev to Sandbox to Prod)

How to retarget an exported Power Apps SharePoint list form package to a same-shaped list on another site in the GCC tenant, with a builder/deployer split, manual schema prep and rollback.

Reviewed Tue Oct 13 2026 00:00:00 GMT+0000 (Coordinated Universal Time) · Owner: Sid Annapragada · Sensitivity: internal

#Summary

A SharePoint list form built with Integrate > Power Apps > Customize forms is not a normal canvas app. It is tied to one list on one site, and it lives in the tenant's SharePoint form environment. That is the default environment unless a tenant admin has set another one (check with Get-AdminPowerAppSharepointFormEnvironment). List forms can't be added to solutions, so the usual ALM path (solutions, pipelines) does not apply, and Microsoft documents canvas app packages as basic export/import, not ALM.

This article describes the method used on the CLL (CCSQ-ISG Contracts) project, where eight forms were moved from Dev to Sandbox and the first three were released to Prod. Here's how it works:

  • The builder retargets the exported package to the target site and list and checks it.
  • The deployer (the SPO admin team or a maker) only imports a zip. They don't run any scripts.
  • List schema changes (new columns, choice values, required flags, calculated formulas) are made on the target list by hand before import, because the package can't carry them.

Supportability. Editing the contents of an exported package (step 3) is not a Microsoft-documented operation. The package format can change without notice. Microsoft documents exporting and importing app packages, but not moving a list form to a different list. The documented alternative is to rebuild the form on the target list. This method is a pragmatic alternative for forms too complex to rebuild. Use it only with a Sandbox trial of the same package, a backup of the target form and a rehearsed rollback. If the package format changes, re-validate the retarget step before relying on it.

#When to use this

  • You have a customized list form in one site and need the same form on the same-shaped list in another site.
  • The target list already exists, possibly with data, and must keep its columns and items.

Out of scope

  • Standalone canvas apps that use SharePoint as a data source. Use solutions for those.
  • Lists with multiple content types and content-type-specific forms. This method wasn't used or tested on them.

#How a list form is bound to its list

Knowing where the binding lives explains every step below. An exported package (.zip) holds:

Location in the package What it holds
Microsoft.PowerApps/apps/<id>/<id>.json > embeddedApp siteId, listId, listUrl and type SharepointFormApp, which is the registration that ties the app to the list
.json > connectionReferences > dataSets Site URL and list ID used by the SharePoint connection
.msapp > References/DataSources.json The form's data source: DatasetName = site URL, TableName = list ID, plus the column schema
.msapp > Properties.json, Resources/PublishInfo.json Further copies of the site and list references
manifest.json Package and app display name, plus the default import setting

Key rules

  • Keep the data source name unchanged. Every formula refers to it by name.
  • Avoid removing and re-adding the data source in Studio. Re-adding can give the source a different name (for example, the list's new display name), and then every formula that uses the old name breaks.
  • Permissions come from the list, not the app. Users need list permissions to use the form, and the app doesn't need to be shared.
  • Cards are bound by column internal name (DataField), not display name.

#Prerequisites

  • A target list with the same shape as the source list. Creating the test list with New list > From existing list (from Prod) gives you Prod's real internal names.
  • A column comparison of source and target (export the fields from each list and compare internal name, type, required flag and choice values).
  • Edit rights (Site Owner is safest) on the target list, and the Environment Maker role (or SharePoint custom form maker role) in the SharePoint form environment.
  • An agreed owner for the Prod form. The person who imports becomes the app owner, so record who that is and add a co-owner or hand ownership over before that person leaves the project.
  • Business answers for any differences that change behavior: choice values, required fields, calculated formulas.

#Method

#1. Compare the lists and plan the changes

For each form, list:

  1. Columns the form uses that are missing on the target. These are created by hand on the target list.
  2. Columns with a different internal name on the target. The form's cards are rebound to the target name (step 3).
  3. Choice values that differ. Align them by hand on the target list, and agree with the business what happens to existing items with old values.
  4. Columns required on the target but not on the form. Make them optional, or saving fails (see Troubleshooting).
  5. Calculated columns. Their formulas belong to the list and must be updated by hand.

Column internal names come from the first display name used when the column is created, and are cut to 32 characters. Create columns with the exact intended name first, in the planned order, and check the Field= value in the column settings URL afterwards.

#2. Export the source form

On the source list, open Customize forms, then in the maker portal go to Apps > … > Export package. Set the import setup to Create as new. An export may default to Update, which won't work for a new target.

#3. Retarget the package (builder only)

Replace every source site URL, list ID and list URL with the target values in the locations listed above. Then check that no source reference remains anywhere in the package, including inside the .msapp, and rename the app to show the target (for example, … Form - Prod).

Convert-SPFormPackage.ps1, published with this article (see its README), does all of this. Use -ListIdMap for other lists the form reads and -AppDisplayName to rename the app. The script fails if anything from the source remains.

Forms that read other lists (lookups, secondary data sources) need those lists' IDs mapped to the target site's lists too. Otherwise they point at the target site with the source site's list IDs, and the form fails.

If internal names differ (step 1.2), also rebind in the .msapp. The script doesn't do this:

  • Change each card's DataField and the formula references to the target internal name.
  • Keep the card's DisplayName as the label users know, so the screen doesn't change.
  • Do the replacements in two phases (old name to placeholder, then placeholder to new name). Otherwise two columns that swap names get renamed twice.

Record the build: source, target, list IDs, columns used, and the SHA-256 of the zip.

#4. Make the list changes on the target (deployer)

Before importing, apply the changes from step 1 on the target list by hand, then check each new column's internal name.

#5. Back up and detach the existing form (deployer)

If the target list already has a custom form:

  1. Export it: Apps > … > Export package. Note its app ID. This is your rollback copy.
  2. On the list: List settings > Form settings > Use the default SharePoint form, tick Delete custom form, then OK.

If the list has no custom form, skip this step. Rollback is then just switching Form settings back to the default form.

#6. Import (deployer)

  1. In the maker portal (make.gov.powerapps.us in GCC), confirm the environment is the SharePoint form environment. For most tenants that's the default environment, and the URL contains Default-<tenant id>. Import the form where the source list's forms already live.
  2. Apps > Import canvas app > Upload the zip.
  3. Wrench icon: Create as new, set the app name, Save, Import.

#7. Check in Studio and publish

  1. Open the app and allow the SharePoint connection.
  2. Confirm the data source points at the target site.
  3. Run App checker: 0 errors expected. Warnings on SharePointIntegration such as "Event rule references a control on another screen" are normal for list forms.
  4. Save, then Publish to SharePoint. Form settings on the list now shows the PowerApps form.

#8. Smoke test

On the target list: New (save an item), Edit an existing item (check that every field loads, including lookups and rich text), View. Delete test items afterwards. Have at least one test done by an ordinary list member, not a site owner, to prove the form works with normal permissions. If old items hold old choice values, open one in Edit and cancel without saving until the business has decided how to handle them.

#Troubleshooting

Symptom Cause Fix
Import fails: "Import failed for one or more package resources" Open the red ⓘ on the resource row for the actual error. In our case, the target list still had its old custom form attached Back up the old form, set Form settings to the default form with "Delete custom form", then import again
Import conflict: "You have already created an application with this name" A failed import left a broken app with that name. Its Edit, Share and Delete buttons are greyed out, so makers can't remove it Import with a new name (for example … v1). Ask a Power Platform admin to delete the broken app
App imported into the wrong environment The environment picker was on another environment Cancel, switch to the SharePoint form environment, upload again
Studio shows a DataSourceInfo(…, 'ColumnName') error A column the form uses doesn't exist on the target list Create the column (check the internal name), then refresh the data source. Don't remove and re-add it
"Network error when using Patch function: Field 'X' is required" A column required on the target isn't on the form Make the column optional on the target list, or add it to the form
Lookup or combo box blank in Edit mode DefaultSelectedItems = Parent.Default only carries Id/Value Filter('<Lookup list>', ID = ThisItem.<LookupColumn>.Id). Parent.Default.Id fails with "'Id' isn't recognized"
Date picker blank in Edit (modern controls) Wrong property set Use DefaultDate, not SelectedDate
Rich text column shows HTML tags in a text input The target column is rich text, the source was plain PlainText(Parent.Default) on the input's Default. Saving then writes plain text, so existing formatting is lost on edit. Agree this with the business, or use a rich text editor control instead
Delegation warning on sort or search Sorting or StartsWith on a calculated column Use a real text column instead
Lookup on the target points to the wrong list "From existing list" lookups point at the same-named list on the target site Check the lookup's source list on the target site

#Rollback

Situation Rollback
The list had a custom form Set Form settings to the default form with "Delete custom form", import the backup zip as Create as new (with a new name if the old app still exists), open it in Studio, Publish to SharePoint
The list had no custom form Set Form settings back to Use the default SharePoint form
List changes Reverse by hand. Keep the column definitions you backed up before the change. Removing a new column deletes any data entered in it, so export the items first
Old app deleted by mistake A Power Platform admin can recover a deleted canvas app within 28 days (Get-AdminDeletedPowerAppsList, Get-AdminRecoverDeletedPowerApp)
A later fix to the new form goes wrong In the maker portal, Apps > … > Details > Versions to restore an earlier version, then publish it to SharePoint again

Rehearse the rollback once in a test site before the first Prod release.

#Things to check beyond the form

  • Reports (Power BI / RDL) that read the list by column display name fail if a column is renamed or removed. Check them before changing list schema.
  • Power Automate flows that use a list name typed as a custom value break when the list's display name changes. Flows that picked the list from the dropdown store the list ID and keep working.
  • Renaming a list's display name doesn't affect the form. It's bound by list ID, and the URL and internal names stay the same.
  • Choice value changes don't rewrite existing items. Items keep their old values, which the new form may show blank or reject on save. Decide with the business whether to update old items in bulk or leave them.
  • Calculated columns that depend on changed choice values must be updated in the same change window.

#References

#Checklist

  • Column comparison done, and business answers in hand
  • Package retargeted, no source references left, build recorded
  • List changes applied on the target, and internal names checked
  • Existing form backed up and detached (if any)
  • SharePoint form environment selected, imported as Create as new
  • Form owner recorded, co-owner added
  • App checker shows 0 errors, published to SharePoint
  • New, Edit and View pass, including one test by an ordinary list member
  • App IDs and results recorded in the runbook
power-platformpower-appssharepointlist-formsalmmigrationdeployment