Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Resumen: aprenda a usar Open XML SDK 2.0 para manipular un libro de Microsoft Excel
2010.
Hace referencia a: Excel 2010 | Office 2010 | Open XML | SharePoint Server 2010 | VBA
Contenido
Open XML es un formato de archivo abierto para las aplicaciones principales de Office,
orientadas a documentos. Open XML representa de manera fiel documentos de
procesamiento de texto, presentaciones y hojas de cálculo existentes y codificados en
formato binario según las aplicaciones de Microsoft Office. Los formatos de archivo Open
XML ofrecen varias ventajas. Una ventaja es que con los formatos de archivo Open XML
cualquier programa que entienda el formato del archivo puede tener acceso a los datos
contenidos en el documento. De este modo, las organizaciones tienen la seguridad de que
los documentos que crean hoy seguirán siendo válidos en el futuro. Otra ventaja es que
facilita la creación de documentos y la manipulación en entornos de servidor u otros
entornos en los que no se pueden instalar aplicaciones cliente de Office.
Como indica el nombre, los archivos Open XML se representan mediante XML. No
obstante, en lugar de representar un documento usando un único archivo XML grande, un
documento Open XML se representa en realidad usando un conjunto de archivos
relacionados, denominados partes, que se almacenan en un paquete que después se
comprime en un archivo ZIP. Los paquetes de documentos Open XML son compatibles con
la especificación Open Packaging Conventions (Convenciones de empaquetado abierto,
OPC), una tecnología de archivo-contenedor que sirve para almacenar una combinación de
archivos XML y no XML que en su conjunto forman una entidad única.
Una de las mejoras maneras de empezar a comprender cómo funciona todo en conjunto es
abrir un archivo de libro y examinar sus partes. Para estudiar las partes de un paquete de
libro de Microsoft Excel 2010, basta con cambiar la extensión del nombre del archivo .xlsx
por .zip. Vea el ejemplo del libro mostrado en las figuras 1 y 2.
Este libro contiene dos hojas de cálculo: en la figura 1 se muestra una hoja de cálculo que
contiene las ventas anuales y en la figura 2 se muestra una hoja de cálculo que contiene un
gráfico sencillo.
XML
Copiar
<c r="C3" s="1">
<v>2008</v>
</c>
Para mantener el tamaño de los archivos Open XML lo más pequeño posible, muchos de
los nodos y atributos de XML tienen nombres muy cortos. En el fragmento anterior, c
representa una celda. Esta celda determinada especifica dos atributos: r (Referencia) y s
(Índice de estilos). El atributo de referencia especifica una referencia de ubicación para la
celda.
El índice de estilos es una referencia al estilo que se usa para dar formato a la celda. Los
estilos se definen en la parte de estilo (styles.xml) que se encuentra en la carpeta xl (vea la
carpeta xl en la figura 3). Compare el XML de la celda C3 con el de la celda C4 mostrado
en el ejemplo siguiente.
XML
Copiar
<c r="C4">
<v>182</v>
</c>
Aunque es muy útil saber más sobre las peculiaridades del formato de archivos Open XML,
la finalidad última de este artículo es mostrar cómo usar Open XML SDK 2.0 para
Microsoft Office para manipular mediante programación los documentos Open XML, en
particular, los libros de Excel.
Todos estos pasos, salvo el tres y el cuatro, pueden realizarse fácilmente usando las clases
que se encuentran en el espacio de nombres System.IO.Packaging. Estas clases están
pensadas para facilitar el trabajo con los paquetes y tareas de Open XML asociados con la
manipulación de partes en general.
El paso más complicado de este proceso es el cuarto, la manipulación del XML. Para este
paso es absolutamente necesario que el desarrollador conozca todos los tediosos detalles
necesarios para trabajar satisfactoriamente con las numerosas peculiaridades que presentan
los formatos de archivo Open XML. Por ejemplo, antes hemos aprendido que la
información de formato de una celda no se almacena con la celda, sino que la información
detallada de formato se define como estilo en una parte de documento diferente y que el
índice de estilos asociado con el estilo es lo que Excel almacena en la celda.
Open XML SDK 2.0 se desarrolló para facilitar la manipulación de los paquetes Open
XML y los elementos de esquema Open XML subyacentes en el interior del paquete. Open
XML SDK 2.0 encapsula muchas tareas comunes que los desarrolladores realizan en los
paquetes Open XML de modo que en lugar de trabajar con XML sin formato, puede usar
las clases de .NET que le proporcionan muchas ventajas durante el diseño, como
compatibilidad con IntelliSense y desarrollo con seguridad de tipos.
Nota
Descargue Open XML SDK 2.0 del Centro de descarga de Microsoft.
Con el objeto de mostrar cómo se manipula un libro de Excel con Open XML SDK 2.0,
este artículo explica cómo crear un generador de informes. Imagine que trabaja para una
agencia de valores y bolsa denominada Contoso. El sitio web ASP.NET de Contoso
permite a los clientes conectarse y ver en línea informes sobre algunas carteras. No
obstante, los usuarios solicitan con frecuencia poder ver o descargar los informes en Excel
para realizar otros análisis específicos en las carteras.
Nota
Para que pueda probar fácilmente este código usted mismo, en el ejemplo siguiente se crea
una aplicación basada en la consola. Dicho esto, las técnicas que se usan en este ejemplo
serían 100% compatibles con un sitio web ASP.NET. En ningún momento, se necesita
Microsoft Excel en este ejemplo.
Configurar el proyecto
Para crear un generador de informes de cartera, abra Microsoft Visual Studio 2010 y cree
una aplicación de consola denominada PortfolioReportGenerator.
Nota
Para descargar los proyectos de C# y .NET Visual Basic de ejemplo, haga clic en
Descargue el código de ejemplo (en inglés).
Figura 6. Crear una solución de generador de informes de cartera
A continuación, agregue dos clases al proyecto: PortfolioReport y Portfolio. La clase
PortfolioReport es la clase clave que realiza toda la manipulación del documento con Open
XML SDK 2.0. La clase Portfolio es básicamente una estructura de datos que contiene las
propiedades necesarias para representar una cartera de cliente.
Nota
La clase Portfolio se detalla en este cambio. Es un contenedor de datos con algunos datos
de prueba y no tiene código relacionado con Open XML ni Open XML SDK 2.0.
Antes de escribir el código, lo primero que debe hacerse en un proyecto donde se usen
Open XML y Open XML SDK 2.0 es agregar las referencias necesarias al proyecto. Se
necesitan dos referencias específicas: DocumentFormat.OpenXml y WindowsBase.
DocumentFormat.OpenXml contiene las clases que se instalan con Open XML SDK 2.0. Si
no puede encontrar esta referencia después de instalar Open XML SDK 2.0, puede buscarla
con el explorador. De forma predeterminada, se encuentra en C:\Archivos de programa
(x86)\Open XML SDK\V2.0\lib\. Esta referencia solo es necesaria si tiene la intención de
usar Open XML SDK 2.0. Si va a manipular los documentos Open XML modificando el
XML sin formato, no necesitará esta referencia.
WindowsBase incluye las clases del espacio de nombres System.IO.Packaging. Esta
referencia es necesaria en todos los proyectos Open XML sin importar si Open XML SDK
2.0 se usa o no. Las clases del espacio de nombres System.IO.Packaging proporcionan
funciones para abrir paquetes Open XML. Además, hay clases que permiten manipular
(agregar, eliminar, editar) partes del interior de un paquete Open XML.
C#
Copiar
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using DocumentFormat.OpenXml;
namespace PortfolioReportGenerator
{
class PortfolioReport
{
string path = "c:\\example\\";
string templateName = "PortfolioReport.xlsx";
Para no tener que pasar parámetros a los métodos ni tener que volver a abrir
constantemente el documento y extraer la parte de libro, agregue dos variables privadas de
ámbito de clase a la clase PortfolioReport. De la misma manera, agregue una variable
privada de ámbito de clase para mantener una referencia al objeto Portfolio actual cuyos
datos se están usando para generar un informe. Al usar estas variables donde corresponda,
podrá inicializarlas posteriormente en el interior del constructor PortfolioReport, como se
muestra en el ejemplo siguiente.
C#
Copiar
string path = "c:\\example\\";
string templateName = "PortfolioReport.xlsx";
En este segmento de código, se puede ver lo fácil que es abrir un documento y extraer una
parte con Open XML SDK 2.0. En el constructor PortfolioReport, el archivo de libro se
abre con el método Open de la clase SpreadsheetDocument. SpreadsheetDocument forma
parte del espacio de nombres DocumentFormat.OpenXml.Packaging.
SpreadsheetDocument proporciona el acceso adecuado a la parte del libro del paquete del
documento por medio de una propiedad denominada WorkbookPart. Hasta esta fase del
proceso, el generador de informes ha realizado las acciones siguientes:
Modificar los valores de las celdas de la hoja de cálculo con Open XML SDK
VBA
Copiar
ThisWorkbook.Worksheets("Sales").Range("B4").Value = 250
Open XML SDK 2.0 no funciona exactamente igual. Una gran diferencia es que al usar el
modelo de objeto de Excel puede manipular las celdas de las hojas de cálculo
independientemente de si contienen algún valor o no. Es decir, para el modelo de objeto,
todas las celdas de una hoja de cálculo existen. Cuando se trabaja con Open XML, los
objetos no existen. Esto ocurre de forma predeterminada. Si una celda no tiene un valor, no
existe, lo que es lógico desde la perspectiva de especificación de formatos de archivo. Para
mantener el tamaño de un archivo lo más pequeño posible, solo se guarda la información
importante. Vuelva a examinar, por ejemplo, la figura 4 y observe el primer nodo de fila
situado debajo de sheetData. La primera fila empieza en el 3, se saltan las filas 1 y 2. Esto
ocurre porque las celdas de las dos primeras filas están vacías. Observe, igualmente, que en
el primer nodo de fila (fila 3), la dirección de la primera celda es C3. Esto ocurre porque A3
y B3 están vacías.
Como no se puede presuponer que una celda exista en un documento Open XML, primero
debe comprobar si existe y, después, si no existe, debe agregarla al archivo. En el ejemplo
siguiente, se muestra un método denominado InsertCellInWorksheet que lleva a cabo esta
función, junto con los demás métodos del listado. Agregue estos métodos a la clase
PortfolioReport.
Nota
Microsoft tiene ejemplos de código para muchas tareas de Open XML SDK 2.0 comunes.
No solo eso, estos ejemplos están disponibles como ejemplos de código que pueden usarse
en Visual Studio 2010. Parte del código de este artículo se basa en estos ejemplos de
código. Puede descargar el código de ejemplo (en inglés) desde aquí.
C#
Copiar
// Given a Worksheet and an address (like "AZ254"), either return
a
// cell reference, or create the cell reference and return it.
private Cell InsertCellInWorksheet(Worksheet ws, string
addressName)
{
SheetData sheetData = ws.GetFirstChild<SheetData>();
Cell cell = null;
row.InsertBefore(cellResult, refCell);
return cellResult;
}
Otra diferencia entre usar el modelo de objeto de Excel y manipular un documento Open
XML es que cuando se usa el modelo de objeto de Excel, los tipos de datos del valor que
proporcione a la celda o al rango no son relevantes. En cambio, si modifica el valor de una
celda con Open XML, el proceso varía en función del tipo de datos del valor. Para los
valores numéricos, el proceso es en parte parecido a usar el modelo de objeto de Excel. Hay
una propiedad asociada al objeto de Cell en Open XML SDK 2.0 denominada CellValue.
Puede usar esta propiedad para asignar valores numéricos a una celda.
C#
Copiar
public bool UpdateValue(string sheetName, string addressName,
string value,
UInt32Value styleIndex, bool isString)
{
// Assume failure.
bool updated = false;
if (sheet != null)
{
Worksheet ws =
((WorksheetPart)(wbPart.GetPartById(sheet.Id))).Worksheet;
Cell cell = InsertCellInWorksheet(ws, addressName);
if (isString)
{
// Either retrieve the index of an existing string,
// or insert the string into the shared string table
// and get the index of the new item.
int stringIndex = InsertSharedStringItem(wbPart,
value);
cell.CellValue = new
CellValue(stringIndex.ToString());
cell.DataType = new
EnumValue<CellValues>(CellValues.SharedString);
}
else
{
cell.CellValue = new CellValue(value);
cell.DataType = new
EnumValue<CellValues>(CellValues.Number);
}
if (styleIndex > 0)
cell.StyleIndex = styleIndex;
return updated;
}
// Given the main workbook part, and a text value, insert the
text into
// the shared string table. Create the table if necessary. If the
value
// already exists, return its index. If it doesn't exist, insert
it and
// return its new index.
private int InsertSharedStringItem(WorkbookPart wbPart, string
value)
{
int index = 0;
bool found = false;
var stringTablePart = wbPart
.GetPartsOfType<SharedStringTablePart>().FirstOrDefault();
if (!found)
{
stringTable.AppendChild(new SharedStringItem(new
Text(value)));
stringTable.Save();
}
return index;
}
Un punto interesante del ejemplo de código anterior es el formato de las celdas. Como ya
hemos mencionado en este artículo, el formato de las celdas no se almacena en los nodos de
celda, sino que la celda almacena un índice de estilos que apunta a un estilo que está
definido en otra parte (styles.xml). Si se usa el patrón de plantilla mostrado en este
documento y el modelo de objeto de Excel mediante VBA o .NET, normalmente, se aplica
el formato que se desea a un rango de una o más celdas. A medida que se agregan mediante
programación datos al libro, se aplica fielmente el formato que se ha aplicado en el rango.
Puesto que los archivos Open XML solo contienen información relacionada con las celdas
que contienen datos, cuando se agregue una celda nueva al archivo, si la celda necesita
formato, se deberá actualizar en el índice de estilos. En consecuencia, el método
UpdateValue acepta un parámetro styleIndex que indica qué índice de estilos se aplica a la
celda. Si pasa un valor cero, no se define ningún índice de estilos y la celda usa el formato
predeterminado de Excel.
Un método sencillo para determinar el índice de estilos apropiado para cada celda es dar el
formato que desee al archivo de plantilla del libro y después abrir las partes del libro
correspondientes en modo XML (como se muestra en la figura 4) y buscar el índice de
estilo de las celdas a las que ha dado formato.
Con los métodos del listado de códigos anterior implementados, para generar el informe
ahora basta con obtener los datos de la cartera y llamar repetidamente a UpdateValue para
crear el informe. Si agrega el código necesario para hacerlo, todo funcionará bien salvo una
cuestión: las celdas que contengan una fórmula que haga referencia a una celda cuyo valor
se haya cambiado manipulando Open XML no mostrarán el resultado correcto. Esto sucede
porque Excel almacena en la caché el resultado de la fórmula de la celda. Como Excel cree
que tiene el valor correcto en la caché, no vuelve a calcular la celda. Aunque tenga la
función de cálculo automático activada o presione F9 para realizar un cálculo manual,
Excel no vuelve a calcular la celda.
Para solucionar este problema, debe eliminar el valor almacenado en la caché de estas
celdas de modo que Excel vuelva a realizar el cálculo cuando el archivo se abra en Excel.
Para proporcionar esta función, agregue el método RemoveCellValue mostrado en el
ejemplo siguiente a la clase PortfolioReport.
C#
Copiar
// This method is used to force a recalculation of cells
containing formulas. The
// CellValue has a cached value of the evaluated formula. This
// prevents Excel from recalculating the cell even if
// calculation is set to automatic.
private bool RemoveCellValue(string sheetName, string
addressName)
{
bool returnValue = false;
return returnValue;
}
C#
Copiar
// Create a new Portfolio report
public void CreateReport()
{
string wsName = "Portfolio Summary";
int row = 7;
wsName = "Portfolio Holdings";
El paso final (presuponiendo que haya copiado el origen de la clase Portfolio) es agregar
código al método Main de la clase Program. Modifique el método Main de modo que
contenga el código mostrado en el ejemplo siguiente. Observe que el origen de la clase
Portfolio incluye datos de ejemplo para dos clientes: Steve y Kelly.
C#
Copiar
static void Main(string[] args)
{
PortfolioReport report = new PortfolioReport("Steve");
report.CreateReport();
report = new PortfolioReport("Kelly");
report.CreateReport();
Console.WriteLine("Reports created!");
Console.WriteLine("Press ENTER to quit.");
Console.ReadLine();
}
Uno de los efectos que se aprecia cuando se ejecuta este proceso es lo rápido que se
generan los informes, lo que es idóneo para aquellos casos en los que se hace un uso
intensivo del servidor. El rendimiento en comparación con código parecido que usa el
modelo de objeto de Excel para alcanzar el mismo resultado ni siquiera se acerca a este: el
método Open XML es muchísimo más rápido.
Conclusión
Comenzando con Microsoft Office 2007, las aplicaciones principales de Microsoft Office
centradas en documentos han cambiado el formato usual de archivo binario por el formato
de archivos Open XML. Los formatos de archivo Open XML son formatos de archivo
basados en estándares abiertos XML. El paso a los formatos de archivo Open XML abre
nuevas oportunidades de desarrollo para los desarrolladores. Pero, para poder aprovechar
estas oportunidades, se tiene que invertir mucho tiempo y esfuerzo para entender la
especificación Open XML y en la tediosa manipulación de XML sin formato.
Con Open XML SDK 2.0, no es necesario dedicar tanto tiempo al aprendizaje de la técnica
de desarrollo, porque encapsula muchos de los detalles de la especificación Open XML en
una biblioteca de clases fácil de usar para trabajar con documentos Open XML. Además de
reducir el tiempo de aprendizaje, con Open XML SDK 2.0, los desarrolladores podrán ser
más productivos al proporcionar funciones durante el diseño, como la compatibilidad con
IntelliSense y un desarrollo con seguridad de tipos.
En este artículo, se ha mostrado cómo usar Open XML SDK 2.0 para crear un generador de
informes de cartera. Este ejercicio ha mostrado un patrón de solución común y una
estrategia para las tareas orientadas a Excel comunes, como abrir libros, hacer referencia a
hojas de cálculo y actualizar el valor de una celda.
Recursos adicionales
Para obtener más información acerca de los temas tratados en este artículo, consulte los
siguientes recursos adicionales.
Steve Hansen es el fundador de Grid Logic, una consultoría con sede principal en
Minnesota especializada en soluciones para trabajadores de la información e inteligencia
empresarial. Steve es desarrollador, autor de muchos artículos y ponente en conferencias
técnicas, es un MVP de Microsoft por su trabajo con herramientas de Visual Studio para
Office. Programador y amante de la economía, Steve cuenta también con un MBA de la
Universidad de Minnesota en la especialización de finanzas.