• 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
 

Esportare gli sms di iPhone con Entity Framework, SQLite e FileHelpers

March 31, 2010 11:13 by M.Poponi

Domenica scorsa ho avuto bisogno di esportare in un file gli SMS presenti nel mio fido iPhone. "Niente di più semplice", ho pensato, abituato alla Nokia PCSuite, "ci sarà una comoda funzione di iTunes che lo fa".

Errore.

iTunes non permette di esportare gli SMS presenti nell'iPhone! cercando un po' su google, ho trovato una schiera di programmi non free che lo fanno, addirittura alcuni siti che lo fanno online, entrambe le soluzione inaccettabili: non ho voglia di spendere soldi per una funzione che dovrebbe essere fornita gratuitamente e non ho voglia di uploadare i miei SMS personali su un sito che non conosco. Mi sono un po' documentato, ho scoperto qualcosa di utile e ne è uscita fuori un'applicazioncina che esporta gli sms e un'esperienza didatticamente interessante.
Ecco come ho fatto.
Premessa: Non è possibile estrarre gli SMS direttamente da un iPhone (legalmente). Quel che si deve fare è passare per il backup di iTunes.

I passi:

1) backuppare l'iphone con iTunes

2) andare sulla cartella %appdata%\Apple Computer\MobileSync\Backup\

3) c'è una sola cartella qui dentro, chiamata con un numero GUID-like. esplorare questa cartella, e individuare due files: 3d0d7e5fb2ce288813306e4d4636395e047a3d28.mddata è un db SQLite che contiene gli SMS 31bb7ba8914766d4ba40d6dfb6113c8b614be442.mddata è un db SQLite che contiene i contatti

4) utilizzare un qualche strumento SQLite che permette di leggere i db. Vi consiglio http://code.google.com/p/sqlite-manager/, una utilissima estensione per FireFox.

Il primo DB ha una tabella, message, che contiene i veri e propri SMS. La struttura di tale tabella è:

 messages

i campi più interessanti sono:

address: contiene il numero di telefono da cui/ verso il quale è stato inviato l'sms
date: timestamp UNIX della data di invio
flags: 2 se è un SMS in ingresso, 3 se è un SMS in uscita
text: il testo del messaggio

5) se invece dei numeri di telefono vogliamo sapere il nome dei contatti con cui abbiamo scambiato gli sms, occorre aprire l'altro DB. questo basterebbe per esportare gli SMS. contacts

 

In ABPerson troviamo tutti i nostri contatti, in ABMultivalue i numeri di telefono (e altre info), facendo la join ABMultivalue.record_id=ABPerson.ROWID.

 

Tra l'altro lo stesso sqlite manager può esportare i dati contenuti nella tabella, ma noi siamo sviluppatori, quindi facciamo un'applicazioncina! 

 

Strumenti:

1) volendo utilizzare per l’accesso ai dati Entity Framework, ho dovuto cercare un provider di accesso a SQLite che lo supportasse.  La scelta è caduta su System.Data.SQLite: http://sqlite.phxsoftware.com/ 

2) volendo esportare i dati, ho optato per un vecchio amore che mi ha fatto risparmiare innumerevoli ore di lavoro negli anni: FileHelpers

L’applicazione:

La realizzazione dell’applicazione è stata davvero istantanea:

1) Ho installato System.Data.SQLite

2) Ho creato un’applicazione Winforms, aggiunto i riferimenti a System.Data.SQLite, System.Data.SQLite.Linq e FileHelpers

3) Ho aggiunto al server explorer due connessioni di tipo SQLite ai due files/db di cui abbiamo parlato sopra

4) Ho creato due modelli di Entity Framework: Entities che contiene le tabelle relative agli SMS e Contacts che contiene, be’… lo avete capito.

5) Nella form principale ho aggiunto una lista che conterrà i contatti (lbContacts), un Menu per le funzionalità di esportazione, una DataGridView per contenere i messaggi.

6) Ho scritto una classe per trasportare i dati dei contatti:

   1: public class PersonDTO
   2:   {
   3:       public string Person { get; set; }
   4:        
   5:       public string Address{ get; set; }
   6:       
   7:   }

7) Una semplice funzioncina che all’avvio carica i dati dei contatti che hanno SMS, ripulisce i numeri di telefono da ‘+’ e spazi, estrae i nomi e li mette nella ListBox:

   1: public void LoadAddressess()
   2:        {
   3:            Entities ent  = new Entities();
   4:            var addresses = (from  m in ent.message select  new {address= m.address.Replace(" ","").Replace("+","")}).Distinct();
   5:  
   6:            Contacts cont = new Contacts();
   7:            var numbersContacts = from d in cont.ABPerson
   8:                                  join v in cont.ABMultiValue on d.ROWID equals v.record_id
   9:                                   select new {person = (d.First??"") + " " + (d.Last??""), number = v.value.Replace(" ","").Replace("+","")};
  10:  
  11:                              
  12:  
  13:            var smartAddresses= from nc in numbersContacts.ToList() join m in addresses.ToList()
  14:                                                           on nc.number equals m.address
  15:                                                           select new PersonDTO() {Person=nc.person , Address=m.address}
  16:            ;
  17:            lbAddresses.DisplayMember = "Person";
  18:            lbAddresses.DataSource = smartAddresses.ToList();
  19:             
  20:        }
  21:        private void Form1_Load(object sender, EventArgs e)
  22:        {
  23:            LoadAddressess();
  24:  
  25:  
  26:        }

 

8) Ho creato un DTO per contenere gli SMS:

   1: [FileHelpers.DelimitedRecord("|")]
   2:    public class SMSDTO
   3:    {
   4:        private string numero;
   5:        private string inOut;
   6:        [FileHelpers.FieldConverter(FileHelpers.ConverterKind.Date,"dd-MM-yyyy HH:mm:ss")]
   7:       
   8:        private DateTime dataOra;
   9:        private String testo;
  10:       
  11:    public string Numero
  12:        {
  13:            get { return numero; }
  14:            set { numero = value; }
  15:        }
  16:        public DateTime DataOra
  17:        {
  18:            get
  19:            {
  20:                return dataOra;
  21:            }
  22:            set { dataOra = value; }
  23:        }
  24:  
  25:        public string Testo
  26:        {
  27:            get { return testo; }
  28:            set { testo = value; }
  29:        }
  30:  
  31:        public string InOut
  32:        {
  33:            get { return inOut; }
  34:            set { inOut = value; }
  35:        }
  36:  
  37:       
  38:    }

 

Tanto che c’ero :) ho aggiunto due attirbuti che dicono a FileHelpers che voglio esportare i dati in un file a campi delimitati dal pipe (‘|’) e che voglio che la data sia nel formato italiano.

 

9) A questo punto è banale scrivere una funzioncina che ottiene gli SMS relativi al numero selezionato nella lista, e una che invece ottiene tutti gli SMS

   1: public IEnumerable<SMSDTO> GetSelectedSms()
   2:         {
   3:             Entities ent = new Entities();
   4:             string address = ((PersonDTO) lbAddresses.SelectedItem).Address;
   5:             var messages = (from m in ent.message where m.address.Replace(" ", "").Replace("+", "") == address select new {m.address, m.date, m.text, m.flags });
   6:  
   7:             return from m in messages.ToList()
   8:                    select
   9:                        new SMSDTO()
  10:                            {
  11:                                Numero =m.address,
  12:                                DataOra   = ConvertTimestamp((double) m.date),
  13:                                Testo = m.text,
  14:                                InOut = m.flags == 2 ? "in " : "out"
  15:                            };
  16:         }
  17:         public IEnumerable<SMSDTO> GetAllSms()
  18:         {
  19:             Entities ent = new Entities();
  20:             
  21:             var messages = (from m in ent.message  select new { m.address, m.date, m.text, m.flags });
  22:  
  23:             return from m in messages.ToList()
  24:                    select
  25:                        new SMSDTO()
  26:                        {
  27:                            Numero = m.address,
  28:                            DataOra = ConvertTimestamp((double)m.date),
  29:                            Testo = m.text,
  30:                            InOut = m.flags == 2 ? "in " : "out"
  31:                        };
  32:         }

le date devono essere convertite da Unix ad un formato più maneggevole, per questo basta una funzioncina semplice semplice:

   1: private static DateTime ConvertTimestamp(double timestamp)
   2:   
   3:      {
   4:   
   5:          return (new DateTime(1970, 1, 1, 0, 0, 0, 0)).AddSeconds(timestamp).ToLocalTime();
   6:  
   7:      } 

10) A questo punto basta solo collegare il binding della DataGridView al cambio di selezione della lista per vedere i dati,

   1: private void lbAddresses_SelectedIndexChanged(object sender, EventArgs e)
   2:       {
   3:           IEnumerable<SMSDTO> SMS = GetSelectedSms();
   4:  
   5:           dgvMessages.DataSource = SMS.ToList();
   6:       }

e collegare il click di due voci di menu per esportare i dati selezionati o tutti i dati in un file, con l’incredibile FileHelpers:

   1: private void exportSelectedToolStripMenuItem_Click(object sender, EventArgs e)
   2:        {
   3:            ExportSMS( GetSelectedSms()  );
   4:        }
   5:        private void exportAllToolStripMenuItem_Click(object sender, EventArgs e)
   6:        {
   7:            ExportSMS(GetAllSms());
   8:        }
   9:  
  10:  
  11:        private void ExportSMS(IEnumerable records)
  12:        {
  13:            FileHelpers.DelimitedFileEngine engine = new DelimitedFileEngine(typeof(SMSDTO));
  14:            SaveFileDialog sfd= new SaveFileDialog();
  15:            sfd.DefaultExt = ".csv";
  16:            sfd.FileName = "export.csv";
  17:            if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
  18:            { 
  19:                engine.WriteFile(sfd.FileName,records);
  20:            }
  21:        }

e abbiamo finito!

Conclusioni:

Abbiamo visto come sia possibile utilizzare Entity Framework con SQLite in modo semplice ed efficace, come l’esportazione su file sia immediata con FileHelpers e come questo possa essere utilizzato per l’esportazione dei propri SMS da un backup iPhone.

Buon divertimento!!!


Currently rated 4.7 by 3 people

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

Debriefing su .NET Campus

March 15, 2010 16:52 by L.Maiorfi

Era parecchio che non uscivamo in trasferta così in gruppo per partecipare ad un evento, e sinceramente non pensavo che considerati gli impegni di tutti ci si riuscisse addirittura di sabato, ma così è stato.

A titolo di feedback (sempre che a qualcuno importi qualcosa) credo valga la pena di evidenziare quali sessioni si sono veramente distinte dalle altre, così che in futuro l’interesse dell’audience si possa concentrare intorno a chi (e a cosa)merita più attenzione:

  • Sessione “architetturale” di Andrea Saltarello: notevole soprattutto per la solidità “granitica” con cui ha trattato temi per loro natura “eterei”. Fa rabbia solo vedere che avrà almeno 10 anni meno del sottoscritto!
  • Sessione su ASP.NET 4 di Daniele Bochicchio: una sessione semplice ma molto densa, più che altro una enumerazione delle novità più interessanti presenti sul framework 4.0 per quanto riguarda le applicazioni web forms. Routing, gestione del viewstate, markup HTML emesso senza tabelle se richiesto, deploy del file .config differente per diversi profili di deploy sono solo alcune delle novità viste
  • Sessione di Brunetti su Azure. Una introduzione per forza di cose molto veloce ma di taglio molto pratico sul perché e un pochino sul come sviluppare un'applicazione web per Azure, o comunque per il cloud computing in generale. Interessante la produzione e pubblicazione di un'applicazione durante la sessione
  • Sessione su Asincronia e Parallelismo in .NET 4.0 con Mauro Minella. Sessione estremamente interessante, sia per l'argomento che per la preparazione del relatore. Poche chiacchiere, molto codice scritto e testato, benchmark brutali ed effetti speciali. I nuovi task e PLINQ sono davvero entusiasmanti. Come la demo finale con il 16-core!

 imageimage image


Be the first to rate this post

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

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