• Come un abito cucito su misura, i nostri progetti software uniscono le potenzialità di tecnologie innovative alle specifiche esigenze del cliente.

    Showcase progetti
  • Analizziamo e razionalizziamo con il cliente i processi e le attività della propria azienda, per poi seguirlo nella scelta delle giuste strategie IT da adottare.

    Le nostre competenze
  • Crediamo nelle potenzialità di un percorso formativo che unisca forti basi teoriche e metodologiche ad una continua applicazione pratica di quanto si apprende.

    Dettaglio dei corsi
  • Progettiamo e sviluppiamo sistemi e progetti basati su dispositivi mobile consumer (iPhone, Windows Phone 7 Series), industriali (Windows CE) e custom (basati su microcontrollori 8/16/32 bit).

    Approfondimenti
 

Generazione di report in PDF con il framework .NET

March 4, 2010 17:49 by f.bernabei

Spesso all’interno di applicazioni abbiamo la necessità di generare report/stampe più o meno complesse, ed in particolare molte volte l’esigenza è quella di poter generare direttamente file in formato PDF, magari senza uscire dalla nostra applicazione o generare anteprime intermedie del risultato. Per farlo ci sono svariate soluzioni e strumenti, a partire dalle suite di reportistica professionali che permettono la generazione di report molto sofisticati, fino ad arrivare a librerie che permettono la sola generazione di documenti PDF a fronte però di una complessa programmazione e composizione da codice del documento finale.

Fortunatamente dalla versione 2.0 del framework .Net è possibile utilizzare un motore di reportistica derivato dai “Microsoft SQL Server Reporting Services” e distribuito con Visual Studio che è possibile utilizzare a tale scopo. Questo componente è in realtà un visualizzatore di report con estensione rdlc (variante “locale” dei file rdl utilizzati da Reposrting Services ed in pratica un formato xml che permette di descrivere template per i report) che permette l’esportazione dei report in svariati formati, tra cui anche il PDF; vedremo che con poche righe di codice è possibile pilotare direttamente la creazione di un PDF senza dover neanche aprire il visualizzatore, con il vantaggio rispetto ad altre soluzione di avere un editor visuale nativo in Visual Studio (nel nostro caso utilizzeremo Visual Studio 2008 SP1) per la definizione del report stesso (esistono inoltre strumenti esterni in grado di editare i file rdlc che rendono ipoteticamente possibile la personalizzazione dei report in un secondo tempo da parte dei clienti stessi).

In questo articolo quindi vedremo in “stile tutorial” i vari step necessari per la realizzazione di una semplice applicazione di test che alla pressione di un bottone esegua tutte le operazioni necessarie per generare un report e salvarlo in formato PDF.

Da bravi programmatori decideremo di rendere il report completamente slegato dalla base dati e gli forniremo quello di cui ha bisogno attraverso il passaggio di oggetti DTO creati ad hoc (o magari già presenti ed utilizzati all’interno della nostra applicazione). Nel progetto di esempio creiamo una classe che rappresenta un ipotetico articolo da stampare con il codice seguente:

   1: public class ReportDataDTO
   2: {
   3:     public int IdArticolo { get; set; }
   4:     public string Descrizione { get; set; }
   5:     public string Dettagli { get; set; }
   6:     public double Costo { get; set; }
   7:     public byte[] Immagine { get; set; }
   8: }

A questo punto possiamo aggiungere al progetto anche il file rdlc, cioè il template del report che utilizzeremo poi per la stampa. Per farlo basta aggiungere un nuovo item e scegliere dalla categoria “Reportings” il template per i report rdlc (nel mio caso l’ho chiamato ReportDemo.rdlc). Appena inserito il nuovo item si dovrebbe aprire automaticamente in Visual Studio 2008 l’editor dei report: dovreste avere qualcosa tipo:

Empty_rdlc
Il prossimo passo consiste nell’associare al template del report il DTO che sarà utilizzato come contenitore per lo scambio dei dati, nel nostro caso la classe ReportDataDTO precedentemente creata. Per farlo è necessario aggiungere una nuova sorgente dati (Menu Data –> Add New Data Source…) attraverso l’apposito wizard al quale dovremo dire di utilizzare un oggetto come sorgente dati e nella schermata successiva selezionare esplicitamente il tipo ReportDataDTO che abbiamo precedentemente creato.

wizard_dati_2
Una volta selezionata la nostra classe DTO possiamo premere direttamente il tasto “Finish” per completare l’operazione di aggiunta sorgente dati. Ora nella finestra “Data Sources” del report (Visualizzabile dal menu Data –> Show data Sources) avremo la sorgente reportDataDTO con l’elenco dei campi pubblici disponibili ed utilizzabili nel report. Non ci resta altro che “creare” graficamente il report aggiungendo con il semplice trascinamento i campi disponibili nell’area di lavoro dell’editor. Ecco il mio risultato:

rdlc_final

La parte di puro “design” è giunta al termine, ora dobbiamo iniziare a sporcarci un po’ le mani con del buon codice C#.

Per prima cosa ritocchiamo leggermente le impostazioni di compilazione del file rdlc all’interno del progetto Visual Studio. Per default i file rdlc vengono “inglobati” nell’eseguibile/libreria come risorse di progetto, mentre in molti casi è preferibile a mio parere lasciare il template esterno (e caricarlo “al volo” per la generazione del report) in modo da permettere correzioni o semplici modifiche estetiche al template senza la necessità di dover ricompilare e ridistribuire l’intero binario dell’applicazione. Per farlo dobbiamo selezionare il file rdlc nel ”Solution Explorer” di VS2008 e modificare alcune proprietà dalla apposita toolbox “Properties”; in particolare bisogna cambiare la proprietà “Build Action” dal default “Embedded Resource” in “None”. Inoltre impostiamo anche la proprietà “Copy to Output Directory” al valore “Copy if newer” in modo da fare una copia del file nella cartella dei binari ad ogni compilazione. Ecco le modifiche finali delle proprietà del file rdlc:

rdlc_prop
Ora siamo pronti per la generazione del report. Nell’applicazione del progetto di esempio aggiungiamo un bottone e nel gestore dell’evento “Click” di quest’ultimo iniziamo le operazioni per la generazione del PDF.

Per prima cosa simuliamo il caricamento dei dati da una ipotetica sorgente dati implementando un metodo che restituisca una lista di oggetti DTO, nel nostro caso sarà in realtà solamente uno. Il codice è banale e non fa altro che creare un’istanza della classe DTO, valorizzarne le proprietà (i dati utilizzati nell’esempio tra l’altro sono di un libro che vi consiglio di leggere Open-mouthed) e restituuirlo:

   1: private ReportDataDTO[] estraiDati()
   2: {
   3:     byte[] rawImg;
   4:     using (System.Drawing.Image img = System.Drawing.Bitmap.FromFile("RocketSurgeryCover.jpg"))
   5:     {
   6:         using (MemoryStream ms = new MemoryStream())
   7:         {
   8:             img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
   9:             rawImg = ms.ToArray();
  10:         }
  11:     }
  12:  
  13:     ReportDataDTO dto = new ReportDataDTO
  14:     {
  15:         IdArticolo = 9847,
  16:         Descrizione = "Rocket Surgery Made Easy: The Do-It-Yourself Guide to Finding and Fixing Usability Problems",
  17:         Dettagli = "It's been known for years that usability testing can dramatically...",
  18:         Costo = 21.99,
  19:         Immagine = rawImg
  20:     };
  21:     
  22:     return new ReportDataDTO[] { dto };
  23: }

Ora si passa alla generazione vera e proprio utilizzando la classe LocalReport che permette di elaborare un report rdlc ed effettuarne la renderizzazione. I passi da seguire sono il caricamento del file rdlc esterno impostando la proprietà “ReportPath”, aggiunta della sorgente dati da utilizzare, esecuzione del render specificando i parametri per generare un file in formato PDF ed infine il salvataggio dei dati risultanti dall’operazione precedente su file system, ed il gioco è fatto.

Il codice seguente (metodo “generaReport” richiamato dal gestore d’evento del bottone) implementa esattamente i passi appena descritti:

   1: private void generaReport()
   2: {
   3:     // Simulazione estrazione dati da una qualsiasi sorgente
   4:     ReportDataDTO[] dtoList = estraiDati();
   5:  
   6:     // Creazione istanza LocalReport e caricamento template rdlc e dati
   7:     LocalReport lr = new LocalReport();
   8:     lr.ReportPath = "ReportDemo.rdlc";
   9:     lr.DataSources.Add(new ReportDataSource("DemoReportPDF_ReportDataDTO", dtoList));
  10:  
  11:     // Elaborazione e render del report in formato PDF
  12:     Warning[] warnings;
  13:     string[] streamids;
  14:     string mimeType, encoding, extension;
  15:     string deviceInfo = "<DeviceInfo>" +
  16:                         "  <OutputFormat>PDF</OutputFormat>" +
  17:                         "</DeviceInfo>";
  18:  
  19:     byte[] bytes = lr.Render("PDF", deviceInfo, out mimeType, out encoding, out extension, out streamids, out warnings);
  20:  
  21:     // Salvataggio del report generato su file system
  22:     string reportFileName = Guid.NewGuid().ToString() + ".pdf";
  23:     using (MemoryStream ms = new MemoryStream(bytes))
  24:     {
  25:         using (FileStream fs = new FileStream(reportFileName, FileMode.Create))
  26:         {
  27:             fs.Write(bytes, 0, bytes.Length);
  28:             fs.Close();
  29:         }
  30:     }
  31:  
  32:     MessageBox.Show("Report generato correttamente: " + reportFileName);
  33: }

Le uniche due note da sottolineare sono:

- Nella fase di aggiunta dei dati deve essere specificato il nome con cui la sorgente dati è configurata all’interno dell’rdlc. Questo valore è presente (e modificabile) andando nel designer del report ed accedendo dal menu “Report” alla finestra “Report Data Sources”.

- La classe LocalReport fa parte del ridistribuibile Microsoft Report Viewer (installato da Visual Studio). Per poter ridistribuire l’applicazione in un PC con il solo framework .Net installato c’è bisogno anche di questo pacchetto scaricabile gratuitamente dal sito MSDN (il download si riferisce alla versione relativa al framework 3.5 SP1). Per l’utilizzo nel progetto è necessario aggiungere un riferimento all’assembly “Microsoft.ReportViewer.WinForms”.

E con questo è tutto, non resta che eseguire l’applicazione, premere il pulsante e se tutto è andato come dovrebbe, nella cartella di esecuzione del progetto dovrebbe comparire per incanto un file PDF più o meno così

pdf_result

 

File allegati:


Currently rated 5.0 by 3 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Utilizzo di Twitter da un’applicazione .NET

August 28, 2009 15:39 by F.Bernabei

Per un piccolo progetto interno abbiamo la necessità di interfacciarci con twitter ed eseguire alcune operazioni comuni come ad esempio ottenere i tweet che stiamo seguendo oppure aggiornare il nostro stato.

Dopo un rapido sguardo alle API messe a disposizione ho pensato: “possibile che non ci sia qualcuno che ha già scritto una bella libreria per utilizzare codeste API da .NET?”. Detto fatto, con l’aiuto del prode Google sono partito alla ricerca ed ho trovato tweet#, bellissima libreria tipizzata e con interfaccia fluente che mette a disposizione (credo) tutte le funzionalità accessibili con le API native (a cui ovviamente si appoggia).

Di seguito un esempio di utilizzo per ottenere la lista di tweet seguiti da uno specifico utente:

   1: var twitter = FluentTwitter.CreateRequest()
   2:     .AuthenticateAs("username", "password")
   3:     .Statuses().OnFriendsTimeline()
   4:     .AsJson();
   5:  
   6: IEnumerable<TwitterStatus> response = twitter.Request().AsStatuses();

Si tratta in conclusione di una libreria ben fatta e molto potente per aggiungere il supporto a Twitter al nostro software… ora non resta che utilizzarla.


Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Creare immagini in c#

February 20, 2009 16:57 by F.Villi

Ecco un esempio di codice che renderizza una immagine PNG. Utile, ad esempio, quando si vuole pubblicare l'indirizzo email nel proprio sito senza che questo venga indicizzato dai motori di ricerca o ancor peggio catturato dagli spider degli spammer.

   1: <%@ WebHandler Language="C#" Class="Handler" %>
   2:  
   3: using System;
   4: using System.Web;
   5: using System.Drawing;
   6: using System.Drawing.Drawing2D;
   7: using System.Drawing.Imaging;
   8: using System.IO;
   9:  
  10:  
  11: public class Handler : IHttpHandler
  12: {
  13:  
  14:     public bool IsReusable { get { return false; }  }
  15:     
  16:     public void ProcessRequest (HttpContext context) 
  17:     {
  18:         Bitmap bmp;
  19:         Graphics g;
  20:         
  21:         try
  22:         {
  23:             int w = Convert.ToInt32(context.Request.QueryString["width"]);
  24:             int h = Convert.ToInt32(context.Request.QueryString["height"]);
  25:             string t = context.Request.QueryString["text"];
  26:             string f = context.Request.QueryString["font"];
  27:             int s = Convert.ToInt32(context.Request.QueryString["size"]);
  28:             Color c = Color.FromName(context.Request.QueryString["color"]);
  29:  
  30:             bmp = new Bitmap(w, h, PixelFormat.Format32bppArgb);
  31:             g = Graphics.FromImage(bmp);
  32:  
  33:             g.Clear(Color.Transparent);
  34:             g.DrawString(
  35:                 t.Replace("_", "")
  36:                 ,new Font(f, s, FontStyle.Bold)
  37:                 ,new SolidBrush(c), 0, 0);
  38:         }
  39:         catch
  40:         {
  41:             bmp = new Bitmap(40, 18, PixelFormat.Format32bppArgb);
  42:             g = Graphics.FromImage(bmp);
  43:             g.Clear(Color.Yellow);
  44:             
  45:             g.DrawString(
  46:                 "error"
  47:                 ,new Font("Tahoma", 10, FontStyle.Bold)
  48:                 ,new SolidBrush(Color.Red), 0, 0);
  49:         }
  50:  
  51:         MemoryStream oStream = new MemoryStream();
  52:         bmp.Save(oStream, ImageFormat.Png);
  53:  
  54:         context.Response.ClearContent();
  55:         context.Response.ContentType = "image/png";
  56:         context.Response.BinaryWrite(oStream.ToArray());
  57:         context.Response.End();
  58:  
  59:         bmp.Dispose();
  60:         g.Dispose();
  61:     }
  62: }

Inserita questa pagina ashx nel progetto verrà utilizzata in questo modo:

<img src="/pagina.ashx?text=012.3456789&width=160&height=19&size=12&color=black&font=courier" />

La classe Graphics incorpora primitive grafiche (ad esempio DrawLine oppure DrawPie) con le quali non sarà difficile realizzare grafici o disegni utilizzando un approccio vettoriale.


Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5