ASPNL logo (1 kb)
zaterdag 17 mei 2008




Microsoft MVP

.NET Codewise Community
<< vorige | overzicht | volgende >>

Crystal Reports gebruiken in ASP.NET

Door Tim Musschoot
27 maart 2002

Eén van de vele handige opties die ASP.NET en Visual Studio .NET ons bieden is ongetwijfeld Crystal Reports. Dit product is een gevestigde orde als het aankomt op het maken van reports. Op een eenvoudige manier maakt u een visuele voorstelling van uw data in de vorm van charts, listings, etc… De beperkte controle op het afdrukbeheer van uw webpagina’s en de bijhorende browser afhankelijke mogelijkheden worden volledig aan de kant geschoven. De Crystal Reports component geeft u volledige controle over hoe uw report er in afgedrukte vorm uit zal zien.

Het is niet de bedoeling van dit document om de verschillende mogelijkheden van Crystal Reports uit de doeken te gaan doen. Hiervoor verwijzen we naar de bijhorende website van het product. Wel is het de bedoeling om aan de hand van een voorbeeld de creatie van een dergelijke report en de incorporatie ervan in uw website te demonstreren. De gebruikte ontwikkelomgeving is Microsoft Visual Studio .NET. De gebruikte programmeertaal is C#.

1. Aanmaak van de report

In deze sectie wordt van het standpunt vertrokken dat u een C# ASP.NET webproject hebt aangemaakt en dat u in één van de pagina’s een report wilt weergeven. Om een report te kunnen weergeven moeten we natuurlijk eerst zo’n report aanmaken.

Om een nieuwe report toe te voegen aan het project kiest u uit het menu de optie Project | Add new Item. Uit het volgende dialoogvenster selecteert u het Crystal Reports item.

Indien u deze optie niet tegenkomt controleert u best de installatieopties van Visual Studio. U moet Crystal Reports for Visual Studio .NET geďnstalleerd hebben. Wanneer u op de Open knop klikt worden er automatisch een nieuwe report en een bijhorende C# klasse aangemaakt. Deze klasse representeert de report in uw website. Ze heeft de zelfde naam als uw report.

Vervolgens past u de report aan aan uw behoeften. Hiervoor wordt integraal verwezen naar de MSDN sectie over Crystal Reports en de manuals van de ontwikkelaars van Crystal Reports.

In ons voorbeeld werd een report gemaakt dat via een ADO.NET dataset zijn gegevens ophaalt. Daarnaast zijn er een aantal specifieke velden die moeten ingevuld worden bij de weergave van de report. Dit is wat de field explorer toont:

De dataset bevat een table met als naam W_ORDERITEMS.

2. De ReportViewer

Eenmaal een report werd aangemaakt is het de bedoeling deze in een webpagina in te voegen. Hiervoor maakt u een nieuwe Webform pagina aan of kiest u een bestaande pagina. Voor dit voorbeeld werd een nieuwe Web Form aangemaakt met als naam showorder.aspx. In het “Web Forms” gedeelte van de Toolbox vindt u de component die voor de weergave van de report zal zorgen.

Die plaatst u op uw pagina. Wanneer u de HTML code van uw pagina opvraagt ziet u dat volgende code werd toegevoegd na het invoeren van de component. De opties DisplayGroupTree en SeparatePages werden via de property inspector toegevoegd om de weergave te verbeteren. (meer hierover in de MSDN help over Crystal Reports).

<CR:CrystalReportViewer id="CrystalReportViewer1" runat="server" Width="350px" Height="50px" DisplayGroupTree="False" SeparatePages="False" />

Wat nu toegevoegd werd is een component die het mogelijk maakt om Crystal reports weer te geven in een .aspx pagina. We hebben echter nog niet aangegeven welke pagina we wensen weer te geven. Hiervoor openen we het bestand myreport.cs. Dit bevat alle code die aan de pagina myreport.aspx is verbonden.

Om de report zoals die werd aangemaakt weer te geven moeten we aan de CrystalReportViewer aangeven welk report we wensen te tonen. Dit gebeurt door de property CrystalReportViewer1.ReportSource in te vullen. Dit gebeurt in de Page_Load(…) member functie. Deze ziet er als volgt uit:

private void Page_Load(object sender, System.EventArgs e)
{
   SqlConnection cn = new
   SqlConnection(SQLConnStr);
   cn.Open();
   String SqlStr = "SELECT W_ORDERITEMS.* ";
   SqlStr += "FROM W_ORDERS, W_ORDERITEMS ";
   SqlStr += "WHERE (W_ORDERITEMS.ORDERID = W_ORDERS.ID) ";

   SqlDataAdapter da = new SqlDataAdapter(SqlStr,cn);
   DataSet ds = new DataSet("W_ORDERITEMS");
   da.Fill(ds,"W_ORDERITEMS");

In eerste instantie moeten we een dataset vullen met de gegevens die we in de report wensen weer te geven. In dit voorbeeld werd voor een dataset gekozen, maar het kan evengoed om een SQL query binnen uw report gaan. De structuur van de dataset dient identiek te zijn als degene die je gekozen hebt in uw report. Hiermee wordt het merendeel van de gegevens in uw report ingevuld.

Bij de creatie van het report werd gesproken dat er ook een aantal parameter fields aanwezig zijn. Dit zijn velden met variabele inhoud die at runtime kunnen worden ingevuld. Het aangemaakte report is een bestelbon van een online aankoop. Deze parametervelden bevatten specifieke gegevens van de persoon die de bestelling plaatste en tevens van de bestelling zelf. Deze gegevens moeten worden ingevuld voor de report aan de report-viewer wordt gekoppeld. Dit kunt u zien in het vervolg op de code.

   ParameterFields fields = new ParameterFields();
   AddParameter("clientname","test",fields);
   AddParameter("clientaddress","test",fields);
   AddParameter("clientcity","test",fields);
   AddParameter("orderdate","test",fields);
   AddParameter("deliverydate","test",fields);
   AddParameter("ordernr","123",fields);

Alle parameters moeten worden ingevuld. Indien u dit niet doet wordt bij de weergave een fout gegenereerd. De functie AddParameter is een zelfgeschreven functie die het proces van parameters toevoegen wat gebruiksvriendelijker maakt. De bijhorende code vindt u iets verder in deze sectie.

Als u eenmaal alle gegevensstructuren hebt opgebouwd kunt u deze koppelen aan de report viewer.

   CrystalReportViewer1.ParameterFieldInfo = fields;
   myreport bon = new myreport();
   bon.SetDataSource(ds);
   CrystalReportViewer1.ReportSource = bon;
}

In de laatste fase van dit koppelproces wordt de report zelf (myreport) aan de viewer gekoppeld. De klasse myreport werd automatisch gegenereerd bij het aanmaken van een report.

Een sleutelfunctie wordt vervuld door de functie AddParameter.

private ParameterFields AddParameter( string paramName,
            string paramValue,
         ParameterFields paramFields)
{
   ParameterField paramField= new ParameterField ();
   ParameterDiscreteValue paramDiscreteValue = new
         ParameterDiscreteValue ();
   ParameterValues paramValues = new ParameterValues ();
   'Set the name of the parameter to modify.
   paramField.ParameterFieldName = paramName;
   'Set a value to the parameter.
   paramDiscreteValue.Value = paramValue;
   paramValues.Add (paramDiscreteValue);
   paramField.CurrentValues = paramValues;
   'Add the parameter to the ParameterFields collection.
   paramFields.Add (paramField);
   return paramFields;
}


Wanneer u nu uw pagina compileert en opent in uw browser ziet u uw report met de ingevulde waarden.

3. Exportmogelijkheden

Bij de weergave van uw report bent u gebonden aan de mogelijkheden die HTML u biedt. Indien u uw report wenst af te drukken bent u nog steeds gebonden aan de mogelijkheden die uw browser u biedt. Inclusief de instellingen voor marges, kopteksten, etc…

Wanneer u alle moeite gedaan hebt om een degelijk report te maken hebt u er geen behoefte aan om de layout te laten verstoren door deze details. Een mogelijke oplossing hiervoor is uw report in een ander (beter) formaat om te zetten en door de gebruiker te laten downloaden. Deze kan het dan afdrukken of in zijn digitale vorm bewaren. De meest gebruikte opties (waarbij er tevens het minst van de layout verloren gaat) zijn PDF en RTF. De conversie gebeurt op de server. Bij het openen wordt uw report dan naar clientside gedownloaded.

Het exporteren kan bijvoorbeeld gebeuren wanneer de gebruiker op een knop op de webpagina klikt. Hieronder wordt de code in detail besproken.

   String ReportName = @"c:\myreport.rpt" ;
   ReportDocument Doc = new ReportDocument();
         Doc.Load(ReportName,OpenReportMethod.OpenReportByTempCopy);

Om een report te converteren maken we een nieuwe instantie aan van het ReportDocument object. Hiervan zijn alle reports afgeleid, en dus ook myreport. Onze report wordt in het object geladen. De optie OpenReportByTempCopy slaat op het feit dat we het report in niet exclusieve mode wensen te openen.

In een volgende fase gaan we opnieuw de gegevens aan de report binden. Op dezelfde manier als de dataset werd gebonden aan de report in de Page_Load functie zal men deze opnieuw aan de report binden.

Het binden van de parameter fields gebeurt enigszins anders. Deze worden meegegeven aan de ReportDocument.DataDefinition.ParameterFields collectie. Hieronder ziet u hoe dit gebeurt.

   DataDefinition DataDef = Doc.DataDefinition;
   ParameterFieldDefinitions Defs = DataDef.ParameterFields;

   ParameterDiscreteValue paramDiscreteValue = new ParameterDiscreteValue();
   ParameterValues currentValue = new ParameterValues();

   paramDiscreteValue.Value = "test";
   currentValue.Add(paramDiscreteValue);
   Defs["clientname"].ApplyCurrentValues(currentValue);

   paramDiscreteValue = new ParameterDiscreteValue();
   currentValue = new ParameterValues();
   paramDiscreteValue.Value = "test";
   currentValue.Add(paramDiscreteValue);
   Defs["clientaddress"].ApplyCurrentValues(currentValue);

   paramDiscreteValue = new ParameterDiscreteValue();
   currentValue = new ParameterValues();
   paramDiscreteValue.Value = "test";
   currentValue.Add(paramDiscreteValue);
   Defs["clientcity"].ApplyCurrentValues(currentValue);

   paramDiscreteValue = new ParameterDiscreteValue();
   currentValue = new ParameterValues();
   paramDiscreteValue.Value = "test";
   currentValue.Add(paramDiscreteValue);
   Defs["orderdate"].ApplyCurrentValues(currentValue);

   paramDiscreteValue = new ParameterDiscreteValue();
   currentValue = new ParameterValues();
   paramDiscreteValue.Value = "test";
   currentValue.Add(paramDiscreteValue);
   Defs["deliverydate"].ApplyCurrentValues(currentValue);

   paramDiscreteValue = new ParameterDiscreteValue();
   currentValue = new ParameterValues();
   paramDiscreteValue.Value = "test";
   currentValue.Add(paramDiscreteValue);
   Defs["ordernr"].ApplyCurrentValues(currentValue);

Waar u vooral dient op te letten bij het invullen van de parameters is, is dat u dit doet via de ApplyCurrentValues(…) functie. De collecties zijn namelijk readonly. Alle ander mogelijkheden om de items toe te voegen geven geen resultaat, maar leiden ook niet noodzakelijk tot een foutmelding !!

In de laatste fase gaat u instellen naar welk bestandstype u de report wenst te converteren. In dit voorbeeld gebruiken we een .RTF document. Onderstaande code spreekt voor zich.

   DiskFileDestinationOptions Dest = new DiskFileDestinationOptions();
   Doc.ExportOptions.ExportDestinationType = ExportDestinationType.DiskFile;
   Doc.ExportOptions.ExportFormatType = ExportFormatType.RichText;

   Dest.DiskFileName= @"C:\Inetpub\wwwroot\crystal\output.rtf";

   Doc.ExportOptions.DestinationOptions = Dest;
   Doc.Export();
   Doc.Close();

   Response.Redirect(Dest.DiskFileName);

Het is heel belangrijk dat het pad waarin u het resultaat wenst te schrijven toegankelijk is. Meer hierover in de volgende sectie. Wanneer u de Export() functie oproept wordt de report aangemaakt en naar het juiste formaat geconverteerd. Als voorbeeld werd het bestand geopend. Omdat het een .RTF document is zal het standaard naar de browser van de client worden verstuurd, waar het met Microsoft Word zal worden geopend (indien dit geďnstalleerd is op de client computer en indien deze optie niet geblokkeerd is). Wanneer u ondervindt dat de eerste report perfect werkt maar dat alles vanaf de tweede poging fout gaat, controleer dan of u Doc.Close() niet bent vergeten. Vooral de PDF export functie blijkt hier last van te hebben.

4. Foutmeldingen

Windows 2000 en XP gebruikers onder jullie weten ongetwijfeld dat de beveiligingen van het NTFS bestandssysteem wel eens voor problemen kunnen zorgen. Omdat Crystal Reports met bestanden werkt werd deze sectie aan dit document toegevoegd. Er kunnen nogal wat problemen ontstaan wanneer u vanuit uw ASP.NET pagina’s een bestand probeert te openen dat zich in een directory bevindt waartoe de .NET systeem geen toegang heeft.

Om dit te vermijden moet u de gebruiker aspwp_net lees en schrijfpermissies heeft tot alle directories van uw applicatie en tot de directories waar u uw reportfiles haalt en wenst te exporteren. Deze gebruiker vindt u terug onder de naam <SERVERNAAM>\ASPNET. De foutmelding die veroorzaakt wordt doordat het ASP.NET systeem geen toegang krijgt tot de bestanden zegt dat het bestand niet geopend kanworden omdat het misschien door een andere toepassing in exclusieve mode werd geopend.

Indien u andere foutmeldingen krijgt kunt u op de FAQ terecht van Crystal Reports.

copyright 2002 Tim Musschoot

<< vorige | ^ naar boven | overzicht | volgende >>
copyright 2000-2007 ASPNL