
You're staring at another Excel spreadsheet with hundreds of rows of equipment maintenance data. Your field technicians are emailing their findings, your operations team is manually typing updates into cells, and you're spending hours each week consolidating reports that should flow seamlessly into your system. Sound familiar?
This is exactly the kind of problem Power Apps was designed to solve. In the next 30 minutes, you're going to build your first canvas app—a mobile-friendly equipment maintenance form that captures data directly from the field and stores it in SharePoint. By the end of this lesson, you'll have a working app that you can deploy to your team today and the foundational skills to tackle more complex Power Apps projects.
What you'll learn:
You'll need access to Power Apps (included with most Microsoft 365 business plans) and SharePoint Online. Basic familiarity with Excel formulas will help, but isn't required—Power Apps formulas work similarly but we'll explain the syntax as we go.
Before we build anything in Power Apps, we need somewhere to store our data. SharePoint Lists are perfect for this—they're essentially cloud-based databases that integrate seamlessly with Power Apps.
Navigate to your SharePoint site and create a new list called "Equipment Maintenance". We're going to build this list to capture real maintenance data that a facilities team might collect:
Click "New List" and choose "Blank list". Name it "Equipment Maintenance" and add these columns:
The default "Title" column will serve as our record identifier—we'll populate it automatically based on the equipment ID and date.
Tip: Notice how we're using Choice columns for standardized data entry. This prevents typos and makes reporting much cleaner later. Always think about data quality when designing your schema.
Now for the exciting part. In your SharePoint list, click "Integrate" in the ribbon, then "Power Apps" → "Create an app". This launches the Power Apps Studio with a three-screen app automatically generated from your list structure.
Take a moment to explore what Power Apps created for you:
This is impressive, but we want something more focused. We're building a dedicated data entry form for field technicians, not a full CRUD application. Let's start fresh with a more targeted approach.
Delete these screens (right-click each screen in the Tree view and select "Delete") and insert a new blank screen. Rename it "MaintenanceForm" by right-clicking and selecting "Rename".
The key to a good data entry form is logical flow and minimal cognitive load. Field technicians need to quickly capture information without fumbling through complex interfaces. Let's build this step by step.
First, let's add a header that makes the app's purpose immediately clear. Insert a Rectangle control and position it at the top of the screen. Set its properties:
Fill: RGBA(0, 120, 212, 1) // Microsoft blue
Height: 80
Width: Parent.Width
X: 0
Y: 0
Add a Label control on top of the rectangle:
Text: "Equipment Maintenance Report"
Color: RGBA(255, 255, 255, 1)
Font: Font.Lato
Size: 18
FontWeight: FontWeight.Bold
Align: Align.Center
Position it in the center of your blue rectangle. This gives users immediate context about what they're doing.
Below the header, we'll create sections that group related information. Add another Label for the section header:
Text: "Equipment Information"
Font: Font.Lato
Size: 16
FontWeight: FontWeight.Semibold
Color: RGBA(51, 51, 51, 1)
Now add the first input field. Insert a Text Input control for Equipment ID:
HintText: "Enter equipment ID (e.g., HVAC-101)"
Default: ""
Format: TextFormat.Text
Add a Label above it with the text "Equipment ID *" (the asterisk indicates required fields). This pattern—label above input—creates a clean, scannable form layout.
For Equipment Type, we'll use a Dropdown control since we defined this as a choice field in SharePoint:
Items: ["HVAC", "Electrical", "Plumbing", "Safety", "Other"]
DefaultSelectedItems: []
HintText: "Select equipment type"
Continue this pattern for Location (Text Input) and Issue Priority (another Dropdown with items: ["Low", "Medium", "High", "Critical"]).
Add another section header: "Issue Details". Here's where we capture the meat of the maintenance request.
For Issue Description, use a Text Input control but make it taller to accommodate longer text:
Mode: TextMode.MultiLine
HintText: "Describe the issue in detail"
Height: 120
Add a final section for "Report Information". Include:
Set the Date Picker's DefaultDate property to Today() so it defaults to the current date.
Pro tip: Always provide sensible defaults. The Date Reported field should almost always be today, so don't make users think about it.
A form without validation is just a pretty way to collect bad data. Let's add validation that provides immediate feedback to users.
We'll implement a common pattern: show validation errors when users leave required fields empty and try to submit. First, create variables to track which fields have been touched.
On each text input's OnChange property, set a variable:
For Equipment ID:
Set(varEquipmentIDTouched, true)
For Issue Description:
Set(varIssueDescTouched, true)
Now add validation labels that appear when fields are empty and have been touched. Under your Equipment ID field, add a Label with:
Text: "Equipment ID is required"
Color: RGBA(255, 0, 0, 1)
Visible: IsBlank(TextInput_EquipmentID.Text) && varEquipmentIDTouched
This creates a red error message that only appears when the field is empty AND the user has interacted with it.
Let's add some business logic. Equipment IDs should follow a pattern (equipment type + number). Add this validation label under Equipment ID:
Text: "Equipment ID should contain the equipment type (e.g., HVAC-101)"
Color: RGBA(255, 140, 0, 1) // Orange for warnings
Visible: !IsBlank(TextInput_EquipmentID.Text) &&
!IsBlank(Dropdown_EquipmentType.Selected.Value) &&
!StartsWith(Upper(TextInput_EquipmentID.Text), Upper(Dropdown_EquipmentType.Selected.Value))
This warning appears when both fields have values but the Equipment ID doesn't start with the selected equipment type. It's helpful guidance without being overly restrictive.
One of Power Apps' most powerful features is native camera integration. Field technicians can capture photos of equipment issues directly in the app.
Add a Camera control to your form:
OnSelect: Set(varCapturedPhoto, Camera1.Photo)
Text: "Take Photo"
Height: 200
Width: 300
Below it, add an Image control to preview captured photos:
Image: varCapturedPhoto
Visible: !IsBlank(varCapturedPhoto)
This creates a workflow where users tap the camera, take a photo, and immediately see a preview. The photo data is stored in the varCapturedPhoto variable until we save the record.
Now we need to wire everything together to actually save data to SharePoint. Add a Button control at the bottom of your form:
Text: "Submit Report"
Fill: RGBA(0, 120, 212, 1)
Color: RGBA(255, 255, 255, 1)
DisplayMode: If(
IsBlank(TextInput_EquipmentID.Text) ||
IsBlank(Dropdown_EquipmentType.Selected.Value) ||
IsBlank(TextInput_IssueDescription.Text),
DisplayMode.Disabled,
DisplayMode.Edit
)
The DisplayMode property disables the button when required fields are empty, providing visual feedback about form completeness.
In the button's OnSelect property, add this formula:
Patch(
'Equipment Maintenance',
Defaults('Equipment Maintenance'),
{
Title: TextInput_EquipmentID.Text & " - " & Text(DatePicker_DateReported.SelectedDate, "mm/dd/yyyy"),
'Equipment ID': TextInput_EquipmentID.Text,
'Equipment Type': {Value: Dropdown_EquipmentType.Selected.Value},
Location: TextInput_Location.Text,
'Issue Priority': {Value: Dropdown_IssuePriority.Selected.Value},
'Issue Description': TextInput_IssueDescription.Text,
'Technician Name': TextInput_TechnicianName.Text,
'Date Reported': DatePicker_DateReported.SelectedDate,
Status: {Value: "Reported"},
Photos: {Value: JSON(varCapturedPhoto)}
}
);
Notify("Maintenance request submitted successfully!", NotificationType.Success);
Reset(TextInput_EquipmentID);
Reset(TextInput_Location);
Reset(TextInput_IssueDescription);
Reset(TextInput_TechnicianName);
Reset(Dropdown_EquipmentType);
Reset(Dropdown_IssuePriority);
Set(varCapturedPhoto, Blank());
Set(varEquipmentIDTouched, false);
Set(varIssueDescTouched, false)
This formula does several important things:
Important: Notice how Choice fields (Equipment Type, Issue Priority, Status) are wrapped in {Value: } objects. This is required syntax for SharePoint Choice columns.
Before we go further, let's test what we've built. Click the Play button (▶) in the top-right corner to preview your app. Try filling out the form with realistic data:
Click Submit Report. You should see the success notification and the form should clear. Switch back to your SharePoint list and refresh—your new record should appear.
If you encounter errors, the most common issues are:
Your form works, but let's add some professional polish that makes it feel like a real business application.
When users submit forms on mobile devices, network delays can create uncertainty. Add a loading indicator by modifying your submit button:
Text: If(IsBlank(varSubmitting), "Submit Report", "Submitting...")
DisplayMode: If(
IsBlank(TextInput_EquipmentID.Text) ||
IsBlank(Dropdown_EquipmentType.Selected.Value) ||
IsBlank(TextInput_IssueDescription.Text) ||
!IsBlank(varSubmitting),
DisplayMode.Disabled,
DisplayMode.Edit
)
Update your OnSelect to include loading states:
Set(varSubmitting, true);
Patch(...); // your existing Patch formula
Set(varSubmitting, Blank());
// rest of your existing OnSelect code
Your form needs to work on phones, tablets, and desktops. Power Apps provides screen size information through the App object. Modify your control widths to be responsive:
For text inputs and dropdowns:
Width: If(App.Width < 640, App.Width - 40, Min(400, App.Width - 100))
This makes controls nearly full-width on phones (with 20px margins) and constrains them to a reasonable width on larger screens.
Pre-populate fields when possible. If your organization has multiple buildings, you might set Location's Default property to:
If(
CountRows(Filter('Equipment Maintenance', 'Technician Name' = User().FullName)) > 0,
Last(FirstN(Sort(Filter('Equipment Maintenance', 'Technician Name' = User().FullName), ID, Descending), 1)).Location,
""
)
This formula looks up the most recent location this technician reported from and suggests it as the default. Small touches like this dramatically improve user experience.
Now it's time to enhance your app with a feature that wasn't in our original design. Add a "Follow-up Required" section with:
Implement the toggle visibility pattern:
Visible: Toggle_FollowUp.Value = true
Update your Patch formula to include these new fields, but only when the toggle is enabled. This teaches you conditional data collection—a pattern you'll use frequently in real applications.
Add validation that prevents submission if follow-up is required but the expected completion date is in the past.
"Gallery control not found" errors: When Power Apps auto-generates formulas, it sometimes references controls that don't exist in your custom layout. Check all formulas for references to Gallery1, BrowseGallery1, etc., and remove them.
Choice field values not saving: SharePoint Choice fields require the {Value: "YourChoice"} syntax. If you're getting "Invalid argument type" errors, wrap your choice values properly.
Photos not appearing in SharePoint: The Photos column must be an "Image" type, not "Multiple lines of text". If you created it wrong, you'll need to delete and recreate it.
Form not responsive on mobile: Always test on actual devices, not just the browser preview. Use App.Width and App.Height to make layouts truly responsive.
Slow performance with large SharePoint lists: If your Equipment Maintenance list grows beyond a few hundred items, you'll need to implement delegation-friendly formulas. Avoid using functions like CountRows() on large data sources.
Users can't see the app: After publishing, you must explicitly share the app with users or security groups. Publishing doesn't automatically grant access.
Field technicians often work in areas with poor connectivity. Power Apps can work offline, but you need to explicitly load data into collections:
OnVisible: ClearCollect(
colOfflineRecords,
Filter('Equipment Maintenance', Status.Value = "In Progress")
)
Then reference colOfflineRecords instead of the SharePoint list directly. When connectivity returns, sync changes back to SharePoint.
In real organizations, maintenance requests often require approval. Connect your Power App to Power Automate to trigger approval workflows automatically when high-priority issues are submitted.
Instead of free-text Equipment ID entry, connect to your organization's asset management system. Use Power Apps' ability to call external APIs to validate equipment IDs and pre-populate location data.
Your app is ready for production. Here's how to deploy it professionally:
Before sharing, save your app with a meaningful version comment. Go to File → Save As and enter something like "v1.0 - Initial equipment maintenance form with photo capture and validation".
Don't just share with "Everyone in your organization." Create a security group in Azure AD for "Equipment Maintenance App Users" and share with that group. This gives you control over who can access the app and makes it easy to remove access when needed.
Create a simple one-page guide showing:
Set up monitoring from Day 1:
In 30 minutes, you've built a complete business application that captures structured data, validates input, handles photos, and integrates with your organization's existing SharePoint infrastructure. More importantly, you've learned the foundational patterns that power most Power Apps solutions:
Your next steps should focus on expanding these foundational skills:
The equipment maintenance form you built today can be deployed immediately and will likely save your organization hours of manual data entry each week. But more than that, you now have the skills to identify other paper-based processes that could benefit from the same treatment.
Power Apps shines brightest when you focus on solving real business problems with clean, intuitive interfaces. Keep that principle in mind as you tackle your next project.
Learning Path: Canvas Apps 101