Showing posts with label Dynamic. Show all posts
Showing posts with label Dynamic. Show all posts

Saturday, April 1, 2023

PowerApps: Multiple Filters On Single Column (And/Or)

Hello Friends,
Welcome back with another post on PowerApps. We had discussed lot of things in some of our earlier posts. Sometimes, we have to apply multiple filter criteria on a single column. For example- we have a name column and we want to filter those names which Starts With "Wes" AND Ends With "mons". Additionally, it might be possible that instead of Starts with, user wants to filter records where Name Equals To  "Richard Lin". Or, user may want to get the records which Starts With "Roger". Means, there may be multiple combination of filter options with Single or Multiple criteria. How, we are going to tackle it?


Today, we will be discussing the same. Let's start-

  1. Login to PowerApps Maker Portal.
  2. Create a blank PowerApps Canvas App and give a suitable name.
  3. Either refer below post for adding a scrollable gallery or you can just create a gallery and add some data.
    1. PowerApps: Scroll Bar In Gallery
    2. PowerApps: Pagination Component
  4. I had added a scrollable gallery from Scroll Bar post and the content of gallery picked from Pagination component post.
  5. Here, I have created 1 master collection named "coll_MasterData" and later on assigned this master collection to another collection named "coll_FinalData". The reason of creating the second collection is to assign the filtered data to this collection so that it can be linked to gallery, while our master collection will remain intact.
  6. Next, we will add-
    1. Text Label (1 Nos)
    2. Text Input (2 Nos)
    3. Dropdown (3 Nos)
    4. Button (2 Nos)
  7. After adding, I had grouped them. The naming conventions are-
    1. Text Label: lbl_FatherNameFilterTitle
    2. Dropdown For 1st Filter Criteria: dd_FatherNameFilter1
    3. Textinput For 1st Filter Criteria: txt_FatherNameFilter1
    4. Dropdown For Filter Join Condition: dd_FatherNameFilterJoin
    5. Dropdown For 2nd Filter Criteria: dd_FatherNameFilter2
    6. Textinput For 2nd Filter Criteria: txt_FatherNameFilter2
    7. Button For Apply Filter: btn_FatherNameFilter_Apply
    8. Button For Apply Filter: btn_FatherNameFilter_Clear
  8. Similary, add another set of controls (mentioned above) for Mother Name filter.
  9. Now, we will create a collection of various filter criteria. Likewise- "If equal to", "Contains" ...
  10. So, on App >> OnStart, we will create this collection.
    1. ClearCollect(
          coll_FilterOptions,
          {Text: "Is equal to"},
          {Text: "Is not equal to"},
          {Text: "Starts with"},
          {Text: "Ends with"},
          {Text: "Contains"},
          {Text: "Does not contain"}
      );
  11. Next, we will bind this collection with Items property of-
    1. dd_FatherNameFilter1
    2. dd_FatherNameFilter2
    3. dd_MotherNameFilter1
    4. dd_MotherNameFilter2
  12. Also assign the Default property to the first item of collection.
  13. Now, we will create another collection "coll_JoinConditions" for Join conditions (And/Or) on App >> OnStart. Later, we will bind this collection to the Items property of-
    1. dd_FatherNameFilterJoin
    2. dd_MotherNameFilterJoin
  14. Also assign the Default property to the first item of collection.
  15. At this point, our base structure is ready. Now, we will write the filter code for each button. Ideally, we must include one more button which will contain the common logic. The reason behind is that, when a user will click on "Apply" button, you have to validate the filters of each column. So, rather than writing the same code on each "Apply" button, write down the code on a common button and add the Select function for this button on each "Apply" button.
  16. Let's add the button and name it as "btn_ApplyCommonFilter". Later-on we will set it's visible property as False. So that, the button should not be visible to users. 
  17. Now, apply the below code on "OnSelect" property of this button.
    1. UpdateContext({vrFilterCriteria1Key_FatherName:dd_FatherNameFilter1.SelectedText.Text});
      UpdateContext({vrFilterCriteria1Value_FatherName:txt_FatherNameFilter1.Text});
      UpdateContext({vrFilterJoinCondition_FatherName:dd_FatherNameFilterJoin.SelectedText.Text});
      UpdateContext({vrFilterCriteria2Key_FatherName:dd_FatherNameFilter2.SelectedText.Text});
      UpdateContext({vrFilterCriteria2Value_FatherName:txt_FatherNameFilter2.Text});
      UpdateContext({vrIsFilterAppliedOn_FatherName:false});
      ClearCollect(coll_Filter1_FatherName,[]);
      ClearCollect(coll_Filter2_FatherName,[]);
      ClearCollect(coll_FinalFilter_FatherName,[]);
      
      //GET COLLECTION BASED UPON FATHERNAME FIRST FILTER CRITERIA 
      If(
          !IsBlank(vrFilterCriteria1Value_FatherName)
          ,UpdateContext({vrIsFilterAppliedOn_FatherName:true});
          If(
              Upper(vrFilterCriteria1Key_FatherName) = "IS EQUAL TO"
              ,ClearCollect(coll_Filter1_FatherName,Filter(coll_MasterData,Upper(Father) = Upper(vrFilterCriteria1Value_FatherName)));
              ,If(
                  Upper(vrFilterCriteria1Key_FatherName) = "IS NOT EQUAL TO"
                  ,ClearCollect(coll_Filter1_FatherName,Filter(coll_MasterData,Upper(Father) <> Upper(vrFilterCriteria1Value_FatherName)));
                  ,If(
                      Upper(vrFilterCriteria1Key_FatherName) = "STARTS WITH"
                      ,ClearCollect(coll_Filter1_FatherName,Filter(coll_MasterData,StartsWith(Upper(Father), Upper(vrFilterCriteria1Value_FatherName))));
                      ,If(
                          Upper(vrFilterCriteria1Key_FatherName) = "ENDS WITH"
                          ,ClearCollect(coll_Filter1_FatherName,Filter(coll_MasterData,EndsWith(Upper(Father), Upper(vrFilterCriteria1Value_FatherName))));
                          ,If(
                              Upper(vrFilterCriteria1Key_FatherName) = "CONTAINS"
                              ,ClearCollect(coll_Filter1_FatherName,Filter(coll_MasterData,Upper(vrFilterCriteria1Value_FatherName) in Upper(Father)));
                              ,If(
                                  Upper(vrFilterCriteria1Key_FatherName) = "DOES NOT CONTAIN"
                                  ,ClearCollect(coll_Filter1_FatherName,Filter(coll_MasterData,!(Upper(vrFilterCriteria1Value_FatherName) in Upper(Father))));
                              );
                          );
                      );
                  );
              );
          );
      );
      
      //GET COLLECTION BASED UPON FATHERNAME SECOND FILTER CRITERIA 
      If(
          !IsBlank(vrFilterCriteria2Value_FatherName)
          ,UpdateContext({vrIsFilterAppliedOn_FatherName:true});
          If(
              Upper(vrFilterCriteria2Key_FatherName) = "IS EQUAL TO"
              ,ClearCollect(coll_Filter2_FatherName,Filter(coll_MasterData,Upper(Father) = Upper(vrFilterCriteria2Value_FatherName)));
              ,If(
                  Upper(vrFilterCriteria2Key_FatherName) = "IS NOT EQUAL TO"
                  ,ClearCollect(coll_Filter2_FatherName,Filter(coll_MasterData,Upper(Father) <> Upper(vrFilterCriteria2Value_FatherName)));
                  ,If(
                      Upper(vrFilterCriteria2Key_FatherName) = "STARTS WITH"
                      ,ClearCollect(coll_Filter2_FatherName,Filter(coll_MasterData,StartsWith(Upper(Father), Upper(vrFilterCriteria2Value_FatherName))));
                      ,If(
                          Upper(vrFilterCriteria2Key_FatherName) = "ENDS WITH"
                          ,ClearCollect(coll_Filter2_FatherName,Filter(coll_MasterData,EndsWith(Upper(Father), Upper(vrFilterCriteria2Value_FatherName))));
                          ,If(
                              Upper(vrFilterCriteria2Key_FatherName) = "CONTAINS"
                              ,ClearCollect(coll_Filter2_FatherName,Filter(coll_MasterData,Upper(vrFilterCriteria2Value_FatherName) in Upper(Father)));
                              ,If(
                                  Upper(vrFilterCriteria2Key_FatherName) = "DOES NOT CONTAIN"
                                  ,ClearCollect(coll_Filter2_FatherName,Filter(coll_MasterData,!(Upper(vrFilterCriteria2Value_FatherName) in Upper(Father))));
                              );
                          );
                      );
                  );
              );
          );
      );
      
      // GET THE FINAL FILTER RESULT FOR FATHER NAME BASED UPON JOIN CONDITION
      If(
          !IsBlank(vrFilterCriteria1Value_FatherName) && !IsBlank(vrFilterCriteria2Value_FatherName)
          ,If(
              Upper(vrFilterJoinCondition_FatherName) = "OR"
              ,ClearCollect(coll_FinalFilter_FatherName,coll_Filter2_FatherName);
              Collect(coll_FinalFilter_FatherName,Filter(coll_Filter1_FatherName, !(ID in coll_Filter2_FatherName.ID)));
              ,ClearCollect(coll_FinalFilter_FatherName,Filter(coll_Filter1_FatherName, ID in coll_Filter2_FatherName.ID));
          )
          ,If(
              !IsBlank(vrFilterCriteria2Value_FatherName)
              ,ClearCollect(coll_FinalFilter_FatherName,coll_Filter2_FatherName);
              ,If(
                  !IsBlank(vrFilterCriteria1Value_FatherName)
                  ,ClearCollect(coll_FinalFilter_FatherName,coll_Filter1_FatherName);
                  ,ClearCollect(coll_FinalFilter_FatherName,coll_MasterData);
              )
          )
      );
      
      
      //********************************************************************************************************//
      
      UpdateContext({vrFilterCriteria1Key_MotherName:dd_MotherNameFilter1.SelectedText.Text});
      UpdateContext({vrFilterCriteria1Value_MotherName:txt_MotherNameFilter1.Text});
      UpdateContext({vrFilterJoinCondition_MotherName:dd_MotherNameFilterJoin.SelectedText.Text});
      UpdateContext({vrFilterCriteria2Key_MotherName:dd_MotherNameFilter2.SelectedText.Text});
      UpdateContext({vrFilterCriteria2Value_MotherName:txt_MotherNameFilter2.Text});
      UpdateContext({vrIsFilterAppliedOn_MotherName:false});
      ClearCollect(coll_Filter1_MotherName,[]);
      ClearCollect(coll_Filter2_MotherName,[]);
      ClearCollect(coll_FinalFilter_MotherName,[]);
      
      //GET COLLECTION BASED UPON MotherNAME FIRST FILTER CRITERIA 
      If(
          !IsBlank(vrFilterCriteria1Value_MotherName)
          ,UpdateContext({vrIsFilterAppliedOn_MotherName:true});
          If(
              Upper(vrFilterCriteria1Key_MotherName) = "IS EQUAL TO"
              ,ClearCollect(coll_Filter1_MotherName,Filter(coll_MasterData,Upper(Mother) = Upper(vrFilterCriteria1Value_MotherName)));
              ,If(
                  Upper(vrFilterCriteria1Key_MotherName) = "IS NOT EQUAL TO"
                  ,ClearCollect(coll_Filter1_MotherName,Filter(coll_MasterData,Upper(Mother) <> Upper(vrFilterCriteria1Value_MotherName)));
                  ,If(
                      Upper(vrFilterCriteria1Key_MotherName) = "STARTS WITH"
                      ,ClearCollect(coll_Filter1_MotherName,Filter(coll_MasterData,StartsWith(Upper(Mother), Upper(vrFilterCriteria1Value_MotherName))));
                      ,If(
                          Upper(vrFilterCriteria1Key_MotherName) = "ENDS WITH"
                          ,ClearCollect(coll_Filter1_MotherName,Filter(coll_MasterData,EndsWith(Upper(Mother), Upper(vrFilterCriteria1Value_MotherName))));
                          ,If(
                              Upper(vrFilterCriteria1Key_MotherName) = "CONTAINS"
                              ,ClearCollect(coll_Filter1_MotherName,Filter(coll_MasterData,Upper(vrFilterCriteria1Value_MotherName) in Upper(Mother)));
                              ,If(
                                  Upper(vrFilterCriteria1Key_MotherName) = "DOES NOT CONTAIN"
                                  ,ClearCollect(coll_Filter1_MotherName,Filter(coll_MasterData,!(Upper(vrFilterCriteria1Value_MotherName) in Upper(Mother))));
                              );
                          );
                      );
                  );
              );
          );
      );
      
      //GET COLLECTION BASED UPON MotherNAME SECOND FILTER CRITERIA 
      If(
          !IsBlank(vrFilterCriteria2Value_MotherName)
          ,UpdateContext({vrIsFilterAppliedOn_MotherName:true});
          If(
              Upper(vrFilterCriteria2Key_MotherName) = "IS EQUAL TO"
              ,ClearCollect(coll_Filter2_MotherName,Filter(coll_MasterData,Upper(Mother) = Upper(vrFilterCriteria2Value_MotherName)));
              ,If(
                  Upper(vrFilterCriteria2Key_MotherName) = "IS NOT EQUAL TO"
                  ,ClearCollect(coll_Filter2_MotherName,Filter(coll_MasterData,Upper(Mother) <> Upper(vrFilterCriteria2Value_MotherName)));
                  ,If(
                      Upper(vrFilterCriteria2Key_MotherName) = "STARTS WITH"
                      ,ClearCollect(coll_Filter2_MotherName,Filter(coll_MasterData,StartsWith(Upper(Mother), Upper(vrFilterCriteria2Value_MotherName))));
                      ,If(
                          Upper(vrFilterCriteria2Key_MotherName) = "ENDS WITH"
                          ,ClearCollect(coll_Filter2_MotherName,Filter(coll_MasterData,EndsWith(Upper(Mother), Upper(vrFilterCriteria2Value_MotherName))));
                          ,If(
                              Upper(vrFilterCriteria2Key_MotherName) = "CONTAINS"
                              ,ClearCollect(coll_Filter2_MotherName,Filter(coll_MasterData,Upper(vrFilterCriteria2Value_MotherName) in Upper(Mother)));
                              ,If(
                                  Upper(vrFilterCriteria2Key_MotherName) = "DOES NOT CONTAIN"
                                  ,ClearCollect(coll_Filter2_MotherName,Filter(coll_MasterData,!(Upper(vrFilterCriteria2Value_MotherName) in Upper(Mother))));
                              );
                          );
                      );
                  );
              );
          );
      );
      
      // GET THE FINAL FILTER RESULT FOR Mother NAME BASED UPON JOIN CONDITION
      If(
          !IsBlank(vrFilterCriteria1Value_MotherName) && !IsBlank(vrFilterCriteria2Value_MotherName)
          ,If(
              Upper(vrFilterJoinCondition_MotherName) = "OR"
              ,ClearCollect(coll_FinalFilter_MotherName,coll_Filter2_MotherName);
              Collect(coll_FinalFilter_MotherName,Filter(coll_Filter1_MotherName, !(ID in coll_Filter2_MotherName.ID)));
              ,ClearCollect(coll_FinalFilter_MotherName,Filter(coll_Filter1_MotherName, ID in coll_Filter2_MotherName.ID));
          )
          ,If(
              !IsBlank(vrFilterCriteria2Value_MotherName)
              ,ClearCollect(coll_FinalFilter_MotherName,coll_Filter2_MotherName);
              ,If(
                  !IsBlank(vrFilterCriteria1Value_MotherName)
                  ,ClearCollect(coll_FinalFilter_MotherName,coll_Filter1_MotherName);
                  ,ClearCollect(coll_FinalFilter_MotherName,coll_MasterData);
              )
          )
      );
      
      //********************************************************************************************************//
      
      // FINAL RESULT BASED UPON ALL COLUMNS AND FILTERS
      
      If(
          vrIsFilterAppliedOn_FatherName && vrIsFilterAppliedOn_MotherName
          ,ClearCollect(coll_FinalData,Filter(coll_FinalFilter_FatherName,ID in coll_FinalFilter_MotherName.ID));
          ,If(
              vrIsFilterAppliedOn_FatherName
              ,ClearCollect(coll_FinalData,coll_FinalFilter_FatherName)
              ,If(
                  vrIsFilterAppliedOn_MotherName
                  ,ClearCollect(coll_FinalData,coll_FinalFilter_MotherName)
                  ,ClearCollect(coll_FinalData,coll_MasterData)
              );
          );
      );
  18. Just to clarify, it contains 3 section. The first section contains code for FatherName. The second section is replica of first section for the MotherName. we had just replaced Father with Mother. (or whatever be the column name you are going to apply the filter). The third section is the merging the result of both sections to one final result. Always remember to write code in such a way that if you have to make a replica of that code for other section/column, you have to do minimum rework. Here, I just replaced Father by Mother and it worked.
  19. Now, add the below code on "OnSelect" property of buttons - "btn_FatherNameFilter_Apply" & "btn_MotherNameFilter_Apply".
    1. Select(btn_ApplyCommonFilter)
  20. Add below code on "OnSelect" property of "btn_FatherNameFilter_Clear"-
    1. Reset(dd_FatherNameFilter1);
      Reset(txt_FatherNameFilter1);
      Reset(dd_FatherNameFilterJoin);
      Reset(dd_FatherNameFilter2);
      Reset(txt_FatherNameFilter2);
      Select(btn_ApplyCommonFilter);
  21. Similary add below code on "OnSelect" property of "btn_MotherNameFilter_Clear"
    1. Reset(dd_MotherNameFilter1);
      Reset(txt_MotherNameFilter1);
      Reset(dd_MotherNameFilterJoin);
      Reset(dd_MotherNameFilter2);
      Reset(txt_MotherNameFilter2);
      Select(btn_ApplyCommonFilter);
  22. Lastly, set the "Visible" property of button "btn_ApplyCommonFilter" as false.
  23. Now, save the app, publish and Run.
  24. First I will filter the data where FatherName StartsWith "a"
  25. Now, I will add the filter for MotherName where it should EndsWith "s".
  26. If I say, I want records where FatherName should either StartsWtih "ric" OR StartsWith "ant".
  27. This way, you may apply filters on more columns as well.
  28. A typical UI example of above filter box, I had applied in one of the application-

With this, I am concluding this post.
Happy Coding !!!
Will see you again with some new topics.

Stay Safe !
Stay Healthy !

Friday, September 23, 2022

Power Automate: Export To Excel With Dynamic Table & Columns Creation

Hello Friends,
Welcome back with another post on Power Automate. Today, we will learn how create a table in excel dynamically along with the columns where number of columns are not predefined. The export data to excel. The outcome of this post will be-
Let's start-
  1. First of all, we need a SharePoint list. Below is the list, I had created. It has 8 columns.
  2. Now, the objective is that I wish to export any combination of columns-
    1. ID, Title, First Name, Last Name 
    2. ID, First Name, Date Of Joining, Salary, Designation
    3. ID, Full Name (First Name + Last Name), Designation
  3. As we can see in above examples, the number of column as well as the columns itself are not fixed. Till now, we were creating a defined template which is having a table with columns and using it to export the data. This approach will not work here.
  4. Microsoft had given solution for this problem as well. Let's begin-
  5. Create a document library in Site Assets or the Documents library. Let say "ExcelFiles".
  6. Now create a blank excel file and save it with name "EmployeesData.xlsx".
  7. Upload this file in "ExcelFiles" folder.
  8. Now, open the Power Automate maker portal and create a new Instant cloud flow with flow name as "POC-ExportExcelDynamic" and trigger condition "PowerApps".
  9. Add a variable that will interact with PowerApps to get the column names.
  10. Save the flow and keep saving the flow at regular interval during the flow writing.
  11.  Now, to create the table in excel dynamically, we should know the number of columns that are going to be created and based upon the count, the Excel cell address. As we know, that excel works upon cell address. Columns are defined as A, B, C, .... while rows are defined as 1, 2, 3, ...
  12. So, for the first row the first cell address is A1, second cell address is B1 and so on.
  13. Similarly, for the second row the first cell address is A2, second cell address is B2 and so on.
  14. Similarly, table is also dependent upon cells. For a 3 column table, the header address will be A1 -> C1. For a 4 column table, it will be A1 -> D1.
  15. However, there is no direct method to get the respective address of cell using the count. Here, we have to apply some trick. We will use an excel file to get the series of the address based upon count. Excel has provided "ADDRESS" function. Here is the excel.
  16. We have to create a JSON and will use the same. Here is the JSON.
    1. [
        {
          "ColumnNo": 1,
          "ColumnAddress": "A1"
        },
        {
          "ColumnNo": 2,
          "ColumnAddress": "B1"
        },
        {
          "ColumnNo": 3,
          "ColumnAddress": "C1"
        },
        {
          "ColumnNo": 4,
          "ColumnAddress": "D1"
        },
        {
          "ColumnNo": 5,
          "ColumnAddress": "E1"
        },
        {
          "ColumnNo": 6,
          "ColumnAddress": "F1"
        },
        {
          "ColumnNo": 7,
          "ColumnAddress": "G1"
        },
        {
          "ColumnNo": 8,
          "ColumnAddress": "H1"
        },
        {
          "ColumnNo": 9,
          "ColumnAddress": "I1"
        },
        {
          "ColumnNo": 10,
          "ColumnAddress": "J1"
        },
        {
          "ColumnNo": 11,
          "ColumnAddress": "K1"
        },
        {
          "ColumnNo": 12,
          "ColumnAddress": "L1"
        },
        {
          "ColumnNo": 13,
          "ColumnAddress": "M1"
        },
        {
          "ColumnNo": 14,
          "ColumnAddress": "N1"
        },
        {
          "ColumnNo": 15,
          "ColumnAddress": "O1"
        },
        {
          "ColumnNo": 16,
          "ColumnAddress": "P1"
        },
        {
          "ColumnNo": 17,
          "ColumnAddress": "Q1"
        },
        {
          "ColumnNo": 18,
          "ColumnAddress": "R1"
        },
        {
          "ColumnNo": 19,
          "ColumnAddress": "S1"
        },
        {
          "ColumnNo": 20,
          "ColumnAddress": "T1"
        },
        {
          "ColumnNo": 21,
          "ColumnAddress": "U1"
        },
        {
          "ColumnNo": 22,
          "ColumnAddress": "V1"
        },
        {
          "ColumnNo": 23,
          "ColumnAddress": "W1"
        },
        {
          "ColumnNo": 24,
          "ColumnAddress": "X1"
        },
        {
          "ColumnNo": 25,
          "ColumnAddress": "Y1"
        },
        {
          "ColumnNo": 26,
          "ColumnAddress": "Z1"
        },
        {
          "ColumnNo": 27,
          "ColumnAddress": "AA1"
        },
        {
          "ColumnNo": 28,
          "ColumnAddress": "AB1"
        }
      ]
      
  17. You may create as many as column numbers you want. Ideally, keep it "Total Number of Columns in list + 10" so that in case, if one or 2 columns got added later on in the list, it will not impact your flow.
  18. Now, add an action called Parse JSON in flow and paste this JSON in Content as well as use this JSN to create schema "Generate from sample".
  19. Now, we have the columns list that were passed through PowerApps and we have the mapping structure of Column Number vs Cell Address.
  20. Add another action called "Filter array".
  21. Here we will filter the JSON to find the corresponding cell address row (Column Address property in JSON) using the count of columns passed through PowerApps.
  22. It will give us the item which is having ColumnNo property equals to the total number of columns received from PowerApps.
  23. Now, we will fetch the ColumnAddress property from this output. So, add another called "Compose".
  24. The first part is completed. Now, add an action called "Copy file". We will create a copy of the excel template.
  25. Remember to select "Copy with a new name" option in dropdown which is asking the further course of action "If another file is already there".
  26. Now, here the climax part of the flow. Microsoft have given a unique feature to create table on the fly. Add an action "Create table".
  27. Provide the input as shown below. The starting range is fixed to A1, followed by a colon ":". The table range can be "Absolute", "Partial Relative" or "Relative". Make sure, whatever you are choosing, both cell address must be in same format. Here, I had chosen, "Relative"
  28. You may give the table name as per your wish. I had given "SearchResults". You may define a variable for the Table Name as well in the beginning because, this table name is going to be used at two places, therefore, to avoid any misspell, you may use variable.
  29. This was the second part.
  30. The last part is adding items to table.
  31. Add an action called "Get Items".
  32. Next, we will use the "Select" to transform the data as per our requirement. For an example, if we wish to add another column "Full Name", we can do here by using "concat" function. Remember, the name of column at left side in mapping must be exactly the same as we are expecting to get receive from PowerApps.
  33. So, add "Select" action.
  34. I had used "concat" function to join First Name & Last Name. Also, I used "formatDateTime" function to apply formating upon Date Of Joining. 
  35. Now, use "Apply to each" action to add this data to excel table.
  36. Add an action "Apply to each".
  37. Now, add "Add row into a table" action inside this "Apply to each" action.
  38. It's all done.
  39. Now, If you wish to send this excel as attachment or send the link of the file, you can add further actions that will fulfil the requirements. These all, we have already discussed in our previous posts.
  40. Save the flow and test it.
  41. Let's check for our first set of columns mentioned in the beginning of the post. Remember, column names should be separated either by comma or semicolon and should not have leading or trailing spaces.
    1. ID,Title,First Name,Last Name [Correct Format]
    2. ID;Title;First Name;Last Name [Correct Format]
    3. ID, Title,First Name , Last Name [In-Correct Format]
  42. Click on "Test" >> "Manually" >> "Test". It will show the Run window and asking for Column names.
  43. Give the input as "ID,Title,First Name,Last Name" and click on Run.
  44. Wait for the flow to complete it's execution. It got succeeded.
  45. Check the SharePoint library. The file got created with name as "EmployeesData1.xlsx".
  46. Here we go. The is there.
  47. Now let's try with custom column 
    1. ID,Full Name,Designation,Date Of Joining,Salary,Experience
  48. Here we go. This also tested successfully.
  49. This is how, you can create Excel Tables dynamically with any number of columns. However, you can create the file on the runtime but for that, you need to include the OneDrive connection. Ultimately, you are creating a file then copying it. Means one more step. Therefore, we avoided that. Keeping a blank file is far better than to include one more connection and adding one more step.
With this, I am concluding this post.
Happy Coding !!!
Will see you again with some new topics.

Stay Safe !
Stay Healthy !