Monday, 23 June 2008

Programmatically adding reports in MSCRM v4

New in v4, lots more objects are now system entities within MSCRM, including REPORTS. This means that you have lots more control and flexibility in manipulating reports in code, so I was surprised that I couldn't find good examples for uploading them. In case anyone else is looking for an example, I'm posting this...

Back in v3 we used publish.config as a convenient way of itemising the reports of interest and how we wanted them installed, so I have used the same file, adding only one more attribute [@parentname] as v4 is more picky in this regard.

You will notice I'm using the xpath navigator rather than the xmldocument in order to pre-sort the reports and ensure that the parentreports get created first! There are probably better/more elegant ways of doing some parts for which comments are gladly received.

Enjoy!

Addendum:You need to set the languagecode in order to get them to show in all views, plus there are some useful other params for maintaining/updating the reports which could be added as attributes to the config file.

rpt.languagecode = new CrmNumber(1033);
rpt.signatureid = new UniqueIdentifier(Guid.NewGuid());
rpt.signaturedate = new CrmDateTime("2008/06/23");
rpt.signaturemajorversion = new CrmNumber(4);
rpt.signatureminorversion = new CrmNumber(0);
rpt.signaturelcid = new CrmNumber(1033);



string cfgfile = "publish.config";
string rptfile = "";

#region Open config and sort reports

//open the config file and sort the report nodes
XPathDocument doc = new XPathDocument(cfgfile);
XPathNavigator nav = doc.CreateNavigator();
XPathExpression xrpts = nav.Compile("//report");
xrpts.AddSort("@parentname", XmlSortOrder.Ascending, XmlCaseOrder.None, "", XmlDataType.Text);

#endregion

foreach (XPathNavigator xrpt in nav.Select(xrpts))
{//load each report inc parent link and related as necessary
rptfile = xrpt.GetAttribute("filename", "");
report rpt = new report();

#region Set report parameters

using (StreamReader reader = new StreamReader(rptfile))
{
rpt.bodytext = reader.ReadToEnd();
}
rpt.iscustomreport = new CrmBoolean(false);
rpt.ispersonal = new CrmBoolean(false);
rpt.isscheduledreport = new CrmBoolean(false);
rpt.name = xrpt.GetAttribute("name", "").ToString();
rpt.description = xrpt.GetAttribute("description", "").ToString();
rpt.reporttypecode = new Picklist(ReportTypeCode.ReportingServices);
rpt.filename = rptfile;

#endregion

#region Set the parent link if necessary

string pn = xrpt.GetAttribute("parentname", "");
if (pn != "")
{//get the Id of the first matching parent report
FilterExpression flt = new FilterExpression();
flt.Conditions.Add(new ConditionExpression("name", ConditionOperator.Like, pn));
QueryExpression qry = new QueryExpression(EntityName.report.ToString());
qry.Criteria = flt;
report prpt = (report)service.RetrieveMultiple(qry).BusinessEntities[0];
rpt.parentreportid = new Lookup(EntityName.report.ToString(), prpt.reportid.Value);
}

#endregion

Guid rptId = service.Create(rpt);

#region Execute SetReportRelatedRequest
SetReportRelatedRequest rrReq = new SetReportRelatedRequest();
rrReq.ReportId = rptId;

#region Set the categories for the report

string[] cats = xrpt.GetAttribute("category", "").Split(';');
ArrayList catsi = new ArrayList(); int tmp = 0;
for (int i = 0; i < cats.Length; i++)
{
int.TryParse(cats[i], out tmp);
catsi.Add(tmp);
}
rrReq.Categories = (int[])catsi.ToArray(typeof(int));

#endregion

#region Set the relationships for the report

string[] rents = xrpt.GetAttribute("relatedentity", "").Split(';');
ArrayList rentsi = new ArrayList();
if (rents.Length != 0)
{
for (int i = 0; i < rents.Length; i++)
{//get the OTC for each related entity
RetrieveEntityRequest req = new RetrieveEntityRequest();
req.RetrieveAsIfPublished = true;
req.LogicalName = rents[i];
req.EntityItems = EntityItems.EntityOnly;
RetrieveEntityResponse res = (RetrieveEntityResponse)mservice.Execute(req);
EntityMetadata entMdata = res.EntityMetadata;
rentsi.Add(entMdata.ObjectTypeCode.Value);
}
}
rrReq.Entities = (int[])rentsi.ToArray(typeof(int));

#endregion

#region Set the visibility for the report

string[] viss = xrpt.GetAttribute("showin", "").ToString().Split(';');
ArrayList visi = new ArrayList();
for (int i = 0; i < viss.Length; i++)
{
switch (viss[i])
{
case "reports": visi.Add(ReportVisibilityCode.ReportsGrid); break;
case "entity": visi.Add(ReportVisibilityCode.Grid); break;
case "form": visi.Add(ReportVisibilityCode.Form); break;
}
}
rrReq.Visibility = (int[])visi.ToArray(typeof(int));

#endregion

// Execute the request.
SetReportRelatedResponse reportRelatedResponse = (SetReportRelatedResponse)service.Execute(rrReq);

#endregion

}

No comments: