/// <summary>
        /// Convierte el contenido de un archivo de Excel en una lista de objectos usando un parseador de XML.
        /// Asume que cada hoja en el archivo de Excel representa a un objecto y que la primera fila de cada 
        /// hoja contiene las columnas que describen las propiedades del objeto. También asume que los nombres 
        /// de las columnas no se repiten. En caso de repetirse el nombre de alguna columna solo se guardará en 
        /// el objeto una sola vez.
        /// También se da por sentado que todos los datos en una columna a excepción del encabezado son del 
        /// mismo tipo.
        /// </summary>
        /// <exception cref="System.IO.IOException">Excepción lanzada cuando el archivo de Excel 
        /// está siendo usado por otro proceso.</exception>

        public static List<List<Object>> ConvertExcelArchiveToListObjectsSAXApproach(string filePath)
        {
            List<List<Object>> listObjects = new List<List<Object>>();
            using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(filePath, false))
            {
                WorkbookPart wbPart = spreadsheetDocument.WorkbookPart;
                Sheets theSheets = wbPart.Workbook.Sheets;

                SharedStringTablePart sstPart = spreadsheetDocument.WorkbookPart.GetPartsOfType<SharedStringTablePart>().FirstOrDefault();
                SharedStringTable ssTable = null;
                if (sstPart != null)
                    ssTable = sstPart.SharedStringTable;

                // Obtiene el formato de celdas para las celdas sin tipos de datos definidos.
                WorkbookStylesPart workbookStylesPart = spreadsheetDocument.WorkbookPart.GetPartsOfType<WorkbookStylesPart>().First();
                CellFormats cellFormats = (CellFormats)workbookStylesPart.Stylesheet.CellFormats;
                var sheets = wbPart.Workbook.Sheets.Cast<Sheet>().ToList();

                foreach (WorksheetPart worksheetpart in wbPart.WorksheetParts)
                {
                    OpenXmlPartReader reader = new OpenXmlPartReader(worksheetpart);
                    List<String> columnValues = new List<String>();
                    Cell c;
                    var value = string.Empty;

                    string partRelationshipId = wbPart.GetIdOfPart(worksheetpart);
                    var correspondingSheet = sheets.FirstOrDefault(
                        s => s.Id.HasValue && s.Id.Value == partRelationshipId);

                    string sheetName = string.Empty;

                    // Obtiene el nombre de la hoja de Excel
                    if (correspondingSheet != null)
                    {
                        sheetName = correspondingSheet.GetAttribute("name", "").Value;
                    }

                    if (sheetName == string.Empty)
                    {
                        sheetName = "MyDynamicType";
                    }
                    // Crea un ensamblado dinámico y un módulo.
                    AssemblyName assemblyName = new AssemblyName();
                    assemblyName.Name = "tmpAssembly";
                    AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
                    ModuleBuilder module = assemblyBuilder.DefineDynamicModule("tmpModule");

                    // Crea un nuevo constructor de tipos.
                    TypeBuilder typeBuilder = module.DefineType(sheetName, TypeAttributes.Public | TypeAttributes.Class);

                    MethodAttributes GetSetAttr =
                       MethodAttributes.Public |
                       MethodAttributes.HideBySig;
                    int numberOfColumns = 0;

                    bool firstRowInformation = false;

                    while (reader.Read())
                    {
                        if (reader.ElementType == typeof(SheetData))
                        {
                            // Obtiene la primera fila.
                            // Asume que no hay celdas en blanco entre las columnas con información.
                            // Si hay columnas vacias no serán agregadas. 
                            reader.ReadFirstChild();
                            if (reader.ElementType == typeof(Row))
                            {
                                reader.ReadFirstChild();
                                do
                                {
                                    if (reader.ElementType == typeof(Cell))
                                    {
                                        c = (Cell)reader.LoadCurrentElement();

                                        if (c.DataType != null
                                            && c.DataType.HasValue
                                            && c.DataType == CellValues.SharedString
                                            && int.Parse(c.CellValue.InnerText) < ssTable.ChildElements.Count)
                                        {
                                            value = ssTable.ChildElements[int.Parse(c.CellValue.InnerText)].InnerText ?? string.Empty;
                                        }
                                        else
                                        {
                                            if (c.CellValue != null && c.CellValue.InnerText != null)
                                            {
                                                value = c.CellValue.InnerText;
                                            }
                                            else
                                            {
                                                value = string.Empty;
                                            }
                                        }
                                        if (value != string.Empty)
                                        {
                                            columnValues.Add(value);
                                            ++numberOfColumns;
                                        }
                                    }
                                } while (reader.ReadNextSibling());
                            }
                            reader.Read();

                            foreach (var columnName in columnValues)
                            {
                                // Genera una propiedad pública
                                var field = typeBuilder.DefineField("_" + columnName.ToString(), typeof(String), FieldAttributes.Private);
                                PropertyBuilder property =
                                    typeBuilder.DefineProperty(columnName.ToString(),
                                                        System.Reflection.PropertyAttributes.None,
                                                        typeof(string),
                                                        new Type[] { typeof(string) });

                                // Genera un método para acceder a la propiedad.
                                var getter = typeBuilder.DefineMethod("get_" + columnName.ToString(), GetSetAttr, typeof(String), Type.EmptyTypes);

                                var il = getter.GetILGenerator();

                                il.Emit(OpCodes.Ldarg_0);
                                il.Emit(OpCodes.Ldfld, field);
                                il.Emit(OpCodes.Ret);

                                property.SetGetMethod(getter);

                                // Genera un método para cambiar el valor de la propiedad. 
                                var setter = typeBuilder.DefineMethod("set_" + columnName, GetSetAttr, null, new[] { typeof(string) });

                                il = setter.GetILGenerator();

                                il.Emit(OpCodes.Ldarg_0);
                                il.Emit(OpCodes.Ldarg_1);
                                il.Emit(OpCodes.Stfld, field);
                                il.Emit(OpCodes.Ret);

                                property.SetSetMethod(setter);
                            }

                            dynamic expandoObjectClass = new ExpandoObject();
                            List<Object> listObjectsCustomClasses = new List<Object>();

                            // Lee el resto de las filas en la hoja de Excel
                            do
                            {
                                if (reader.ElementType == typeof(Row))
                                {
                                    reader.ReadFirstChild();
                                    Type generatedType = typeBuilder.CreateType();
                                    object generatedObject = Activator.CreateInstance(generatedType);

                                    PropertyInfo[] properties = generatedType.GetProperties();

                                    int propertiesCounter = 0;
                                    // Lee todas las celdas en la fila.

                                    if (firstRowInformation == false)
                                    {
                                        firstRowInformation = true;
                                        do
                                        {
                                            if (reader.ElementType == typeof(Cell))
                                            {
                                                c = (Cell)reader.LoadCurrentElement();

                                                if (c.DataType != null
                                                    && c.DataType.HasValue
                                                    && c.DataType == CellValues.SharedString
                                                    && int.Parse(c.CellValue.InnerText) < ssTable.ChildElements.Count)
                                                {
                                                    value = ssTable.ChildElements[int.Parse(c.CellValue.InnerText)].InnerText ?? string.Empty;
                                                }
                                                else
                                                {
                                                    if (c.CellValue != null && c.CellValue.InnerText != null)
                                                    {
                                                        value = c.CellValue.InnerText;
                                                    }
                                                    else
                                                    {
                                                        value = string.Empty;
                                                    }
                                                }

                                                if (propertiesCounter < properties.Count())
                                                {
                                                    properties[propertiesCounter].SetValue(generatedObject, value, null);
                                                }
                                                propertiesCounter++;
                                            }
                                        } while (reader.ReadNextSibling());
                                    }

                                    else
                                    {
                                        do
                                        {
                                            if (reader.ElementType == typeof(Cell))
                                            {
                                                c = (Cell)reader.LoadCurrentElement();

                                                if (c.DataType != null
                                                    && c.DataType.HasValue
                                                    && c.DataType == CellValues.SharedString
                                                    && int.Parse(c.CellValue.InnerText) < ssTable.ChildElements.Count)
                                                {
                                                    value = ssTable.ChildElements[int.Parse(c.CellValue.InnerText)].InnerText ?? string.Empty;
                                                }
                                                else
                                                {
                                                    if (c.CellValue != null && c.CellValue.InnerText != null)
                                                    {
                                                        value = c.CellValue.InnerText;
                                                    }
                                                    else
                                                    {
                                                        value = string.Empty;
                                                    }
                                                }

                                                if (propertiesCounter < properties.Count())
                                                {
                                                    if (value == string.Empty && properties[propertiesCounter].GetType().Name != "String") 
                                                    {
                                                        properties[propertiesCounter].SetValue(generatedObject, null, null);
                                                    }
                                                    else
                                                    {
                                                        properties[propertiesCounter].SetValue(generatedObject, value, null);
                                                    }
                                                    
                                                }
                                                propertiesCounter++;
                                            }
                                        } while (reader.ReadNextSibling());
                                    }
                                    listObjectsCustomClasses.Add(generatedObject);
                                }
                            } while (reader.Read() && reader.ElementType == typeof(Row));
                            listObjects.Add(listObjectsCustomClasses);
                        }
                    }
                }
            }
            return listObjects;
        }
Пример #2
0
        public void WriterWithNsTest()
        {
            using (var memStream = new MemoryStream())
            {
                using (OpenXmlPartWriter target = new OpenXmlPartWriter(memStream))
                {
                    target.WriteStartDocument();
                    target.WriteStartElement(new Document());

                    target.WriteStartElement(new Body(), new List<OpenXmlAttribute>() { new OpenXmlAttribute("a:a", "http://aa", "ab") });

                    target.WriteStartElement(new Paragraph(), null, null);
                    target.WriteEndElement();

                    List<KeyValuePair<string, string>> ns = new List<KeyValuePair<string, string>>();
                    KeyValuePair<string, string> item = new KeyValuePair<string, string>("b", "http://aaa");
                    ns.Add(item);
                    target.WriteStartElement(new Table(), null, ns);
                    target.WriteEndElement();

                    target.WriteEndElement();
                    
                    target.WriteEndElement();
                    target.Close();
                }
                memStream.Flush();
                memStream.Seek(0, SeekOrigin.Begin);

                using (var reader = new OpenXmlPartReader(memStream))
                {
                    //<w:document>
                    reader.Read();
                    Assert.Equal(1, reader.NamespaceDeclarations.Count());

                    //<w:body>
                    reader.Read();
                    Assert.Equal(1, reader.NamespaceDeclarations.Count());

                    //<w:p>
                    reader.ReadFirstChild();
                    Assert.True(reader.ElementType.Name.EndsWith("Paragraph"));
                    Assert.Equal(0, reader.NamespaceDeclarations.Count());

                    //<w:p>
                    reader.ReadNextSibling();
                    Assert.True(reader.ElementType.Name.EndsWith("Table"));
                    Assert.Equal(1, reader.NamespaceDeclarations.Count());


                }
            }
        }