Your SlideShare is downloading. ×
Porting evolutivo di una applicazione per la gestione di riferimenti bibliografici in ambiente .net 4.5
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

Porting evolutivo di una applicazione per la gestione di riferimenti bibliografici in ambiente .net 4.5

305
views

Published on

Published in: Education

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
305
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
6
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. DIPARTIMENTO DI INGEGNERIACORSO DI LAUREA TRIENNALE IN INGEGNERIA DELLINFORMAZIONE CURRICULUM INFORMATICA Porting evolutivo di una applicazione per la gestione di dati di riferimenti biliografici in ambiente .NET 4.5Relatore : Prof. Maurizio FermegliaLaureando : Giulio AmbrogiAnno Accademico : 2011 / 2012
  • 2. Indice dei contenutiCAPITOLO 1 Introduzione (pag. 3)CAPITOLO 2 Analisi dei requisiti e della situazione esistente 2.1 Intervista al committente (pag. 5) 2.2 Analisi della situazione esistente (pag. 6) 2.2.1 Il database (pag. 6) 2.2.2 Applicazione esistente (pag. 9) 2.2.3 Data Bindig (pag 12) 2.2.4 SharePoint e Web Application (pag. 12)CAPITOLO 3 Progettazione 3.1 Principi generali di progettazione (pag. 13)CAPITOLO 4 Implementazione 4.1 Upload di file (pag. 15) 4.2 Cancellazione di file (pag. 22) 4.3 Opzioni utente (pag. 25) 4.4 Export (pag. 26) 4.5 Implementazioni di carattere generale (pag. 41)CAPITOLO 5 Conclusioni 5.1 Possibili miglioramenti futuri (pag. 43) 5.2 Conclusioni (pag. 43) 2
  • 3. CAPITOLO 1IntroduzioneLobiettivo di questa tesi è estendere le funzionalità di unapplicazione clientesistente la quale è utilizzata per la gestione dei riferimenti bibliografici e delleattività del laboratorio MOSE.In particolare si vuole fornire allutente, che utilizzerà lapplicazione,la possibilità digestire lupload e la cancellazione di documenti relativi alle pubblicazione, di upload cancellazioneesportare in forma tabellare un insieme di record bibliografici e si intendemigliorare ulteriormente linterfaccia utente ,per rendere lapplicazionemaggiormente user friendly , coerentemente con le nuove funzionalità daimplementare.Nei capitoli successivi le singole funzionalità e la loro implementazione verrannoillustrate nello specifico.La situazione iniziale vede lesistenza di :- versione beta dellapplicazione di cui si vuole effettuare il porting, ancora privadelle sopracitate funzionalità;- una base di dati ,su server remoto , nella quale sono immagazzinate tutte leinformazioni utilizzate dallapplicazione, come dati anagrafici, dati bibliografici,ecc. ;- unistanza di SharePoint Server installata su un server remoto (un altro), utilizzatadalla web application che lavora in parallelo allapplicazione in questione; è danotare che questultima ancora non comunica con tale istanza ; 3
  • 4. in questo server vengono salvati i file pdf relativi alle pubblicazioni ;- una web application che presenta sul Web i dati bibliografici e permetteallutente di effettuare il download di un file pdf relativo ad una pubblicazioneCiò che ha motivato la realizzazione di questo lavoro è la necessità di permettereallutente di svolgere alcune operazioni direttamente dallapplicazione, ovverosvincolare lutente dallutilizzo di ulteriori software , garantendo così una maggioresemplicità di esecuzione, una presentazione dei dati funzionale ed una maggioresicurezza relativamente allintegrità dei dati e allaggiornamento degli stessi.I vincoli progettuali sono rappresentati in primo luogo dallo sviluppo in ambiente.NET, utilizzando la tecnologia Windows Presentation Foundation e il linguaggiodi programmazione C#, in secondo luogo ,relativamente allapplicazione giàesistente, dallattenersi per quanto possibile alla sua logica e infinedallimplementare il tutto in modo tale che possa essere accessibile alla webapplication.Gli obiettivi di questo lavoro sono :- analisi dei requisiti da parte del committente;- analisi della situazione preesistente;- studio delle tecnologie .NET, e nel particolare di WPF e C#;- studio del funzionamento delle interazioni tra Database, applicazione e server;- progettazione del front-end;- realizzazione effettiva e compilazione su piattaforma .NET Framework 4.5;- test e distribuzione dellapplicazione. 4
  • 5. CAPITOLO 2Analisi dei requisiti e della situazione esistente esistente2.1 Intervista al committenteLe richieste del committente per la nuovaversione dellapplicazione sono : • effettuare un analisi degli oggetti ffettuare programmabili (viste , stored viste procedures , user defined functions functions) effettivamente utilizzati dallapplicazione al fine di effettuare un lavoro di pulizia nella base di dati dati; • effettuare lupload di un documento relativo ad una determinata ffettuare pubblicazione nel server sul quale è presente unistanza di ShareP SharePoint Server , aggiornando allo stesso tempo i valori presenti nella base di dati (Titolo del pdf e ID del documento) documento). Questo documento dovrà poi essere reperibile dalla web application che permette la visualizzazione dei contenuti dal web web; • effettuare la cancellazione di un documento (analogamente allupload ffettuare bisogna gestire entrambi i "lati" : SharePoint e SQL Server) ed avere a disposizione opportuni controlli per verificare la presenza o meno di un 5
  • 6. documento, e potere gestire facilmente le azioni (upload , cancellazione, presentazione) relative ad esso; • poter esportare un file in formato Excel nel quale vengano riportati tutti i dati relativi al titolo della pubblicazione, allanno , agli autori, alla denominazione e ai riferimenti, fornendo inoltre allutente la possibilità di filtrare i risultati a suo piacimento prima di effettuare lexport; • eventuali accorgimenti per migliorare ulteriormente il front end.2.2 Analisi della situazione esistente2.2.1 Il database2.2.1La base di dati esistente è sita in un server remoto ( di3.units.it ) ed è composta da27 tabelle, 63 viste e 133 stored procedures.Contiene tutti i dati inerenti la gestione del laboratorio come, ad esempio: datianagrafici dei dipendenti, dati delle pubblicazioni, congressi, progetti e tesi.Le viste utilizzate dallapplicazione esistente sono: • ViewPubblicazioniRivista : mette in relazione le informazioni delle riviste con le informazioni dello staff; • ViewPubblicazioniCongressi : mette in relazione i le informazioni dello staff con il congresso relativo alla pubblicazione ; • Staff_View : una raccolta dei dati anagrafici dei membri dello staff . • ViewPubblicazioniRivista_Staff: variante della prima vista citataLe stored procedures utilizzate dallapplicazione esistente sono: 6
  • 7. • sp_PubbStaff : utilizzata per visualizzare le pubblicazioni relative ad un membro dello staff. Riceve in input 2 parametri: @ID_staff è lID del componente dello staff, mentre @ID_output è un parametro che se settato a 0 fornisce sia le pubblicazioni presentate in un congresso che in una rivista, se settato ad 1 fornisce solo le pubblicazioni presentate in un congresso ed infine se settato a 2 fornisce solo le pubblicazioni presentate in una rivista • sp_PubbWeb: utilizzata per visualizzare le pubblicazioni presentate nel sito web del MOSE. Riceve in input un parametro @ID_SitoWeb , che rappresenta lidentificatore del sito web.Non sono state trovate invece User Defined Functions.Nella Figura 1 si riporta il Database Diagram della base di dati in questione : 7
  • 8. TBL_Options tblRiviste tblAnno TBL_PDFDocument Versions ID ID_rivista ID_Anno IDTitolo VersionId FolderPDFDocument Denominazione Anno NameFile Version RivistaInternazionale Id Referee UserName [Luogo pubblicazione] TimeStamp ISSN FinalizeTimeStamp Mode ModeStack Updates Notes tblProgetti tblTesiDettaglio tblTesi ID_Progetto ID_Tesi ID_Tesi Progetto DettaglioIT ID_Tipo SiglaProgetto DettaglioEN ArgomentoIT Anno_Inizio ArgomentoEN tblTesiStato Anno_Fine ID_Stato Collaborazione Finanziatore StatoTesi Correlatori ResponsabileLocale ID_Curriculum ResponsabileGlobale tblCurriculum Stato FinanziamentoLocale ID_Curriculum ID_Relatore FinanziamentoGlobale Curriculum Autore VIsualizzaSito CurriculumEN tblTipiTesi DataInizioTesi ID_Tipo TipoProgetto MEseLAurea Tipo imgproject AnnoLaurea summary Voto link tblStaffCongressi tblStaff ID_Staff tblStaffGruppi ID_Staff ID_Congresso ID_Gruppo Cognome Presentazione ID_Staff Nome Organizzazione Amministratore Attivo tblTItoloProgetto Partecipazione Username ID_progetto SuInvito Amministratore ID_titolo PhotoFileName PhoneNumber OfficeLocation Email tblGruppi tblCongressi Summary ID_Gruppo ID_Congresso Education Nome tblKeyword Denominazione ResearchActivity Note ID_Keyword Data ResearchProject Keyword Anno Collaborations CongressoIntenazionale Enabled RefereetblCollegamentoKeywordsTitolo tblStaffCorsi Id_Keyword tblTitoli ID_Staff tblStaffTitoli ID_Titolo ID_Corso ID_Titolo ID_Staff Autori Organizzatore ID_Titoli Riferimento ID_Stato ID_Rivista ID_Congresso tblCorsi Anno tblTipoPubbl ID_Corso ID_TipoPubb NomeCorso TitolotblStatoTitolo TipoPubblicazione EnteOrganizzatore ID_Stato ID_tipoPubb TipoPubEnglish Periodo Stato ID_SitoW eb Class_TS Luogo Statoen ImpactFactor Class_PD Anno ID_Settore Figura 1 8
  • 9. 2.2.22.2.2 Analisi dellapplicazione esistenteQuesta applicazione è stata implementata utilizzando la tecnologia WindowsPresentation Foundation (linguaggi C# e XAML).Il suo aspetto richiama quello delle applicazioni della suite Microsoft Office 2010.Alcuni studi sulla User Experience condotti dalle più importanti software house, hanno dimostrato come , attraverso luso di tecniche come leye tracking, lutente tenda Figura 2 a leggere icontenuti delle pagine focalizzando maggiormente la propria attenzione su duelinee orizzontali nella parte alta della pagina e su una linea verticale nella partesinistra della pagina, secondo quello che è noto come schema ad F. Questorappresenta un grande punto di forza per lapplicazione.La pagina visualizzata in Figura 2 è la home dellapplicazione , nella quale sonopresenti link testuali che rimandano alle diverse pagine, e pulsanti (nella banda ingrigio chiaro) che rimandano alle stesse.Lapplicazione esistente è di tipo navigation-based nello stile di numerose altre navigation-based,applicazioni come Windows Explorer e Windows Media Player.Le pagine sulle quali è stata focalizzata maggiormente lattenzione sono quellerelative alla gestione e alla presentazione dei dati relativi alle pubblicazioni pubblicazioni. 9
  • 10. Figura 3Nella pagina relativa alle pubblicazioni si nota la presenza di 3 pulsanti: Dettaglio ,Griglia e Staff Il primo di questi , lo si può già vedere nellimmagine, fornisce i Staff.dettagli della pubblicazione selezionata attraverso gli appositi controlli (Figura 3), ilsecondo fornisce una vista in un formato griglia, simulando linterfaccia di unatabella di SQL Server (Figura 4) ed il terzo infine raggruppa, in formato-griglia, lepubblicazioni in base allautore (Figura 5) ,che può essere selezionato attraversouna apposita listbox. Figura 4 10
  • 11. I pulsanti Export e Upload non svolgono ancora alcuna funzione.Figura 52.2.3 Data BindingLo scambio di dati tra applicazione e database avviene grazie ad una stringa diconnessione denominata MoseDBConnectionString.Il tipo di autenticazione utilizzata è Windows Authentication.<add name="MoseUXPrototype.Properties.Settings.MoseDBConnectionString" connectionString="Data Source=SERVERNAMESQLEXPRESS; Initial Catalog=MoseDB;Integrated Security=True" providerName="System.Data.SqlClient" />Invece le interazioni tra applicazione e SharePoint (su server remoto) sarannoimplementate come richieste HTTP corredate delle opportune credenziali everranno illustrate in seguito. 11
  • 12. Questa stringa si trova nel file ./MoseUXPrototype.exe.config.xaml , il quale èpresente nel folder della versione distribuibile dellapplicazione.2.2.4 Sharepoint Server e Web ApplicationÈ presente inoltre una applicazione web che presenta le informazionibibliografiche su un sito web. Questo sito web è stato creato utilizzando MicrosoftSharePoint.SharePoint è un software lato server che permette la creazione di particolari sitiweb attraverso lo strumento software SharePoint Designer, con il quale è possibilegestire, tra le varie cose, un archivio di file che possono essere utilizzatidallapplicazione web.I file delle pubblicazioni infatti sono salvati in una apposita cartella (www.mose.units.it/doc ). 12
  • 13. CAPITOLO 3Progettazione3.1 Principi generali di progettazioneLidea di fondo è sempre quella di conservare il layout dellapplicazione esistente,per quanto possibile, mantenendo vivace linterfaccia e garantendone un facile esicuro utilizzo da parte dellutente.Per quanto riguarda sia lupload che lexport si è deciso di implementare questedue funzionalità su due diverse finestre e non delle pagine : il motivo principale è finestre,il voler marcare la differenza sostanziale tra la gestione di file e la gestione direcord.Si immagini di suddividere le funzionalità dellapplicazione su due livelli differenti: • lettura/scrittura di record (comunicazioni tra applicazione e base di dati) • gestione di file (upload / cancellazione) ed export (comunicazioni tra applicazione , SharePoint e base di dati )Lintera applicazione esistente si presenta allutente su ununica finestra e lutentepuò accedere ai diversi contenuti sfogliando tra le pagine di essa.Si è preferito invece implementare le nuove funzionalità per la gestione dei file , sufinestre pop up , in modo tale da dare allutente la sensazione di utilizzare unostrumento con vero e proprio. Si intende implementare quindi un Uploader ed unExporter. 13
  • 14. Si intende inoltre permettere allutente di gestire le connessioni e le credenziali perle interazioni web con i server, quindi sarà implementata un ulteriore finestra popup per la consolle delle opzioni.Queste finestre saranno aperte da opportuni pulsanti posizionati nelle paginedellapplicazione coerentemente con la loro funzione. 14
  • 15. CAPITOLO 4Implementazione4.1 UploadSi vuole caricare un file , relativo ad una determinata pubblicazione, su SharePointed aggiornare i record del database SQL Server che associano "id della idpubblicazione" con "titolo del pdf (Figura 6). titolo pdf" Figura 6Il pulsante che permette di accedere a questa funzionalità è il pulsante Upload cheè implementato nella pagina Pubblicazioni (Figura 3,4,5).Cliccando su tale pulsante si accede ad un nuova finestra : la console di upload una(Figura 7).Linterfaccia (figura 7) di questa finestra è stata implementata in modo tale da : interfaccia 15
  • 16. • selezionare, attraverso una listBox, la pubblicazione per la quale si vuole effettuare lupload del file; • cercare e selezionare il file da caricare; • selezionare il server e il percorso allinterno del quale caricare il documento; • di impostare le proprie credenziali (Username, Dominio e Password); • eseguire effettivamente lupload.È presente inoltre un pulsante per effettuare un refresh della finestra. Figura 7 16
  • 17. La listbox che presenta le pubblicazioni esistenti viene popolata attraverso ilmetodo RiempiListbox(), il quale esegue una query di tipo select sul databasedescritto dalla stringa di connessione, si riporta di seguito il codice:public void RiempiListBox(){try{string query = "select ID_Titolo, Anno, Titolo from ViewPubblicazioniCongressi union select ID_Titolo,Anno,Titolo from ViewPubblicazioniRivista";SqlConnection cn=newSqlConnection(Properties.Settings.Default.MoseDBConnectionString);SqlCommand cm = new SqlCommand(query);cm.Connection = cn;cn.Open();SqlDataReader dr = cm.ExecuteReader();while (dr.Read()) { listBox1.Items.Add(dr["ID_Titolo"]+", "+dr["Anno"]+", "+dr["Titolo"]); } dr.Close(); dr.Dispose();}catch (SqlException ex) { MessageBox.Show(ex.Message); }}Il file dialog per la selezione del documento da caricare viene invece apertocliccando sul pulsante Sfoglia (btnSfoglia) , si riporta di seguito il codice relativo:private void btnSfoglia_Click(object sender, RoutedEventArgs e) 17
  • 18. { Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog(); Microsoft.Win32.OpenFil Nullable<bool> result = dlg.ShowDialog(); > if (result == true true) { string filename = dlg.FileName; // aggiorno il contenuto della textbox textBox1.Text = filename; } }Una tipica esecuzione dellupload è rappresentata in pseudo codice in Figura 8 : rappresentata Figura 8Di seguito è riportato il codice delleffettivo upload del documento:private bool Upload(string myFile) string { try 18
  • 19. { //UPLOAD SU SQL SERVER SqlConnection connection1 = new SqlConnection(Properties.Settings.Default.MoseDBConnectionString); string id = listBox1.SelectedItem.ToString(); string[] words = id.Split(,); //creo un array contenente i campi della selezione SqlCommand command = new SqlCommand("select IDTitolo from TBL_PDFDocument where IDTitolo=" + words[0]); command.Connection = connection1; connection1.Open(); //apro la connessione if (command.ExecuteScalar() != null){ connection1.Close(); } else { //se non cè il documento nel db lo inserisco connection1.Close(); SqlCommand insertPdf = new SqlCommand("insert into TBL_PDFDocument values (" + words[0] + " , " + "P" + returnID() + ".pdf)"); insertPdf.Connection = connection1; connection1.Open(); insertPdf.ExecuteNonQuery(); connection1.Close(); } connection1.Close(); //UPLOAD SU SHAREPOINT WebClient client = new WebClient(); //vado a reperire le credenziali dellutente client.Credentials = new System.Net.NetworkCredential(textBox4.Text, passwordBox1.Password, textBox5.Text); string url="http://"+textBox2.Text+":" + textBox3.Text+"/"; client.UploadFile(url+"P"+returnID()+".pdf" , "PUT", myFile); client.Dispose(); MessageBox.Show("upload su sharepoint e su sql eseguito nDocumento : p"+returnID()+".pdf");}catch (Exception err) { MessageBox.Show(err.Message); 19
  • 20. return false; } return true; }Analisi del codice [ metodo Upload ]Come si puo notare il metodo è diviso fondamentalmente in due parti parti:laggiornamento di record su SQL Server e lupload su SharePoint.Per quanto riguarda laggiornamento del record su SQL Server , le fasi direalizzazione sono: • creazione di un nuovo oggetto Connection (per poter comunicare con listanza di SQL Server) e in particolare attraverso lutilizzo della MoseDBConnectionString. • reperimento dellID del documento selezionato dalla listbox , attraverso un metodo abbastanza rudimentale ma efficace: ovvero, viene effettuato un parsing dellelemento selezionato (in formato stringa) al fine di estrarre il primo membro separato da virgola, ovvero lID della pubblicazione • costruzione della query in linguaggio Transact-SQL Questa query fornisce un risultato numerico, se il documento è già presente nella tabella (tabella delle pubblicazioni aventi già un file relativo caricato), altrimenti restituisce un valore nullo se questo file non è presente: • Se il record è già presente nella tabella, questo record non viene aggiornato; • Se il record non è presente viene eseguita una nuova query (statement di tipo INSERT ) che inserisce nella tabella (ID, nome del file).E da notare che il nome del file , obbedisce ad uno standard dovuto ad un vincoloimposto dalla web application ,che lavora in parallelo con questa applicazione , inparticolare il nome del file dovrà essere nel formato "Pxxxx.pdf" dove xxxx 20
  • 21. rappresenta lid della pubblicazione (ad es. se lid della pubblicazione è 16 , ildocumento si chiamerà "p0016.pdf").Il metodo returnID() è un semplice metodo che utilizza lID della pubblicazioneselezionata e crea la parte numerica del nome del file apponendo a sinistra dellIDtanti zeri quanti sono necessari al fine di ottenere un nome con 4 cifre .private string returnID() { string id = listBox1.SelectedItem.ToString(); string[] words = id.Split(,); string returnstring; if (words[0].Length == 1) { returnstring = "000" + words[0]; return returnstring; } else if (words[0].Length == 2) { returnstring = "00" + words[0]; return returnstring; } else if (words[0].Length == 3) { returnstring = "0" + words[0]; return returnstring; } else { return words[0]; } }Per quanto riguarda lupload del documento su SharePoint upload SharePoint: • in input si riceve il path del file (locale) da caricare; • viene creato un oggetto di tipo client che sarà il virtuale esecutore dellupload; • a questo oggetto vengono assegnate le credenziali per la richiesta http , che saranno reperite dalle textBox (Username e Dominio) e dalla passwordBox (Password); • viene costruita la stringa dellurl nel quale sarà caricato il file andando a reperire le informazioni dalle textBox (Server e Folder); 21
  • 22. • attraverso il metodo UploadFile delloggetto di tipo WebClient viene poi ttraverso caricato il documento su SharePoint , per mezzo di una richiesta HTTP di tipo PUT.4.2 Cancellazione di files Figura 9E stata implementata un interfaccia utente per migliorare linterazione con lefunzionalità aggiunte e per dare allutente la possibilità di cancellare un file pdf pdf.Nella schermata relativa al dettaglio della pubblicazione (Figura 9 ) sono statiaggiunti : • un indicatore che segnala se è presente o meno, nel database ,un file relativo alla pubblicazione selezionata selezionata; • un pulsante che rimanda alla finestra di upload; • un pulsante che permette, in caso di presenza di un file, di cancellarlo. presenzaÈ più interessante concentrarsi sullimplementazione di questultimo considerata lasemplicità degli altri controlli citati.Come per lupload del documento, la cancellazione dovrà essere effettuata su effettuataentrambi i "lati" (SQL Server e SharePoint) SQL SharePoint). 22
  • 23. Per il primo contesto viene eseguita una query del tipo : "delete fromTBL_PDFDocument where IDTitolo= ".Mentre per la cancellazione in ambiente SharePoint viene eseguita una richiestahttp di tipo DELETE, corredando la request delle credenziali opportune.Si riporta di seguito il codice utilizzato per la cancellazione del documento.Figura 10 private void DeletePDF() { try { //CANCELLAZIONE SU SQL SERVER System.Windows.Window loading = new System.Windows.Window { Height = 100, Width = 200, WindowStartupLocation = WindowStartupLocation.CenterScreen, WindowStyle = WindowStyle.None }; loading.Content = new TextBlock { Text = "Please Wait", FontSize = 30, FontWeight = FontWeights.Bold, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center }; loading.Show();// Mostra finestra di attesa tblTitoli currentTitle = (tblTitoli)this.MasterView.CurrentItem; 23
  • 24. int IDTitolo = currentTitle.ID_Titolo; SqlConnection connection1 = newSqlConnection(Properties.Settings.Default.MoseDBConnectionString); SqlCommand command = new SqlCommand("delete from TBL_PDFDocument where IDTitolo=" + IDTitolo); command.Connection = connection1; connection1.Open(); command.ExecuteNonQuery(); connection1.Close(); label1.Content= SetLabel(); //CANCELLAZIONE SU SHAREPOINT string nomeFile = "P" + returnID() + ".pdf"; string url = "http://"+Properties.Settings.Default.Server+":" +Properties.Settings.Default.Sito +"/"+nomeFile; //server:sito HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(url); req.Credentials = new System.Net.NetworkCredential(Properties.Settings.Default.Username, Properties.Settings.Default.Password, Properties.Settings.Default.Dominio); req.Method="DELETE"; HttpWebResponse response = (HttpWebResponse)req.GetResponse(); loading.Close(); MessageBox.Show("Il documento : P" + returnID() + ".pdf è stato eliminato"); } catch (Exception e) { MessageBox.Show(e.Message); }} 24
  • 25. 4.3 Opzioni Utente Figura 11Il pulsante Opzioni (Figura 11) permette allutente di visualizzare una nuova finestra(Figura 12) allinterno della quale sarà possibile impostare dei valori di default perle credenziali, in modo tale da non dover selezionare il server ed autenticarsi ogniqualvolta si dovesse caricare o cancellare un documento da SharePoint.Queste impostazioni di configurazione, sono salvate, al primo utilizzodellapplicazione, nel file MoseUXPrototype,xml.config , mentre successivamente inautomatico, lapplicazione andrà a reperire questi settaggi da un file presente inC:/Users/NomeUser/AppData/Local/ che viene creato al primo utilizzo di questa .Allinterno di questa finestra, il pulsante Conferma esegue una modifica del valoredelle stringhe di default presenti nelle file di configurazione dellapplicazione: • Properties.Settings.Default.Server, • Properties.Settings.Default.Sito, • Properties.Settings.Default.Username, • Properties.Settings.Default.Password, • Properties.Settings.Default.Dominio. 25
  • 26. Figura 124.4 ExportQuesta funzione permette allutente di esportare in un foglio elettronico Excel idati delle pubblicazioni.In particolare le informazioni che possono essere reperite sono: • Anno di pubblicazione; • Titolo ; • Autore/i ; • Riferimento ; • Congresso (nel quale è stata presentata la pubblicazione) .Sono presenti inoltre alcuni filtri aggiuntivi che permettono di raffinare la ricerca: • intervallo di tempo (anni); • tipo di pubblicazione; • membro dello staff (autore).Come si può notare nellimmagine (Figura 13), lutente può scegliere se inserire omeno ognuno dei 5 campi in alto a sinistra , selezionando o deselezionando lecheckbox. 26
  • 27. Il processo di esportazionein formato Excel dei datirichiesti dallutente sisvolge in 4 passaggifondamentali: 1. operazioni preliminari (ad es. popolamento combobox) 2. costruzione della query da eseguire sulla base di dati, in base ai campi selezionati dallutente 3. compilazione di un Figura 13 file di testo semplice , utilizzando il delimitatore tab (t), utilizzando i dati di output della query 4. apertura del file di testo da parte dellapplicazione Excel riconoscendo il tabPrimo passoLa comboBox relativa ai membri dello staff si popola grazie ad una query eseguitasulla base di dati, questa query estrapola Nome e Cognome dei membri dello staffpublic void LoadCmbStaff() { try { 27
  • 28. SqlConnection cn = new SqlConnection(Properties.Settings.Default.MoseDBConnectionString); SqlCommand cm = new SqlCommand("SELECT Cognome , Nome FROM tblStaff"); cm.Connection = cn; cn.Open(); SqlDataReader dr = cm.ExecuteReader(); while (dr.Read()) { //popolamento della combobox cmbStaff.Items.Add(dr["Cognome"]+" , "+dr["Nome"]); } dr.Close(); dr.Dispose(); } catch (SqlException ex) { MessageBox.Show(ex.Message); } }Secondo passoLidea che sta alla base di questa implementazione è quella di analizzare elementoper elemento (Titolo, Autore, Anno, ecc ) le richieste dellutente e costruirecoerentemente la query.Lalgoritmo per la costruzione della stringa , che sarà il contenuto della query sicostituisce di 3 steps fondamentali, in base ai campi che vengono selezionati e inbase ai filtri che vengono attivati: • costruzione della stringa "SELECT …FROM…" • costruzione della stringa "WHERE …" • coordinamento del tutto e costruzione della stringa completa 28
  • 29. Nelle pagine seguenti viene riportato lalgoritmo in pseudocodice (Figure 14 e15): Stringa = «SELECT» Stringa1 = «WHERE» F F Anno is checked IF Dal != null T T Stringa1 = Stringa1 + Stringa = Stringa + «Anno» «ANNO >= Dal » F F Titolo is checked IF Al != null T T Stringa1 = Stringa1 + Stringa = Stringa + «Titolo» «ANNO <= Al » F F Autori is checked IF Autore != Tutti T T Stringa1 = Stringa1 + Stringa = Stringa + «Autori» «AUTORI LIKE ‘CognomeAutore’» F Riferimento is checked strWhere =14 Figura Stringa1 TStringa = Stringa + «Riferimento» F Denominazione is checked T Stringa = Stringa + «Denominazione» strSelect = Stringa Figura 14 29
  • 30. X = tipoPubblicazione T X==1 Query = strSelect + «FROM dbo.ViewPubblicazioniCongressi» +strWhere F T X==2 Query = strSelect + «FROM dbo.ViewPubblicazioniRiviste» +strWhere F T Query = strSelect + «FROM dbo.ViewPubblicazioniCongressi» +strWhere X==0 + «UNION» + strSelect + «FROM dbo.ViewPubblicazioniRiviste» +strWhere F Figura 15Il passaggio finale (Figura 15) è motivato dal fatto che è possibile che unapubblicazione sia riferita contemporaneamente ad una rivista e ad un congresso e congresso,quindi bisogna fornire allutente la possibilità di scegliere che tipo di datovisualizzare , se la prima, se la seconda o se entrambe.Di seguito si riporta il metodo per la creazione della parte iniziale della query:string CorpoStringCongressi = " FROM dbo.ViewPubblicazioniCongressi ";string CorpoStringRiviste = " FROM dbo.ViewPubblicazioniRivista ";private string CostruisciQueryIniziale() { string SelectBase = "SELECT "; string Supporto = SelectBase; if (checkBoxAnno.IsChecked == true) { /* Questi IF interni servono ad evitare il caso in cui ci si trovi ad avere una Select del tipo: >> SELECT , NOME << (virgola in mezzo) */ if (Supporto == "SELECT ") { Supporto = Supporto + " Anno ";} else { Supporto = Supporto + ", Anno "; 30
  • 31. } } if (checkBoxTitolo.IsChecked == true) { if (Supporto == "SELECT ") { Supporto = Supporto + " Titolo "; } else { Supporto = Supporto + ", Titolo "; } } if (checkBoxAutori.IsChecked == true) { if (Supporto == "SELECT ") { Supporto = Supporto + " Autori "; } else { Supporto = Supporto + ", Autori "; } } if (checkBoxRiferimento.IsChecked == true) { if (Supporto == "SELECT "){ Supporto = Supporto+" Riferimento"; } else { Supporto = Supporto + ", Riferimento "; } } if (checkBoxCongresso.IsChecked == true) { if (Supporto == "SELECT "){ Supporto =Supporto+" Denominazione";} else { Supporto = Supporto + ", Denominazione "; } } return Supporto;} 31
  • 32. Di seguito si riporta il codice relativo allo statement WHERE della query:private string CostruisciQueryWhere() { string Original = " WHERE "; string Supporto = Original; if (cmbStaff.Text != null && checkBoxStaff.IsChecked==false ) { //nella combobox sono presenti COGNOME,NOME io vado ad utilizzare solo //il cognome facendo un parsing della stringa cmbbox.text string autore =cmbStaff.Text.ToString(); string[] arr = autore.Split(,); if (Supporto == Original) //per risolvere il problema di "WHERE , //NOME STAFF.." SINTASSI T-SQL { Supporto = Supporto + " Autori LIKE %" + arr[0] + "% "; } else { Supporto = Supporto + " AND " + " Autori LIKE %" + arr[0] + "% "; } } if ( textBoxDal.Text!=null && textBoxDal.Text!=""){ if (Supporto == Original) { Supporto = Supporto + " Anno >= "+ textBoxDal.Text + " "; } else { Supporto = Supporto + " AND " + " Anno >= " + textBoxDal.Text + " "; } } if (textBoxAl.Text != null && textBoxAl.Text != "") { 32
  • 33. if (Supporto == Original) { Supporto = Supporto + " Anno <= " + textBoxAl.Text + " "; } else { Supporto = Supporto + " AND " + " Anno <= " + textBoxAl.Text + " "; } } //passaggio finale if (Supporto == Original) { return ""; } else { return Supporto; } }Infine si riporta il codice relativo alla concatenazione delle diverse sottostringhe ealla formazione query completa:private string CostruisciQuery() { string vuota = ""; string TotalQuery = vuota; if (cmbTipoPubb.SelectedIndex == 0) { TotalQuery = TotalQuery + CostruisciQueryIniziale() + " " + CorpoStringCongressi + CostruisciQueryWhere() + " UNION " + CostruisciQueryIniziale() + CorpoStringRiviste + CostruisciQueryWhere(); } else if (cmbTipoPubb.SelectedIndex == 1) 33
  • 34. { TotalQuery = TotalQuery + CostruisciQueryIniziale() + CorpoStringCongressi + CostruisciQueryWhere(); } else if (cmbTipoPubb.SelectedIndex == 2) { TotalQuery = TotalQuery + CostruisciQueryIniziale() + CorpoStringRiviste + CostruisciQueryWhere(); } else { TotalQuery = TotalQuery + CostruisciQueryIniziale() + CorpoStringCongressi + CostruisciQueryWhere() + " UNION " + CostruisciQueryIniziale() + CorpoStringRiviste + CostruisciQueryWhere(); } Console.WriteLine(TotalQuery); if (TotalQuery != vuota) { return TotalQuery; } else return vuota; }Terzo passoDi seguito si riporta il codice per la costruzione del file di testo:public string generaCsv(int colonne, string sqlCommand) { string csvFile = ".//TempFile.txt"; try { string connectionString = Properties.Settings.Default.MoseDBConnectionString; using (SqlConnection connection = new SqlConnection(connectionString)) { 34
  • 35. try { connection.Open(); } catch (System.Data.SqlClient.SqlException ex) { // handle return ""; } using (SqlDataAdapter adapter = new SqlDataAdapter(sqlCommand, connection)) { using (System.Data.DataTable table = new System.Data.DataTable("tbl")) { adapter.Fill(table); StringBuilder commaDelimitedText = new StringBuilder(); foreach (DataRow row in table.Rows) { for (int i = 0; i < colonne; i++) {/*Qui era sorto un problema, il mio "Generatore di Csv" , quando trovava 2 spaziconsecutivi li considerava come una nuovacolonna. risolto usando espressione regolare */ row[i] = Regex.Replace(row[i].ToString(), @"s+", " "); } switch (colonne) { case 1: { string value = string.Format("{0}", row[0]); commaDelimitedText.AppendLine(value); File.WriteAllText(csvFile,commaDelimitedText.ToString()); break; } case 2: { 35
  • 36. string value=string.Format("{0}t{1}", row[0], row[1]); commaDelimitedText.AppendLine(value); File.WriteAllText(csvFile,commaDelimitedText.ToString()); break; } case 3: { string value = string.Format("{0}t{1}t{2}", row[0], row[1], row[2]); commaDelimitedText.AppendLine(value); File.WriteAllText(csvFile,commaDelimitedText.ToString()); break; } case 4: { string value = string.Format("{0}t{1}t{2}t{3}",row[0], row[1], row[2], row[3]); commaDelimitedText.AppendLine(value); File.WriteAllText(csvFile,commaDelimitedText.ToString()); break; } case 5: { string value = string.Format("{0}t{1}t{2}t{3}t{4}", row[0], row[1], row[2], row[3], row[4]); commaDelimitedText.AppendLine(value); File.WriteAllText(csvFile,commaDelimitedText.ToString()); break; } } } } }} 36
  • 37. } catch (Exception ex) { System.Windows.MessageBox.Show(ex.Message); } return csvFile; }Analisi del codiceQuesto metodo sfrutta il metodo Contacolonne() che restituisce il numero di colonneche andranno a formare la tabella in formato Excel, il risultato di questo metodo èpassato come input (int colonne).È necessario contare le colonne perché la sintassi del comando string.Format(..)permette di stabilire un unico tipo di formattazione.Linput string sqlCommand è invece la query che sarà eseguita sulla base di dati.Sono stati identificati 5 casi possibili in base al risultato del metodo Contacolonne().Il riempimento del file di testo è effettuato attraverso un ciclo , allinterno delquale vengono copiati nel file i dati della tabella (risultato della query) apponendoun delimitatore /t eccezion fatta per lultima colonna ( /n). /t,Questo file viene salvato con il nome TempFile.txt nella cartella in cui è presenteleseguibile dellapplicazione, ed ogni qual volta verrà eseguita unoperazione diquesto tipo lo stesso file verrà riscritto prevenendo problemi di capienza dimemoria o di semplice esubero di file non necessari.Quarto passoUna volta creato il file di testo viene aperto un foglio elettronico Excel il qualeattraverso limpostazione che prevede il riconoscimento del delimitatore tab ( "/t" )popola le sue celle in base a quanto contenuto nel file di testo. 37
  • 38. Successivamente verranno inserite le intestazioni delle colonne attraverso ilmetodo generaIntestazioniExcel().Il metodo CSVtoExcel prende in input: • il path del file che si vuole aprire; • il foglio Excel nel quale aprire il file; • le coordinate della cella da cui iniziare la popolazione delle celle; • un array di tipi di dato per le rispettive colonne; • un valore booleano che che imposta lautodimensionamento (o meno) delle colonne.Di seguito si riporta il codice del metodo in questione:public void CSVtoExcel(string importFileName, Excel.Worksheet destinationSheet, Excel.Range destinationRange, int[] columnDataTypes, bool autoFitColumns) { destinationSheet.QueryTables.Add( "TEXT;" + System.IO.Path.GetFullPath(importFileName),destinationRange, Type.Missing); destinationSheet.QueryTables[1].Name = System.IO.Path.GetFileNameWithoutExtension(importFileName); destinationSheet.QueryTables[1].FieldNames = true; destinationSheet.QueryTables[1].RowNumbers = false; destinationSheet.QueryTables[1].FillAdjacentFormulas = false; destinationSheet.QueryTables[1].PreserveFormatting = true; destinationSheet.QueryTables[1].RefreshOnFileOpen = false; destinationSheet.QueryTables[1].RefreshStyle = XlCellInsertionMode.xlInsertDeleteCells; destinationSheet.QueryTables[1].SavePassword = false; destinationSheet.QueryTables[1].SaveData = true; destinationSheet.QueryTables[1].AdjustColumnWidth = true; destinationSheet.QueryTables[1].RefreshPeriod = 0; destinationSheet.QueryTables[1].TextFilePromptOnRefresh = false; //lid 65001 rappresenta lid della piattaforma che decodifica i contenuti in UTF-8 destinationSheet.QueryTables[1].TextFilePlatform = 65001; destinationSheet.QueryTables[1].TextFileStartRow = 1; 38
  • 39. destinationSheet.QueryTables[1].TextFileParseType = XlTextParsingType.xlDelimited; destinationSheet.QueryTables[1].TextFileTextQualifier = XlTextQualifier.xlTextQualifierDoubleQuote; destinationSheet.QueryTables[1].TextFileConsecutiveDelimiter = false; destinationSheet.QueryTables[1].TextFileTabDelimiter = true; destinationSheet.QueryTables[1].TextFileSemicolonDelimiter = false; destinationSheet.QueryTables[1].TextFileCommaDelimiter = false; destinationSheet.QueryTables[1].TextFileSpaceDelimiter = false; destinationSheet.QueryTables[1].TextFileColumnDataTypes = columnDataTypes; destinationSheet.QueryTables[1].Refresh(false); if (autoFitColumns == true) { destinationSheet.QueryTables[1].Destination.EntireColumn.AutoFit(); } }Mentre il pulsante che aziona questo meccanismo agisce in questo modo: vieneaperta inizialmente una finestra che avvisa lutente di attendere lesecuzione delprocesso, viene aperto un foglio Excel (non visibile ancora allutente), vienegenerato il file di testo sopra citato, viene eseguito il metodo CsvToExcel ,vengono generate le intestazioni per le colonne del file Excel , dunque sparisce lafinestra di attesa e viene visualizzato il file.private void button1_Click(object sender, RoutedEventArgs e) { try { System.Windows.Window loading = new System.Windows.Window {Height = 100, Width = 200, WindowStartupLocation = WindowStartupLocation.CenterScreen, WindowStyle = WindowStyle.None }; 39
  • 40. loading.Content = new TextBlock { Text = "Please Wait", FontSize = 30,FontWeight = FontWeights.Bold, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center }; loading.Show(); Excel.Application xla = new Excel.Application(); Excel.Workbook wb = xla.Workbooks.Add(Excel.XlSheetType.xlWorksheet); Excel.Worksheet ws = (Excel.Worksheet)xla.ActiveSheet; xla.Visible = false; int cln = contacolonne(); string filepath = generaCsv(cln, CostruisciQuery()); CSVtoExcel(filepath, (Excel.Worksheet)(wb.Worksheets[1]),(Excel.Range)(((Excel.Worksheet)wb.Worksheets[1]).get_Range("$A$2")), new int[] { 2, 2, 2, 2, 2 }, true); //Come ultima cosa inserisco le intestazioni delle colonne List<string> lista = generaIntestazioniExcel(); for (int i = 0; i < cln; i++) { ws.Cells[1, i + 1] = lista[i]; } xla.Visible = true; wb.ActiveSheet.QueryTables[1].Delete(); loading.Close(); } catch (Exception myex) { MessageBox.Show(myex.Message); } } 40
  • 41. Il risultato di un possibile Export può essere:(a) Creazione del file txt, non visibile allutente(b) Apertura del file da parte di Excel4.5 Implementazioni di carattere generaleSempre nellottica di migliorare ulteriormente linterfaccia utente per renderla piùfunzionali ai bisogni del committente sono implementate alcune features , diminor rilevanza per, ma di indubbia utilità per lutente: • nella pagina relativa alle pubblicazioni in formato-griglia, viene aggiunta una colonna che presenta il nome del documento pdf , se presente, o nulla in caso contrario (Figura 16); • per le pagine "PubblicationGrid" e "PubblicationCustom" è stato riscritto , in modo coerente con le modifiche apportate, il codice che permette allutente di accedere ai dettagli della pubblicazione selezionata cliccando due volte sulla riga della griglia; • sono stati abilitati, nella home page, i link testuali che rimandano alle pagine relative (come Upload e Export) e sono stati modificati i label relativi alla versione ed al nome dellapplicazione. 41
  • 42. Figura 16 42
  • 43. CAPITOLO 5Conclusioni5.1 Possibili miglioramentiSvolgendo questo lavoro si è pensato inoltre a possibili miglioramenti , chepotrebbero essere sviluppati in futuro.Tra i quali quelli di maggior rilevanza sono: • funzionalità di import: permettere allutente di effettuare un importazione di dati, da tabella excel, in modo tale da non dover inserire i record manualmente (ad esempio : nome, cognome e dati anagrafici di un nuovo membro dello staff). Questa feature alleggerirebbe ancor di più il lavoro per lutente che attualmente deve inserire i nuovi dati , pur sempre via applicazione, ma manualmente • versione web dellapplicazione, completamente svincolata quindi dal Pc dellutente . Possibile utilizzo della tecnologia ASP.NET5.2 ConclusioniFeatures implementate Upload PDF Cancella PDF Export Gestione Credenziali 43
  • 44. Lobiettivo di implementare tutte le funzionalità richieste dal committente è statoraggiunto.Per quanto riguarda invece le conoscenze e le abilità acquisite, sono stati raggiuntii seguenti obiettivi: • raccolta dei requisiti mediante intervista al committente • analisi della situazione esistente • studio di .NET e di Windows Presentation Foundation • studio di Database Relazionali • studi sulle comunicazioni tra le diverse entità (server, applicazione, db)Lapplicazione ora non è più in fase di test (beta), ma è a tutti gli effetti in uso ,nella sua versione 2.0 2.0.Righe di codice scritte : • C# : 700 • XAML : 300 44
  • 45. Bibliografia • http://msdn.microsoft.com/en-us/library/aa970268.aspx (Introduction to WPF - MSDN) • M. Miotto, "Progettazione e sviluppo di una applicazione per la gestione di dati bibliografici in ambiente .NET " , Tesi per corso di laurea triennale in Ingegneria Informatica (Università degli studi di Trieste) • Dispense del corso di Basi di Dati tenuto dal Dott. Fermeglia presso lUniversità degli Studi di Trieste • http://msdn.microsoft.com/it-it/library/ms254978(v=vs.110).aspx • http://stackoverflow.com/questions/8947410/using-settings-settings-in-a- windows-wpf-app-vs2010 • http://www.codeproject.com/Articles/19509/Write-Data-to-Excel-using-C • Adam Nathan - WPF 4 Unleashed - Pearson Education (US) – 2010 • http://blogs.msdn.com/b/pietrobr/archive/2007/09/07/parliamo-di-linq- parte-3.aspx • http://msdn.microsoft.com/it-it/vcsharp/cc788743(en-us).aspx 45