Home Page Home Page Articoli Integrare Crystal Reports con una Windows Form

Integrare Crystal Reports con una Windows Form

Ecco come sfruttare in modo semplice e rapido le funzionalità offerte dal tool di reportistica Crystal Reports di Business Objects all'interno di una Windows Form .NET, dalla crazione del Report al Binding dei dati.
Autore: Matteo Raumer Livello:
Quando ci si trova davanti alla necessità di stampe di dati aziendali, grafici e quant'altro quasi sempre si ricorre a strumenti di reportistica. Questo perchè sia con grandi sia con piccole moli di dati il le attività per visualizzare, impaginare, costruire, e fare manutenzione di stampe e Report sono sempre complicate e richiedono notevoli quantità di tempo se non supportate da designer efficienti.

Crystal Report, come tanti altri tool di reportistica, è uno strumento avanzato per costruire pagine che visualizzano una serie di dati, calcoli, grafici e con possibilita' di esportazione in vari formati come PDF,Excel e HTML che spesso sono le esigenze piu' richieste.

Con Visual Studio .NET viene integrata una versione "Embedded" di Crystal Report, il designer di report della BusinessObjetcs, completo di quasi tutte le funzionalita' del pacchetto "stand-alone", con il vantaggio di essere velocemente integrabile nelle nostre applicazioni.

Lo sviluppo di un Report e l'integrazione nella nostra applicazione, consiste sostanzialmente in due operazioni distinte:

1) La creazione del file ".rpt" tramite l'editor nel quale vengono salvate tutte le informazioni necessarie al runtime per generare l'anteprima.
2) La scrittura di codice .NET per caricare il report, passare i dati, e tipicamente visualizzarlo tramite il CrystalReportViewer (ma anche senza visualizzarlo potremmo usarlo direttamente per stamparlo, o esportarlo in qualche altro formato).

Aggiunto un Report ad un nostro progetto, ci dobbiamo preoccupare di fornirgli una sorgente dati con cui possiamo costruire il nostro risultato,operando sui campi a disposizione.
Tipicamente viene disegnato agganciando un database, ma è possibile anche dare Collections tipizzate basate su un nostri oggetti di Business, per questo articolo comunque, verra' usato un database Access come sorgente dati.

Al momento dell'aggiunta del Report, parte un Wizard che ci aiuta nella costruzione, quindi la prima cosa è scegliere la sorgente dati, qui possiamo dare un'intera tabella, o possiamo definire un comando/statement customizzato, ovvero una stringa SQL, o possiamo costruirla tramite un Query Builder:



Nel caso dovessimo cambiarla successivamente, la cosa è sempre possibile, basteà' entrare nella voce "Esperto Database" (DataBase Expert in inglese) e modificare il set di dati come mostrato nell'animazione seguente (cliccare sull'immagine Thumbnail per vedere l'animazione):



In questo esempio la Query che vogliamo è il classico "Master-Details" fatto utilizzando la LEFT JOIN a livello di Query. Perciò nel report avrà senso raggruppare (GROUP BY)i dati secondo uno dei campi comuni, in modo da avere una struttura gerarchica senza ricorrere ai Subreports che sono sicuramente più pesanti in fase di Rendering del Report:



Ora dobbiamo passare alla parte di codice .NET per integrarlo dentro alla nostra applicazione:
Il report è un oggetto del tipo ReportDocument, al quale bisogna dare la struttura del report,ovvero un File con estensione .rpt.
Dopodichè lo passiamo come proprieta' ReportSource ad un oggetto ReportViewer (oppure usare direttamente per altri scopi, ma tipicamente un viewer si usa quasi sempre per dare un'anteprima interattiva all'utente).

Codice .NET n°1
        ReportDocument report;
private void Form1_Load(object sender, EventArgs e)
{
report = new ReportDocument();
report.Load("ReportProducts.rpt");

CaricaDatiReport(report);

crystalReportViewer1.ReportSource = report;
crystalReportViewer1.RefreshReport();
}


private void filtraButton_Click(object sender, EventArgs e)
{
ReportDocument report = crystalReportViewer1.ReportSource as ReportDocument;
CaricaDatiReport(report);

report.RecordSelectionFormula = string.Empty;
if (logonRadioButton.Checked && !string.IsNullOrEmpty(cercaTextBox.Text))
report.RecordSelectionFormula = "{command.description} like '*" + cercaTextBox.Text + "*'";

crystalReportViewer1.RefreshReport();
}


A questo punto se mandiamo in esecuzione la nostra applicazione, il Report funziona correttamente, la cosa che pero' dobbiamo considerare è che adesso il report punta ad un percorso di dati che in fase di Deploy quasi sicuramente cambiera'. La cosa da fare perciò, è passare i dati al nostro oggetto Report, e qui abbiamo due metodi a disposizione:

1) Usare il metodo SetDataSource
2) Dare le impostazioni LogonInfo al Report, in modo che vada lui a recuperare i dati necessari

Con il primo metodo siamo noi da codice .NET a passare i dati al Report, dando una sorgente dati che abbia la stessa struttura di quelli con cui abbiamo costruito il Report. Qui di seguito un esempio:

Codice .NET n°2
        private DataTable GetDatiFromDatabase(string ricerca,bool dataset)
{
DataTable table = new DataTable();

if (dataset)
{
//--- versione DataSet
DatiDataSetTableAdapters.MiaQueryTableTableAdapter queryDataAdapter = new DatiDataSetTableAdapters.MiaQueryTableTableAdapter();
if (!string.IsNullOrEmpty(ricerca))
table = queryDataAdapter.GetDataByDescrizione("%" + ricerca + "%");
else
table = queryDataAdapter.GetData();
}
else
{
//--- versione ADO.NET
string stringaSelect =
" SELECT products.*,categories.Description, categories.Manager FROM products " +
" LEFT JOIN categories ON products.CategoryID = categories.ID";

if (!string.IsNullOrEmpty(ricerca))
stringaSelect = stringaSelect + " WHERE description LIKE '%" + ricerca + "%'";

using (OleDbConnection conn = new OleDbConnection(ConfigurationManager.ConnectionStrings["ReportVisualStudio.Crystal.Properties.Settings.dbConnectionString"].ConnectionString))
{
OleDbCommand command = conn.CreateCommand();
command.CommandText = stringaSelect;
conn.Open();
table.Load(command.ExecuteReader());
}
}

return table;
}


In questo esempio tra l'altro, si usano due strade anche con lo stesso metodo SetDataSource, ovvero caricare i dati in una DataTable, o usare i metodi di un DataSet tipizzato incluso nella nostra applicazione. Le prestazioni sono le stesse, dipende ovviamente da come è stata architettata l'applicazione in precedenza.

Codice .NET n°3
        private void CaricaDatiReport(ReportDocument report)
{

if (logonRadioButton.Checked)
{
//--- passaggio dati di connessione al db
TableLogOnInfo info = new TableLogOnInfo();
info.ConnectionInfo.ServerName = "db.mdb"; //--- di default lo cerca sulla current

report.Database.Tables[0].ApplyLogOnInfo(info);
}
else
{
//--- caricamento dati tramite codice
report.SetDataSource(GetDatiFromDatabase(cercaTextBox.Text, datasetRadioButton.Checked));
}
}


Con la seconda invece sarà il Report ad essere autosufficiente nel prendersi i dati dalla connessione a cui stiamo puntando, con il vantaggio di non dover fare niente al codice se i dati cambiano, basterà fornire all'utente un nuovo file .rpt.

Dopo che abbiamo finito la fase di creazione del Report, lo possiamo dare in pasto al CrystalReportViewer il quale gestirà l'interattività con l'utente. Nell'esempio tra l'altro usando i raggruppamenti, il Viewer ci abilita una feature abbastanza interessante, il "DrillDown", ovvero la possibilità di "isolare" le pagine relative ai dati di un singolo valore di raggruppamento. Questo si attiva quando si passa con il mouse sopra al campo di raggruppamento e il puntatore diventa una lente: (cliccare sull'immagine Thumbnail per vedere l'animazione):



L'ultima cosa presente nell'esempio è una banale casella di ricerca, che permette di filtrare i dati da passare. Nel caso di utilizzo del metodo SetDataSource è abbastanza facile da fare con la sintassi SQL classica, o nel caso di un DataSet Tipizzato, usando un metodo personalizzato. Nel caso invece dell'utilizzo di LogonInfo, la cosa va fatta tramite l'impostazione della Selection Formula, con una sintassi propria di Crystal Reports.

Applicazione a runtime


Qui di seguito è possibile vedere un'animazione della nostra applicazione in esecuzione (cliccare sull'immagine Thumbnail per vedere l'animazione):



Conclusioni


Il metodo che personalmente preferisco è passare i dati con SetDataSource, in quanto spesso i dati da visualizzare non sono tantissimi, ma soprattutto si hanno magari in memoria durante il funzionamento dell'applicazione stessa. Per questo passarli al report diventa il metodo più comodo e più "controllabile", soprattutto nel caso si debbano fare trasformazioni particolari sui dati, dove il codice -.NET ci aiuta molto, senza impazzire con "campi formula" dove la sintassi è più complessa e senza IntelliSense.

La seconda invece ha senso per grandi moli di dati, tipicamente su stampe di statistiche per archivi grossi, e magari soggetti spesso a continue modifiche richieste da clienti, a discapito del controllo sui dati visualizzati.

In entrambi i casi un po' di codice va comunque scritto ma utilizzando il secondo metodo è sicuramente di meno. Per quanto riguarda le prestazioni sono praticamente uguali.

Accorgimenti usati nel codice di esempio


Se raggruppando i dati, desiderate che i valori del campo per cui si raggruppa non appaiano nella Treeview di navigazione del ReportViewer (tipicamente quando avete un numerico e preferite vedere la descrizione di un altro campo), potete cambiare il nome e lasciare il raggruppamento ugualmente su quel campo: (cliccare sull'immagine Thumbnail per vedere l'animazione)



Quando aggiungete dei file statici come un Report .rpt, un Database Access ecc. ricordatevi di specificare nelle proprietà del file, BuildAction=none e CopyToOutput=Always in modo che quando lanciamo l'applicazione vengano copiati nella Bin.



Se fate uso di DataSet Tipizzati e volete costruire la vostra Query sui dati come nell'esempio, aggiungete un DataAdapter basato sul vostro statement SQL. In particolare nel caso del filtro serviva che ricevesse in ingresso un parametro:



Quando i dati dal Database cambiano, o quando modificate la stringa di SELECT, lanciate un "Verify DataBase" per allineare il Report:

Voto medio articolo: 4.0 Numero Voti: 3

File allegati


Matteo Raumer

Matteo Raumer

Laurea breve in Ingegneria Elettronica presso l'Universita di Padova nel 2001, e nel febbraio 2009 un'altra triennale in Ingegneria Informatica. Da anni lavoro come programmatore .NET principalmente in C#, per migrare applicativi win32 in applicazioni ASP.NET. Ho sviluppato inoltre parecchia reportistica su Crystal Re... Profilo completo

Articoli collegati

Garantire l'univocità di una colonna ammettendo valori NULL multipli
Chi sviluppa in ambito professionale o per puro diletto prima o poi si troverà ad affrontare tematiche nuove ed avvincenti. In questo articolo cercherò di illustrare tre tecniche con i relativi pregi e difetti per permettere con SQL Server di garantire l'univocità di una colonna senza alcuna limitazione sui valori NULL
Autore: Lorenzo Benaglia | Difficoltà:
Il Logging con Integration Services 2005
Perchè si è bloccata la mia applicazione ? Che errori si sono verificati ? Perchè il flusso d'esecuzione non procede nel modo corretto ? Cerchiamo di capire come possono esserci utili le funzionalità di logging offerte da SQL Server e gli Integration Services per rendere più affidabili e consistenti le nostre applicazioni.
Autore: Alessandro Alpi | Difficoltà: | Commenti: 3
Utilizzare i SQL Server Agent Proxies con i Package SSIS
Chi utilizza frequentemente i SSIS Packages e accede a risorse esterne a SQL Server non può fare a meno di conoscere ed utilizzare i Proxy Account (o SQL Server Agent Proxies). Vediamo che cosa sono e come si utilizzano in modo proficuo.
Autore: Alessandro Alpi | Difficoltà: | Commenti: 4
SQL Server 2005 - La Import/Export utility
Chi lavora sui Database si ritrova quasi quotidianamente a dover importare o esportare dati. SQL Server 2005 agevola notevolmente il compito tramite l'Import/Export Utility (ex DTS Import/Export di SQL 2000). Vediamo come funziona.
Autore: Alessandro Alpi | Difficoltà: | Commenti: 14
Visual Studio 2005 Team System for Database Professionals
Scopriamo questo nuovo e potente Tool della famiglia Visual Studio 2005 Team System per creare, sviluppare, testare e gestire con più facilità e flessibilità i database di SQL Server.
Autore: Marco Caruso | Difficoltà:
Parallelismo tra SSIS e DTS, due prodotti a confronto
In questo articolo un'analisi sulle novità dei SQL Server 2005 Integration Services rispetto ai DTS di SQL Server 2000.
Autore: Alessandro Alpi | Difficoltà: | Commenti: 2
Overview dei SQL Server Integration Services (SSIS)
Scopriamo i nuovi Sql Server Integration Services presenti in SQL Server 2005 che sostituisco i DTS aggiungendo delle nuove funzionalità davvero interessanti
Autore: Alessandro Alpi | Difficoltà: | Commenti: 6 | Voto:
Leggere un file XML con SQL Server 2005
Scopriamo in questo articolo alcune potenzialità offerte dal nuovo database SQL 2005, tra cui il nuovo data type XML, e le Stored Procedures per importare e gestire all'interno del database file testuali in formato XML.
Autore: Lorenzo Benaglia | Difficoltà: | Commenti: 5
ExcelDataSetLib, una libreria .NET per esportare dati in formato Excel
In questo articolo verrà dimostrato come derivare la classe DataSet e integrare funzionalità per esportare in formato Excel XLS, XML o CSV i dati provenienti da un base dati qualsiasi.
Autore: David De Giacomi | Difficoltà: | Commenti: 3 | Voto:
Microsoft Application Blocks Data Access
Quante volte vi è capitato di riscrivere decine di volte lo stesso pezzo di codice all'interno di un progetto ? Scopriamo in questo articolo l'utilità dei Microsoft Application Blocks che vi permettono di ottimizzare il vostro codice evitando ripetizioni e vi facilitano la lettura.
Autore: Marco Caruso | Difficoltà:
Comprimere e decomprimere files ZIP con .NET e #ZipLib
Visualizzare il contenuto di un file Zip da una applicazione vi sembra una Mission Impossibile? Oppure la vostra azienda ha fatto un mutuo per pagare il componente che vi aiuta nel lavoro? Ecco un articolo che parla della libreria sharpZipLib, libreria Open Source per la gestione dei formati compressi.
Autore: Giovanni Ferron | Difficoltà: | Commenti: 7
Rivoluzione nel campo dei Reports con i SQL Reporting Services
Finalmente Microsoft ci mette a disposizione uno straordinario tool per la produzione di Report perfettamente integrato con l'architettura .NET. Fino ad ora siamo sempre stati abituati ad utilizzare il buono seppur limitato Crystal Report. Vediamo cosa cambia da ora in poi.
Autore: David De Giacomi | Difficoltà: | Commenti: 6 | Voto:
Scopriamo cosa sono gli Office XP PIA
Vediamo in quest'articolo una dettagliata introduzione dei PIA gli assemblies che permettono ad un'applicazione .NET di interagire e di dialogare con i prodotti della suite Microsoft Office XP.
Autore: David De Giacomi | Difficoltà: | Commenti: 6
Migliorare la qualità dei grafici nei Crystal Reports
In questo breve articolo vedremo come aumentare la qualità dei grafici prodotti da Crystal Reports durante il rendering tramite Web con ASP.NET e all'interno di applicazioni WinForms.
Autore: David De Giacomi | Difficoltà:
Costruire Report con ASP.NET e Crystal Reports
Vedremo in questo semplice Tutorial le istruzioni base che ci permetteranno di costruire un report avanzato usando ASP.NET e l'oggetto CrystalReportViewer integrato in questa versione di Visual Studio .NET.
Autore: David De Giacomi | Difficoltà: | Commenti: 14
Copyright © dotNetHell.it 2002-2017
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5