Tutorials/Power Apps/Inline Editable Data Table in Power Apps Without Premium Connectors
Power Appsintermediate

Inline Editable Data Table in Power Apps Without Premium Connectors

Recreate the feel of Excel data entry inside a canvas app using a gallery, text inputs, and a hidden toggle – no external libraries required.

NA
Narmer Abader
@narmer · Published June 3, 2026

Since Excel is the de facto standard for quick data entry, many business users expect the same “click and type” experience inside Power Apps. The default forms and galleries are great for viewing, but they don’t let you edit multiple rows in place without going into an edit form for each record. Fortunately, you can build a fully inline editable table using only a gallery, text input controls, and a bit of Power Fx logic. No premium connectors or custom code components required.

In this article you’ll build an Equipment Checkout Log where staff can quickly modify asset assignments, update condition notes, and save changes back to a SharePoint list. You’ll also learn how to detect only the rows that actually changed, so you can avoid unnecessary API calls. By the end you’ll have a reusable pattern that you can apply to any data source.

What You’ll Be Building

Imagine you manage a pool of laptops, projectors, and other equipment. Employees check out items, and you need an easy way to update the “Assigned To” or “Condition” column without opening a separate form for each row.

Your finished app will contain a gallery that looks like a spreadsheet. Users click an Edit button, type directly into the cells, then click Save to commit changes or Cancel to revert. A hidden toggle inside the gallery tracks which rows were actually modified so that only those records are patched.

Step 1 – Create a SharePoint List (or Use Dataverse)

The example uses a SharePoint list named EquipmentCheckout with these columns:

Column NameType
EquipmentIDSingle line of text
EquipmentNameSingle line of text
AssignedToSingle line of text
ConditionSingle line of text

Add a few sample rows so you can test the editing later. If you prefer Dataverse, the steps are identical – just substitute your table and column names in the code.

Open a blank canvas app and connect it to your EquipmentCheckout list. Insert a vertical gallery and rename it to gal_AssetTable. Set its Items property to 'EquipmentCheckout'.

Inside the gallery, delete the default controls and add four Text Input controls:

  • txt_EquipmentID
  • txt_EquipmentName
  • txt_AssignedTo
  • txt_Condition

Set each text input’s Default property to the corresponding column of the current record:

ThisItem.EquipmentID
ThisItem.EquipmentName
ThisItem.AssignedTo
ThisItem.Condition

Now the gallery shows the data, but it still looks like a typical gallery. Let’s transform it into a clean table.

Step 3 – Style the Table

To make the gallery resemble a spreadsheet, change these properties on gal_AssetTable:

PropertyValue
TemplatePadding0
TemplateSize40

Next, apply the following properties to all four text inputs to remove rounded corners and give them a white background with dark gray borders:

  • BorderColor: DarkGray
  • BorderThickness: 1
  • Color: Black
  • Fill: White
  • FocusedBorderColor: Self.BorderColor
  • FocusedBorderThickness: Self.BorderThickness
  • HoverBorderColor: Self.BorderColor
  • HoverColor: Self.Color
  • HoverFill: RGBA(186, 202, 226, 1)
  • PressedBorderColor: Self.BorderColor
  • PressedColor: Self.Color
  • PressedFill: Self.Fill
  • RadiusBottomLeft: 0
  • RadiusBottomRight: 0
  • RadiusTopLeft: 0
  • RadiusTopRight: 0

Finally, add a label above the gallery with column headers (Equipment ID, Equipment Name, etc.). Give it a themed background color and bold font weight. Now you have a read‑only table that looks like an Excel grid.

Step 4 – Detect Changes with a Hidden Toggle

We want to save only the rows that were actually edited. Insert a Toggle control inside the gallery, placed on the right side, and rename it to tog_Changed.

Set its Default property to a formula that compares each text input’s current value with the original value from the data source:

ThisItem.EquipmentID <> txt_EquipmentID.Text
Or ThisItem.EquipmentName <> txt_EquipmentName.Text
Or ThisItem.AssignedTo <> txt_AssignedTo.Text
Or ThisItem.Condition <> txt_Condition.Text

When you modify a cell, the toggle will switch to On for that row. Because the toggle is hidden from end users, set its Visible property to false.

Step 5 – Add Edit, Save, and Cancel Buttons

The table should start in view‑only mode. Users click Edit to unlock the cells, then Save to persist changes or Cancel to discard them.

Create a variable to track the current mode. Place the following code in App.OnStart (or in the OnVisible of a screen if you prefer):

Set(var_EditMode, Blank())

Now add three icon‑label pairs (or buttons) above the gallery. I’ll use icons for compactness, but buttons work just as well.

Edit Button

  • Icon: Edit (pencil) – name it ico_Edit
  • Visible: IsBlank(var_EditMode)
  • OnSelect: Set(var_EditMode, "Edit")

Also add a label next to the icon with the same Visible and OnSelect logic.

Save Button

  • Icon: Save – name it ico_Save
  • Visible: var_EditMode = "Edit"
  • OnSelect: (we’ll fill this in the next step)

Cancel Button

  • Icon: Cancel / X – name it ico_Cancel
  • Visible: var_EditMode = "Edit"
  • OnSelect: (we’ll fill this later)

Make Text Inputs Editable Only in Edit Mode

Select all four text inputs inside the gallery and set their DisplayMode property to:

If(var_EditMode = "Edit", DisplayMode.Edit, DisplayMode.View)

Now clicking Edit switches the entire table to editable mode; the Save and Cancel buttons appear.

Step 6 – Save Only Changed Rows

Saving should collect the modified rows and patch them back to the data source. First, create a collection that defines the schema. In App.OnStart add:

ClearCollect(col_Updates,
    {ID: 1, EquipmentID: "A", EquipmentName: "A", AssignedTo: "A", Condition: "A"}
);
Clear(col_Updates);

(The {ID: 1, ...} record is only used to establish the column types; it’s cleared immediately.)

Now set the OnSelect of the Save icon (and its label) to:

// Gather all changed rows into the collection
ForAll(
    Filter(gal_AssetTable.AllItems, tog_Changed.Value) As ChangedRows,
    Patch(col_Updates,
        Defaults(col_Updates),
        {
            ID: ChangedRows.ID,
            EquipmentID: ChangedRows.txt_EquipmentID.Text,
            EquipmentName: ChangedRows.txt_EquipmentName.Text,
            AssignedTo: ChangedRows.txt_AssignedTo.Text,
            Condition: ChangedRows.txt_Condition.Text
        }
    )
);

// Write all changes at once (fast batch patch)
Patch('EquipmentCheckout', col_Updates);

// Clear the working collection
Clear(col_Updates);

// Return to view mode
Set(var_EditMode, Blank());

This code loops through only the rows where tog_Changed is On, packs them into col_Updates, and then calls Patch once with the entire collection. The Patch function performs multiple updates in a single request when you pass a table as the second argument, which is much faster than individual Patch calls.

Step 7 – Cancel Changes

When the user presses Cancel, you need to reset all text inputs to their original values (from the data source) and return to view mode.

Add this code to the OnSelect of the Cancel icon:

// Trigger reset of all text inputs in the gallery
Set(var_ResetInputs, true);
Set(var_ResetInputs, false);

// Clear any accumulated changes
Clear(col_Updates);

// Switch back to view mode
Set(var_EditMode, Blank());

Then, on each of the four text inputs, set the Reset property to var_ResetInputs. Now when Cancel is clicked, the variable flips, all inputs revert to their Default value (which is still ThisItem.ColumnName), and the edits are lost.

Performance & Delegation Notes

  • Gallery.AllItems is not delegated – it retrieves all records from the data source. For lists with more than 500 rows, consider adding a search/filter to reduce the set. The change‑detection toggle still works on the filtered subset.
  • Using a single Patch(dataSource, collectionOfChanges) is far more efficient than individual patches inside a ForAll. The ForAll here only runs in the local app, so it’s fast; the actual network call is one batch operation.
  • If your data source is Dataverse, the pattern is identical – just use the Dataverse table name and columns. Dataverse also supports batch patching, so performance is similar.

Common Mistakes & Troubleshooting

Numbers not saving correctly If you have a numeric column, remember to convert the text input with Value(txt_MyNumber.Text) when patching. Otherwise the string may be rejected.

Toggle never turns on Make sure the Default property references the correct column names and that you’re using <> (not !=). Also check that the text inputs’ Default property points to ThisItem.ColumnName.

Reset not working The Set(var_ResetInputs, true) / Set(var_ResetInputs, false) pattern works because the reset triggers when the variable transitions to a new value. If you set it to the same value twice nothing happens. The toggle from true to false is that transition.

Visible toggle distracting Set its Visible property to false. The toggle will still work, just not be seen.

Final Thoughts

This inline editable table pattern gives your users a comfortable Excel‑like experience without leaving Power Apps. You can extend it further by adding an “Add new row” feature (inserting a blank row into the gallery) or a “Delete” button that removes selected rows. The same change‑tracking technique with a hidden toggle works for those scenarios too.

Start with a simple list, tweak the styling to match your app theme, and you’ll have a flexible data entry grid ready in minutes.

References