WΛЯИING's blog

The deepest secrets of Visual Basic ...

Crystal Reports : Point sur le déploiement

December 4, 2009 12:37 by WΛЯИІNG

Avant Visual Studio 2008 :

J'écris cet article car les solutions de déploiement d'une application .Net employant Crystal Reports ont quelques peux évoluées depuis Visual Studio 2008. En effet afin de déployer son application avec les librairies de Crystal Reports il suffisait d'ajouter les « merge modules » ou modules de fusion suivant à son projet d'installation et de déploiement :

  • Crystal Reports 2003 :
    • Crystal_Database_Access2003.msm
    • Crystal_Database_Access2003_enu.msm
    • Crystal_regwiz2003.msm
  • Crystal Reports 2005 :
    • CrystalReportsRedist2005_x86.msm

L'idée des merge modules de pouvoir intégrer facilement des fichiers et librairies supplémentaire à une solution de déploiement/installation.

Après Visual Studio 2008 :

Cette solution n'est plus d'actualité avec Crystal Reports 2008 qui ne s'intègre plus aussi facilement à un package de déploiement .Net, il faut désormais inclure l'installation des composants Crystal Reports au processus d'installation de votre application, en plus de votre propre solution de déploiement. Ces fichiers sont inclus à l'installation de Visual Studio 2008 et disponibles dans les dossiers suivants :

Crystal Reports Basic for Visual Studio 2008 (x86)

C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bootstrapper\Packages\CrystalReports10_5\CRRedist2008_x86.msi

Crystal Reports Basic for Visual Studio 2008 (x64)

C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bootstrapper\Packages\CrystalReports10_5\CRRedist2008_x64.msi

Crystal Reports Basic for Visual Studio 2008 (IA64)

C:\Program Files\Microsoft Visual Studio 9.0\Crystal Reports\CRRedist\IA64\CRRedist2008_ia64.msi

Il est également possible d'obtenir les fichiers d'installation de Crystal Reports, toutes versions confondu via le site de l'éditeur http://service.sap.com/sap/bc/bsp/spn/bobj_download/main.htm.

Et Crystal Reports dans Visual Studio 2010 ?

Ceux qui utilisent la version bêta de Visual Studio 2010 l'auront remarqué, Crystal Reports est tout simplement absent. Pour les inquiets, Scott Nonnenberg (Program Manager, Visual C# Team) a annoncé que Crystal Reports for Visual Studio 2010 sera publié séparément au lieu d'être inclus directement dans Visual Studio.

Plus d'informations par ici :

http://msdn.microsoft.com/en-us/library/aa288411(VS.71).aspx

http://msdn.microsoft.com/en-us/library/ms225231.aspx

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Tags:
Categories: Crystal Reports | .Net
Actions: E-mail | Permalink | Comments (0) | Comment RSSRSS comment feed

C#: Adding many SortField to a CrystalReportViewer using reflection

April 9, 2009 22:16 by WΛЯИІNG

I'm currently working on a project for a client which consists in translating an important management application initially developed in VB6, into C# 3.5, by using decompilation since the client lost his source code. This is my first .Net related post.

The application uses many external components, including the powerful Crystal Report component.

During the development of that new version I faced a problem with the .Net implementation of Crystal Report.

Actually, with Visual Basic 6.0 it was an easy task to add one or many sort fields to the report document in order to sort the result by field (for example by "Lastname", "Firstname", and "ID").

It's not the case with .Net implementation of Crystal Report Document, on which you cannot dynamically add sort field to document. You must add the sort field when you're editing the document. It's not really convenient when you don't know how many fields must be sorted when creating the document.

The reason of this missing is not really clear since it's an existing feature on Visual Basic 6.0. We will learn here how to add many SortField to the ReportDocument of a CrystalReportViewer, using reflection.

Imagine you have to sort the request's result by "Firstname", "Lastname", and "ID" fields, using the Crystal report document with the variable "Filename" as the report document path, and the variable "srcDataSet" dataset as the data source:

string[] sortFieldNames = new string[] { "Firstname", "Lastname", "ID" };

ReportDocument
reportDocument = new ReportDocument();

reportDocument.FileName = String.Format("rassdk://{0}", Filename);

reportDocument.SetDataSource(srcDataSet.Tables[0]);

SortFields targetSortField = reportDocument.DataDefinition.SortFields;

Here we can modify the sort field (only if existing in the document):

DatabaseFieldDefinition fieldDef = reportDocument.Database.Tables["REPORTS"].Fields["FIRSTNAME"];

targetSortField[0].Field = fieldDef;

targetSortField[0].SortDirection = CrystalDecisions.Shared.SortDirection.AscendingOrder;

But impossible to add directly a new field to that SortFields collection because no method allows performing action:

pic1

Actually, it's possible to add a new sort field using the mother inherited class of each used component.

First we get the "SortFields" mother's class of type (CrystalDecisions.ReportAppServer.DataDefModel.SortsClass ) by using the RasSorts private accessor of the SortFields object:

MethodInfo getRasSorts = targetSortField.GetType().GetMethod("get_RasSorts", BindingFlags.NonPublic | BindingFlags.Instance);

object rasSorts = getRasSorts.Invoke(targetSortField, System.Type.EmptyTypes);

It return an object of type CrystalDecisions.ReportAppServer.DataDefModel.SortsClass.

Now we can access to the private "Add" method of the mother's class:

MethodInfo addSort = rasSorts.GetType().GetMethod("Add");

The description of that method show that it accept one parameter of type CrystalDecisions.ReportAppServer.DataDefModel.ISCRSort.

pic2 

ISCRSort is an interface, so we have to create a new instance of a class that implement the ISCRSort interface. That class is called "SortClass" and come from the "CrystalDecisions.ReportAppServer.DataDefModel" assembly.

Assembly rasAssembly = getRasSorts.ReturnType.Assembly;

ConstructorInfo ciRasSort = rasAssembly.GetType("CrystalDecisions.ReportAppServer.DataDefModel.SortClass").GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, System.Type.EmptyTypes, null);

object rasSort = ciRasSort.Invoke(System.Type.EmptyTypes);

Our "rasSort" object now instantiate the SortClass class, implementing ISCRSort.
Once the SortClass object is created, we must complete it with valid field, else it will return an error on execution.

The SortClass class uses the "RasField" accessor to define the field which will be sorted.

MethodInfo setSortField = rasSort.GetType().GetMethod("set_SortField", BindingFlags.Public | BindingFlags.Instance);

But this method only accepts an object implementing the ISCRField interface:
Void set_SortField(CrystalDecisions.ReportAppServer.DataDefModel.ISCRField);

So we have to extract the object of our field object (called fieldDef) that implement the ISCRField interface, it can be done with the "RasField" accessor of our DatabaseFieldDefinition object called "fieldDef":

MethodInfo getRasField = fieldDef.GetType().GetMethod("get_RasField", BindingFlags.NonPublic | BindingFlags.Instance);

object rasField = getRasField.Invoke(fieldDef, System.Type.EmptyTypes);

And now, the final touch, we add it to the collection:

addSort.Invoke(rasSorts, new object[] { rasSort });

Your new sort field has been adding to the SortFields collection, and you can now modify it:

int n = reportDocument.DataDefinition.SortFields.Count - 1;

reportDocument.DataDefinition.SortFields[n].SortDirection = CrystalDecisions.Shared.SortDirection.AscendingOrder;
reportDocument.DataDefinition.SortFields[n].Field = fieldDef;

That's all.

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList