Rollup fields in CRM are updated asynchronously ever 1 hr.
you can manually refresh individual rollup field on form by clicking
refresh button, but some time we need to refresh all rollup fields on form in
single click.
To do this
1. Create custom
workflow activity which will calculate all roll up fields and update values.
To calculate
rollup fields you can use CalculateRollupFieldRequest message,
and pass it to Execute.
Custom workflow
activity code
using System;
using System.Activities;
using System.ServiceModel;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Workflow;
using System.Linq;
using System.Collections.Generic;
using Microsoft.Crm.Sdk.Messages;
public sealed class CalculateRollupStatistics : CodeActivity
{
///
///
/// The execution
context.
[RequiredArgument]
[Input("Company")]
[ReferenceTarget(new_company.EntityLogicalName)]
public InArgument<EntityReference>
iCompany { get; set; }
protected override void Execute(CodeActivityContext executionContext)
{
// Create the
context
IWorkflowContext context =
executionContext.GetExtension<IWorkflowContext>();
if (context == null)
{
throw new InvalidPluginExecutionException("Failed to retrieve workflow context.");
}
IOrganizationServiceFactory serviceFactory =
executionContext.GetExtension<IOrganizationServiceFactory>();
IOrganizationService service =
serviceFactory.CreateOrganizationService(context.UserId);
try
{
EntityReference companyReference
= iCompany.Get(executionContext);
List<string>
rollupAttributes = new List<string>() {"new_totalnoOfvehicals","new_totalcars","new_totalTrucks","new_totalbickes","new_totalbuses" };
foreach (string attribute in rollupAttributes)
{
CalculateRollupFieldRequest reqUpdateRollup
= new CalculateRollupFieldRequest
{
FieldName = attribute,
Target = companyReference
};
service.Execute(reqUpdateRollup);
}
}
catch (FaultException<OrganizationServiceFault> e)
{
throw;
}
}
}
2. Now create one
real time workflow for entity where wants to update rollup fields and call
created custom workflow activity.
3. Set workflow,
Available to Run =
No need to
set any option for Automatic processes.
4. Now Create HTML
web resource
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="../jquery_1.10.2.js" type="text/javascript"></script>
<script>
function RefreshCount() {
var url =
parent.Xrm.Page.context.getClientUrl();
var recordId =
parent.Xrm.Page.data.entity.getId();
var workflowId = "aa63b391-0001-4f49-9ef3-700957cf8d0d";
var request = "< s:Envelope
xmlns:s='http://schemas.xmlsoap.org/soap/envelope/'>" +
"< s:Body>" +
"< Execute
xmlns='http://schemas.microsoft.com/xrm/2011/Contracts/Services'
xmlns:i='http://www.w3.org/2001/XMLSchema-instance'>" +
"< request i:type='b:ExecuteWorkflowRequest'
xmlns:a='http://schemas.microsoft.com/xrm/2011/Contracts'
xmlns:b='http://schemas.microsoft.com/crm/2011/Contracts'>" +
"< a:Parameters
xmlns:c='http://schemas.datacontract.org/2004/07/System.Collections.Generic'>" +
"< a:KeyValuePairOfstringanyType>" +
"< c:key>EntityId
" +
"< c:value i:type='d:guid'
xmlns:d='http://schemas.microsoft.com/2003/10/Serialization/'>" + recordId + "
" +
"< /a:KeyValuePairOfstringanyType>" +
"< a:KeyValuePairOfstringanyType>" +
"< c:key>WorkflowId
" +
"< c:value i:type='d:guid'
xmlns:d='http://schemas.microsoft.com/2003/10/Serialization/'>" + workflowId + "
" +
"< /a:KeyValuePairOfstringanyType>" +
"< /a:Parameters>" +
"< a:RequestId i:nil='true' />" +
"< a:RequestName>ExecuteWorkflow
" +
"< /request>" +
"< /Execute>" +
"< /s:Body>" +
"< /s:Envelope>";
var req = new XMLHttpRequest();
req.open("POST", url + "/XRMServices/2011/Organization.svc/web", true);
req.setRequestHeader("Accept", "application/xml, text/xml, */*");
req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
req.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute");
req.onreadystatechange
= function () {
if (req.readyState == 4) {
if (req.status == 200) {
parent.Xrm.Utility.openEntityForm("Entity Logical Name", recordId);
}
else {
alert('Unable to calculate');
}
}
};
req.send(request);
}
</script>
</head>
<body>
<div>
<table style="width:50%">
<tr>
<td style="text-align: right"> <input id="btnRecalculate" type="button" value="Recalculate" onclick="RefreshCount()" /></td>
<td></td>
</tr>
</table>
</div>
</body>
</html>
In above code
replace Workflow Id with your real time workflow Id and Entity name with your
entity name.
5. Add this
web resource on Form where you want to show button.
6. Save and
publish Web resource, form and activate workflow.
Now when you click
on Recalculate button, roll up attributes count will be recalculated and entity
form refreshed to show latest result.
I sure am going to try this next week! We have 5 rollup fields in a form and need up-to-date calcuations.
ReplyDeleteThanks for this!
Any way we could run the workflow on Save? Would be awesome!
ReplyDeleteYou can run workflow on save. You need to set workflow Start When = Record Fields Change, and select Modified On & Modified By fields.
DeleteWhen record is saved both fields will be updated (If there is any change in form), and workflow will be executed.
Wow, I wonder how I did not think of that! Thanks very much. The plugin works A1!!
Delete