A SharePoint Person column looks like a name in the list, but Power Apps treats it as a record rather than plain text.
That distinction matters whenever the control used to select a person gets its records from somewhere other than the Person column itself. Two records can refer to the same user and still be incompatible because their field names and schemas are different.
This post compares three ways to populate a single-value Project Manager Person column in a SharePoint list called Projects:
- Use the choices exposed by the SharePoint Person column.
- Restrict the selection to a predefined pool stored in a separate SharePoint list.
- Search the organization directory through the Office 365 Users connector.
The Person Record SharePoint Expects
A SharePoint Person value is an object. When Power Apps writes to the column, the SharePoint connector commonly expects a record shaped like this:
{
'@odata.type': "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedUser",
Claims: "i:0#.f|membership|user@contoso.com",
DisplayName: "Alex Wilber",
Email: "user@contoso.com"
}
The connector can also expose properties such as Department, JobTitle, and Picture. The important point is that a text value such as "Alex Wilber" or "user@contoso.com" is not, by itself, a SharePoint Person record.
In the examples below, ddlProjectManager is a single-select Combo box inside the Project Manager data card.
In the classic Combo box, use
DefaultSelectedItems. The olderDefaultproperty is deprecated. For a generated SharePoint form,Parent.Defaultis also a good starting point when the control'sItemsschema matches the data card value.
Case 1: Use the SharePoint Person Column's Choices
The simplest approach is to let the SharePoint column supply the records:
Choices(
[@Projects].'Project Manager',
Self.SearchText
)
Set the data card's Update property to:
ddlProjectManager.Selected
Set the Combo box's DefaultSelectedItems property to:
ThisItem.'Project Manager'
This works because Items, Selected, and the existing SharePoint value all use the SharePoint Person schema.
Does Choices Bind Directly to Office 365 Users?
Not quite. Choices([@Projects].'Project Manager') asks the SharePoint connector for valid choices for that Person column. SharePoint resolves people from the directory according to the column and tenant configuration, but the app is not calling the Office 365 Users connector directly.
This distinction is useful:
Choices(...)returns SharePoint-shaped Person records that can normally be saved without conversion.Office365Users.SearchUserV2(...)returns Microsoft Graph user records that must be converted before SharePoint can save them.
Use this first pattern when users may choose anyone SharePoint makes available to the Person column.
Case 2: Use a Predefined Project-Manager Pool
Sometimes project managers must come from a controlled list instead of the entire directory.
Suppose a separate SharePoint list called Users contains:
Title: the person's display name;Email: the person's email address;Role: either a Text or Choice column;Pillar Code: a Choice column used to narrow the pool.
The Combo box can show only project managers for the selected pillar:
ShowColumns(
Filter(
Users,
'Pillar Code'.Value = ddPillarCode.Selected.Value &&
Role = "PM"
),
Title,
Email
)
If Role is a SharePoint Choice column, compare its Value instead:
Role.Value = "PM"
The selected record now contains Title and Email. It does not contain SharePoint's Claims and DisplayName fields, so assigning ddlProjectManager.Selected directly to the data card produces a schema mismatch.
Build the Person record manually in the data card's Update property:
With(
{
selectedEmail: Lower(ddlProjectManager.Selected.Email)
},
{
'@odata.type': "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedUser",
Claims: "i:0#.f|membership|" & selectedEmail,
DisplayName: ddlProjectManager.Selected.Title,
Email: selectedEmail
}
)
The Combo box's existing value must match its Items schema, not the SharePoint Person schema. Set DefaultSelectedItems to:
{
Title: ThisItem.'Project Manager'.DisplayName,
Email: ThisItem.'Project Manager'.Email
}
An even safer edit-form default is to retrieve the matching row from the same data source:
LookUp(
ShowColumns(
Filter(
Users,
'Pillar Code'.Value = ddPillarCode.Selected.Value &&
Role = "PM"
),
Title,
Email
),
Lower(Email) = Lower(ThisItem.'Project Manager'.Email)
)
This version guarantees that the default record comes from the same table expression as Items.
Case 3: Search Office 365 Users Directly
Add the Office 365 Users connector to the canvas app before using this approach.
Set the Combo box's Items property to:
Office365Users.SearchUserV2(
{
searchTerm: ddlProjectManager.SearchText,
top: 10
}
).value
SearchUserV2 returns directory fields such as:
DisplayNameMailUserPrincipalNameJobTitleDepartment
Notice that this schema uses DisplayName and Mail. It does not use Title for the person's name, and JobTitle is the job-title field.
Convert the selected directory user into a SharePoint Person record in the data card's Update property:
With(
{
selectedEmail: Lower(
Coalesce(
ddlProjectManager.Selected.Mail,
ddlProjectManager.Selected.UserPrincipalName
)
)
},
{
'@odata.type': "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedUser",
Claims: "i:0#.f|membership|" & selectedEmail,
DisplayName: ddlProjectManager.Selected.DisplayName,
Email: selectedEmail
}
)
Coalesce handles accounts whose Mail property is blank by falling back to UserPrincipalName.
Default Value for an Existing Project
The SharePoint record contains Email; it does not contain an Office 365 Users Mail property. Therefore, this expression is not valid:
ThisItem.'Project Manager'.Mail
The most reliable default is to search for the existing SharePoint email and return the matching Office 365 Users record. That keeps the default in exactly the same schema as Items:
LookUp(
Office365Users.SearchUserV2(
{
searchTerm: ThisItem.'Project Manager'.Email,
top: 10
}
).value,
Lower(
Coalesce(
Mail,
UserPrincipalName
)
) = Lower(ThisItem.'Project Manager'.Email)
)
Set this formula on DefaultSelectedItems.
This requires another directory query when the form loads. If that cost matters, load or cache the matching directory user when the form opens.
Why Items and DefaultSelectedItems Must Agree
The Combo box is concerned with the schema of the records it displays:
Items schema = DefaultSelectedItems schema
The SharePoint data card is concerned with the schema written back to its column:
Update schema = SharePoint Person schema
These are separate boundaries.
For example, the controlled Users list gives the Combo box {Title, Email} records. The existing SharePoint Person must first be reshaped to {Title, Email} for DefaultSelectedItems. When the user submits the form, the selected {Title, Email} record must be reshaped again into {Claims, DisplayName, Email, ...} for Update.
Thinking in terms of those two boundaries makes most Person-field errors much easier to diagnose.
Extending the Pattern to Multiple Project Managers
To allow more than one project manager:
- Configure the SharePoint
Project Managercolumn to allow multiple selections. - Set the Combo box's
SelectMultipleproperty totrue. - Return a table of SharePoint Person records from the data card's
Updateproperty.
When Items comes from the Person column itself, the records already have the correct schema:
ddlProjectManager.SelectedItems
When Items comes from the controlled Users list:
ForAll(
ddlProjectManager.SelectedItems As selectedPM,
With(
{
selectedEmail: Lower(selectedPM.Email)
},
{
'@odata.type': "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedUser",
Claims: "i:0#.f|membership|" & selectedEmail,
DisplayName: selectedPM.Title,
Email: selectedEmail
}
)
)
When Items comes from Office 365 Users:
ForAll(
ddlProjectManager.SelectedItems As selectedUser,
With(
{
selectedEmail: Lower(
Coalesce(
selectedUser.Mail,
selectedUser.UserPrincipalName
)
)
},
{
'@odata.type': "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedUser",
Claims: "i:0#.f|membership|" & selectedEmail,
DisplayName: selectedUser.DisplayName,
Email: selectedEmail
}
)
)
For multiple defaults, use a table whose records match Items. With the SharePoint-native approach, the existing multi-person column normally supplies that table directly. With a custom list or Office 365 Users, map or retrieve every existing person in the source schema used by the Combo box.
Practical Checks
When a Person field refuses to save or an existing person does not appear in the Combo box, check:
- Is the SharePoint column single-value or multi-value?
- Does
Updatereturn one record or a table accordingly? - Does the
Updaterecord use SharePoint fields such asClaims,DisplayName, andEmail? - Does
DefaultSelectedItemsuse the same field names asItems? - Are you using
Emailfor a SharePoint Person record andMailfor an Office 365 Users record? - Could
Mailbe blank, requiringUserPrincipalNameas a fallback? - Is
Rolea Text column (Role = "PM") or a Choice column (Role.Value = "PM")?
The Rule to Remember
A person is not just an email address in Power Apps. It is a typed record whose shape depends on the connector that returned it.
Use the SharePoint Person column's choices when that meets the requirement. The selected value can usually be saved directly.
When the Combo box uses a controlled list or Office 365 Users, treat the control schema and the SharePoint schema as two separate contracts:
ItemsandDefaultSelectedItemsmust match each other.- The data card's
Updatevalue must match the SharePoint Person column.
Once those schemas line up, Person fields become predictable rather than mysterious.