post icon

How to Create Excel file Programmatically

Come creare un file Excel dinamicamente

Sempre più spesso mi capita di dover generare dinamicamente un file Excel senza che sul Server sia disponibile l’Excel services e quindi senza poter utilizzare le classi native di Microsoft Office per generare gli Excel programmaticamente.

La logica in uso è la seguente:

  • Creiamo un file di template XML Spreadsheet 2003 (per la versione in Italiano, Foglio di calcolo XML 2003).
    Si tratta di un vero e proprio file XML creato con Microsoft Office Excel e compatibile con le versioni precedenti di Office 2003.
    Scarica il template file di esempio: template.xml (3,03 kb)
  • Editiamo il file XML con un editor di testo e faciamo le seguenti modifiche:
    • Eliminiamo gli attributi ss:ExpandedColumnCount="3" e ss:ExpandedRowCount="2" che provocano un errore nell’apertura del file quando il numero di righe/colonne supera il valore specificato in questi attributi. Può tornare utile la seguente Regular Expression per sostituire rapidamente tutte le occorrenze di RowCount: (ss\:ExpandedRowCount\=\")([0-9]+)\"
    • Aggiungiamo l’attributo id="tb_dinamica" al nodo <Table> che rappresenta la tabella nella quale andremo ad inserire dinamicamente le righe.
    • Aggiungiamo l’attributo id="row_template" al nodo <Row> che rappresenta la riga che andremo ad aggiungere dinamicamente.
      Nota: Nella riga template (riga vuota fittizia, vedi template.xml) deve essere presente almeno un carattere fittizio affinché possa essere rilevato al suo interno il nodo <Data>.
      Scarica il template adattato: template_edited.xml (3,02 kb)
  • Creiamo le classi e i metodi per leggere la riga template dall’XML ed inserirne nuove in maniera dinamica.

Per poter leggere il template XML come XmlDocument è necessario istanziare anche un oggetto di tipo XmlNamespaceManager, che consente di gestire i nodi dell’XML con i namespace di Office.
Ecco lo snippet per la dichiarazione dell’XmlNamespaceManager:

XmlNamespaceManager nsMgr = new XmlNamespaceManager(xmlDoc.NameTable); nsMgr.AddNamespace("d", "urn:schemas-microsoft-com:office:spreadsheet"); nsMgr.AddNamespace("o", "urn:schemas-microsoft-com:office:office"); nsMgr.AddNamespace("x", "urn:schemas-microsoft-com:office:excel"); nsMgr.AddNamespace("ss", "urn:schemas-microsoft-com:office:spreadsheet"); nsMgr.AddNamespace("html", "http://www.w3.org/TR/REC-html40");

Una volta creato il namespace manager accedo alla riga template con il seguente code snippet:

//Recupero la riga templateXmlNode rowTemplate; rowTemplate = xmlDoc.SelectSingleNode("//d:Row[@id='row_template']", nsMgr).CloneNode(true); //tolgo l'attributo ID fittiziorowTemplate.Attributes["id"].RemoveAll();

Quindi aggiungo dinamicamente le righe nel modo seguente:

//Recupero il nodo TableXmlNode _tableNode; _tableNode = xmlDoc.SelectSingleNode("//d:Table[@id='tb_dinamica']", nsMgr); //Rimuovo il nodo template di riga_tableNode.RemoveChild(xmlDoc.SelectSingleNode("//d:Row[@id='row_template']", nsMgr)); //Aggiungo righe dinamichefor (int i = 0; i < 5000; i++){ //Mi creo un template di riga corrente XmlNode currentNode = rowTemplate.CloneNode(true); //Nome currentNode.ChildNodes[0].ChildNodes[0].InnerText = "Mario"; //Cognome currentNode.ChildNodes[1].ChildNodes[0].InnerText = "Rossi"; //Data di nascita currentNode.ChildNodes[2].ChildNodes[0].InnerText = "10/01/1970"; //Aggiungo la riga corrente alla Table _tableNode.AppendChild(currentNode); }

 

Scarica lo snippet completo: CreateExcel.zip (3,89 kb)

30 giugno 2009 @ 15:27

No comments yet.

Leave a comment

Leave a Reply

Are you human? Time limit is exhausted. Please reload CAPTCHA.