Sunday, October 14, 2012

Crystal Reports, C#, Object as Data Source

Based on the Ping example from one of the recent posts, I'm continuing it with the Crystal Reports example, because I have never used Crystal Reports until now. So consider that the following class was added to the solution.

public class PingResult
{
 public string sPacketsSent;
 public string sPacketsReceived;
 public string sPacketsLost;
 public string sPacketTime;
}

An instance of the class is created and populated with results when the ping command runs and its results are parsed. So I have one of the simplest possible objects to use as a source for a report. The next step is to add a Crystal Report to the application. Visual Studio 2010 has an item to add called "Crystal Report", but they are not installed.

Crystal Report Online Template

When I select this item, I'm prompted with a download screen.

Download Crystal Reports

Installation is simple - just following the instructions. I chose the standard version, and the download size is 288MB. After a few short hours, I have a Crystal Report called pingReport.mht in my solution. I have an option to configure my report using the wizard, which I'm doing by choosing the following options:

On the first page, Using the Report Wizard, and Standard layout.

Create a New Crystal Report Document

On the next page, I choose to populate my report from .NET Object in project data. My PingResult class is in the list, and I move it to the Selected Tables.

Choose the data you want to report on

Then I choose the fields to display, of which I select all.

Choose the information to display on the report

I skip Grouping, Report Selection and Report Style, leaving default values. Now I have my report editor. I only want to do a little change - make the headers human readable, so I edit them in the following manner

Edit text object

Now some tricks: when I build my solution, I get the following error:

Warning 1 The referenced assembly "CrystalDecisions.CrystalReports.Engine, Version=13.0.2000.0, Culture=neutral, PublicKeyToken=692fbea5521e1304, processorArchitecture=MSIL" could not be resolved because it has a dependency on "System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" which is not in the currently targeted framework ".NETFramework,Version=v4.0,Profile=Client". Please remove references to assemblies not in the targeted framework or consider retargeting your project. PingTest

This is quite obvious, I need to add a reference to System.Web, but to do that I need to first change the Target Framework default setting of .NET Framework 4 Client Profile to just .NET Framework 4. Now the project builds.

In my toolbox I now have the pingReport1 component, which I add to the form.

pingReport1

I also need a report viewer, which I also add

CrystalReportViewer

The final effort: connect the report with the object that contains data. Here's how:

pingReport1 myReport = new pingReport1();
myReport.SetDataSource(new[] { pingResult });
pingReportViewer1.ReportSource = myReport;

Looks simple, just note how the objects are wrapped into array. This is important.

And the final trick, when I run the application, I get the FileNotFound exception

FileNotFoundException

which is resolved by adding the useLegacyV2RuntimeActivationPolicy="true" parameter to the startup node of my app.config which now looks like the following

<?xml version="1.0"?>
<configuration>
<startup  useLegacyV2RuntimeActivationPolicy="true">
  <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>

At this point I consider my small example complete.

Complete

References

Creating Crystal Reports using C# with Datasets
Very Odd situation with CrystalReport and/or Visual studio 2010 I don't know maybe .Net Framework
Can crystal reports get data from an object data source? by . Also posted on my website

1 comment:

Unknown said...

I know this is a fairly old article and I found the content to be exactly what I was looking for. I do have an issue of only getting every other record to come out on the report. The resultset from the query shows 50 records but writes every other record to the report. I can't seem to find why.