Wednesday, March 22, 2017

Creating & Deploying SharePoint Workflow Custom Activities to SharePoint Online

Creating the Workflow Custom Activity

In your project select new item and add a custom SharePoint workflow activity as below:


A custom activity comprise of three components. they are the Elements.xml, the actions4 file and the xaml file which contain the flow of the activity.


Depending on your implementation the input and output parameters in your custom activity may vary. You need to edit the actions4 file accordingly. In the custom activity I'm creating there are three input parameters. Therefore I change the actions4 file as shown below. Basically you neeed to add the RuleDesigner and the parameters section to the file.

<Action Name="GetBuildingDetailsActivity" ClassName="CustomActivites.GetBuildingDetailsActivity" Category="Custom" AppliesTo="all">
  <RuleDesigner Sentence="Create a new lease record for the given %1 and records the %2, %3, %4 ">
    <FieldBind Field="buildingId" Text="Building ID" Id="1" />
    <FieldBind Field="buildingAddress" Text="Address" Id="2" />
    <FieldBind Field="buildingPhone" Text="Phone" Id="3" />
    <FieldBind Field="buildingManager" Text="Building Manager" Id="4" />
  </RuleDesigner>
  <Parameters>
    <Parameter Type="System.String, mscorlib" Direction="In" Name="buildingId" />
    <Parameter Type="System.String, mscorlib" Direction="Out" Name="buildingAddress" />
    <Parameter Type="System.String, mscorlib" Direction="Out" Name="buildingPhone" />
    <Parameter Type="System.String, mscorlib" Direction="Out" Name="buildingManager" />
  </Parameter>
</Action>

Afterwards, edit the xaml file according to the logic you need to implement. Here note that i have created several In and Out arguments of string type.



Deploying the Custom Activities to SharePoint Online

First create the WSP. In my case I published the WSP to a local folder location.


Then upload it to the SharePoint Solutions catalog which in under the "Web Designer Galleries" section

Activate the solution
















Now we can launch the SharePoint Designer and configure the created Workflow Custom Activity to a workflow.

SharePoint Designer Configuration

  • Launch SharePoint Designer
  • Open the SharePoint site
  • Under the "Workflows" select the type of workflow you need to create. In my case I'm choosing a list workflow. So I choose the list/library which I need the workflow to get deployed as well.
  • When the workflow is generated, click on the "Stage" section which you need to add the custom activity, then select the custom activity you created.


Here, I need to point out few things.

1) My Custom Activity was packaged within a feature. Therefore I have to activate the feature in order to get the custom activities listed down in SharePoint Designer as follows:


2) Initially when the Custom Activity is added you will get the argument names supplied. You need to configure them according to the columns in your list/library. The initial view is as below:

3) Also make it a point to add a ending transition by adding a go to

A final cut of the workflow will look something similar to the below image. In this workflow I have also added another custom activity which I created separately. The custom activities will run in a sequential manner during the workflow run.

In my list the Building Id is provided from the "Title" column. Hence, the argument is changed to reflect that. Also notice the, Go to which is added to end the workflow.

 Save and Publish the workflow you created to the SharePoint list/library.
Now is when the fun begins. You can go to the list/library and test run your workflow and see how it goes !!

Additionally, you can navigate to the list/library item and check on all the workflows associated with the item. You can see stage of the workflow and how it has proceeded so far, provided that you have done the logging (write to history actions) properly. One such example would be as in the below image




Tuesday, March 21, 2017

Migrate code first solution - Entity Framework

Fire up package manager console
























Type Enable-Migrations









A Migration folder will get created in your solution


Do the code changes you need to do for the entities. In my case I have added a new property as BirthDate to my Student class

Then in the Package Manager Window, type Add-Migration with a custom name which you would like to be referred to on the solution. In the solution explorer window, you would see a new file which has been created now.



Then run the update command to update the DB like below. Your changes will get reflected in the Database




Friday, February 3, 2017

DAX queries in Power BI

The acronym DAX stands for Data Analysis Expressions. DAX is a set of functions, operators, and constants which can be used to construct formulas from existing information in your data store. if you are familiar with creating functions in Excel that knowledge comes in handy to create DAX functions.

An example for DAX function format would be like:

<MEASURE_NAME> = <DAX FUNCTION>(<TABLE_NAME>[<COLUMN_NAME>])
Eg:
Total sales = SUM(financials[sales])

Lets check out some of the DAX functions

DISTINCT
Distinct Cities = DISTINCT(Portfolio[City])

SUM
Total Sales = SUM(financials[sales])

SUMX
Allows to get the sum of an expression evaluated for each row in the table.
SUMX(<table>, <expression>)

FILTER
Filtered sales = FILTER(financials, financials[ Sales] > 100000)
Here you can create a new table to filter and get rows where sales are greater than 100000. The base table is 'financials'. The new table created is 'Filtered sales'.

CALCULATE
For this example you can refer to a sample table which I created. Refer the code in Annex for table creation.

total online sales = CALCULATE(SUM('Sales Types'[Amount]),FILTER('Sales Types','Sales Types'[Mode]="ONLINE"))

online sales 2010 = CALCULATE(SUM('Sales Types'[Amount]),FILTER('Sales Types','Sales Types'[Mode]="ONLINE"), 'Sales Types'[Year]="2010")

The total online sales put into a table would look like below


SUMMARIZE

Sales Summary = SUMMARIZE('Sales Types', 'Sales Types'[Region], "Sales per region", COUNT('Sales Types'[Amount]), "online sales count", CALCULATE(COUNT('Sales Types'[Mode]), FILTER('Sales Types','Sales Types'[Mode]="ONLINE")), "total online sales", 'Sales Types'[total online sales], "total store sales", 'Sales Types'[total store sales], "store sales count", CALCULATE(COUNT('Sales Types'[Mode]), FILTER('Sales Types','Sales Types'[Mode]="STORE")))



UNION
Union Test = UNION(SELECTCOLUMNS(Employees, "Lat", Employees[Lat], "Lon", Employees[Lon], "Type", "Employee"), SELECTCOLUMNS(Portfolio, "Lat", Portfolio[LAT], "Lon", Portfolio[LONG], "Type", "Office"))

In the last example above, I have used the UNION and SELECTCOLUMN function to get both office and employee locations in a hypothetical organization.

In order to visualize this sample you can create a new table and provide the function as shown below


















Annex

Sales Figures =
DATATABLE (
    "Year", STRING,
    "Asia", DOUBLE,
    "Europe", DOUBLE, "Australia", DOUBLE,
    "America", DOUBLE,
    {
        { "2010", 100000, 200000,80000, 100000 },
        { "2011", 400000, 250000,100000, 100000 },
        { "2012", 600000, 350000,150000, 100000 }
    }
)

Sales Types =
DATATABLE (
    "Year"STRING,
    "Region"STRING,
    "Amount"DOUBLE,
    "Mode"STRING,
    {
        { "2010", "Asia", 80000, "STORE"}, { "2010", "Asia", 25000, "ONLINE"}, { "2010", "Europe", 180000, "STORE"}, { "2010", "Europe", 125000, "ONLINE"}, { "2010", "Australia", 180000, "STORE"}, { "2010", "Australia", 125000, "ONLINE"},
        { "2011", "Asia", 80400, "STORE"}, { "2011", "Asia", 35000, "ONLINE"}, { "2011", "Europe", 185000, "STORE"}, { "2011", "Europe", 145000, "ONLINE"}, { "2011", "Australia", 175000, "STORE"}, { "2011", "Australia", 227500, "ONLINE"},
{ "2012", "Asia", 90000, "STORE"}, { "2012", "Asia", 45000, "ONLINE"}, { "2012", "Europe", 190500, "STORE"}, { "2012", "Europe", 115000, "ONLINE"}, { "2012", "Australia", 180000, "STORE"}, { "2012", "Australia", 145000, "ONLINE"},
{ "2013", "Asia", 94500, "STORE"}, { "2013", "Asia", 15000, "ONLINE"}, { "2013", "Europe", 194000, "STORE"}, { "2013", "Europe", 95000, "ONLINE"}, { "2013", "Australia", 200000, "STORE"}, { "2013", "Australia", 195000, "ONLINE"},
{ "2014", "Asia", 110000, "STORE"}, { "2014", "Asia", 225000, "ONLINE"}, { "2014", "Europe", 185000, "STORE"}, { "2014", "Europe", 120000, "ONLINE"}, { "2014", "Australia", 205000, "STORE"}, { "2014", "Australia", 225000, "ONLINE"}
    }
)

Thursday, February 2, 2017

Understanding Measures in Power BI

Measures are numbers created to create graphs. Power BI calculates and returns values according to the types of aggregation we choose for the measure. We can also create our own measures to perform complex or specific calculations.

You can create your own measures with the Data Analysis Expressions (DAX) formula language. DAX formulas are similar to Excel formulas.

In the below sample I created a new measure as 'Gross Profit'

Click on the table which you intend to create a measure, and select 'New measure'


Define the formula on the newly created measure. Note that you get IntelliSense to assist you with the formula creation.


Now you can create a graph for the 'gross Profit' by location using the created measure. Drag and drop the two related columns to the reports page


Wednesday, February 1, 2017

An Introduction to Power BI

Power BI software has a Desktop application, a web application and a mobile version. First il give an intro on the Desktop version, then will publish whats created using the desktop to the web app.

For data import you have many options. Excel and SQL data sources are mainly used by businesses.

If you choose SQL Server, then you will have to provide server details and authentication parameters. Also there are two data connectivity modes. They are Direct & Import. If you choose import the copy of the data source will be stored at Power BI, else it will directly query from db as the name implies.

The panes
In the Reports view there are two panes, namely Visualization & Fields pane. The fields pane shows the table and colum details associated with the Power BI project. So when you import from a data source the table information will be visible there. You can use the visualization pane to showcase the information in your table in chart formats and etc..


Views
There are three main views. They are Report, Data & Relationships. You can use each view update the data set. The relationship view allows you to add relationships between the data tables.



Once you are done doing the visualizations hit Publish button in the Home tabs menu. Then the project gets published to the web.


In the web site you can generate quick insights for the project. Click on the three dots which appear on your data set (in this example it's 'Sales by country'). then Power BI starts generating the insights. The result will be something similar to below.


Monday, January 23, 2017

Angular JS - Control form submit when input controls have validation errors

Did you happen to come across this scenario while using AngularJS, where you cannot stop the form being submitted even when the input controls have validation errors? Follow the below updates.

Remove the save data method from the button control. And control to the form using ng-submit

Old code

<input type="button" value="Save" name="Save" ng-click="vm.mySaveFunction()" />

Updated form code

<form name="mySampleForm" ng-submit="mySampleForm.$valid && vm.mySaveFunction()">

<input type="submit" value="Save" name="Save" />

Thursday, January 19, 2017

AngularJS ng-repeat creates a hashKey for the items in the loop

Scenario:
You load data from an Xml file and display it on your web page. You use a angular repeater (ng-repeat) to loop through the data blocks in the Xml file. After the user changes the input values you submit the data back for saving (may be back to a SharePoint document library to update the residing Xml file).

Result:
When trying to save the file back, you get an error as "Input string was not in a correct format". The Xml file in the SP library does not get updated.

Cause: 
When you inspect the updated Xml you may see that there is a hash key generated for each item with in the Xml blocks where we used the repeater.

 Example:

<Block>
   <Details>
     <Record></Record>
     <Description></Description>
     <Duedate></Duedate>
     <Cost></Cost>
   </Details>

   <$$hashKey>object:94</$$hashKey>
</Block>

<Block>
   <Details>
     <Record></Record>
     <Description></Description>
     <Duedate></Duedate>
     <Cost></Cost>
   </Details>

   <$$hashKey>object:95</$$hashKey>
</Block>

In the page your repeater attributes might look like below:

<div ng-repeat="Block in vm.data.Block">

The reason why the hash keys are generated is, because AngularJS needs to keep track of the items with in the repeater, so that it can update the DOM when necessary.

Solution:
Use a child node inside the block to keep track of the items in the repeater. You can use "track by" for this purpose. Since this provides a tracking mechanism, AngularJS will not generate the hash keys anymore.

Example 1:
<div ng-repeat="blockItem in vm.data.Block track by blockItem.Record">

Note that here I have used Record field which is unique. If you don't have any such child nodes having unique values, use the below code

Example 2:
<div ng-repeat="blockItem in vm.data.Block track by $index">