Office Web Components in programmi C# da http://escher07.altervista.org Generalità L obiettivo è realizzare un programma C# che utilizzando il componente Web Pivot permetta di ottenere un risultato come il seguente: Figura 1 Nel quale in una form compare un componente Tabella Pivot caricato con i dati di una tabella proveniente da un DB che permette di eseguire analisi OLAP (es. Drill Down) sui dati in questione. Implementazione I dati saranno prelevati da un DB Oracle e si utilizzerà la seguente architettura:
In pratica un opportuno Web Service preleva i dati dal DB utilizzando la tecnologia ADO : la form invocando il corrispondente Web Method carica localmente i dati che saranno consumati dalla tabella Pivot. Web Service Per scrivere il nostro WS saremo molto sintetici : il che vuol dire ad esempio che non ci occuperemo né degli aspetti di sicurezza né di flessibilità per minimizzare il codice. In pratica il nostro WS esporrà un unico metodo che non richiederà né argomenti né autenticazioni ovvero GetAdo XML(). E chiaro che in una soluzione da utilizzare in produzione sarebbe opportuno curarsi di entrambi gli aspetti ad esempio prevedendo gli argomenti ComandoSQL, Utente, Password. Per i nostri scopi il WS deve costruire un ADO Recordset e restituirlo come stringa rappresentato in XML. Affinché l office data source control lo possa utilizzare è fondamentale che sia tradotto in XML attraverso il metodo Save un recordset ADO e non ad esempio un semplice DataSet. Praticamente possiamo verificare come il primo sia fatto così: Mentre il secondo sia ben più ricco:
Operativamente per scrivere il WS si procede come segue. Da Visual Web Developer si sceglie File/New Web Site e poi: L applicazione /ced/wsced deve essere stata definita su IIS nella directory root con permessi di esecuzione solo script. Fatto questo si crea una cosa del genere: Nel file WSced.cs aggiungiamo il seguente Web Method: [WebMethod] public string GetAdoXML()
ADODB.Connection m_adocnn = new ADODB.Connection(); ADODB.Recordset m_adorst = new ADODB.Recordset(); ADODB.Stream m_stream = new ADODB.Stream(); string m_adocnnstr =""; string m_sqlcmd = "SELECT * FROM TuaTabella"; m_adocnnstr = "Provider=MSDAORA;Password=TuaPassword;User ID=TuoOracleUser;Data Source=TuoServerOracle"; m_adocnn.connectionstring = m_adocnnstr; m_adocnn.open(m_adocnnstr, "", "", 0); m_adorst.open(m_sqlcmd, m_adocnn, CursorTypeEnum.adOpenStatic, LockTypeEnum.adLockBatchOptimistic, -1); m_adorst.save(m_stream,persistformatenum.adpersistxml); return m_stream.readtext(-1); Notare la connessione ADO che per provider nella ConnectionString utilizza MSDAORA ed il riempimento del recordset ADO facendo riferimento al comando SQL e alla connessione precedentemente aperta. Notare infine l invocazione del metodo save dell ADO recordset con l opzione adpersistxml. L argomento -1 in Read Text vuol dire leggi tutto il file. Soluzione C# L idea è quella di incorporare la tabella Pivot in un controllo Utente. In VS Express si può procedere come segue. Innanzitutto da File/New creiamo una nuova Class Library: Dal solution Explorer cancelliamo Pivot.cs e salviamo il tutto. Notiamo che questo è uno stratagemma perché in teoria per creare user control servirebbe una versione a pagamento di Visual Studio. A questo punto devono essere impostate le giuste reference, in particolare alle DLL che contengono gli OWC OWC11.dll e AxOWC11.dll (la DLL che permette l interoperabilità COM-CLR per i componenti in questione) e aggiunto il controllo Tabella Pivot alla toolbox. Ovvero da Add/References:
e poi da Choose Items : Dal menù contestuale (click dx) della toobox. Se tutto è stato fatto correttamente la toobox si presenterà così:
NB: il data source control al momento non serve, semplicemente mi faceva fatica rimuoverlo per stampare la videata. Dovrà comparire obbligatoriamente invece più avanti. Nella form trasciniamo la nostra Microsoft Pivot Table 11.0 e nel codice Pivot.Designer.cs mettiamo le proprietà e gli eventuali metodi esposti. Ad esempio: public string PivotConnectionString get return this.axpivottable1.connectionstring; set this.axpivottable1.connectionstring = value; public string PivotDataMember get return this.axpivottable1.datamember; set this.axpivottable1.datamember = value; public string PivotCommandText get
set return this.axpivottable1.commandtext; this.axpivottable1.commandtext = value; public string PivotCubeProvider get return this.axpivottable1.cubeprovider; set this.axpivottable1.cubeprovider = value; public object PivotDataSource get return (object)this.axpivottable1.datasource; set this.axpivottable1.datasource = (msdatasrc.datasource)value; public string PivotXMLData get return this.axpivottable1.xmldata; set this.axpivottable1.xmldata = value; private AxMicrosoft.Office.Interop.Owc11.AxPivotTable axpivottable1; Fatto questo aggiungiamo un nuovo progetto alla soluzione (da Solution Explorer File/Add/New Project) rendiamolo progetto di Start up. Mettiamo le giuste reference, ovvero:
Se tutto è stato fatto correttamente la toolbox si presenterà come prima riportato (quindi anche con DSC) e dopo aver lanciato la compilazione avremo anche il nostro user control trascinabile nella form: Si tratta ora di trascinare nella form lo user control che abbiamo fatto ed un componente Data Source, che sarà quello che riceverà i dati dal WS e, dopo aver costruito in RAM il cubo li passerà alla Pivot per la presentazione. In pratica il form builder si presenterà così:
Il WS per poter essere utilizzato dovrà essere referenziato nella soluzione (con Add Web Reference da Solution Explorer) per cui alla fine il solution explorer medesimo si presenterà così:
Si tratta ora di scrivere il gestore del click del bottone carica, cosa che sarà fatta in questo modo: private void button1_click(object sender, EventArgs e) localhost.wsced objwebmethod = new localhost.wsced(); string strresult = ""; string strdatafile = "";
strdatafile = "mydata.xml"; strresult = objwebmethod.getdataxml(); XmlDocument xmldoc = new XmlDocument(); xmldoc.loadxml(strresult); xmldoc.save(strdatafile); if (this.axdatasourcecontrol1.connectionstring == null) this.axdatasourcecontrol1.connectionstring = "provider=mspersist"; this.axdatasourcecontrol1.recordsetdefs.addnew(strdatafile, 5,"dscData"); pivot1.pivotdatasource = this.axdatasourcecontrol1.defaultrecordset.datasource; pivot1.pivotconnectionstring = "provider=mspersist"; pivot1.pivotcommandtext = strdatafile; Riguardo al bottone Show HTML l ho messo per controllo. In pratica mostra la definizione (non i dati!) nella pivot table e corrisponde al seguente codice: private void button2_click(object sender, EventArgs e) textbox1.text = pivot1.pivotxmldata; Il suo output sarà qualcosa del genere: <xml xmlns:x="urn:schemas-microsoft-com:office:excel"> <x:pivottable> <x:owcversion>12.0.0.4518 </x:owcversion> <x:displayscreentips/> <x:cubeprovider>msolap.2</x:cubeprovider> <x:displayfieldlist/> <x:fieldlisttop>188</x:fieldlisttop> <x:fieldlistleft>644</x:fieldlistleft> <x:fieldlistbottom>559</x:fieldlistbottom> <x:fieldlistright>844</x:fieldlistright> <x:cachedetails/> <x:connectionstring>provider=mspersist.1</x:connectionstring> <x:commandtext>mydata.xml</x:commandtext> <x:name>tabella pivot di Microsoft Office 11.0</x:Name> <x:pivotfield> <x:name>num_ticket</x:name> <x:datatype>number</x:datatype> <x:encodedtype>adnumeric</x:encodedtype> <x:compareorderedmembersby>uniquename</x:compareorderedmembersby> </x:pivotfield> <x:pivotfield> <x:name>anni3</x:name> <x:basefield>dat_scadenza2</x:basefield> <x:grouptype>years</x:grouptype> <x:plcaption>anni</x:plcaption> <x:encodedtype>adinteger</x:encodedtype> <x:numberformat>yyyy</x:numberformat> <x:compareorderedmembersby>name</x:compareorderedmembersby> </x:plpivotfield> <x:pivotdata> <x:top>0</x:top> <x:topoffset>0</x:topoffset> <x:left>0.0</x:left> <x:leftoffset>0</x:leftoffset> <x:seqnum>1</x:seqnum> <x:expanded/> </x:pivotdata> <x:pivotview>
<x:isnotfiltered/> </x:pivotview> </x:pivottable> </xml> ovvero i campi del cubo (quelli che compaiono sulla destra nella Figura 1) e i formati della tabella. Links http://forums.microsoft.com/msdn/showpost.aspx?postid=1144426&siteid=1 Creare uno User Control in VS Express. http://blog.shareoffice.it/emanuele/archive/2006/10/08/7951.aspx Creare una tabella pivot in Visual Basic.Net http://support.microsoft.com/kb/555237/it Risorse di Microsoft Office Web Components http://aspnetresources.com/articles/office_web_components.aspx Building Dazzling Chart With Office Web Components