
Buenas
mientras descanso en las minivacaciones de semana santa completamente desenchufado y con un par de cervezas near to me, me quedó en la cabeza el post de David relacionado con el OpenXML, mientras también pensaba en cuando Luis nos comentó algo sobre los clásicos problemas con el COM Interop de Office y la solución que tuvo que aplicar.
Uno de los problemas que tenemos al tratar de interactuar con documentos de Office 2003, es que además de crear una instancia de cada uno de los objetos necesarios utilizando COM Interop, debemos cargar la instancia casi completa de la aplicación en memoria para poder cargar el documento sobre el que queremos trabajar. El nuevo formato Open XML realmente nos facilita mucho las cosas. Microsoft ha publicado las especificaciones para los archivos de Word 2007, Excel 2007 y Powerpoint 2007; cada uno de estos productos gestionan sus archivos con un formato interno basado en XML, lo que hace que la interacción con estos documentos desde una aplicación .Net sea mucho más simple.
(este es un post y no un artículo asi que me reservo la info técnica, aunque si alquien quiere más información puede comenzar por aquí y tal vez seguir por aquí)
Creación de un documento Word 2007
Para demostrar como podemos intearctuar con los nuevos documentos me plantee como objetivo escribir un par de líneas de código que modifiquen un documento Word 2007 utilizando clases nativas de .Net.
Para esto primero crearemos un documento con Word 2007, agregaremos un contenido superoriginal dentro del mismo y lo grabaremos, en este caso en C:\Hello World.docx.
Un detalle interesante a tener en cuenta una vez creado el documento de ejemplo, es conocer como esta compuesto internamente el mismo. La mejor forma de hacerlo es cambiar la extensión del archivo por zip y ver la estructura del mismo. Como muestra la siguiente imagen, el documento docx realmente es un archivo comprimido zip y dentro del mismo se almacenan una serie de documentos xml que son los que contienen la información del documento word.
Por ejemplo, el archivo xml core.xml situado en el directorio docProps, contiene las propiedades del documento word y dentro del mismo podemos encontrar la siguiente información:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:dcmitype="http://purl.org/dc/dcmitype/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<dc:title>Ejemplo de modificacion con .Net</dc:title>
<dc:creator>Bruno Capuano</dc:creator>
<cp:keywords>.Net, Visual Studio</cp:keywords>
<cp:lastModifiedBy>Bruno Capuano</cp:lastModifiedBy>
<cp:revision>4</cp:revision>
<dcterms:created xsi:type="dcterms:W3CDTF">2007-04-07T16:44:00Z</dcterms:created>
<dcterms:modified xsi:type="dcterms:W3CDTF">2007-04-07T17:15:00Z</dcterms:modified>
</cp:coreProperties>
que se corresponde con cada una de las propiedades que hemos definido en el documento
Actualizando el documento utilizando .Net Framework
Pues bien, después de ver como está constituido un documento Word 2007, y ver que simplemente es un archivo comprimido lleno de xmls; se nos pueden ocurrir varias opciones si comenzamos a pensar en las opciones para modificar el mismo utilizando .Net.
En este caso, me aprovecharé de una de las nuevas librerías que trae el .Net Framework 3.0: System.IO.Packaging.Package contenido en el assembly WindowsBase. Esta librería permite organizar objetos/archivos en una sola entidad de un formato físico determinado, usualmente un ZIP. Como un sistema de ficheros, los archivos contenidos en un paquete se organizan utilizando carpetas y archivos.
Basado en que el documento se encuentra en la ubicacion C:\Hola Mundo.docx (recuerden renombrarlo nuevamente por docx si no lo han hecho), el código VB.Net para modificar el mismo es el siguiente:
1 Imports System.IO
2 Imports System.IO.Packaging
3 Imports System.Xml
4
5 Public Class Form1
6
7 Private Sub ChangeDoc()
8
9 ' open Word 2007 Document
10 Dim wordDocFile As System.IO.Packaging.Package
11 wordDocFile = Package.Open("c:\Hola Mundo.docx")
12
13 ' open Documtn in Xml Format
14 Dim wordDoc As New XmlDocument()
15 Dim pathtodoc As New Uri("/word/document.xml", UriKind.Relative)
16 Dim newPart As PackagePart = wordDocFile.GetPart(pathtodoc)
17 wordDoc.Load(newPart.GetStream(FileMode.Open, FileAccess.Read))
18
19 ' get and update text/data nodes
20 Dim textNodes As XmlNodeList = wordDoc.GetElementsByTagName("w:t")
21 For Each xmlnode As XmlNode In textNodes
22 ' add now datetime to text nodes
23 xmlnode.InnerText = String.Format("{0} [DateTime:{1}]", xmlnode.InnerText, Now.ToString)
24 Next
25
26 ' update and save document
27 Using infoStream As Stream = newPart.GetStream(FileMode.Create, FileAccess.Write)
28 wordDoc.Save(infoStream)
29 End Using
30
31 End Sub
32
33 End Class
34
Como se puede ver, en las líneas 10 y 11 utilizo la clase Package para abrir el documento y luego en la línea 17 abro un XmlDocument() con el contenido del archivo /word/document.xml que es el archivo que contiene toda la información del documento word que hemos creado. A continuación recorro los nodos que almacenan el texto del documento y agrego a los mismos la fecha y hora actual (línea 23).
Finalmente actualizo el documento utilizando un Stream() y como resultado final, si abrimos nuevamente el documento podremos ver que el mismo se ha modificado
A partir de este momento, crear apliaciones que necesiten manejar archivos propios de Office 2007 se torna mucho mas simple. En los 20 min. que utilicé para escribir este post, no he tenido tiempo de buscarlos, pero estoy seguro de haber visto en la web, algunas librerias que nos facilitan mucho mas este trabajo, encapsulando este proceso de los archivos xml en componentes mucho mas orientados hacia una aplicación.
Y si todavía no están online, es buen momento para crearlas ¿no? :P
Saludos
El Bruno
Crossposting from
ElBruno.com