Save List Attachments to SharePoint Document Library

Is it possible to save list item attachments to the document library? The short answer is yes.

This question is really common, and as you might know, there isn’t an OOTB way to do it. Still, I do understand this need because having the attachment documents in the SharePoint document library brings many benefits; search and filtering, metadata, collaboration, etc. I remember, when I was looking for a solution for this, I did find many blogs about how to upload images to the SharePoint document library with Power App.

At the end of the day, the solution for this comes to the point I had in my Tech Days 2020 session ‘The Right Tool for the Job – Combine Power Platform and SharePoint.’ Know your tools and use the right tool for the job. There is no need to read the attachment blobs in Power App and then upload the data somehow. Everything can be done with Power Automate, SharePoint, and some smart additions to extend user experience with UI only customizations.

Prepare the Library

There isn’t anything special you will need to the list that has the attachments. For the document library, I like to add a field to link the documents and the item in the referring list. So, add a column called ParentID as metadata to the document library where you want to save the document. Later, we will use this column to give the users more accessible access to the documents.

Copy the Attachments

In this example, I have a simple list with few columns and a Canvas Power App with a simple. The Save button is using the basic SubmitForm to save the given details. The attachment handling is done so that the end-user uses the default attachment field functionality to save the attachment document to the list. Then we will use a Power Automate flow to move them to the document library. There are few ways to build the necessary Power Automation.

  1. You can build a flow that is triggered on SharePoint When an item is created.
    1. In this method, the user, who is using the form, will need edit permission to the list
    2. If needed, the end-user doesn’t need permission to the document library because that connection is handled with the account that is used to create the flow
    3. But in many cases, we want the end-users to have access both on the list and document library
  2. You can initialize the flow from the Power App
    1. In this case, the user will need permission both in the list and the document library

Let’s use the option two here and initialize the flow straight from the Power App. From the ribbon in the Power Apps studio, select Action -> Power Automate -> Create a new flow. This will open a new Power Automate for you that is triggered by a Power App.

  1. Add an Initialize variable action in the beginning
    1. Name can be, for example, ListItemID
    2. Type is Integer
    3. For the value, open the dynamic value panel and select Ask in PowerApps
    4. I also like to rename the action for easier recognition in later steps
  2. Then we can select a SharePoint action related to attachments
    1. There are multiply available, and we need to use the Get attachments one
    2. Connect the action to the correct SharePoint list
    3. The id parameter is coming from the variable initialized in the beginning
  1. Next, add Apply to each action under the Control category
    1. For the output, select the Body from the Get attachment step
  2. Then add a Create file action under the SharePoint category
    1. Connect the step to the correct document library
    2. Set File name from the dynamic value panel and select the DisplayName coming from the Get attachments step
    3. File Content can also be set from the dynamic values, and you can use the AbsoluteUri parameter from the Get attachments step

Finally, remember to give a name to the flow and save it. I used the name ‘Save Attachments Demo.’ After this, we can go back to the Power App and connect the flow to the application. First, select the Save button and open the OnSelect property. Then from the ribbon, select Action -> Power Automate -> select the flow we just created. If you had something in the OnSelect property, you might lose the written function, but with undo, you can get them back.

We need to modify the OnSelect property of the button with the following functions.

SubmitForm(frmMyReport);

SaveAttachmentsDemo.Run(frmMyReport.LastSubmit.ID);

  • submit form is used to send the form details to the SharePoint list
  • Then we call the flow and give the necessary details to copy the attachments

The forms in Power Apps have some data state-related properties (LastSubmited, Unsaved, Updates) we can use in the process. LastSubmited property holds all the fields and their values of the last submitted form. We will send the list item ID parameter to the Power Automate. This id is then saved in the ListItemID variable at the beginning of the flow. Test the form with few attachments, and after the submission, the flow should copy the list attachments to the document library.

Finetuning

At this point, we can copy the attachments to the document library, but this leaves us two copies in different places, which is not ideal. Let us make some additions to the flow to overcome this.

The next step is to add the list item id as metadata to the document. This can be done with Update file properties action. The correct file is found with dynamic id fetch from the Create file action. Set the ParentID with the value in the ListItemID variable.

In the final step, we will delete the attachment from the list item. This can be done with Delete attachment action. Point the action to the list and get the item based on the ListItemID variable. The File Identifier id is fetched from the Get Attachment action.

Save the flow and make a test run with the app. Now we have a solution where the user can give list details and documents with Power Apps form. The form details are saved in the SharePoint list, and the documents are saved in a document library.

Linking the Details

So, what is the benefit of saving the id of the list item as metadata for the documents? With the id, we can build an easy functionality where users can access the desired documents straight from the list.

  1. Add a new text column to the list
    1. I like to name the column as Link to Documents
  2. Go to the document library, filter the list based on the ParentID field.
  3. Next, open the column formatting setting of the Link to Documents field
  4. Paste the following JSON to the column formatting field.

{
"$schema": "https://developer.microsoft.com/json-schemas/sp/column-formatting.schema.json",
"elmType": "a",
"txtContent": "Show Documents",
"attributes": {
"target": "_blank",
"href": "='LINK TO YOUR LIBRARY/Forms/AllItems.aspx?FilterField1=ParentID&FilterValue1=' + [$ID]"
},
"style": {
"border": "none",
"background-color": "transparent",
"cursor": "pointer",
"color": "Blue"
}
}

  1. Replace the ‘LINK TO YOUR LIBRARY’ with an URL pointing to your document library.
    1. This link in the JSON is pointing to a filtered view in the document library
    2. The FilterValue1 is set dynamically based on the ID of each list row ([$ID])
  2. Save the formatting and close the formatting panel

Now we have an easy way to navigate to the document straight from the list. When you click the Show Document link in the list, you will be directed to the documents library, and you will see only the documents related to the list item. More information on column formatting, like using the icons, can be found here: https://github.com/SharePoint/sp-dev-list-formatting

Creating a Feedback Form Part 2 – Connecting the Flow

In my last post, I started to create a Feedback form that is using the new possibility to us PowerApps for SharePoint Online list form customization. The first part shows how to create a separated forms for View, Edit, and New action. You should check that out first because we will extend that functionality on this post.

PowerApp Custom Forms and Flow – Creating a Feedback Form Part 1

In the old days, you probably have created workflow and send an email when something is added to the list. This type of action is completely valid, and you can still use traditional workflows even in Office 365. But the modern better way to do similar things is to use Flow. For our Feedback form, I wanted to connect the given feedbacks as tasks for our internal team that is building our Intranet.

Let’s add a Flow to our custom form and create a new to do item in Planner that comes as default service for each new Microsoft Group.

  1. From the Feedback list click the PowerApps -> Customize forms from the lists action ribbon.
    1. This will open the custom app forms application we did in Part 1 of this series.
  1. From the ribbon select Flows.
    1. This will open the Associated Flows panel.
  2. Select Create a new Flow.
  3. Flow application will be opened in new tab, and a new flow is created automatically.
    1. You can see that the flow is associated to PowerApps.
  1. What we wanted to do is to add a new task to Planner so let’s add an action to do that.
    1. Click New step -> Add an action
    2. From the opened form search all Planner related action by writing Planner to the search box.
    3. Select the first action Planner – Create a task
    4. This will add a new task to your flow. This task is used to create a new task into Planner.
  1. Now you need to connect to correct plan and bucket where you want to add the tasks.
    1. From Plan Id select the drop-down menu by clicking the down arrow in the field.
    2. This will open a form showing all available Planner plans.
    3. Select the one you want to use.
    4. Do the same thing for Bucket Id. Except, this time you will see all available buckets found from the plan you selected.
  2. For task Title let’s get the value from a user through PowerApps.
    1. Select Title field and select dynamic content -> Ask in PowerApps.
    2. This will create a new PowerApps parameter that we need to populate in our custom form. We will come back to this later.
  1. You could give values for other fields also if you want.
    1. One option is to add current time and date to Start Date-Time field.
    2. Select the Start Date field and select dynamic content.
    3. Open the Expression tab and scroll until you see utcNow().
    4. Click utcNow and click OK.
  2. Now we have a task that creates a new task to Planner and uses the title detail that the user created as task title.

But we are asking some more information from the user also, so let’s add the value from the Description field also into the task.

  1. Add a new step after the first task above and add a new action.
  2. From task selection form again, search planner but this time select Update task details.
  1. To update the new task we just created, select Task Id field and Add dynamic content.
    1. From the list select Id.
    2. The created task will send us the details of the created task, and we can now use that info to find it and update the details.
  2. Next, select the Description.
    1. From dynamic content, menu select Ask in PowerApp to get the value from our custom form.
  1. Finally, click the default name next to Flow name at the beginning of the form.
    1. Give the flow a name you desire to use.
    2. Click Create flow.
  2. Finally, you can click Done, and our flow is completed.

At this point, we have a custom form and a flow that does the task creation. But we still need to combine these two, so that right after a new task is created a new task will be created automatically. Of course, we could attach the flow in New Item Added event on the list, but for this example, we will add the flow straight to our custom form.

  1. Go back to the list and open the custom form PowerApp.
  2. Open the NewFormScreen we created in Part 1.
  3. From the screen select CustomNewForm.
    1. Expand the Title and Description card details. You need the see the name of the fields of the cards later on.
  1. While the form is selected choose OnSuccess event from the attribute drop-down.
    1. This event is run every time a new item is added successfully to the list.
    2. By default, it includes two actions. One for clearing the form and another one to close the panel.
    3. Copy the current OnSuccess value and save them for later use.
  2. From the ribbon select Action -> Flows
    1. You should see the flow you created earlier.
    2. Select the flow, and it will be added as a task to the OnSuccess event.
  1. Now we need to give those two parameters, Createatask_Title and Updatetaskdetails_Description, we decided to ask for the app.
    1. We will connect the form fields to the Flow task call to get the text user has given.
  1. The field value reference can be done based on the field name on the card.
    1. The name depends on your environment, but on this example, the names are DataCardValue2_1 for Description, and DataCardValue1_1 for Title.
    2. With the name, you can refer to the Text value and use that on the Flow call.
  1. Finally add the default tasks back to the OnSuccess action so that the form will be reset and closed when everything is done.
    1. Here’s the whole value used in the example: NewIntranetFeedback.Run(DataCardValue1_1.Text, DataCardValue2_1.Text); ResetForm(CustomNewForm); RequestHide()
  2. Now save and publish the app to SharePoint.

Navigate back to your list and start to add a new item. After the save check from Planner (https://tasks.office.com/) that a new task is added for future steps.

 

PowerApp Custom Forms and Flow – Creating a Feedback Form Part 1

Last month Microsoft announced a long waited functionality where you can use PowerApps to customize the modern list forms in Office 365. Customizing the OOTB SharePoint list forms is something we have done for years already, and everyone has done customizations in multiple different ways.

But when the new modern lists were announced, all of those old ways were useless. I do understand the shouts and anger that came out of this. Starting from last month the first release tenants have been able to use PowerApps and Flow to create custom forms. We can finally do something real with list forms.

Here are few articles related to custom form with PowerApps.

 

Over the time, I have created many types of Feedback forms in my SharePoint projects. The most simple solution is to use SharePoint list and let the users send feedback with OOTB form. But maybe there has been a need to give some instructions to the users or notify someone when new feedback created. To do this, you need to do some level of customization. Sometimes even some coding.

The best part of the new features in Office 365 is that changes can now be done without coding (almost, in many cases, etc. 😉 ) Even a power users can create customization with PowerApps and Flow. This is exactly what I’m about to show in this series.

My example form has the following requirements.

  1. Give a possibility to add some text and instructions to the users when they are giving the feedback.
  2. Show the necessary fields for feedback gathering.
  3. Save the details to SharePoint list.
  4. Create a new task on a backlog list in Planner.
  5. Give a quick view and search for existing feedback items.

Custom List for Feedbacks

  1. Step one which is the easiest one. Just create a new list to your SharePoint Online site.
    • Make sure that the list type is modern. I did create the list to the new modern team site that comes along the Office 365 Group.

Now add two new columns to the list. The quickest way to do this is by clicking the + sign on the view.
AddNewColumn

  1. Create the following fields
    • Description – Multiple lines of text
    • Feature Type – Choice with values; New Feature, Question, Update, and Bug
  2. And now you do have a simple feedback form ready to use!

PowerApp for Custom Forms

Now, let’s start to customize the form. Open the PowerApps menu from the list toolbar and select Customize forms. This will open and create the PowerApps application for your lists forms. Let’s take a look at few things before we make any changes.

  1. Click the SharePointIntegration link on the left and select Advanced tab from the right.
    • You can see the basic settings of the SharePoint integration from this screen.
    • DataSource is pointing to the list you created, and Action selection is pointing to custom forms.
  2. Notice that all Action events are pointing to only one form.
    • Different action types are handling the data mode automatically so calling your form with ViewForm action will show to form in read-only mode.
    • One thing to remember here is that in OOTB only one form is used. If you make any changes, these changes will reflect on all views types.
  3. To solve this issue, we need to create a new screen and form for our custom form.

  4. I ended up to create only two screens seen in the image above. One screen is for View and Edit, the other is for New item creation. You still have to update the values for each action setting in the SharePointIntegration. My settings are as follows (remember to use the names you set on your screens).
    • OnNew – Set(SharePointFormMode, “CreateForm”); NewForm(CustomNewForm); Navigate(NewFormScreen, ScreenTransition.None)
    • OnEdit – Set(SharePointFormMode, “EditForm”); EditForm(CustomViewForm); Navigate(ViewFormScreen, ScreenTransition.None)
    • OnView – Set(SharePointFormMode, “ShowForm”); ViewForm(CustomViewForm); Navigate(ViewFormScreen, ScreenTransition.None)
    • OnSave – If(SharePointFormMode=”CreateForm”, SubmitForm(CustomNewForm), If(SharePointFormMode=”EditForm”, SubmitForm(CustomNewForm)))
    • OnCancel – If(SharePointFormMode=”CreateForm”, ResetForm(CustomNewForm), If(SharePointFormMode=”EditForm”, ResetForm(CustomNewForm)))
  5. Now let’s make some changes to the New form. Delete the fields that are unnecessary like date fields etc.
    • Select the Title_DataCard from the CustomNewForm table and increase the height.
    • Lower the Title field and add two new Label controls at the beginning of the form.
    • Add the instructions in these new labels and make any other change you like.
    • You also have to change the mode of the Description box (DataCardValue2_1) to Multiline.
    • Now save and publish the forms.

Navigate to the Feedback list and try to create a new item. You should now see our custom form in use. Create one item and open it and you should see a different form in use.

CustomForm

In next part we will add a Flow send our Feedback to Planner.

Part 2: https://mikkokoskinen.com/2017/12/06/creating-a-feedback-form-part-2-connecting-the-flow/