El Libro del Día: 2016-08-17
Titulo: Modern JavaScript Applications
Autor: Narayan Prusty
Editorial: Packt
Nro Paginas: 330
Capítulos:
Chapter 1: Breaking into Microservices Architecture
Chapter 2: Building a Coupon Site
Chapter 3: Communication between Browsers in Real Time
Chapter 4: Building a Chatroulette
Chapter 5: Bidirectional Communication in Real Time
Chapter 6: Building a Live Score Site
Chapter 7: Functional Reactive Programming
Chapter 8: Building an Advanced Profile Search Widget
Chapter 9: New Features of Bootstrap 4
Chapter 10: Building User Interfaces Using React
Chapter 11: Building an RSS Reader Using React and Flux
Chapter 12: New Features of Angular 2
Chapter 13: Building a Search Engine Template Using AngularJS 2
Chapter 14: Securing and Scaling Node.js Applications
Descarga:
Modern_JavaScript_Applications
Blog de Luis Dueñas dedicado a la difusión del Desarrollo en Microsoft .NET, Visual Studio, WinForms, WebForms, MVC, ASP .NET, jQuery, AJAX, HTML5, JavaScript, Móviles, etc. Encontrarás Libros, Demos, Artículos Técnicos, Entrenamiento.
miércoles, 17 de agosto de 2016
El Libro del Día: Modern JavaScript Applications
Etiquetas:
Angular 2,
Applications,
Architecture,
Bidirectional,
Bootstrap 4,
Flux,
Fullstack,
Functional,
Javascript,
Libros,
Microservices,
Modern,
Narayan Prusty,
Node.js,
Packt,
React,
reactive,
Real Time,
Securing
jueves, 11 de agosto de 2016
El Libro del Día: AngularJS in Action
El Libro del Día: 2016-08-11
Titulo: AngularJS in Action
Autor: Lukas Ruebbelke
Editorial: Manning
Nro Paginas: 191
Capítulos:
PART 1 GET ACQUAINTED WITH ANGULARJS
1 Hello AngularJS
2 Structuring your AngularJS application
PART 2 MAKE SOMETHING WITH ANGULARJS
3 Views and controllers
4 Models and services
5 Directives
6 Animations
7 Structuring your site with routes
8 Forms and validations
APPENIDXES
A Setting up Karma
B Setting up a Node.js server
C Setting up a Firebase server
D Running the app
Descarga:
AngularJS_in_Action
Titulo: AngularJS in Action
Autor: Lukas Ruebbelke
Editorial: Manning
Nro Paginas: 191
Capítulos:
PART 1 GET ACQUAINTED WITH ANGULARJS
1 Hello AngularJS
2 Structuring your AngularJS application
PART 2 MAKE SOMETHING WITH ANGULARJS
3 Views and controllers
4 Models and services
5 Directives
6 Animations
7 Structuring your site with routes
8 Forms and validations
APPENIDXES
A Setting up Karma
B Setting up a Node.js server
C Setting up a Firebase server
D Running the app
Descarga:
AngularJS_in_Action
Etiquetas:
AngularJS,
Animations,
Application,
Controllers,
Directives,
FireBase,
Forms,
in Action,
Karma,
Libros,
Lukas Ruebbelke,
Manning,
Models,
Node.js,
Routes,
Running,
Services,
Setting,
Validations,
Views
miércoles, 10 de agosto de 2016
Entrenamiento - Ultima Semana de Charla Gratuita a Empresas
Ultima Semana de Charla Gratuita a Empresas
Solo hasta este Viernes 12 de Agosto estaré recibiendo correos para coordinar la charla gratuita de muestra a Empresas para Capacitación en ASP.NET MVC & JavaScript.
La charla dura 1.5 horas y tiene la siguiente agenda:
Título: "Desarrollo de Software Ligero y Desconectado"
1. Acerca del Instructor
1.1. Estudios
1.2. Experiencia Laboral
1.3. Aportes
2. Desarrollo de Software
2.1. Etapas del Desarrollo de Software
2.2. Tipos de Aplicaciones
2.3. Frameworks de Programación
3. Necesidad de una Nueva Arquitectura
3.1. Problemas diarios en Sistemas
3.2. Causas de los Problemas
3.3. Solución de los Problemas
4. Introducción al Desarrollo Web
4.1. Componentes de un Sitio Web
4.2. El Problema de la Performance de las Páginas
4.3. Principales Reglas de Performance
4.4. Arquitecturas de Desarrollo Web
5. Desarrollo Web en ASP.NET
5.1. Programando en el Servidor con C# (.NET)
5.2. Programando en el Cliente con las APIs de JavaScript
6. Utilitarios, Aplicaciones y Demos
6.1. Utilitarios de Lduenas
6.2. Aplicaciones Web en Producción
6.3. Demos de Clases y Capacitaciones
7. Preguntas y Respuestas
Los interesados envíar un mail a Luis.duenash@gmail.com con los siguientes datos:
- Nombre de la Empresa
- Rubro
- Persona de Contacto
- Teléfono e Email del Contacto
- Fecha y Hora de la Exposición con su equipo de desarrolladores
- Dirección del lugar de la Exposición
Si están convencidos de los resultados de la metodología, la arquitectura y las técnicas se programa la capacitación, sino no hay ningún compromiso.
Las capacitaciones son 6 horas semanales y solo me queda un horario disponible: Lunes y Miércoles a partir de las 5:00 pm.
Gracias a todos por el interés.
Solo hasta este Viernes 12 de Agosto estaré recibiendo correos para coordinar la charla gratuita de muestra a Empresas para Capacitación en ASP.NET MVC & JavaScript.
La charla dura 1.5 horas y tiene la siguiente agenda:
Título: "Desarrollo de Software Ligero y Desconectado"
1. Acerca del Instructor
1.1. Estudios
1.2. Experiencia Laboral
1.3. Aportes
2. Desarrollo de Software
2.1. Etapas del Desarrollo de Software
2.2. Tipos de Aplicaciones
2.3. Frameworks de Programación
3. Necesidad de una Nueva Arquitectura
3.1. Problemas diarios en Sistemas
3.2. Causas de los Problemas
3.3. Solución de los Problemas
4. Introducción al Desarrollo Web
4.1. Componentes de un Sitio Web
4.2. El Problema de la Performance de las Páginas
4.3. Principales Reglas de Performance
4.4. Arquitecturas de Desarrollo Web
5. Desarrollo Web en ASP.NET
5.1. Programando en el Servidor con C# (.NET)
5.2. Programando en el Cliente con las APIs de JavaScript
6. Utilitarios, Aplicaciones y Demos
6.1. Utilitarios de Lduenas
6.2. Aplicaciones Web en Producción
6.3. Demos de Clases y Capacitaciones
7. Preguntas y Respuestas
Los interesados envíar un mail a Luis.duenash@gmail.com con los siguientes datos:
- Nombre de la Empresa
- Rubro
- Persona de Contacto
- Teléfono e Email del Contacto
- Fecha y Hora de la Exposición con su equipo de desarrolladores
- Dirección del lugar de la Exposición
Si están convencidos de los resultados de la metodología, la arquitectura y las técnicas se programa la capacitación, sino no hay ningún compromiso.
Las capacitaciones son 6 horas semanales y solo me queda un horario disponible: Lunes y Miércoles a partir de las 5:00 pm.
Gracias a todos por el interés.
Etiquetas:
.NET,
Asíncrono,
ASP.NET,
C#,
Capacitación,
Contacto,
CSS3,
Desconectado,
Empresas,
Entrenamiento,
Exposición,
Frameworks,
High Performance,
HTML5,
Javascript,
Lduenas,
Ligero,
Seguridad,
Visual Studio,
XHR
martes, 9 de agosto de 2016
El Demo del Día: Exportar a Excel 2007 desde Listas y Tablas usando XML
Exportar a Excel 2007 desde Listas y Tablas usando XML
1. Introducción
En el post anterior vimos las 3 técnicas que hay para crear un archivo de Excel 2007 exportando datos desde varias listas de objetos o varias tablas de un DataSet en .NET. En ese post se presentó un Demo de cómo usar OLEDB para crear el archivo Excel.
En este post vamos a ver algo inédito, que no hay en la web, que es como crear un archivo de Excel 2007, creando los archivos XML necesarios y luego comprimiendolo en un xlsx.
2. Ventajas de Crear un Archivo Excel usando XML
Existen muchas ventajas de usar esta técnica entre las 3 mas importantes tenemos:
- Es la más rápida en la creación de archivos Excel, casi 3 veces más rápida que OLEDB y mas de 10 veces más rápida que abrir una instancia de Excel (Automatización COM).
- No necesita tener instalado ni los Componentes de Acceso a Datos del "Microsoft Access Database Engine 2010 Redistributable" ni tampoco una instancia de Excel para crear el archivo.
Nota: Ni siquiera se necesita tener instalado el Excel para leer o ver el archivo ya que se puede hacer usando los Visores de los Demos pasados.
- Se puede crear no solo celdas con datos sino gráficos, dar estilo, formatos, etc, cosa que no se puede al usar OLEDB.
Nota: Si se puede abriendo una instancia de Excel pero se demora demasiado y consume muchos recursos, lo cual está terminantemente prohibido para Aplicaciones Web ASP.NET.
3. Crear una Aplicación Windows Forms en C#
Abrir Visual Studio y crear una aplicación Windows Forms en C# llamada "Excel_Crear_XML", cambiarle de nombre al formulario por "frmExcel" y realizar el diseño similar a la figura mostrada:
En el diseño hay los siguientes controles:
- Botón para Llenar desde Listas llamado "btnLlenarLista".
- Botón para Llenar desde Tablas llamado "btnLlenarTabla".
- Botón para Exportar Listas a Excel llamado "btnExportarListas". Deshabilitado por defecto.
- Botón para Exportar Tablas a Excel llamado "btnExportarTablas". Deshabilitado por defecto.
- Control Tab llamado "tabExcel" con 2 tabPages: "tabCategorias" y "tabProducto".
- Control DataGridView llamado "dgvCategoria" ubicado en el tab de Categorias.
- Control DataGridView llamado "dgvProducto" ubicado en el tab de Productos.
4. Crear las Clases con las Entidades de Negocio
Lo primero que debemos crear son las clases de entidades para las listas de objetos de categorías y productos:
Archivo de Clase: beCategoria.cs
namespace Excel_Crear_XML
{
public class beCategoria
{
public int IdCategoria { get; set; }
public string Nombre { get; set; }
}
}
Archivo de Clase: beProducto.cs
namespace Excel_Crear_XML
{
public class beProducto
{
public int IdProducto { get; set; }
public string Nombre { get; set; }
public int IdCategoria { get; set; }
public decimal Precio { get; set; }
public short Stock { get; set; }
}
}
Archivo de Clase: beCategoriaProducto.cs
using System.Collections.Generic;
namespace Excel_Crear_XML
{
public class beCategoriaProducto
{
public List<beCategoria> ListaCategoria { get; set; }
public List<beProducto> ListaProducto { get; set; }
}
}
5. Crear una Clase que permita llenar los Datos
Lo segundo que debemos hacer es crear una clase para llenar los datos de las tablas y listas de objetos tanto para categorías como productos.
En una aplicación real esto se reemplazará por la llamada a un componente de reglas del negocio y solo se elegirá uno de las 2 repositorios de datos: DataSet o Objeto con Listas. Lo recomendable es elegir el Objeto con Listas ya que consume menos memoria y procesa más rápido.
Archivo de Clase: Data.cs
using System;
using System.Collections.Generic;
using System.Data;
namespace Excel_Crear_XML
{
public class Data
{
public static List<beCategoria> ListaCategorias()
{
//Llenar la Lista de Categorias
List<beCategoria> lbeCategoria = new List<beCategoria>();
lbeCategoria.Add(new beCategoria
{
IdCategoria = 1,
Nombre = "Bebidas"
});
lbeCategoria.Add(new beCategoria
{
IdCategoria = 2,
Nombre = "Cereales"
});
lbeCategoria.Add(new beCategoria
{
IdCategoria = 3,
Nombre = "Condimentos"
});
lbeCategoria.Add(new beCategoria
{
IdCategoria = 4,
Nombre = "Lacteos"
});
lbeCategoria.Add(new beCategoria
{
IdCategoria = 5,
Nombre = "Pastas"
});
return lbeCategoria;
}
public static List<beProducto> ListaProductos()
{
//Llenar la Lista de Productos
List<beProducto> lbeProducto = new List<beProducto>();
lbeProducto.Add(new beProducto
{
IdProducto = 1,
Nombre = "Pepsi",
IdCategoria = 1,
Precio = 1.5M,
Stock = 100
});
lbeProducto.Add(new beProducto
{
IdProducto = 2,
Nombre = "Avena 3 Ositos",
IdCategoria = 2,
Precio = 2.0M,
Stock = 50
});
lbeProducto.Add(new beProducto
{
IdProducto = 3,
Nombre = "Ajinomoto",
IdCategoria = 3,
Precio = 0.5M,
Stock = 200
});
lbeProducto.Add(new beProducto
{
IdProducto = 4,
Nombre = "Leche Gloria",
IdCategoria = 4,
Precio = 3.5M,
Stock = 300
});
lbeProducto.Add(new beProducto
{
IdProducto = 5,
Nombre = "Fideos Lavaggi",
IdCategoria = 5,
Precio = 3.0M,
Stock = 150
});
lbeProducto.Add(new beProducto
{
IdProducto = 6,
Nombre = "Sprite",
IdCategoria = 1,
Precio = 2.0M,
Stock = 200
});
lbeProducto.Add(new beProducto
{
IdProducto = 7,
Nombre = "Quinua Avena",
IdCategoria = 2,
Precio = 2.5M,
Stock = 150
});
lbeProducto.Add(new beProducto
{
IdProducto = 8,
Nombre = "Tuco Sibarita",
IdCategoria = 3,
Precio = 0.5M,
Stock = 200
});
lbeProducto.Add(new beProducto
{
IdProducto = 9,
Nombre = "Leche Pura Vida",
IdCategoria = 4,
Precio = 3.5M,
Stock = 300
});
lbeProducto.Add(new beProducto
{
IdProducto = 10,
Nombre = "Spagetti Don Victorio",
IdCategoria = 5,
Precio = 2.0M,
Stock = 250
});
return lbeProducto;
}
public static DataTable TablaCategorias()
{
//Llenar la Tabla de Categorias
DataTable tblCategoria = new DataTable();
tblCategoria.Columns.Add("IdCategoria",
Type.GetType("System.Int32"));
tblCategoria.Columns.Add("Nombre",
Type.GetType("System.String"));
DataRow drCat1 = tblCategoria.NewRow();
drCat1[0] = 1;
drCat1[1] = "Bebidas";
tblCategoria.Rows.Add(drCat1);
DataRow drCat2 = tblCategoria.NewRow();
drCat2[0] = 2;
drCat2[1] = "Cereales";
tblCategoria.Rows.Add(drCat2);
DataRow drCat3 = tblCategoria.NewRow();
drCat3[0] = 3;
drCat3[1] = "Condimentos";
tblCategoria.Rows.Add(drCat3);
DataRow drCat4 = tblCategoria.NewRow();
drCat4[0] = 4;
drCat4[1] = "Lacteos";
tblCategoria.Rows.Add(drCat4);
DataRow drCat5 = tblCategoria.NewRow();
drCat5[0] = 5;
drCat5[1] = "Pastas";
tblCategoria.Rows.Add(drCat5);
return tblCategoria;
}
public static DataTable TablaProductos()
{
//Llenar la Tabla de Productos
DataTable tblProducto = new DataTable();
tblProducto.Columns.Add("IdProducto",
Type.GetType("System.Int32"));
tblProducto.Columns.Add("Nombre",
Type.GetType("System.String"));
tblProducto.Columns.Add("IdCategoria",
Type.GetType("System.Int32"));
tblProducto.Columns.Add("Precio",
Type.GetType("System.Decimal"));
tblProducto.Columns.Add("Stock",
Type.GetType("System.Int16"));
DataRow drPro1 = tblProducto.NewRow();
drPro1[0] = 1;
drPro1[1] = "Pepsi";
drPro1[2] = 1;
drPro1[3] = 1.5M;
drPro1[4] = 100;
tblProducto.Rows.Add(drPro1);
DataRow drPro2 = tblProducto.NewRow();
drPro2[0] = 2;
drPro2[1] = "Avena 3 Ositos";
drPro2[2] = 2;
drPro2[3] = 2.0M;
drPro2[4] = 50;
tblProducto.Rows.Add(drPro2);
DataRow drPro3 = tblProducto.NewRow();
drPro3[0] = 3;
drPro3[1] = "Ajinomoto";
drPro3[2] = 3;
drPro3[3] = 0.5M;
drPro3[4] = 200;
tblProducto.Rows.Add(drPro3);
DataRow drPro4 = tblProducto.NewRow();
drPro4[0] = 4;
drPro4[1] = "Leche Gloria";
drPro4[2] = 4;
drPro4[3] = 3.5M;
drPro4[4] = 300;
tblProducto.Rows.Add(drPro4);
DataRow drPro5 = tblProducto.NewRow();
drPro5[0] = 5;
drPro5[1] = "Fideos Lavaggi";
drPro5[2] = 5;
drPro5[3] = 3.0M;
drPro5[4] = 150;
tblProducto.Rows.Add(drPro5);
DataRow drPro6 = tblProducto.NewRow();
drPro6[0] = 6;
drPro6[1] = "Sprite";
drPro6[2] = 1;
drPro6[3] = 2.0M;
drPro6[4] = 200;
tblProducto.Rows.Add(drPro6);
DataRow drPro7 = tblProducto.NewRow();
drPro7[0] = 7;
drPro7[1] = "Quinua Avena";
drPro7[2] = 2;
drPro7[3] = 2.5M;
drPro7[4] = 150;
tblProducto.Rows.Add(drPro7);
DataRow drPro8 = tblProducto.NewRow();
drPro8[0] = 8;
drPro8[1] = "Tuco Sibarita";
drPro8[2] = 3;
drPro8[3] = 0.5M;
drPro8[4] = 200;
tblProducto.Rows.Add(drPro8);
DataRow drPro9 = tblProducto.NewRow();
drPro9[0] = 9;
drPro9[1] = "Leche Pura Vida";
drPro9[2] = 4;
drPro9[3] = 3.5M;
drPro9[4] = 200;
tblProducto.Rows.Add(drPro9);
DataRow drPro10 = tblProducto.NewRow();
drPro10[0] = 10;
drPro10[1] = "Spagetti Don Victorio";
drPro10[2] = 5;
drPro10[3] = 2.0M;
drPro10[4] = 250;
tblProducto.Rows.Add(drPro10);
return tblProducto;
}
}
}
6. Crear una Clase que permita Crear Archivos XML y Comprimirlos
La tercera parte a codificar es crear una clase que permita crear los diferentes archivos XML necesitados y luego comprimirlos en un archivo XLSX.
Archivo de Clase: Excel.cs
using System;
using System.IO;
using System.Data;
using System.Text;
using System.Reflection;
using System.Linq;
using System.Collections.Generic;
using System.IO.Compression;
namespace Excel_Crear_XML
{
public class Excel
{
private enum TipoOrigen {
Listas = 0,
Tablas =1
}
private static string sArchivoXlsx;
private static string[] sHojas;
private static string[] sRango;
private static int nHojas;
private static TipoOrigen tipoOrigen;
private static List<dynamic> data;
public static void ExportarDeLista<T>(string archivoXlsx, string[] hojas, T objData)
{
data = new List<dynamic>();
tipoOrigen = TipoOrigen.Listas;
sArchivoXlsx = archivoXlsx;
sHojas = hojas;
nHojas = hojas.Length;
sRango = new string[nHojas];
PropertyInfo[] listas = objData.GetType().GetProperties();
dynamic lista;
PropertyInfo[] campos;
for (int i = 0; i < listas.Length;i++)
{
lista = listas[i].GetValue(objData, null);
data.Add(lista);
campos = lista[0].GetType().GetProperties();
sRango[i] = String.Format("${0}${1}", (char)(64 + campos.Length), lista.Count + 1);
}
crearDirectoriosArchivos();
}
public static void ExportarDeTabla(string archivoXlsx, string[] hojas, DataSet objData)
{
data = new List<dynamic>();
tipoOrigen = TipoOrigen.Tablas;
sArchivoXlsx = archivoXlsx;
sHojas = hojas;
nHojas = hojas.Length;
sRango = new string[nHojas];
DataTable tabla;
for (int i = 0; i < objData.Tables.Count; i++)
{
tabla = objData.Tables[i];
data.Add(tabla);
sRango[i] = String.Format("${0}${1}",
(char)(64 + tabla.Columns.Count), tabla.Rows.Count + 1);
}
crearDirectoriosArchivos();
}
private static void crearDirectoriosArchivos()
{
//Definir la ruta de los directorios a crear
string sDirectorioRaiz = Path.Combine(Path.GetDirectoryName(sArchivoXlsx),
Path.GetFileNameWithoutExtension(sArchivoXlsx));
string sDirectorioRels = Path.Combine(sDirectorioRaiz, "_rels");
string sDirectorioDocProps = Path.Combine(sDirectorioRaiz, "docProps");
string sDirectorioXl = Path.Combine(sDirectorioRaiz, "xl");
string sDirectorioXlRels = Path.Combine(sDirectorioXl, "_rels");
string sDirectorioXlTheme = Path.Combine(sDirectorioXl, "theme");
string sDirectorioXlWorksheets = Path.Combine(sDirectorioXl, "worksheets");
//Definir la ruta de los archivos a crear
string sArchivoContentTypes = Path.Combine(sDirectorioRaiz, "[Content_Types].xml");
string sArchivoRels = Path.Combine(sDirectorioRels, ".rels");
string sArchivoDocApp = Path.Combine(sDirectorioDocProps, "app.xml");
string sArchivoDocCore = Path.Combine(sDirectorioDocProps, "core.xml");
string sArchivoXlStyles = Path.Combine(sDirectorioXl, "styles.xml");
string sArchivoXlWorkbook = Path.Combine(sDirectorioXl, "workbook.xml");
string sArchivoXlRels = Path.Combine(sDirectorioXlRels, "workbook.xml.rels");
string sArchivoXlTheme = Path.Combine(sDirectorioXlTheme, "theme1.xml");
string[] sArchivoXlSheets = new string[nHojas];
for (var i = 0; i < nHojas;i++) sArchivoXlSheets[i] =
Path.Combine(sDirectorioXlWorksheets, String.Format("sheet{0}.xml",i+1));
//Crear los Directorios definidos
DirectoryInfo oDirectorioRaiz = Directory.CreateDirectory(sDirectorioRaiz);
oDirectorioRaiz.CreateSubdirectory("_rels");
oDirectorioRaiz.CreateSubdirectory("docProps");
DirectoryInfo oDirectorioXl = oDirectorioRaiz.CreateSubdirectory("xl");
oDirectorioXl.CreateSubdirectory("_rels");
oDirectorioXl.CreateSubdirectory("theme");
oDirectorioXl.CreateSubdirectory("worksheets");
//Crear los Archivos definidos
File.WriteAllText(sArchivoContentTypes, getContentTypes());
File.WriteAllText(sArchivoRels, getRels());
File.WriteAllText(sArchivoDocApp, getApp());
File.WriteAllText(sArchivoDocCore, getCore());
File.WriteAllText(sArchivoXlStyles, getXlStyles());
File.WriteAllText(sArchivoXlWorkbook, getXlWorkbook());
File.WriteAllText(sArchivoXlRels, getXlRels());
File.WriteAllText(sArchivoXlTheme, getXlTheme());
for (var i = 0; i < nHojas; i++) File.WriteAllText(sArchivoXlSheets[i], getXlSheet(i));
//Comprimir los archivos en un Xlsx
ZipFile.CreateFromDirectory(sDirectorioRaiz, sArchivoXlsx);
//Borrar todo el directorio con los archivos temporales creados
Directory.Delete(sDirectorioRaiz, true);
}
private static string getContentTypes()
{
StringBuilder sb = new StringBuilder();
sb.Append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>");
sb.Append("<Types xmlns=\"http://schemas.openxmlformats.org/
package/2006/content-types\">");
sb.Append("<Default Extension=\"rels\" ContentType=
\"application/vnd.openxmlformats-package.relationships+xml\"/>");
//sb.Append("<Default Extension=\"wmf\" ContentType=\"image/x-wmf\"/>");
sb.Append("<Default Extension=\"xml\" ContentType=\"application/xml\"/>");
sb.Append("<Override PartName=\"/xl/workbook.xml\" ContentType=
\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml\"/>");
sb.Append("<Override PartName=\"/xl/styles.xml\" ContentType=
\"application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml\"/>");
sb.Append("<Override PartName=\"/xl/theme/theme1.xml\" ContentType=
\"application/vnd.openxmlformats-officedocument.theme+xml\"/>");
sb.Append("<Override PartName=\"/docProps/core.xml\" ContentType=
\"application/vnd.openxmlformats-package.core-properties+xml\"/>");
sb.Append("<Override PartName=\"/docProps/app.xml\" ContentType=
\"application/vnd.openxmlformats-officedocument.extended-properties+xml\"/>");
for (var i = 0; i < nHojas; i++)
{
sb.Append("<Override PartName=\"/xl/worksheets/sheet");
sb.Append(i + 1);
sb.Append(".xml\" ContentType=\"application/vnd.openxmlformats-officedocument.
spreadsheetml.worksheet+xml\"/>");
}
sb.Append("</Types>");
return sb.ToString();
}
private static string getRels()
{
StringBuilder sb = new StringBuilder();
sb.Append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>");
sb.Append("<Relationships xmlns=\"http://schemas.openxmlformats.org/
package/2006/relationships\">");
sb.Append("<Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/
package/2006/relationships/metadata/core-properties\" Target=\"docProps/core.xml\"/>");
//sb.Append("<Relationship Id=\"rId2\" Type=\"http://schemas.openxmlformats.org/
package/2006/relationships/metadata/thumbnail\" Target=\"docProps/thumbnail.wmf\"/>");
sb.Append("<Relationship Id=\"rId2\" Type=\"http://schemas.openxmlformats.org/
officeDocument/2006/relationships/officeDocument\" Target=\"xl/workbook.xml\"/>");
sb.Append("<Relationship Id=\"rId3\" Type=\"http://schemas.openxmlformats.org/
officeDocument/2006/relationships/extended-properties\"
Target=\"docProps/app.xml\"/>");
sb.Append("</Relationships>");
return sb.ToString();
}
private static string getApp()
{
StringBuilder sb = new StringBuilder();
sb.Append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>");
sb.Append("<Properties xmlns=\"http://schemas.openxmlformats.org/
officeDocument/2006/extended-properties\"
xmlns:vt=\"http://schemas.openxmlformats.org/
officeDocument/2006/docPropsVTypes\">");
sb.Append("<Application>Microsoft Access</Application>");
sb.Append("<DocSecurity>0</DocSecurity>");
sb.Append("<ScaleCrop>false</ScaleCrop>");
sb.Append("<HeadingPairs>");
sb.Append("<vt:vector size=\"2\" baseType=\"variant\">");
sb.Append("<vt:variant><vt:lpstr>Worksheets</vt:lpstr></vt:variant>");
sb.Append("<vt:variant><vt:i4>1</vt:i4></vt:variant>");
sb.Append("</vt:vector>");
sb.Append("</HeadingPairs>");
sb.Append("<TitlesOfParts>");
sb.Append("<vt:vector size=\"1\" baseType=\"lpstr\">");
sb.Append("<vt:lpstr>A266FF2A662E84b639DA</vt:lpstr>");
sb.Append("</vt:vector>");
sb.Append("</TitlesOfParts>");
sb.Append("<Company>Microsoft</Company>");
sb.Append("<LinksUpToDate>false</LinksUpToDate>");
sb.Append("<SharedDoc>false</SharedDoc>");
sb.Append("<HyperlinksChanged>false</HyperlinksChanged>");
sb.Append("<AppVersion>12.0000</AppVersion>");
sb.Append("</Properties>");
return sb.ToString();
}
private static string getCore()
{
StringBuilder sb = new StringBuilder();
sb.Append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>");
sb.Append("<cp:coreProperties ");
sb.Append("xmlns:cp=\"http://schemas.openxmlformats.org/package/2006/metadata/
core-properties\" ");
sb.Append("xmlns:dc=\"http://purl.org/dc/elements/1.1/\" ");
sb.Append("xmlns:dcterms=\"http://purl.org/dc/terms/\" ");
sb.Append("xmlns:dcmitype=\"http://purl.org/dc/dcmitype/\" ");
sb.Append("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">");
sb.Append("<dc:creator>");
sb.Append(Environment.UserName);
sb.Append("</dc:creator>");
sb.Append("<cp:lastModifiedBy>");
sb.Append(Environment.UserName);
sb.Append("</cp:lastModifiedBy>");
sb.Append("<dcterms:created xsi:type=\"dcterms:W3CDTF\">");
sb.Append(DateTime.Now.ToString("s"));
sb.Append("Z</dcterms:created>");
sb.Append("<dcterms:modified xsi:type=\"dcterms:W3CDTF\">");
sb.Append(DateTime.Now.ToString("s"));
sb.Append("Z</dcterms:modified>");
sb.Append("</cp:coreProperties>");
return sb.ToString();
}
private static string getXlStyles()
{
StringBuilder sb = new StringBuilder();
sb.Append("<styleSheet xmlns=\"http://schemas.openxmlformats.org/
spreadsheetml/2006/main\">");
sb.Append("<fonts count=\"1\">");
sb.Append("<font>");
sb.Append("<sz val=\"11\"/>");
sb.Append("<color theme=\"1\"/>");
sb.Append("<name val=\"MS Sans Serif\"/>");
sb.Append("<family val=\"2\"/>");
sb.Append("<scheme val=\"minor\"/>");
sb.Append("</font>");
sb.Append("</fonts>");
sb.Append("<fills count=\"2\">");
sb.Append("<fill><patternFill patternType=\"none\"/></fill>");
sb.Append("<fill><patternFill patternType=\"gray125\"/></fill>");
sb.Append("</fills>");
sb.Append("<borders count=\"1\">");
sb.Append("<border><left/><right/><top/><bottom/><diagonal/></border>");
sb.Append("</borders>");
sb.Append("<cellStyleXfs count=\"1\">");
sb.Append("<xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\"/>");
sb.Append("</cellStyleXfs>");
sb.Append("<cellXfs count=\"1\">");
sb.Append("<xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\"/>");
sb.Append("</cellXfs>");
sb.Append("<cellStyles count=\"1\">");
sb.Append("<cellStyle name=\"Normal\" xfId=\"0\" builtinId=\"0\"/>");
sb.Append("</cellStyles>");
sb.Append("<dxfs count=\"0\"/>");
sb.Append("<tableStyles count=\"0\" defaultTableStyle=\"TableStyleMedium9\"
defaultPivotStyle=\"PivotStyleLight16\"/>");
sb.Append("</styleSheet>");
return sb.ToString();
}
private static string getXlWorkbook()
{
StringBuilder sb = new StringBuilder();
sb.Append("<workbook xmlns=\"http://schemas.openxmlformats.org/
spreadsheetml/2006/main\" ");
sb.Append("xmlns:r=\"http://schemas.openxmlformats.org/
officeDocument/2006/relationships\">");
sb.Append("<fileVersion appName=\"xl\" lastEdited=\"4\" lowestEdited=\"4\"
rupBuild=\"4505\"/>");
sb.Append("<workbookPr defaultThemeVersion=\"124226\"/>");
sb.Append("<bookViews>");
sb.Append("<workbookView xWindow=\"120\" yWindow=\"90\"
windowWidth=\"23895\" windowHeight=\"14535\"/>");
sb.Append("</bookViews>");
sb.Append("<sheets>");
for (var i = 0; i < nHojas; i++)
{
sb.Append("<sheet sheetId=\"");
sb.Append(i + 1);
sb.Append("\" r:id=\"rId");
sb.Append(i + 3);
sb.Append("\" name=\"");
sb.Append(sHojas[i]);
sb.Append("\"/>");
}
sb.Append("</sheets>");
sb.Append("<definedNames>");
for (var i = 0; i < nHojas; i++)
{
sb.Append("<definedName name=\"");
sb.Append(sHojas[i]);
sb.Append("\">'");
sb.Append(sHojas[i]);
sb.Append("'!$A$1:");
sb.Append(sRango[i]);
sb.Append("</definedName>");
}
sb.Append("</definedNames>");
sb.Append("<calcPr calcId=\"125725\" fullCalcOnLoad=\"true\"/>");
sb.Append("</workbook>");
return sb.ToString();
}
private static string getXlRels()
{
StringBuilder sb = new StringBuilder();
sb.Append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>");
sb.Append("<Relationships xmlns=\"http://schemas.openxmlformats.org/
package/2006/relationships\">");
sb.Append("<Relationship Id=\"rId1\" ");
sb.Append("Type=\"http://schemas.openxmlformats.org/
officeDocument/2006/relationships/styles\" ");
sb.Append("Target=\"styles.xml\"/>");
sb.Append("<Relationship Id=\"rId2\" ");
sb.Append("Type=\"http://schemas.openxmlformats.org/
officeDocument/2006/relationships/theme\" ");
sb.Append("Target=\"theme/theme1.xml\"/>");
for (var i = 0; i < nHojas; i++)
{
sb.Append("<Relationship Id=\"rId");
sb.Append(i + 3);
sb.Append("\" ");
sb.Append("Type=\"http://schemas.openxmlformats.org/
officeDocument/2006/relationships/worksheet\" ");
sb.Append("Target=\"worksheets/sheet");
sb.Append(i + 1);
sb.Append(".xml\"/>");
}
sb.Append("</Relationships>");
return sb.ToString();
}
private static string getXlTheme()
{
StringBuilder sb = new StringBuilder();
sb.Append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>");
sb.Append("<a:theme xmlns:a=\"http://schemas.openxmlformats.org/
drawingml/2006/main\" name=\"Office Theme\">");
sb.Append("<a:themeElements>");
sb.Append("<a:clrScheme name=\"Office\">");
sb.Append("<a:dk1><a:sysClr val=\"windowText\" lastClr=\"000000\"/></a:dk1>");
sb.Append("<a:lt1><a:sysClr val=\"window\" lastClr=\"FFFFFF\"/></a:lt1>");
sb.Append("<a:dk2><a:srgbClr val=\"1F497D\"/></a:dk2>");
sb.Append("<a:lt2><a:srgbClr val=\"EEECE1\"/></a:lt2>");
sb.Append("<a:accent1><a:srgbClr val=\"4F81BD\"/></a:accent1>");
sb.Append("</a:themeElements>");
sb.Append("<a:objectDefaults/>");
sb.Append("<a:extraClrSchemeLst/>");
sb.Append("</a:theme>");
return sb.ToString();
}
private static string getXlSheet(int nHoja)
{
StringBuilder sb = new StringBuilder();
sb.Append("<worksheet xmlns=\"http://schemas.openxmlformats.org/
spreadsheetml/2006/main\" ");
sb.Append("xmlns:r=\"http://schemas.openxmlformats.org/
officeDocument/2006/relationships\">");
sb.Append("<dimension ref=\"A1:");
sb.Append(sRango[nHoja]);
sb.Append("\"/>");
sb.Append("<sheetViews>");
sb.Append("<sheetView tabSelected=\"1\" workbookViewId=\"0\" rightToLeft=\"false\">");
sb.Append("<selection activeCell=\"A1\" sqref=\"A1\"/>");
sb.Append("</sheetView>");
sb.Append("</sheetViews>");
sb.Append("<sheetFormatPr defaultRowHeight=\"15\"/>");
sb.Append("<sheetData>");
if(tipoOrigen.Equals(TipoOrigen.Listas)) sb.Append(getSheetList(nHoja));
else sb.Append(getSheetTable(nHoja));
sb.Append("</sheetData>");
sb.Append("<pageMargins left=\"0.7\" right=\"0.7\" top=\"0.75\"
bottom=\"0.75\" header=\"0.3\" footer=\"0.3\"/>");
sb.Append("</worksheet>");
return sb.ToString();
}
private static string getSheetList(int nHoja)
{
StringBuilder sb = new StringBuilder();
var lista = data[nHoja];
PropertyInfo[] campos = lista[0].GetType().GetProperties();
sb.Append("<row outlineLevel=\"0\" r=\"1\">");
string celda;
string valor;
string tipo;
for (int j = 0; j < campos.Length; j++)
{
celda = String.Format("{0}1", (char)(65 + j));
valor = campos[j].Name;
sb.Append("<c r=\"");
sb.Append(celda);
sb.Append("\" s=\"0\" t=\"inlineStr\"><is><t>");
sb.Append(valor);
sb.Append("</t></is></c>");
}
sb.Append("</row>");
for (int i = 0; i < lista.Count; i++)
{
sb.Append("<row outlineLevel=\"0\" r=\"");
sb.Append(i + 2);
sb.Append("\">");
for (int j = 0; j < campos.Length; j++)
{
celda = String.Format("{0}{1}", (char)(65 + j),i+2);
valor = lista[i].GetType().GetProperty(campos[j].Name).
GetValue(lista[i], null).ToString();
tipo = lista[i].GetType().GetProperty(campos[j].Name).PropertyType.ToString();
sb.Append("<c r=\"");
sb.Append(celda);
sb.Append("\" s=\"0\"");
if (tipo.Contains("String"))
{
sb.Append(" t=\"inlineStr\"><is><t>");
sb.Append(valor);
sb.Append("</t></is>");
}
else
{
sb.Append("><v>");
sb.Append(valor);
sb.Append("</v>");
}
sb.Append("</c>");
}
sb.Append("</row>");
}
return sb.ToString();
}
private static string getSheetTable(int nHoja)
{
StringBuilder sb = new StringBuilder();
var tabla = data[nHoja];
DataColumnCollection campos = tabla.Columns;
sb.Append("<row outlineLevel=\"0\" r=\"1\">");
string celda;
string valor;
string tipo;
for (int j = 0; j < campos.Count ; j++)
{
celda = String.Format("{0}1", (char)(65 + j));
valor = campos[j].ColumnName;
sb.Append("<c r=\"");
sb.Append(celda);
sb.Append("\" s=\"0\" t=\"inlineStr\"><is><t>");
sb.Append(valor);
sb.Append("</t></is></c>");
}
sb.Append("</row>");
for (int i = 0; i < tabla.Rows.Count; i++)
{
sb.Append("<row outlineLevel=\"0\" r=\"");
sb.Append(i + 2);
sb.Append("\">");
for (int j = 0; j < campos.Count; j++)
{
celda = String.Format("{0}{1}", (char)(65 + j), i + 2);
valor = tabla.Rows[i][j].ToString();
tipo = campos[j].DataType.ToString();
sb.Append("<c r=\"");
sb.Append(celda);
sb.Append("\" s=\"0\"");
if (tipo.Contains("String"))
{
sb.Append(" t=\"inlineStr\"><is><t>");
sb.Append(valor);
sb.Append("</t></is>");
}
else
{
sb.Append("><v>");
sb.Append(valor);
sb.Append("</v>");
}
sb.Append("</c>");
}
sb.Append("</row>");
}
return sb.ToString();
}
}
}
7. Explicación Resumida de la Clase Excel
Para cada origen de datos se ha creado un método: "ExportarDeLista" que trabaja con Reflection para extraer los datos de las listas y "ExportarDeTabla" que trabaja con DataTable para extraer los datos de las tablas.
Ambos métodos llaman a una función común y principal llamada "crearDirectoriosArchivos" que primero define las rutas de los directorios y archivos a crear y luego crea los directorios y archivos definidos.
La función "crearDirectoriosArchivos" llama a diferentes funciones una para crear cada archivo XML y para llenar la data de las listas se usa la función "getSheetList" y para llenar la data de las tablas se usa la función "getSheetTable".
Finalmente se comprime los archivos en un solo archivo XLSX y se borra todos los directorios y archivos XML creados temporalmente.
8. Programar el formulario para que use las Clases creadas y Exporte
El último bloque a codificar es el formulario "frmExcel" en el cual debe escribir el siguiente código:
using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.IO;
using System.Diagnostics;
using System.Windows.Forms;
namespace Excel_Crear_XML
{
public partial class frmExcel : Form
{
private beCategoriaProducto obeCatPro;
private DataSet dstCatPro;
private string archivoXlsx;
private string[] hojas;
public frmExcel()
{
InitializeComponent();
}
private void llenarDesdeListas(object sender, EventArgs e)
{
//Simular que se llenan las listas desde la base de datos
obeCatPro = new beCategoriaProducto();
obeCatPro.ListaCategoria = Data.ListaCategorias();
obeCatPro.ListaProducto = Data.ListaProductos();
//Enlazar las listas del objeto principal a las grillas
dgvCategoria.DataSource = obeCatPro.ListaCategoria;
dgvProducto.DataSource = obeCatPro.ListaProducto;
//Habilitar botón de Exportar Listas a Excel y deshabilitar el otro
btnExportarListas.Enabled = true;
btnExportarTablas.Enabled = false;
}
private void llenarDesdeTablas(object sender, EventArgs e)
{
//Simular que se llenan las tablas desde la base de datos
dstCatPro = new DataSet();
dstCatPro.Tables.Add(Data.TablaCategorias());
dstCatPro.Tables.Add(Data.TablaProductos());
//Enlazar las tablas del DataSet a las grillas
dgvCategoria.DataSource = dstCatPro.Tables[0];
dgvProducto.DataSource = dstCatPro.Tables[1];
//Habilitar botón de Exportar Tablas a Excel y deshabilitar el otro
btnExportarListas.Enabled = false;
btnExportarTablas.Enabled = true;
}
private void guardarExcel(Action exportar)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.Title = "Selecciona el Directorio e ingresa Nombre del Archivo Excel";
sfd.Filter = "Archivos de Excel 2007|*.xlsx";
if (sfd.ShowDialog().Equals(DialogResult.OK))
{
archivoXlsx = sfd.FileName;
hojas = new string[]{"Categorias", "Productos"};
Stopwatch oCronometro = new Stopwatch();
oCronometro.Start();
exportar();
oCronometro.Stop();
MessageBox.Show(String.Format("Archivo Excel fué creado en {0:n0} msg",
oCronometro.Elapsed.TotalMilliseconds));
}
}
private void exportarDesdeListas()
{
Excel.ExportarDeLista(archivoXlsx, hojas, obeCatPro);
}
private void exportarDesdeTablas()
{
Excel.ExportarDeTabla(archivoXlsx, hojas, dstCatPro);
}
private void exportarListasExcel(object sender, EventArgs e)
{
guardarExcel(exportarDesdeListas);
}
private void exportarTablasExcel(object sender, EventArgs e)
{
guardarExcel(exportarDesdeTablas);
}
}
}
9. Ejecutar y Probar la Aplicación Windows Forms
Grabar la aplicación y pulsar F5 para ejecutarla, se mostrará una ventana similar a la figura:
Luego clic al primer botón "Llenar desde Listas" y se mostrará en las grillas los datos desde las listas de categorías y productos, tal como se muestra en las siguientes figuras:
Se habilitará el botón de "Exportar Listas a Excel" al cual si se da click se mostrará el siguiente diálogo de guardar:
Escribir el nombre del archivo de Excel 2007, por ejemplo "ListasXML.xlsx" y "Guardar" e inmediatamente se mostrará un cuadro de diálogo con el tiempo que demoró la operación.
Continuando con las pruebas click al botón "Llenar desde Tablas" y se mostrará en las grillas los datos desde las tablas de categorías y productos, similar a las presentadas en las figuras de arriba.
Se habilitará el botón de "Exportar Tablas a Excel" al cual si se da click se mostrará el siguiente diálogo de guardar:
Escribir el nombre del archivo de Excel 2007, por ejemplo "TablasXML.xlsx" y "Guardar" e inmediatamente se mostrará un cuadro de diálogo con el tiempo que demoró la operación.
Finalmente, pueden abrir los 2 archivos de Excel creados que contendrán ambos 2 hojas: Categorías y Productos con los datos de los orígenes.
10. Comentario Final
Personalmente considero este post como uno de mis favoritos ya que no hay información en Internet sobre cómo crear un archivo de Excel 2007 en forma nativa, es decir creando los archivos XML necesarios para luego comprimirlos en un solo archivo XLSX.
Esta técnica es muy rápida, no necesita de instalar nada, y puede crear archivos de Excel con todo tipo de objetos como gráficos, formas, estilos, formatos, etc. Es la mejor forma para exportar datos sobre todo en la Web ya que también se puede hacer por JavaScript nativo como lo veremos en otro post.
Espero que este post ayude a muchas programadores a entender como es la estructura de un archivo Excel y poder crearlo sin necesidad de usar librerías, ya que según mi opinión solo volviendo a "Crear la Rueda" se puede construir una mejor. Los que usen el refrán "Para que Inventar la Rueda" es porque "NO saben como crearla".
Este Blog nació con ese fin, demostrar que con un poco de ingenio y mucha investigación se puede hacer "cualquier cosa". Finalmente, los quiero dejar con otra reflexión: "Fácil es hacer Complejo lo Simple", pero "Difícil es hacer Simple lo Complejo".
Cuando uno aprende hacer lo Complejo Simple estará en condiciones de resolver cualquier problema en corto tiempo y no esperar a que otro lo haga por ti (Frameworks y Librerías) que éste se hace mas fuerte y tu dependiente de él. Además que te pierdes de lo más interesante.
11. Descarga la Aplicación Windows
2016_08_09_Demo_Excel_Crear_XML
1. Introducción
En el post anterior vimos las 3 técnicas que hay para crear un archivo de Excel 2007 exportando datos desde varias listas de objetos o varias tablas de un DataSet en .NET. En ese post se presentó un Demo de cómo usar OLEDB para crear el archivo Excel.
En este post vamos a ver algo inédito, que no hay en la web, que es como crear un archivo de Excel 2007, creando los archivos XML necesarios y luego comprimiendolo en un xlsx.
2. Ventajas de Crear un Archivo Excel usando XML
Existen muchas ventajas de usar esta técnica entre las 3 mas importantes tenemos:
- Es la más rápida en la creación de archivos Excel, casi 3 veces más rápida que OLEDB y mas de 10 veces más rápida que abrir una instancia de Excel (Automatización COM).
- No necesita tener instalado ni los Componentes de Acceso a Datos del "Microsoft Access Database Engine 2010 Redistributable" ni tampoco una instancia de Excel para crear el archivo.
Nota: Ni siquiera se necesita tener instalado el Excel para leer o ver el archivo ya que se puede hacer usando los Visores de los Demos pasados.
- Se puede crear no solo celdas con datos sino gráficos, dar estilo, formatos, etc, cosa que no se puede al usar OLEDB.
Nota: Si se puede abriendo una instancia de Excel pero se demora demasiado y consume muchos recursos, lo cual está terminantemente prohibido para Aplicaciones Web ASP.NET.
3. Crear una Aplicación Windows Forms en C#
Abrir Visual Studio y crear una aplicación Windows Forms en C# llamada "Excel_Crear_XML", cambiarle de nombre al formulario por "frmExcel" y realizar el diseño similar a la figura mostrada:
Diseño del formulario "frmExcel"
En el diseño hay los siguientes controles:
- Botón para Llenar desde Listas llamado "btnLlenarLista".
- Botón para Llenar desde Tablas llamado "btnLlenarTabla".
- Botón para Exportar Listas a Excel llamado "btnExportarListas". Deshabilitado por defecto.
- Botón para Exportar Tablas a Excel llamado "btnExportarTablas". Deshabilitado por defecto.
- Control Tab llamado "tabExcel" con 2 tabPages: "tabCategorias" y "tabProducto".
- Control DataGridView llamado "dgvCategoria" ubicado en el tab de Categorias.
- Control DataGridView llamado "dgvProducto" ubicado en el tab de Productos.
4. Crear las Clases con las Entidades de Negocio
Lo primero que debemos crear son las clases de entidades para las listas de objetos de categorías y productos:
Archivo de Clase: beCategoria.cs
namespace Excel_Crear_XML
{
public class beCategoria
{
public int IdCategoria { get; set; }
public string Nombre { get; set; }
}
}
Archivo de Clase: beProducto.cs
namespace Excel_Crear_XML
{
public class beProducto
{
public int IdProducto { get; set; }
public string Nombre { get; set; }
public int IdCategoria { get; set; }
public decimal Precio { get; set; }
public short Stock { get; set; }
}
}
Archivo de Clase: beCategoriaProducto.cs
using System.Collections.Generic;
namespace Excel_Crear_XML
{
public class beCategoriaProducto
{
public List<beCategoria> ListaCategoria { get; set; }
public List<beProducto> ListaProducto { get; set; }
}
}
5. Crear una Clase que permita llenar los Datos
Lo segundo que debemos hacer es crear una clase para llenar los datos de las tablas y listas de objetos tanto para categorías como productos.
En una aplicación real esto se reemplazará por la llamada a un componente de reglas del negocio y solo se elegirá uno de las 2 repositorios de datos: DataSet o Objeto con Listas. Lo recomendable es elegir el Objeto con Listas ya que consume menos memoria y procesa más rápido.
Archivo de Clase: Data.cs
using System;
using System.Collections.Generic;
using System.Data;
namespace Excel_Crear_XML
{
public class Data
{
public static List<beCategoria> ListaCategorias()
{
//Llenar la Lista de Categorias
List<beCategoria> lbeCategoria = new List<beCategoria>();
lbeCategoria.Add(new beCategoria
{
IdCategoria = 1,
Nombre = "Bebidas"
});
lbeCategoria.Add(new beCategoria
{
IdCategoria = 2,
Nombre = "Cereales"
});
lbeCategoria.Add(new beCategoria
{
IdCategoria = 3,
Nombre = "Condimentos"
});
lbeCategoria.Add(new beCategoria
{
IdCategoria = 4,
Nombre = "Lacteos"
});
lbeCategoria.Add(new beCategoria
{
IdCategoria = 5,
Nombre = "Pastas"
});
return lbeCategoria;
}
public static List<beProducto> ListaProductos()
{
//Llenar la Lista de Productos
List<beProducto> lbeProducto = new List<beProducto>();
lbeProducto.Add(new beProducto
{
IdProducto = 1,
Nombre = "Pepsi",
IdCategoria = 1,
Precio = 1.5M,
Stock = 100
});
lbeProducto.Add(new beProducto
{
IdProducto = 2,
Nombre = "Avena 3 Ositos",
IdCategoria = 2,
Precio = 2.0M,
Stock = 50
});
lbeProducto.Add(new beProducto
{
IdProducto = 3,
Nombre = "Ajinomoto",
IdCategoria = 3,
Precio = 0.5M,
Stock = 200
});
lbeProducto.Add(new beProducto
{
IdProducto = 4,
Nombre = "Leche Gloria",
IdCategoria = 4,
Precio = 3.5M,
Stock = 300
});
lbeProducto.Add(new beProducto
{
IdProducto = 5,
Nombre = "Fideos Lavaggi",
IdCategoria = 5,
Precio = 3.0M,
Stock = 150
});
lbeProducto.Add(new beProducto
{
IdProducto = 6,
Nombre = "Sprite",
IdCategoria = 1,
Precio = 2.0M,
Stock = 200
});
lbeProducto.Add(new beProducto
{
IdProducto = 7,
Nombre = "Quinua Avena",
IdCategoria = 2,
Precio = 2.5M,
Stock = 150
});
lbeProducto.Add(new beProducto
{
IdProducto = 8,
Nombre = "Tuco Sibarita",
IdCategoria = 3,
Precio = 0.5M,
Stock = 200
});
lbeProducto.Add(new beProducto
{
IdProducto = 9,
Nombre = "Leche Pura Vida",
IdCategoria = 4,
Precio = 3.5M,
Stock = 300
});
lbeProducto.Add(new beProducto
{
IdProducto = 10,
Nombre = "Spagetti Don Victorio",
IdCategoria = 5,
Precio = 2.0M,
Stock = 250
});
return lbeProducto;
}
public static DataTable TablaCategorias()
{
//Llenar la Tabla de Categorias
DataTable tblCategoria = new DataTable();
tblCategoria.Columns.Add("IdCategoria",
Type.GetType("System.Int32"));
tblCategoria.Columns.Add("Nombre",
Type.GetType("System.String"));
DataRow drCat1 = tblCategoria.NewRow();
drCat1[0] = 1;
drCat1[1] = "Bebidas";
tblCategoria.Rows.Add(drCat1);
DataRow drCat2 = tblCategoria.NewRow();
drCat2[0] = 2;
drCat2[1] = "Cereales";
tblCategoria.Rows.Add(drCat2);
DataRow drCat3 = tblCategoria.NewRow();
drCat3[0] = 3;
drCat3[1] = "Condimentos";
tblCategoria.Rows.Add(drCat3);
DataRow drCat4 = tblCategoria.NewRow();
drCat4[0] = 4;
drCat4[1] = "Lacteos";
tblCategoria.Rows.Add(drCat4);
DataRow drCat5 = tblCategoria.NewRow();
drCat5[0] = 5;
drCat5[1] = "Pastas";
tblCategoria.Rows.Add(drCat5);
return tblCategoria;
}
public static DataTable TablaProductos()
{
//Llenar la Tabla de Productos
DataTable tblProducto = new DataTable();
tblProducto.Columns.Add("IdProducto",
Type.GetType("System.Int32"));
tblProducto.Columns.Add("Nombre",
Type.GetType("System.String"));
tblProducto.Columns.Add("IdCategoria",
Type.GetType("System.Int32"));
tblProducto.Columns.Add("Precio",
Type.GetType("System.Decimal"));
tblProducto.Columns.Add("Stock",
Type.GetType("System.Int16"));
DataRow drPro1 = tblProducto.NewRow();
drPro1[0] = 1;
drPro1[1] = "Pepsi";
drPro1[2] = 1;
drPro1[3] = 1.5M;
drPro1[4] = 100;
tblProducto.Rows.Add(drPro1);
DataRow drPro2 = tblProducto.NewRow();
drPro2[0] = 2;
drPro2[1] = "Avena 3 Ositos";
drPro2[2] = 2;
drPro2[3] = 2.0M;
drPro2[4] = 50;
tblProducto.Rows.Add(drPro2);
DataRow drPro3 = tblProducto.NewRow();
drPro3[0] = 3;
drPro3[1] = "Ajinomoto";
drPro3[2] = 3;
drPro3[3] = 0.5M;
drPro3[4] = 200;
tblProducto.Rows.Add(drPro3);
DataRow drPro4 = tblProducto.NewRow();
drPro4[0] = 4;
drPro4[1] = "Leche Gloria";
drPro4[2] = 4;
drPro4[3] = 3.5M;
drPro4[4] = 300;
tblProducto.Rows.Add(drPro4);
DataRow drPro5 = tblProducto.NewRow();
drPro5[0] = 5;
drPro5[1] = "Fideos Lavaggi";
drPro5[2] = 5;
drPro5[3] = 3.0M;
drPro5[4] = 150;
tblProducto.Rows.Add(drPro5);
DataRow drPro6 = tblProducto.NewRow();
drPro6[0] = 6;
drPro6[1] = "Sprite";
drPro6[2] = 1;
drPro6[3] = 2.0M;
drPro6[4] = 200;
tblProducto.Rows.Add(drPro6);
DataRow drPro7 = tblProducto.NewRow();
drPro7[0] = 7;
drPro7[1] = "Quinua Avena";
drPro7[2] = 2;
drPro7[3] = 2.5M;
drPro7[4] = 150;
tblProducto.Rows.Add(drPro7);
DataRow drPro8 = tblProducto.NewRow();
drPro8[0] = 8;
drPro8[1] = "Tuco Sibarita";
drPro8[2] = 3;
drPro8[3] = 0.5M;
drPro8[4] = 200;
tblProducto.Rows.Add(drPro8);
DataRow drPro9 = tblProducto.NewRow();
drPro9[0] = 9;
drPro9[1] = "Leche Pura Vida";
drPro9[2] = 4;
drPro9[3] = 3.5M;
drPro9[4] = 200;
tblProducto.Rows.Add(drPro9);
DataRow drPro10 = tblProducto.NewRow();
drPro10[0] = 10;
drPro10[1] = "Spagetti Don Victorio";
drPro10[2] = 5;
drPro10[3] = 2.0M;
drPro10[4] = 250;
tblProducto.Rows.Add(drPro10);
return tblProducto;
}
}
}
6. Crear una Clase que permita Crear Archivos XML y Comprimirlos
La tercera parte a codificar es crear una clase que permita crear los diferentes archivos XML necesitados y luego comprimirlos en un archivo XLSX.
Archivo de Clase: Excel.cs
using System;
using System.IO;
using System.Data;
using System.Text;
using System.Reflection;
using System.Linq;
using System.Collections.Generic;
using System.IO.Compression;
namespace Excel_Crear_XML
{
public class Excel
{
private enum TipoOrigen {
Listas = 0,
Tablas =1
}
private static string sArchivoXlsx;
private static string[] sHojas;
private static string[] sRango;
private static int nHojas;
private static TipoOrigen tipoOrigen;
private static List<dynamic> data;
public static void ExportarDeLista<T>(string archivoXlsx, string[] hojas, T objData)
{
data = new List<dynamic>();
tipoOrigen = TipoOrigen.Listas;
sArchivoXlsx = archivoXlsx;
sHojas = hojas;
nHojas = hojas.Length;
sRango = new string[nHojas];
PropertyInfo[] listas = objData.GetType().GetProperties();
dynamic lista;
PropertyInfo[] campos;
for (int i = 0; i < listas.Length;i++)
{
lista = listas[i].GetValue(objData, null);
data.Add(lista);
campos = lista[0].GetType().GetProperties();
sRango[i] = String.Format("${0}${1}", (char)(64 + campos.Length), lista.Count + 1);
}
crearDirectoriosArchivos();
}
public static void ExportarDeTabla(string archivoXlsx, string[] hojas, DataSet objData)
{
data = new List<dynamic>();
tipoOrigen = TipoOrigen.Tablas;
sArchivoXlsx = archivoXlsx;
sHojas = hojas;
nHojas = hojas.Length;
sRango = new string[nHojas];
DataTable tabla;
for (int i = 0; i < objData.Tables.Count; i++)
{
tabla = objData.Tables[i];
data.Add(tabla);
sRango[i] = String.Format("${0}${1}",
(char)(64 + tabla.Columns.Count), tabla.Rows.Count + 1);
}
crearDirectoriosArchivos();
}
private static void crearDirectoriosArchivos()
{
//Definir la ruta de los directorios a crear
string sDirectorioRaiz = Path.Combine(Path.GetDirectoryName(sArchivoXlsx),
Path.GetFileNameWithoutExtension(sArchivoXlsx));
string sDirectorioRels = Path.Combine(sDirectorioRaiz, "_rels");
string sDirectorioDocProps = Path.Combine(sDirectorioRaiz, "docProps");
string sDirectorioXl = Path.Combine(sDirectorioRaiz, "xl");
string sDirectorioXlRels = Path.Combine(sDirectorioXl, "_rels");
string sDirectorioXlTheme = Path.Combine(sDirectorioXl, "theme");
string sDirectorioXlWorksheets = Path.Combine(sDirectorioXl, "worksheets");
//Definir la ruta de los archivos a crear
string sArchivoContentTypes = Path.Combine(sDirectorioRaiz, "[Content_Types].xml");
string sArchivoRels = Path.Combine(sDirectorioRels, ".rels");
string sArchivoDocApp = Path.Combine(sDirectorioDocProps, "app.xml");
string sArchivoDocCore = Path.Combine(sDirectorioDocProps, "core.xml");
string sArchivoXlStyles = Path.Combine(sDirectorioXl, "styles.xml");
string sArchivoXlWorkbook = Path.Combine(sDirectorioXl, "workbook.xml");
string sArchivoXlRels = Path.Combine(sDirectorioXlRels, "workbook.xml.rels");
string sArchivoXlTheme = Path.Combine(sDirectorioXlTheme, "theme1.xml");
string[] sArchivoXlSheets = new string[nHojas];
for (var i = 0; i < nHojas;i++) sArchivoXlSheets[i] =
Path.Combine(sDirectorioXlWorksheets, String.Format("sheet{0}.xml",i+1));
//Crear los Directorios definidos
DirectoryInfo oDirectorioRaiz = Directory.CreateDirectory(sDirectorioRaiz);
oDirectorioRaiz.CreateSubdirectory("_rels");
oDirectorioRaiz.CreateSubdirectory("docProps");
DirectoryInfo oDirectorioXl = oDirectorioRaiz.CreateSubdirectory("xl");
oDirectorioXl.CreateSubdirectory("_rels");
oDirectorioXl.CreateSubdirectory("theme");
oDirectorioXl.CreateSubdirectory("worksheets");
//Crear los Archivos definidos
File.WriteAllText(sArchivoContentTypes, getContentTypes());
File.WriteAllText(sArchivoRels, getRels());
File.WriteAllText(sArchivoDocApp, getApp());
File.WriteAllText(sArchivoDocCore, getCore());
File.WriteAllText(sArchivoXlStyles, getXlStyles());
File.WriteAllText(sArchivoXlWorkbook, getXlWorkbook());
File.WriteAllText(sArchivoXlRels, getXlRels());
File.WriteAllText(sArchivoXlTheme, getXlTheme());
for (var i = 0; i < nHojas; i++) File.WriteAllText(sArchivoXlSheets[i], getXlSheet(i));
//Comprimir los archivos en un Xlsx
ZipFile.CreateFromDirectory(sDirectorioRaiz, sArchivoXlsx);
//Borrar todo el directorio con los archivos temporales creados
Directory.Delete(sDirectorioRaiz, true);
}
private static string getContentTypes()
{
StringBuilder sb = new StringBuilder();
sb.Append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>");
sb.Append("<Types xmlns=\"http://schemas.openxmlformats.org/
package/2006/content-types\">");
sb.Append("<Default Extension=\"rels\" ContentType=
\"application/vnd.openxmlformats-package.relationships+xml\"/>");
//sb.Append("<Default Extension=\"wmf\" ContentType=\"image/x-wmf\"/>");
sb.Append("<Default Extension=\"xml\" ContentType=\"application/xml\"/>");
sb.Append("<Override PartName=\"/xl/workbook.xml\" ContentType=
\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml\"/>");
sb.Append("<Override PartName=\"/xl/styles.xml\" ContentType=
\"application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml\"/>");
sb.Append("<Override PartName=\"/xl/theme/theme1.xml\" ContentType=
\"application/vnd.openxmlformats-officedocument.theme+xml\"/>");
sb.Append("<Override PartName=\"/docProps/core.xml\" ContentType=
\"application/vnd.openxmlformats-package.core-properties+xml\"/>");
sb.Append("<Override PartName=\"/docProps/app.xml\" ContentType=
\"application/vnd.openxmlformats-officedocument.extended-properties+xml\"/>");
for (var i = 0; i < nHojas; i++)
{
sb.Append("<Override PartName=\"/xl/worksheets/sheet");
sb.Append(i + 1);
sb.Append(".xml\" ContentType=\"application/vnd.openxmlformats-officedocument.
spreadsheetml.worksheet+xml\"/>");
}
sb.Append("</Types>");
return sb.ToString();
}
private static string getRels()
{
StringBuilder sb = new StringBuilder();
sb.Append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>");
sb.Append("<Relationships xmlns=\"http://schemas.openxmlformats.org/
package/2006/relationships\">");
sb.Append("<Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/
package/2006/relationships/metadata/core-properties\" Target=\"docProps/core.xml\"/>");
//sb.Append("<Relationship Id=\"rId2\" Type=\"http://schemas.openxmlformats.org/
package/2006/relationships/metadata/thumbnail\" Target=\"docProps/thumbnail.wmf\"/>");
sb.Append("<Relationship Id=\"rId2\" Type=\"http://schemas.openxmlformats.org/
officeDocument/2006/relationships/officeDocument\" Target=\"xl/workbook.xml\"/>");
sb.Append("<Relationship Id=\"rId3\" Type=\"http://schemas.openxmlformats.org/
officeDocument/2006/relationships/extended-properties\"
Target=\"docProps/app.xml\"/>");
sb.Append("</Relationships>");
return sb.ToString();
}
private static string getApp()
{
StringBuilder sb = new StringBuilder();
sb.Append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>");
sb.Append("<Properties xmlns=\"http://schemas.openxmlformats.org/
officeDocument/2006/extended-properties\"
xmlns:vt=\"http://schemas.openxmlformats.org/
officeDocument/2006/docPropsVTypes\">");
sb.Append("<Application>Microsoft Access</Application>");
sb.Append("<DocSecurity>0</DocSecurity>");
sb.Append("<ScaleCrop>false</ScaleCrop>");
sb.Append("<HeadingPairs>");
sb.Append("<vt:vector size=\"2\" baseType=\"variant\">");
sb.Append("<vt:variant><vt:lpstr>Worksheets</vt:lpstr></vt:variant>");
sb.Append("<vt:variant><vt:i4>1</vt:i4></vt:variant>");
sb.Append("</vt:vector>");
sb.Append("</HeadingPairs>");
sb.Append("<TitlesOfParts>");
sb.Append("<vt:vector size=\"1\" baseType=\"lpstr\">");
sb.Append("<vt:lpstr>A266FF2A662E84b639DA</vt:lpstr>");
sb.Append("</vt:vector>");
sb.Append("</TitlesOfParts>");
sb.Append("<Company>Microsoft</Company>");
sb.Append("<LinksUpToDate>false</LinksUpToDate>");
sb.Append("<SharedDoc>false</SharedDoc>");
sb.Append("<HyperlinksChanged>false</HyperlinksChanged>");
sb.Append("<AppVersion>12.0000</AppVersion>");
sb.Append("</Properties>");
return sb.ToString();
}
private static string getCore()
{
StringBuilder sb = new StringBuilder();
sb.Append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>");
sb.Append("<cp:coreProperties ");
sb.Append("xmlns:cp=\"http://schemas.openxmlformats.org/package/2006/metadata/
core-properties\" ");
sb.Append("xmlns:dc=\"http://purl.org/dc/elements/1.1/\" ");
sb.Append("xmlns:dcterms=\"http://purl.org/dc/terms/\" ");
sb.Append("xmlns:dcmitype=\"http://purl.org/dc/dcmitype/\" ");
sb.Append("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">");
sb.Append("<dc:creator>");
sb.Append(Environment.UserName);
sb.Append("</dc:creator>");
sb.Append("<cp:lastModifiedBy>");
sb.Append(Environment.UserName);
sb.Append("</cp:lastModifiedBy>");
sb.Append("<dcterms:created xsi:type=\"dcterms:W3CDTF\">");
sb.Append(DateTime.Now.ToString("s"));
sb.Append("Z</dcterms:created>");
sb.Append("<dcterms:modified xsi:type=\"dcterms:W3CDTF\">");
sb.Append(DateTime.Now.ToString("s"));
sb.Append("Z</dcterms:modified>");
sb.Append("</cp:coreProperties>");
return sb.ToString();
}
private static string getXlStyles()
{
StringBuilder sb = new StringBuilder();
sb.Append("<styleSheet xmlns=\"http://schemas.openxmlformats.org/
spreadsheetml/2006/main\">");
sb.Append("<fonts count=\"1\">");
sb.Append("<font>");
sb.Append("<sz val=\"11\"/>");
sb.Append("<color theme=\"1\"/>");
sb.Append("<name val=\"MS Sans Serif\"/>");
sb.Append("<family val=\"2\"/>");
sb.Append("<scheme val=\"minor\"/>");
sb.Append("</font>");
sb.Append("</fonts>");
sb.Append("<fills count=\"2\">");
sb.Append("<fill><patternFill patternType=\"none\"/></fill>");
sb.Append("<fill><patternFill patternType=\"gray125\"/></fill>");
sb.Append("</fills>");
sb.Append("<borders count=\"1\">");
sb.Append("<border><left/><right/><top/><bottom/><diagonal/></border>");
sb.Append("</borders>");
sb.Append("<cellStyleXfs count=\"1\">");
sb.Append("<xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\"/>");
sb.Append("</cellStyleXfs>");
sb.Append("<cellXfs count=\"1\">");
sb.Append("<xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\"/>");
sb.Append("</cellXfs>");
sb.Append("<cellStyles count=\"1\">");
sb.Append("<cellStyle name=\"Normal\" xfId=\"0\" builtinId=\"0\"/>");
sb.Append("</cellStyles>");
sb.Append("<dxfs count=\"0\"/>");
sb.Append("<tableStyles count=\"0\" defaultTableStyle=\"TableStyleMedium9\"
defaultPivotStyle=\"PivotStyleLight16\"/>");
sb.Append("</styleSheet>");
return sb.ToString();
}
private static string getXlWorkbook()
{
StringBuilder sb = new StringBuilder();
sb.Append("<workbook xmlns=\"http://schemas.openxmlformats.org/
spreadsheetml/2006/main\" ");
sb.Append("xmlns:r=\"http://schemas.openxmlformats.org/
officeDocument/2006/relationships\">");
sb.Append("<fileVersion appName=\"xl\" lastEdited=\"4\" lowestEdited=\"4\"
rupBuild=\"4505\"/>");
sb.Append("<workbookPr defaultThemeVersion=\"124226\"/>");
sb.Append("<bookViews>");
sb.Append("<workbookView xWindow=\"120\" yWindow=\"90\"
windowWidth=\"23895\" windowHeight=\"14535\"/>");
sb.Append("</bookViews>");
sb.Append("<sheets>");
for (var i = 0; i < nHojas; i++)
{
sb.Append("<sheet sheetId=\"");
sb.Append(i + 1);
sb.Append("\" r:id=\"rId");
sb.Append(i + 3);
sb.Append("\" name=\"");
sb.Append(sHojas[i]);
sb.Append("\"/>");
}
sb.Append("</sheets>");
sb.Append("<definedNames>");
for (var i = 0; i < nHojas; i++)
{
sb.Append("<definedName name=\"");
sb.Append(sHojas[i]);
sb.Append("\">'");
sb.Append(sHojas[i]);
sb.Append("'!$A$1:");
sb.Append(sRango[i]);
sb.Append("</definedName>");
}
sb.Append("</definedNames>");
sb.Append("<calcPr calcId=\"125725\" fullCalcOnLoad=\"true\"/>");
sb.Append("</workbook>");
return sb.ToString();
}
private static string getXlRels()
{
StringBuilder sb = new StringBuilder();
sb.Append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>");
sb.Append("<Relationships xmlns=\"http://schemas.openxmlformats.org/
package/2006/relationships\">");
sb.Append("<Relationship Id=\"rId1\" ");
sb.Append("Type=\"http://schemas.openxmlformats.org/
officeDocument/2006/relationships/styles\" ");
sb.Append("Target=\"styles.xml\"/>");
sb.Append("<Relationship Id=\"rId2\" ");
sb.Append("Type=\"http://schemas.openxmlformats.org/
officeDocument/2006/relationships/theme\" ");
sb.Append("Target=\"theme/theme1.xml\"/>");
for (var i = 0; i < nHojas; i++)
{
sb.Append("<Relationship Id=\"rId");
sb.Append(i + 3);
sb.Append("\" ");
sb.Append("Type=\"http://schemas.openxmlformats.org/
officeDocument/2006/relationships/worksheet\" ");
sb.Append("Target=\"worksheets/sheet");
sb.Append(i + 1);
sb.Append(".xml\"/>");
}
sb.Append("</Relationships>");
return sb.ToString();
}
private static string getXlTheme()
{
StringBuilder sb = new StringBuilder();
sb.Append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>");
sb.Append("<a:theme xmlns:a=\"http://schemas.openxmlformats.org/
drawingml/2006/main\" name=\"Office Theme\">");
sb.Append("<a:themeElements>");
sb.Append("<a:clrScheme name=\"Office\">");
sb.Append("<a:dk1><a:sysClr val=\"windowText\" lastClr=\"000000\"/></a:dk1>");
sb.Append("<a:lt1><a:sysClr val=\"window\" lastClr=\"FFFFFF\"/></a:lt1>");
sb.Append("<a:dk2><a:srgbClr val=\"1F497D\"/></a:dk2>");
sb.Append("<a:lt2><a:srgbClr val=\"EEECE1\"/></a:lt2>");
sb.Append("<a:accent1><a:srgbClr val=\"4F81BD\"/></a:accent1>");
sb.Append("</a:themeElements>");
sb.Append("<a:objectDefaults/>");
sb.Append("<a:extraClrSchemeLst/>");
sb.Append("</a:theme>");
return sb.ToString();
}
private static string getXlSheet(int nHoja)
{
StringBuilder sb = new StringBuilder();
sb.Append("<worksheet xmlns=\"http://schemas.openxmlformats.org/
spreadsheetml/2006/main\" ");
sb.Append("xmlns:r=\"http://schemas.openxmlformats.org/
officeDocument/2006/relationships\">");
sb.Append("<dimension ref=\"A1:");
sb.Append(sRango[nHoja]);
sb.Append("\"/>");
sb.Append("<sheetViews>");
sb.Append("<sheetView tabSelected=\"1\" workbookViewId=\"0\" rightToLeft=\"false\">");
sb.Append("<selection activeCell=\"A1\" sqref=\"A1\"/>");
sb.Append("</sheetView>");
sb.Append("</sheetViews>");
sb.Append("<sheetFormatPr defaultRowHeight=\"15\"/>");
sb.Append("<sheetData>");
if(tipoOrigen.Equals(TipoOrigen.Listas)) sb.Append(getSheetList(nHoja));
else sb.Append(getSheetTable(nHoja));
sb.Append("</sheetData>");
sb.Append("<pageMargins left=\"0.7\" right=\"0.7\" top=\"0.75\"
bottom=\"0.75\" header=\"0.3\" footer=\"0.3\"/>");
sb.Append("</worksheet>");
return sb.ToString();
}
private static string getSheetList(int nHoja)
{
StringBuilder sb = new StringBuilder();
var lista = data[nHoja];
PropertyInfo[] campos = lista[0].GetType().GetProperties();
sb.Append("<row outlineLevel=\"0\" r=\"1\">");
string celda;
string valor;
string tipo;
for (int j = 0; j < campos.Length; j++)
{
celda = String.Format("{0}1", (char)(65 + j));
valor = campos[j].Name;
sb.Append("<c r=\"");
sb.Append(celda);
sb.Append("\" s=\"0\" t=\"inlineStr\"><is><t>");
sb.Append(valor);
sb.Append("</t></is></c>");
}
sb.Append("</row>");
for (int i = 0; i < lista.Count; i++)
{
sb.Append("<row outlineLevel=\"0\" r=\"");
sb.Append(i + 2);
sb.Append("\">");
for (int j = 0; j < campos.Length; j++)
{
celda = String.Format("{0}{1}", (char)(65 + j),i+2);
valor = lista[i].GetType().GetProperty(campos[j].Name).
GetValue(lista[i], null).ToString();
tipo = lista[i].GetType().GetProperty(campos[j].Name).PropertyType.ToString();
sb.Append("<c r=\"");
sb.Append(celda);
sb.Append("\" s=\"0\"");
if (tipo.Contains("String"))
{
sb.Append(" t=\"inlineStr\"><is><t>");
sb.Append(valor);
sb.Append("</t></is>");
}
else
{
sb.Append("><v>");
sb.Append(valor);
sb.Append("</v>");
}
sb.Append("</c>");
}
sb.Append("</row>");
}
return sb.ToString();
}
private static string getSheetTable(int nHoja)
{
StringBuilder sb = new StringBuilder();
var tabla = data[nHoja];
DataColumnCollection campos = tabla.Columns;
sb.Append("<row outlineLevel=\"0\" r=\"1\">");
string celda;
string valor;
string tipo;
for (int j = 0; j < campos.Count ; j++)
{
celda = String.Format("{0}1", (char)(65 + j));
valor = campos[j].ColumnName;
sb.Append("<c r=\"");
sb.Append(celda);
sb.Append("\" s=\"0\" t=\"inlineStr\"><is><t>");
sb.Append(valor);
sb.Append("</t></is></c>");
}
sb.Append("</row>");
for (int i = 0; i < tabla.Rows.Count; i++)
{
sb.Append("<row outlineLevel=\"0\" r=\"");
sb.Append(i + 2);
sb.Append("\">");
for (int j = 0; j < campos.Count; j++)
{
celda = String.Format("{0}{1}", (char)(65 + j), i + 2);
valor = tabla.Rows[i][j].ToString();
tipo = campos[j].DataType.ToString();
sb.Append("<c r=\"");
sb.Append(celda);
sb.Append("\" s=\"0\"");
if (tipo.Contains("String"))
{
sb.Append(" t=\"inlineStr\"><is><t>");
sb.Append(valor);
sb.Append("</t></is>");
}
else
{
sb.Append("><v>");
sb.Append(valor);
sb.Append("</v>");
}
sb.Append("</c>");
}
sb.Append("</row>");
}
return sb.ToString();
}
}
}
7. Explicación Resumida de la Clase Excel
Para cada origen de datos se ha creado un método: "ExportarDeLista" que trabaja con Reflection para extraer los datos de las listas y "ExportarDeTabla" que trabaja con DataTable para extraer los datos de las tablas.
Ambos métodos llaman a una función común y principal llamada "crearDirectoriosArchivos" que primero define las rutas de los directorios y archivos a crear y luego crea los directorios y archivos definidos.
La función "crearDirectoriosArchivos" llama a diferentes funciones una para crear cada archivo XML y para llenar la data de las listas se usa la función "getSheetList" y para llenar la data de las tablas se usa la función "getSheetTable".
Finalmente se comprime los archivos en un solo archivo XLSX y se borra todos los directorios y archivos XML creados temporalmente.
8. Programar el formulario para que use las Clases creadas y Exporte
El último bloque a codificar es el formulario "frmExcel" en el cual debe escribir el siguiente código:
using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.IO;
using System.Diagnostics;
using System.Windows.Forms;
namespace Excel_Crear_XML
{
public partial class frmExcel : Form
{
private beCategoriaProducto obeCatPro;
private DataSet dstCatPro;
private string archivoXlsx;
private string[] hojas;
public frmExcel()
{
InitializeComponent();
}
private void llenarDesdeListas(object sender, EventArgs e)
{
//Simular que se llenan las listas desde la base de datos
obeCatPro = new beCategoriaProducto();
obeCatPro.ListaCategoria = Data.ListaCategorias();
obeCatPro.ListaProducto = Data.ListaProductos();
//Enlazar las listas del objeto principal a las grillas
dgvCategoria.DataSource = obeCatPro.ListaCategoria;
dgvProducto.DataSource = obeCatPro.ListaProducto;
//Habilitar botón de Exportar Listas a Excel y deshabilitar el otro
btnExportarListas.Enabled = true;
btnExportarTablas.Enabled = false;
}
private void llenarDesdeTablas(object sender, EventArgs e)
{
//Simular que se llenan las tablas desde la base de datos
dstCatPro = new DataSet();
dstCatPro.Tables.Add(Data.TablaCategorias());
dstCatPro.Tables.Add(Data.TablaProductos());
//Enlazar las tablas del DataSet a las grillas
dgvCategoria.DataSource = dstCatPro.Tables[0];
dgvProducto.DataSource = dstCatPro.Tables[1];
//Habilitar botón de Exportar Tablas a Excel y deshabilitar el otro
btnExportarListas.Enabled = false;
btnExportarTablas.Enabled = true;
}
private void guardarExcel(Action exportar)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.Title = "Selecciona el Directorio e ingresa Nombre del Archivo Excel";
sfd.Filter = "Archivos de Excel 2007|*.xlsx";
if (sfd.ShowDialog().Equals(DialogResult.OK))
{
archivoXlsx = sfd.FileName;
hojas = new string[]{"Categorias", "Productos"};
Stopwatch oCronometro = new Stopwatch();
oCronometro.Start();
exportar();
oCronometro.Stop();
MessageBox.Show(String.Format("Archivo Excel fué creado en {0:n0} msg",
oCronometro.Elapsed.TotalMilliseconds));
}
}
private void exportarDesdeListas()
{
Excel.ExportarDeLista(archivoXlsx, hojas, obeCatPro);
}
private void exportarDesdeTablas()
{
Excel.ExportarDeTabla(archivoXlsx, hojas, dstCatPro);
}
private void exportarListasExcel(object sender, EventArgs e)
{
guardarExcel(exportarDesdeListas);
}
private void exportarTablasExcel(object sender, EventArgs e)
{
guardarExcel(exportarDesdeTablas);
}
}
}
9. Ejecutar y Probar la Aplicación Windows Forms
Grabar la aplicación y pulsar F5 para ejecutarla, se mostrará una ventana similar a la figura:
Ventana de ejecución del formulario "frmExcel"
Luego clic al primer botón "Llenar desde Listas" y se mostrará en las grillas los datos desde las listas de categorías y productos, tal como se muestra en las siguientes figuras:
Ventana con la Ficha de Categorías para Listas
Ventana con la Ficha de Productos para Listas
Se habilitará el botón de "Exportar Listas a Excel" al cual si se da click se mostrará el siguiente diálogo de guardar:
Diálogo de Guardar Excel para Listas
Escribir el nombre del archivo de Excel 2007, por ejemplo "ListasXML.xlsx" y "Guardar" e inmediatamente se mostrará un cuadro de diálogo con el tiempo que demoró la operación.
Continuando con las pruebas click al botón "Llenar desde Tablas" y se mostrará en las grillas los datos desde las tablas de categorías y productos, similar a las presentadas en las figuras de arriba.
Ventana con la Ficha de Categorías para Tablas
Se habilitará el botón de "Exportar Tablas a Excel" al cual si se da click se mostrará el siguiente diálogo de guardar:
Diálogo de Guardar Excel para Tablas
Escribir el nombre del archivo de Excel 2007, por ejemplo "TablasXML.xlsx" y "Guardar" e inmediatamente se mostrará un cuadro de diálogo con el tiempo que demoró la operación.
Finalmente, pueden abrir los 2 archivos de Excel creados que contendrán ambos 2 hojas: Categorías y Productos con los datos de los orígenes.
10. Comentario Final
Personalmente considero este post como uno de mis favoritos ya que no hay información en Internet sobre cómo crear un archivo de Excel 2007 en forma nativa, es decir creando los archivos XML necesarios para luego comprimirlos en un solo archivo XLSX.
Esta técnica es muy rápida, no necesita de instalar nada, y puede crear archivos de Excel con todo tipo de objetos como gráficos, formas, estilos, formatos, etc. Es la mejor forma para exportar datos sobre todo en la Web ya que también se puede hacer por JavaScript nativo como lo veremos en otro post.
Espero que este post ayude a muchas programadores a entender como es la estructura de un archivo Excel y poder crearlo sin necesidad de usar librerías, ya que según mi opinión solo volviendo a "Crear la Rueda" se puede construir una mejor. Los que usen el refrán "Para que Inventar la Rueda" es porque "NO saben como crearla".
Este Blog nació con ese fin, demostrar que con un poco de ingenio y mucha investigación se puede hacer "cualquier cosa". Finalmente, los quiero dejar con otra reflexión: "Fácil es hacer Complejo lo Simple", pero "Difícil es hacer Simple lo Complejo".
Cuando uno aprende hacer lo Complejo Simple estará en condiciones de resolver cualquier problema en corto tiempo y no esperar a que otro lo haga por ti (Frameworks y Librerías) que éste se hace mas fuerte y tu dependiente de él. Además que te pierdes de lo más interesante.
11. Descarga la Aplicación Windows
2016_08_09_Demo_Excel_Crear_XML
Etiquetas:
ADO.NET,
Categorias,
Command,
Connection,
Crear Excel,
DataSet,
Demos,
Exportar a Excel,
File,
FileStream,
Lduenas,
Listas,
Productos,
PropertyInfo,
Reflection,
SaveFileDialog,
Stopwatch,
StreamWriter,
Tablas,
XML
El Libro del Día: Reliable JavaScript
El Libro del Día: 2016-08-09
Titulo: Reliable JavaScript
Autor: Lawrence D. Spencer, Seth H. Richards
Editorial: Wrox
Nro Paginas: 530
Capítulos:
Part I: Laying a Solid Foundation
Chapter 1 Practicing Skillful Software Engineering
Chapter 2 Tooling Up
Chapter 3 Constructing Reliable Objects
Part II: Testing Pattern-Based Code
Chapter 4 Reviewing the Benefits of Patterns
Chapter 5 Ensuring Correct Use of the Callback Pattern
Chapter 6 Ensuring Correct Use of the Promise Pattern
Chapter 7 Ensuring Correct Use of Partial Function Application
Chapter 8 Ensuring Correct Use of the Memoization Pattern
Chapter 9 Ensuring Correct Implementation of the Singleton Pattern
Chapter 10 Ensuring Correct Implementation of the Factory Pattern
Chapter 11 Ensuring Correct Implementation and Use of the Sandbox Pattern
Chapter 12 Ensuring Correct Implementation of the Decorator Pattern
Chapter 13 Ensuring Correct Implementation of the Strategy Pattern
Chapter 14 Ensuring Correct Implementation of the Proxy Pattern
Chapter 15 Ensuring Correct Implementation of Chainable Methods
Part III: Testing and Writing with Advanced JavaScript Features
Chapter 16 Conforming to Interfaces in an Interface-Free Language
Chapter 17 Ensuring Correct Argument Types
Chapter 18 Ensuring Correct Use of call, apply, and bind
Chapter 19 Ensuring Correct Use of Method Borrowing
Chapter 20 Ensuring Correct Use of Mixins
Chapter 21 Testing Advanced Program Architectures
Part IV: Special Subjects in Testing
Chapter 22 Testing DOM Access
Chapter 23 Ensuring Conformance to Standards
Part V: Summary
Chapter 24 Summary of the Principles of Test-Driven Development
Chapter 25 Summary of JavaScript Idioms in This Book
Descarga:
Reliable_JavaScript
Titulo: Reliable JavaScript
Autor: Lawrence D. Spencer, Seth H. Richards
Editorial: Wrox
Nro Paginas: 530
Capítulos:
Part I: Laying a Solid Foundation
Chapter 1 Practicing Skillful Software Engineering
Chapter 2 Tooling Up
Chapter 3 Constructing Reliable Objects
Part II: Testing Pattern-Based Code
Chapter 4 Reviewing the Benefits of Patterns
Chapter 5 Ensuring Correct Use of the Callback Pattern
Chapter 6 Ensuring Correct Use of the Promise Pattern
Chapter 7 Ensuring Correct Use of Partial Function Application
Chapter 8 Ensuring Correct Use of the Memoization Pattern
Chapter 9 Ensuring Correct Implementation of the Singleton Pattern
Chapter 10 Ensuring Correct Implementation of the Factory Pattern
Chapter 11 Ensuring Correct Implementation and Use of the Sandbox Pattern
Chapter 12 Ensuring Correct Implementation of the Decorator Pattern
Chapter 13 Ensuring Correct Implementation of the Strategy Pattern
Chapter 14 Ensuring Correct Implementation of the Proxy Pattern
Chapter 15 Ensuring Correct Implementation of Chainable Methods
Part III: Testing and Writing with Advanced JavaScript Features
Chapter 16 Conforming to Interfaces in an Interface-Free Language
Chapter 17 Ensuring Correct Argument Types
Chapter 18 Ensuring Correct Use of call, apply, and bind
Chapter 19 Ensuring Correct Use of Method Borrowing
Chapter 20 Ensuring Correct Use of Mixins
Chapter 21 Testing Advanced Program Architectures
Part IV: Special Subjects in Testing
Chapter 22 Testing DOM Access
Chapter 23 Ensuring Conformance to Standards
Part V: Summary
Chapter 24 Summary of the Principles of Test-Driven Development
Chapter 25 Summary of JavaScript Idioms in This Book
Descarga:
Reliable_JavaScript
Etiquetas:
Callback,
Decorator,
Factory,
Javascript,
Lawrence D. Spencer,
Libros,
Memoization,
Mixins,
Objects,
Partial Function,
Patterns,
Promise,
Proxy,
Reliable,
Sandbox,
Seth H. Richards,
Singleton,
Strategy,
Tooling Up,
Wrox
lunes, 8 de agosto de 2016
El Libro del Día: Professional AngularJS
El Libro del Día: 2016-08-08
Titulo: Professional AngularJS
Autor: Valeri Karpov, Diego Netto
Editorial: Wrox
Nro Paginas: 399
Capítulos:
CHAPTER 1 Building a Simple AngularJS Application
CHAPTER 2 Intelligent Workflow and Build Tools
CHAPTER 3 Architecture
CHAPTER 4 Data Binding
CHAPTER 5 Directives
CHAPTER 6 Templates, Location, and Routing
CHAPTER 7 Services, Factories, and Providers
CHAPTER 8 Server Communication
CHAPTER 9 Testing and Debugging AngularJS Applications
CHAPTER 10 Moving On
APPENDIX Resources
Descarga:
Professional_AngularJS
Titulo: Professional AngularJS
Autor: Valeri Karpov, Diego Netto
Editorial: Wrox
Nro Paginas: 399
Capítulos:
CHAPTER 1 Building a Simple AngularJS Application
CHAPTER 2 Intelligent Workflow and Build Tools
CHAPTER 3 Architecture
CHAPTER 4 Data Binding
CHAPTER 5 Directives
CHAPTER 6 Templates, Location, and Routing
CHAPTER 7 Services, Factories, and Providers
CHAPTER 8 Server Communication
CHAPTER 9 Testing and Debugging AngularJS Applications
CHAPTER 10 Moving On
APPENDIX Resources
Descarga:
Professional_AngularJS
Etiquetas:
AngularJS,
Apps,
Architecture,
Build Tools,
Data Binding,
Debugging,
Diego Netto,
Directives,
Factories,
Libros,
Location,
Professional,
Providers,
Routing,
Services,
Templates,
Testing,
Valeri Karpov,
Workflow,
Wrox
domingo, 7 de agosto de 2016
El Libro del Día: Programming WCF Services
El Libro del Día: 2016-08-07
Titulo: Programming WCF Services (4th Edition)
Autor: Juval Lowy, Michael Montgomery
Editorial: O'Reilly
Nro Paginas: 1017
Capítulos:
1. WCF Essentials
2. Service Contracts
3. Data Contracts
4. Instance Management
5. Operations
6. Faults
7. Transactions
8. Concurrency Management
9. Queued Services
10. Security
11. The Azure Service Fabric
A. Introduction to Service Orientation
B. Headers and Contexts
C. Discovery
D. Publish-Subscribe Service
E. Generic Interceptor
F. WCF Coding Standard
G. ServiceModelEx Catalog
Descarga:
Programming_WCF_Services
Titulo: Programming WCF Services (4th Edition)
Autor: Juval Lowy, Michael Montgomery
Editorial: O'Reilly
Nro Paginas: 1017
Capítulos:
1. WCF Essentials
2. Service Contracts
3. Data Contracts
4. Instance Management
5. Operations
6. Faults
7. Transactions
8. Concurrency Management
9. Queued Services
10. Security
11. The Azure Service Fabric
A. Introduction to Service Orientation
B. Headers and Contexts
C. Discovery
D. Publish-Subscribe Service
E. Generic Interceptor
F. WCF Coding Standard
G. ServiceModelEx Catalog
Descarga:
Programming_WCF_Services
Etiquetas:
Azure,
Concurrency,
Contexts,
Data Contracts,
Faults,
Headers,
Instances,
Juval Lowy,
Libros,
Michael Montgomery,
O'Reilly,
Operations,
Queued,
Security,
Service Contracts,
Service Fabric,
Transactions,
WCF Services
sábado, 6 de agosto de 2016
El Libro del Día: Beginning Visual Basic 2015
El Libro del Día: 2016-08-06
Titulo: Beginning Visual Basic 2015
Autor: Bryan Newsome
Editorial: Wrox
Nro Paginas: 621
Capítulos:
Chapter 1 Welcome to Visual Basic 2015
Chapter 2 The Microsoft .NET Framework
Chapter 3 Writing Software
Chapter 4 Controlling the Flow
Chapter 5 Working with Data Structures
Chapter 6 Building Windows Applications
Chapter 7 Displaying Dialogs
Chapter 8 Creating Menus
Chapter 9 Debugging and Error Handling
Chapter 10 Building Objects
Chapter 11 Advanced Object-Oriented Techniques
Chapter 12 Accessing Data Using Structured Query Language
Chapter 13 Database Programming with SQL Server and ADO.NET
Chapter 14 ASP.NET
Chapter 15 Deploying Your Application
Chapter 16 Windows 8 Apps
Appendix Exercise Solutions
Descarga:
Beginning_Visual_Basic_2015
Titulo: Beginning Visual Basic 2015
Autor: Bryan Newsome
Editorial: Wrox
Nro Paginas: 621
Capítulos:
Chapter 1 Welcome to Visual Basic 2015
Chapter 2 The Microsoft .NET Framework
Chapter 3 Writing Software
Chapter 4 Controlling the Flow
Chapter 5 Working with Data Structures
Chapter 6 Building Windows Applications
Chapter 7 Displaying Dialogs
Chapter 8 Creating Menus
Chapter 9 Debugging and Error Handling
Chapter 10 Building Objects
Chapter 11 Advanced Object-Oriented Techniques
Chapter 12 Accessing Data Using Structured Query Language
Chapter 13 Database Programming with SQL Server and ADO.NET
Chapter 14 ASP.NET
Chapter 15 Deploying Your Application
Chapter 16 Windows 8 Apps
Appendix Exercise Solutions
Descarga:
Beginning_Visual_Basic_2015
Etiquetas:
.NET,
ADO.NET,
ASP.NET,
Beginning,
Bryan Newsome,
Debugging,
Deploying,
Dialogs,
Error Handling,
Libros,
LINQ,
Menus,
Objects,
SQL Server,
Structures,
VB 2015,
Visual Basic,
Windows 8 Apps,
Windows Apps,
Wrox
viernes, 5 de agosto de 2016
El Libro del Día: Beginning ASP.NET for Visual Studio 2015
El Libro del Día: 2016-08-05
Titulo: Beginning ASP.NET for Visual Studio 2015
Autor: William Penberthy
Editorial: Wrox
Nro Paginas: 793
Capítulos:
CHAPTER 1 Getting Started with ASP.NET 6.0
CHAPTER 2 Building an Initial ASP.NET Application
CHAPTER 3 Designing Your Web Pages
CHAPTER 4 Programming in C# and VB.NET
CHAPTER 5 ASP.NET Web Form Server Controls
CHAPTER 6 ASP.NET MVC Helpers and Extensions
CHAPTER 7 Creating Consistent-Looking Websites
CHAPTER 8 Navigation
CHAPTER 9 Displaying and Updating Data
CHAPTER 10 Working with Data—Advanced Topics
CHAPTER 11 User Controls and Partial Views
CHAPTER 12 Validating User Input
CHAPTER 13 ASP.NET AJAX
CHAPTER 14 jQuery
CHAPTER 15 Security in Your ASP.NET Website
CHAPTER 16 Personalizing Websites
CHAPTER 17 Exception Handling, Debugging, and Tracing
CHAPTER 18 Working with Source Control
CHAPTER 19 Deploying Your Website
APPENDIX Answers to Exercises
Descarga:
Beginning_ASP.NET_for_Visual_Studio_2015
Titulo: Beginning ASP.NET for Visual Studio 2015
Autor: William Penberthy
Editorial: Wrox
Nro Paginas: 793
Capítulos:
CHAPTER 1 Getting Started with ASP.NET 6.0
CHAPTER 2 Building an Initial ASP.NET Application
CHAPTER 3 Designing Your Web Pages
CHAPTER 4 Programming in C# and VB.NET
CHAPTER 5 ASP.NET Web Form Server Controls
CHAPTER 6 ASP.NET MVC Helpers and Extensions
CHAPTER 7 Creating Consistent-Looking Websites
CHAPTER 8 Navigation
CHAPTER 9 Displaying and Updating Data
CHAPTER 10 Working with Data—Advanced Topics
CHAPTER 11 User Controls and Partial Views
CHAPTER 12 Validating User Input
CHAPTER 13 ASP.NET AJAX
CHAPTER 14 jQuery
CHAPTER 15 Security in Your ASP.NET Website
CHAPTER 16 Personalizing Websites
CHAPTER 17 Exception Handling, Debugging, and Tracing
CHAPTER 18 Working with Source Control
CHAPTER 19 Deploying Your Website
APPENDIX Answers to Exercises
Descarga:
Beginning_ASP.NET_for_Visual_Studio_2015
Etiquetas:
AJAX,
ASP.NET,
Beginning,
C#,
Extensions,
jQuery,
Libros,
MVC Helpers,
Navigation,
Partial Views,
Security,
Server Controls,
User Controls,
Validating,
VB.NET,
VS 2015,
Web Form,
Web Pages,
William Penberthy,
Wrox
jueves, 4 de agosto de 2016
El Libro del Día: Building Maintainable Software
El Libro del Día: 2016-08-04
Titulo: Building Maintainable Software (C# Edition)
Autor: Joost Visser
Editorial: O'Reilly
Nro Paginas: 172
Capítulos:
1. Introduction
2. Write Short Units of Code
3. Write Simple Units of Code
4. Write Code Once
5. Keep Unit Interfaces Small
6. Separate Concerns in Modules
7. Couple Architecture Components Loosely
8. Keep Architecture Components Balanced
9. Keep Your Codebase Small
10. Automate Tests
11. Write Clean Code
12. Next Steps
A. How SIG Measures Maintainability
Descarga:
Building_Maintainable_Software
Titulo: Building Maintainable Software (C# Edition)
Autor: Joost Visser
Editorial: O'Reilly
Nro Paginas: 172
Capítulos:
1. Introduction
2. Write Short Units of Code
3. Write Simple Units of Code
4. Write Code Once
5. Keep Unit Interfaces Small
6. Separate Concerns in Modules
7. Couple Architecture Components Loosely
8. Keep Architecture Components Balanced
9. Keep Your Codebase Small
10. Automate Tests
11. Write Clean Code
12. Next Steps
A. How SIG Measures Maintainability
Descarga:
Building_Maintainable_Software
Etiquetas:
Architecture,
Balanced,
Building,
C#,
Clean Code,
Code Once,
Components,
Interfaces,
Joost Visser,
Libros,
Loosely,
Maintainable,
Modules,
O'Reilly,
Separate Concerns,
Short Units,
SIG,
Simple Units,
Software,
Tests
martes, 2 de agosto de 2016
El Libro del Día: C# 6.0 in a Nutshell
El Libro del Día: 2016-08-02
Titulo: C# 6.0 in a Nutshell (6th Edition)
Autor: Joseph Albahari, Ben Albahari
Editorial: O'Reilly
Nro Paginas: 1133
Capítulos:
1. Introducing C# and the .NET Framework
2. C# Language Basics
3. Creating Types in C#
4. Advanced C#
5. Framework Overview
6. Framework Fundamentals
7. Collections
8. LINQ Queries
9. LINQ Operators
10. LINQ to XML
11. Other XML Technologies
12. Disposal and Garbage Collection
13. Diagnostics and Code Contracts
14. Concurrency and Asynchrony
15. Streams and I/O
16. Networking
17. Serialization
18. Assemblies
19. Reflection and Metadata
20. Dynamic Programming
21. Security
22. Advanced Threading
23. Parallel Programming
24. Application Domains
25. Interoperability
26. Regular Expressions
27. The Roslyn Compiler
Descarga:
C#_6.0_in_a_Nutshell
Titulo: C# 6.0 in a Nutshell (6th Edition)
Autor: Joseph Albahari, Ben Albahari
Editorial: O'Reilly
Nro Paginas: 1133
Capítulos:
1. Introducing C# and the .NET Framework
2. C# Language Basics
3. Creating Types in C#
4. Advanced C#
5. Framework Overview
6. Framework Fundamentals
7. Collections
8. LINQ Queries
9. LINQ Operators
10. LINQ to XML
11. Other XML Technologies
12. Disposal and Garbage Collection
13. Diagnostics and Code Contracts
14. Concurrency and Asynchrony
15. Streams and I/O
16. Networking
17. Serialization
18. Assemblies
19. Reflection and Metadata
20. Dynamic Programming
21. Security
22. Advanced Threading
23. Parallel Programming
24. Application Domains
25. Interoperability
26. Regular Expressions
27. The Roslyn Compiler
Descarga:
C#_6.0_in_a_Nutshell
Etiquetas:
Advanced C#,
Assemblies,
Asynchrony,
Ben Albahari,
C# 6.0,
Collections,
Concurrency,
Framework,
Joseph Albahari,
Libros,
LINQ,
Networking,
Nutshell,
O'Reilly,
Reflection,
Security,
Serialization,
Streams,
Types,
XML
Videos - Carrito de Compras en ASP.NET MVC & JavaScript
Videos del Carrito de Compras en ASP.NET MVC & JavaScript
Quiero compartir con los que No asistieron a mi último taller y con los visitantes del Blog de otros países los videos de una aplicación completa en ASP.NET MVC & JavaScript que tiene un 20% de código en el servidor (C#) y un 80% de código en el cliente (JavaScript).
Partes de la Aplicación
La aplicación es un Carrito de Compras que trabaja con la BD Northwind a la cual se le aumento la tabla de Usuarios asociados a cada Cliente (para el Login y ordenar el Pedido).
Esta consta de 4 vistas o páginas:
- Login: Esta página permite el ingreso de un usuario y su clave, mas un código de Captcha.
- Categorias: Página que lista las Categorías de Productos.
- Productos: Página que lista los Productos de una cierta Categoría y permite agregar una cantidad al Carrito y también ir a ver.
- Pedidos: Página que permite mostrar los pedidos y cambiar su cantidad o eliminar un producto del pedido. También permite grabar el pedido al cliente.
Características Técnicas
Este Carrito de Compras tiene las siguientes características:
- Los controladores están protegidos por un Filtro de Autenticación usando una Sesión para el Cliente, es decir no se puede ir a ningún controlador o vista sino te autenticas (Login).
- Todas las llamadas al servidor son asíncronas con XHR (No jQuery, No Angular, etc)
- Todos los datos enviados al cliente se serializan a CSV (No XML ni JSON que son mas grandes por tener metadata).
- El Login usa un Captcha y cifrado en el cliente con WebCryptoAPI (No Librerías Externas JS)
- Todas las imágenes vienen en un solo viaje (No Sprite sino Serializado en Conjunto).
- Los datos del pedido se almacenan en el cliente con SessionStorage (No Session en el servidor).
- La grabación de la cabecera detalle es muy rápida ya que se pasa una cadena desde el cliente hasta el servidor web y de datos consumiendo una sola conexión y ejecutando un solo comando.
Videos del Carrito de Compras
Comentario Final
Este Carrito de Compras es totalmente distinto al que ven en la mayoría de sitios web que enseñan ASP.NET, ya que tiene muy poco código y trabaja casi desconectado donde toda la funcionalidad se construye con JavaScript y es 100% asíncrono con XHR.
No es un Carrito de Compras tradicional, es un "Formula 1" pura Performance usando JavaScript nativo que se ejecuta en cualquier Browser moderno.
Lástima que solo unos pocos pudieron apreciar esta interesante demostración de un nuevo tipo de aplicaciones. Para los que están en Lima y se atreven a pedir el código fuente, la respuesta es "hubieras participado en el taller" y para los del exterior pronto veremos la forma de que estos cursos se hagan virtuales (primero vería si tienen demanda, para lo cual están sus comentarios).
Quiero compartir con los que No asistieron a mi último taller y con los visitantes del Blog de otros países los videos de una aplicación completa en ASP.NET MVC & JavaScript que tiene un 20% de código en el servidor (C#) y un 80% de código en el cliente (JavaScript).
Partes de la Aplicación
La aplicación es un Carrito de Compras que trabaja con la BD Northwind a la cual se le aumento la tabla de Usuarios asociados a cada Cliente (para el Login y ordenar el Pedido).
Esta consta de 4 vistas o páginas:
- Login: Esta página permite el ingreso de un usuario y su clave, mas un código de Captcha.
- Categorias: Página que lista las Categorías de Productos.
- Productos: Página que lista los Productos de una cierta Categoría y permite agregar una cantidad al Carrito y también ir a ver.
- Pedidos: Página que permite mostrar los pedidos y cambiar su cantidad o eliminar un producto del pedido. También permite grabar el pedido al cliente.
Características Técnicas
Este Carrito de Compras tiene las siguientes características:
- Los controladores están protegidos por un Filtro de Autenticación usando una Sesión para el Cliente, es decir no se puede ir a ningún controlador o vista sino te autenticas (Login).
- Todas las llamadas al servidor son asíncronas con XHR (No jQuery, No Angular, etc)
- Todos los datos enviados al cliente se serializan a CSV (No XML ni JSON que son mas grandes por tener metadata).
- El Login usa un Captcha y cifrado en el cliente con WebCryptoAPI (No Librerías Externas JS)
- Todas las imágenes vienen en un solo viaje (No Sprite sino Serializado en Conjunto).
- Los datos del pedido se almacenan en el cliente con SessionStorage (No Session en el servidor).
- La grabación de la cabecera detalle es muy rápida ya que se pasa una cadena desde el cliente hasta el servidor web y de datos consumiendo una sola conexión y ejecutando un solo comando.
Videos del Carrito de Compras
Carrito de Compras Parte 1
Carrito de Compras Parte 2
Carrito de Compras Parte 3
Carrito de Compras Parte 4
Comentario Final
Este Carrito de Compras es totalmente distinto al que ven en la mayoría de sitios web que enseñan ASP.NET, ya que tiene muy poco código y trabaja casi desconectado donde toda la funcionalidad se construye con JavaScript y es 100% asíncrono con XHR.
No es un Carrito de Compras tradicional, es un "Formula 1" pura Performance usando JavaScript nativo que se ejecuta en cualquier Browser moderno.
Lástima que solo unos pocos pudieron apreciar esta interesante demostración de un nuevo tipo de aplicaciones. Para los que están en Lima y se atreven a pedir el código fuente, la respuesta es "hubieras participado en el taller" y para los del exterior pronto veremos la forma de que estos cursos se hagan virtuales (primero vería si tienen demanda, para lo cual están sus comentarios).
Etiquetas:
ASP.NET,
CAPTCHA,
Carrito de Compras,
Categorias,
CSV,
Entrenamiento,
Filtros,
HTML5,
Javascript,
Lduenas,
Local Storage,
MVC,
Performance,
Productos,
Shopping Cart,
Taller,
Videos,
WebCryptoAPI,
XHR,
YouTube
Suscribirse a:
Entradas (Atom)